(Fx_file_dialog) [HAVE_MOTIF_2_1]: Handle events
[bpt/emacs.git] / src / xfns.c
index 147a6d1..3136c76 100644 (file)
@@ -42,6 +42,7 @@ Boston, MA 02111-1307, USA.  */
 #include "fontset.h"
 #include "systime.h"
 #include "termhooks.h"
+#include "atimer.h"
 
 #ifdef HAVE_X_WINDOWS
 
@@ -49,14 +50,6 @@ Boston, MA 02111-1307, USA.  */
 #include <sys/types.h>
 #include <sys/stat.h>
 
-/* On some systems, the character-composition stuff is broken in X11R5.  */
-
-#if defined (HAVE_X11R5) && ! defined (HAVE_X11R6)
-#ifdef X11R5_INHIBIT_I18N
-#define X_I18N_INHIBITED
-#endif
-#endif
-
 #ifndef VMS
 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work.  */
 #include "bitmaps/gray.xbm"
@@ -243,7 +236,7 @@ Lisp_Object Quser_position;
 Lisp_Object Quser_size;
 extern Lisp_Object Qdisplay;
 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
-Lisp_Object Qscreen_gamma;
+Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
 
 /* The below are defined in frame.c.  */
 
@@ -747,6 +740,7 @@ struct x_frame_parm_table
 
 static void x_create_im P_ ((struct frame *));
 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
+static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
@@ -782,30 +776,31 @@ static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
 
 static struct x_frame_parm_table x_frame_parms[] =
 {
-  "auto-raise", x_set_autoraise,
-  "auto-lower", x_set_autolower,
-  "background-color", x_set_background_color,
-  "border-color", x_set_border_color,
-  "border-width", x_set_border_width,
-  "cursor-color", x_set_cursor_color,
-  "cursor-type", x_set_cursor_type,
-  "font", x_set_font,
-  "foreground-color", x_set_foreground_color,
-  "icon-name", x_set_icon_name,
-  "icon-type", x_set_icon_type,
-  "internal-border-width", x_set_internal_border_width,
-  "menu-bar-lines", x_set_menu_bar_lines,
-  "mouse-color", x_set_mouse_color,
-  "name", x_explicitly_set_name,
-  "scroll-bar-width", x_set_scroll_bar_width,
-  "title", x_set_title,
-  "unsplittable", x_set_unsplittable,
-  "vertical-scroll-bars", x_set_vertical_scroll_bars,
-  "visibility", x_set_visibility,
-  "tool-bar-lines", x_set_tool_bar_lines,
-  "scroll-bar-foreground", x_set_scroll_bar_foreground,
-  "scroll-bar-background", x_set_scroll_bar_background,
-  "screen-gamma", x_set_screen_gamma
+  "auto-raise",                        x_set_autoraise,
+  "auto-lower",                        x_set_autolower,
+  "background-color",          x_set_background_color,
+  "border-color",              x_set_border_color,
+  "border-width",              x_set_border_width,
+  "cursor-color",              x_set_cursor_color,
+  "cursor-type",               x_set_cursor_type,
+  "font",                      x_set_font,
+  "foreground-color",          x_set_foreground_color,
+  "icon-name",                 x_set_icon_name,
+  "icon-type",                 x_set_icon_type,
+  "internal-border-width",     x_set_internal_border_width,
+  "menu-bar-lines",            x_set_menu_bar_lines,
+  "mouse-color",               x_set_mouse_color,
+  "name",                      x_explicitly_set_name,
+  "scroll-bar-width",          x_set_scroll_bar_width,
+  "title",                     x_set_title,
+  "unsplittable",              x_set_unsplittable,
+  "vertical-scroll-bars",      x_set_vertical_scroll_bars,
+  "visibility",                        x_set_visibility,
+  "tool-bar-lines",            x_set_tool_bar_lines,
+  "scroll-bar-foreground",     x_set_scroll_bar_foreground,
+  "scroll-bar-background",     x_set_scroll_bar_background,
+  "screen-gamma",              x_set_screen_gamma,
+  "line-spacing",              x_set_line_spacing
 };
 
 /* Attach the `x-frame-parameter' properties to
@@ -822,8 +817,10 @@ init_x_parm_symbols ()
 }
 \f
 /* Change the parameters of frame F as specified by ALIST.
-   If a parameter is not specially recognized, do nothing;
-   otherwise call the `x_set_...' function for that parameter.  */
+   If a parameter is not specially recognized, do nothing special;
+   otherwise call the `x_set_...' function for that parameter.
+   Except for certain geometry properties, always call store_frame_param
+   to store the new value in the parameter alist.  */
 
 void
 x_set_frame_parameters (f, alist)
@@ -1105,7 +1102,7 @@ x_real_positions (f, xptr, yptr)
 #endif
   Window tmp_root_window;
   Window *tmp_children;
-  int tmp_nchildren;
+  unsigned int tmp_nchildren;
 
   while (1)
     {
@@ -1231,131 +1228,90 @@ gamma_correct (f, color)
 }
 
 
-/* Decide if color named COLOR is valid for the display associated with
-   the selected frame; if so, return the rgb values in COLOR_DEF.
-   If ALLOC is nonzero, allocate a new colormap cell.  */
+/* Decide if color named COLOR_NAME is valid for use on frame F.  If
+   so, return the RGB values in COLOR.  If ALLOC_P is non-zero,
+   allocate the color.  Value is zero if COLOR_NAME is invalid, or
+   no color could be allocated.  */
 
 int
-x_defined_color (f, color, color_def, alloc)
-     FRAME_PTR f;
-     char *color;
-     XColor *color_def;
-     int alloc;
+x_defined_color (f, color_name, color, alloc_p)
+     struct frame *f;
+     char *color_name;
+     XColor *color;
+     int alloc_p;
 {
-  register int status;
-  Colormap screen_colormap;
-  Display *display = FRAME_X_DISPLAY (f);
+  int success_p;
+  Display *dpy = FRAME_X_DISPLAY (f);
+  Colormap cmap = FRAME_X_COLORMAP (f);
 
   BLOCK_INPUT;
-  screen_colormap = DefaultColormap (display, XDefaultScreen (display));
-
-  status = XParseColor (display, screen_colormap, color, color_def);
-  if (status && alloc) 
-    {
-      /* Apply gamma correction.  */
-      gamma_correct (f, color_def);
-      
-      status = XAllocColor (display, screen_colormap, color_def);
-      if (!status)
-       {
-         /* If we got to this point, the colormap is full, so we're 
-            going to try and get the next closest color.
-            The algorithm used is a least-squares matching, which is
-            what X uses for closest color matching with StaticColor visuals.  */
-
-         XColor *cells;
-         int no_cells;
-         int nearest;
-         long nearest_delta, trial_delta;
-         int x;
-
-         no_cells = XDisplayCells (display, XDefaultScreen (display));
-         cells = (XColor *) alloca (sizeof (XColor) * no_cells);
-
-         for (x = 0; x < no_cells; x++) 
-           cells[x].pixel = x;
-
-         XQueryColors (display, screen_colormap, cells, no_cells);
-         nearest = 0;
-         /* I'm assuming CSE so I'm not going to condense this. */
-         nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8))
-                           * ((color_def->red >> 8) - (cells[0].red >> 8)))
-                          +
-                          (((color_def->green >> 8) - (cells[0].green >> 8))
-                           * ((color_def->green >> 8) - (cells[0].green >> 8)))
-                          +
-                          (((color_def->blue >> 8) - (cells[0].blue >> 8))
-                           * ((color_def->blue >> 8) - (cells[0].blue >> 8))));
-         for (x = 1; x < no_cells; x++) 
-           {
-             trial_delta = ((((color_def->red >> 8) - (cells[x].red >> 8))
-                             * ((color_def->red >> 8) - (cells[x].red >> 8)))
-                            +
-                            (((color_def->green >> 8) - (cells[x].green >> 8))
-                             * ((color_def->green >> 8) - (cells[x].green >> 8)))
-                            +
-                            (((color_def->blue >> 8) - (cells[x].blue >> 8))
-                             * ((color_def->blue >> 8) - (cells[x].blue >> 8))));
-             if (trial_delta < nearest_delta) 
-               {
-                 XColor temp;
-                 temp.red = cells[x].red;
-                 temp.green = cells[x].green;
-                 temp.blue = cells[x].blue;
-                 status = XAllocColor (display, screen_colormap, &temp);
-                 if (status)
-                   {
-                     nearest = x;
-                     nearest_delta = trial_delta;
-                   }
-               }
-           }
-         color_def->red = cells[nearest].red;
-         color_def->green = cells[nearest].green;
-         color_def->blue = cells[nearest].blue;
-         status = XAllocColor (display, screen_colormap, color_def);
-       }
-    }
+  success_p = XParseColor (dpy, cmap, color_name, color);
+  if (success_p && alloc_p)
+    success_p = x_alloc_nearest_color (f, cmap, color);
   UNBLOCK_INPUT;
 
-  if (status)
-    return 1;
-  else
-    return 0;
+  return success_p;
 }
 
-/* Given a string ARG naming a color, compute a pixel value from it
-   suitable for screen F.
-   If F is not a color screen, return DEF (default) regardless of what
-   ARG says.  */
+
+/* Return the pixel color value for color COLOR_NAME on frame F.  If F
+   is a monochrome frame, return MONO_COLOR regardless of what ARG says.
+   Signal an error if color can't be allocated.  */
 
 int
-x_decode_color (f, arg, def)
+x_decode_color (f, color_name, mono_color)
      FRAME_PTR f;
-     Lisp_Object arg;
-     int def;
+     Lisp_Object color_name;
+     int mono_color;
 {
   XColor cdef;
 
-  CHECK_STRING (arg, 0);
+  CHECK_STRING (color_name, 0);
 
-  if (strcmp (XSTRING (arg)->data, "black") == 0)
+#if 0 /* Don't do this.  It's wrong when we're not using the default
+        colormap, it makes freeing difficult, and it's probably not
+        an important optimization.  */
+  if (strcmp (XSTRING (color_name)->data, "black") == 0)
     return BLACK_PIX_DEFAULT (f);
-  else if (strcmp (XSTRING (arg)->data, "white") == 0)
+  else if (strcmp (XSTRING (color_name)->data, "white") == 0)
     return WHITE_PIX_DEFAULT (f);
+#endif
 
+  /* Return MONO_COLOR for monochrome frames.  */
   if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
-    return def;
+    return mono_color;
 
   /* x_defined_color is responsible for coping with failures
      by looking for a near-miss.  */
-  if (x_defined_color (f, XSTRING (arg)->data, &cdef, 1))
+  if (x_defined_color (f, XSTRING (color_name)->data, &cdef, 1))
     return cdef.pixel;
 
   Fsignal (Qerror, Fcons (build_string ("undefined color"),
-                         Fcons (arg, Qnil)));
+                         Fcons (color_name, Qnil)));
 }
+
+
 \f
+/* Change the `line-spacing' frame parameter of frame F.  OLD_VALUE is
+   the previous value of that parameter, NEW_VALUE is the new value.  */
+
+static void
+x_set_line_spacing (f, new_value, old_value)
+     struct frame *f;
+     Lisp_Object new_value, old_value;
+{
+  if (NILP (new_value))
+    f->extra_line_spacing = 0;
+  else if (NATNUMP (new_value))
+    f->extra_line_spacing = XFASTINT (new_value);
+  else
+    Fsignal (Qerror, Fcons (build_string ("Illegal line-spacing"),
+                           Fcons (new_value, Qnil)));
+  if (FRAME_VISIBLE_P (f))
+    redraw_frame (f);
+}
+
+
 /* Change the `screen-gamma' frame parameter of frame F.  OLD_VALUE is
    the previous value of that parameter, NEW_VALUE is the new value.  */
 
@@ -1533,13 +1489,9 @@ x_set_mouse_color (f, arg, oldval)
 
     fore_color.pixel = f->output_data.x->mouse_pixel;
     back_color.pixel = mask_color;
-    XQueryColor (FRAME_X_DISPLAY (f),
-                DefaultColormap (FRAME_X_DISPLAY (f),
-                                 DefaultScreen (FRAME_X_DISPLAY (f))),
+    XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
                 &fore_color);
-    XQueryColor (FRAME_X_DISPLAY (f),
-                DefaultColormap (FRAME_X_DISPLAY (f),
-                                 DefaultScreen (FRAME_X_DISPLAY (f))),
+    XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
                 &back_color);
     XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
                    &fore_color, &back_color);
@@ -1592,26 +1544,49 @@ x_set_cursor_color (f, arg, oldval)
      Lisp_Object arg, oldval;
 {
   unsigned long fore_pixel, pixel;
+  int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
 
-  if (!EQ (Vx_cursor_fore_pixel, Qnil))
-    fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
-                                WHITE_PIX_DEFAULT (f));
+  if (!NILP (Vx_cursor_fore_pixel))
+    {
+      fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
+                                  WHITE_PIX_DEFAULT (f));
+      fore_pixel_allocated_p = 1;
+    }
   else
     fore_pixel = f->output_data.x->background_pixel;
+  
   pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+  pixel_allocated_p = 1;
 
   /* Make sure that the cursor color differs from the background color.  */
   if (pixel == f->output_data.x->background_pixel)
     {
+      if (pixel_allocated_p)
+       {
+         x_free_colors (f, &pixel, 1);
+         pixel_allocated_p = 0;
+       }
+      
       pixel = f->output_data.x->mouse_pixel;
       if (pixel == fore_pixel)
-       fore_pixel = f->output_data.x->background_pixel;
+       {
+         if (fore_pixel_allocated_p)
+           {
+             x_free_colors (f, &fore_pixel, 1);
+             fore_pixel_allocated_p = 0;
+           }
+         fore_pixel = f->output_data.x->background_pixel;
+       }
     }
 
   unload_color (f, f->output_data.x->cursor_foreground_pixel);
+  if (!fore_pixel_allocated_p)
+    fore_pixel = x_copy_color (f, fore_pixel);
   f->output_data.x->cursor_foreground_pixel = fore_pixel;
 
   unload_color (f, f->output_data.x->cursor_pixel);
