*** empty log message ***
[bpt/emacs.git] / src / xfns.c
index 037a0ba..cc778d8 100644 (file)
@@ -107,6 +107,14 @@ extern XFontStruct *xlwmenu_default_font;
 extern void free_frame_menubar ();
 extern double atof ();
 
+#ifdef USE_MOTIF
+
+/* LessTif/Motif version info.  */
+
+static Lisp_Object Vmotif_version_string;
+
+#endif /* USE_MOTIF */
+
 #endif /* USE_X_TOOLKIT */
 
 #define min(a,b) ((a) < (b) ? (a) : (b))
@@ -135,15 +143,15 @@ Lisp_Object Vx_resource_name;
 
 Lisp_Object Vx_resource_class;
 
-/* Non-zero means we're allowed to display a busy cursor.  */
+/* Non-zero means we're allowed to display an hourglass cursor.  */
 
-int display_busy_cursor_p;
+int display_hourglass_p;
 
 /* The background and shape of the mouse pointer, and shape when not
    over text or in the modeline.  */
 
 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
-Lisp_Object Vx_busy_pointer_shape;
+Lisp_Object Vx_hourglass_pointer_shape;
 
 /* The shape when over mouse-sensitive text.  */
 
@@ -174,41 +182,6 @@ Lisp_Object Vx_bitmap_file_path;
 
 Lisp_Object Vx_pixel_size_width_font_regexp;
 
-/* Evaluate this expression to rebuild the section of syms_of_xfns
-   that initializes and staticpros the symbols declared below.  Note
-   that Emacs 18 has a bug that keeps C-x C-e from being able to
-   evaluate this expression.
-
-(progn
-  ;; Accumulate a list of the symbols we want to initialize from the
-  ;; declarations at the top of the file.
-  (goto-char (point-min))
-  (search-forward "/\*&&& symbols declared here &&&*\/\n")
-  (let (symbol-list)
-    (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
-      (setq symbol-list
-           (cons (buffer-substring (match-beginning 1) (match-end 1))
-                 symbol-list))
-      (forward-line 1))
-    (setq symbol-list (nreverse symbol-list))
-    ;; Delete the section of syms_of_... where we initialize the symbols.
-    (search-forward "\n  /\*&&& init symbols here &&&*\/\n")
-    (let ((start (point)))
-      (while (looking-at "^  Q")
-       (forward-line 2))
-      (kill-region start (point)))
-    ;; Write a new symbol initialization section.
-    (while symbol-list
-      (insert (format "  %s = intern (\"" (car symbol-list)))
-      (let ((start (point)))
-       (insert (substring (car symbol-list) 1))
-       (subst-char-in-region start (point) ?_ ?-))
-      (insert (format "\");\n  staticpro (&%s);\n" (car symbol-list)))
-      (setq symbol-list (cdr symbol-list)))))
-
-  */        
-
-/*&&& symbols declared here &&&*/
 Lisp_Object Qauto_raise;
 Lisp_Object Qauto_lower;
 Lisp_Object Qbar;
@@ -243,7 +216,8 @@ Lisp_Object Quser_size;
 extern Lisp_Object Qdisplay;
 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
 Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
-Lisp_Object Qcompound_text;
+Lisp_Object Qcompound_text, Qcancel_timer;
+Lisp_Object Qwait_for_wm;
 
 /* The below are defined in frame.c.  */
 
@@ -356,7 +330,7 @@ x_window_to_frame (dpyinfo, wdesc)
       f = XFRAME (frame);
       if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
        continue;
-      if (f->output_data.x->busy_window == wdesc)
+      if (f->output_data.x->hourglass_window == wdesc)
        return f;
 #ifdef USE_X_TOOLKIT
       if ((f->output_data.x->edit_widget 
@@ -400,7 +374,7 @@ x_any_window_to_frame (dpyinfo, wdesc)
        {
          /* This frame matches if the window is any of its widgets.  */
          x = f->output_data.x;
-         if (x->busy_window == wdesc)
+         if (x->hourglass_window == wdesc)
            found = f;
          else if (x->widget)
            {
@@ -442,7 +416,7 @@ x_non_menubar_window_to_frame (dpyinfo, wdesc)
        continue;
       x = f->output_data.x;
       /* This frame matches if the window is any of its widgets.  */
-      if (x->busy_window == wdesc)
+      if (x->hourglass_window == wdesc)
        return f;
       else if (x->widget)
        {
@@ -755,9 +729,9 @@ static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
 static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
 static void x_change_window_heights P_ ((Lisp_Object, int));
 static void x_disable_image P_ ((struct frame *, struct image *));
-static void x_create_im P_ ((struct frame *));
 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
+static void x_set_wait_for_wm 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));
@@ -826,7 +800,8 @@ static struct x_frame_parm_table x_frame_parms[] =
   "scroll-bar-foreground",     x_set_scroll_bar_foreground,
   "scroll-bar-background",     x_set_scroll_bar_background,
   "screen-gamma",              x_set_screen_gamma,
-  "line-spacing",              x_set_line_spacing
+  "line-spacing",              x_set_line_spacing,
+  "wait-for-wm",               x_set_wait_for_wm
 };
 
 /* Attach the `x-frame-parameter' properties to
@@ -1339,8 +1314,22 @@ x_set_line_spacing (f, new_value, old_value)
 }
 
 
+/* Change the `wait-for-wm' frame parameter of frame F.  OLD_VALUE is
+   the previous value of that parameter, NEW_VALUE is the new value.
+   See also the comment of wait_for_wm in struct x_output.  */
+
+static void
+x_set_wait_for_wm (f, new_value, old_value)
+     struct frame *f;
+     Lisp_Object new_value, old_value;
+{
+  f->output_data.x->wait_for_wm = !NILP (new_value);
+}
+
+
 /* Change the `screen-gamma' frame parameter of frame F.  OLD_VALUE is
-   the previous value of that parameter, NEW_VALUE is the new value.  */
+   the previous value of that parameter, NEW_VALUE is the new
+   value.  */
 
 static void
 x_set_screen_gamma (f, new_value, old_value)
@@ -1373,24 +1362,37 @@ x_set_foreground_color (f, arg, oldval)
      struct frame *f;
      Lisp_Object arg, oldval;
 {
-  unsigned long pixel
-    = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+  struct x_output *x = f->output_data.x;
+  unsigned long fg, old_fg;
 
-  unload_color (f, f->output_data.x->foreground_pixel);
-  f->output_data.x->foreground_pixel = pixel;
+  fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+  old_fg = x->foreground_pixel;
+  x->foreground_pixel = fg;
 
   if (FRAME_X_WINDOW (f) != 0)
     {
+      Display *dpy = FRAME_X_DISPLAY (f);
+      
       BLOCK_INPUT;
-      XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
-                     f->output_data.x->foreground_pixel);
-      XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
-                     f->output_data.x->foreground_pixel);
+      XSetForeground (dpy, x->normal_gc, fg);
+      XSetBackground (dpy, x->reverse_gc, fg);
+
+      if (x->cursor_pixel == old_fg)
+       {
+         unload_color (f, x->cursor_pixel);
+         x->cursor_pixel = x_copy_color (f, fg);
+         XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
+       }
+      
       UNBLOCK_INPUT;
+      
       update_face_from_frame_parameter (f, Qforeground_color, arg);
+      
       if (FRAME_VISIBLE_P (f))
         redraw_frame (f);
     }
+      
+  unload_color (f, old_fg);
 }
 
 void
