]> code.delx.au - gnu-emacs/blobdiff - src/xfns.c
(cancel_busy_cursor): Set busy_cursor_atimer to null
[gnu-emacs] / src / xfns.c
index 385724fcf84a2fe78e939286e5355ff6e1d0617e..e412cc568c644f1d1b4449d37d6ceed1a049e707 100644 (file)
@@ -19,17 +19,10 @@ 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,
-   toolbars, 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>
 
 /* This makes the fields of a Display accessible, in Xlib header files.  */
 
@@ -40,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"
@@ -48,9 +42,13 @@ Boston, MA 02111-1307, USA.  */
 #include "fontset.h"
 #include "systime.h"
 #include "termhooks.h"
+#include "atimer.h"
 
 #ifdef HAVE_X_WINDOWS
-extern void abort ();
+
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 /* On some systems, the character-composition stuff is broken in X11R5.  */
 
@@ -114,6 +112,7 @@ extern XFontStruct *xlwmenu_default_font;
 #endif
 
 extern void free_frame_menubar ();
+extern double atof ();
 
 #endif /* USE_X_TOOLKIT */
 
@@ -243,14 +242,15 @@ 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;
 
 /* The below are defined in frame.c.  */
 
 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
-extern Lisp_Object Qtoolbar_lines;
+extern Lisp_Object Qtool_bar_lines;
 
 extern Lisp_Object Vwindow_system_version;
 
@@ -285,12 +285,9 @@ check_x_frame (frame)
   FRAME_PTR f;
 
   if (NILP (frame))
-    f = selected_frame;
-  else
-    {
-      CHECK_LIVE_FRAME (frame, 0);
-      f = XFRAME (frame);
-    }
+    frame = selected_frame;
+  CHECK_LIVE_FRAME (frame, 0);
+  f = XFRAME (frame);
   if (! FRAME_X_P (f))
     error ("Non-X frame used");
   return f;
@@ -306,9 +303,10 @@ check_x_display_info (frame)
 {
   if (NILP (frame))
     {
-      if (FRAME_X_P (selected_frame)
-         && FRAME_LIVE_P (selected_frame))
-       return FRAME_X_DISPLAY_INFO (selected_frame);
+      struct frame *sf = XFRAME (selected_frame);
+      
+      if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
+       return FRAME_X_DISPLAY_INFO (sf);
       else if (x_display_list != 0)
        return x_display_list;
       else
@@ -342,14 +340,16 @@ x_window_to_frame (dpyinfo, wdesc)
   Lisp_Object tail, frame;
   struct frame *f;
 
-  for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
     {
-      frame = XCONS (tail)->car;
+      frame = XCAR (tail);
       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)
@@ -377,34 +377,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 = XCONS (tail)->cdr)
+  found = NULL;
+  for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
     {
-      frame = XCONS (tail)->car;
+      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.  */
@@ -418,17 +424,19 @@ x_non_menubar_window_to_frame (dpyinfo, wdesc)
   struct frame *f;
   struct x_output *x;
 
-  for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
     {
-      frame = XCONS (tail)->car;
+      frame = XCAR (tail);
       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) 
@@ -453,13 +461,13 @@ x_menubar_window_to_frame (dpyinfo, wdesc)
   struct frame *f;
   struct x_output *x;
 
-  for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
     {
-      frame = XCONS (tail)->car;
+      frame = XCAR (tail);
       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.  */
@@ -482,13 +490,13 @@ x_top_window_to_frame (dpyinfo, wdesc)
   struct frame *f;
   struct x_output *x;
 
-  for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
     {
-      frame = XCONS (tail)->car;
+      frame = XCAR (tail);
       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;
 
@@ -660,7 +668,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;
 
@@ -735,30 +743,33 @@ x_destroy_all_bitmaps (dpyinfo)
 struct x_frame_parm_table
 {
   char *name;
-  void (*setter)( /* struct frame *frame, Lisp_Object val, oldval */ );
+  void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
 };
 
-void x_set_foreground_color ();
-void x_set_background_color ();
-void x_set_mouse_color ();
-void x_set_cursor_color ();
-void x_set_border_color ();
-void x_set_cursor_type ();
-void x_set_icon_type ();
-void x_set_icon_name ();
-void x_set_font ();
-void x_set_border_width ();
-void x_set_internal_border_width ();
-void x_explicitly_set_name ();
-void x_set_autoraise ();
-void x_set_autolower ();
-void x_set_vertical_scroll_bars ();
-void x_set_visibility ();
-void x_set_menu_bar_lines ();
-void x_set_scroll_bar_width ();
-void x_set_title ();
-void x_set_unsplittable ();
-void x_set_toolbar_lines 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));
+void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
+                                     Lisp_Object));
+void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
+                                    Lisp_Object));
+void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
                                      Lisp_Object));
 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
@@ -768,6 +779,7 @@ static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
                                                             Lisp_Object,
                                                             char *, char *,
                                                             int));
+static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
 
 static struct x_frame_parm_table x_frame_parms[] =
 {
@@ -791,9 +803,10 @@ static struct x_frame_parm_table x_frame_parms[] =
   "unsplittable", x_set_unsplittable,
   "vertical-scroll-bars", x_set_vertical_scroll_bars,
   "visibility", x_set_visibility,
-  "toolbar-lines", x_set_toolbar_lines,
+  "tool-bar-lines", x_set_tool_bar_lines,
   "scroll-bar-foreground", x_set_scroll_bar_foreground,
   "scroll-bar-background", x_set_scroll_bar_background,
+  "screen-gamma", x_set_screen_gamma
 };
 
 /* Attach the `x-frame-parameter' properties to
@@ -834,7 +847,7 @@ x_set_frame_parameters (f, alist)
   /* Record in these vectors all the parms specified.  */
   Lisp_Object *parms;
   Lisp_Object *values;
-  int i;
+  int i, p;
   int left_no_change = 0, top_no_change = 0;
   int icon_left_no_change = 0, icon_top_no_change = 0;
 
@@ -882,6 +895,29 @@ x_set_frame_parameters (f, alist)
   else
     height = FRAME_HEIGHT (f);
 
