(x_set_font): Handle case of x_new_fontset returning the
[bpt/emacs.git] / src / xfns.c
index 0bc3c39..58a965d 100644 (file)
@@ -1,5 +1,5 @@
 /* Functions for the X window system.
-   Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000
+   Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
      Free Software Foundation.
 
 This file is part of GNU Emacs.
@@ -124,7 +124,7 @@ extern double atof ();
 
 int gray_bitmap_width = gray_width;
 int gray_bitmap_height = gray_height;
-unsigned char *gray_bitmap_bits = gray_bits;
+char *gray_bitmap_bits = gray_bits;
 
 /* The name we're using in resource queries.  Most often "emacs".  */
 
@@ -135,20 +135,25 @@ 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.  */
 
 Lisp_Object Vx_sensitive_text_pointer_shape;
 
+/* If non-nil, the pointer shape to indicate that windows can be
+   dragged horizontally.  */
+
+Lisp_Object Vx_window_horizontal_drag_shape;
+
 /* Color of chars displayed in cursor box.  */
 
 Lisp_Object Vx_cursor_fore_pixel;
@@ -169,41 +174,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;
@@ -238,7 +208,7 @@ 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;
 
 /* The below are defined in frame.c.  */
 
@@ -250,6 +220,11 @@ extern Lisp_Object Vwindow_system_version;
 
 Lisp_Object Qface_set_after_frame_default;
 
+#if GLYPH_DEBUG
+int image_cache_refcount, dpyinfo_refcount;
+#endif
+
+
 \f
 /* Error if we are not connected to X.  */
 
@@ -346,7 +321,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 
@@ -390,7 +365,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)
            {
@@ -432,7 +407,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)
        {
@@ -663,9 +638,6 @@ x_create_bitmap_from_file (f, file)
   fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
   if (fd < 0)
     return -1;
-  /* XReadBitmapFile won't handle magic file names.  */
-  if (fd == 0)
-    return -1;
   emacs_close (fd);
 
   filename = (char *) XSTRING (found)->data;
@@ -744,6 +716,8 @@ struct x_frame_parm_table
   void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
 };
 
+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 *));
@@ -1364,8 +1338,7 @@ 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));
+  unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
 
   unload_color (f, f->output_data.x->foreground_pixel);
   f->output_data.x->foreground_pixel = pixel;
@@ -1389,8 +1362,7 @@ 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));
+  unsigned long pixel = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
 
   unload_color (f, f->output_data.x->background_pixel);
   f->output_data.x->background_pixel = pixel;
@@ -1430,7 +1402,7 @@ x_set_mouse_color (f, arg, oldval)
      Lisp_Object arg, oldval;
 {
   Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
-  Cursor busy_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;
@@ -1438,7 +1410,10 @@ x_set_mouse_color (f, arg, oldval)
   /* 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;
+    {
+      x_free_colors (f, &pixel, 1);
+      pixel = x_copy_color (f, f->output_data.x->foreground_pixel);
+    }
 
   unload_color (f, f->output_data.x->mouse_pixel);
   f->output_data.x->mouse_pixel = pixel;
@@ -1467,15 +1442,15 @@ x_set_mouse_color (f, arg, oldval)
     nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_left_ptr);
   x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
 
-  if (!EQ (Qnil, Vx_busy_pointer_shape))
+  if (!EQ (Qnil, 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 (FRAME_X_DISPLAY (f),
+                                           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 (FRAME_X_DISPLAY (f), XC_watch);
+  x_check_errors (FRAME_X_DISPLAY (f), "bad hourglass pointer cursor: %s");
   
   x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
   if (!EQ (Qnil, Vx_mode_pointer_shape))
@@ -1498,6 +1473,17 @@ x_set_mouse_color (f, arg, oldval)
   else
     cross_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), 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));
+    }
+  else
+    horizontal_drag_cursor
+      = XCreateFontCursor (FRAME_X_DISPLAY (f), 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);
@@ -1506,11 +1492,10 @@ x_set_mouse_color (f, arg, oldval)
     XColor fore_color, back_color;
 
     fore_color.pixel = f->output_data.x->mouse_pixel;
+    x_query_color (f, &fore_color);
     back_color.pixel = mask_color;
-    XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
-                &fore_color);
-    XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
-                &back_color);
+    x_query_color (f, &back_color);
+    
     XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
                    &fore_color, &back_color);
     XRecolorCursor (FRAME_X_DISPLAY (f), nontext_cursor,
@@ -1518,15 +1503,18 @@ x_set_mouse_color (f, arg, oldval)
     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), hourglass_cursor,
                     &fore_color, &back_color);
-    XRecolorCursor (FRAME_X_DISPLAY (f), busy_cursor,
+    XRecolorCursor (FRAME_X_DISPLAY (f), 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)
+  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;
 
@@ -1535,10 +1523,10 @@ x_set_mouse_color (f, arg, oldval)
     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 (hourglass_cursor != f->output_data.x->hourglass_cursor
+      && f->output_data.x->hourglass_cursor != 0)
+    XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hourglass_cursor);
+  f->output_data.x->hourglass_cursor = hourglass_cursor;
 
   if (mode_cursor != f->output_data.x->modeline_cursor
       && f->output_data.x->modeline_cursor != 0)
@@ -1550,6 +1538,11 @@ x_set_mouse_color (f, arg, oldval)
     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;
+
   XFlush (FRAME_X_DISPLAY (f));
   UNBLOCK_INPUT;
 
@@ -1821,6 +1814,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);
 
@@ -1838,6 +1832,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);
     }
@@ -2012,6 +2016,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);
@@ -2046,8 +2054,24 @@ x_set_tool_bar_lines (f, value, oldval)
     {
       updating_frame = f;
       clear_frame ();
+      clear_current_matrices (f);
       updating_frame = NULL;
     }
+
+  /* If the tool bar gets smaller, the internal border below it
+     has to be cleared.  It was formerly part of the display
+     of the larger tool bar, and updating windows won't clear it.  */
+  if (delta < 0)
+    {
+      int height = FRAME_INTERNAL_BORDER_WIDTH (f);
+      int width = PIXEL_WIDTH (f);
+      int y = nlines * CANON_Y_UNIT (f);
+
+      BLOCK_INPUT;
+      x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                   0, y, width, height, False);
+      UNBLOCK_INPUT;
+    }
 }
 
 