+  if (!pixel_allocated_p)
+    pixel = x_copy_color (f, pixel);
   f->output_data.x->cursor_pixel = pixel;
 
   if (FRAME_X_WINDOW (f) != 0)
@@ -1681,27 +1656,51 @@ x_set_border_pixel (f, pix)
     }
 }
 
-void
-x_set_cursor_type (f, arg, oldval)
-     FRAME_PTR f;
-     Lisp_Object arg, oldval;
+
+/* Value is the internal representation of the specified cursor type
+   ARG.  If type is BAR_CURSOR, return in *WIDTH the specified width
+   of the bar cursor.  */
+
+enum text_cursor_kinds
+x_specified_cursor_type (arg, width)
+     Lisp_Object arg;
+     int *width;
 {
+  enum text_cursor_kinds type;
+  
   if (EQ (arg, Qbar))
     {
-      FRAME_DESIRED_CURSOR (f) = BAR_CURSOR;
-      f->output_data.x->cursor_width = 2;
+      type = BAR_CURSOR;
+      *width = 2;
     }
-  else if (CONSP (arg) && EQ (XCAR (arg), Qbar)
-          && INTEGERP (XCDR (arg)))
+  else if (CONSP (arg)
+          && EQ (XCAR (arg), Qbar)
+          && INTEGERP (XCDR (arg))
+          && XINT (XCDR (arg)) >= 0)
     {
-      FRAME_DESIRED_CURSOR (f) = BAR_CURSOR;
-      f->output_data.x->cursor_width = XINT (XCDR (arg));
+      type = BAR_CURSOR;
+      *width = XINT (XCDR (arg));
     }
+  else if (NILP (arg))
+    type = NO_CURSOR;
   else
     /* Treat anything unknown as "box cursor".
        It was bad to signal an error; people have trouble fixing
        .Xdefaults with Emacs, when it has something bad in it.  */
-    FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
+    type = FILLED_BOX_CURSOR;
+
+  return type;
+}
+
+void
+x_set_cursor_type (f, arg, oldval)
+     FRAME_PTR f;
+     Lisp_Object arg, oldval;
+{
+  int width;
+  
+  FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
+  f->output_data.x->cursor_width = width;
 
   /* Make sure the cursor gets redrawn.  This is overkill, but how
      often do people change cursor types?  */
@@ -1911,6 +1910,11 @@ x_set_menu_bar_lines_1 (window, n)
   XSETFASTINT (w->top, XFASTINT (w->top) + n);
   XSETFASTINT (w->height, XFASTINT (w->height) - n);
 
+  if (INTEGERP (w->orig_top))
+    XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
+  if (INTEGERP (w->orig_height))
+    XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
+
   /* Handle just the top child in a vertical split.  */
   if (!NILP (w->vchild))
     x_set_menu_bar_lines_1 (w->vchild, n);
@@ -2514,8 +2518,6 @@ display_x_get_resource (dpyinfo, attribute, class, component, subclass)
   char *name_key;
   char *class_key;
 
-  check_x ();
-
   CHECK_STRING (attribute, 0);
   CHECK_STRING (class, 0);
 
@@ -3132,7 +3134,6 @@ void
 create_frame_xic (f)
      struct frame *f;
 {
-#ifndef X_I18N_INHIBITED
   XIM xim;
   XIC xic = NULL;
   XFontSet xfs = NULL;
@@ -3159,22 +3160,39 @@ create_frame_xic (f)
        base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
       else
        {
-         struct fontset_info *fontsetp;
-         int len = 0;
+         /* Determine the base fontname from the ASCII font name of
+            FONTSET.  */
+         char *ascii_font = (char *) XSTRING (fontset_ascii (fontset))->data;
+         char *p = ascii_font;
          int i;
-         
-         fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
-         for (i = 0; i <= MAX_CHARSET; i++)
-           if (fontsetp->fontname[i])
-             len += strlen (fontsetp->fontname[i]) + 1;
-         base_fontname = alloca (len);
-         strcpy (base_fontname, fontsetp->fontname[CHARSET_ASCII]);
-         for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
-           if (fontsetp->fontname[i])
-             {
-               strcat (base_fontname, ",");
-               strcat (base_fontname, fontsetp->fontname[i]);
-             }
+
+         for (i = 0; *p; p++)
+           if (*p == '-') i++;
+         if (i != 14)
+           /* As the font name doesn't conform to XLFD, we can't
+              modify it to get a suitable base fontname for the
+              frame.  */
+           base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
+         else
+           {
+             int len = strlen (ascii_font) + 1;
+             char *p1;
+
+             for (i = 0, p = ascii_font; i < 8; p++)
+               {
+                 if (*p == '-')
+                   {
+                     i++;
+                     if (i == 3)
+                       p1 = p + 1;
+                   }
+               }
+             base_fontname = (char *) alloca (len);
+             bzero (base_fontname, len);
+             strcpy (base_fontname, "-*-*-");
+             bcopy (p1, base_fontname + 5, p - p1);
+             strcat (base_fontname, "*-*-*-*-*-*-*");
+           }
        }
       xfs = xic_create_xfontset (f, base_fontname);
 
@@ -3225,11 +3243,6 @@ create_frame_xic (f)
   FRAME_XIC (f) = xic;
   FRAME_XIC_STYLE (f) = xic_style;
   FRAME_XIC_FONTSET (f) = xfs;
-#else /* X_I18N_INHIBITED */
-  FRAME_XIC (f) = NULL;
-  FRAME_XIC_STYLE (f) = 0;
-  FRAME_XIC_FONTSET (f) = NULL;
-#endif /* X_I18N_INHIBITED */
 }
 
 
@@ -3355,7 +3368,6 @@ x_window (f, window_prompting, minibuffer_only)
   XClassHint class_hints;
   XSetWindowAttributes attributes;
   unsigned long attribute_mask;
-
   Widget shell_widget;
   Widget pane_widget;
   Widget frame_widget;
@@ -3381,6 +3393,9 @@ x_window (f, window_prompting, minibuffer_only)
   XtSetArg (al[ac], XtNinput, 1); ac++;
   XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
   XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
+  XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
+  XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
+  XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
   shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
                                   applicationShellWidgetClass,
                                   FRAME_X_DISPLAY (f), al, ac);
@@ -3396,6 +3411,11 @@ x_window (f, window_prompting, minibuffer_only)
                                  (lw_callback) NULL,
                                  (lw_callback) NULL);
 
+  ac = 0;
+  XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
+  XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
+  XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
+  XtSetValues (pane_widget, al, ac);
   f->output_data.x->column_widget = pane_widget;
 
   /* mappedWhenManaged to false tells to the paned window to not map/unmap 
@@ -3407,9 +3427,11 @@ x_window (f, window_prompting, minibuffer_only)
   XtSetArg (al[ac], XtNallowResize, 1); ac++;
   XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
   XtSetArg (al[ac], XtNemacsFrame, f); ac++;
-  frame_widget = XtCreateWidget (f->namebuf,
-                                 emacsFrameClass,
-                                 pane_widget, al, ac);
+  XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
+  XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
+  XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
+  frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
+                                al, ac);
  
   f->output_data.x->edit_widget = frame_widget;
  
@@ -3585,11 +3607,9 @@ x_window (f)
   attributes.backing_store = NotUseful;
   attributes.save_under = True;
   attributes.event_mask = STANDARD_EVENT_SET;
-  attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity
-#if 0
-                   | CWBackingStore | CWSaveUnder
-#endif
-                   | CWEventMask);
+  attributes.colormap = FRAME_X_COLORMAP (f);
+  attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
+                   | CWColormap);
 
   BLOCK_INPUT;
   FRAME_X_WINDOW (f)
@@ -3601,7 +3621,7 @@ x_window (f)
                     f->output_data.x->border_width,
                     CopyFromParent, /* depth */
                     InputOutput, /* class */
-                    FRAME_X_DISPLAY_INFO (f)->visual,
+                    FRAME_X_VISUAL (f),
                     attribute_mask, &attributes);
 
 #ifdef HAVE_X_I18N
@@ -3893,6 +3913,29 @@ This function is an internal primitive--use `make-frame' instead.")
   FRAME_KBOARD (f) = kb;
 #endif
 
+  /* These colors will be set anyway later, but it's important
+     to get the color reference counts right, so initialize them!  */
+  {
+    Lisp_Object black;
+    struct gcpro gcpro1;
+    
+    black = build_string ("black");
+    GCPRO1 (black);
+    f->output_data.x->foreground_pixel
+      = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+    f->output_data.x->background_pixel
+      = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+    f->output_data.x->cursor_pixel
+      = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+    f->output_data.x->cursor_foreground_pixel
+      = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+    f->output_data.x->border_pixel
+      = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+    f->output_data.x->mouse_pixel
+      = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+    UNGCPRO;
+  }
+
   /* Specify the parent under which to make this X window.  */
 
   if (!NILP (parent))
@@ -3921,10 +3964,6 @@ This function is an internal primitive--use `make-frame' instead.")
       specbind (Qx_resource_name, name);
     }
 
-  /* Create fontsets from `global_fontset_alist' before handling fonts.  */
-  for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCDR (tem))
-    fs_register_fontset (f, XCAR (tem));
-
   /* Extract the window parameters from the supplied values
      that are needed to determine window geometry.  */
   {
@@ -4007,6 +4046,8 @@ This function is an internal primitive--use `make-frame' instead.")
                       "borderColor", "BorderColor", RES_TYPE_STRING);
   x_default_parameter (f, parms, Qscreen_gamma, Qnil,
                       "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
+  x_default_parameter (f, parms, Qline_spacing, Qnil,
+                      "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
 
   x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
                                        "scrollBarForeground",
@@ -4169,6 +4210,36 @@ x_get_focus_frame (frame)
   return xfocus;
 }
 
+
+/* In certain situations, when the window manager follows a
+   click-to-focus policy, there seems to be no way around calling
+   XSetInputFocus to give another frame the input focus .
+
+   In an ideal world, XSetInputFocus should generally be avoided so
+   that applications don't interfere with the window manager's focus
+   policy.  But I think it's okay to use when it's clearly done
+   following a user-command.  */
+
+DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
+  "Set the input focus to FRAME.\n\
+FRAME nil means use the selected frame.")
+  (frame)
+     Lisp_Object frame;
+{
+  struct frame *f = check_x_frame (frame);
+  Display *dpy = FRAME_X_DISPLAY (f);
+  int count;
+
+  BLOCK_INPUT;
+  count = x_catch_errors (dpy);
+  XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                 RevertToParent, CurrentTime);
+  x_uncatch_errors (dpy, count);
+  UNBLOCK_INPUT;
+  
+  return Qnil;
+}
+
 \f
 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
   "Internal function called by `color-defined-p', which see.")
@@ -4512,1047 +4583,201 @@ x_screen_planes (f)
 {
   return FRAME_X_DISPLAY_INFO (f)->n_planes;
 }
+
+
 \f
-#if 0  /* These no longer seem like the right way to do things.  */
+/************************************************************************
+                             X Displays
+ ************************************************************************/
 
-/* Draw a rectangle on the frame with left top corner including
-   the character specified by LEFT_CHAR and TOP_CHAR.  The rectangle is
-   CHARS by LINES wide and long and is the color of the cursor.  */
+\f
+/* Mapping visual names to visuals.  */
 
-void
-x_rectangle (f, gc, left_char, top_char, chars, lines)
-     register struct frame *f;
-     GC gc;
-     register int top_char, left_char, chars, lines;
+static struct visual_class
 {
-  int width;
-  int height;
-  int left = (left_char * FONT_WIDTH (f->output_data.x->font)
-                   + f->output_data.x->internal_border_width);
-  int top = (top_char * f->output_data.x->line_height
-                  + f->output_data.x->internal_border_width);
-
-  if (chars < 0)
-    width = FONT_WIDTH (f->output_data.x->font) / 2;
-  else
-    width = FONT_WIDTH (f->output_data.x->font) * chars;
-  if (lines < 0)
-    height = f->output_data.x->line_height / 2;
-  else
-    height = f->output_data.x->line_height * lines;
-
-  XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 gc, left, top, width, height);
+  char *name;
+  int class;
 }
-
-DEFUN ("x-draw-rectangle", Fx_draw_rectangle, Sx_draw_rectangle, 5, 5, 0,
-  "Draw a rectangle on FRAME between coordinates specified by\n\
-numbers X0, Y0, X1, Y1 in the cursor pixel.")
-  (frame, X0, Y0, X1, Y1)
-     register Lisp_Object frame, X0, X1, Y0, Y1;
+visual_classes[] =
 {
-  register int x0, y0, x1, y1, top, left, n_chars, n_lines;
+  {"StaticGray",       StaticGray},
+  {"GrayScale",                GrayScale},
+  {"StaticColor",      StaticColor},
+  {"PseudoColor",      PseudoColor},
+  {"TrueColor",                TrueColor},
+  {"DirectColor",      DirectColor},
+  NULL
+};
 
-  CHECK_LIVE_FRAME (frame, 0);
-  CHECK_NUMBER (X0, 0);
-  CHECK_NUMBER (Y0, 1);
-  CHECK_NUMBER (X1, 2);
-  CHECK_NUMBER (Y1, 3);
 
-  x0 = XINT (X0);
-  x1 = XINT (X1);
-  y0 = XINT (Y0);
-  y1 = XINT (Y1);
+#ifndef HAVE_XSCREENNUMBEROFSCREEN
 
-  if (y1 > y0)
-    {
-      top = y0;
-      n_lines = y1 - y0 + 1;
-    }
-  else
-    {
-      top = y1;
-      n_lines = y0 - y1 + 1;
-    }
+/* Value is the screen number of screen SCR.  This is a substitute for
+   the X function with the same name when that doesn't exist.  */
 