@@ -1398,34 +1400,38 @@ x_set_background_color (f, arg, oldval)
      struct frame *f;
      Lisp_Object arg, oldval;
 {
-  unsigned long pixel
-    = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
+  struct x_output *x = f->output_data.x;
+  unsigned long bg;
 
-  unload_color (f, f->output_data.x->background_pixel);
-  f->output_data.x->background_pixel = pixel;
+  bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
+  unload_color (f, x->background_pixel);
+  x->background_pixel = bg;
 
   if (FRAME_X_WINDOW (f) != 0)
     {
+      Display *dpy = FRAME_X_DISPLAY (f);
+      
       BLOCK_INPUT;
-      /* The main frame area.  */
-      XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
-                     f->output_data.x->background_pixel);
-      XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
-                     f->output_data.x->background_pixel);
-      XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
-                     f->output_data.x->background_pixel);
-      XSetWindowBackground (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                           f->output_data.x->background_pixel);
+      XSetBackground (dpy, x->normal_gc, bg);
+      XSetForeground (dpy, x->reverse_gc, bg);
+      XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
+      XSetForeground (dpy, x->cursor_gc, bg);
+
+#ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
+                                  toolkit scroll bars.  */
       {
        Lisp_Object bar;
-       for (bar = FRAME_SCROLL_BARS (f); !NILP (bar);
+       for (bar = FRAME_SCROLL_BARS (f);
+            !NILP (bar);
             bar = XSCROLL_BAR (bar)->next)
-         XSetWindowBackground (FRAME_X_DISPLAY (f),
-                               SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
-                               f->output_data.x->background_pixel);
+         {
+           Window window = SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar));
+           XSetWindowBackground (dpy, window, bg);
+         }
       }
-      UNBLOCK_INPUT;
+#endif /* USE_TOOLKIT_SCROLL_BARS */
 
+      UNBLOCK_INPUT;
       update_face_from_frame_parameter (f, Qbackground_color, arg);
 
       if (FRAME_VISIBLE_P (f))
@@ -1438,146 +1444,141 @@ x_set_mouse_color (f, arg, oldval)
      struct frame *f;
      Lisp_Object arg, oldval;
 {
+  struct x_output *x = f->output_data.x;
+  Display *dpy = FRAME_X_DISPLAY (f);
   Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
-  Cursor busy_cursor, horizontal_drag_cursor;
+  Cursor hourglass_cursor, horizontal_drag_cursor;
   int count;
   unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
-  unsigned long mask_color = f->output_data.x->background_pixel;
+  unsigned long mask_color = x->background_pixel;
 
   /* Don't let pointers be invisible.  */
-  if (mask_color == pixel
-      && mask_color == f->output_data.x->background_pixel)
-    pixel = f->output_data.x->foreground_pixel;
+  if (mask_color == pixel)
+    {
+      x_free_colors (f, &pixel, 1);
+      pixel = x_copy_color (f, x->foreground_pixel);
+    }
 
-  unload_color (f, f->output_data.x->mouse_pixel);
-  f->output_data.x->mouse_pixel = pixel;
+  unload_color (f, x->mouse_pixel);
+  x->mouse_pixel = pixel;
 
   BLOCK_INPUT;
 
   /* It's not okay to crash if the user selects a screwy cursor.  */
-  count = x_catch_errors (FRAME_X_DISPLAY (f));
+  count = x_catch_errors (dpy);
 
-  if (!EQ (Qnil, Vx_pointer_shape))
+  if (!NILP (Vx_pointer_shape))
     {
       CHECK_NUMBER (Vx_pointer_shape, 0);
-      cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XINT (Vx_pointer_shape));
+      cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
     }
   else
-    cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
-  x_check_errors (FRAME_X_DISPLAY (f), "bad text pointer cursor: %s");
+    cursor = XCreateFontCursor (dpy, XC_xterm);
+  x_check_errors (dpy, "bad text pointer cursor: %s");
 
-  if (!EQ (Qnil, Vx_nontext_pointer_shape))
+  if (!NILP (Vx_nontext_pointer_shape))
     {
       CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
-      nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
-                                         XINT (Vx_nontext_pointer_shape));
+      nontext_cursor
+       = XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
     }
   else
-    nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_left_ptr);
-  x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
+    nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
+  x_check_errors (dpy, "bad nontext pointer cursor: %s");
 
-  if (!EQ (Qnil, Vx_busy_pointer_shape))
+  if (!NILP (Vx_hourglass_pointer_shape))
     {
-      CHECK_NUMBER (Vx_busy_pointer_shape, 0);
-      busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
-                                      XINT (Vx_busy_pointer_shape));
+      CHECK_NUMBER (Vx_hourglass_pointer_shape, 0);
+      hourglass_cursor
+       = XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
     }
   else
-    busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_watch);
-  x_check_errors (FRAME_X_DISPLAY (f), "bad busy pointer cursor: %s");
+    hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
+  x_check_errors (dpy, "bad hourglass pointer cursor: %s");
   
-  x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
-  if (!EQ (Qnil, Vx_mode_pointer_shape))
+  x_check_errors (dpy, "bad nontext pointer cursor: %s");
+  if (!NILP (Vx_mode_pointer_shape))
     {
       CHECK_NUMBER (Vx_mode_pointer_shape, 0);
-      mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
-                                      XINT (Vx_mode_pointer_shape));
+      mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
     }
   else
-    mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm);
-  x_check_errors (FRAME_X_DISPLAY (f), "bad modeline pointer cursor: %s");
+    mode_cursor = XCreateFontCursor (dpy, XC_xterm);
+  x_check_errors (dpy, "bad modeline pointer cursor: %s");
 
-  if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
+  if (!NILP (Vx_sensitive_text_pointer_shape))
     {
       CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
       cross_cursor
-       = XCreateFontCursor (FRAME_X_DISPLAY (f),
-                            XINT (Vx_sensitive_text_pointer_shape));
+       = XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
     }
   else
-    cross_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_crosshair);
+    cross_cursor = XCreateFontCursor (dpy, XC_crosshair);
 
   if (!NILP (Vx_window_horizontal_drag_shape))
     {
       CHECK_NUMBER (Vx_window_horizontal_drag_shape, 0);
       horizontal_drag_cursor
-       = XCreateFontCursor (FRAME_X_DISPLAY (f),
-                            XINT (Vx_window_horizontal_drag_shape));
+       = XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
     }
   else
     horizontal_drag_cursor
-      = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow);
+      = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
 
   /* Check and report errors with the above calls.  */
-  x_check_errors (FRAME_X_DISPLAY (f), "can't set cursor shape: %s");
-  x_uncatch_errors (FRAME_X_DISPLAY (f), count);
+  x_check_errors (dpy, "can't set cursor shape: %s");
+  x_uncatch_errors (dpy, count);
 
   {
     XColor fore_color, back_color;
 
-    fore_color.pixel = f->output_data.x->mouse_pixel;
+    fore_color.pixel = x->mouse_pixel;
     x_query_color (f, &fore_color);
     back_color.pixel = mask_color;
     x_query_color (f, &back_color);
     
-    XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
-                   &fore_color, &back_color);
-    XRecolorCursor (FRAME_X_DISPLAY (f), nontext_cursor,
-                   &fore_color, &back_color);
-    XRecolorCursor (FRAME_X_DISPLAY (f), mode_cursor,
-                   &fore_color, &back_color);
-    XRecolorCursor (FRAME_X_DISPLAY (f), cross_cursor,
-                   &fore_color, &back_color);
-    XRecolorCursor (FRAME_X_DISPLAY (f), busy_cursor,
-                    &fore_color, &back_color);
-    XRecolorCursor (FRAME_X_DISPLAY (f), horizontal_drag_cursor,
-                    &fore_color, &back_color);
+    XRecolorCursor (dpy, cursor, &fore_color, &back_color);
+    XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
+    XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
+    XRecolorCursor (dpy, cross_cursor, &fore_color, &back_color);
+    XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
+    XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
   }
 
   if (FRAME_X_WINDOW (f) != 0)