@@ -2164,6 +2188,8 @@ x_encode_text (string, coding_system, text_bytes, stringp)
   coding.mode |= CODING_MODE_LAST_BLOCK;
   if (coding.type == coding_type_iso2022)
     coding.flags |= CODING_FLAG_ISO_SAFE;
+  /* We suppress producing escape sequences for composition.  */
+  coding.composing = COMPOSITION_DISABLED;
   bufsize = encoding_buffer_size (&coding, bytes);
   buf = (unsigned char *) xmalloc (bufsize);
   encode_coding (&coding, str, buf, bytes, bufsize);
@@ -3261,6 +3287,8 @@ best_xim_style (user, xim)
 
 /* Create XIC for frame F. */
 
+static XIMStyle xic_style;
+
 void
 create_frame_xic (f)
      struct frame *f;
@@ -3268,7 +3296,6 @@ create_frame_xic (f)
   XIM xim;
   XIC xic = NULL;
   XFontSet xfs = NULL;
-  static XIMStyle xic_style;
 
   if (FRAME_XIC (f))
     return;
@@ -3898,20 +3925,20 @@ x_make_gc (f)
   gc_values.foreground = f->output_data.x->foreground_pixel;
   gc_values.background = f->output_data.x->background_pixel;
   gc_values.line_width = 0;    /* Means 1 using fast algorithm.  */
-  f->output_data.x->normal_gc = XCreateGC (FRAME_X_DISPLAY (f),
-                                      FRAME_X_WINDOW (f),
-                                      GCLineWidth | GCFont
-                                      | GCForeground | GCBackground,
-                                      &gc_values);
+  f->output_data.x->normal_gc
+    = XCreateGC (FRAME_X_DISPLAY (f),
+                FRAME_X_WINDOW (f),
+                GCLineWidth | GCFont | GCForeground | GCBackground,
+                &gc_values);
 
   /* Reverse video style.  */
   gc_values.foreground = f->output_data.x->background_pixel;
   gc_values.background = f->output_data.x->foreground_pixel;
-  f->output_data.x->reverse_gc = XCreateGC (FRAME_X_DISPLAY (f),
-                                       FRAME_X_WINDOW (f),
-                                       GCFont | GCForeground | GCBackground
-                                       | GCLineWidth,
-                                       &gc_values);
+  f->output_data.x->reverse_gc
+    = XCreateGC (FRAME_X_DISPLAY (f),
+                FRAME_X_WINDOW (f),
+                GCFont | GCForeground | GCBackground | GCLineWidth,
+                &gc_values);
 
   /* Cursor has cursor-color background, background-color foreground.  */
   gc_values.foreground = f->output_data.x->background_pixel;