-  if (x1 > x0)
-    {
-      left = x0;
-      n_chars = x1 - x0 + 1;
-    }
-  else
-    {
-      left = x1;
-      n_chars = x0 - x1 + 1;
-    }
+int
+XScreenNumberOfScreen (scr)
+    register Screen *scr;
+{
+  Display *dpy = scr->display;
+  int i;
 
-  BLOCK_INPUT;
-  x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->cursor_gc,
-              left, top, n_chars, n_lines);
-  UNBLOCK_INPUT;
+  for (i = 0; i < dpy->nscreens; ++i)
+    if (scr == dpy->screens[i])
+      break;
 
-  return Qt;
+  return i;
 }
 
-DEFUN ("x-erase-rectangle", Fx_erase_rectangle, Sx_erase_rectangle, 5, 5, 0,
-  "Draw a rectangle drawn on FRAME between coordinates\n\
-X0, Y0, X1, Y1 in the regular background-pixel.")
-  (frame, X0, Y0, X1, Y1)
-  register Lisp_Object frame, X0, Y0, X1, Y1;
-{
-  register int x0, y0, x1, y1, top, left, n_chars, n_lines;
+#endif /* not HAVE_XSCREENNUMBEROFSCREEN */
 
-  CHECK_LIVE_FRAME (frame, 0);
-  CHECK_NUMBER (X0, 0);
-  CHECK_NUMBER (Y0, 1);
-  CHECK_NUMBER (X1, 2);
-  CHECK_NUMBER (Y1, 3);
 
-  x0 = XINT (X0);
-  x1 = XINT (X1);
-  y0 = XINT (Y0);
-  y1 = XINT (Y1);
+/* Select the visual that should be used on display DPYINFO.  Set
+   members of DPYINFO appropriately.  Called from x_term_init.  */
 
-  if (y1 > y0)
-    {
-      top = y0;
-      n_lines = y1 - y0 + 1;
-    }
-  else
-    {
-      top = y1;
-      n_lines = y0 - y1 + 1;
-    }
+void
+select_visual (dpyinfo)
+     struct x_display_info *dpyinfo;
+{
+  Display *dpy = dpyinfo->display;
+  Screen *screen = dpyinfo->screen;
+  Lisp_Object value;
 
-  if (x1 > x0)
-    {
-      left = x0;
-      n_chars = x1 - x0 + 1;
-    }
-  else
+  /* See if a visual is specified.  */
+  value = display_x_get_resource (dpyinfo,
+                                 build_string ("visualClass"),
+                                 build_string ("VisualClass"),
+                                 Qnil, Qnil);
+  if (STRINGP (value))
     {
-      left = x1;
-      n_chars = x0 - x1 + 1;
-    }
-
-  BLOCK_INPUT;
-  x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->reverse_gc,
-              left, top, n_chars, n_lines);
-  UNBLOCK_INPUT;
-
-  return Qt;
-}
-
-/* Draw lines around the text region beginning at the character position
-   TOP_X, TOP_Y and ending at BOTTOM_X and BOTTOM_Y.  GC specifies the
-   pixel and line characteristics.  */
+      /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
+        of `PseudoColor', `TrueColor' etc. and DEPTH is the color
+        depth, a decimal number.  NAME is compared with case ignored.  */
+      char *s = (char *) alloca (STRING_BYTES (XSTRING (value)) + 1);
+      char *dash;
+      int i, class = -1;
+      XVisualInfo vinfo;
+
+      strcpy (s, XSTRING (value)->data);
+      dash = index (s, '-');
+      if (dash)
+       {
+         dpyinfo->n_planes = atoi (dash + 1);
+         *dash = '\0';
+       }
+      else
+       /* We won't find a matching visual with depth 0, so that
+          an error will be printed below.  */
+       dpyinfo->n_planes = 0;
 
-#define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
+      /* Determine the visual class.  */
+      for (i = 0; visual_classes[i].name; ++i)
+       if (xstricmp (s, visual_classes[i].name) == 0)
+         {
+           class = visual_classes[i].class;
+           break;
+         }
 
-static void
-outline_region (f, gc, top_x, top_y, bottom_x, bottom_y)
-     register struct frame *f;
-     GC gc;
-     int  top_x, top_y, bottom_x, bottom_y;
-{
-  register int ibw = f->output_data.x->internal_border_width;
-  register int font_w = FONT_WIDTH (f->output_data.x->font);
-  register int font_h = f->output_data.x->line_height;
-  int y = top_y;
-  int x = line_len (y);
-  XPoint *pixel_points
-    = (XPoint *) alloca (((bottom_y - top_y + 2) * 4) * sizeof (XPoint));
-  register XPoint *this_point = pixel_points;
-
-  /* Do the horizontal top line/lines */
-  if (top_x == 0)
-    {
-      this_point->x = ibw;
-      this_point->y = ibw + (font_h * top_y);
-      this_point++;
-      if (x == 0)
-       this_point->x = ibw + (font_w / 2); /* Half-size for newline chars.  */
-      else
-       this_point->x = ibw + (font_w * x);
-      this_point->y = (this_point - 1)->y;
+      /* Look up a matching visual for the specified class.  */
+      if (class == -1
+         || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
+                               dpyinfo->n_planes, class, &vinfo))
+       fatal ("Invalid visual specification `%s'", XSTRING (value)->data);
+      
+      dpyinfo->visual = vinfo.visual;
     }
   else
     {
-      this_point->x = ibw;
-      this_point->y = ibw + (font_h * (top_y + 1));
-      this_point++;
-      this_point->x = ibw + (font_w * top_x);
-      this_point->y = (this_point - 1)->y;
-      this_point++;
-      this_point->x = (this_point - 1)->x;
-      this_point->y = ibw + (font_h * top_y);
-      this_point++;
-      this_point->x = ibw + (font_w * x);
-      this_point->y = (this_point - 1)->y;
-    }
-
-  /* Now do the right side.  */
-  while (y < bottom_y)
-    {                          /* Right vertical edge */
-      this_point++;
-      this_point->x = (this_point - 1)->x;
-      this_point->y = ibw + (font_h * (y + 1));
-      this_point++;
-
-      y++;                     /* Horizontal connection to next line */
-      x = line_len (y);
-      if (x == 0)
-       this_point->x = ibw + (font_w / 2);
-      else
-       this_point->x = ibw + (font_w * x);
-
-      this_point->y = (this_point - 1)->y;
-    }
-
-  /* Now do the bottom and connect to the top left point.  */
-  this_point->x = ibw + (font_w * (bottom_x + 1));
+      int n_visuals;
+      XVisualInfo *vinfo, vinfo_template;
+      
+      dpyinfo->visual = DefaultVisualOfScreen (screen);
 
-  this_point++;
-  this_point->x = (this_point - 1)->x;
-  this_point->y = ibw + (font_h * (bottom_y + 1));
-  this_point++;
-  this_point->x = ibw;
-  this_point->y = (this_point - 1)->y;
-  this_point++;
-  this_point->x = pixel_points->x;
-  this_point->y = pixel_points->y;
+#ifdef HAVE_X11R4
+      vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
+#else
+      vinfo_template.visualid = dpyinfo->visual->visualid;
+#endif
+      vinfo_template.screen = XScreenNumberOfScreen (screen);
+      vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
+                             &vinfo_template, &n_visuals);
+      if (n_visuals != 1)
+       fatal ("Can't get proper X visual info");
 
-  XDrawLines (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-             gc, pixel_points,
-             (this_point - pixel_points + 1), CoordModeOrigin);
+      dpyinfo->n_planes = vinfo->depth;
+      XFree ((char *) vinfo);
+    }
 }
 
-DEFUN ("x-contour-region", Fx_contour_region, Sx_contour_region, 1, 1, 0,
-  "Highlight the region between point and the character under the mouse\n\
-selected frame.")
-  (event)
-     register Lisp_Object event;
-{
-  register int x0, y0, x1, y1;
-  register struct frame *f = selected_frame;
-  struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
-  register int p1, p2;
 
-  CHECK_CONS (event, 0);
+/* Return the X display structure for the display named NAME.
+   Open a new connection if necessary.  */
 
-  BLOCK_INPUT;
-  x0 = XINT (Fcar (Fcar (event)));
-  y0 = XINT (Fcar (Fcdr (Fcar (event))));
+struct x_display_info *
+x_display_info_for_name (name)
+     Lisp_Object name;
+{
+  Lisp_Object names;
+  struct x_display_info *dpyinfo;
 
-  /* If the mouse is past the end of the line, don't that area.  */
-  /* ReWrite this...  */
+  CHECK_STRING (name, 0);
 
-  /* Where the cursor is.  */
-  x1 = WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x);
-  y1 = WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y);
+  if (! EQ (Vwindow_system, intern ("x")))
+    error ("Not using X Windows");
 
-  if (y1 > y0)                 /* point below mouse */
-    outline_region (f, f->output_data.x->cursor_gc,
-                   x0, y0, x1, y1);
-  else if (y1 < y0)            /* point above mouse */
-    outline_region (f, f->output_data.x->cursor_gc,
-                   x1, y1, x0, y0);
-  else                         /* same line: draw horizontal rectangle */
+  for (dpyinfo = x_display_list, names = x_display_name_list;
+       dpyinfo;
+       dpyinfo = dpyinfo->next, names = XCDR (names))
     {
-      if (x1 > x0)
-       x_rectangle (f, f->output_data.x->cursor_gc,
-                    x0, y0, (x1 - x0 + 1), 1);
-      else if (x1 < x0)
-         x_rectangle (f, f->output_data.x->cursor_gc,
-                      x1, y1, (x0 - x1 + 1), 1);
+      Lisp_Object tem;
+      tem = Fstring_equal (XCAR (XCAR (names)), name);
+      if (!NILP (tem))
+       return dpyinfo;
     }
 
-  XFlush (FRAME_X_DISPLAY (f));
-  UNBLOCK_INPUT;
+  /* Use this general default value to start with.  */
+  Vx_resource_name = Vinvocation_name;
 
-  return Qnil;
-}
+  validate_x_resource_name ();
 
-DEFUN ("x-uncontour-region", Fx_uncontour_region, Sx_uncontour_region, 1, 1, 0,
-  "Erase any highlighting of the region between point and the character\n\
-at X, Y on the selected frame.")
-  (event)
-     register Lisp_Object event;
-{
-  register int x0, y0, x1, y1;
-  register struct frame *f = selected_frame;
-  struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
+  dpyinfo = x_term_init (name, (unsigned char *)0,
+                        (char *) XSTRING (Vx_resource_name)->data);
 
-  BLOCK_INPUT;
-  x0 = XINT (Fcar (Fcar (event)));
-  y0 = XINT (Fcar (Fcdr (Fcar (event))));
-  x1 = WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x);
-  y1 = WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y);
-
-  if (y1 > y0)                 /* point below mouse */
-    outline_region (f, f->output_data.x->reverse_gc,
-                     x0, y0, x1, y1);
-  else if (y1 < y0)            /* point above mouse */
-    outline_region (f, f->output_data.x->reverse_gc,
-                     x1, y1, x0, y0);
-  else                         /* same line: draw horizontal rectangle */
-    {
-      if (x1 > x0)
-       x_rectangle (f, f->output_data.x->reverse_gc,
-                    x0, y0, (x1 - x0 + 1), 1);
-      else if (x1 < x0)
-       x_rectangle (f, f->output_data.x->reverse_gc,
-                    x1, y1, (x0 - x1 + 1), 1);
-    }
-  UNBLOCK_INPUT;
+  if (dpyinfo == 0)
+    error ("Cannot connect to X server %s", XSTRING (name)->data);
 
-  return Qnil;
-}
+  x_in_use = 1;
+  XSETFASTINT (Vwindow_system_version, 11);
 
-#if 0
-int contour_begin_x, contour_begin_y;
-int contour_end_x, contour_end_y;
-int contour_npoints;
+  return dpyinfo;
+}
 
-/* Clip the top part of the contour lines down (and including) line Y_POS.
-   If X_POS is in the middle (rather than at the end) of the line, drop
-   down a line at that character.  */
 