-    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
-
-  if (cursor != f->output_data.x->text_cursor
-      && f->output_data.x->text_cursor != 0)
-    XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
-  f->output_data.x->text_cursor = cursor;
-
-  if (nontext_cursor != f->output_data.x->nontext_cursor
-      && f->output_data.x->nontext_cursor != 0)
-    XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
-  f->output_data.x->nontext_cursor = nontext_cursor;
-
-  if (busy_cursor != f->output_data.x->busy_cursor
-      && f->output_data.x->busy_cursor != 0)
-    XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->busy_cursor);
-  f->output_data.x->busy_cursor = busy_cursor;
-
-  if (mode_cursor != f->output_data.x->modeline_cursor
-      && f->output_data.x->modeline_cursor != 0)
-    XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
-  f->output_data.x->modeline_cursor = mode_cursor;
-  
-  if (cross_cursor != f->output_data.x->cross_cursor
-      && f->output_data.x->cross_cursor != 0)
-    XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->cross_cursor);
-  f->output_data.x->cross_cursor = cross_cursor;
-
-  if (horizontal_drag_cursor != f->output_data.x->horizontal_drag_cursor
-      && f->output_data.x->horizontal_drag_cursor != 0)
-    XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->horizontal_drag_cursor);
-  f->output_data.x->horizontal_drag_cursor = horizontal_drag_cursor;
+    XDefineCursor (dpy, FRAME_X_WINDOW (f), cursor);
+
+  if (cursor != x->text_cursor
+      && x->text_cursor != 0)
+    XFreeCursor (dpy, x->text_cursor);
+  x->text_cursor = cursor;
+
+  if (nontext_cursor != x->nontext_cursor
+      && x->nontext_cursor != 0)
+    XFreeCursor (dpy, x->nontext_cursor);
+  x->nontext_cursor = nontext_cursor;
+
+  if (hourglass_cursor != x->hourglass_cursor
+      && x->hourglass_cursor != 0)
+    XFreeCursor (dpy, x->hourglass_cursor);
+  x->hourglass_cursor = hourglass_cursor;
+
+  if (mode_cursor != x->modeline_cursor
+      && x->modeline_cursor != 0)
+    XFreeCursor (dpy, f->output_data.x->modeline_cursor);
+  x->modeline_cursor = mode_cursor;
+  
+  if (cross_cursor != x->cross_cursor
+      && x->cross_cursor != 0)
+    XFreeCursor (dpy, x->cross_cursor);
+  x->cross_cursor = cross_cursor;
 
-  XFlush (FRAME_X_DISPLAY (f));
+  if (horizontal_drag_cursor != x->horizontal_drag_cursor
+      && x->horizontal_drag_cursor != 0)
+    XFreeCursor (dpy, x->horizontal_drag_cursor);
+  x->horizontal_drag_cursor = horizontal_drag_cursor;
+
+  XFlush (dpy);
   UNBLOCK_INPUT;
 
   update_face_from_frame_parameter (f, Qmouse_color, arg);
@@ -1590,6 +1591,7 @@ x_set_cursor_color (f, arg, oldval)
 {
   unsigned long fore_pixel, pixel;
   int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
+  struct x_output *x = f->output_data.x;
 
   if (!NILP (Vx_cursor_fore_pixel))
     {
@@ -1598,13 +1600,13 @@ x_set_cursor_color (f, arg, oldval)
       fore_pixel_allocated_p = 1;
     }
   else
-    fore_pixel = f->output_data.x->background_pixel;
+    fore_pixel = x->background_pixel;
   
   pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
   pixel_allocated_p = 1;
 
   /* Make sure that the cursor color differs from the background color.  */
-  if (pixel == f->output_data.x->background_pixel)
+  if (pixel == x->background_pixel)
     {
       if (pixel_allocated_p)
        {
@@ -1612,7 +1614,7 @@ x_set_cursor_color (f, arg, oldval)
          pixel_allocated_p = 0;
        }
       
-      pixel = f->output_data.x->mouse_pixel;
+      pixel = x->mouse_pixel;
       if (pixel == fore_pixel)
        {
          if (fore_pixel_allocated_p)
@@ -1620,27 +1622,25 @@ x_set_cursor_color (f, arg, oldval)
              x_free_colors (f, &fore_pixel, 1);
              fore_pixel_allocated_p = 0;
            }
-         fore_pixel = f->output_data.x->background_pixel;
+         fore_pixel = x->background_pixel;
        }
     }
 
-  unload_color (f, f->output_data.x->cursor_foreground_pixel);
+  unload_color (f, x->cursor_foreground_pixel);
   if (!fore_pixel_allocated_p)
     fore_pixel = x_copy_color (f, fore_pixel);
-  f->output_data.x->cursor_foreground_pixel = fore_pixel;
+  x->cursor_foreground_pixel = fore_pixel;
 
-  unload_color (f, f->output_data.x->cursor_pixel);
+  unload_color (f, x->cursor_pixel);
   if (!pixel_allocated_p)
     pixel = x_copy_color (f, pixel);
-  f->output_data.x->cursor_pixel = pixel;
+  x->cursor_pixel = pixel;
 
   if (FRAME_X_WINDOW (f) != 0)
     {
       BLOCK_INPUT;
-      XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
-                     f->output_data.x->cursor_pixel);
-      XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
-                     fore_pixel);
+      XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
+      XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
       UNBLOCK_INPUT;
 
       if (FRAME_VISIBLE_P (f))
@@ -1848,6 +1848,7 @@ x_set_font (f, arg, oldval)
   Lisp_Object result;
   Lisp_Object fontset_name;
   Lisp_Object frame;
+  int old_fontset = f->output_data.x->fontset;
 
   CHECK_STRING (arg, 1);
 
@@ -1865,6 +1866,16 @@ x_set_font (f, arg, oldval)
     error ("The characters of the given font have varying widths");
   else if (STRINGP (result))
     {
+      if (STRINGP (fontset_name))
+       {
+         /* Fontset names are built from ASCII font names, so the
+            names may be equal despite there was a change.  */
+         if (old_fontset == f->output_data.x->fontset)
+           return;
+       }
+      else if (!NILP (Fequal (result, oldval)))
+       return;
+      
       store_frame_param (f, Qfont, result);
       recompute_basic_faces (f);
     }
@@ -2039,6 +2050,10 @@ x_set_tool_bar_lines (f, value, oldval)
   int delta, nlines, root_height;
   Lisp_Object root_window;
 
+  /* Treat tool bars like menu bars.  */
+  if (FRAME_MINIBUF_ONLY_P (f))
+    return;
+
   /* Use VALUE only if an integer >= 0.  */
   if (INTEGERP (value) && XINT (value) >= 0)
     nlines = XFASTINT (value);
@@ -2087,9 +2102,12 @@ x_set_tool_bar_lines (f, value, oldval)
       int y = nlines * CANON_Y_UNIT (f);
 
       BLOCK_INPUT;
-      XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 0, y, width, height, False);
+      x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                   0, y, width, height, False);
       UNBLOCK_INPUT;
+
+      if (WINDOWP (f->tool_bar_window))
+       clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
     }
 }
 
@@ -3306,6 +3324,8 @@ best_xim_style (user, xim)
 
 /* Create XIC for frame F. */
 
+static XIMStyle xic_style;
+
 void
 create_frame_xic (f)
      struct frame *f;
@@ -3313,7 +3333,6 @@ create_frame_xic (f)
   XIM xim;
   XIC xic = NULL;
   XFontSet xfs = NULL;
-  static XIMStyle xic_style;
 
   if (FRAME_XIC (f))
     return;
@@ -3985,8 +4004,7 @@ x_make_gc (f)
        gray_bits, gray_width, gray_height,
        f->output_data.x->foreground_pixel,
        f->output_data.x->background_pixel,
-       DefaultDepth (FRAME_X_DISPLAY (f),
-                     XScreenNumberOfScreen (FRAME_X_SCREEN (f)))));
+       DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
 
   UNBLOCK_INPUT;
 }
@@ -4171,6 +4189,16 @@ This function is an internal primitive--use `make-frame' instead.")
   {
     Lisp_Object black;
     struct gcpro gcpro1;
+
+    /* Function x_decode_color can signal an error.  Make
+       sure to initialize color slots so that we won't try
+       to free colors we haven't allocated.  */
+    f->output_data.x->foreground_pixel = -1;
+    f->output_data.x->background_pixel = -1;
+    f->output_data.x->cursor_pixel = -1;
+    f->output_data.x->cursor_foreground_pixel = -1;
+    f->output_data.x->border_pixel = -1;
+    f->output_data.x->mouse_pixel = -1;
     
     black = build_string ("black");
     GCPRO1 (black);
@@ -4326,8 +4354,40 @@ This function is an internal primitive--use `make-frame' instead.")
                       RES_TYPE_SYMBOL);
   x_default_parameter (f, parms, Qtitle, Qnil,
                       "title", "Title", RES_TYPE_STRING);