@@ -3946,6 +3973,74 @@ x_make_gc (f)
   UNBLOCK_INPUT;
 }
 
+
+/* Free what was was allocated in x_make_gc.  */
+
+void
+x_free_gcs (f)
+     struct frame *f;
+{
+  Display *dpy = FRAME_X_DISPLAY (f);
+
+  BLOCK_INPUT;
+  
+  if (f->output_data.x->normal_gc)
+    {
+      XFreeGC (dpy, f->output_data.x->normal_gc);
+      f->output_data.x->normal_gc = 0;
+    }
+
+  if (f->output_data.x->reverse_gc)
+    {
+      XFreeGC (dpy, f->output_data.x->reverse_gc);
+      f->output_data.x->reverse_gc = 0;
+    }
+  
+  if (f->output_data.x->cursor_gc)
+    {
+      XFreeGC (dpy, f->output_data.x->cursor_gc);
+      f->output_data.x->cursor_gc = 0;
+    }
+
+  if (f->output_data.x->border_tile)
+    {
+      XFreePixmap (dpy, f->output_data.x->border_tile);
+      f->output_data.x->border_tile = 0;
+    }
+
+  UNBLOCK_INPUT;
+}
+
+
+/* Handler for signals raised during x_create_frame and
+   x_create_top_frame.  FRAME is the frame which is partially
+   constructed.  */
+
+static Lisp_Object
+unwind_create_frame (frame)
+     Lisp_Object frame;
+{
+  struct frame *f = XFRAME (frame);
+
+  /* If frame is ``official'', nothing to do.  */
+  if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
+    {
+#if GLYPH_DEBUG
+      struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+#endif
+      
+      x_free_frame_resources (f);
+
+      /* Check that reference counts are indeed correct.  */
+      xassert (dpyinfo->reference_count == dpyinfo_refcount);
+      xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
+      return Qt;
+    }
+  
+  return Qnil;
+}
+
+
 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
        1, 1, 0,
   "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
@@ -3966,7 +4061,7 @@ This function is an internal primitive--use `make-frame' instead.")
   int minibuffer_only = 0;
   long window_prompting = 0;
   int width, height;
-  int count = specpdl_ptr - specpdl;
+  int count = BINDING_STACK_SIZE ();
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   Lisp_Object display;
   struct x_display_info *dpyinfo = NULL;
@@ -4036,6 +4131,7 @@ This function is an internal primitive--use `make-frame' instead.")
   f->output_data.x->fontset = -1;
   f->output_data.x->scroll_bar_foreground_pixel = -1;
   f->output_data.x->scroll_bar_background_pixel = -1;
+  record_unwind_protect (unwind_create_frame, frame);
 
   f->icon_name
     = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
@@ -4044,6 +4140,10 @@ This function is an internal primitive--use `make-frame' instead.")
     f->icon_name = Qnil;
 
   FRAME_X_DISPLAY_INFO (f) = dpyinfo;
+#if GLYPH_DEBUG
+  image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
+  dpyinfo_refcount = dpyinfo->reference_count;
+#endif /* GLYPH_DEBUG */
 #ifdef MULTI_KBOARD
   FRAME_KBOARD (f) = kb;
 #endif
@@ -4232,14 +4332,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
@@ -4273,10 +4366,46 @@ This function is an internal primitive--use `make-frame' instead.")
      f->height.  */
   width = f->width;
   height = f->height;
+  
+  /* 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;
+      height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
+    }
+
   f->height = 0;
   SET_FRAME_WIDTH (f, 0);
   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);
+
 #ifdef USE_X_TOOLKIT
   /* Create the menu bar.  */
   if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
@@ -4325,6 +4454,7 @@ This function is an internal primitive--use `make-frame' instead.")
   return unbind_to (count, frame);
 }
 
+
 /* FRAME is used only to get a handle on the X display.  We don't pass the
    display info directly because we're called from frame.c, which doesn't
    know about that structure.  */
@@ -4895,7 +5025,7 @@ x_display_info_for_name (name)
 
   validate_x_resource_name ();
 
-  dpyinfo = x_term_init (name, (unsigned char *)0,
+  dpyinfo = x_term_init (name, (char *)0,
                         (char *) XSTRING (Vx_resource_name)->data);
 
   if (dpyinfo == 0)
@@ -5068,7 +5198,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.  */
@@ -5177,6 +5307,7 @@ enum image_value_type
   IMAGE_STRING_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,
@@ -5281,6 +5412,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;
@@ -5387,8 +5527,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)),
@@ -5517,7 +5657,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)
@@ -5827,7 +5967,6 @@ lookup_image (f, spec)
          /* Handle image type independent image attributes
             `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'.  */
          Lisp_Object ascent, margin, relief;