+  /* Process foreground_color and background_color before anything else.
+     They are independent of other properties, but other properties (e.g.,
+     cursor_color) are dependent upon them.  */
+  for (p = 0; p < i; p++) 
+    {
+      Lisp_Object prop, val;
+
+      prop = parms[p];
+      val = values[p];
+      if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
+       {
+         register Lisp_Object param_index, old_value;
+
+         param_index = Fget (prop, Qx_frame_parameter);
+         old_value = get_frame_param (f, prop);
+         store_frame_param (f, prop, val);
+         if (NATNUMP (param_index)
+             && (XFASTINT (param_index)
+                 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
+           (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
+       }
+    }
+
   /* Now process them in reverse of specified order.  */
   for (i--; i >= 0; i--)
     {
@@ -902,6 +938,9 @@ x_set_frame_parameters (f, alist)
        icon_top = val;
       else if (EQ (prop, Qicon_left))
        icon_left = val;
+      else if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
+       /* Processed above.  */
+       continue;
       else
        {
          register Lisp_Object param_index, old_value;
@@ -988,18 +1027,18 @@ x_set_frame_parameters (f, alist)
            if (leftpos < 0)
              f->output_data.x->size_hint_flags |= XNegative;
          }
-       else if (CONSP (left) && EQ (XCONS (left)->car, Qminus)
-                && CONSP (XCONS (left)->cdr)
-                && INTEGERP (XCONS (XCONS (left)->cdr)->car))
+       else if (CONSP (left) && EQ (XCAR (left), Qminus)
+                && CONSP (XCDR (left))
+                && INTEGERP (XCAR (XCDR (left))))
          {
-           leftpos = - XINT (XCONS (XCONS (left)->cdr)->car);
+           leftpos = - XINT (XCAR (XCDR (left)));
            f->output_data.x->size_hint_flags |= XNegative;
          }
-       else if (CONSP (left) && EQ (XCONS (left)->car, Qplus)
-                && CONSP (XCONS (left)->cdr)
-                && INTEGERP (XCONS (XCONS (left)->cdr)->car))
+       else if (CONSP (left) && EQ (XCAR (left), Qplus)
+                && CONSP (XCDR (left))
+                && INTEGERP (XCAR (XCDR (left))))
          {
-           leftpos = XINT (XCONS (XCONS (left)->cdr)->car);
+           leftpos = XINT (XCAR (XCDR (left)));
          }
 
        if (EQ (top, Qminus))
@@ -1010,18 +1049,18 @@ x_set_frame_parameters (f, alist)
            if (toppos < 0)
              f->output_data.x->size_hint_flags |= YNegative;
          }
-       else if (CONSP (top) && EQ (XCONS (top)->car, Qminus)
-                && CONSP (XCONS (top)->cdr)
-                && INTEGERP (XCONS (XCONS (top)->cdr)->car))
+       else if (CONSP (top) && EQ (XCAR (top), Qminus)
+                && CONSP (XCDR (top))
+                && INTEGERP (XCAR (XCDR (top))))
          {
-           toppos = - XINT (XCONS (XCONS (top)->cdr)->car);
+           toppos = - XINT (XCAR (XCDR (top)));
            f->output_data.x->size_hint_flags |= YNegative;
          }
-       else if (CONSP (top) && EQ (XCONS (top)->car, Qplus)
-                && CONSP (XCONS (top)->cdr)
-                && INTEGERP (XCONS (XCONS (top)->cdr)->car))
+       else if (CONSP (top) && EQ (XCAR (top), Qplus)
+                && CONSP (XCDR (top))
+                && INTEGERP (XCAR (XCDR (top))))
          {
-           toppos = XINT (XCONS (XCONS (top)->cdr)->car);
+           toppos = XINT (XCAR (XCDR (top)));
          }
 
 
@@ -1166,7 +1205,7 @@ x_report_frame_params (f, alistptr)
                  (FRAME_VISIBLE_P (f) ? Qt
                   : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
   store_in_alist (alistptr, Qdisplay,
-                 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->car);
+                 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
 
   if (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
     tem = Qnil;
@@ -1176,12 +1215,29 @@ x_report_frame_params (f, alistptr)
 }
 \f
 
+
+/* Gamma-correct COLOR on frame F.  */
+
+void
+gamma_correct (f, color)
+     struct frame *f;
+     XColor *color;
+{
+  if (f->gamma)
+    {
+      color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
+      color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
+      color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
+    }
+}
+
+
 /* 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.  */
 
 int
-defined_color (f, color, color_def, alloc)
+x_defined_color (f, color, color_def, alloc)
      FRAME_PTR f;
      char *color;
      XColor *color_def;
@@ -1197,6 +1253,9 @@ defined_color (f, color, color_def, alloc)
   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)
        {
@@ -1289,15 +1348,36 @@ x_decode_color (f, arg, def)
   if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
     return def;
 
-  /* 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 (arg)->data, &cdef, 1))
     return cdef.pixel;
 
   Fsignal (Qerror, Fcons (build_string ("undefined color"),
                          Fcons (arg, 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.  */
+
+static void
+x_set_screen_gamma (f, new_value, old_value)
+     struct frame *f;
+     Lisp_Object new_value, old_value;
+{
+  if (NILP (new_value))
+    f->gamma = 0;
+  else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
+    /* The value 0.4545 is the normal viewing gamma.  */
+    f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
+  else
+    Fsignal (Qerror, Fcons (build_string ("Illegal screen-gamma"),
+                           Fcons (new_value, Qnil)));
+
+  clear_face_cache (0);
+}
+
+
 /* Functions called only from `x_set_frame_param'
    to set individual parameters.
 
@@ -1325,7 +1405,7 @@ x_set_foreground_color (f, arg, oldval)
       XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
                      f->output_data.x->foreground_pixel);
       UNBLOCK_INPUT;
-      recompute_basic_faces (f);
+      update_face_from_frame_parameter (f, Qforeground_color, arg);
       if (FRAME_VISIBLE_P (f))
         redraw_frame (f);
     }
@@ -1336,9 +1416,6 @@ x_set_background_color (f, arg, oldval)
      struct frame *f;
      Lisp_Object arg, oldval;
 {
-  Pixmap temp;
-  int mask;
-
   unsigned long pixel
     = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
 
@@ -1367,7 +1444,7 @@ x_set_background_color (f, arg, oldval)
       }
       UNBLOCK_INPUT;
 
-      recompute_basic_faces (f);
+      update_face_from_frame_parameter (f, Qbackground_color, arg);
 
       if (FRAME_VISIBLE_P (f))
         redraw_frame (f);
@@ -1506,6 +1583,8 @@ x_set_mouse_color (f, arg, oldval)
 
   XFlush (FRAME_X_DISPLAY (f));
   UNBLOCK_INPUT;
+
+  update_face_from_frame_parameter (f, Qmouse_color, arg);
 }
 
 void
@@ -1551,6 +1630,8 @@ x_set_cursor_color (f, arg, oldval)
          x_update_cursor (f, 1);
        }
     }
+
+  update_face_from_frame_parameter (f, Qcursor_color, arg);
 }
 \f
 /* Set the border-color of frame F to value described by ARG.
@@ -1569,15 +1650,12 @@ x_set_border_color (f, arg, oldval)
      struct frame *f;
      Lisp_Object arg, oldval;
 {
-  unsigned char *str;
   int pix;
 
   CHECK_STRING (arg, 0);
-  str = XSTRING (arg)->data;
-
   pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
-
   x_set_border_pixel (f, pix);
+  update_face_from_frame_parameter (f, Qborder_color, arg);
 }
 
 /* Set the border-color of frame F to pixel value PIX.
@@ -1594,9 +1672,6 @@ x_set_border_pixel (f, pix)
 
   if (FRAME_X_WINDOW (f) != 0 && f->output_data.x->border_width > 0)
     {
-      Pixmap temp;
-      int mask;
-
       BLOCK_INPUT;
       XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                        (unsigned long)pix);
@@ -1617,11 +1692,11 @@ 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 (XCONS (arg)->car, Qbar)
-          && INTEGERP (XCONS (arg)->cdr))
+  else if (CONSP (arg) && EQ (XCAR (arg), Qbar)
+          && INTEGERP (XCDR (arg)))
     {
       FRAME_DESIRED_CURSOR (f) = BAR_CURSOR;
-      f->output_data.x->cursor_width = XINT (XCONS (arg)->cdr);
+      f->output_data.x->cursor_width = XINT (XCDR (arg));
     }
   else
     /* Treat anything unknown as "box cursor".
@@ -1678,7 +1753,7 @@ x_icon_type (f)
 
   tem = assq_no_quit (Qicon_type, f->param_alist);
   if (CONSP (tem))
-    return XCONS (tem)->cdr;
+    return XCDR (tem);
   else
     return Qnil;
 }
@@ -1753,6 +1828,8 @@ x_set_font (f, arg, oldval)
   else
     abort ();
 
+  do_pending_window_change (0);
+
   /* Don't call `face-set-after-frame-default' when faces haven't been
      initialized yet.  This is the case when called from
      Fx_create_frame.  In that case, the X widget or window doesn't
@@ -1803,14 +1880,9 @@ x_set_internal_border_width (f, arg, oldval)
 
   if (FRAME_X_WINDOW (f) != 0)
     {
-      BLOCK_INPUT;
       x_set_window_size (f, 0, f->width, f->height);
-#if 0
-      x_set_resize_hint (f);
-#endif
-      XFlush (FRAME_X_DISPLAY (f));
-      UNBLOCK_INPUT;
       SET_FRAME_GARBAGED (f);
+      do_pending_window_change (0);
     }
 }
 
@@ -1858,7 +1930,9 @@ x_set_menu_bar_lines (f, value, oldval)
      Lisp_Object value, oldval;
 {
   int nlines;
+#ifndef USE_X_TOOLKIT
   int olines = FRAME_MENU_BAR_LINES (f);
+#endif
 
   /* Right now, menu bars don't work properly in minibuf-only frames;
      most of the commands try to apply themselves to the minibuffer
@@ -1907,7 +1981,7 @@ x_set_menu_bar_lines (f, value, oldval)
    The frame's height doesn't change.  */
 
 void
-x_set_toolbar_lines (f, value, oldval)
+x_set_tool_bar_lines (f, value, oldval)
      struct frame *f;
      Lisp_Object value, oldval;
 {
@@ -1922,8 +1996,8 @@ x_set_toolbar_lines (f, value, oldval)
   /* Make sure we redisplay all windows in this frame.  */
   ++windows_or_buffers_changed;
 
-  delta = nlines - FRAME_TOOLBAR_LINES (f);
-  FRAME_TOOLBAR_LINES (f) = nlines;
+  delta = nlines - FRAME_TOOL_BAR_LINES (f);
+  FRAME_TOOL_BAR_LINES (f) = nlines;
   x_set_menu_bar_lines_1 (FRAME_ROOT_WINDOW (f), delta);
   adjust_glyphs (f);
 }
@@ -1957,7 +2031,8 @@ x_set_scroll_bar_foreground (f, value, oldval)
        (*condemn_scroll_bars_hook) (f);
       if (judge_scroll_bars_hook)
        (*judge_scroll_bars_hook) (f);
-      
+
+      update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
       redraw_frame (f);
     }
 }
@@ -1992,6 +2067,7 @@ x_set_scroll_bar_background (f, value, oldval)
       if (judge_scroll_bars_hook)
        (*judge_scroll_bars_hook) (f);
       
+      update_face_from_frame_parameter (f, Qscroll_bar_background, value);
       redraw_frame (f);
     }
 }