+  x_default_parameter (f, parms, Qwait_for_wm, Qt,
+                      "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
 
   f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_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 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 tool-bar
+     will get.  */
+  if (FRAME_TOOL_BAR_LINES (f))
+    {
+      int margin, relief, bar_height;
+      
+      relief = (tool_bar_button_relief > 0
+               ? tool_bar_button_relief
+               : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
+
+      if (INTEGERP (Vtool_bar_button_margin)
+         && XINT (Vtool_bar_button_margin) > 0)
+       margin = XFASTINT (Vtool_bar_button_margin);
+      else if (CONSP (Vtool_bar_button_margin)
+              && INTEGERP (XCDR (Vtool_bar_button_margin))
+              && XINT (XCDR (Vtool_bar_button_margin)) > 0)
+       margin = XFASTINT (XCDR (Vtool_bar_button_margin));
+      else
+       margin = 0;
+         
+      bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
+      f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
+    }
+
+  /* Compute the size of the X window.  */
   window_prompting = x_figure_window_size (f, parms);
 
   if (window_prompting & XNegative)
@@ -4350,14 +4410,7 @@ This function is an internal primitive--use `make-frame' instead.")
   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 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 tool-bar will get.  */
-  f->height += FRAME_TOOL_BAR_LINES (f);
-
+  /* Create the X widget or window.  */
 #ifdef USE_X_TOOLKIT
   x_window (f, window_prompting, minibuffer_only);
 #else
@@ -4391,6 +4444,7 @@ This function is an internal primitive--use `make-frame' instead.")
      f->height.  */
   width = f->width;
   height = f->height;
+  
   f->height = 0;
   SET_FRAME_WIDTH (f, 0);
   change_frame_size (f, height, width, 1, 0, 0);
@@ -4447,6 +4501,11 @@ This function is an internal primitive--use `make-frame' instead.")
     }
 
   UNGCPRO;
+
+  /* Make sure windows on this frame appear in calls to next-window
+     and similar functions.  */
+  Vwindow_list = Qnil;
+  
   return unbind_to (count, frame);
 }
 
@@ -5194,7 +5253,7 @@ Lisp_Object Qxbm;
 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
 extern Lisp_Object QCdata;
 Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
-Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask;
+Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
 
 /* Other symbols.  */
@@ -5266,11 +5325,22 @@ valid_image_p (object)
   
   if (CONSP (object) && EQ (XCAR (object), Qimage))
     {
-      Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
-      struct image_type *type = lookup_image_type (symbol);
-      
-      if (type)
-       valid_p = type->valid_p (object);
+      Lisp_Object tem;
+
+      for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
+       if (EQ (XCAR (tem), QCtype))
+         {
+           tem = XCDR (tem);
+           if (CONSP (tem) && SYMBOLP (XCAR (tem)))
+             {
+               struct image_type *type;
+               type = lookup_image_type (XCAR (tem));
+               if (type)
+                 valid_p = type->valid_p (object);
+             }
+           
+           break;
+         }
     }
 
   return valid_p;
@@ -5301,8 +5371,10 @@ enum image_value_type
 {
   IMAGE_DONT_CHECK_VALUE_TYPE,
   IMAGE_STRING_VALUE,
+  IMAGE_STRING_OR_NIL_VALUE,
   IMAGE_SYMBOL_VALUE,
   IMAGE_POSITIVE_INTEGER_VALUE,
+  IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
   IMAGE_NON_NEGATIVE_INTEGER_VALUE,
   IMAGE_ASCENT_VALUE,
   IMAGE_INTEGER_VALUE,
@@ -5397,6 +5469,11 @@ parse_image_spec (spec, keywords, nkeywords, type)
            return 0;
          break;
 
+       case IMAGE_STRING_OR_NIL_VALUE:
+         if (!STRINGP (value) && !NILP (value))
+           return 0;
+         break;
+
        case IMAGE_SYMBOL_VALUE:
          if (!SYMBOLP (value))
            return 0;
@@ -5407,6 +5484,15 @@ parse_image_spec (spec, keywords, nkeywords, type)
            return 0;
          break;
 
+       case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
+         if (INTEGERP (value) && XINT (value) >= 0)
+           break;
+         if (CONSP (value)
+             && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
+             && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
+           break;
+         return 0;
+
        case IMAGE_ASCENT_VALUE:
          if (SYMBOLP (value) && EQ (value, Qcenter))
            break;
@@ -5513,8 +5599,8 @@ or omitted means use the selected frame.")
       struct frame *f = check_x_frame (frame);
       int id = lookup_image (f, spec);
       struct image *img = IMAGE_FROM_ID (f, id);
-      int width = img->width + 2 * img->margin;
-      int height = img->height + 2 * img->margin;
+      int width = img->width + 2 * img->hmargin;
+      int height = img->height + 2 * img->vmargin;
   
       if (NILP (pixels))
        size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
@@ -5643,7 +5729,7 @@ image_ascent (img, face)
      struct image *img;
      struct face *face;
 {
-  int height = img->height + img->margin;
+  int height = img->height + img->vmargin;
   int ascent;
 
   if (img->ascent == CENTERED_IMAGE_ASCENT)
@@ -5765,6 +5851,7 @@ x_alloc_image_color (f, img, color_name, dflt)
  ***********************************************************************/
 
 static void cache_image P_ ((struct frame *f, struct image *img));
+static void postprocess_image P_ ((struct frame *, struct image *));
 
 
 /* Return a new, initialized image cache that is allocated from the
@@ -5896,6 +5983,81 @@ FRAME t means clear the image caches of all frames.")
 }
 
 
+/* Compute masks and transform image IMG on frame F, as specified
+   by the image's specification,  */
+
+static void
+postprocess_image (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  /* Manipulation of the image's mask.  */
+  if (img->pixmap)
+    {
+      Lisp_Object conversion, spec;
+      Lisp_Object mask;
+
+      spec = img->spec;
+      
+      /* `:heuristic-mask t'
+        `:mask heuristic'
+        means build a mask heuristically.
+        `:heuristic-mask (R G B)'
+        `:mask (heuristic (R G B))'
+        means build a mask from color (R G B) in the
+        image.
+        `:mask nil'
+        means remove a mask, if any.  */
+             
+      mask = image_spec_value (spec, QCheuristic_mask, NULL);
+      if (!NILP (mask))
+       x_build_heuristic_mask (f, img, mask);
+      else
+       {
+         int found_p;
+                   
+         mask = image_spec_value (spec, QCmask, &found_p);
+                 
+         if (EQ (mask, Qheuristic))
+           x_build_heuristic_mask (f, img, Qt);
+         else if (CONSP (mask)
+                  && EQ (XCAR (mask), Qheuristic))
+           {
+             if (CONSP (XCDR (mask)))
+               x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
+             else
+               x_build_heuristic_mask (f, img, XCDR (mask));
+           }
+         else if (NILP (mask) && found_p && img->mask)
+           {
+             XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
+             img->mask = None;
+           }
+       }
+         
+      /* Should we apply an image transformation algorithm?  */
+      conversion = image_spec_value (spec, QCconversion, NULL);
+      if (EQ (conversion, Qdisabled))
+       x_disable_image (f, img);
+      else if (EQ (conversion, Qlaplace))
+       x_laplace (f, img);
+      else if (EQ (conversion, Qemboss))
+       x_emboss (f, img);
+      else if (CONSP (conversion)
+              && EQ (XCAR (conversion), Qedge_detection))
+       {
+         Lisp_Object tem;
+         tem = XCDR (conversion);
+         if (CONSP (tem))
+           x_edge_detection (f, img,
+                             Fplist_get (tem, QCmatrix),
+                             Fplist_get (tem, QCcolor_adjustment));
+       }
+    }
+}
+
+
 /* Return the id of image with Lisp specification SPEC on frame F.
    SPEC must be a valid Lisp image specification (see valid_image_p).  */
 