-         Lisp_Object file;
 
          ascent = image_spec_value (spec, QCascent, NULL);
          if (INTEGERP (ascent))
@@ -5837,13 +5976,22 @@ 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.  */
@@ -5891,20 +6039,20 @@ lookup_image (f, spec)
          /* Should we apply an image transformation algorithm?  */
          if (img->pixmap)
            {
-             Lisp_Object algorithm;
+             Lisp_Object conversion;
 
-             algorithm = image_spec_value (spec, QCalgorithm, NULL);
-             if (EQ (algorithm, Qdisabled))
+             conversion = image_spec_value (spec, QCconversion, NULL);
+             if (EQ (conversion, Qdisabled))
                x_disable_image (f, img);
-             else if (EQ (algorithm, Qlaplace))
+             else if (EQ (conversion, Qlaplace))
                x_laplace (f, img);
-             else if (EQ (algorithm, Qemboss))
+             else if (EQ (conversion, Qemboss))
                x_emboss (f, img);
-             else if (CONSP (algorithm)
-                      && EQ (XCAR (algorithm), Qedge_detection))
+             else if (CONSP (conversion)
+                      && EQ (XCAR (conversion), Qedge_detection))
                {
                  Lisp_Object tem;
-                 tem = XCDR (algorithm);
+                 tem = XCDR (conversion);
                  if (CONSP (tem))
                    x_edge_detection (f, img,
                                      Fplist_get (tem, QCmatrix),
@@ -6109,7 +6257,7 @@ x_find_image_file (file)
   /* Try to find FILE in data-directory, then x-bitmap-file-path.  */
   fd = openp (search_path, file, "", &file_found, 0);
   
-  if (fd < 0)
+  if (fd == -1)
     file_found = Qnil;
   else
     close (fd);
@@ -6203,9 +6351,9 @@ static struct image_keyword xbm_format[XBM_LAST] =
   {":foreground",      IMAGE_STRING_VALUE,                     0},
   {":background",      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}
 };
@@ -6710,12 +6858,11 @@ xbm_load (f, img)
     {
       struct image_keyword fmt[XBM_LAST];
       Lisp_Object data;
-      unsigned char *bitmap_data;
       int depth;
       unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
       unsigned long background = FRAME_BACKGROUND_PIXEL (f);
       char *bits;
-      int parsed_p, height, width;
+      int parsed_p;
       int in_memory_file_p = 0;
 
       /* See if data looks like an in-memory XBM file.  */
@@ -6837,9 +6984,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}
@@ -7106,7 +7253,7 @@ xpm_load (f, img)
      struct frame *f;
      struct image *img;
 {
-  int rc, i;
+  int rc;
   XpmAttributes attrs;
   Lisp_Object specified_file, color_symbols;
 
@@ -7207,6 +7354,8 @@ xpm_load (f, img)
 #ifdef ALLOC_XPM_COLORS
       img->colors = colors_in_color_table (&img->ncolors);
 #else /* not ALLOC_XPM_COLORS */
+      int i;
+
       img->ncolors = attrs.nalloc_pixels;
       img->colors = (unsigned long *) xmalloc (img->ncolors
                                               * sizeof *img->colors);
@@ -7398,7 +7547,7 @@ lookup_pixel_color (f, pixel)
 
       cmap = FRAME_X_COLORMAP (f);
       color.pixel = pixel;
-      XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
+      x_query_color (f, &color);
       rc = x_alloc_nearest_color (f, cmap, &color);
 
       if (rc)
@@ -7465,7 +7614,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;
@@ -7526,8 +7675,7 @@ x_to_xcolors (f, img, rgb_p)
        p->pixel = XGetPixel (ximg, x, y);
 
       if (rgb_p)
-       XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
-                     row, img->width);
+       x_query_colors (f, row, img->width);
     }
 
   XDestroyImage (ximg);
@@ -7921,9 +8069,9 @@ 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},
@@ -8248,9 +8396,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}
 };
@@ -8541,7 +8689,7 @@ png_load (f, img)
 
          cmap = FRAME_X_COLORMAP (f);
          color.pixel = FRAME_BACKGROUND_PIXEL (f);
-         XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
+         x_query_color (f, &color);
 
          bzero (&frame_background, sizeof frame_background);
          frame_background.red = color.red;
@@ -8725,9 +8873,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}
 };
@@ -9080,9 +9228,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}
 };
