]> code.delx.au - gnu-emacs/blobdiff - src/xfns.c
(compute_tip_xy): Add parameters WIDTH and HEIGHT.
[gnu-emacs] / src / xfns.c
index 6c9b40a329749cdac211fdef8e92aacb0fb53091..4f718fa902018000bbe7e89af8c8bf982fa1d5be 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.  */
 
@@ -321,7 +329,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 
@@ -365,7 +373,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)
            {
@@ -407,7 +415,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)
        {
@@ -1350,6 +1358,8 @@ x_set_foreground_color (f, arg, oldval)
                      f->output_data.x->foreground_pixel);
       XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
                      f->output_data.x->foreground_pixel);
+      XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
+                     f->output_data.x->foreground_pixel);
       UNBLOCK_INPUT;
       update_face_from_frame_parameter (f, Qforeground_color, arg);
       if (FRAME_VISIBLE_P (f))
@@ -1402,7 +1412,7 @@ x_set_mouse_color (f, arg, oldval)
      Lisp_Object arg, oldval;
 {
   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;
@@ -1442,15 +1452,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))
@@ -1504,7 +1514,7 @@ x_set_mouse_color (f, arg, oldval)
                    &fore_color, &back_color);
     XRecolorCursor (FRAME_X_DISPLAY (f), cross_cursor,
                    &fore_color, &back_color);
-    XRecolorCursor (FRAME_X_DISPLAY (f), busy_cursor,
+    XRecolorCursor (FRAME_X_DISPLAY (f), hourglass_cursor,
                     &fore_color, &back_color);
     XRecolorCursor (FRAME_X_DISPLAY (f), horizontal_drag_cursor,
                     &fore_color, &back_color);
@@ -1523,10 +1533,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)
@@ -1814,6 +1824,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);
 
@@ -1831,8 +1842,16 @@ x_set_font (f, arg, oldval)
     error ("The characters of the given font have varying widths");
   else if (STRINGP (result))
     {
-      if (!NILP (Fequal (result, oldval)))
+      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);
     }
@@ -3958,8 +3977,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;
 }
@@ -4301,6 +4319,36 @@ This function is an internal primitive--use `make-frame' instead.")
                       "title", "Title", RES_TYPE_STRING);
 
   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)
@@ -4358,34 +4406,6 @@ This function is an internal primitive--use `make-frame' instead.")
   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);
@@ -4442,6 +4462,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);
 }
 
@@ -5770,6 +5795,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
@@ -5901,6 +5927,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).  */
 
@@ -5934,6 +6035,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);
@@ -5985,71 +6088,10 @@ lookup_image (f, spec)
              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 conversion;
-
-             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));
-               }
-           }
+         /* 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;
@@ -10074,6 +10116,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;
 }
 
 
@@ -10188,94 +10236,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;
   
@@ -10295,16 +10343,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,
@@ -10312,24 +10360,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;
 
@@ -10340,17 +10389,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;
     }
 }
@@ -10362,9 +10412,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.  */
 
@@ -10400,7 +10450,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
@@ -10408,9 +10459,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;
@@ -10421,6 +10472,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 ();
 
@@ -10446,6 +10499,15 @@ 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));
+  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);
 
@@ -10705,13 +10767,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;
@@ -10725,18 +10789,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);
 }
 
 
@@ -10818,9 +10894,10 @@ DY added (default is -10).")
            }
 
          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;
        }
@@ -10848,7 +10925,7 @@ 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
@@ -10862,12 +10939,8 @@ DY added (default is -10).")
   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));
   clear_glyph_matrix (w->desired_matrix);
   clear_glyph_matrix (w->current_matrix);
   SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
@@ -10909,11 +10982,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;
   
@@ -10975,7 +11048,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);
@@ -11402,20 +11475,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,
@@ -11470,10 +11543,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);
 
@@ -11583,8 +11661,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);