@@ -5929,6 +6091,8 @@ lookup_image (f, spec)
   /* If not found, create a new image and cache it.  */
   if (img == NULL)
     {
+      extern Lisp_Object Qpostscript;
+      
       BLOCK_INPUT;
       img = make_image (spec, hash);
       cache_image (f, img);
@@ -5962,80 +6126,28 @@ lookup_image (f, spec)
          
          margin = image_spec_value (spec, QCmargin, NULL);
          if (INTEGERP (margin) && XINT (margin) >= 0)
-           img->margin = XFASTINT (margin);
+           img->vmargin = img->hmargin = XFASTINT (margin);
+         else if (CONSP (margin) && INTEGERP (XCAR (margin))
+                  && INTEGERP (XCDR (margin)))
+           {
+             if (XINT (XCAR (margin)) > 0)
+               img->hmargin = XFASTINT (XCAR (margin));
+             if (XINT (XCDR (margin)) > 0)
+               img->vmargin = XFASTINT (XCDR (margin));
+           }
          
          relief = image_spec_value (spec, QCrelief, NULL);
          if (INTEGERP (relief))
            {
              img->relief = XINT (relief);
-             img->margin += abs (img->relief);
+             img->hmargin += abs (img->relief);
+             img->vmargin += abs (img->relief);
            }
 
-         /* Manipulation of the image's mask.  */
-         if (img->pixmap)
-           {
-             /* `:heuristic-mask t'
-                `:mask heuristic'
-                       means build a mask heuristically.
-                `:heuristic-mask (R G B)'
-                `:mask (heuristic (R G B))'
-                       means build a mask from color (R G B) in the
-                       image.
-                `:mask nil'
-                       means remove a mask, if any.  */
-             
-             Lisp_Object mask;
-
-             mask = image_spec_value (spec, QCheuristic_mask, NULL);
-             if (!NILP (mask))
-               x_build_heuristic_mask (f, img, mask);
-             else
-               {
-                 int found_p;
-                   
-                 mask = image_spec_value (spec, QCmask, &found_p);
-                 
-                 if (EQ (mask, Qheuristic))
-                   x_build_heuristic_mask (f, img, Qt);
-                 else if (CONSP (mask)
-                          && EQ (XCAR (mask), Qheuristic))
-                   {
-                     if (CONSP (XCDR (mask)))
-                       x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
-                     else
-                       x_build_heuristic_mask (f, img, XCDR (mask));
-                   }
-                 else if (NILP (mask) && found_p && img->mask)
-                   {
-                     XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
-                     img->mask = None;
-                   }
-               }
-           }
-         
-         /* Should we apply an image transformation algorithm?  */
-         if (img->pixmap)
-           {
-             Lisp_Object algorithm;
-
-             algorithm = image_spec_value (spec, QCalgorithm, NULL);
-             if (EQ (algorithm, Qdisabled))
-               x_disable_image (f, img);
-             else if (EQ (algorithm, Qlaplace))
-               x_laplace (f, img);
-             else if (EQ (algorithm, Qemboss))
-               x_emboss (f, img);
-             else if (CONSP (algorithm)
-                      && EQ (XCAR (algorithm), Qedge_detection))
-               {
-                 Lisp_Object tem;
-                 tem = XCDR (algorithm);
-                 if (CONSP (tem))
-                   x_edge_detection (f, img,
-                                     Fplist_get (tem, QCmatrix),
-                                     Fplist_get (tem, QCcolor_adjustment));
-               }
-           }
+         /* Do image transformations and compute masks, unless we
+            don't have the image yet.  */
+         if (!EQ (*img->type->type, Qpostscript))
+           postprocess_image (f, img);
        }
 
       UNBLOCK_INPUT;
@@ -6325,12 +6437,12 @@ static struct image_keyword xbm_format[XBM_LAST] =
   {":width",           IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":height",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":data",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":foreground",      IMAGE_STRING_VALUE,                     0},
-  {":background",      IMAGE_STRING_VALUE,                     0},
+  {":foreground",      IMAGE_STRING_OR_NIL_VALUE,              0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
+  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
-  {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
 };
@@ -6860,10 +6972,12 @@ xbm_load (f, img)
        }
 
       /* Get foreground and background colors, maybe allocate colors.  */
-      if (fmt[XBM_FOREGROUND].count)
+      if (fmt[XBM_FOREGROUND].count
+         && STRINGP (fmt[XBM_FOREGROUND].value))
        foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
                                          foreground);
-      if (fmt[XBM_BACKGROUND].count)
+      if (fmt[XBM_BACKGROUND].count
+         && STRINGP (fmt[XBM_BACKGROUND].value))
        background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
                                          background);
 
@@ -6961,9 +7075,9 @@ static struct image_keyword xpm_format[XPM_LAST] =
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
+  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
-  {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":color-symbols",   IMAGE_DONT_CHECK_VALUE_TYPE,            0}
@@ -7591,7 +7705,7 @@ static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
 
-/* Non-zero means draw a cross on images having `:algorithm
+/* Non-zero means draw a cross on images having `:conversion
    disabled'.  */
 
 int cross_disabled_images;
