(X_I18N_INHIBITED): Don't define.
[bpt/emacs.git] / src / xfns.c
index eee9b91..8ed9b7d 100644 (file)
@@ -19,16 +19,8 @@ along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-/* Image support (XBM, XPM, PBM, JPEG, TIFF, GIF, PNG, GS). tooltips,
-   tool-bars, busy-cursor, file selection dialog added by Gerd
-   Moellmann <gerd@gnu.org>.  */
-
-/* Completely rewritten by Richard Stallman.  */
-
-/* Rewritten for X11 by Joseph Arceneaux */
-
-#include <signal.h>
 #include <config.h>
+#include <signal.h>
 #include <stdio.h>
 #include <math.h>
 
@@ -41,6 +33,7 @@ Boston, MA 02111-1307, USA.  */
 #include "frame.h"
 #include "window.h"
 #include "buffer.h"
+#include "intervals.h"
 #include "dispextern.h"
 #include "keyboard.h"
 #include "blockinput.h"
@@ -49,23 +42,13 @@ Boston, MA 02111-1307, USA.  */
 #include "fontset.h"
 #include "systime.h"
 #include "termhooks.h"
+#include "atimer.h"
 
 #ifdef HAVE_X_WINDOWS
 
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#else
-extern void abort ();
-#endif
 #include <ctype.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
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #ifndef VMS
 #if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work.  */
@@ -251,7 +234,7 @@ Lisp_Object Qx_frame_parameter;
 Lisp_Object Qx_resource_name;
 Lisp_Object Quser_position;
 Lisp_Object Quser_size;
-Lisp_Object Qdisplay;
+extern Lisp_Object Qdisplay;
 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
 Lisp_Object Qscreen_gamma;
 
@@ -355,8 +338,10 @@ x_window_to_frame (dpyinfo, wdesc)
       if (!GC_FRAMEP (frame))
         continue;
       f = XFRAME (frame);
-      if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
+      if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
        continue;
+      if (f->output_data.x->busy_window == wdesc)
+       return f;
 #ifdef USE_X_TOOLKIT
       if ((f->output_data.x->edit_widget 
           && XtWindow (f->output_data.x->edit_widget) == wdesc)
@@ -384,34 +369,40 @@ x_any_window_to_frame (dpyinfo, wdesc)
      int wdesc;
 {
   Lisp_Object tail, frame;
-  struct frame *f;
+  struct frame *f, *found;
   struct x_output *x;
 
-  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
+  found = NULL;
+  for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
     {
       frame = XCAR (tail);
       if (!GC_FRAMEP (frame))
         continue;
+      
       f = XFRAME (frame);
-      if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
-       continue;
-      x = f->output_data.x;
-      /* This frame matches if the window is any of its widgets.  */
-      if (x->widget)
+      if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
        {
-         if (wdesc == XtWindow (x->widget) 
-             || wdesc == XtWindow (x->column_widget) 
-             || wdesc == XtWindow (x->edit_widget))
-           return f;
-         /* Match if the window is this frame's menubar.  */
-         if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
-           return f;
+         /* This frame matches if the window is any of its widgets.  */
+         x = f->output_data.x;
+         if (x->busy_window == wdesc)
+           found = f;
+         else if (x->widget)
+           {
+             if (wdesc == XtWindow (x->widget) 
+                 || wdesc == XtWindow (x->column_widget) 
+                 || wdesc == XtWindow (x->edit_widget))
+               found = f;
+             /* Match if the window is this frame's menubar.  */
+             else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
+               found = f;
+           }
+         else if (FRAME_X_WINDOW (f) == wdesc)
+           /* A tooltip frame.  */
+           found = f;
        }
-      else if (FRAME_X_WINDOW (f) == wdesc)
-       /* A tooltip frame.  */
-       return f;
     }
-  return 0;
+  
+  return found;
 }
 
 /* Likewise, but exclude the menu bar widget.  */
@@ -431,11 +422,13 @@ x_non_menubar_window_to_frame (dpyinfo, wdesc)
       if (!GC_FRAMEP (frame))
         continue;
       f = XFRAME (frame);
-      if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
+      if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
        continue;
       x = f->output_data.x;
       /* This frame matches if the window is any of its widgets.  */
-      if (x->widget)
+      if (x->busy_window == wdesc)
+       return f;
+      else if (x->widget)
        {
          if (wdesc == XtWindow (x->widget) 
              || wdesc == XtWindow (x->column_widget) 
@@ -466,7 +459,7 @@ x_menubar_window_to_frame (dpyinfo, wdesc)
       if (!GC_FRAMEP (frame))
         continue;
       f = XFRAME (frame);
-      if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
+      if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
        continue;
       x = f->output_data.x;
       /* Match if the window is this frame's menubar.  */
@@ -495,7 +488,7 @@ x_top_window_to_frame (dpyinfo, wdesc)
       if (!GC_FRAMEP (frame))
         continue;
       f = XFRAME (frame);
-      if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
+      if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
        continue;
       x = f->output_data.x;
 
@@ -667,7 +660,7 @@ x_create_bitmap_from_file (f, file)
   /* XReadBitmapFile won't handle magic file names.  */
   if (fd == 0)
     return -1;
-  close (fd);
+  emacs_close (fd);
 
   filename = (char *) XSTRING (found)->data;
 
@@ -745,6 +738,7 @@ struct x_frame_parm_table
   void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
 };
 
+static void x_create_im P_ ((struct frame *));
 void x_set_foreground_color 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));
@@ -1230,130 +1224,69 @@ 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
-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;
 
-  /* defined_color is responsible for coping with failures
+  /* x_defined_color is responsible for coping with failures
      by looking for a near-miss.  */