@@ -2125,9 +2201,9 @@ x_implicitly_set_name (f, arg, oldval)
        F->explicit_name is set, ignore the new name; otherwise, set it.  */
 
 void
-x_set_title (f, name)
+x_set_title (f, name, old_name)
      struct frame *f;
-     Lisp_Object name;
+     Lisp_Object name, old_name;
 {
   /* Don't change the title if it's already NAME.  */
   if (EQ (name, f->title))
@@ -2228,6 +2304,7 @@ x_set_vertical_scroll_bars (f, arg, oldval)
         call x_set_window_size.  */
       if (FRAME_X_WINDOW (f))
        x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
+      do_pending_window_change (0);
     }
 }
 
@@ -2240,8 +2317,8 @@ x_set_scroll_bar_width (f, arg, oldval)
 
   if (NILP (arg))
     {
-#ifdef USE_X_TOOLKIT
-      /* A too wide or narrow toolkit scroll bar doesn't look good.  */
+#ifdef USE_TOOLKIT_SCROLL_BARS
+      /* A minimum width of 14 doesn't look good for toolkit scroll bars.  */
       int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
       FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
       FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
@@ -2257,6 +2334,7 @@ x_set_scroll_bar_width (f, arg, oldval)
 
       if (FRAME_X_WINDOW (f))
         x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
+      do_pending_window_change (0);
     }
   else if (INTEGERP (arg) && XINT (arg) > 0
           && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
@@ -2270,7 +2348,7 @@ x_set_scroll_bar_width (f, arg, oldval)
        x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
     }
 
-  change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0);
+  change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
   XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
   XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
 }
@@ -2501,6 +2579,7 @@ x_get_resource_string (attribute, class)
 {
   char *name_key;
   char *class_key;
+  struct frame *sf = SELECTED_FRAME ();
 
   /* Allocate space for the components, the dots which separate them,
      and the final '\0'.  */
@@ -2514,7 +2593,7 @@ x_get_resource_string (attribute, class)
           attribute);
   sprintf (class_key, "%s.%s", EMACS_CLASS, class);
 
-  return x_get_string_resource (FRAME_X_DISPLAY_INFO (selected_frame)->xrdb,
+  return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
                                name_key, class_key);
 }
 
@@ -2522,6 +2601,7 @@ x_get_resource_string (attribute, class)
 enum resource_types
 {
   RES_TYPE_NUMBER,
+  RES_TYPE_FLOAT,
   RES_TYPE_BOOLEAN,
   RES_TYPE_STRING,
   RES_TYPE_SYMBOL
@@ -2569,6 +2649,9 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type)
            case RES_TYPE_NUMBER:
              return make_number (atoi (XSTRING (tem)->data));
 
+           case RES_TYPE_FLOAT:
+             return make_float (atof (XSTRING (tem)->data));
+
            case RES_TYPE_BOOLEAN:
              tem = Fdowncase (tem);
              if (!strcmp (XSTRING (tem)->data, "on")
@@ -2780,8 +2863,6 @@ x_figure_window_size (f, parms)
      Lisp_Object parms;
 {
   register Lisp_Object tem0, tem1, tem2;
-  int height, width, left, top;
-  register int geometry;
   long window_prompting = 0;
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
@@ -2821,7 +2902,7 @@ x_figure_window_size (f, parms)
        ? 0
        : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
   f->output_data.x->flags_areas_extra
-    = 2 * FRAME_FLAGS_AREA_WIDTH (f);
+    = FRAME_FLAGS_AREA_WIDTH (f);
   f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
   f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
 
@@ -2835,18 +2916,18 @@ x_figure_window_size (f, parms)
          f->output_data.x->top_pos = 0;
          window_prompting |= YNegative;
        }
-      else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qminus)
-              && CONSP (XCONS (tem0)->cdr)
-              && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
+      else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
+              && CONSP (XCDR (tem0))
+              && INTEGERP (XCAR (XCDR (tem0))))
        {
-         f->output_data.x->top_pos = - XINT (XCONS (XCONS (tem0)->cdr)->car);
+         f->output_data.x->top_pos = - XINT (XCAR (XCDR (tem0)));
          window_prompting |= YNegative;
        }