@@ -8046,13 +8160,13 @@ static struct image_keyword pbm_format[PBM_LAST] =
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
+  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
-  {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":foreground",      IMAGE_STRING_VALUE,                     0},
-  {":background",      IMAGE_STRING_VALUE,                     0}
+  {":foreground",      IMAGE_STRING_OR_NIL_VALUE,              0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
 /* Structure describing the image type `pbm'.  */
@@ -8250,9 +8364,11 @@ pbm_load (f, img)
       parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
       
       /* Get foreground and background colors, maybe allocate colors.  */
-      if (fmt[PBM_FOREGROUND].count)
+      if (fmt[PBM_FOREGROUND].count
+         && STRINGP (fmt[PBM_FOREGROUND].value))
        fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
-      if (fmt[PBM_BACKGROUND].count)
+      if (fmt[PBM_BACKGROUND].count
+         && STRINGP (fmt[PBM_BACKGROUND].value))
        bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
       
       for (y = 0; y < height; ++y)
@@ -8373,9 +8489,9 @@ static struct image_keyword png_format[PNG_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
+  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
-  {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
 };
@@ -8850,9 +8966,9 @@ static struct image_keyword jpeg_format[JPEG_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
+  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
-  {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":conversions",     IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
 };
@@ -9205,9 +9321,9 @@ static struct image_keyword tiff_format[TIFF_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
+  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
-  {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":conversions",     IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
 };
@@ -9528,9 +9644,9 @@ static struct image_keyword gif_format[GIF_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
+  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
-  {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":image",           IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0}
@@ -9841,9 +9957,9 @@ static struct image_keyword gs_format[GS_LAST] =
   {":loader",          IMAGE_FUNCTION_VALUE,                   0},
   {":bounding-box",    IMAGE_DONT_CHECK_VALUE_TYPE,            1},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
+  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
-  {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
 };
@@ -10001,9 +10117,13 @@ x_kill_gs_process (pixmap, f)
     if (c->images[i]->pixmap == pixmap)
       break;
 
+  /* Should someone in between have cleared the image cache, for
+     instance, give up.  */
+  if (i == c->used)
+    return;
+  
   /* Kill the GS process.  We should have found PIXMAP in the image
      cache and its image should contain a process object.  */
-  xassert (i < c->used);
   img = c->images[i];
   xassert (PROCESSP (img->data.lisp_val));
   Fkill_process (img->data.lisp_val, Qnil);
@@ -10060,6 +10180,12 @@ x_kill_gs_process (pixmap, f)
       
       UNBLOCK_INPUT;
     }
+
+  /* Now that we have the pixmap, compute mask and transform the
+     image if requested.  */
+  BLOCK_INPUT;
+  postprocess_image (f, img);
+  UNBLOCK_INPUT;
 }
 
 
@@ -10157,7 +10283,7 @@ value.")
                               &actual_type, &actual_format, 
                               &actual_size, &bytes_remaining, 
                               (unsigned char **) &tmp_data);
-      if (rc == Success)
+      if (rc == Success && tmp_data)
        prop_value = make_string (tmp_data, size);
 
       XFree (tmp_data);
@@ -10174,94 +10300,94 @@ value.")
  ***********************************************************************/
 
 /* If non-null, an asynchronous timer that, when it expires, displays
-   a busy cursor on all frames.  */
+   an hourglass cursor on all frames.  */
 
-static struct atimer *busy_cursor_atimer;
+static struct atimer *hourglass_atimer;
 
-/* Non-zero means a busy cursor is currently shown.  */
+/* Non-zero means an hourglass cursor is currently shown.  */
 
-static int busy_cursor_shown_p;
+static int hourglass_shown_p;
 
-/* Number of seconds to wait before displaying a busy cursor.  */
+/* Number of seconds to wait before displaying an hourglass cursor.  */
 
-static Lisp_Object Vbusy_cursor_delay;
+static Lisp_Object Vhourglass_delay;
 
-/* Default number of seconds to wait before displaying a busy
+/* Default number of seconds to wait before displaying an hourglass
    cursor.  */
 
-#define DEFAULT_BUSY_CURSOR_DELAY 1
+#define DEFAULT_HOURGLASS_DELAY 1
 
 /* Function prototypes.  */
 
-static void show_busy_cursor P_ ((struct atimer *));
-static void hide_busy_cursor P_ ((void));
+static void show_hourglass P_ ((struct atimer *));
+static void hide_hourglass P_ ((void));
 
 
-/* Cancel a currently active busy-cursor timer, and start a new one.  */
+/* Cancel a currently active hourglass timer, and start a new one.  */
 
 void
-start_busy_cursor ()
+start_hourglass ()
 {
   EMACS_TIME delay;
   int secs, usecs = 0;
   
-  cancel_busy_cursor ();
+  cancel_hourglass ();
 
-  if (INTEGERP (Vbusy_cursor_delay)
-      && XINT (Vbusy_cursor_delay) > 0)
-    secs = XFASTINT (Vbusy_cursor_delay);
-  else if (FLOATP (Vbusy_cursor_delay)
-          && XFLOAT_DATA (Vbusy_cursor_delay) > 0)
+  if (INTEGERP (Vhourglass_delay)
+      && XINT (Vhourglass_delay) > 0)
+    secs = XFASTINT (Vhourglass_delay);
+  else if (FLOATP (Vhourglass_delay)
+          && XFLOAT_DATA (Vhourglass_delay) > 0)
     {
       Lisp_Object tem;
-      tem = Ftruncate (Vbusy_cursor_delay, Qnil);
+      tem = Ftruncate (Vhourglass_delay, Qnil);
       secs = XFASTINT (tem);
-      usecs = (XFLOAT_DATA (Vbusy_cursor_delay) - secs) * 1000000;
+      usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
     }
   else
-    secs = DEFAULT_BUSY_CURSOR_DELAY;
+    secs = DEFAULT_HOURGLASS_DELAY;
   
   EMACS_SET_SECS_USECS (delay, secs, usecs);
-  busy_cursor_atimer = start_atimer (ATIMER_RELATIVE, delay,
-                                    show_busy_cursor, NULL);
+  hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
+                                    show_hourglass, NULL);
 }
 
 
-/* Cancel the busy cursor timer if active, hide a busy cursor if
+/* Cancel the hourglass cursor timer if active, hide a busy cursor if
    shown.  */
 
 void
-cancel_busy_cursor ()
+cancel_hourglass ()
 {
-  if (busy_cursor_atimer)
+  if (hourglass_atimer)
     {
-      cancel_atimer (busy_cursor_atimer);
-      busy_cursor_atimer = NULL;
+      cancel_atimer (hourglass_atimer);
+      hourglass_atimer = NULL;
     }
   
-  if (busy_cursor_shown_p)
-    hide_busy_cursor ();
+  if (hourglass_shown_p)
+    hide_hourglass ();
 }
 
 
-/* Timer function of busy_cursor_atimer.  TIMER is equal to
-   busy_cursor_atimer.
+/* Timer function of hourglass_atimer.  TIMER is equal to
+   hourglass_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.  */
+   Display an hourglass pointer on all frames by mapping the frames'
+   hourglass_window.  Set the hourglass_p flag in the frames'
+   output_data.x structure to indicate that an hourglass cursor is
+   shown on the frames.  */
 
 static void
-show_busy_cursor (timer)
+show_hourglass (timer)
      struct atimer *timer;
 {
   /* The timer implementation will cancel this timer automatically
-     after this function has run.  Set busy_cursor_atimer to null
+     after this function has run.  Set hourglass_atimer to null
      so that we know the timer doesn't have to be canceled.  */
-  busy_cursor_atimer = NULL;
+  hourglass_atimer = NULL;
 
-  if (!busy_cursor_shown_p)
+  if (!hourglass_shown_p)
     {
       Lisp_Object rest, frame;
   
@@ -10281,16 +10407,16 @@ show_busy_cursor (timer)
              if (FRAME_OUTER_WINDOW (f))
 #endif
                {
-                 f->output_data.x->busy_p = 1;
+                 f->output_data.x->hourglass_p = 1;
        
-                 if (!f->output_data.x->busy_window)
+                 if (!f->output_data.x->hourglass_window)
                    {
                      unsigned long mask = CWCursor;
                      XSetWindowAttributes attrs;
            
-                     attrs.cursor = f->output_data.x->busy_cursor;
+                     attrs.cursor = f->output_data.x->hourglass_cursor;
            
-                     f->output_data.x->busy_window
+                     f->output_data.x->hourglass_window
                        = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
                                         0, 0, 32000, 32000, 0, 0,
                                         InputOnly,
@@ -10298,24 +10424,25 @@ show_busy_cursor (timer)
                                         mask, &attrs);
                    }
        
-                 XMapRaised (dpy, f->output_data.x->busy_window);
+                 XMapRaised (dpy, f->output_data.x->hourglass_window);
                  XFlush (dpy);
                }
            }
        }
 
-      busy_cursor_shown_p = 1;
+      hourglass_shown_p = 1;
       UNBLOCK_INPUT;
     }
 }
 
 
-/* Hide the busy cursor on all frames, if it is currently shown.  */
+/* Hide the hourglass pointer on all frames, if it is currently
+   shown.  */
 
 static void
-hide_busy_cursor ()
+hide_hourglass ()
 {
-  if (busy_cursor_shown_p)
+  if (hourglass_shown_p)
     {
       Lisp_Object rest, frame;
 
@@ -10326,17 +10453,18 @@ hide_busy_cursor ()
       
          if (FRAME_X_P (f)
              /* Watch out for newly created frames.  */
-             && f->output_data.x->busy_window)
+             && f->output_data.x->hourglass_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.  */
+             XUnmapWindow (FRAME_X_DISPLAY (f),
+                           f->output_data.x->hourglass_window);
+             /* Sync here because XTread_socket looks at the
+                hourglass_p flag that is reset to zero below.  */
              XSync (FRAME_X_DISPLAY (f), False);
-             f->output_data.x->busy_p = 0;
+             f->output_data.x->hourglass_p = 0;
            }
        }
 
-      busy_cursor_shown_p = 0;
+      hourglass_shown_p = 0;
       UNBLOCK_INPUT;
     }
 }
@@ -10348,9 +10476,9 @@ hide_busy_cursor ()
  ***********************************************************************/
 
 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
-                                          Lisp_Object));
+                                          Lisp_Object, Lisp_Object));
 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
-                               Lisp_Object, int *, int *));
+                               Lisp_Object, int, int, int *, int *));
      
 /* The frame of a currently visible tooltip.  */
 
@@ -10367,6 +10495,10 @@ Window tip_window;
 
 Lisp_Object last_show_tip_args;
 
+/* Maximum size for tooltips; a cons (COLUMNS . ROWS).  */
+
+Lisp_Object Vx_max_tooltip_size;
+
 
 static Lisp_Object
 unwind_create_tip_frame (frame)
@@ -10386,7 +10518,8 @@ unwind_create_tip_frame (frame)
 
 
 /* Create a frame for a tooltip on the display described by DPYINFO.
-   PARMS is a list of frame parameters.  Value is the frame.
+   PARMS is a list of frame parameters.  TEXT is the string to
+   display in the tip frame.  Value is the frame.
 
    Note that functions called here, esp. x_default_parameter can
    signal errors, for instance when a specified color name is
@@ -10394,9 +10527,9 @@ unwind_create_tip_frame (frame)
    when this happens.  */
 
 static Lisp_Object
-x_create_tip_frame (dpyinfo, parms)
+x_create_tip_frame (dpyinfo, parms, text)
      struct x_display_info *dpyinfo;