-  if (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 `screen-gamma' frame parameter of frame F.  OLD_VALUE is
    the previous value of that parameter, NEW_VALUE is the new value.  */
@@ -1532,13 +1465,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);
@@ -1690,12 +1619,16 @@ x_set_cursor_type (f, arg, oldval)
       FRAME_DESIRED_CURSOR (f) = BAR_CURSOR;
       f->output_data.x->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));
     }
+  else if (NILP (arg))
+    FRAME_DESIRED_CURSOR (f) = NO_CURSOR;
   else
     /* Treat anything unknown as "box cursor".
        It was bad to signal an error; people have trouble fixing
@@ -1910,6 +1843,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);
@@ -2513,8 +2451,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);
 
@@ -3053,6 +2989,287 @@ hack_wm_protocols (f, widget)
   UNBLOCK_INPUT;
 }
 #endif
+
+
+\f
+/* Support routines for XIC (X Input Context).  */
+
+#ifdef HAVE_X_I18N
+
+static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
+static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
+
+
+/* Supported XIM styles, ordered by preferenc.  */
+
+static XIMStyle supported_xim_styles[] =
+{
+  XIMPreeditPosition | XIMStatusArea,
+  XIMPreeditPosition | XIMStatusNothing,
+  XIMPreeditPosition | XIMStatusNone,
+  XIMPreeditNothing | XIMStatusArea,
+  XIMPreeditNothing | XIMStatusNothing,
+  XIMPreeditNothing | XIMStatusNone,
+  XIMPreeditNone | XIMStatusArea,
+  XIMPreeditNone | XIMStatusNothing,
+  XIMPreeditNone | XIMStatusNone,
+  0,
+};
+
+
+/* Create an X fontset on frame F with base font name
+   BASE_FONTNAME.. */
+
+static XFontSet
+xic_create_xfontset (f, base_fontname)
+     struct frame *f;
+     char *base_fontname;
+{
+  XFontSet xfs;
+  char **missing_list;
+  int missing_count;
+  char *def_string;
+  
+  xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
+                       base_fontname, &missing_list,
+                       &missing_count, &def_string);
+  if (missing_list)
+    XFreeStringList (missing_list);
+  
+  /* No need to free def_string. */
+  return xfs;
+}
+
+
+/* Value is the best input style, given user preferences USER (already
+   checked to be supported by Emacs), and styles supported by the
+   input method XIM.  */
+
+static XIMStyle
+best_xim_style (user, xim)
+     XIMStyles *user;
+     XIMStyles *xim;
+{
+  int i, j;
+
+  for (i = 0; i < user->count_styles; ++i)
+    for (j = 0; j < xim->count_styles; ++j)
+      if (user->supported_styles[i] == xim->supported_styles[j])
+       return user->supported_styles[i];
+
+  /* Return the default style.  */
+  return XIMPreeditNothing | XIMStatusNothing;
+}
+
+/* Create XIC for frame F. */
+
+void
+create_frame_xic (f)
+     struct frame *f;
+{
+  XIM xim;
+  XIC xic = NULL;
+  XFontSet xfs = NULL;
+  static XIMStyle xic_style;
+
+  if (FRAME_XIC (f))
+    return;
+  
+  xim = FRAME_X_XIM (f);
+  if (xim)
+    {
+      XRectangle s_area;
+      XPoint spot;
+      XVaNestedList preedit_attr;
+      XVaNestedList status_attr;
+      char *base_fontname;
+      int fontset;
+
+      s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
+      spot.x = 0; spot.y = 1;
+      /* Create X fontset. */
+      fontset = FRAME_FONTSET (f);
+      if (fontset < 0)
+       base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
+      else
+       {
+         struct fontset_info *fontsetp;
+         int len = 0;
+         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]);
+             }
+       }
+      xfs = xic_create_xfontset (f, base_fontname);
+
+      /* Determine XIC style.  */
+      if (xic_style == 0)
+       {
+         XIMStyles supported_list;
+         supported_list.count_styles = (sizeof supported_xim_styles
+                                        / sizeof supported_xim_styles[0]);
+         supported_list.supported_styles = supported_xim_styles;
+         xic_style = best_xim_style (&supported_list,
+                                     FRAME_X_XIM_STYLES (f));
+       }
+
+      preedit_attr = XVaCreateNestedList (0,
+                                         XNFontSet, xfs,
+                                         XNForeground,
+                                         FRAME_FOREGROUND_PIXEL (f),
+                                         XNBackground,
+                                         FRAME_BACKGROUND_PIXEL (f),
+                                         (xic_style & XIMPreeditPosition
+                                          ? XNSpotLocation
+                                          : NULL),
+                                         &spot,
+                                         NULL);
+      status_attr = XVaCreateNestedList (0,
+                                        XNArea,
+                                        &s_area,
+                                        XNFontSet,
+                                        xfs,
+                                        XNForeground,
+                                        FRAME_FOREGROUND_PIXEL (f),
+                                        XNBackground,
+                                        FRAME_BACKGROUND_PIXEL (f),
+                                        NULL);
+
+      xic = XCreateIC (xim,
+                      XNInputStyle, xic_style,
+                      XNClientWindow, FRAME_X_WINDOW(f),
+                      XNFocusWindow, FRAME_X_WINDOW(f),
+                      XNStatusAttributes, status_attr,
+                      XNPreeditAttributes, preedit_attr,
+                      NULL);
+      XFree (preedit_attr);
+      XFree (status_attr);
+    }
+  
+  FRAME_XIC (f) = xic;
+  FRAME_XIC_STYLE (f) = xic_style;
+  FRAME_XIC_FONTSET (f) = xfs;
+}
+
+
+/* Destroy XIC and free XIC fontset of frame F, if any. */
+
+void
+free_frame_xic (f)
+     struct frame *f;
+{
+  if (FRAME_XIC (f) == NULL)
+    return;
+  
+  XDestroyIC (FRAME_XIC (f));
+  if (FRAME_XIC_FONTSET (f))
+    XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
+
+  FRAME_XIC (f) = NULL;
+  FRAME_XIC_FONTSET (f) = NULL;
+}
+
+
+/* Place preedit area for XIC of window W's frame to specified
+   pixel position X/Y.  X and Y are relative to window W.  */
+
+void
+xic_set_preeditarea (w, x, y)
+     struct window *w;
+     int x, y;
+{
+  struct frame *f = XFRAME (w->frame);
+  XVaNestedList attr;
+  XPoint spot;
+      
+  spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
+  spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
+  attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
+  XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
+  XFree (attr);
+}
+
+
+/* Place status area for XIC in bottom right corner of frame F.. */
+
+void
+xic_set_statusarea (f)
+     struct frame *f;
+{
+  XIC xic = FRAME_XIC (f);
+  XVaNestedList attr;
+  XRectangle area;
+  XRectangle *needed;
+
+  /* Negotiate geometry of status area.  If input method has existing
+     status area, use its current size.  */
+  area.x = area.y = area.width = area.height = 0;
+  attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
+  XSetICValues (xic, XNStatusAttributes, attr, NULL);
+  XFree (attr);
+  
+  attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
+  XGetICValues (xic, XNStatusAttributes, attr, NULL);
+  XFree (attr);
+
+  if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
+    {
+      attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
+      XGetICValues (xic, XNStatusAttributes, attr, NULL);
+      XFree (attr);
+    }
+
+  area.width  = needed->width;
+  area.height = needed->height;
+  area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
+  area.y = (PIXEL_HEIGHT (f) - area.height
+           - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f));
+  XFree (needed);
+
+  attr = XVaCreateNestedList (0, XNArea, &area, NULL);
+  XSetICValues(xic, XNStatusAttributes, attr, NULL);
+  XFree (attr);
+}
+
+
+/* Set X fontset for XIC of frame F, using base font name
+   BASE_FONTNAME.  Called when a new Emacs fontset is chosen.  */
+
+void
+xic_set_xfontset (f, base_fontname)
+     struct frame *f;
+     char *base_fontname;
+{
+  XVaNestedList attr;
+  XFontSet xfs;
+
+  xfs = xic_create_xfontset (f, base_fontname);
+
+  attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
+  if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
+    XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
+  if (FRAME_XIC_STYLE (f) & XIMStatusArea)
+    XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
+  XFree (attr);
+  
+  if (FRAME_XIC_FONTSET (f))
+    XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
+  FRAME_XIC_FONTSET (f) = xfs;
+}
+
+#endif /* HAVE_X_I18N */
+
+
 \f
 #ifdef USE_X_TOOLKIT
 
@@ -3067,7 +3284,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;
@@ -3093,6 +3309,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);
@@ -3105,8 +3324,14 @@ x_window (f, window_prompting, minibuffer_only)
                                  shell_widget, False,
                                  (lw_callback) NULL,
                                  (lw_callback) NULL,
+                                 (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 
@@ -3118,9 +3343,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;
  
@@ -3210,35 +3437,9 @@ x_window (f, window_prompting, minibuffer_only)
   XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
 
 #ifdef HAVE_X_I18N
-#ifndef X_I18N_INHIBITED
-  { 
-    XIM xim;
-    XIC xic = NULL;
-
-    xim = XOpenIM (FRAME_X_DISPLAY (f), NULL, NULL, NULL);
-
-    if (xim)
-      {
-       xic = XCreateIC (xim,  
-                        XNInputStyle,   XIMPreeditNothing | XIMStatusNothing,
-                        XNClientWindow, FRAME_X_WINDOW(f),
-                        XNFocusWindow,  FRAME_X_WINDOW(f),
-                        NULL);
-
-       if (xic == 0)
-         {
-           XCloseIM (xim);
-           xim = NULL;
-         }
-      }
-    FRAME_XIM (f) = xim;
-    FRAME_XIC (f) = xic;
-  }
-#else /* X_I18N_INHIBITED */
-  FRAME_XIM (f) = 0;
-  FRAME_XIC (f) = 0;
-#endif /* X_I18N_INHIBITED */
-#endif /* HAVE_X_I18N */
+  FRAME_XIC (f) = NULL;
+  create_frame_xic (f);
+#endif
 
   f->output_data.x->wm_hints.input = True;
   f->output_data.x->wm_hints.flags |= InputHint;
@@ -3260,8 +3461,19 @@ x_window (f, window_prompting, minibuffer_only)
                   XA_ATOM, 32, PropModeAppend,
                   (unsigned char*) NULL, 0);
 
- /* Make all the standard events reach the Emacs frame.  */
 /* Make all the standard events reach the Emacs frame.  */
   attributes.event_mask = STANDARD_EVENT_SET;
+
+#ifdef HAVE_X_I18N
+  if (FRAME_XIC (f))
+    {
+      /* XIM server might require some X events. */
+      unsigned long fevent = NoEventMask;
+      XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
+      attributes.event_mask |= fevent;
+    }
+#endif /* HAVE_X_I18N */
+  
   attribute_mask = CWEventMask;
   XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
                           attribute_mask, &attributes);
@@ -3311,11 +3523,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)
@@ -3327,40 +3537,23 @@ 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
-#ifndef X_I18N_INHIBITED
-  { 
-    XIM xim;
-    XIC xic = NULL;
 
-    xim = XOpenIM (FRAME_X_DISPLAY(f), NULL, NULL, NULL);
-
-    if (xim)
-      {
-       xic = XCreateIC (xim,  
-                        XNInputStyle,   XIMPreeditNothing | XIMStatusNothing,
-                        XNClientWindow, FRAME_X_WINDOW(f),
-                        XNFocusWindow,  FRAME_X_WINDOW(f),
-                        NULL);
-
-       if (!xic)
-         {
-           XCloseIM (xim);
-           xim = NULL;
-         }
-      }
-
-    FRAME_XIM (f) = xim;
-    FRAME_XIC (f) = xic;
-  }
-#else /* X_I18N_INHIBITED */
-  FRAME_XIM (f) = 0;
-  FRAME_XIC (f) = 0;
-#endif /* X_I18N_INHIBITED */
+#ifdef HAVE_X_I18N
+  create_frame_xic (f);
+  if (FRAME_XIC (f))
+    {
+      /* XIM server might require some X events. */
+      unsigned long fevent = NoEventMask;
+      XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
+      attributes.event_mask |= fevent;
+      attribute_mask = CWEventMask;
+      XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                              attribute_mask, &attributes);
+    }
 #endif /* HAVE_X_I18N */
-
+  
   validate_x_resource_name ();
 
   class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
@@ -3636,6 +3829,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))
@@ -3741,7 +3957,7 @@ This function is an internal primitive--use `make-frame' instead.")
   x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
                       "foreground", "Foreground", RES_TYPE_STRING);
   x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
-                          "background", "Background", RES_TYPE_STRING);
+                      "background", "Background", RES_TYPE_STRING);
   x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
                       "pointerColor", "Foreground", RES_TYPE_STRING);
   x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