-      else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qplus)
-              && CONSP (XCONS (tem0)->cdr)
-              && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
+      else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
+              && CONSP (XCDR (tem0))
+              && INTEGERP (XCAR (XCDR (tem0))))
        {
-         f->output_data.x->top_pos = XINT (XCONS (XCONS (tem0)->cdr)->car);
+         f->output_data.x->top_pos = XINT (XCAR (XCDR (tem0)));
        }
       else if (EQ (tem0, Qunbound))
        f->output_data.x->top_pos = 0;
@@ -2863,18 +2944,18 @@ x_figure_window_size (f, parms)
          f->output_data.x->left_pos = 0;
          window_prompting |= XNegative;
        }
-      else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qminus)
-              && CONSP (XCONS (tem1)->cdr)
-              && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
+      else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
+              && CONSP (XCDR (tem1))
+              && INTEGERP (XCAR (XCDR (tem1))))
        {
-         f->output_data.x->left_pos = - XINT (XCONS (XCONS (tem1)->cdr)->car);
+         f->output_data.x->left_pos = - XINT (XCAR (XCDR (tem1)));
          window_prompting |= XNegative;
        }
-      else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qplus)
-              && CONSP (XCONS (tem1)->cdr)
-              && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
+      else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
+              && CONSP (XCDR (tem1))
+              && INTEGERP (XCAR (XCDR (tem1))))
        {
-         f->output_data.x->left_pos = XINT (XCONS (XCONS (tem1)->cdr)->car);
+         f->output_data.x->left_pos = XINT (XCAR (XCDR (tem1)));
        }
       else if (EQ (tem1, Qunbound))
        f->output_data.x->left_pos = 0;
@@ -2974,6 +3055,293 @@ 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;
+{
+#ifndef X_I18N_INHIBITED
+  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;
+#else /* X_I18N_INHIBITED */
+  FRAME_XIC (f) = NULL;
+  FRAME_XIC_STYLE (f) = 0;
+  FRAME_XIC_FONTSET (f) = NULL;
+#endif /* X_I18N_INHIBITED */
+}
+
+
+/* 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
 
@@ -3026,6 +3394,7 @@ x_window (f, window_prompting, minibuffer_only)
                                  shell_widget, False,
                                  (lw_callback) NULL,
                                  (lw_callback) NULL,
+                                 (lw_callback) NULL,
                                  (lw_callback) NULL);
 
   f->output_data.x->column_widget = pane_widget;
@@ -3059,7 +3428,6 @@ x_window (f, window_prompting, minibuffer_only)
         ? (f->output_data.x->menubar_widget->core.height
            + f->output_data.x->menubar_widget->core.border_width)
         : 0);
-    extern char *lwlib_toolkit_type;
 
 #if 0 /* Experimentally, we now get the right results
         for -geometry -0-0 without this.  24 Aug 96, rms.  */
@@ -3132,35 +3500,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;
@@ -3182,8 +3524,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);
@@ -3209,12 +3562,9 @@ x_window (f, window_prompting, minibuffer_only)
 
   UNBLOCK_INPUT;
 
-  if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
-    initialize_frame_menubar (f);
-  lw_set_main_areas (pane_widget, f->output_data.x->menubar_widget, frame_widget);
-
-  if (FRAME_X_WINDOW (f) == 0)
-    error ("Unable to create window");
+  /* This is a no-op, except under Motif.  Make sure main areas are
+     set to something reasonable, in case we get an error later.  */
+  lw_set_main_areas (pane_widget, 0, frame_widget);
 }
 
 #else /* not USE_X_TOOLKIT */
@@ -3254,38 +3604,21 @@ x_window (f)
                     InputOutput, /* class */
                     FRAME_X_DISPLAY_INFO (f)->visual,
                     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;
@@ -3590,8 +3923,8 @@ This function is an internal primitive--use `make-frame' instead.")
     }
 
   /* Create fontsets from `global_fontset_alist' before handling fonts.  */
-  for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCONS (tem)->cdr)
-    fs_register_fontset (f, XCONS (tem)->car);
+  for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCDR (tem))
+    fs_register_fontset (f, XCAR (tem));
 
   /* Extract the window parameters from the supplied values
      that are needed to determine window geometry.  */
@@ -3666,13 +3999,15 @@ 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"),
                       "cursorColor", "Foreground", RES_TYPE_STRING);
   x_default_parameter (f, parms, Qborder_color, build_string ("black"),
                       "borderColor", "BorderColor", RES_TYPE_STRING);