-     Lisp_Object parms;
+     Lisp_Object parms, text;
 {
   struct frame *f;
   Lisp_Object frame, tem;
@@ -10407,6 +10540,8 @@ x_create_tip_frame (dpyinfo, parms)
   struct gcpro gcpro1, gcpro2, gcpro3;
   struct kboard *kb;
   int face_change_count_before = face_change_count;
+  Lisp_Object buffer;
+  struct buffer *old_buffer;
 
   check_x ();
 
@@ -10432,6 +10567,16 @@ x_create_tip_frame (dpyinfo, parms)
   GCPRO3 (parms, name, frame);
   f = make_frame (1);
   XSETFRAME (frame, f);
+
+  buffer = Fget_buffer_create (build_string (" *tip*"));
+  Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
+  old_buffer = current_buffer;
+  set_buffer_internal_1 (XBUFFER (buffer));
+  current_buffer->truncate_lines = Qnil;
+  Ferase_buffer ();
+  Finsert (1, &text);
+  set_buffer_internal_1 (old_buffer);
+  
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
   record_unwind_protect (unwind_create_tip_frame, frame);
 
@@ -10645,11 +10790,24 @@ x_create_tip_frame (dpyinfo, parms)
   change_frame_size (f, height, width, 1, 0, 0);
 
   /* Set up faces after all frame parameters are known.  This call
-     also merges in face attributes specified for new frames.  If we
-     don't do this, the `menu' face for instance won't have the right
-     colors, and the menu bar won't appear in the specified colors for
-     new frames.  */
-  call1 (Qface_set_after_frame_default, frame);
+     also merges in face attributes specified for new frames.
+
+     Frame parameters may be changed if .Xdefaults contains
+     specifications for the default font.  For example, if there is an
+     `Emacs.default.attributeBackground: pink', the `background-color'
+     attribute of the frame get's set, which let's the internal border
+     of the tooltip frame appear in pink.  Prevent this.  */
+  {
+    Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
+
+    /* Set tip_frame here, so that */
+    tip_frame = frame;
+    call1 (Qface_set_after_frame_default, frame);
+    
+    if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
+      Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
+                                             Qnil));
+  }
   
   f->no_split = 1;
 
@@ -10659,7 +10817,6 @@ x_create_tip_frame (dpyinfo, parms)
      below.  And the frame needs to be on Vframe_list or making it
      visible won't work.  */
   Vframe_list = Fcons (frame, Vframe_list);
-  tip_frame = frame;
 
   /* Now that the frame is official, it counts as a reference to
      its display.  */
@@ -10679,13 +10836,15 @@ x_create_tip_frame (dpyinfo, parms)
 
 /* Compute where to display tip frame F.  PARMS is the list of frame
    parameters for F.  DX and DY are specified offsets from the current
-   location of the mouse.  Return coordinates relative to the root
-   window of the display in *ROOT_X, and *ROOT_Y.  */
+   location of the mouse.  WIDTH and HEIGHT are the width and height
+   of the tooltip.  Return coordinates relative to the root window of
+   the display in *ROOT_X, and *ROOT_Y.  */
 
 static void
-compute_tip_xy (f, parms, dx, dy, root_x, root_y)
+compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
      struct frame *f;
      Lisp_Object parms, dx, dy;
+     int width, height;
      int *root_x, *root_y;
 {
   Lisp_Object left, top;
@@ -10699,18 +10858,30 @@ compute_tip_xy (f, parms, dx, dy, root_x, root_y)
   
   /* Move the tooltip window where the mouse pointer is.  Resize and
      show it.  */
-  BLOCK_INPUT;
-  XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
-                &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
-  UNBLOCK_INPUT;
+  if (!INTEGERP (left) && !INTEGERP (top))
+    {
+      BLOCK_INPUT;
+      XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
+                    &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
+      UNBLOCK_INPUT;
+    }
 
-  *root_x += XINT (dx);
-  *root_y += XINT (dy);
-  
-  if (INTEGERP (left))
-    *root_x = XINT (left);
   if (INTEGERP (top))
     *root_y = XINT (top);
+  else if (*root_y + XINT (dy) - height < 0)
+    *root_y -= XINT (dy);
+  else
+    {
+      *root_y -= height;
+      *root_y += XINT (dy);
+    }
+
+  if (INTEGERP (left))
+    *root_x = XINT (left);
+  else if (*root_x + XINT (dx) + width > FRAME_X_DISPLAY_INFO (f)->width)
+    *root_x -= width + XINT (dx);
+  else
+    *root_x += XINT (dx);
 }
 
 
@@ -10732,13 +10903,16 @@ displayed at the mouse position, with offset DX added (default is 5 if\n\
 DX isn't specified).  Likewise for the y-position; if a `top' frame\n\
 parameter is specified, it determines the y-position of the tooltip\n\
 window, otherwise it is displayed at the mouse position, with offset\n\
-DY added (default is -10).")
+DY added (default is -10).\n\
+\n\
+A tooltip's maximum size is specified by `x-max-tooltip-size'.\n\
+Text larger than the specified size is clipped.")
   (string, frame, parms, timeout, dx, dy)
      Lisp_Object string, frame, parms, timeout, dx, dy;
 {
   struct frame *f;
   struct window *w;
-  Lisp_Object buffer, top, left;
+  Lisp_Object buffer, top, left, max_width, max_height;
   int root_x, root_y;
   struct buffer *old_buffer;
   struct text_pos pos;
@@ -10785,12 +10959,17 @@ DY added (default is -10).")
          
          /* Only DX and DY have changed.  */
          if (!NILP (tip_timer))
-           call1 (intern ("cancel-timer"), tip_timer);
+           {
+             Lisp_Object timer = tip_timer;
+             tip_timer = Qnil;
+             call1 (Qcancel_timer, timer);
+           }
 
          BLOCK_INPUT;
-         compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
+         compute_tip_xy (f, parms, dx, dy, PIXEL_WIDTH (f),
+                         PIXEL_HEIGHT (f), &root_x, &root_y);
          XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                      root_x, root_y - PIXEL_HEIGHT (f));
+                      root_x, root_y);
          UNBLOCK_INPUT;
          goto start_timer;
        }
@@ -10818,26 +10997,36 @@ DY added (default is -10).")
 
   /* Create a frame for the tooltip, and record it in the global
      variable tip_frame.  */
-  frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms);
+  frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
   f = XFRAME (frame);
 
-  /* Set up the frame's root window.  Currently we use a size of 80
-     columns x 40 lines.  If someone wants to show a larger tip, he
-     will loose.  I don't think this is a realistic case.  */
+  /* Set up the frame's root window.  */
   w = XWINDOW (FRAME_ROOT_WINDOW (f));
   w->left = w->top = make_number (0);
-  w->width = make_number (80);
-  w->height = make_number (40);
+  
+  if (CONSP (Vx_max_tooltip_size)
+      && INTEGERP (XCAR (Vx_max_tooltip_size))
+      && XINT (XCAR (Vx_max_tooltip_size)) > 0
+      && INTEGERP (XCDR (Vx_max_tooltip_size))
+      && XINT (XCDR (Vx_max_tooltip_size)) > 0)
+    {
+      w->width = XCAR (Vx_max_tooltip_size);
+      w->height = XCDR (Vx_max_tooltip_size);
+    }
+  else
+    {
+      w->width = make_number (80);
+      w->height = make_number (40);
+    }
+  
+  f->window_width = XINT (w->width);
   adjust_glyphs (f);
   w->pseudo_window_p = 1;
 
   /* Display the tooltip text in a temporary buffer.  */
-  buffer = Fget_buffer_create (build_string (" *tip*"));
-  Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
   old_buffer = current_buffer;
-  set_buffer_internal_1 (XBUFFER (buffer));
-  Ferase_buffer ();
-  Finsert (1, &string);
+  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
+  current_buffer->truncate_lines = Qnil;
   clear_glyph_matrix (w->desired_matrix);
   clear_glyph_matrix (w->current_matrix);
   SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
@@ -10879,11 +11068,11 @@ DY added (default is -10).")
 
   /* Move the tooltip window where the mouse pointer is.  Resize and
      show it.  */
-  compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
+  compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
 
   BLOCK_INPUT;
   XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                    root_x, root_y - height, width, height);
+                    root_x, root_y, width, height);
   XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
   UNBLOCK_INPUT;
   
@@ -10928,7 +11117,7 @@ Value is t is tooltip was open, nil otherwise.")
   specbind (Qinhibit_quit, Qt);
   
   if (!NILP (timer))
-    call1 (intern ("cancel-timer"), timer);
+    call1 (Qcancel_timer, timer);
 
   if (FRAMEP (frame))
     {
@@ -10945,7 +11134,7 @@ Value is t is tooltip was open, nil otherwise.")
        extern void xlwmenu_redisplay P_ ((Widget));
        
        if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
-           && w != None)
+           && w != NULL)
          {
            BLOCK_INPUT;
            xlwmenu_redisplay (w);
@@ -10980,6 +11169,21 @@ file_dialog_cb (widget, client_data, call_data)
 }
 
 