@@ -3770,9 +3986,6 @@ This function is an internal primitive--use `make-frame' instead.")
                       "menuBar", "MenuBar", RES_TYPE_NUMBER);
   x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
                       "toolBar", "ToolBar", RES_TYPE_NUMBER);
-  x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
-                      "scrollBarWidth", "ScrollBarWidth",
-                      RES_TYPE_NUMBER);
   x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
                       "bufferPredicate", "BufferPredicate",
                       RES_TYPE_SYMBOL);
@@ -3834,6 +4047,9 @@ This function is an internal primitive--use `make-frame' instead.")
                       "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
   x_default_parameter (f, parms, Qcursor_type, Qbox,
                       "cursorType", "CursorType", RES_TYPE_SYMBOL);
+  x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
+                      "scrollBarWidth", "ScrollBarWidth",
+                      RES_TYPE_NUMBER);
 
   /* Dimensions, especially f->height, must be done via change_frame_size.
      Change will not be effected unless different from the current
@@ -3912,10 +4128,39 @@ 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 ("x-color-defined-p", Fx_color_defined_p, Sx_color_defined_p, 1, 2, 0,
-       "Return non-nil if color COLOR is supported on frame FRAME.\n\
-If FRAME is omitted or nil, use the selected frame.")
+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.")
   (color, frame)
      Lisp_Object color, frame;
 {
@@ -3924,18 +4169,14 @@ If FRAME is omitted or nil, use the selected frame.")
 
   CHECK_STRING (color, 1);
 
-  if (defined_color (f, XSTRING (color)->data, &foo, 0))
+  if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
     return Qt;
   else
     return Qnil;
 }
 
-DEFUN ("x-color-values", Fx_color_values, Sx_color_values, 1, 2, 0,
-  "Return a description of the color named COLOR on frame FRAME.\n\
-The value is a list of integer RGB values--(RED GREEN BLUE).\n\
-These values appear to range from 0 to 65280 or 65535, depending\n\
-on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
-If FRAME is omitted or nil, use the selected frame.")
+DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
+  "Internal function called by `color-values', which see.")
   (color, frame)
      Lisp_Object color, frame;
 {
@@ -3944,7 +4185,7 @@ If FRAME is omitted or nil, use the selected frame.")
 
   CHECK_STRING (color, 1);
 
-  if (defined_color (f, XSTRING (color)->data, &foo, 0))
+  if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
     {
       Lisp_Object rgb[3];
 
@@ -3957,11 +4198,8 @@ If FRAME is omitted or nil, use the selected frame.")
     return Qnil;
 }
 
-DEFUN ("x-display-color-p", Fx_display_color_p, Sx_display_color_p, 0, 1, 0,
-  "Return t if the X display supports color.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
+DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
+  "Internal function called by `display-color-p', which see.")
   (display)
      Lisp_Object display;
 {
@@ -4263,980 +4501,146 @@ 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.  */
 
-/* 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.  */
 
-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;
-{
-  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;
+\f
+/************************************************************************
+                             X Displays
+ ************************************************************************/
 
-  XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 gc, left, top, width, height);
-}
+\f
+/* Mapping visual names to visuals.  */
 
-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;
+static struct visual_class
+{
+  char *name;
+  int class;
+}
+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;
-    }
-
-  if (x1 > x0)
-    {
-      left = x0;
-      n_chars = x1 - x0 + 1;
-    }
-  else
-    {
-      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.  */
-
-#define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
-
-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;
-    }
-  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));
-
-  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;
-
-  XDrawLines (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-             gc, pixel_points,
-             (this_point - pixel_points + 1), CoordModeOrigin);
-}
-
-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);
-
-  BLOCK_INPUT;
-  x0 = XINT (Fcar (Fcar (event)));
-  y0 = XINT (Fcar (Fcdr (Fcar (event))));
-
-  /* If the mouse is past the end of the line, don't that area.  */
-  /* ReWrite this...  */
-
-  /* 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 (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 */
-    {
-      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);
-    }
-
-  XFlush (FRAME_X_DISPLAY (f));
-  UNBLOCK_INPUT;
-
-  return Qnil;
-}
-
-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));
-
-  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;
-
-  return Qnil;
-}
-
-#if 0
-int contour_begin_x, contour_begin_y;
-int contour_end_x, contour_end_y;
-int contour_npoints;
-
-/* 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)
-{
-  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];
-
-  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);
-
-      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);
-
-      /* 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);
-
-      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;
+void
+select_visual (dpyinfo)
+     struct x_display_info *dpyinfo;
 {
-  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
+  Display *dpy = dpyinfo->display;
+  Screen *screen = dpyinfo->screen;
+  Lisp_Object value;
 
-  while (1)
+  /* See if a visual is specified.  */
+  value = display_x_get_resource (dpyinfo,
+                                 build_string ("visualClass"),
+                                 build_string ("VisualClass"),
+                                 Qnil, Qnil);
+  if (STRINGP (value))
     {
-      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
+      /* 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)
        {
-         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;
-           }
+         dpyinfo->n_planes = atoi (dash + 1);
+         *dash = '\0';
        }
-      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;
+      else
+       /* We won't find a matching visual with depth 0, so that
+          an error will be printed below.  */
+       dpyinfo->n_planes = 0;
 
-  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])
+      /* 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;
+         }
 
-         /* 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);
-       }
+      /* 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;
     }
-  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);
+      int n_visuals;
+      XVisualInfo *vinfo, vinfo_template;
+      
+      dpyinfo->visual = DefaultVisualOfScreen (screen);
 
 #ifdef HAVE_X11R4
-  vinfo_template.visualid = XVisualIDFromVisual (v);
+      vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
 #else
-  vinfo_template.visualid = v->visualid;
+      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");
-
-  if ((1 << vinfo->depth) == vinfo->colormap_size)
-    *depth = vinfo->depth;
-  else
-    {
-      int i = 0;
-      int n = vinfo->colormap_size - 1;
-      while (n)
+      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)
+       dpyinfo->n_planes = vinfo->depth;
+      else
        {
-         n = n >> 1;
-         i++;
+         int i = 0;
+         int n = vinfo->colormap_size - 1;
+         while (n)
+           {
+             n = n >> 1;
+             i++;
+           }
+         dpyinfo->n_planes = i;
        }
-      *depth = i;
-    }
 
-  XFree ((char *) vinfo);
-  return v;
+      XFree ((char *) vinfo);
+    }
 }
 
+
 /* Return the X display structure for the display named NAME.
    Open a new connection if necessary.  */
 
@@ -5279,6 +4683,7 @@ x_display_info_for_name (name)
   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\
@@ -5440,8 +4845,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;
 
@@ -5460,8 +4866,8 @@ static void define_image_type P_ ((struct image_type *type));
 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
 static void x_laplace P_ ((struct frame *, struct image *));
-static int x_build_heuristic_mask P_ ((struct frame *, Lisp_Object,
-                                      struct image *, Lisp_Object));
+static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
+                                      Lisp_Object));
 
 
 /* Define a new image type from TYPE.  This adds a copy of TYPE to
@@ -5578,10 +4984,8 @@ struct image_keyword
 };
 
 
-static int parse_image_spec P_ ((Lisp_Object spec,
-                                struct image_keyword *keywords,
-                                int nkeywords, Lisp_Object type,
-                                int allow_other_keys_p));
+static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
+                                int, Lisp_Object));
 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
 
 
@@ -5589,17 +4993,14 @@ static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
    has the format (image KEYWORD VALUE ...).  One of the keyword/
    value pairs must be `:type TYPE'.  KEYWORDS is a vector of
    image_keywords structures of size NKEYWORDS describing other
-   allowed keyword/value pairs.  ALLOW_OTHER_KEYS_P non-zero means
-   allow KEYWORD/VALUE pairs other than those described by KEYWORDS
-   without checking them.  Value is non-zero if SPEC is valid.  */
+   allowed keyword/value pairs.  Value is non-zero if SPEC is valid.  */
 
 static int
-parse_image_spec (spec, keywords, nkeywords, type, allow_other_keys_p)
+parse_image_spec (spec, keywords, nkeywords, type)
      Lisp_Object spec;
      struct image_keyword *keywords;
      int nkeywords;
      Lisp_Object type;
-     int allow_other_keys_p;
 {
   int i;
   Lisp_Object plist;
@@ -5630,11 +5031,7 @@ parse_image_spec (spec, keywords, nkeywords, type, allow_other_keys_p)
          break;
 
       if (i == nkeywords)
-       {
-         if (!allow_other_keys_p)
-           return 0;
-         continue;
-       }
+       continue;
 
       /* Record that we recognized the keyword.  If a keywords
         was found more than once, it's an error.  */
@@ -5852,21 +5249,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;
@@ -5892,7 +5277,7 @@ x_alloc_image_color (f, img, color_name, dflt)
 
   xassert (STRINGP (color_name));
 
-  if (defined_color (f, XSTRING (color_name)->data, &color, 1))
+  if (x_defined_color (f, XSTRING (color_name)->data, &color, 1))
     {
       /* This isn't called frequently so we get away with simply
         reallocating the color vector to the needed size, here.  */
@@ -6115,10 +5500,7 @@ lookup_image (f, spec)
          /* Should we built a mask heuristically?  */
          heuristic_mask = image_spec_value (spec, QCheuristic_mask, NULL);
          if (img->pixmap && !img->mask && !NILP (heuristic_mask))
-           {
-             file = image_spec_value (spec, QCfile, NULL);
-             x_build_heuristic_mask (f, file, img, heuristic_mask);
-           }
+           x_build_heuristic_mask (f, img, heuristic_mask);
        }
     }
 