+  x_default_parameter (f, parms, Qscreen_gamma, Qnil,
+                      "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
 
   x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
                                        "scrollBarForeground",
@@ -3691,11 +4026,8 @@ This function is an internal primitive--use `make-frame' instead.")
   
   x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
                       "menuBar", "MenuBar", RES_TYPE_NUMBER);
-  x_default_parameter (f, parms, Qtoolbar_lines, make_number (0),
+  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);
@@ -3722,23 +4054,30 @@ This function is an internal primitive--use `make-frame' instead.")
 
   f->output_data.x->size_hint_flags = window_prompting;
 
-  /* Create the X widget or window.  Add the toolbar height to the
+  tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
+  f->no_split = minibuffer_only || EQ (tem, Qt);
+
+  /* Create the X widget or window.  Add the tool-bar height to the
      initial frame height so that the user gets a text display area of
      the size he specified with -g or via .Xdefaults.  Later changes
-     of the toolbar height don't change the frame size.  This is done
+     of the tool-bar height don't change the frame size.  This is done
      so that users can create tall Emacs frames without having to
-     guess how tall the toolbar will get.  */
-  f->height += FRAME_TOOLBAR_LINES (f);
+     guess how tall the tool-bar will get.  */
+  f->height += FRAME_TOOL_BAR_LINES (f);
+
 #ifdef USE_X_TOOLKIT
   x_window (f, window_prompting, minibuffer_only);
 #else
   x_window (f);
 #endif
+  
   x_icon (f, parms);
   x_make_gc (f);
 
-  call1 (Qface_set_after_frame_default, frame);
-  
+  /* Now consider the frame official.  */
+  FRAME_X_DISPLAY_INFO (f)->reference_count++;
+  Vframe_list = Fcons (frame, Vframe_list);
+
   /* We need to do this after creating the X window, so that the
      icon-creation functions can say whose icon they're describing.  */
   x_default_parameter (f, parms, Qicon_type, Qnil,
@@ -3750,6 +4089,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
@@ -3758,32 +4100,37 @@ This function is an internal primitive--use `make-frame' instead.")
   height = f->height;
   f->height = 0;
   SET_FRAME_WIDTH (f, 0);
-  change_frame_size (f, height, width, 1, 0);
-
-  /* Tell the server what size and position, etc, we want,
-     and how badly we want them.  */
-  BLOCK_INPUT;
-  x_wm_set_size_hint (f, window_prompting, 0);
-  UNBLOCK_INPUT;
+  change_frame_size (f, height, width, 1, 0, 0);
 
-  tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
-  f->no_split = minibuffer_only || EQ (tem, Qt);
+  /* Set up faces after all frame parameters are known.  */
+  call1 (Qface_set_after_frame_default, frame);
 
-  UNGCPRO;
+#ifdef USE_X_TOOLKIT
+  /* Create the menu bar.  */
+  if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
+    {
+      /* If this signals an error, we haven't set size hints for the
+        frame and we didn't make it visible.  */
+      initialize_frame_menubar (f);
 
-  /* It is now ok to make the frame official
-     even if we get an error below.
-     And the frame needs to be on Vframe_list
-     or making it visible won't work.  */
-  Vframe_list = Fcons (frame, Vframe_list);
+      /* This is a no-op, except under Motif where it arranges the
+        main window for the widgets on it.  */
+      lw_set_main_areas (f->output_data.x->column_widget,
+                        f->output_data.x->menubar_widget,
+                        f->output_data.x->edit_widget);
+    }
+#endif /* USE_X_TOOLKIT */
 
-  /* Now that the frame is official, it counts as a reference to
-     its display.  */
-  FRAME_X_DISPLAY_INFO (f)->reference_count++;
+  /* Tell the server what size and position, etc, we want, and how
+     badly we want them.  This should be done after we have the menu
+     bar so that its size can be taken into account.  */
+  BLOCK_INPUT;
+  x_wm_set_size_hint (f, window_prompting, 0);
+  UNBLOCK_INPUT;
 
-  /* Make the window appear on the frame and enable display,
-     unless the caller says not to.  However, with explicit parent,
-     Emacs cannot control visibility, so don't try.  */
+  /* Make the window appear on the frame and enable display, unless
+     the caller says not to.  However, with explicit parent, Emacs
+     cannot control visibility, so don't try.  */
   if (! f->output_data.x->explicit_parent)
     {
       Lisp_Object visibility;
@@ -3802,6 +4149,7 @@ This function is an internal primitive--use `make-frame' instead.")
        ;
     }
 
+  UNGCPRO;
   return unbind_to (count, frame);
 }
 
@@ -3823,9 +4171,8 @@ x_get_focus_frame (frame)
 }
 
 \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;
 {
@@ -3834,18 +4181,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;
 {
@@ -3854,7 +4197,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];
 
@@ -3867,11 +4210,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;
 {
@@ -5164,10 +5504,10 @@ x_display_info_for_name (name)
 
   for (dpyinfo = x_display_list, names = x_display_name_list;
        dpyinfo;
-       dpyinfo = dpyinfo->next, names = XCONS (names)->cdr)
+       dpyinfo = dpyinfo->next, names = XCDR (names))
     {
       Lisp_Object tem;
-      tem = Fstring_equal (XCONS (XCONS (names)->car)->car, name);
+      tem = Fstring_equal (XCAR (XCAR (names)), name);
       if (!NILP (tem))
        return dpyinfo;
     }
@@ -5285,8 +5625,8 @@ DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
   Lisp_Object tail, result;
 
   result = Qnil;
-  for (tail = x_display_name_list; ! NILP (tail); tail = XCONS (tail)->cdr)
-    result = Fcons (XCONS (XCONS (tail)->car)->car, result);
+  for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
+    result = Fcons (XCAR (XCAR (tail)), result);
 
   return result;
 }
@@ -5350,10 +5690,10 @@ Lisp_Object Qxbm;
 
 /* Keywords.  */
 
-Lisp_Object QCtype, QCdata, QCfile, QCascent, QCmargin, QCrelief;
-extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground;
+Lisp_Object QCtype, QCdata, QCascent, QCmargin, QCrelief;
+extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
 Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask;
-extern Lisp_Object QCimage;
+Lisp_Object QCindex;
 
 /* Other symbols.  */
 
@@ -5362,7 +5702,7 @@ Lisp_Object Qlaplace;
 /* Time in seconds after which images should be removed from the cache
    if not displayed.  */
 
-Lisp_Object Vimage_eviction_seconds;
+Lisp_Object Vimage_cache_eviction_delay;
 
 /* Function prototypes.  */
 
@@ -5370,8 +5710,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
@@ -5434,23 +5774,18 @@ valid_image_p (object)
 }
 
 
-/* Display an error message with format string FORMAT and argument
-   ARG.  Signaling an error, e.g. when an image cannot be loaded,
-   is not a good idea because this would interrupt redisplay, and
-   the error message display would lead to another redisplay.  This
-   function therefore simply displays a message.  */
+/* Log error message with format string FORMAT and argument ARG.
+   Signaling an error, e.g. when an image cannot be loaded, is not a
+   good idea because this would interrupt redisplay, and the error
+   message display would lead to another redisplay.  This function
+   therefore simply displays a message.  */
 
 static void
 image_error (format, arg1, arg2)
      char *format;
      Lisp_Object arg1, arg2;
 {
-  Lisp_Object args[3];
-
-  args[0] = build_string (format);
-  args[1] = arg1;
-  args[2] = arg2;
-  Fmessage (make_number (DIM (args)), args);
+  add_to_log (format, arg1, arg2);
 }
 
 
@@ -5493,10 +5828,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 *));
 
 
@@ -5504,17 +5837,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;
@@ -5545,11 +5875,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.  */
@@ -5734,8 +6060,8 @@ prepare_image_for_display (f, img)
 
   /* If IMG doesn't have a pixmap yet, load it now, using the image
      type dependent loader function.  */
-  if (img->pixmap == 0)
-    img->type->load (f, img);
+  if (img->pixmap == 0 && !img->load_failed_p)
+    img->load_failed_p = img->type->load (f, img) == 0;
 }
      
 
@@ -5807,7 +6133,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.  */
@@ -5891,14 +6217,14 @@ clear_image_cache (f, force_p)
 {
   struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
 
-  if (c && INTEGERP (Vimage_eviction_seconds))
+  if (c && INTEGERP (Vimage_cache_eviction_delay))
     {
       EMACS_TIME t;
       unsigned long old;
       int i, any_freed_p = 0;
 
       EMACS_GET_TIME (t);
-      old = EMACS_SECS (t) - XFASTINT (Vimage_eviction_seconds);
+      old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
       
       for (i = 0; i < c->used; ++i)
        {
@@ -5961,6 +6287,7 @@ lookup_image (f, spec)
   int i;
   unsigned hash;
   struct gcpro gcpro1;
+  EMACS_TIME now;
 
   /* F must be a window-system frame, and SPEC must be a valid image
      specification.  */
@@ -5980,18 +6307,15 @@ lookup_image (f, spec)
   /* If not found, create a new image and cache it.  */
   if (img == NULL)
     {
-      extern Lisp_Object QCenable, QCselect;
-      Lisp_Object tem;
-      int loading_failed_p;
-      
       img = make_image (spec, hash);
       cache_image (f, img);
-      loading_failed_p = img->type->load (f, img) == 0;
+      img->load_failed_p = img->type->load (f, img) == 0;
+      xassert (!interrupt_input_blocked);
 
       /* If we can't load the image, and we don't have a width and
         height, use some arbitrary width and height so that we can
         draw a rectangle for it.  */
-      if (loading_failed_p)
+      if (img->load_failed_p)
        {
          Lisp_Object value;
 
@@ -6032,13 +6356,14 @@ 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);
        }
     }
 
+  /* We're using IMG, so set its timestamp to `now'.  */
+  EMACS_GET_TIME (now);
+  img->timestamp = EMACS_SECS (now);
+  
   UNGCPRO;
   
   /* Value is the image id.  */
@@ -6112,9 +6437,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));
 