@@ -9403,9 +9551,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}
@@ -9621,7 +9769,7 @@ gif_load (f, img)
     {
       static int interlace_start[] = {0, 4, 2, 1};
       static int interlace_increment[] = {8, 8, 4, 2};
-      int pass, inc;
+      int pass;
       int row = interlace_start[0];
 
       pass = 0;
@@ -9716,9 +9864,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}
 };
@@ -10049,138 +10197,149 @@ 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;
   
       BLOCK_INPUT;
   
       FOR_EACH_FRAME (rest, frame)
-       if (FRAME_X_P (XFRAME (frame)))
-         {
-           struct frame *f = XFRAME (frame);
-       
-           f->output_data.x->busy_p = 1;
+       {
+         struct frame *f = XFRAME (frame);
+         
+         if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
+           {
+             Display *dpy = FRAME_X_DISPLAY (f);
+             
+#ifdef USE_X_TOOLKIT
+             if (f->output_data.x->widget)
+#else
+             if (FRAME_OUTER_WINDOW (f))
+#endif
+               {
+                 f->output_data.x->hourglass_p = 1;
        
-           if (!f->output_data.x->busy_window)
-             {
-               unsigned long mask = CWCursor;
-               XSetWindowAttributes attrs;
+                 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
-                 = XCreateWindow (FRAME_X_DISPLAY (f),
-                                  FRAME_OUTER_WINDOW (f),
-                                  0, 0, 32000, 32000, 0, 0,
-                                  InputOnly,
-                                  CopyFromParent,
-                                  mask, &attrs);
-             }
+                     f->output_data.x->hourglass_window
+                       = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
+                                        0, 0, 32000, 32000, 0, 0,
+                                        InputOnly,
+                                        CopyFromParent,
+                                        mask, &attrs);
+                   }
        
-           XMapRaised (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
-           XFlush (FRAME_X_DISPLAY (f));
-         }
+                 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;
 
@@ -10191,17 +10350,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;
     }
 }
@@ -10214,10 +10374,12 @@ hide_busy_cursor ()
 
 static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
                                           Lisp_Object));
+static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
+                               Lisp_Object, int *, int *));
      
-/* The frame of a currently visible tooltip, or null.  */
+/* The frame of a currently visible tooltip.  */
 
-struct frame *tip_frame;
+Lisp_Object tip_frame;
 
 /* If non-nil, a timer started that hides the last tooltip when it
    fires.  */
@@ -10225,8 +10387,36 @@ struct frame *tip_frame;
 Lisp_Object tip_timer;
 Window tip_window;
 
+/* If non-nil, a vector of 3 elements containing the last args
+   with which x-show-tip was called.  See there.  */
+
+Lisp_Object last_show_tip_args;
+
+
+static Lisp_Object
+unwind_create_tip_frame (frame)
+     Lisp_Object frame;
+{
+  Lisp_Object deleted;
+
+  deleted = unwind_create_frame (frame);
+  if (EQ (deleted, Qt))
+    {
+      tip_window = None;
+      tip_frame = Qnil;
+    }
+  
+  return deleted;
+}
+
+
 /* 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.  Value is the frame.
+
+   Note that functions called here, esp. x_default_parameter can
+   signal errors, for instance when a specified color name is
+   undefined.  We have to make sure that we're in a consistent state
+   when this happens.  */
 
 static Lisp_Object
 x_create_tip_frame (dpyinfo, parms)
@@ -10238,9 +10428,10 @@ x_create_tip_frame (dpyinfo, parms)
   Lisp_Object name;
   long window_prompting = 0;
   int width, height;
-  int count = specpdl_ptr - specpdl;
+  int count = BINDING_STACK_SIZE ();
   struct gcpro gcpro1, gcpro2, gcpro3;
   struct kboard *kb;
+  int face_change_count_before = face_change_count;
 
   check_x ();
 
@@ -10264,10 +10455,15 @@ x_create_tip_frame (dpyinfo, parms)
 
   frame = Qnil;
   GCPRO3 (parms, name, frame);
-  tip_frame = f = make_frame (1);
+  f = make_frame (1);
   XSETFRAME (frame, f);
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
+  record_unwind_protect (unwind_create_tip_frame, frame);
 
+  /* By setting the output method, we're essentially saying that
+     the frame is live, as per FRAME_LIVE_P.  If we get a signal
+     from this point on, x_destroy_window might screw up reference
+     counts etc.  */
   f->output_method = output_x_window;
   f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
   bzero (f->output_data.x, sizeof (struct x_output));