@@ -6199,9 +5581,8 @@ forall_images_in_image_cache (f, fn)
                            X support code
  ***********************************************************************/
 
-static int x_create_x_image_and_pixmap P_ ((struct frame *, Lisp_Object,
-                                           int, int, int, XImage **,
-                                           Pixmap *));
+static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
+                                           XImage **, Pixmap *));
 static void x_destroy_x_image P_ ((XImage *));
 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
 
@@ -6210,13 +5591,11 @@ static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
    frame F.  Set *XIMG and *PIXMAP to the XImage and Pixmap created.
    Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
    via xmalloc.  Print error messages via image_error if an error
-   occurs.  FILE is the name of an image file being processed, for
-   error messages.  Value is non-zero if successful.  */
+   occurs.  Value is non-zero if successful.  */
 
 static int
-x_create_x_image_and_pixmap (f, file, width, height, depth, ximg, pixmap)
+x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
      struct frame *f;
-     Lisp_Object file;
      int width, height, depth;
      XImage **ximg;
      Pixmap *pixmap;
@@ -6234,7 +5613,7 @@ x_create_x_image_and_pixmap (f, file, width, height, depth, ximg, pixmap)
                        depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
   if (*ximg == NULL)
     {
-      image_error ("Unable to allocate X image for %s", file, Qnil);
+      image_error ("Unable to allocate X image", Qnil, Qnil);
       return 0;
     }
 
@@ -6247,7 +5626,7 @@ x_create_x_image_and_pixmap (f, file, width, height, depth, ximg, pixmap)
     {
       x_destroy_x_image (*ximg);
       *ximg = NULL;
-      image_error ("Unable to create pixmap for `%s'", file, Qnil);
+      image_error ("Unable to create X pixmap", Qnil, Qnil);
       return 0;
     }
 
@@ -6428,7 +5807,7 @@ xbm_image_p (object)
   struct image_keyword kw[XBM_LAST];
   
   bcopy (xbm_format, kw, sizeof kw);
-  if (!parse_image_spec (object, kw, XBM_LAST, Qxbm, 0))
+  if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
     return 0;
 
   xassert (EQ (kw[XBM_TYPE].value, Qxbm));
@@ -6762,7 +6141,7 @@ xbm_load_image_from_file (f, img, specified_file)
   file = x_find_image_file (specified_file);
   if (!STRINGP (file))
     {
-      image_error ("Cannot find image file %s", specified_file, Qnil);
+      image_error ("Cannot find image file `%s'", specified_file, Qnil);
       UNGCPRO;
       return 0;
     }
@@ -6808,7 +6187,7 @@ xbm_load_image_from_file (f, img, specified_file)
       UNBLOCK_INPUT;
     }
   else
-    image_error ("Error loading XBM image %s", img->spec, Qnil);
+    image_error ("Error loading XBM image `%s'", img->spec, Qnil);
 
   UNGCPRO;
   return success_p;
@@ -6844,7 +6223,7 @@ xbm_load (f, img)
 
       /* Parse the list specification.  */
       bcopy (xbm_format, fmt, sizeof fmt);
-      parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm, 0);
+      parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
       xassert (parsed_p);
 
       /* Get specified width, and height.  */
@@ -6901,7 +6280,8 @@ xbm_load (f, img)
        success_p = 1;
       else
        {
-         image_error ("Unable to create pixmap for XBM image", Qnil, Qnil);
+         image_error ("Unable to create pixmap for XBM image `%s'",
+                      img->spec, Qnil);
          x_clear_image (f, img);
        }
 