@@ -6123,13 +6447,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;
@@ -6147,7 +6469,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;
     }
 
@@ -6160,7 +6482,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;
     }
 
@@ -6187,7 +6509,7 @@ x_destroy_x_image (ximg)
 /* Put XImage XIMG into pixmap PIXMAP on frame F.  WIDTH and HEIGHT
    are width and height of both the image and pixmap.  */
 
-void
+static void
 x_put_x_image (f, ximg, pixmap, width, height)
      struct frame *f;
      XImage *ximg;
@@ -6249,7 +6571,6 @@ static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
 static int xbm_image_p P_ ((Lisp_Object object));
 static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
                                          unsigned char **));
-static int xbm_read_hexint P_ ((FILE *));
 
 
 /* Indices of image specification fields in xbm_format, below.  */
@@ -6342,7 +6663,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));
@@ -6548,8 +6869,6 @@ xbm_read_bitmap_file_data (file, width, height, data)
   /* Parse defines for width, height and hot-spots.  */
   while (LA1 == '#')
     {
-      char *p;
-
       match ();
       expect_ident ("define");
       expect (XBM_TK_IDENT);
@@ -6678,7 +6997,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;
     }
@@ -6724,7 +7043,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;
@@ -6760,7 +7079,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.  */
@@ -6817,7 +7136,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);
        }
 
@@ -6919,7 +7239,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
@@ -6949,8 +7269,13 @@ xpm_load (f, img)
   attrs.visual = FRAME_X_DISPLAY_INFO (f)->visual;
   attrs.valuemask |= XpmVisual;
   attrs.valuemask |= XpmReturnAllocPixels;
+#ifdef XpmAllocCloseColors
   attrs.alloc_close_colors = 1;
   attrs.valuemask |= XpmAllocCloseColors;
+#else
+  attrs.closeness = 600;
+  attrs.valuemask |= XpmCloseness;
+#endif
 
   /* If image specification contains symbolic color definitions, add
      these to `attrs'.  */
@@ -6997,7 +7322,8 @@ 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;
        }
       
@@ -7167,8 +7493,7 @@ lookup_rgb_color (f, r, g, b)
       
       BLOCK_INPUT;
       cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
-      rc = x_alloc_nearest_color (FRAME_X_DISPLAY (f), FRAME_X_SCREEN (f),
-                                 cmap, &color);
+      rc = x_alloc_nearest_color (f, cmap, &color);
       UNBLOCK_INPUT;
 
       if (rc)
@@ -7217,8 +7542,7 @@ lookup_pixel_color (f, pixel)
       cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
       color.pixel = pixel;
       XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
-      rc = x_alloc_nearest_color (FRAME_X_DISPLAY (f), FRAME_X_SCREEN (f),
-                                 cmap, &color);
+      rc = x_alloc_nearest_color (f, cmap, &color);
       UNBLOCK_INPUT;
 
       if (rc)
@@ -7355,7 +7679,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.  */
@@ -7415,28 +7739,26 @@ x_laplace (f, img)
 
 /* Build a mask for image IMG which is used on frame F.  FILE is the
    name of an image file, for error messages.  HOW determines how to
-   determine the background color of IMG.  If it is an integer, take
-   that as the pixel value of the background.  Otherwise, determine
-   the background color of IMG heuristically.  Value is non-zero
-   if successful.  */
+   determine the background color of IMG.  If it is a list '(R G B)',
+   with R, G, and B being integers >= 0, take that as the color of the
+   background.  Otherwise, determine the background color of 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;
 {
   Display *dpy = FRAME_X_DISPLAY (f);
-  Window win = FRAME_X_WINDOW (f);
   XImage *ximg, *mask_img;
-  int x, y, rc;
+  int x, y, rc, look_at_corners_p;
   unsigned long bg;
 
   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)
     {
@@ -7448,12 +7770,41 @@ x_build_heuristic_mask (f, file, img, how)
   ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
                    ~0, ZPixmap);
 
-  /* Determine the background color of ximg.  If HOW is an integer,
-     take that as a pixel color.  Otherwise, try to determine the
-     color heuristically.  */
-  if (NATNUMP (how))
-    bg = XFASTINT (how);
-  else
+  /* Determine the background color of ximg.  If HOW is `(R G B)'
+     take that as color.  Otherwise, try to determine the color
+     heuristically. */
+  look_at_corners_p = 1;
+  
+  if (CONSP (how))
+    {
+      int rgb[3], i = 0;
+
+      while (i < 3
+            && CONSP (how)
+            && NATNUMP (XCAR (how)))
+       {
+         rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
+         how = XCDR (how);
+       }
+
+      if (i == 3 && NILP (how))
+       {
+         char color_name[30];
+         XColor exact, color;
+         Colormap cmap;
+
+         sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
+         
+         cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+         if (XLookupColor (dpy, cmap, color_name, &exact, &color))
+           {
+             bg = color.pixel;
+             look_at_corners_p = 0;
+           }
+       }
+    }
+  
+  if (look_at_corners_p)
     {
       unsigned long corners[4];
       int i, best_count;
@@ -7501,7 +7852,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.  */
 
@@ -7513,6 +7864,7 @@ enum pbm_keyword_index
 {
   PBM_TYPE,
   PBM_FILE,
+  PBM_DATA,
   PBM_ASCENT,
   PBM_MARGIN,
   PBM_RELIEF,
@@ -7527,7 +7879,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},
@@ -7557,40 +7910,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;
        }
@@ -7602,6 +7958,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 
@@ -7609,50 +8001,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, value;
+  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;
@@ -7679,40 +8081,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.  */
@@ -7728,12 +8123,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)
@@ -7748,31 +8143,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.
@@ -7784,8 +8177,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);
@@ -7800,6 +8191,7 @@ pbm_load (f, img)
   img->height = height;
 
   UNGCPRO;
+  xfree (contents);
   return 1;
 }
 
@@ -7827,6 +8219,7 @@ Lisp_Object Qpng;
 enum png_keyword_index
 {
   PNG_TYPE,
+  PNG_DATA,
   PNG_FILE,
   PNG_ASCENT,
   PNG_MARGIN,
@@ -7842,7 +8235,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},
@@ -7850,7 +8244,7 @@ static struct image_keyword png_format[PNG_LAST] =
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0}
 };
 