@@ -10277,6 +10473,10 @@ x_create_tip_frame (dpyinfo, parms)
   f->output_data.x->scroll_bar_background_pixel = -1;
   f->icon_name = Qnil;
   FRAME_X_DISPLAY_INFO (f) = dpyinfo;
+#if GLYPH_DEBUG
+  image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
+  dpyinfo_refcount = dpyinfo->reference_count;
+#endif /* GLYPH_DEBUG */
 #ifdef MULTI_KBOARD
   FRAME_KBOARD (f) = kb;
 #endif
@@ -10321,8 +10521,8 @@ x_create_tip_frame (dpyinfo, parms)
       specbind (Qx_resource_name, name);
     }
 
-  /* Extract the window parameters from the supplied values
-     that are needed to determine window geometry.  */
+  /* Extract the window parameters from the supplied values that are
+     needed to determine window geometry.  */
   {
     Lisp_Object font;
 
@@ -10426,7 +10626,10 @@ x_create_tip_frame (dpyinfo, parms)
     unsigned long mask;
     
     BLOCK_INPUT;
-    mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
+    mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
+    if (DoesSaveUnders (dpyinfo->screen))
+      mask |= CWSaveUnder;
+    
     /* Window managers look at the override-redirect flag to determine
        whether or net to give windows a decoration (Xlib spec, chapter
        3.2.8).  */
@@ -10466,6 +10669,26 @@ x_create_tip_frame (dpyinfo, parms)
   SET_FRAME_WIDTH (f, 0);
   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.
+
+     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;
 
   UNGCPRO;
@@ -10479,10 +10702,55 @@ x_create_tip_frame (dpyinfo, parms)
      its display.  */
   FRAME_X_DISPLAY_INFO (f)->reference_count++;
 
+  /* Setting attributes of faces of the tooltip frame from resources
+     and similar will increment face_change_count, which leads to the
+     clearing of all current matrices.  Since this isn't necessary
+     here, avoid it by resetting face_change_count to the value it
+     had before we created the tip frame.  */
+  face_change_count = face_change_count_before;
+
+  /* Discard the unwind_protect.  */
   return unbind_to (count, frame);
 }
 
 
+/* 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.  */
+
+static void
+compute_tip_xy (f, parms, dx, dy, root_x, root_y)
+     struct frame *f;
+     Lisp_Object parms, dx, dy;
+     int *root_x, *root_y;
+{
+  Lisp_Object left, top;
+  int win_x, win_y;
+  Window root, child;
+  unsigned pmask;
+  
+  /* User-specified position?  */
+  left = Fcdr (Fassq (Qleft, parms));
+  top  = Fcdr (Fassq (Qtop, parms));
+  
+  /* 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;
+
+  *root_x += XINT (dx);
+  *root_y += XINT (dy);
+  
+  if (INTEGERP (left))
+    *root_x = XINT (left);
+  if (INTEGERP (top))
+    *root_y = XINT (top);
+}
+
+
 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
   "Show STRING in a \"tooltip\" window on frame FRAME.\n\
 A tooltip window is a small X window displaying a string.\n\
@@ -10501,22 +10769,20 @@ 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 -5).")
+DY added (default is -10).")
   (string, frame, parms, timeout, dx, dy)
      Lisp_Object string, frame, parms, timeout, dx, dy;
 {
   struct frame *f;
   struct window *w;
-  Window root, child;
   Lisp_Object buffer, top, left;
+  int root_x, root_y;
   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, gcpro4;
   int old_windows_or_buffers_changed = windows_or_buffers_changed;
-  int count = specpdl_ptr - specpdl;
+  int count = BINDING_STACK_SIZE ();
   
   specbind (Qinhibit_redisplay, Qt);
 
@@ -10535,13 +10801,49 @@ DY added (default is -5).")
     CHECK_NUMBER (dx, 5);
   
   if (NILP (dy))
-    dy = make_number (-5);
+    dy = make_number (-10);
   else
     CHECK_NUMBER (dy, 6);
 
+  if (NILP (last_show_tip_args))
+    last_show_tip_args = Fmake_vector (make_number (3), Qnil);
+
+  if (!NILP (tip_frame))
+    {
+      Lisp_Object last_string = AREF (last_show_tip_args, 0);
+      Lisp_Object last_frame = AREF (last_show_tip_args, 1);
+      Lisp_Object last_parms = AREF (last_show_tip_args, 2);
+
+      if (EQ (frame, last_frame)
+         && !NILP (Fequal (last_string, string))
+         && !NILP (Fequal (last_parms, parms)))
+       {
+         struct frame *f = XFRAME (tip_frame);
+         
+         /* Only DX and DY have changed.  */
+         if (!NILP (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);
+         XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                      root_x, root_y - PIXEL_HEIGHT (f));
+         UNBLOCK_INPUT;
+         goto start_timer;
+       }
+    }
+
   /* Hide a previous tip, if any.  */
   Fx_hide_tip ();
 