@@ -7003,7 +6383,7 @@ xpm_image_p (object)
 {
   struct image_keyword fmt[XPM_LAST];
   bcopy (xpm_format, fmt, sizeof fmt);
-  return (parse_image_spec (object, fmt, XPM_LAST, Qxpm, 0)
+  return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
          /* Either `:file' or `:data' must be present.  */
          && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
          /* Either no `:color-symbols' or it's a list of conses
@@ -7030,8 +6410,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;
@@ -7086,7 +6468,7 @@ xpm_load (f, img)
       Lisp_Object file = x_find_image_file (specified_file);
       if (!STRINGP (file))
        {
-         image_error ("Cannot find image file %s", specified_file, Qnil);
+         image_error ("Cannot find image file `%s'", specified_file, Qnil);
          UNBLOCK_INPUT;
          return 0;
        }
@@ -7256,7 +6638,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;
 
@@ -7303,7 +6685,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);
@@ -7421,7 +6803,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;
@@ -7443,7 +6825,7 @@ x_laplace (f, img)
   out = (long *) alloca (img->width * sizeof (long));
 
   /* Create an X image for output.  */
-  rc = x_create_x_image_and_pixmap (f, Qnil, img->width, img->height, 0,
+  rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0,
                                    &oimg, &pixmap);
 
   /* Fill first two rows.  */
@@ -7509,9 +6891,8 @@ x_laplace (f, img)
    heuristically.  Value is non-zero if successful. */
 
 static int
-x_build_heuristic_mask (f, file, img, how)
+x_build_heuristic_mask (f, img, how)
      struct frame *f;
-     Lisp_Object file;
      struct image *img;
      Lisp_Object how;
 {
@@ -7523,7 +6904,7 @@ x_build_heuristic_mask (f, file, img, how)
   BLOCK_INPUT;
   
   /* Create an image and pixmap serving as mask.  */
-  rc = x_create_x_image_and_pixmap (f, file, img->width, img->height, 1,
+  rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
                                    &mask_img, &img->mask);
   if (!rc)
     {
@@ -7560,7 +6941,7 @@ x_build_heuristic_mask (f, file, 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;
@@ -7617,7 +6998,7 @@ x_build_heuristic_mask (f, file, img, how)
 
 static int pbm_image_p P_ ((Lisp_Object object));
 static int pbm_load P_ ((struct frame *f, struct image *img));
-static int pbm_scan_number P_ ((FILE *fp));
+static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
 
 /* The symbol `pbm' identifying images of this type.  */
 
@@ -7629,6 +7010,7 @@ enum pbm_keyword_index
 {
   PBM_TYPE,
   PBM_FILE,
+  PBM_DATA,
   PBM_ASCENT,
   PBM_MARGIN,
   PBM_RELIEF,
@@ -7643,7 +7025,8 @@ enum pbm_keyword_index
 static struct image_keyword pbm_format[PBM_LAST] =
 {
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
-  {":file",            IMAGE_STRING_VALUE,                     1},
+  {":file",            IMAGE_STRING_VALUE,                     0},
+  {":data",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
@@ -7673,40 +7056,43 @@ pbm_image_p (object)
   
   bcopy (pbm_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm, 0)
+  if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
       || (fmt[PBM_ASCENT].count 
          && XFASTINT (fmt[PBM_ASCENT].value) > 100))
     return 0;
-  return 1;
+
+  /* Must specify either :data or :file.  */
+  return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
 }
 
 
-/* Scan a decimal number from PBM input file FP and return it.  Value
-   is -1 at end of file or if an error occurs.  */
+/* Scan a decimal number from *S and return it.  Advance *S while
+   reading the number.  END is the end of the string.  Value is -1 at
+   end of input.  */
 
 static int
-pbm_scan_number (fp)
-     FILE *fp;
+pbm_scan_number (s, end)
+     unsigned char **s, *end;
 {
   int c, val = -1;
 
-  while (!feof (fp))
+  while (*s < end)
     {
       /* Skip white-space.  */
-      while ((c = fgetc (fp)) != EOF && isspace (c))
+      while (*s < end && (c = *(*s)++, isspace (c)))
        ;
 
       if (c == '#')
        {
          /* Skip comment to end of line.  */
-         while ((c = fgetc (fp)) != EOF && c != '\n')
+         while (*s < end && (c = *(*s)++, c != '\n'))
            ;
        }
       else if (isdigit (c))
        {
          /* Read decimal number.  */
          val = c - '0';
-         while ((c = fgetc (fp)) != EOF && isdigit (c))
+         while (*s < end && (c = *(*s)++, isdigit (c)))
            val = 10 * val + c - '0';
          break;
        }
@@ -7718,6 +7104,42 @@ pbm_scan_number (fp)
 }
 
 
+/* 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 
@@ -7725,50 +7147,60 @@ pbm_load (f, img)
      struct frame *f;
      struct image *img;
 {
-  FILE *fp;
-  char magic[2];
   int raw_p, x, y;
   int width, height, max_color_idx = 0;
   XImage *ximg;
   Lisp_Object file, specified_file;
   enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
   struct gcpro gcpro1;
+  unsigned char *contents = NULL;
+  unsigned char *end, *p;
+  int size;
 
   specified_file = image_spec_value (img->spec, QCfile, NULL);
-  file = x_find_image_file (specified_file);
+  file = Qnil;
   GCPRO1 (file);
-  if (!STRINGP (file))
-    {
-      image_error ("Cannot find image file %s", specified_file, Qnil);
-      UNGCPRO;
-      return 0;
-    }
 
-  fp = fopen (XSTRING (file)->data, "r");
-  if (fp == NULL)
+  if (STRINGP (specified_file))
     {
-      UNGCPRO;
-      return 0;
-    }
+      file = x_find_image_file (specified_file);
+      if (!STRINGP (file))
+       {
+         image_error ("Cannot find image file `%s'", specified_file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
 
-  /* Read first two characters.  */
-  if (fread (magic, sizeof *magic, 2, fp) != 2)
+      contents = pbm_read_file (file, &size);
+      if (contents == NULL)
+       {
+         image_error ("Error reading `%s'", file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
+
+      p = contents;
+      end = contents + size;
+    }
+  else
     {
-      fclose (fp);
-      image_error ("Not a PBM image file: %s", file, Qnil);
-      UNGCPRO;
-      return 0;
+      Lisp_Object data;
+      data = image_spec_value (img->spec, QCdata, NULL);
+      p = XSTRING (data)->data;
+      end = p + STRING_BYTES (XSTRING (data));
     }
 
-  if (*magic != 'P')
+  /* Check magic number.  */
+  if (end - p < 2 || *p++ != 'P')
     {
-      fclose (fp);
-      image_error ("Not a PBM image file: %s", file, Qnil);
+      image_error ("Not a PBM image: `%s'", img->spec, Qnil);
+    error:
+      xfree (contents);
       UNGCPRO;
       return 0;
     }
 
-  switch (magic[1])
+  switch (*p++)
     {
     case '1':
       raw_p = 0, type = PBM_MONO;
@@ -7795,40 +7227,33 @@ pbm_load (f, img)
       break;
 
     default:
-      fclose (fp);
-      image_error ("Not a PBM image file: %s", file, Qnil);
-      UNGCPRO;
-      return 0;
+      image_error ("Not a PBM image: `%s'", img->spec, Qnil);
+      goto error;
     }
 
   /* Read width, height, maximum color-component.  Characters
      starting with `#' up to the end of a line are ignored.  */
-  width = pbm_scan_number (fp);
-  height = pbm_scan_number (fp);
+  width = pbm_scan_number (&p, end);
+  height = pbm_scan_number (&p, end);
 
   if (type != PBM_MONO)
     {
-      max_color_idx = pbm_scan_number (fp);
+      max_color_idx = pbm_scan_number (&p, end);
       if (raw_p && max_color_idx > 255)
        max_color_idx = 255;
     }
   
-  if (width < 0 || height < 0
+  if (width < 0
+      || height < 0
       || (type != PBM_MONO && max_color_idx < 0))
-    {
-      fclose (fp);
-      UNGCPRO;
-      return 0;
-    }
+    goto error;
 
   BLOCK_INPUT;
-  if (!x_create_x_image_and_pixmap (f, file, width, height, 0,
+  if (!x_create_x_image_and_pixmap (f, width, height, 0,
                                    &ximg, &img->pixmap))
     {
-      fclose (fp);
       UNBLOCK_INPUT;
-      UNGCPRO;
-      return 0;
+      goto error;
     }
   
   /* Initialize the color hash table.  */
@@ -7844,12 +7269,12 @@ pbm_load (f, img)
            if (raw_p)
              {
                if ((x & 7) == 0)
-                 c = fgetc (fp);
+                 c = *p++;
                g = c & 0x80;
                c <<= 1;
              }
            else
-             g = pbm_scan_number (fp);
+             g = pbm_scan_number (&p, end);
 
            XPutPixel (ximg, x, y, (g
                                    ? FRAME_FOREGROUND_PIXEL (f)
@@ -7864,31 +7289,29 @@ pbm_load (f, img)
            int r, g, b;
            
            if (type == PBM_GRAY)
-             r = g = b = raw_p ? fgetc (fp) : pbm_scan_number (fp);
+             r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
            else if (raw_p)
              {
-               r = fgetc (fp);
-               g = fgetc (fp);
-               b = fgetc (fp);
+               r = *p++;
+               g = *p++;
+               b = *p++;
              }
            else
              {
-               r = pbm_scan_number (fp);
-               g = pbm_scan_number (fp);
-               b = pbm_scan_number (fp);
+               r = pbm_scan_number (&p, end);
+               g = pbm_scan_number (&p, end);
+               b = pbm_scan_number (&p, end);
              }
            
            if (r < 0 || g < 0 || b < 0)
              {
-               fclose (fp);
                xfree (ximg->data);
                ximg->data = NULL;
                XDestroyImage (ximg);
                UNBLOCK_INPUT;
-               image_error ("Invalid pixel value in file `%s'",
-                            file, Qnil);
-               UNGCPRO;
-               return 0;
+               image_error ("Invalid pixel value in image `%s'",
+                            img->spec, Qnil);
+               goto error;
              }
            
            /* RGB values are now in the range 0..max_color_idx.
@@ -7900,8 +7323,6 @@ pbm_load (f, img)
          }
     }
   
-  fclose (fp);
-
   /* Store in IMG->colors the colors allocated for the image, and
      free the color table.  */
   img->colors = colors_in_color_table (&img->ncolors);
@@ -7916,6 +7337,7 @@ pbm_load (f, img)
   img->height = height;
 
   UNGCPRO;
+  xfree (contents);
   return 1;
 }
 
@@ -7943,6 +7365,7 @@ Lisp_Object Qpng;
 enum png_keyword_index
 {
   PNG_TYPE,
+  PNG_DATA,
   PNG_FILE,
   PNG_ASCENT,
   PNG_MARGIN,
@@ -7958,7 +7381,8 @@ enum png_keyword_index
 static struct image_keyword png_format[PNG_LAST] =
 {
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
-  {":file",            IMAGE_STRING_VALUE,                     1},
+  {":data",            IMAGE_STRING_VALUE,                     0},
+  {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
@@ -7987,11 +7411,13 @@ 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, 1)
+  if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
       || (fmt[PNG_ASCENT].count 
          && XFASTINT (fmt[PNG_ASCENT].value) > 100))
     return 0;
-  return 1;
+
+  /* Must specify either the :data or :file keyword.  */
+  return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
 }
 
 
@@ -8018,6 +7444,35 @@ my_png_warning (png_ptr, msg)
   image_error ("PNG warning: %s", build_string (msg), Qnil);
 }
 
+/* Memory source for PNG decoding.  */
+
+struct png_memory_storage
+{
+  unsigned char *bytes;                /* The data       */
+  size_t len;                  /* How big is it? */
+  int index;                   /* Where are we?  */
+};
+
+
+/* Function set as reader function when reading PNG image from memory.
+   PNG_PTR is a pointer to the PNG control structure.  Copy LENGTH
+   bytes from the input to DATA.  */
+
+static void
+png_read_from_memory (png_ptr, data, length)
+     png_structp png_ptr;
+     png_bytep data;
+     png_size_t length;
+{
+  struct png_memory_storage *tbr
+    = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
+
+  if (length > tbr->len - tbr->index)
+    png_error (png_ptr, "Read error");
+  
+  bcopy (tbr->bytes + tbr->index, data, length);
+  tbr->index = tbr->index + length;
+}
 
 /* Load PNG image IMG for use on frame F.  Value is non-zero if
    successful.  */
@@ -8028,12 +7483,13 @@ png_load (f, img)
      struct image *img;
 {
   Lisp_Object file, specified_file;
+  Lisp_Object specified_data;
   int x, y, i;
   XImage *ximg, *mask_img = NULL;
   struct gcpro gcpro1;
   png_struct *png_ptr = NULL;
   png_info *info_ptr = NULL, *end_info = NULL;
-  FILE *fp;
+  FILE *fp = NULL;
   png_byte sig[8];
   png_byte *pixels = NULL;
   png_byte **rows = NULL;
@@ -8045,36 +7501,62 @@ png_load (f, img)
   char *gamma_str;
   double screen_gamma, image_gamma;
   int intent;
+  struct png_memory_storage tbr;  /* Data to be read */
 
   /* Find out what file to load.  */
   specified_file = image_spec_value (img->spec, QCfile, NULL);
-  file = x_find_image_file (specified_file);
+  specified_data = image_spec_value (img->spec, QCdata, NULL);
+  file = Qnil;
   GCPRO1 (file);
-  if (!STRINGP (file))
-    {
-      image_error ("Cannot find image file %s", specified_file, Qnil);
-      UNGCPRO;
-      return 0;
-    }
 
-  /* Open the image file.  */
-  fp = fopen (XSTRING (file)->data, "rb");
-  if (!fp)
+  if (NILP (specified_data))
     {
-      image_error ("Cannot open image file %s", file, Qnil);
-      UNGCPRO;
-      fclose (fp);
-      return 0;
-    }
+      file = x_find_image_file (specified_file);
+      if (!STRINGP (file))
+       {
+         image_error ("Cannot find image file `%s'", specified_file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
 
-  /* Check PNG signature.  */
-  if (fread (sig, 1, sizeof sig, fp) != sizeof sig
-      || !png_check_sig (sig, sizeof sig))
+      /* Open the image file.  */
+      fp = fopen (XSTRING (file)->data, "rb");
+      if (!fp)
+       {
+         image_error ("Cannot open image file `%s'", file, Qnil);
+         UNGCPRO;
+         fclose (fp);
+         return 0;
+       }
+
+      /* Check PNG signature.  */
+      if (fread (sig, 1, sizeof sig, fp) != sizeof sig
+         || !png_check_sig (sig, sizeof sig))
+       {
+         image_error ("Not a PNG file: `%s'", file, Qnil);
+         UNGCPRO;
+         fclose (fp);
+         return 0;
+       }
+    }
+  else
     {
-      image_error ("Not a PNG file: %s", file, Qnil);
-      UNGCPRO;
-      fclose (fp);
-      return 0;
+      /* Read from memory.  */
+      tbr.bytes = XSTRING (specified_data)->data;
+      tbr.len = STRING_BYTES (XSTRING (specified_data));
+      tbr.index = 0;
+
+      /* Check PNG signature.  */
+      if (tbr.len < sizeof sig
+         || !png_check_sig (tbr.bytes, sizeof sig))
+       {
+         image_error ("Not a PNG image: `%s'", img->spec, Qnil);
+         UNGCPRO;
+         return 0;
+       }
+
+      /* Need to skip past the signature.  */
+      tbr.bytes += sizeof (sig);
     }
 
   /* Initialize read and info structs for PNG lib.  */
@@ -8082,7 +7564,7 @@ png_load (f, img)
                                    my_png_error, my_png_warning);
   if (!png_ptr)
     {
-      fclose (fp);
+      if (fp) fclose (fp);
       UNGCPRO;
       return 0;
     }
@@ -8091,7 +7573,7 @@ png_load (f, img)
   if (!info_ptr)
     {
       png_destroy_read_struct (&png_ptr, NULL, NULL);
-      fclose (fp);
+      if (fp) fclose (fp);
       UNGCPRO;
       return 0;
     }
@@ -8100,7 +7582,7 @@ png_load (f, img)
   if (!end_info)
     {
       png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
-      fclose (fp);
+      if (fp) fclose (fp);
       UNGCPRO;
       return 0;
     }
@@ -8114,14 +7596,17 @@ png_load (f, img)
         png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
       xfree (pixels);
       xfree (rows);
-      if (fp)
-       fclose (fp);
+      if (fp) fclose (fp);
       UNGCPRO;
       return 0;
     }
 
   /* Read image info.  */
-  png_init_io (png_ptr, fp);
+  if (!NILP (specified_data))
+    png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
+  else
+    png_init_io (png_ptr, fp);
+
   png_set_sig_bytes (png_ptr, sizeof sig);
   png_read_info (png_ptr, info_ptr);
   png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
@@ -8157,10 +7642,13 @@ png_load (f, img)
 
   /* Tell the PNG lib to handle gamma correction for us.  */
 
+#if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
   if (png_get_sRGB (png_ptr, info_ptr, &intent))
     /* There is a special chunk in the image specifying the gamma.  */
     png_set_sRGB (png_ptr, info_ptr, intent);
-  else if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
+  else
+#endif
+  if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
     /* Image contains gamma information.  */
     png_set_gamma (png_ptr, screen_gamma, image_gamma);
   else
@@ -8189,7 +7677,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;
@@ -8227,13 +7715,16 @@ png_load (f, img)
   /* Read the entire image.  */
   png_read_image (png_ptr, rows);
   png_read_end (png_ptr, info_ptr);
-  fclose (fp);
-  fp = NULL;
+  if (fp)
+    {
+      fclose (fp);
+      fp = NULL;
+    }
   
   BLOCK_INPUT;
 
   /* Create the X image and pixmap.  */
-  if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg,
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
                                    &img->pixmap))
     {
       UNBLOCK_INPUT;
@@ -8244,7 +7735,7 @@ png_load (f, img)
      contains an alpha channel.  */
   if (channels == 4
       && !transparent_p
-      && !x_create_x_image_and_pixmap (f, file, width, height, 1,
+      && !x_create_x_image_and_pixmap (f, width, height, 1,
                                       &mask_img, &img->mask))
     {
       x_destroy_x_image (ximg);
@@ -8360,6 +7851,7 @@ Lisp_Object Qjpeg;
 enum jpeg_keyword_index
 {
   JPEG_TYPE,
+  JPEG_DATA,
   JPEG_FILE,
   JPEG_ASCENT,
   JPEG_MARGIN,
@@ -8375,7 +7867,8 @@ enum jpeg_keyword_index
 static struct image_keyword jpeg_format[JPEG_LAST] =
 {
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
-  {":file",            IMAGE_STRING_VALUE,                     1},
+  {":data",            IMAGE_STRING_VALUE,                     0},
+  {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
@@ -8395,37 +7888,136 @@ static struct image_type jpeg_type =
 };
 
 
-/* Return non-zero if OBJECT is a valid JPEG image specification.  */
+/* Return non-zero if OBJECT is a valid JPEG image specification.  */
+
+static int
+jpeg_image_p (object)
+     Lisp_Object object;
+{
+  struct image_keyword fmt[JPEG_LAST];
+  
+  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))
+    return 0;
+
+  /* Must specify either the :data or :file keyword.  */
+  return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
+}
+
+
+struct my_jpeg_error_mgr
+{
+  struct jpeg_error_mgr pub;
+  jmp_buf setjmp_buffer;
+};
+
+static void
+my_error_exit (cinfo)
+     j_common_ptr cinfo;
+{
+  struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
+  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.  */
+
+static void
+our_init_source (cinfo)
+     j_decompress_ptr cinfo;
+{
+}
+
+
+/* Fill input buffer method for JPEG data source manager.  Called
+   whenever more data is needed.  We read the whole image in one step,
+   so this only adds a fake end of input marker at the end.  */
+
+static boolean
+our_fill_input_buffer (cinfo)
+     j_decompress_ptr cinfo;
+{
+  /* Insert a fake EOI marker.  */
+  struct jpeg_source_mgr *src = cinfo->src;
+  static JOCTET buffer[2];
+
+  buffer[0] = (JOCTET) 0xFF;
+  buffer[1] = (JOCTET) JPEG_EOI;
+
+  src->next_input_byte = buffer;
+  src->bytes_in_buffer = 2;
+  return TRUE;
+}
+
+
+/* Method to skip over NUM_BYTES bytes in the image data.  CINFO->src
+   is the JPEG data source manager.  */
+
+static void
+our_skip_input_data (cinfo, num_bytes)
+     j_decompress_ptr cinfo;
+     long num_bytes;
+{
+  struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
+
+  if (src)
+    {
+      if (num_bytes > src->bytes_in_buffer)
+       ERREXIT (cinfo, JERR_INPUT_EOF);
+      
+      src->bytes_in_buffer -= num_bytes;
+      src->next_input_byte += num_bytes;
+    }
+}
+
+
+/* Method to terminate data source.  Called by
+   jpeg_finish_decompress() after all data has been processed.  */
 
-static int
-jpeg_image_p (object)
-     Lisp_Object object;
+static void
+our_term_source (cinfo)
+     j_decompress_ptr cinfo;
 {
-  struct image_keyword fmt[JPEG_LAST];
-  
-  bcopy (jpeg_format, fmt, sizeof fmt);
-  
-  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg, 0)
-      || (fmt[JPEG_ASCENT].count 
-         && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
-    return 0;
-  return 1;
 }
 
-struct my_jpeg_error_mgr
-{
-  struct jpeg_error_mgr pub;
-  jmp_buf setjmp_buffer;
-};
+
+/* Set up the JPEG lib for reading an image from DATA which contains
+   LEN bytes.  CINFO is the decompression info structure created for
+   reading the image.  */
 
 static void
-my_error_exit (cinfo)
-     j_common_ptr cinfo;
+jpeg_memory_src (cinfo, data, len)
+     j_decompress_ptr cinfo;
+     JOCTET *data;
+     unsigned int len;
 {
-  struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
-  longjmp (mgr->setjmp_buffer, 1);
+  struct jpeg_source_mgr *src;
+
+  if (cinfo->src == NULL)
+    {
+      /* First time for this JPEG object?  */
+      cinfo->src = (struct jpeg_source_mgr *)
+       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+                                   sizeof (struct jpeg_source_mgr));
+      src = (struct jpeg_source_mgr *) cinfo->src;
+      src->next_input_byte = data;
+    }
+  
+  src = (struct jpeg_source_mgr *) cinfo->src;
+  src->init_source = our_init_source;
+  src->fill_input_buffer = our_fill_input_buffer;
+  src->skip_input_data = our_skip_input_data;
+  src->resync_to_restart = jpeg_resync_to_restart; /* Use default method.  */
+  src->term_source = our_term_source;
+  src->bytes_in_buffer = len;
+  src->next_input_byte = data;
 }
 
+
 /* Load image IMG for use on frame F.  Patterned after example.c
    from the JPEG lib.  */
 
@@ -8437,7 +8029,8 @@ jpeg_load (f, img)
   struct jpeg_decompress_struct cinfo;
   struct my_jpeg_error_mgr mgr;
   Lisp_Object file, specified_file;
-  FILE *fp;
+  Lisp_Object specified_data;
+  FILE *fp = NULL;
   JSAMPARRAY buffer;
   int row_stride, x, y;
   XImage *ximg = NULL;
@@ -8448,26 +8041,31 @@ jpeg_load (f, img)
 
   /* Open the JPEG file.  */
   specified_file = image_spec_value (img->spec, QCfile, NULL);
-  file = x_find_image_file (specified_file);
+  specified_data = image_spec_value (img->spec, QCdata, NULL);
+  file = Qnil;
   GCPRO1 (file);
-  if (!STRINGP (file))
+
+  if (NILP (specified_data))
     {
-      image_error ("Cannot find image file %s", specified_file, Qnil);
-      UNGCPRO;
-      return 0;
-    }
+      file = x_find_image_file (specified_file);
+      if (!STRINGP (file))
+       {
+         image_error ("Cannot find image file `%s'", specified_file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
   
-  fp = fopen (XSTRING (file)->data, "r");
-  if (fp == NULL)
-    {
-      image_error ("Cannot open `%s'", file, Qnil);
-      UNGCPRO;
-      return 0;
+      fp = fopen (XSTRING (file)->data, "r");
+      if (fp == NULL)
+       {
+         image_error ("Cannot open `%s'", file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
     }
 
-  /* Customize libjpeg's error handling to call my_error_exit
-     when an error is detected.  This function will perform
-     a longjmp.  */
+  /* 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);
   
@@ -8478,12 +8076,13 @@ jpeg_load (f, img)
          /* Called from my_error_exit.  Display a JPEG error.  */
          char buffer[JMSG_LENGTH_MAX];
          cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
-         image_error ("Error reading JPEG file `%s': %s", file,
+         image_error ("Error reading JPEG image `%s': %s", img->spec,
                       build_string (buffer));
        }
          
       /* Close the input file and destroy the JPEG object.  */
-      fclose (fp);
+      if (fp)
+       fclose (fp);
       jpeg_destroy_decompress (&cinfo);
 
       BLOCK_INPUT;
@@ -8500,13 +8099,19 @@ jpeg_load (f, img)
     }
 
   /* Create the JPEG decompression object.  Let it read from fp.
-     Read the JPEG image header.  */
+        Read the JPEG image header.  */
   jpeg_create_decompress (&cinfo);
-  jpeg_stdio_src (&cinfo, fp);
+
+  if (NILP (specified_data))
+    jpeg_stdio_src (&cinfo, fp);
+  else
+    jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
+                    STRING_BYTES (XSTRING (specified_data)));
+
   jpeg_read_header (&cinfo, TRUE);
 
   /* Customize decompression so that color quantization will be used.
-     Start decompression.  */
+        Start decompression.  */
   cinfo.quantize_colors = TRUE;
   jpeg_start_decompress (&cinfo);
   width = img->width = cinfo.output_width;
@@ -8515,8 +8120,7 @@ jpeg_load (f, img)
   BLOCK_INPUT;
 
   /* Create X image and pixmap.  */
-  if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg,
-                                   &img->pixmap))
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
     {
       UNBLOCK_INPUT;
       longjmp (mgr.setjmp_buffer, 2);
@@ -8574,7 +8178,8 @@ jpeg_load (f, img)
   /* Clean up.  */
   jpeg_finish_decompress (&cinfo);
   jpeg_destroy_decompress (&cinfo);
-  fclose (fp);
+  if (fp)
+    fclose (fp);
   
   /* Put the image into the pixmap.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
@@ -8608,6 +8213,7 @@ Lisp_Object Qtiff;
 enum tiff_keyword_index
 {
   TIFF_TYPE,
+  TIFF_DATA,
   TIFF_FILE,
   TIFF_ASCENT,
   TIFF_MARGIN,
@@ -8623,7 +8229,8 @@ enum tiff_keyword_index
 static struct image_keyword tiff_format[TIFF_LAST] =
 {
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
-  {":file",            IMAGE_STRING_VALUE,                     1},
+  {":data",            IMAGE_STRING_VALUE,                     0},
+  {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
@@ -8652,13 +8259,124 @@ 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, 1)
+  if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
       || (fmt[TIFF_ASCENT].count 
          && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
     return 0;
-  return 1;
+  
+  /* Must specify either the :data or :file keyword.  */
+  return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
+}
+
+
+/* Reading from a memory buffer for TIFF images Based on the PNG
+   memory source, but we have to provide a lot of extra functions.
+   Blah.
+
+   We really only need to implement read and seek, but I am not
+   convinced that the TIFF library is smart enough not to destroy
+   itself if we only hand it the function pointers we need to
+   override.  */
+
+typedef struct
+{
+  unsigned char *bytes;
+  size_t len;
+  int index;
+}
+tiff_memory_source;
+
+static size_t
+tiff_read_from_memory (data, buf, size)
+     thandle_t data;
+     tdata_t buf;
+     tsize_t size;
+{
+  tiff_memory_source *src = (tiff_memory_source *) data;
+
+  if (size > src->len - src->index)
+    return (size_t) -1;
+  bcopy (src->bytes + src->index, buf, size);
+  src->index += size;
+  return size;
+}
+
+static size_t
+tiff_write_from_memory (data, buf, size)
+     thandle_t data;
+     tdata_t buf;
+     tsize_t size;
+{
+  return (size_t) -1;
+}
+
+static toff_t
+tiff_seek_in_memory (data, off, whence)
+     thandle_t data;
+     toff_t off;
+     int whence;
+{
+  tiff_memory_source *src = (tiff_memory_source *) data;
+  int idx;
+
+  switch (whence)
+    {
+    case SEEK_SET:             /* Go from beginning of source.  */
+      idx = off;
+      break;
+      
+    case SEEK_END:             /* Go from end of source.  */
+      idx = src->len + off;
+      break;
+      
+    case SEEK_CUR:             /* Go from current position.  */
+      idx = src->index + off;
+      break;
+      
+    default:                   /* Invalid `whence'.   */
+      return -1;
+    }
+  
+  if (idx > src->len || idx < 0)
+    return -1;
+  
+  src->index = idx;
+  return src->index;
+}
+
+static int
+tiff_close_memory (data)
+     thandle_t data;
+{
+  /* NOOP */
+  return 0;
+}
+
+static int
+tiff_mmap_memory (data, pbase, psize)
+     thandle_t data;
+     tdata_t *pbase;
+     toff_t *psize;
+{
+  /* It is already _IN_ memory. */
+  return 0;
+}
+
+static void
+tiff_unmap_memory (data, base, size)
+     thandle_t data;
+     tdata_t base;
+     toff_t size;
+{
+  /* We don't need to do this. */
 }
 
+static toff_t
+tiff_size_of_memory (data)
+     thandle_t data;
+{
+  return ((tiff_memory_source *) data)->len;
+}
 
 /* Load TIFF image IMG for use on frame F.  Value is non-zero if
    successful.  */
@@ -8669,30 +8387,62 @@ tiff_load (f, img)
      struct image *img;
 {
   Lisp_Object file, specified_file;
+  Lisp_Object specified_data;
   TIFF *tiff;
   int width, height, x, y;
   uint32 *buf;
   int rc;
   XImage *ximg;
   struct gcpro gcpro1;
+  tiff_memory_source memsrc;
 
   specified_file = image_spec_value (img->spec, QCfile, NULL);
-  file = x_find_image_file (specified_file);
+  specified_data = image_spec_value (img->spec, QCdata, NULL);
+  file = Qnil;
   GCPRO1 (file);
-  if (!STRINGP (file))
+
+  if (NILP (specified_data))
     {
-      image_error ("Cannot find image file %s", file, Qnil);
-      UNGCPRO;
-      return 0;
+      /* Read from a file */
+      file = x_find_image_file (specified_file);
+      if (!STRINGP (file))
+       {
+         image_error ("Cannot find image file `%s'", file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
+         
+      /* Try to open the image file.  */
+      tiff = TIFFOpen (XSTRING (file)->data, "r");
+      if (tiff == NULL)
+       {
+         image_error ("Cannot open `%s'", file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
     }
-  
-  /* Try to open the image file.  */
-  tiff = TIFFOpen (XSTRING (file)->data, "r");
-  if (tiff == NULL)
+  else
     {
-      image_error ("Cannot open `%s'", file, Qnil);
-      UNGCPRO;
-      return 0;
+      /* Memory source! */
+      memsrc.bytes = XSTRING (specified_data)->data;
+      memsrc.len = STRING_BYTES (XSTRING (specified_data));
+      memsrc.index = 0;
+
+      tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
+                            (TIFFReadWriteProc) tiff_read_from_memory,
+                            (TIFFReadWriteProc) tiff_write_from_memory,
+                            tiff_seek_in_memory,
+                            tiff_close_memory,
+                            tiff_size_of_memory,
+                            tiff_mmap_memory,
+                            tiff_unmap_memory);
+
+      if (!tiff)
+       {
+         image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
+         UNGCPRO;
+         return 0;
+       }
     }
 
   /* Get width and height of the image, and allocate a raster buffer
@@ -8705,7 +8455,7 @@ tiff_load (f, img)
   TIFFClose (tiff);
   if (!rc)
     {
-      image_error ("Error reading `%s'", file, Qnil);
+      image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
       xfree (buf);
       UNGCPRO;
       return 0;
@@ -8714,8 +8464,7 @@ tiff_load (f, img)
   BLOCK_INPUT;
 
   /* Create the X image and pixmap.  */
-  if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg, 
-                                   &img->pixmap))
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
     {
       UNBLOCK_INPUT;
       xfree (buf);
@@ -8782,6 +8531,7 @@ Lisp_Object Qgif;
 enum gif_keyword_index
 {
   GIF_TYPE,
+  GIF_DATA,
   GIF_FILE,
   GIF_ASCENT,
   GIF_MARGIN,
@@ -8798,7 +8548,8 @@ enum gif_keyword_index
 static struct image_keyword gif_format[GIF_LAST] =
 {
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
-  {":file",            IMAGE_STRING_VALUE,                     1},
+  {":data",            IMAGE_STRING_VALUE,                     0},
+  {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
@@ -8818,7 +8569,6 @@ static struct image_type gif_type =
   NULL
 };
 
-
 /* Return non-zero if OBJECT is a valid GIF image specification.  */
 
 static int
@@ -8828,11 +8578,45 @@ 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, 1)
+  if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
       || (fmt[GIF_ASCENT].count 
          && XFASTINT (fmt[GIF_ASCENT].value) > 100))
     return 0;
-  return 1;
+  
+  /* 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. */
+
+typedef struct
+{
+  unsigned char *bytes;
+  size_t len;
+  int index;
+}
+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.  */
+static gif_memory_source *current_gif_memory_src;
+
+static int
+gif_read_from_memory (file, buf, len)
+     GifFileType *file;
+     GifByteType *buf;
+     int len;
+{
+  gif_memory_source *src = current_gif_memory_src;
+
+  if (len > src->len - src->index)
+    return -1;
+
+  bcopy (src->bytes + src->index, buf, len);
+  src->index += len;
+  return len;
 }
 
 
@@ -8845,6 +8629,7 @@ gif_load (f, img)
      struct image *img;
 {
   Lisp_Object file, specified_file;
+  Lisp_Object specified_data;
   int rc, width, height, x, y, i;
   XImage *ximg;
   ColorMapObject *gif_color_map;
@@ -8853,31 +8638,55 @@ gif_load (f, img)
   struct gcpro gcpro1;
   Lisp_Object image;
   int ino, image_left, image_top, image_width, image_height;
+  gif_memory_source memsrc;
+  unsigned char *raster;
 
   specified_file = image_spec_value (img->spec, QCfile, NULL);
-  file = x_find_image_file (specified_file);
+  specified_data = image_spec_value (img->spec, QCdata, NULL);
+  file = Qnil;
   GCPRO1 (file);
-  if (!STRINGP (file))
+
+  if (NILP (specified_data))
     {
-      image_error ("Cannot find image file %s", specified_file, Qnil);
-      UNGCPRO;
-      return 0;
-    }
+      file = x_find_image_file (specified_file);
+      if (!STRINGP (file))
+       {
+         image_error ("Cannot find image file `%s'", specified_file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
   
-  /* Open the GIF file.  */
-  gif = DGifOpenFileName (XSTRING (file)->data);
-  if (gif == NULL)
+      /* Open the GIF file.  */
+      gif = DGifOpenFileName (XSTRING (file)->data);
+      if (gif == NULL)
+       {
+         image_error ("Cannot open `%s'", file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
+    }
+  else
     {
-      image_error ("Cannot open `%s'", file, Qnil);
-      UNGCPRO;
-      return 0;
+      /* Read from memory! */
+      current_gif_memory_src = &memsrc;
+      memsrc.bytes = XSTRING (specified_data)->data;
+      memsrc.len = STRING_BYTES (XSTRING (specified_data));
+      memsrc.index = 0;
+
+      gif = DGifOpen(&memsrc, gif_read_from_memory);
+      if (!gif)
+       {
+         image_error ("Cannot open memory source `%s'", img->spec, Qnil);
+         UNGCPRO;
+         return 0;
+       }
     }
 
   /* Read entire contents.  */
   rc = DGifSlurp (gif);
   if (rc == GIF_ERROR)
     {
-      image_error ("Error reading `%s'", file, Qnil);
+      image_error ("Error reading `%s'", img->spec, Qnil);
       DGifCloseFile (gif);
       UNGCPRO;
       return 0;
@@ -8887,7 +8696,8 @@ gif_load (f, img)
   ino = INTEGERP (image) ? XFASTINT (image) : 0;
   if (ino >= gif->ImageCount)
     {
-      image_error ("Invalid image number `%s'", image, Qnil);
+      image_error ("Invalid image number `%s' in image `%s'",
+                  image, img->spec);
       DGifCloseFile (gif);
       UNGCPRO;
       return 0;
@@ -8899,8 +8709,7 @@ gif_load (f, img)
   BLOCK_INPUT;
 
   /* Create the X image and pixmap.  */
-  if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg,
-                                   &img->pixmap))
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
     {
       UNBLOCK_INPUT;
       DGifCloseFile (gif);
@@ -8952,7 +8761,11 @@ gif_load (f, img)
        XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
     }
 
-  /* Read the GIF image into the X image.  */
+  /* Read the GIF image into the X image.  We use a local variable
+     `raster' here because RasterBits below is a char *, and invites
+     problems with bytes >= 0x80.  */
+  raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
+  
   if (gif->SavedImages[ino].ImageDesc.Interlace)
     {
       static int interlace_start[] = {0, 4, 2, 1};
@@ -8973,8 +8786,7 @@ gif_load (f, img)
          
          for (x = 0; x < image_width; x++)
            {
-             unsigned int i
-               = gif->SavedImages[ino].RasterBits[(y * image_width) + x];
+             int i = raster[(y * image_width) + x];
              XPutPixel (ximg, x + image_left, row + image_top,
                         pixel_colors[i]);
            }
@@ -8987,7 +8799,7 @@ gif_load (f, img)
       for (y = 0; y < image_height; ++y)
        for (x = 0; x < image_width; ++x)
          {
-           unsigned i = gif->SavedImages[ino].RasterBits[y * image_width + x];
+           int i = raster[y * image_width + x];
            XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
          }
     }
@@ -9097,7 +8909,7 @@ gs_image_p (object)
   
   bcopy (gs_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript, 1)
+  if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
       || (fmt[GS_ASCENT].count 
          && XFASTINT (fmt[GS_ASCENT].value) > 100))
     return 0;
@@ -9163,8 +8975,7 @@ gs_load (f, img)
 
   if (!img->pixmap)
     {
-      image_error ("Unable to create pixmap for `%s'",
-                  image_spec_value (img->spec, QCfile, NULL), Qnil);
+      image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
       return 0;
     }
     
@@ -9228,7 +9039,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;
@@ -9267,16 +9078,12 @@ 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
        image_error ("Cannot get X image of `%s'; colors will not be freed",
-                    image_spec_value (img->spec, QCfile, NULL), Qnil);
+                    img->spec, Qnil);
       
       UNBLOCK_INPUT;
     }
@@ -9393,106 +9200,162 @@ 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-undisplay-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),
                                   0, 0, 32000, 32000, 0, 0,
-                                  InputOnly, CopyFromParent,
+                                  InputOnly,
+                                  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-undisplay-busy-cursor' is called for each `x-display-busy-cursor'\n\
-issued.  FORCE non-nil means undisplay 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;
+    }
 }
 
 
@@ -9695,8 +9558,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;
@@ -9761,7 +9624,7 @@ used to change the tooltip's appearance.\n\
 Automatically hide the tooltip after TIMEOUT seconds.\n\
 TIMEOUT nil means use the default timeout of 5 seconds.")
   (string, frame, parms, timeout)
-     Lisp_Object string, frame, parms;
+     Lisp_Object string, frame, parms, timeout;
 {
   struct frame *f;
   struct window *w;
@@ -9772,13 +9635,13 @@ TIMEOUT nil means use the default timeout of 5 seconds.")
   int i, width, height;
   int root_x, root_y, win_x, win_y;
   unsigned pmask;
-  struct gcpro gcpro1, gcpro2, gcpro3;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   int old_windows_or_buffers_changed = windows_or_buffers_changed;
   int count = specpdl_ptr - specpdl;
   
   specbind (Qinhibit_redisplay, Qt);
 
-  GCPRO3 (string, parms, frame);
+  GCPRO4 (string, parms, frame, timeout);
 
   CHECK_STRING (string, 0);
   f = check_x_frame (frame);
@@ -9885,7 +9748,8 @@ TIMEOUT nil means use the default timeout of 5 seconds.")
   /* Let the tip disappear after timeout seconds.  */
   tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
                     intern ("x-hide-tip"));
-  
+
+  UNGCPRO;
   return unbind_to (count, Qnil);
 }
 
@@ -10201,8 +10065,6 @@ syms_of_xfns ()
   staticpro (&Quser_position);
   Quser_size = intern ("user-size");
   staticpro (&Quser_size);
-  Qdisplay = intern ("display");
-  staticpro (&Qdisplay);
   Qscroll_bar_foreground = intern ("scroll-bar-foreground");
   staticpro (&Qscroll_bar_foreground);
   Qscroll_bar_background = intern ("scroll-bar-background");
@@ -10211,6 +10073,11 @@ syms_of_xfns ()
   staticpro (&Qscreen_gamma);
   /* This is the end of symbol initialization.  */
 
+  /* Text property `display' should be nonsticky by default.  */
+  Vtext_property_default_nonsticky
+    = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
+
+
   Qlaplace = intern ("laplace");
   staticpro (&Qlaplace);
   
@@ -10275,6 +10142,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\
@@ -10338,16 +10210,10 @@ 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 (&Sx_display_color_p);
+  defsubr (&Sxw_display_color_p);
   defsubr (&Sx_display_grayscale_p);
-  defsubr (&Sx_color_defined_p);
-  defsubr (&Sx_color_values);
+  defsubr (&Sxw_color_defined_p);
+  defsubr (&Sxw_color_values);
   defsubr (&Sx_server_max_request_size);
   defsubr (&Sx_server_vendor);
   defsubr (&Sx_server_version);
@@ -10361,22 +10227,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;
@@ -10403,8 +10260,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");
@@ -10458,11 +10313,8 @@ Each element of the list is a symbol for a supported image type.");
   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);