-static void
-clip_contour_top (y_pos, x_pos)
+DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
+       1, 3, 0, "Open a connection to an X server.\n\
+DISPLAY is the name of the display to connect to.\n\
+Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
+If the optional third arg MUST-SUCCEED is non-nil,\n\
+terminate Emacs if we can't open the connection.")
+  (display, xrm_string, must_succeed)
+     Lisp_Object display, xrm_string, must_succeed;
 {
-  register XPoint *begin = contour_lines[y_pos].top_left;
-  register XPoint *end;
-  register int npoints;
-  register struct display_line *line = selected_frame->phys_lines[y_pos + 1];
+  unsigned char *xrm_option;
+  struct x_display_info *dpyinfo;
 
-  if (x_pos >= line->len - 1)  /* Draw one, straight horizontal line.  */
-    {
-      end = contour_lines[y_pos].top_right;
-      npoints = (end - begin + 1);
-      XDrawLines (x_current_display, contour_window,
-                 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
+  CHECK_STRING (display, 0);
+  if (! NILP (xrm_string))
+    CHECK_STRING (xrm_string, 1);
 
-      bcopy (end, begin + 1, contour_last_point - end + 1);
-      contour_last_point -= (npoints - 2);
-      XDrawLines (x_current_display, contour_window,
-                 contour_erase_gc, begin, 2, CoordModeOrigin);
-      XFlush (x_current_display);
+  if (! EQ (Vwindow_system, intern ("x")))
+    error ("Not using X Windows");
 
-      /* Now, update contour_lines structure.  */
-    }
-                               /* ______.         */
-  else                         /*       |________*/
-    {
-      register XPoint *p = begin + 1;
-      end = contour_lines[y_pos].bottom_right;
-      npoints = (end - begin + 1);
-      XDrawLines (x_current_display, contour_window,
-                 contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
+  if (! NILP (xrm_string))
+    xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
+  else
+    xrm_option = (unsigned char *) 0;
 
-      p->y = begin->y;
-      p->x = ibw + (font_w * (x_pos + 1));
-      p++;
-      p->y = begin->y + font_h;
-      p->x = (p - 1)->x;
-      bcopy (end, begin + 3, contour_last_point - end + 1);
-      contour_last_point -= (npoints - 5);
-      XDrawLines (x_current_display, contour_window,
-                 contour_erase_gc, begin, 4, CoordModeOrigin);
-      XFlush (x_current_display);
-
-      /* Now, update contour_lines structure.  */
-    }
-}
-
-/* Erase the top horizontal lines of the contour, and then extend
-   the contour upwards.  */
-
-static void
-extend_contour_top (line)
-{
-}
-
-static void
-clip_contour_bottom (x_pos, y_pos)
-     int x_pos, y_pos;
-{
-}
-
-static void
-extend_contour_bottom (x_pos, y_pos)
-{
-}
-
-DEFUN ("x-select-region", Fx_select_region, Sx_select_region, 1, 1, "e",
-  "")
-  (event)
-     Lisp_Object event;
-{
- register struct frame *f = selected_frame;
- struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
- register int point_x = WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x);
- register int point_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y);
- register int mouse_below_point;
- register Lisp_Object obj;
- register int x_contour_x, x_contour_y;
-
- x_contour_x = x_mouse_x;
- x_contour_y = x_mouse_y;
- if (x_contour_y > point_y || (x_contour_y == point_y
-                              && x_contour_x > point_x))
-   {
-     mouse_below_point = 1;
-     outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
-                    x_contour_x, x_contour_y);
-   }
- else
-   {
-     mouse_below_point = 0;
-     outline_region (f, f->output_data.x->cursor_gc, x_contour_x, x_contour_y,
-                    point_x, point_y);
-   }
-
- while (1)
-   {
-     obj = read_char (-1, 0, 0, Qnil, 0);
-     if (!CONSP (obj))
-       break;
-
-     if (mouse_below_point)
-       {
-        if (x_mouse_y <= point_y)                /* Flipped.  */
-          {
-            mouse_below_point = 0;
-
-            outline_region (f, f->output_data.x->reverse_gc, point_x, point_y,
-                            x_contour_x, x_contour_y);
-            outline_region (f, f->output_data.x->cursor_gc, x_mouse_x, x_mouse_y,
-                            point_x, point_y);
-          }
-        else if (x_mouse_y < x_contour_y)        /* Bottom clipped.  */
-          {
-            clip_contour_bottom (x_mouse_y);
-          }
-        else if (x_mouse_y > x_contour_y)        /* Bottom extended.  */
-          {
-            extend_bottom_contour (x_mouse_y);
-          }
-
-        x_contour_x = x_mouse_x;
-        x_contour_y = x_mouse_y;
-       }
-     else  /* mouse above or same line as point */
-       {
-        if (x_mouse_y >= point_y)                /* Flipped.  */
-          {
-            mouse_below_point = 1;
-
-            outline_region (f, f->output_data.x->reverse_gc,
-                            x_contour_x, x_contour_y, point_x, point_y);
-            outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
-                            x_mouse_x, x_mouse_y);
-          }
-        else if (x_mouse_y > x_contour_y)        /* Top clipped.  */
-          {
-            clip_contour_top (x_mouse_y);
-          }
-        else if (x_mouse_y < x_contour_y)        /* Top extended.  */
-          {
-            extend_contour_top (x_mouse_y);
-          }
-       }
-   }
-
- unread_command_event = obj;
- if (mouse_below_point)
-   {
-     contour_begin_x = point_x;
-     contour_begin_y = point_y;
-     contour_end_x = x_contour_x;
-     contour_end_y = x_contour_y;
-   }
- else
-   {
-     contour_begin_x = x_contour_x;
-     contour_begin_y = x_contour_y;
-     contour_end_x = point_x;
-     contour_end_y = point_y;
-   }
-}
-#endif
-
-DEFUN ("x-horizontal-line", Fx_horizontal_line, Sx_horizontal_line, 1, 1, "e",
-  "")
-  (event)
-     Lisp_Object event;
-{
-  register Lisp_Object obj;
-  struct frame *f = selected_frame;
-  register struct window *w = XWINDOW (selected_window);
-  register GC line_gc = f->output_data.x->cursor_gc;
-  register GC erase_gc = f->output_data.x->reverse_gc;
-#if 0
-  char dash_list[] = {6, 4, 6, 4};
-  int dashes = 4;
-  XGCValues gc_values;
-#endif
-  register int previous_y;
-  register int line = (x_mouse_y + 1) * f->output_data.x->line_height
-    + f->output_data.x->internal_border_width;
-  register int left = f->output_data.x->internal_border_width
-    + (WINDOW_LEFT_MARGIN (w)
-       * FONT_WIDTH (f->output_data.x->font));
-  register int right = left + (w->width
-                              * FONT_WIDTH (f->output_data.x->font))
-    - f->output_data.x->internal_border_width;
-
-#if 0
-  BLOCK_INPUT;
-  gc_values.foreground = f->output_data.x->cursor_pixel;
-  gc_values.background = f->output_data.x->background_pixel;
-  gc_values.line_width = 1;
-  gc_values.line_style = LineOnOffDash;
-  gc_values.cap_style = CapRound;
-  gc_values.join_style = JoinRound;
-
-  line_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                      GCLineStyle | GCJoinStyle | GCCapStyle
-                      | GCLineWidth | GCForeground | GCBackground,
-                      &gc_values);
-  XSetDashes (FRAME_X_DISPLAY (f), line_gc, 0, dash_list, dashes);
-  gc_values.foreground = f->output_data.x->background_pixel;
-  gc_values.background = f->output_data.x->foreground_pixel;
-  erase_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                      GCLineStyle | GCJoinStyle | GCCapStyle
-                      | GCLineWidth | GCForeground | GCBackground,
-                      &gc_values);
-  XSetDashes (FRAME_X_DISPLAY (f), erase_gc, 0, dash_list, dashes);
-  UNBLOCK_INPUT;
-#endif
-
-  while (1)
-    {
-      BLOCK_INPUT;
-      if (x_mouse_y >= XINT (w->top)
-         && x_mouse_y < XINT (w->top) + XINT (w->height) - 1)
-       {
-         previous_y = x_mouse_y;
-         line = (x_mouse_y + 1) * f->output_data.x->line_height
-           + f->output_data.x->internal_border_width;
-         XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                    line_gc, left, line, right, line);
-       }
-      XFlush (FRAME_X_DISPLAY (f));
-      UNBLOCK_INPUT;
-
-      do
-       {
-         obj = read_char (-1, 0, 0, Qnil, 0);
-         if (!CONSP (obj)
-             || (! EQ (Fcar (Fcdr (Fcdr (obj))),
-                       Qvertical_scroll_bar))
-             || x_mouse_grabbed)
-           {
-             BLOCK_INPUT;
-             XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                        erase_gc, left, line, right, line);
-             unread_command_event = obj;
-#if 0
-             XFreeGC (FRAME_X_DISPLAY (f), line_gc);
-             XFreeGC (FRAME_X_DISPLAY (f), erase_gc);
-#endif 
-             UNBLOCK_INPUT;
-             return Qnil;
-           }
-       }
-      while (x_mouse_y == previous_y);
-
-      BLOCK_INPUT;
-      XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                erase_gc, left, line, right, line);
-      UNBLOCK_INPUT;
-    }
-}
-#endif
-\f
-#if 0
-/* These keep track of the rectangle following the pointer.  */
-int mouse_track_top, mouse_track_left, mouse_track_width;
-
-/* Offset in buffer of character under the pointer, or 0.  */
-int mouse_buffer_offset;
-
-DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 0, 0, 0,
-  "Track the pointer.")
-  ()
-{
-  static Cursor current_pointer_shape;
-  FRAME_PTR f = x_mouse_frame;
-
-  BLOCK_INPUT;
-  if (EQ (Vmouse_frame_part, Qtext_part)
-      && (current_pointer_shape != f->output_data.x->nontext_cursor))
-    {
-      unsigned char c;
-      struct buffer *buf;
-
-      current_pointer_shape = f->output_data.x->nontext_cursor;
-      XDefineCursor (FRAME_X_DISPLAY (f),
-                    FRAME_X_WINDOW (f),
-                    current_pointer_shape);
-
-      buf = XBUFFER (XWINDOW (Vmouse_window)->buffer);
-      c = *(BUF_CHAR_ADDRESS (buf, mouse_buffer_offset));
-    }
-  else if (EQ (Vmouse_frame_part, Qmodeline_part)
-          && (current_pointer_shape != f->output_data.x->modeline_cursor))
-    {
-      current_pointer_shape = f->output_data.x->modeline_cursor;
-      XDefineCursor (FRAME_X_DISPLAY (f),
-                    FRAME_X_WINDOW (f),
-                    current_pointer_shape);
-    }
-
-  XFlush (FRAME_X_DISPLAY (f));
-  UNBLOCK_INPUT;
-}
-#endif
-
-#if 0
-DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 1, 1, "e",
-  "Draw rectangle around character under mouse pointer, if there is one.")
-  (event)
-     Lisp_Object event;
-{
-  struct window *w = XWINDOW (Vmouse_window);
-  struct frame *f = XFRAME (WINDOW_FRAME (w));
-  struct buffer *b = XBUFFER (w->buffer);
-  Lisp_Object obj;
-
-  if (! EQ (Vmouse_window, selected_window))
-      return Qnil;
-
-  if (EQ (event, Qnil))
-    {
-      int x, y;
-
-      x_read_mouse_position (selected_frame, &x, &y);
-    }
-
-  BLOCK_INPUT;
-  mouse_track_width = 0;
-  mouse_track_left = mouse_track_top = -1;
-
-  do
-    {
-      if ((x_mouse_x != mouse_track_left
-          && (x_mouse_x < mouse_track_left
-              || x_mouse_x > (mouse_track_left + mouse_track_width)))
-         || x_mouse_y != mouse_track_top)
-       {
-         int hp = 0;           /* Horizontal position */
-         int len = FRAME_CURRENT_GLYPHS (f)->used[x_mouse_y];
-         int p = FRAME_CURRENT_GLYPHS (f)->bufp[x_mouse_y];
-         int tab_width = XINT (b->tab_width);
-         int ctl_arrow_p = !NILP (b->ctl_arrow);
-         unsigned char c;
-         int mode_line_vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
-         int in_mode_line = 0;
-
-         if (! FRAME_CURRENT_GLYPHS (f)->enable[x_mouse_y])
-           break;
-
-         /* Erase previous rectangle.  */
-         if (mouse_track_width)
-           {
-             x_rectangle (f, f->output_data.x->reverse_gc,
-                          mouse_track_left, mouse_track_top,
-                          mouse_track_width, 1);
-
-             if ((mouse_track_left == f->phys_cursor_x
-                  || mouse_track_left == f->phys_cursor_x - 1)
-                 && mouse_track_top == f->phys_cursor_y)
-               {
-                 x_display_cursor (f, 1);
-               }
-           }
-
-         mouse_track_left = x_mouse_x;
-         mouse_track_top = x_mouse_y;
-         mouse_track_width = 0;
-
-         if (mouse_track_left > len) /* Past the end of line.  */
-           goto draw_or_not;
-
-         if (mouse_track_top == mode_line_vpos)
-           {
-             in_mode_line = 1;
-             goto draw_or_not;
-           }
-
-         if (tab_width <= 0 || tab_width > 20) tab_width = 8;
-         do
-           {
-             c = FETCH_BYTE (p);
-             if (len == f->width && hp == len - 1 && c != '\n')
-               goto draw_or_not;
-
-             switch (c)
-               {
-               case '\t':
-                 mouse_track_width = tab_width - (hp % tab_width);
-                 p++;
-                 hp += mouse_track_width;
-                 if (hp > x_mouse_x)
-                   {
-                     mouse_track_left = hp - mouse_track_width;
-                     goto draw_or_not;
-                   }
-                 continue;
-
-               case '\n':
-                 mouse_track_width = -1;
-                 goto draw_or_not;
-
-               default:
-                 if (ctl_arrow_p && (c < 040 || c == 0177))
-                   {
-                     if (p > ZV)
-                       goto draw_or_not;
-
-                     mouse_track_width = 2;
-                     p++;
-                     hp +=2;
-                     if (hp > x_mouse_x)
-                       {
-                         mouse_track_left = hp - mouse_track_width;
-                         goto draw_or_not;
-                       }
-                   }
-                 else
-                   {
-                     mouse_track_width = 1;
-                     p++;
-                     hp++;
-                   }
-                 continue;
-               }
-           }
-         while (hp <= x_mouse_x);
-
-       draw_or_not:
-         if (mouse_track_width) /* Over text; use text pointer shape.  */
-           {
-             XDefineCursor (FRAME_X_DISPLAY (f),
-                            FRAME_X_WINDOW (f),
-                            f->output_data.x->text_cursor);
-             x_rectangle (f, f->output_data.x->cursor_gc,
-                          mouse_track_left, mouse_track_top,
-                          mouse_track_width, 1);
-           }
-         else if (in_mode_line)
-           XDefineCursor (FRAME_X_DISPLAY (f),
-                          FRAME_X_WINDOW (f),
-                          f->output_data.x->modeline_cursor);
-         else
-           XDefineCursor (FRAME_X_DISPLAY (f),
-                          FRAME_X_WINDOW (f),
-                          f->output_data.x->nontext_cursor);
-       }
-
-      XFlush (FRAME_X_DISPLAY (f));
-      UNBLOCK_INPUT;
-
-      obj = read_char (-1, 0, 0, Qnil, 0);
-      BLOCK_INPUT;
-    }
-  while (CONSP (obj)              /* Mouse event */
-        && EQ (Fcar (Fcdr (Fcdr (obj))), Qnil)    /* Not scroll bar */
-        && EQ (Vmouse_depressed, Qnil)              /* Only motion events */
-        && EQ (Vmouse_window, selected_window)    /* In this window */
-        && x_mouse_frame);
-
-  unread_command_event = obj;
-
-  if (mouse_track_width)
-    {
-      x_rectangle (f, f->output_data.x->reverse_gc,
-                  mouse_track_left, mouse_track_top,
-                  mouse_track_width, 1);
-      mouse_track_width = 0;
-      if ((mouse_track_left == f->phys_cursor_x
-          || mouse_track_left - 1 == f->phys_cursor_x)
-         && mouse_track_top == f->phys_cursor_y)
-       {
-         x_display_cursor (f, 1);
-       }
-    }
-  XDefineCursor (FRAME_X_DISPLAY (f),
-                FRAME_X_WINDOW (f),
-                f->output_data.x->nontext_cursor);
-  XFlush (FRAME_X_DISPLAY (f));
-  UNBLOCK_INPUT;
-
-  return Qnil;
-}
-#endif
-\f
-#if 0
-#include "glyphs.h"
-
-/* Draw a pixmap specified by IMAGE_DATA of dimensions WIDTH and HEIGHT
-   on the frame F at position X, Y.  */
-
-x_draw_pixmap (f, x, y, image_data, width, height)
-     struct frame *f;
-     int x, y, width, height;
-     char *image_data;
-{
-  Pixmap image;
-
-  image = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
-                                FRAME_X_WINDOW (f), image_data,
-                                width, height);
-  XCopyPlane (FRAME_X_DISPLAY (f), image, FRAME_X_WINDOW (f),
-             f->output_data.x->normal_gc, 0, 0, width, height, x, y);
-}
-#endif
-\f
-#if 0 /* I'm told these functions are superfluous
-        given the ability to bind function keys.  */
-
-#ifdef HAVE_X11
-DEFUN ("x-rebind-key", Fx_rebind_key, Sx_rebind_key, 3, 3, 0,
-"Rebind X keysym KEYSYM, with MODIFIERS, to generate NEWSTRING.\n\
-KEYSYM is a string which conforms to the X keysym definitions found\n\
-in X11/keysymdef.h, sans the initial XK_. MODIFIERS is nil or a\n\
-list of strings specifying modifier keys such as Control_L, which must\n\
-also be depressed for NEWSTRING to appear.")
-  (x_keysym, modifiers, newstring)
-     register Lisp_Object x_keysym;
-     register Lisp_Object modifiers;
-     register Lisp_Object newstring;
-{
-  char *rawstring;
-  register KeySym keysym;
-  KeySym modifier_list[16];
-
-  check_x ();
-  CHECK_STRING (x_keysym, 1);
-  CHECK_STRING (newstring, 3);
-
-  keysym = XStringToKeysym ((char *) XSTRING (x_keysym)->data);
-  if (keysym == NoSymbol)
-    error ("Keysym does not exist");
-
-  if (NILP (modifiers))
-    XRebindKeysym (x_current_display, keysym, modifier_list, 0,
-                  XSTRING (newstring)->data,
-                  STRING_BYTES (XSTRING (newstring)));
-  else
-    {
-      register Lisp_Object rest, mod;
-      register int i = 0;
-
-      for (rest = modifiers; !NILP (rest); rest = Fcdr (rest))
-       {
-         if (i == 16)
-           error ("Can't have more than 16 modifiers");
-
-         mod = Fcar (rest);
-         CHECK_STRING (mod, 3);
-         modifier_list[i] = XStringToKeysym ((char *) XSTRING (mod)->data);
-#ifndef HAVE_X11R5
-         if (modifier_list[i] == NoSymbol
-             || !(IsModifierKey (modifier_list[i]) 
-                   || ((unsigned)(modifier_list[i]) == XK_Mode_switch)
-                   || ((unsigned)(modifier_list[i]) == XK_Num_Lock)))
-#else
-         if (modifier_list[i] == NoSymbol
-             || !IsModifierKey (modifier_list[i]))
-#endif
-           error ("Element is not a modifier keysym");
-         i++;
-       }
-
-      XRebindKeysym (x_current_display, keysym, modifier_list, i,
-                    XSTRING (newstring)->data,
-                    STRING_BYTES (XSTRING (newstring)));
-    }
-
-  return Qnil;
-}
-  
-DEFUN ("x-rebind-keys", Fx_rebind_keys, Sx_rebind_keys, 2, 2, 0,
-  "Rebind KEYCODE to list of strings STRINGS.\n\
-STRINGS should be a list of 16 elements, one for each shift combination.\n\
-nil as element means don't change.\n\
-See the documentation of `x-rebind-key' for more information.")
-  (keycode, strings)
-     register Lisp_Object keycode;
-     register Lisp_Object strings;
-{
-  register Lisp_Object item;
-  register unsigned char *rawstring;
-  KeySym rawkey, modifier[1];
-  int strsize;
-  register unsigned i;
-
-  check_x ();
-  CHECK_NUMBER (keycode, 1);
-  CHECK_CONS (strings, 2);
-  rawkey = (KeySym) ((unsigned) (XINT (keycode))) & 255;
-  for (i = 0; i <= 15; strings = Fcdr (strings), i++)
-    {
-      item = Fcar (strings);
-      if (!NILP (item))
-       {
-         CHECK_STRING (item, 2);
-         strsize = STRING_BYTES (XSTRING (item));
-         rawstring = (unsigned char *) xmalloc (strsize);
-         bcopy (XSTRING (item)->data, rawstring, strsize);
-         modifier[1] = 1 << i;
-         XRebindKeysym (x_current_display, rawkey, modifier, 1,
-                        rawstring, strsize);
-       }
-    }
-  return Qnil;
-}
-#endif /* HAVE_X11 */
-#endif /* 0 */
-\f
-#ifndef HAVE_XSCREENNUMBEROFSCREEN
-int
-XScreenNumberOfScreen (scr)
-    register Screen *scr;
-{
-  register Display *dpy;
-  register Screen *dpyscr;
-  register int i;
-
-  dpy = scr->display;
-  dpyscr = dpy->screens;
-
-  for (i = 0; i < dpy->nscreens; i++, dpyscr++)
-    if (scr == dpyscr)
-      return i;
-
-  return -1;
-}
-#endif /* not HAVE_XSCREENNUMBEROFSCREEN */
-
-Visual *
-select_visual (dpy, screen, depth)
-     Display *dpy;
-     Screen *screen;
-     unsigned int *depth;
-{
-  Visual *v;
-  XVisualInfo *vinfo, vinfo_template;
-  int n_visuals;
-
-  v = DefaultVisualOfScreen (screen);
-
-#ifdef HAVE_X11R4
-  vinfo_template.visualid = XVisualIDFromVisual (v);
-#else
-  vinfo_template.visualid = v->visualid;
-#endif
-
-  vinfo_template.screen = XScreenNumberOfScreen (screen);
-
-  vinfo = XGetVisualInfo (dpy,
-                         VisualIDMask | VisualScreenMask, &vinfo_template,
-                         &n_visuals);
-  if (n_visuals != 1)
-    fatal ("Can't get proper X visual info");
-
-  if ((1 << vinfo->depth) == vinfo->colormap_size)
-    *depth = vinfo->depth;
-  else
-    {
-      int i = 0;
-      int n = vinfo->colormap_size - 1;
-      while (n)
-       {
-         n = n >> 1;
-         i++;
-       }
-      *depth = i;
-    }
-
-  XFree ((char *) vinfo);
-  return v;
-}
-
-/* Return the X display structure for the display named NAME.
-   Open a new connection if necessary.  */
-
-struct x_display_info *
-x_display_info_for_name (name)
-     Lisp_Object name;
-{
-  Lisp_Object names;
-  struct x_display_info *dpyinfo;
-
-  CHECK_STRING (name, 0);
-
-  if (! EQ (Vwindow_system, intern ("x")))
-    error ("Not using X Windows");
-
-  for (dpyinfo = x_display_list, names = x_display_name_list;
-       dpyinfo;
-       dpyinfo = dpyinfo->next, names = XCDR (names))
-    {
-      Lisp_Object tem;
-      tem = Fstring_equal (XCAR (XCAR (names)), name);
-      if (!NILP (tem))
-       return dpyinfo;
-    }
-
-  /* Use this general default value to start with.  */
-  Vx_resource_name = Vinvocation_name;
-
-  validate_x_resource_name ();
-
-  dpyinfo = x_term_init (name, (unsigned char *)0,
-                        (char *) XSTRING (Vx_resource_name)->data);
-
-  if (dpyinfo == 0)
-    error ("Cannot connect to X server %s", XSTRING (name)->data);
-
-  x_in_use = 1;
-  XSETFASTINT (Vwindow_system_version, 11);
-
-  return dpyinfo;
-}
-
-DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
-       1, 3, 0, "Open a connection to an X server.\n\
-DISPLAY is the name of the display to connect to.\n\
-Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
-If the optional third arg MUST-SUCCEED is non-nil,\n\
-terminate Emacs if we can't open the connection.")
-  (display, xrm_string, must_succeed)
-     Lisp_Object display, xrm_string, must_succeed;
-{
-  unsigned char *xrm_option;
-  struct x_display_info *dpyinfo;
-
-  CHECK_STRING (display, 0);
-  if (! NILP (xrm_string))
-    CHECK_STRING (xrm_string, 1);
-
-  if (! EQ (Vwindow_system, intern ("x")))
-    error ("Not using X Windows");
-
-  if (! NILP (xrm_string))
-    xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
-  else
-    xrm_option = (unsigned char *) 0;
-
-  validate_x_resource_name ();
+  validate_x_resource_name ();
 
   /* This is what opens the connection and sets x_current_display.
      This also initializes many symbols, such as those used for input.  */
@@ -5596,9 +4821,9 @@ If DISPLAY is nil, that stands for the selected frame's display.")
   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);