+  ASET (last_show_tip_args, 0, string);
+  ASET (last_show_tip_args, 1, frame);
+  ASET (last_show_tip_args, 2, parms);
+
   /* Add default values to frame parameters.  */
   if (NILP (Fassq (Qname, parms)))
     parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
@@ -10558,7 +10860,7 @@ DY added (default is -5).")
   /* 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);
-  tip_frame = f = XFRAME (frame);
+  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
@@ -10616,31 +10918,16 @@ DY added (default is -5).")
   height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
   width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
 
-  /* User-specified position?  */
-  left = Fcdr (Fassq (Qleft, parms));
-  top  = Fcdr (Fassq (Qtop, parms));
-  
   /* 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;
+  compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
 
-  root_x += XINT (dx);
-  root_y += XINT (dy);
-  
-  if (INTEGERP (left))
-    root_x = XINT (left);
-  if (INTEGERP (top))
-    root_y = XINT (top);
-  
   BLOCK_INPUT;
   XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                     root_x, root_y - height, width, height);
   XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
   UNBLOCK_INPUT;
-
+  
   /* Draw into the window.  */
   w->must_be_updated_p = 1;
   update_single_window (w, 1);
@@ -10649,6 +10936,7 @@ DY added (default is -5).")
   set_buffer_internal_1 (old_buffer);
   windows_or_buffers_changed = old_windows_or_buffers_changed;
 
+ start_timer:
   /* Let the tip disappear after timeout seconds.  */
   tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
                     intern ("x-hide-tip"));
@@ -10663,28 +10951,53 @@ DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
 Value is t is tooltip was open, nil otherwise.")
   ()
 {
-  int count = specpdl_ptr - specpdl;
-  int deleted_p = 0;
+  int count;
+  Lisp_Object deleted, frame, timer;
+  struct gcpro gcpro1, gcpro2;
+
+  /* Return quickly if nothing to do.  */
+  if (NILP (tip_timer) && NILP (tip_frame))
+    return Qnil;
+  
+  frame = tip_frame;
+  timer = tip_timer;
+  GCPRO2 (frame, timer);
+  tip_frame = tip_timer = deleted = Qnil;
   
+  count = BINDING_STACK_SIZE ();
   specbind (Qinhibit_redisplay, Qt);
+  specbind (Qinhibit_quit, Qt);
   
-  if (!NILP (tip_timer))
-    {
-      call1 (intern ("cancel-timer"), tip_timer);
-      tip_timer = Qnil;
-    }
+  if (!NILP (timer))
+    call1 (Qcancel_timer, timer);
 
-  if (tip_frame)
+  if (FRAMEP (frame))
     {
-      Lisp_Object frame;
-      
-      XSETFRAME (frame, tip_frame);
-      Fdelete_frame (frame, Qt);
-      tip_frame = NULL;
-      deleted_p = 1;
+      Fdelete_frame (frame, Qnil);
+      deleted = Qt;
+
+#ifdef USE_LUCID
+      /* Bloodcurdling hack alert: The Lucid menu bar widget's
+        redisplay procedure is not called when a tip frame over menu
+        items is unmapped.  Redisplay the menu manually...  */
+      {
+       struct frame *f = SELECTED_FRAME ();
+       Widget w = f->output_data.x->menubar_widget;
+       extern void xlwmenu_redisplay P_ ((Widget));
+       
+       if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
+           && w != NULL)
+         {
+           BLOCK_INPUT;
+           xlwmenu_redisplay (w);
+           UNBLOCK_INPUT;
+         }
+      }
+#endif /* USE_LUCID */
     }
 
-  return unbind_to (count, deleted_p ? Qt : Qnil);
+  UNGCPRO;
+  return unbind_to (count, deleted);
 }
 
 
@@ -10811,39 +11124,11 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
       XmListSetPos (list, item_pos);
     }
 
-#ifdef HAVE_MOTIF_2_1
-
   /* Process events until the user presses Cancel or OK.  */
   result = 0;
   while (result == 0 || XtAppPending (Xt_app_con))
     XtAppProcessEvent (Xt_app_con, XtIMAll);
 