+/* Callback for unmapping a file selection dialog.  This is used to
+   capture the case where a dialog is closed via a window manager's
+   closer button, for example. Using a XmNdestroyCallback didn't work
+   in this case.  */
+
+static void
+file_dialog_unmap_cb (widget, client_data, call_data)
+     Widget widget;
+     XtPointer call_data, client_data;
+{
+  int *result = (int *) client_data;
+  *result = XmCR_CANCEL;
+}
+
+
 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
   "Read file name, prompting with PROMPT in directory DIR.\n\
 Use a file selection dialog.\n\
@@ -11032,6 +11236,8 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
                 (XtPointer) &result);
   XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
                 (XtPointer) &result);
+  XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
+                (XtPointer) &result);
 
   /* Disable the help button since we can't display help.  */
   help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
@@ -11083,38 +11289,18 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
       XmListSetPos (list, item_pos);
     }
 
-#ifdef HAVE_MOTIF_2_1
-
-  /* Process events until the user presses Cancel or OK.  */
+  /* Process events until the user presses Cancel or OK.  Block
+     and unblock input here so that we get a chance of processing
+     expose events.  */
+  UNBLOCK_INPUT;
   result = 0;
-  while (result == 0 || XtAppPending (Xt_app_con))
-    XtAppProcessEvent (Xt_app_con, XtIMAll);
-
-#else /* not HAVE_MOTIF_2_1 */
-  
-  /* Process all events until the user presses Cancel or OK.  */
-  for (result = 0; result == 0;)
+  while (result == 0)
     {
-      XEvent event;
-      Widget widget, parent;
-      
-      XtAppNextEvent (Xt_app_con, &event);
-
-      /* See if the receiver of the event is one of the widgets of
-        the file selection dialog.  If so, dispatch it.  If not,
-        discard it.  */
-      widget = XtWindowToWidget (event.xany.display, event.xany.window);
-      parent = widget;
-      while (parent && parent != dialog)
-       parent = XtParent (parent);
-
-      if (parent == dialog
-         || (event.type == Expose
-             && !process_expose_from_menu (event)))
-       XtDispatchEvent (&event);
+      BLOCK_INPUT;
+      XtAppProcessEvent (Xt_app_con, XtIMAll);
+      UNBLOCK_INPUT;
     }
-
-#endif /* not HAVE_MOTIF_2_1 */
+  BLOCK_INPUT;
 
   /* Get the result.  */
   if (result == XmCR_OK)
@@ -11179,34 +11365,46 @@ usual X keysyms.")
   major = XkbMajorVersion;
   minor = XkbMinorVersion;
   if (!XkbLibraryVersion (&major, &minor))
-    return Qnil;
+    {
+      UNBLOCK_INPUT;
+      return Qnil;
+    }
 
   /* Check that the server supports XKB.  */
   major = XkbMajorVersion;
   minor = XkbMinorVersion;
   if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
-    return Qnil;
+    {
+      UNBLOCK_INPUT;
+      return Qnil;
+    }
   
   have_keys = Qnil;
-  kb = XkbGetKeyboard (dpy, XkbAllComponentsMask, XkbUseCoreKbd);
+  kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
   if (kb)
     {
       int delete_keycode = 0, backspace_keycode = 0, i;
-      
-      for (i = kb->min_key_code;
-          (i < kb->max_key_code
-           && (delete_keycode == 0 || backspace_keycode == 0));
-          ++i)
+
+      if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
        {
-         /* The XKB symbolic key names can be seen most easily
-            in the PS file generated by `xkbprint -label name $DISPLAY'.  */
-         if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
-           delete_keycode = i;
-         else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
-           backspace_keycode = i;
+         for (i = kb->min_key_code;
+              (i < kb->max_key_code
+               && (delete_keycode == 0 || backspace_keycode == 0));
+              ++i)
+           {
+             /* The XKB symbolic key names can be seen most easily in
+                the PS file generated by `xkbprint -label name
+                $DISPLAY'.  */
+             if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
+               delete_keycode = i;
+             else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
+               backspace_keycode = i;
+           }
+
+         XkbFreeNames (kb, 0, True);
        }
 
-      XkbFreeKeyboard (kb, 0, True);
+      XkbFreeClientMap (kb, 0, True);
   
       if (delete_keycode
          && backspace_keycode
@@ -11308,6 +11506,10 @@ syms_of_xfns ()
   staticpro (&Qcenter);
   Qcompound_text = intern ("compound-text");
   staticpro (&Qcompound_text);
+  Qcancel_timer = intern ("cancel-timer");
+  staticpro (&Qcancel_timer);
+  Qwait_for_wm = intern ("wait-for-wm");
+  staticpro (&Qwait_for_wm);
   /* This is the end of symbol initialization.  */
 
   /* Text property `display' should be nonsticky by default.  */
@@ -11342,7 +11544,7 @@ syms_of_xfns ()
 
   DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
     "Non-nil means always draw a cross over disabled images.\n\
-Disabled images are those having an `:algorithm disabled' property.\n\
+Disabled images are those having an `:conversion disabled' property.\n\
 A cross is always drawn on black & white displays.");
   cross_disabled_images = 0;
 
@@ -11387,20 +11589,20 @@ or when you set the mouse color.");
 #endif
   Vx_nontext_pointer_shape = Qnil;
 
-  DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape,
+  DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
     "The shape of the pointer when Emacs is busy.\n\
 This variable takes effect when you create a new frame\n\
 or when you set the mouse color.");
-  Vx_busy_pointer_shape = Qnil;
+  Vx_hourglass_pointer_shape = Qnil;
 
-  DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p,
-    "Non-zero means Emacs displays a busy cursor on window systems.");
-  display_busy_cursor_p = 1;
+  DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
+    "Non-zero means Emacs displays an hourglass pointer on window systems.");
+  display_hourglass_p = 1;
   
-  DEFVAR_LISP ("busy-cursor-delay", &Vbusy_cursor_delay,
-     "*Seconds to wait before displaying a busy-cursor.\n\
+  DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
+     "*Seconds to wait before displaying an hourglass pointer.\n\
 Value must be an integer or float.");
-  Vbusy_cursor_delay = make_number (DEFAULT_BUSY_CURSOR_DELAY);
+  Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
 
 #if 0 /* This doesn't really do anything.  */
   DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
@@ -11428,6 +11630,11 @@ or when you set the mouse color.");
               "A string indicating the foreground color of the cursor box.");
   Vx_cursor_fore_pixel = Qnil;
 
+  DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
+   "Maximum size for tooltips.  Value is a pair (COLUMNS . ROWS).\n\
+Text larger than this is clipped.");
+  Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
+  
   DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
               "Non-nil if no X window manager is in use.\n\
 Emacs doesn't try to figure this out; this is always nil\n\
@@ -11455,10 +11662,15 @@ meaning don't clear the cache.");
 
 #ifdef USE_X_TOOLKIT
   Fprovide (intern ("x-toolkit"));
-#endif
+  
 #ifdef USE_MOTIF
   Fprovide (intern ("motif"));
-#endif
+
+  DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
+     "Version info for LessTif/Motif.");
+  Vmotif_version_string = build_string (XmVERSION_STRING);
+#endif /* USE_MOTIF */
+#endif /* USE_X_TOOLKIT */
 
   defsubr (&Sx_get_resource);
 
@@ -11512,8 +11724,8 @@ meaning don't clear the cache.");
   staticpro (&Qxbm);
   QCtype = intern (":type");
   staticpro (&QCtype);
-  QCalgorithm = intern (":algorithm");
-  staticpro (&QCalgorithm);
+  QCconversion = intern (":conversion");
+  staticpro (&QCconversion);
   QCheuristic_mask = intern (":heuristic-mask");
   staticpro (&QCheuristic_mask);
   QCcolor_symbols = intern (":color-symbols");
@@ -11568,8 +11780,8 @@ meaning don't clear the cache.");
   defsubr (&Simage_size);
   defsubr (&Simage_mask_p);
 
-  busy_cursor_atimer = NULL;
-  busy_cursor_shown_p = 0;
+  hourglass_atimer = NULL;
+  hourglass_shown_p = 0;
 
   defsubr (&Sx_show_tip);
   defsubr (&Sx_hide_tip);