-       /* Don't free the full_name string;
-          it is always shared with something else.  */
        XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
       }
 
@@ -5674,10 +4899,6 @@ x_sync (f)
 
 static struct image_type *image_types;
 
-/* A list of symbols, one for each supported image type.  */
-
-Lisp_Object Vimage_types;
-
 /* The symbol `image' which is the car of the lists used to represent
    images in Lisp.  */
 
@@ -5689,8 +4910,9 @@ Lisp_Object Qxbm;
 
 /* Keywords.  */
 
-Lisp_Object QCtype, QCdata, QCascent, QCmargin, QCrelief;
 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
+extern Lisp_Object QCdata;
+Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
 Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask;
 Lisp_Object QCindex;
 
@@ -5800,6 +5022,7 @@ enum image_value_type
   IMAGE_SYMBOL_VALUE,
   IMAGE_POSITIVE_INTEGER_VALUE,
   IMAGE_NON_NEGATIVE_INTEGER_VALUE,
+  IMAGE_ASCENT_VALUE,
   IMAGE_INTEGER_VALUE,
   IMAGE_FUNCTION_VALUE,
   IMAGE_NUMBER_VALUE,
@@ -5902,6 +5125,15 @@ parse_image_spec (spec, keywords, nkeywords, type)
            return 0;
          break;
 
+       case IMAGE_ASCENT_VALUE:
+         if (SYMBOLP (value) && EQ (value, Qcenter))
+           break;
+         else if (INTEGERP (value)
+                  && XINT (value) >= 0
+                  && XINT (value) <= 100)
+           break;
+         return 0;
+             
        case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
          if (!INTEGERP (value) || XINT (value) < 0)
            return 0;
@@ -6064,6 +5296,31 @@ prepare_image_for_display (f, img)
 }
      
 
+/* Value is the number of pixels for the ascent of image IMG when
+   drawn in face FACE.  */
+
+int
+image_ascent (img, face)
+     struct image *img;
+     struct face *face;
+{
+  int height = img->height + img->margin;
+  int ascent;
+
+  if (img->ascent == CENTERED_IMAGE_ASCENT)
+    {
+      if (face->font)
+       ascent = height / 2 - (face->font->descent - face->font->ascent) / 2;
+      else
+       ascent = height / 2;
+    }
+  else
+    ascent = height * img->ascent / 100.0;
+
+  return ascent;
+}
+
+
 \f
 /***********************************************************************
                  Helper functions for X image types
@@ -6092,21 +5349,9 @@ x_clear_image (f, img)
       
   if (img->ncolors)
     {
-      int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
-      
-      /* If display has an immutable color map, freeing colors is not
-        necessary and some servers don't allow it.  So don't do it.  */
-      if (class != StaticColor
-         && class != StaticGray
-         && class != TrueColor)
-       {
-         Colormap cmap;
-         BLOCK_INPUT;
-         cmap = DefaultColormapOfScreen (FRAME_X_DISPLAY_INFO (f)->screen);
-         XFreeColors (FRAME_X_DISPLAY (f), cmap, img->colors,
-                      img->ncolors, 0);
-         UNBLOCK_INPUT;
-       }
+      BLOCK_INPUT;
+      x_free_colors (f, img->colors, img->ncolors);
+      UNBLOCK_INPUT;
       
       xfree (img->colors);
       img->colors = NULL;
@@ -6195,8 +5440,8 @@ free_image_cache (f)
       for (i = 0; i < c->used; ++i)
        free_image (f, c->images[i]);
       xfree (c->images);
-      xfree (c);
       xfree (c->buckets);
+      xfree (c);
       FRAME_X_IMAGE_CACHE (f) = NULL;
     }
 }