-#else /* not HAVE_MOTIF_2_1 */
-  
-  /* Process all events until the user presses Cancel or OK.  */
-  for (result = 0; result == 0;)
-    {
-      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);
-    }
-
-#endif /* not HAVE_MOTIF_2_1 */
-
   /* Get the result.  */
   if (result == XmCR_OK)
     {
@@ -10876,6 +11161,92 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
 
 
 \f
+/***********************************************************************
+                              Keyboard
+ ***********************************************************************/
+
+#ifdef HAVE_XKBGETKEYBOARD
+#include <X11/XKBlib.h>
+#include <X11/keysym.h>
+#endif
+
+DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
+       Sx_backspace_delete_keys_p, 0, 1, 0,
+  "Check if both Backspace and Delete keys are on the keyboard of FRAME.\n\
+FRAME nil means use the selected frame.\n\
+Value is t if we know that both keys are present, and are mapped to the\n\
+usual X keysyms.")
+  (frame)
+     Lisp_Object frame;
+{
+#ifdef HAVE_XKBGETKEYBOARD
+  XkbDescPtr kb;
+  struct frame *f = check_x_frame (frame);
+  Display *dpy = FRAME_X_DISPLAY (f);
+  Lisp_Object have_keys;
+  int major, minor, op, event, error;
+
+  BLOCK_INPUT;
+
+  /* Check library version in case we're dynamically linked.  */
+  major = XkbMajorVersion;
+  minor = XkbMinorVersion;
+  if (!XkbLibraryVersion (&major, &minor))
+    {
+      UNBLOCK_INPUT;
+      return Qnil;
+    }
+
+  /* Check that the server supports XKB.  */
+  major = XkbMajorVersion;
+  minor = XkbMinorVersion;
+  if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
+    {
+      UNBLOCK_INPUT;
+      return Qnil;
+    }
+  
+  have_keys = Qnil;
+  kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
+  if (kb)
+    {
+      int delete_keycode = 0, backspace_keycode = 0, i;
+
+      if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
+       {
+         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);
+       }
+
+      XkbFreeClientMap (kb, 0, True);
+  
+      if (delete_keycode
+         && backspace_keycode
+         && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
+         && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
+       have_keys = Qt;
+    }
+  UNBLOCK_INPUT;
+  return have_keys;
+#else /* not HAVE_XKBGETKEYBOARD */
+  return Qnil;
+#endif /* not HAVE_XKBGETKEYBOARD */
+}
+
+
+\f
 /***********************************************************************
                            Initialization
  ***********************************************************************/
@@ -10961,6 +11332,8 @@ syms_of_xfns ()
   staticpro (&Qcenter);
   Qcompound_text = intern ("compound-text");
   staticpro (&Qcompound_text);
+  Qcancel_timer = intern ("cancel-timer");
+  staticpro (&Qcancel_timer);
   /* This is the end of symbol initialization.  */
 
   /* Text property `display' should be nonsticky by default.  */
@@ -10995,7 +11368,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;
 
@@ -11040,20 +11413,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,
@@ -11070,6 +11443,13 @@ This variable takes effect when you create a new frame\n\
 or when you set the mouse color.");
   Vx_sensitive_text_pointer_shape = Qnil;
 
+  DEFVAR_LISP ("x-window-horizontal-drag-cursor",
+             &Vx_window_horizontal_drag_shape,
+  "Pointer shape to use for indicating a window can be dragged horizontally.\n\
+This variable takes effect when you create a new frame\n\
+or when you set the mouse color.");
+  Vx_window_horizontal_drag_shape = Qnil;
+
   DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
               "A string indicating the foreground color of the cursor box.");
   Vx_cursor_fore_pixel = Qnil;
@@ -11137,7 +11517,8 @@ meaning don't clear the cache.");
   defsubr (&Sx_display_list);
   defsubr (&Sx_synchronize);
   defsubr (&Sx_focus_frame);
-
+  defsubr (&Sx_backspace_delete_keys_p);
+  
   /* Setting callback functions for fontset handler.  */
   get_font_info_func = x_get_font_info;
 
@@ -11157,8 +11538,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");
@@ -11213,13 +11594,18 @@ 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);
-  staticpro (&tip_timer);
   tip_timer = Qnil;
+  staticpro (&tip_timer);
+  tip_frame = Qnil;
+  staticpro (&tip_frame);
+
+  last_show_tip_args = Qnil;
+  staticpro (&last_show_tip_args);
 
 #ifdef USE_MOTIF
   defsubr (&Sx_file_dialog);