-/* Structure describing the image type `gif'.  */
+/* Structure describing the image type `png'.  */
 
 static struct image_type png_type =
 {
@@ -7871,11 +8265,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;
 }
 
 
@@ -7902,6 +8298,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.  */
@@ -7912,12 +8337,13 @@ png_load (f, img)
      struct image *img;
 {
   Lisp_Object file, specified_file;
-  int rc, x, y, i;
+  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;
@@ -7929,36 +8355,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.  */
@@ -7966,7 +8418,7 @@ png_load (f, img)
                                    my_png_error, my_png_warning);
   if (!png_ptr)
     {
-      fclose (fp);
+      if (fp) fclose (fp);
       UNGCPRO;
       return 0;
     }
@@ -7975,7 +8427,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;
     }
@@ -7984,7 +8436,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;
     }
@@ -7998,14 +8450,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,
@@ -8041,10 +8496,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
@@ -8111,13 +8569,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;
@@ -8128,7 +8589,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);
@@ -8217,10 +8678,21 @@ png_load (f, img)
 
 #if HAVE_JPEG
 
+/* Work around a warning about HAVE_STDLIB_H being redefined in
+   jconfig.h.  */
+#ifdef HAVE_STDLIB_H
+#define HAVE_STDLIB_H_1
+#undef HAVE_STDLIB_H
+#endif /* HAVE_STLIB_H */
+
 #include <jpeglib.h>
 #include <jerror.h>
 #include <setjmp.h>
 
+#ifdef HAVE_STLIB_H_1
+#define HAVE_STDLIB_H 1
+#endif
+
 static int jpeg_image_p P_ ((Lisp_Object object));
 static int jpeg_load P_ ((struct frame *f, struct image *img));
 
@@ -8233,6 +8705,7 @@ Lisp_Object Qjpeg;
 enum jpeg_keyword_index
 {
   JPEG_TYPE,
+  JPEG_DATA,
   JPEG_FILE,
   JPEG_ASCENT,
   JPEG_MARGIN,
@@ -8248,7 +8721,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},
@@ -8278,13 +8752,16 @@ jpeg_image_p (object)
   
   bcopy (jpeg_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg, 0)
+  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
       || (fmt[JPEG_ASCENT].count 
          && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
     return 0;
-  return 1;
+
+  /* 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;
@@ -8299,6 +8776,102 @@ my_error_exit (cinfo)
   longjmp (mgr->setjmp_buffer, 1);
 }
 
+/* Init source method for JPEG data source manager.  Called by
+   jpeg_read_header() before any data is actually read.  See
+   libjpeg.doc from the JPEG lib distribution.  */
+
+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 void
+our_term_source (cinfo)
+     j_decompress_ptr cinfo;
+{
+}
+
+
+/* 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
+jpeg_memory_src (cinfo, data, len)
+     j_decompress_ptr cinfo;
+     JOCTET *data;
+     unsigned int len;
+{
+  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.  */
 
@@ -8310,37 +8883,43 @@ 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;
-  int rc, value;
+  int rc;
   unsigned long *colors;
   int width, height;
   struct gcpro gcpro1;
 
   /* 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);
   
@@ -8351,12 +8930,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;
@@ -8373,13 +8953,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;
@@ -8388,8 +8974,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);
@@ -8447,7 +9032,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);
@@ -8467,7 +9053,7 @@ jpeg_load (f, img)
 
 #if HAVE_TIFF
 
-#include <tiff34/tiffio.h>
+#include <tiffio.h>
 
 static int tiff_image_p P_ ((Lisp_Object object));
 static int tiff_load P_ ((struct frame *f, struct image *img));
@@ -8481,6 +9067,7 @@ Lisp_Object Qtiff;
 enum tiff_keyword_index
 {
   TIFF_TYPE,
+  TIFF_DATA,
   TIFF_FILE,
   TIFF_ASCENT,
   TIFF_MARGIN,
@@ -8496,7 +9083,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},
@@ -8525,14 +9113,125 @@ 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.  */
 
@@ -8542,30 +9241,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
@@ -8578,7 +9309,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;
@@ -8587,8 +9318,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);
@@ -8655,6 +9385,7 @@ Lisp_Object Qgif;
 enum gif_keyword_index
 {
   GIF_TYPE,
+  GIF_DATA,
   GIF_FILE,
   GIF_ASCENT,
   GIF_MARGIN,
@@ -8671,7 +9402,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},
@@ -8691,7 +9423,6 @@ static struct image_type gif_type =
   NULL
 };
 
-
 /* Return non-zero if OBJECT is a valid GIF image specification.  */
 
 static int
@@ -8701,11 +9432,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;
 }
 
 
@@ -8718,6 +9483,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;
@@ -8726,42 +9492,66 @@ gif_load (f, img)
   struct gcpro gcpro1;
   Lisp_Object image;
   int ino, image_left, image_top, image_width, image_height;
-  int bg;
+  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;
     }
 
-  image = image_spec_value (img->spec, QCimage, NULL);
+  image = image_spec_value (img->spec, QCindex, NULL);
   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;
@@ -8773,8 +9563,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);
@@ -8826,23 +9615,37 @@ 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};
       static int interlace_increment[] = {8, 8, 4, 2};
       int pass, inc;
+      int row = interlace_start[0];
+
+      pass = 0;
 
-      for (pass = 0; pass < 4; ++pass)
+      for (y = 0; y < image_height; y++)
        {
-         inc = interlace_increment[pass];
-         for (y = interlace_start[pass]; y < image_height; y += inc)
-           for (x = 0; x < image_width; ++x)
-             {
-               unsigned i = gif->SavedImages[ino].RasterBits[y * image_width + x];
-               XPutPixel (ximg, x + image_left, y + image_top, 
-                          pixel_colors[i]);
-             }
+         if (row >= image_height)
+           {
+             row = interlace_start[++pass];
+             while (row >= image_height)
+               row = interlace_start[++pass];
+           }
+         
+         for (x = 0; x < image_width; x++)
+           {
+             int i = raster[(y * image_width) + x];
+             XPutPixel (ximg, x + image_left, row + image_top,
+                        pixel_colors[i]);
+           }
+         
+         row += interlace_increment[pass];
        }
     }
   else
@@ -8850,7 +9653,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]);
          }
     }
@@ -8878,9 +9681,9 @@ static int gs_image_p P_ ((Lisp_Object object));
 static int gs_load P_ ((struct frame *f, struct image *img));
 static void gs_clear_image P_ ((struct frame *f, struct image *img));
 
-/* The symbol `ghostscript' identifying images of this type.  */
+/* The symbol `postscript' identifying images of this type.  */
 
-Lisp_Object Qghostscript;
+Lisp_Object Qpostscript;
 
 /* Keyword symbols.  */
 
@@ -8926,7 +9729,7 @@ static struct image_keyword gs_format[GS_LAST] =
 
 static struct image_type gs_type =
 {
-  &Qghostscript,
+  &Qpostscript,
   gs_image_p,
   gs_load,
   gs_clear_image,
@@ -8960,7 +9763,7 @@ gs_image_p (object)
   
   bcopy (gs_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, GS_LAST, Qghostscript, 1)
+  if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
       || (fmt[GS_ASCENT].count 
          && XFASTINT (fmt[GS_ASCENT].value) > 100))
     return 0;