@@ -6328,13 +5573,15 @@ lookup_image (f, spec)
       else
        {
          /* Handle image type independent image attributes
-            `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'.  */
+            `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'.  */
          Lisp_Object ascent, margin, relief, algorithm, heuristic_mask;
          Lisp_Object file;
 
          ascent = image_spec_value (spec, QCascent, NULL);
          if (INTEGERP (ascent))
            img->ascent = XFASTINT (ascent);
+         else if (EQ (ascent, Qcenter))
+           img->ascent = CENTERED_IMAGE_ASCENT;
          
          margin = image_spec_value (spec, QCmargin, NULL);
          if (INTEGERP (margin) && XINT (margin) >= 0)
@@ -6525,10 +5772,12 @@ x_put_x_image (f, ximg, pixmap, width, height)
 
 \f
 /***********************************************************************
-                             Searching files
+                             File Handling
  ***********************************************************************/
 
 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
+static char *slurp_file P_ ((char *, int *));
+
 
 /* Find image file FILE.  Look in data-directory, then
    x-bitmap-file-path.  Value is the full name of the file found, or
@@ -6554,8 +5803,44 @@ x_find_image_file (file)
   else
     close (fd);
 
-  UNGCPRO;
-  return file_found;
+  UNGCPRO;
+  return file_found;
+}
+
+
+/* Read FILE into memory.  Value is a pointer to a buffer allocated
+   with xmalloc holding FILE's contents.  Value is null if an error
+   occured.  *SIZE is set to the size of the file.  */
+
+static char *
+slurp_file (file, size)
+     char *file;
+     int *size;
+{
+  FILE *fp = NULL;
+  char *buf = NULL;
+  struct stat st;
+
+  if (stat (file, &st) == 0
+      && (fp = fopen (file, "r")) != NULL
+      && (buf = (char *) xmalloc (st.st_size),
+         fread (buf, 1, st.st_size, fp) == st.st_size))
+    {
+      *size = st.st_size;
+      fclose (fp);
+    }
+  else
+    {
+      if (fp)
+       fclose (fp);
+      if (buf)
+       {
+         xfree (buf);
+         buf = NULL;
+       }
+    }
+  
+  return buf;
 }
 
 
@@ -6564,12 +5849,14 @@ x_find_image_file (file)
                              XBM images
  ***********************************************************************/
 
+static int xbm_scan P_ ((char **, char *, char *, int *));
 static int xbm_load P_ ((struct frame *f, struct image *img));
-static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
-                                        Lisp_Object file));
+static int xbm_load_image P_ ((struct frame *f, struct image *img,
+                              char *, char *));
 static int xbm_image_p P_ ((Lisp_Object object));
-static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
-                                         unsigned char **));
+static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
+                                    unsigned char **));
+static int xbm_file_p P_ ((Lisp_Object));
 
 
 /* Indices of image specification fields in xbm_format, below.  */
@@ -6603,7 +5890,7 @@ static struct image_keyword xbm_format[XBM_LAST] =
   {":data",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":foreground",      IMAGE_STRING_VALUE,                     0},
   {":background",      IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -6650,10 +5937,14 @@ enum xbm_token
    3. a vector of strings or bool-vectors, one for each line of the
    bitmap.
 
+   4. A string containing an in-memory XBM file.  WIDTH and HEIGHT
+   may not be specified in this case because they are defined in the
+   XBM file.
+
    Both the file and data forms may contain the additional entries
    `:background COLOR' and `:foreground COLOR'.  If not present,
    foreground and background of the frame on which the image is
-   displayed, is used.  */
+   displayed is used.  */
 
 static int
 xbm_image_p (object)
@@ -6672,6 +5963,12 @@ xbm_image_p (object)
       if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
        return 0;
     }
+  else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
+    {
+      /* In-memory XBM file.  */
+      if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
+       return 0;
+    }
   else
     {
       Lisp_Object data;
@@ -6733,11 +6030,6 @@ xbm_image_p (object)
        return 0;
     }
 
-  /* Baseline must be a value between 0 and 100 (a percentage).  */
-  if (kw[XBM_ASCENT].count
-      && XFASTINT (kw[XBM_ASCENT].value) > 100)
-    return 0;
-  
   return 1;
 }
 
@@ -6749,30 +6041,31 @@ xbm_image_p (object)
    scanning a number, store its value in *IVAL.  */
 
 static int
-xbm_scan (fp, sval, ival)
-     FILE *fp;
+xbm_scan (s, end, sval, ival)
+     char **s, *end;
      char *sval;
      int *ival;
 {
   int c;
   
   /* Skip white space.  */
-  while ((c = fgetc (fp)) != EOF && isspace (c))
+  while (*s < end && (c = *(*s)++, isspace (c)))
     ;
 
-  if (c == EOF)
+  if (*s >= end)
     c = 0;
   else if (isdigit (c))
     {
       int value = 0, digit;
       
-      if (c == '0')
+      if (c == '0' && *s < end)
        {
-         c = fgetc (fp);
+         c = *(*s)++;
          if (c == 'x' || c == 'X')
            {
-             while ((c = fgetc (fp)) != EOF)
+             while (*s < end)
                {
+                 c = *(*s)++;
                  if (isdigit (c))
                    digit = c - '0';
                  else if (c >= 'a' && c <= 'f')
@@ -6787,33 +6080,33 @@ xbm_scan (fp, sval, ival)
          else if (isdigit (c))
            {
              value = c - '0';
-             while ((c = fgetc (fp)) != EOF
-                    && isdigit (c))
+             while (*s < end
+                    && (c = *(*s)++, isdigit (c)))
                value = 8 * value + c - '0';
            }
        }
       else
        {
          value = c - '0';
-         while ((c = fgetc (fp)) != EOF
-                && isdigit (c))
+         while (*s < end
+                && (c = *(*s)++, isdigit (c)))
            value = 10 * value + c - '0';
        }
 
-      if (c != EOF)
-       ungetc (c, fp);
+      if (*s < end)
+       *s = *s - 1;
       *ival = value;
       c = XBM_TK_NUMBER;
     }
   else if (isalpha (c) || c == '_')
     {
       *sval++ = c;
-      while ((c = fgetc (fp)) != EOF
-            && (isalnum (c) || c == '_'))
+      while (*s < end
+            && (c = *(*s)++, (isalnum (c) || c == '_')))
        *sval++ = c;
       *sval = 0;
-      if (c != EOF)
-       ungetc (c, fp);
+      if (*s < end)
+       *s = *s - 1;
       c = XBM_TK_IDENT;
     }
 
@@ -6822,18 +6115,19 @@ xbm_scan (fp, sval, ival)
 
 
 /* Replacement for XReadBitmapFileData which isn't available under old
-   X versions.  FILE is the name of the bitmap file to read.  Set
-   *WIDTH and *HEIGHT to the width and height of the image.  Return in
-   *DATA the bitmap data allocated with xmalloc.  Value is non-zero if
-   successful.  */
+   X versions.  CONTENTS is a pointer to a buffer to parse; END is the
+   buffer's end.  Set *WIDTH and *HEIGHT to the width and height of
+   the image.  Return in *DATA the bitmap data allocated with xmalloc.
+   Value is non-zero if successful.  DATA null means just test if
+   CONTENTS looks like an im-memory XBM file.  */
 
 static int
-xbm_read_bitmap_file_data (file, width, height, data)
-     char *file;
+xbm_read_bitmap_data (contents, end, width, height, data)
+     char *contents, *end;
      int *width, *height;
      unsigned char **data;
 {
-  FILE *fp;
+  char *s = contents;
   char buffer[BUFSIZ];
   int padding_p = 0;
   int v10 = 0;
@@ -6843,7 +6137,7 @@ xbm_read_bitmap_file_data (file, width, height, data)
   int LA1;
 
 #define match() \
-     LA1 = xbm_scan (fp, buffer, &value)
+     LA1 = xbm_scan (&s, end, buffer, &value)
 
 #define expect(TOKEN)          \
      if (LA1 != (TOKEN))       \
@@ -6857,13 +6151,10 @@ xbm_read_bitmap_file_data (file, width, height, data)
      else                                                      \
        goto failure
 
-  fp = fopen (file, "r");
-  if (fp == NULL)
-    return 0;
-
   *width = *height = -1;
-  *data = NULL;
-  LA1 = xbm_scan (fp, buffer, &value);
+  if (data)
+    *data = NULL;
+  LA1 = xbm_scan (&s, end, buffer, &value);
 
   /* Parse defines for width, height and hot-spots.  */
   while (LA1 == '#')
@@ -6886,6 +6177,8 @@ xbm_read_bitmap_file_data (file, width, height, data)
 
   if (*width < 0 || *height < 0)
     goto failure;
+  else if (data == NULL)
+    goto success;
 
   /* Parse bits.  Must start with `static'.  */
   expect_ident ("static");
@@ -6923,7 +6216,6 @@ xbm_read_bitmap_file_data (file, width, height, data)
 
   if (v10)
     {
-      
       for (i = 0; i < nbytes; i += 2)
        {
          int val = value;
@@ -6955,13 +6247,12 @@ xbm_read_bitmap_file_data (file, width, height, data)
        }
     }
 
-  fclose (fp);
+ success:
   return 1;
 
  failure:
   
-  fclose (fp);
-  if (*data)
+  if (data && *data)
     {
       xfree (*data);
       *data = NULL;
@@ -6974,35 +6265,21 @@ xbm_read_bitmap_file_data (file, width, height, data)
 }
 
 
-/* Load XBM image IMG which will be displayed on frame F from file
-   SPECIFIED_FILE.  Value is non-zero if successful.  */
+/* Load XBM image IMG which will be displayed on frame F from buffer
+   CONTENTS.  END is the end of the buffer.  Value is non-zero if
+   successful.  */
 
 static int
-xbm_load_image_from_file (f, img, specified_file)
+xbm_load_image (f, img, contents, end)
      struct frame *f;
      struct image *img;
-     Lisp_Object specified_file;
+     char *contents, *end;
 {
   int rc;
   unsigned char *data;
   int success_p = 0;
-  Lisp_Object file;
-  struct gcpro gcpro1;
   
-  xassert (STRINGP (specified_file));
-  file = Qnil;
-  GCPRO1 (file);
-
-  file = x_find_image_file (specified_file);
-  if (!STRINGP (file))
-    {
-      image_error ("Cannot find image file `%s'", specified_file, Qnil);
-      UNGCPRO;
-      return 0;
-    }
-         
-  rc = xbm_read_bitmap_file_data (XSTRING (file)->data, &img->width,
-                                 &img->height, &data);
+  rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
   if (rc)
     {
       int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
@@ -7034,7 +6311,7 @@ xbm_load_image_from_file (f, img, specified_file)
       if (img->pixmap == 0)
        {
          x_clear_image (f, img);
-         image_error ("Unable to create X pixmap for `%s'", file, Qnil);
+         image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
        }
       else
        success_p = 1;
@@ -7044,11 +6321,25 @@ xbm_load_image_from_file (f, img, specified_file)
   else
     image_error ("Error loading XBM image `%s'", img->spec, Qnil);
 
-  UNGCPRO;
   return success_p;
 }
 
 
+/* Value is non-zero if DATA looks like an in-memory XBM file.  */
+
+static int
+xbm_file_p (data)
+     Lisp_Object data;
+{
+  int w, h;
+  return (STRINGP (data)
+         && xbm_read_bitmap_data (XSTRING (data)->data,
+                                  (XSTRING (data)->data
+                                   + STRING_BYTES (XSTRING (data))),
+                                  &w, &h, NULL));
+}
+
+    
 /* Fill image IMG which is used on frame F with pixmap data.  Value is
    non-zero if successful.  */
 
@@ -7065,32 +6356,63 @@ xbm_load (f, img)
   /* If IMG->spec specifies a file name, create a non-file spec from it.  */
   file_name = image_spec_value (img->spec, QCfile, NULL);
   if (STRINGP (file_name))
-    success_p = xbm_load_image_from_file (f, img, file_name);
+    {
+      Lisp_Object file;
+      char *contents;
+      int size;
+      struct gcpro gcpro1;
+      
+      file = x_find_image_file (file_name);
+      GCPRO1 (file);
+      if (!STRINGP (file))
+       {
+         image_error ("Cannot find image file `%s'", file_name, Qnil);
+         UNGCPRO;
+         return 0;
+       }
+
+      contents = slurp_file (XSTRING (file)->data, &size);
+      if (contents == NULL)
+       {
+         image_error ("Error loading XBM image `%s'", img->spec, Qnil);
+         UNGCPRO;
+         return 0;
+       }
+
+      success_p = xbm_load_image (f, img, contents, contents + size);
+      UNGCPRO;
+    }
   else
     {
       struct image_keyword fmt[XBM_LAST];
       Lisp_Object data;
+      unsigned char *bitmap_data;
       int depth;
       unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
       unsigned long background = FRAME_BACKGROUND_PIXEL (f);
       char *bits;
-      int parsed_p;
+      int parsed_p, height, width;
+      int in_memory_file_p = 0;
+
+      /* See if data looks like an in-memory XBM file.  */
+      data = image_spec_value (img->spec, QCdata, NULL);
+      in_memory_file_p = xbm_file_p (data);
 
-      /* Parse the list specification.  */
+      /* Parse the image specification.  */
       bcopy (xbm_format, fmt, sizeof fmt);
       parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
       xassert (parsed_p);
 
       /* Get specified width, and height.  */
-      img->width = XFASTINT (fmt[XBM_WIDTH].value);
-      img->height = XFASTINT (fmt[XBM_HEIGHT].value);
-      xassert (img->width > 0 && img->height > 0);
+      if (!in_memory_file_p)
+       {
+         img->width = XFASTINT (fmt[XBM_WIDTH].value);
+         img->height = XFASTINT (fmt[XBM_HEIGHT].value);
+         xassert (img->width > 0 && img->height > 0);
+       }
 
       BLOCK_INPUT;
       
-      if (fmt[XBM_ASCENT].count)
-       img->ascent = XFASTINT (fmt[XBM_ASCENT].value);
-
       /* Get foreground and background colors, maybe allocate colors.  */
       if (fmt[XBM_FOREGROUND].count)
        foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
@@ -7099,46 +6421,51 @@ xbm_load (f, img)
        background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
                                          background);
 
-      /* Set bits to the bitmap image data.  */
-      data = fmt[XBM_DATA].value;
-      if (VECTORP (data))
+      if (in_memory_file_p)
+       success_p = xbm_load_image (f, img, XSTRING (data)->data,
+                                   (XSTRING (data)->data
+                                    + STRING_BYTES (XSTRING (data))));
+      else
        {
-         int i;
-         char *p;
-         int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
+         if (VECTORP (data))
+           {
+             int i;
+             char *p;
+             int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
          
-         p = bits = (char *) alloca (nbytes * img->height);
-         for (i = 0; i < img->height; ++i, p += nbytes)
+             p = bits = (char *) alloca (nbytes * img->height);
+             for (i = 0; i < img->height; ++i, p += nbytes)
+               {
+                 Lisp_Object line = XVECTOR (data)->contents[i];
+                 if (STRINGP (line))
+                   bcopy (XSTRING (line)->data, p, nbytes);
+                 else
+                   bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
+               }
+           }
+         else if (STRINGP (data))
+           bits = XSTRING (data)->data;
+         else
+           bits = XBOOL_VECTOR (data)->data;
+
+         /* Create the pixmap.  */
+         depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
+         img->pixmap
+           = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
+                                          FRAME_X_WINDOW (f),
+                                          bits,
+                                          img->width, img->height,
+                                          foreground, background,
+                                          depth);
+         if (img->pixmap)
+           success_p = 1;
+         else
            {
-             Lisp_Object line = XVECTOR (data)->contents[i];
-             if (STRINGP (line))
-               bcopy (XSTRING (line)->data, p, nbytes);
-             else
-               bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
+             image_error ("Unable to create pixmap for XBM image `%s'",
+                          img->spec, Qnil);
+             x_clear_image (f, img);
            }
        }
-      else if (STRINGP (data))
-       bits = XSTRING (data)->data;
-      else
-       bits = XBOOL_VECTOR (data)->data;
-
-      /* Create the pixmap.  */
-      depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
-      img->pixmap
-       = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
-                                      FRAME_X_WINDOW (f),
-                                      bits,
-                                      img->width, img->height,
-                                      foreground, background,
-                                      depth);
-      if (img->pixmap)
-       success_p = 1;
-      else
-       {
-         image_error ("Unable to create pixmap for XBM image `%s'",
-                      img->spec, Qnil);
-         x_clear_image (f, img);
-       }
 
       UNBLOCK_INPUT;
     }
@@ -7188,7 +6515,7 @@ static struct image_keyword xpm_format[XPM_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":data",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -7244,9 +6571,7 @@ xpm_image_p (object)
          /* Either no `:color-symbols' or it's a list of conses
             whose car and cdr are strings.  */
          && (fmt[XPM_COLOR_SYMBOLS].count == 0
-             || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
-         && (fmt[XPM_ASCENT].count == 0
-             || XFASTINT (fmt[XPM_ASCENT].value) < 100));
+             || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
 }
 
 
@@ -7265,8 +6590,10 @@ xpm_load (f, img)
   /* Configure the XPM lib.  Use the visual of frame F.  Allocate
      close colors.  Return colors allocated.  */
   bzero (&attrs, sizeof attrs);
-  attrs.visual = FRAME_X_DISPLAY_INFO (f)->visual;
+  attrs.visual = FRAME_X_VISUAL (f);
+  attrs.colormap = FRAME_X_COLORMAP (f);
   attrs.valuemask |= XpmVisual;
+  attrs.valuemask |= XpmColormap;
   attrs.valuemask |= XpmReturnAllocPixels;
 #ifdef XpmAllocCloseColors
   attrs.alloc_close_colors = 1;
@@ -7347,7 +6674,12 @@ xpm_load (f, img)
       img->colors = (unsigned long *) xmalloc (img->ncolors
                                               * sizeof *img->colors);
       for (i = 0; i < attrs.nalloc_pixels; ++i)
-       img->colors[i] = attrs.alloc_pixels[i];
+       {
+         img->colors[i] = attrs.alloc_pixels[i];
+#ifdef DEBUG_X_COLORS
+         register_color (img->colors[i]);
+#endif
+       }
 
       img->width = attrs.width;
       img->height = attrs.height;
@@ -7491,7 +6823,7 @@ lookup_rgb_color (f, r, g, b)
       color.blue = b;
       
       BLOCK_INPUT;
-      cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+      cmap = FRAME_X_COLORMAP (f);
       rc = x_alloc_nearest_color (f, cmap, &color);
       UNBLOCK_INPUT;
 
@@ -7538,7 +6870,7 @@ lookup_pixel_color (f, pixel)
 
       BLOCK_INPUT;
       
-      cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+      cmap = FRAME_X_COLORMAP (f);
       color.pixel = pixel;
       XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
       rc = x_alloc_nearest_color (f, cmap, &color);
@@ -7656,7 +6988,7 @@ x_laplace (f, img)
      struct frame *f;
      struct image *img;
 {
-  Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+  Colormap cmap = FRAME_X_COLORMAP (f);
   XImage *ximg, *oimg;
   XColor *in[3];
   long *out;
@@ -7794,7 +7126,7 @@ x_build_heuristic_mask (f, img, how)
 
          sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
          
-         cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+         cmap = FRAME_X_COLORMAP (f);
          if (XLookupColor (dpy, cmap, color_name, &exact, &color))
            {
              bg = color.pixel;
@@ -7880,7 +7212,7 @@ static struct image_keyword pbm_format[PBM_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":data",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -7909,9 +7241,7 @@ pbm_image_p (object)
   
   bcopy (pbm_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
-      || (fmt[PBM_ASCENT].count 
-         && XFASTINT (fmt[PBM_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
     return 0;
 
   /* Must specify either :data or :file.  */
@@ -7957,42 +7287,6 @@ pbm_scan_number (s, end)
 }
 
 
-/* Read FILE into memory.  Value is a pointer to a buffer allocated
-   with xmalloc holding FILE's contents.  Value is null if an error
-   occured.  *SIZE is set to the size of the file.  */
-
-static char *
-pbm_read_file (file, size)
-     Lisp_Object file;
-     int *size;
-{
-  FILE *fp = NULL;
-  char *buf = NULL;
-  struct stat st;
-
-  if (stat (XSTRING (file)->data, &st) == 0
-      && (fp = fopen (XSTRING (file)->data, "r")) != NULL
-      && (buf = (char *) xmalloc (st.st_size),
-         fread (buf, 1, st.st_size, fp) == st.st_size))
-    {
-      *size = st.st_size;
-      fclose (fp);
-    }
-  else
-    {
-      if (fp)
-       fclose (fp);
-      if (buf)
-       {
-         xfree (buf);
-         buf = NULL;
-       }
-    }
-  
-  return buf;
-}
-
-
 /* Load PBM image IMG for use on frame F.  */
 
 static int 
@@ -8024,7 +7318,7 @@ pbm_load (f, img)
          return 0;
        }
 
-      contents = pbm_read_file (file, &size);
+      contents = slurp_file (XSTRING (file)->data, &size);
       if (contents == NULL)
        {
          image_error ("Error reading `%s'", file, Qnil);
@@ -8236,7 +7530,7 @@ static struct image_keyword png_format[PNG_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -8264,9 +7558,7 @@ png_image_p (object)
   struct image_keyword fmt[PNG_LAST];
   bcopy (png_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
-      || (fmt[PNG_ASCENT].count 
-         && XFASTINT (fmt[PNG_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
     return 0;
 
   /* Must specify either the :data or :file keyword.  */
@@ -8530,7 +7822,7 @@ png_load (f, img)
          png_color_16 frame_background;
 
          BLOCK_INPUT;
-         cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+         cmap = FRAME_X_COLORMAP (f);
          color.pixel = FRAME_BACKGROUND_PIXEL (f);
          XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
          UNBLOCK_INPUT;
@@ -8722,7 +8014,7 @@ static struct image_keyword jpeg_format[JPEG_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -8751,9 +8043,7 @@ jpeg_image_p (object)
   
   bcopy (jpeg_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
-      || (fmt[JPEG_ASCENT].count 
-         && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
     return 0;
 
   /* Must specify either the :data or :file keyword.  */
@@ -8767,6 +8057,7 @@ struct my_jpeg_error_mgr
   jmp_buf setjmp_buffer;
 };
 
+
 static void
 my_error_exit (cinfo)
      j_common_ptr cinfo;
@@ -8775,6 +8066,7 @@ my_error_exit (cinfo)
   longjmp (mgr->setjmp_buffer, 1);
 }
 
+
 /* Init source method for JPEG data source manager.  Called by
    jpeg_read_header() before any data is actually read.  See
    libjpeg.doc from the JPEG lib distribution.  */
@@ -8919,8 +8211,8 @@ jpeg_load (f, img)
 
   /* Customize libjpeg's error handling to call my_error_exit when an
      error is detected.  This function will perform a longjmp.  */
-  mgr.pub.error_exit = my_error_exit;
   cinfo.err = jpeg_std_error (&mgr.pub);
+  mgr.pub.error_exit = my_error_exit;
   
   if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
     {
@@ -9084,7 +8376,7 @@ static struct image_keyword tiff_format[TIFF_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -9112,9 +8404,7 @@ tiff_image_p (object)
   struct image_keyword fmt[TIFF_LAST];
   bcopy (tiff_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
-      || (fmt[TIFF_ASCENT].count 
-         && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
     return 0;
   
   /* Must specify either the :data or :file keyword.  */
@@ -9139,6 +8429,7 @@ typedef struct
 }
 tiff_memory_source;
 
+
 static size_t
 tiff_read_from_memory (data, buf, size)
      thandle_t data;
@@ -9154,6 +8445,7 @@ tiff_read_from_memory (data, buf, size)
   return size;
 }
 
+
 static size_t
 tiff_write_from_memory (data, buf, size)
      thandle_t data;
@@ -9163,6 +8455,7 @@ tiff_write_from_memory (data, buf, size)
   return (size_t) -1;
 }
 
+
 static toff_t
 tiff_seek_in_memory (data, off, whence)
      thandle_t data;
@@ -9197,6 +8490,7 @@ tiff_seek_in_memory (data, off, whence)
   return src->index;
 }
 
+
 static int
 tiff_close_memory (data)
      thandle_t data;
@@ -9205,6 +8499,7 @@ tiff_close_memory (data)
   return 0;
 }
 
+
 static int
 tiff_mmap_memory (data, pbase, psize)
      thandle_t data;
@@ -9215,6 +8510,7 @@ tiff_mmap_memory (data, pbase, psize)
   return 0;
 }
 
+
 static void
 tiff_unmap_memory (data, base, size)
      thandle_t data;
@@ -9224,6 +8520,7 @@ tiff_unmap_memory (data, base, size)
   /* We don't need to do this. */
 }
 
+
 static toff_t
 tiff_size_of_memory (data)
      thandle_t data;
@@ -9231,6 +8528,7 @@ tiff_size_of_memory (data)
   return ((tiff_memory_source *) data)->len;
 }
 
+
 /* Load TIFF image IMG for use on frame F.  Value is non-zero if
    successful.  */
 
@@ -9403,7 +8701,7 @@ static struct image_keyword gif_format[GIF_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -9422,6 +8720,7 @@ static struct image_type gif_type =
   NULL
 };
 
+
 /* Return non-zero if OBJECT is a valid GIF image specification.  */
 
 static int
@@ -9431,15 +8730,14 @@ gif_image_p (object)
   struct image_keyword fmt[GIF_LAST];
   bcopy (gif_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
-      || (fmt[GIF_ASCENT].count 
-         && XFASTINT (fmt[GIF_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
     return 0;
   
   /* Must specify either the :data or :file keyword.  */
   return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
 }
 
+
 /* Reading a GIF image from memory
    Based on the PNG memory stuff to a certain extent. */
 
@@ -9451,6 +8749,7 @@ typedef struct
 }
 gif_memory_source;
 
+
 /* Make the current memory source available to gif_read_from_memory.
    It's done this way because not all versions of libungif support
    a UserData field in the GifFileType structure.  */
@@ -9717,7 +9016,7 @@ static struct image_keyword gs_format[GS_LAST] =
   {":file",            IMAGE_STRING_VALUE,                     1},
   {":loader",          IMAGE_FUNCTION_VALUE,                   0},
   {":bounding-box",    IMAGE_DONT_CHECK_VALUE_TYPE,            1},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -9762,9 +9061,7 @@ gs_image_p (object)
   
   bcopy (gs_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
-      || (fmt[GS_ASCENT].count 
-         && XFASTINT (fmt[GS_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
     return 0;
 
   /* Bounding box must be a list or vector containing 4 integers.  */
@@ -9892,7 +9189,7 @@ x_kill_gs_process (pixmap, f)
   /* On displays with a mutable colormap, figure out the colors
      allocated for the image by looking at the pixels of an XImage for
      img->pixmap.  */
-  class = FRAME_X_DISPLAY_INFO (f)->visual->class;
+  class = FRAME_X_VISUAL (f)->class;
   if (class != StaticColor && class != StaticGray && class != TrueColor)
     {
       XImage *ximg;
@@ -9931,11 +9228,7 @@ x_kill_gs_process (pixmap, f)
             allocated colors on behalf of us.  So, to get the
             reference counts right, free them once.  */
          if (img->ncolors)
-           {
-             Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
-             XFreeColors (FRAME_X_DISPLAY (f), cmap,
-                          img->colors, img->ncolors, 0);
-           }
+           x_free_colors (f, img->colors, img->ncolors);
 #endif
        }
       else
@@ -10057,48 +9350,114 @@ value.")
                                Busy cursor
  ***********************************************************************/
 
-/* The implementation partly follows a patch from
-   F.Pierresteguy@frcl.bull.fr dated 1994.  */
+/* If non-null, an asynchronous timer that, when it expires, displays
+   a busy cursor on all frames.  */
 
-/* Setting inhibit_busy_cursor to 2 inhibits busy-cursor display until
-   the next X event is read and we enter XTread_socket again.  Setting
-   it to 1 inhibits busy-cursor display for direct commands.  */
+static struct atimer *busy_cursor_atimer;
 
-int inhibit_busy_cursor;
+/* Non-zero means a busy cursor is currently shown.  */
 
-/* Incremented with each call to x-display-busy-cursor.
-   Decremented in x-undisplay-busy-cursor.  */
+static int busy_cursor_shown_p;
 
-static int busy_count;
+/* Number of seconds to wait before displaying a busy cursor.  */
 
+static Lisp_Object Vbusy_cursor_delay;
 
-DEFUN ("x-show-busy-cursor", Fx_show_busy_cursor,
-       Sx_show_busy_cursor, 0, 0, 0,
-  "Show a busy cursor, if not already shown.\n\
-Each call to this function must be matched by a call to\n\
-`x-hide-busy-cursor' to make the busy pointer disappear again.")
-  ()
+/* Default number of seconds to wait before displaying a busy
+   cursor.  */
+
+#define DEFAULT_BUSY_CURSOR_DELAY 1
+
+/* Function prototypes.  */
+
+static void show_busy_cursor P_ ((struct atimer *));
+static void hide_busy_cursor P_ ((void));
+
+
+/* Cancel a currently active busy-cursor timer, and start a new one.  */
+
+void
+start_busy_cursor ()
 {
-  ++busy_count;
-  if (busy_count == 1)
+  EMACS_TIME delay;
+  int secs, usecs = 0;
+  
+  cancel_busy_cursor ();
+
+  if (INTEGERP (Vbusy_cursor_delay)
+      && XINT (Vbusy_cursor_delay) > 0)
+    secs = XFASTINT (Vbusy_cursor_delay);
+  else if (FLOATP (Vbusy_cursor_delay)
+          && XFLOAT_DATA (Vbusy_cursor_delay) > 0)
     {
-      Lisp_Object rest, frame;
+      Lisp_Object tem;
+      tem = Ftruncate (Vbusy_cursor_delay, Qnil);
+      secs = XFASTINT (tem);
+      usecs = (XFLOAT_DATA (Vbusy_cursor_delay) - secs) * 1000000;
+    }
+  else
+    secs = DEFAULT_BUSY_CURSOR_DELAY;
+  
+  EMACS_SET_SECS_USECS (delay, secs, usecs);
+  busy_cursor_atimer = start_atimer (ATIMER_RELATIVE, delay,
+                                    show_busy_cursor, NULL);
+}
+
+
+/* Cancel the busy cursor timer if active, hide a busy cursor if
+   shown.  */
+
+void
+cancel_busy_cursor ()
+{
+  if (busy_cursor_atimer)
+    {
+      cancel_atimer (busy_cursor_atimer);
+      busy_cursor_atimer = NULL;
+    }
+  
+  if (busy_cursor_shown_p)
+    hide_busy_cursor ();
+}
+
+
+/* Timer function of busy_cursor_atimer.  TIMER is equal to
+   busy_cursor_atimer.
+
+   Display a busy cursor on all frames by mapping the frames'
+   busy_window.  Set the busy_p flag in the frames' output_data.x
+   structure to indicate that a busy cursor is shown on the
+   frames.  */
 
+static void
+show_busy_cursor (timer)
+     struct atimer *timer;
+{
+  /* The timer implementation will cancel this timer automatically
+     after this function has run.  Set busy_cursor_atimer to null
+     so that we know the timer doesn't have to be canceled.  */
+  busy_cursor_atimer = NULL;
+
+  if (!busy_cursor_shown_p)
+    {
+      Lisp_Object rest, frame;
+  
+      BLOCK_INPUT;
+  
       FOR_EACH_FRAME (rest, frame)
        if (FRAME_X_P (XFRAME (frame)))
          {
            struct frame *f = XFRAME (frame);
-           
-           BLOCK_INPUT;
+       
            f->output_data.x->busy_p = 1;
-           
+       
            if (!f->output_data.x->busy_window)
              {
                unsigned long mask = CWCursor;
                XSetWindowAttributes attrs;
-
+           
                attrs.cursor = f->output_data.x->busy_cursor;
-               
+           
                f->output_data.x->busy_window
                  = XCreateWindow (FRAME_X_DISPLAY (f),
                                   FRAME_OUTER_WINDOW (f),
@@ -10107,58 +9466,46 @@ Each call to this function must be matched by a call to\n\
                                   CopyFromParent,
                                   mask, &attrs);
              }
-
+       
            XMapRaised (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
-           UNBLOCK_INPUT;
+           XFlush (FRAME_X_DISPLAY (f));
          }
-    }
 
-  return Qnil;
+      busy_cursor_shown_p = 1;
+      UNBLOCK_INPUT;
+    }
 }
 
 
-DEFUN ("x-hide-busy-cursor", Fx_hide_busy_cursor,
-       Sx_hide_busy_cursor, 0, 1, 0,
-  "Hide a busy-cursor.\n\
-A busy-cursor will actually be undisplayed when a matching\n\
-`x-hide-busy-cursor' is called for each `x-show-busy-cursor'\n\
-issued.  FORCE non-nil means hide the busy-cursor forcibly,\n\
-not counting calls.")
-  (force)
-     Lisp_Object force;
-{
-  Lisp_Object rest, frame;
-
-  if (busy_count == 0)
-    return Qnil;
-
-  if (!NILP (force) && busy_count != 0)
-    busy_count = 1;
-
-  --busy_count;
-  if (busy_count != 0)
-    return Qnil;
+/* Hide the busy cursor on all frames, if it is currently shown.  */
 
-  FOR_EACH_FRAME (rest, frame)
+static void
+hide_busy_cursor ()
+{
+  if (busy_cursor_shown_p)
     {
-      struct frame *f = XFRAME (frame);
-      
-      if (FRAME_X_P (f)
-         /* Watch out for newly created frames.  */
-         && f->output_data.x->busy_window)
+      Lisp_Object rest, frame;
+
+      BLOCK_INPUT;
+      FOR_EACH_FRAME (rest, frame)
        {
-         
-         BLOCK_INPUT;
-         XUnmapWindow (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
-         /* Sync here because XTread_socket looks at the busy_p flag
-            that is reset to zero below.  */
-         XSync (FRAME_X_DISPLAY (f), False);
-         UNBLOCK_INPUT;
-         f->output_data.x->busy_p = 0;
+         struct frame *f = XFRAME (frame);
+      
+         if (FRAME_X_P (f)
+             /* Watch out for newly created frames.  */
+             && f->output_data.x->busy_window)
+           {
+             XUnmapWindow (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
+             /* Sync here because XTread_socket looks at the busy_p flag
+                that is reset to zero below.  */
+             XSync (FRAME_X_DISPLAY (f), False);
+             f->output_data.x->busy_p = 0;
+           }
        }
-    }
 
-  return Qnil;
+      busy_cursor_shown_p = 0;
+      UNBLOCK_INPUT;
+    }
 }
 
 
@@ -10251,10 +9598,6 @@ x_create_tip_frame (dpyinfo, parms)
       specbind (Qx_resource_name, name);
     }
 
-  /* Create fontsets from `global_fontset_alist' before handling fonts.  */
-  for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCDR (tem))
-    fs_register_fontset (f, XCAR (tem));
-
   /* Extract the window parameters from the supplied values
      that are needed to determine window geometry.  */
   {
@@ -10361,8 +9704,8 @@ x_create_tip_frame (dpyinfo, parms)
     
     BLOCK_INPUT;
     mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
-    /* Window managers looks at the override-redirect flag to
-       determine whether or net to give windows a decoration (Xlib
+    /* Window managers look at the override-redirect flag to determine
+       whether or net to give windows a decoration (Xlib spec, chapter
        3.2.8).  */
     attrs.override_redirect = True;
     attrs.save_under = True;
@@ -10479,8 +9822,8 @@ TIMEOUT nil means use the default timeout of 5 seconds.")
      will loose.  I don't think this is a realistic case.  */
   w = XWINDOW (FRAME_ROOT_WINDOW (f));
   w->left = w->top = make_number (0);
-  w->width = 80;
-  w->height = 40;
+  w->width = make_number (80);
+  w->height = make_number (40);
   adjust_glyphs (f);
   w->pseudo_window_p = 1;
 
@@ -10490,7 +9833,7 @@ TIMEOUT nil means use the default timeout of 5 seconds.")
   old_buffer = current_buffer;
   set_buffer_internal_1 (XBUFFER (buffer));
   Ferase_buffer ();
-  Finsert (make_number (1), &string);
+  Finsert (1, &string);
   clear_glyph_matrix (w->desired_matrix);
   clear_glyph_matrix (w->current_matrix);
   SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
@@ -10511,7 +9854,7 @@ TIMEOUT nil means use the default timeout of 5 seconds.")
       /* Let the row go over the full width of the frame.  */
       row->full_width_p = 1;
 
-      /* There's a glyph at the end of rows that is use to place
+      /* There's a glyph at the end of rows that is used to place
         the cursor there.  Don't include the width of this glyph.  */
       if (row->used[TEXT_AREA])
        {
@@ -10710,6 +10053,15 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
       XmListSetPos (list, item_pos);
     }
 
+#ifdef HAVE_MOTIF_2_1
+
+  /* Process events until the user presses Cancel or OK.  */
+  result = 0;
+  while (result == 0 || XtAppPending (Xt_app_con))
+    XtAppProcessEvent (Xt_app_con, XtIMAll);
+
+#else /* not HAVE_MOTIF_2_1 */
+  
   /* Process all events until the user presses Cancel or OK.  */
   for (result = 0; result == 0;)
     {
@@ -10725,13 +10077,15 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
       parent = widget;
       while (parent && parent != dialog)
        parent = XtParent (parent);
-      
+
       if (parent == dialog
          || (event.type == Expose
              && !process_expose_from_menu (event)))
        XtDispatchEvent (&event);
     }
 
+#endif /* not HAVE_MOTIF_2_1 */
+
   /* Get the result.  */
   if (result == XmCR_OK)
     {
@@ -10762,37 +10116,6 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
 
 #endif /* USE_MOTIF */
 
-\f
-/***********************************************************************
-                               Tests
- ***********************************************************************/
-
-#if GLYPH_DEBUG
-
-DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
-  "Value is non-nil if SPEC is a valid image specification.")
-  (spec)
-     Lisp_Object spec;
-{
-  return valid_image_p (spec) ? Qt : Qnil;
-}
-
-
-DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
-  (spec)
-     Lisp_Object spec;
-{
-  int id = -1;
-  
-  if (valid_image_p (spec))
-    id = lookup_image (SELECTED_FRAME (), spec);
-
-  debug_print (spec);
-  return make_number (id);
-}
-
-#endif /* GLYPH_DEBUG != 0 */
-
 
 \f
 /***********************************************************************
@@ -10874,6 +10197,10 @@ syms_of_xfns ()
   staticpro (&Qscroll_bar_background);
   Qscreen_gamma = intern ("screen-gamma");
   staticpro (&Qscreen_gamma);
+  Qline_spacing = intern ("line-spacing");
+  staticpro (&Qline_spacing);
+  Qcenter = intern ("center");
+  staticpro (&Qcenter);
   /* This is the end of symbol initialization.  */
 
   /* Text property `display' should be nonsticky by default.  */
@@ -10945,6 +10272,11 @@ or when you set the mouse color.");
     "Non-zero means Emacs displays a busy cursor on window systems.");
   display_busy_cursor_p = 1;
   
+  DEFVAR_LISP ("busy-cursor-delay", &Vbusy_cursor_delay,
+     "*Seconds to wait before displaying a busy-cursor.\n\
+Value must be an integer or float.");
+  Vbusy_cursor_delay = make_number (DEFAULT_BUSY_CURSOR_DELAY);
+
 #if 0 /* This doesn't really do anything.  */
   DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
              "The shape of the pointer when over the mode line.\n\
@@ -10989,11 +10321,6 @@ from the image cache.  Value must be an integer or nil with nil\n\
 meaning don't clear the cache.");
   Vimage_cache_eviction_delay = make_number (30 * 60);
 
-  DEFVAR_LISP ("image-types", &Vimage_types,
-     "List of supported image types.\n\
-Each element of the list is a symbol for a supported image type.");
-  Vimage_types = Qnil;
-
 #ifdef USE_X_TOOLKIT
   Fprovide (intern ("x-toolkit"));
 #endif
@@ -11008,12 +10335,6 @@ Each element of the list is a symbol for a supported image type.");
   defsubr (&Sx_delete_window_property);
   defsubr (&Sx_window_property);
 
-#if 0
-  defsubr (&Sx_draw_rectangle);
-  defsubr (&Sx_erase_rectangle);
-  defsubr (&Sx_contour_region);
-  defsubr (&Sx_uncontour_region);
-#endif
   defsubr (&Sxw_display_color_p);
   defsubr (&Sx_display_grayscale_p);
   defsubr (&Sxw_color_defined_p);
@@ -11031,22 +10352,13 @@ Each element of the list is a symbol for a supported image type.");
   defsubr (&Sx_display_visual_class);
   defsubr (&Sx_display_backing_store);
   defsubr (&Sx_display_save_under);
-#if 0
-  defsubr (&Sx_rebind_key);
-  defsubr (&Sx_rebind_keys);
-  defsubr (&Sx_track_pointer);
-  defsubr (&Sx_grab_pointer);
-  defsubr (&Sx_ungrab_pointer);
-#endif
   defsubr (&Sx_parse_geometry);
   defsubr (&Sx_create_frame);
-#if 0
-  defsubr (&Sx_horizontal_line);
-#endif
   defsubr (&Sx_open_connection);
   defsubr (&Sx_close_connection);
   defsubr (&Sx_display_list);
   defsubr (&Sx_synchronize);
+  defsubr (&Sx_focus_frame);
 
   /* Setting callback functions for fontset handler.  */
   get_font_info_func = x_get_font_info;
@@ -11073,8 +10385,6 @@ Each element of the list is a symbol for a supported image type.");
   staticpro (&QCheuristic_mask);
   QCcolor_symbols = intern (":color-symbols");
   staticpro (&QCcolor_symbols);
-  QCdata = intern (":data");
-  staticpro (&QCdata);
   QCascent = intern (":ascent");
   staticpro (&QCascent);
   QCmargin = intern (":margin");
@@ -11123,16 +10433,8 @@ Each element of the list is a symbol for a supported image type.");
 
   defsubr (&Sclear_image_cache);
 
-#if GLYPH_DEBUG
-  defsubr (&Simagep);
-  defsubr (&Slookup_image);
-#endif
-
-  /* Busy-cursor.  */
-  defsubr (&Sx_show_busy_cursor);
-  defsubr (&Sx_hide_busy_cursor);
-  busy_count = 0;
-  inhibit_busy_cursor = 0;
+  busy_cursor_atimer = NULL;
+  busy_cursor_shown_p = 0;
 
   defsubr (&Sx_show_tip);
   defsubr (&Sx_hide_tip);