@@ -9026,8 +9829,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;
     }
     
@@ -9139,7 +9941,7 @@ x_kill_gs_process (pixmap, f)
        }
       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;
     }
@@ -9256,106 +10058,154 @@ 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;
+  
+  cancel_busy_cursor ();
+
+  if (INTEGERP (Vbusy_cursor_delay)
+      && XINT (Vbusy_cursor_delay) > 0)
+    secs = XFASTINT (Vbusy_cursor_delay);
+  else
+    secs = DEFAULT_BUSY_CURSOR_DELAY;
+  
+  EMACS_SET_SECS_USECS (delay, secs, 0);
+  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)
     {
-      Lisp_Object rest, frame;
+      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;
+    }
 }
 
 
@@ -9388,11 +10238,10 @@ x_create_tip_frame (dpyinfo, parms)
   struct frame *f;
   Lisp_Object frame, tem;
   Lisp_Object name;
-  int minibuffer_only = 0;
   long window_prompting = 0;
   int width, height;
   int count = specpdl_ptr - specpdl;
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+  struct gcpro gcpro1, gcpro2, gcpro3;
   struct kboard *kb;
 
   check_x ();
@@ -9450,8 +10299,8 @@ x_create_tip_frame (dpyinfo, parms)
     }
 
   /* Create fontsets from `global_fontset_alist' before handling fonts.  */
-  for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCONS (tem)->cdr)
-    fs_register_fontset (f, XCONS (tem)->car);
+  for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCDR (tem))
+    fs_register_fontset (f, XCAR (tem));
 
   /* Extract the window parameters from the supplied values
      that are needed to determine window geometry.  */
@@ -9582,11 +10431,6 @@ x_create_tip_frame (dpyinfo, parms)
 
   x_make_gc (f);
 
-  /* We need to do this after creating the X window, so that the
-     icon-creation functions can say whose icon they're describing.  */
-  x_default_parameter (f, parms, Qicon_type, Qnil,
-                      "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
-
   x_default_parameter (f, parms, Qauto_raise, Qnil,
                       "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
   x_default_parameter (f, parms, Qauto_lower, Qnil,
@@ -9601,7 +10445,7 @@ x_create_tip_frame (dpyinfo, parms)
   height = f->height;
   f->height = 0;
   SET_FRAME_WIDTH (f, 0);
-  change_frame_size (f, height, width, 1, 0);
+  change_frame_size (f, height, width, 1, 0, 0);
 
   f->no_split = 1;
 
@@ -9621,32 +10465,33 @@ x_create_tip_frame (dpyinfo, parms)
 
 
 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 4, 0,
-  "Show tooltip STRING on frame FRAME.\n\
+  "Show STRING in a \"tooltip\" window on frame FRAME.\n\
+A tooltip window is a small X window displaying STRING at\n\
+the current mouse position.\n\
 FRAME nil or omitted means use the selected frame.\n\
 PARMS is an optional list of frame parameters which can be\n\
 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;
   Window root, child;
-  struct it it;
   Lisp_Object buffer;
   struct buffer *old_buffer;
   struct text_pos pos;
   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);
@@ -9710,9 +10555,8 @@ TIMEOUT nil means use the default timeout of 5 seconds.")
       if (!row->enabled_p || !row->displays_text_p)
        break;
 
-      /* Let the row go over the full width of the frame, not
-        including internal borders.  */
-      row->full_width_p = row->internal_border_p = 1;
+      /* Let the row go over the full width of the frame.  */
+      row->full_width_p = 1;
 
       /* There's a glyph at the end of rows that is use to place
         the cursor there.  Don't include the width of this glyph.  */
@@ -9754,13 +10598,14 @@ 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);
 }
 
 
 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
-  "Hide the current tooltip, if there is any.\n\
+  "Hide the current tooltip window, if there is any.\n\
 Value is t is tooltip was open, nil otherwise.")
   ()
 {
@@ -9819,7 +10664,7 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
      Lisp_Object prompt, dir, default_filename, mustmatch;
 {
   int result;
-  struct frame *f = selected_frame;
+  struct frame *f = SELECTED_FRAME ();
   Lisp_Object file = Qnil;
   Widget dialog, text, list, help;
   Arg al[10];
@@ -9987,7 +10832,7 @@ DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
   int id = -1;
   
   if (valid_image_p (spec))
-    id = lookup_image (selected_frame, spec);
+    id = lookup_image (SELECTED_FRAME (), spec);
 
   debug_print (spec);
   return make_number (id);
@@ -10070,14 +10915,19 @@ 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");
   staticpro (&Qscroll_bar_background);
+  Qscreen_gamma = intern ("screen-gamma");
+  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);
   
@@ -10142,6 +10992,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.");
+  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\
@@ -10179,12 +11034,12 @@ such a font.  This is especially effective for such large fonts as\n\
 Chinese, Japanese, and Korean.");
   Vx_pixel_size_width_font_regexp = Qnil;
 
-  DEFVAR_LISP ("image-eviction-seconds", &Vimage_eviction_seconds,
+  DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
      "Time after which cached images are removed from the cache.\n\
 When an image has not been displayed this many seconds, remove it\n\
 from the image cache.  Value must be an integer or nil with nil\n\
 meaning don't clear the cache.");
-  Vimage_eviction_seconds = make_number (30 * 60);
+  Vimage_cache_eviction_delay = make_number (30 * 60);
 
   DEFVAR_LISP ("image-types", &Vimage_types,
      "List of supported image types.\n\
@@ -10211,10 +11066,10 @@ Each element of the list is a symbol for a supported image type.");
   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);
@@ -10264,8 +11119,6 @@ Each element of the list is a symbol for a supported image type.");
   staticpro (&Qxbm);
   QCtype = intern (":type");
   staticpro (&QCtype);
-  QCfile = intern (":file");
-  staticpro (&QCfile);
   QCalgorithm = intern (":algorithm");
   staticpro (&QCalgorithm);
   QCheuristic_mask = intern (":heuristic-mask");
@@ -10280,8 +11133,8 @@ Each element of the list is a symbol for a supported image type.");
   staticpro (&QCmargin);
   QCrelief = intern (":relief");
   staticpro (&QCrelief);
-  Qghostscript = intern ("ghostscript");
-  staticpro (&Qghostscript);
+  Qpostscript = intern ("postscript");
+  staticpro (&Qpostscript);
   QCloader = intern (":loader");
   staticpro (&QCloader);
   QCbounding_box = intern (":bounding-box");
@@ -10290,6 +11143,8 @@ Each element of the list is a symbol for a supported image type.");
   staticpro (&QCpt_width);
   QCpt_height = intern (":pt-height");
   staticpro (&QCpt_height);
+  QCindex = intern (":index");
+  staticpro (&QCindex);
   Qpbm = intern ("pbm");
   staticpro (&Qpbm);
 
@@ -10325,11 +11180,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);