emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/src/xterm.c


From: Kim F. Storm
Subject: [Emacs-diffs] Changes to emacs/src/xterm.c
Date: Fri, 21 Mar 2003 08:52:49 -0500

Index: emacs/src/xterm.c
diff -c emacs/src/xterm.c:1.781 emacs/src/xterm.c:1.782
*** emacs/src/xterm.c:1.781     Mon Mar 17 18:03:53 2003
--- emacs/src/xterm.c   Fri Mar 21 08:52:48 2003
***************
*** 158,203 ****
  
  #define abs(x)        ((x) < 0 ? -(x) : (x))
  
- #define BETWEEN(X, LOWER, UPPER)  ((X) >= (LOWER) && (X) < (UPPER))
- 
  
  
- extern Lisp_Object Qhelp_echo;
- 
  /* Non-nil means Emacs uses toolkit scroll bars.  */
  
  Lisp_Object Vx_toolkit_scroll_bars;
  
- /* If a string, XTread_socket generates an event to display that string.
-    (The display is done in read_char.)  */
- 
- static Lisp_Object help_echo;
- static Lisp_Object help_echo_window;
- static Lisp_Object help_echo_object;
- static int help_echo_pos;
- 
- /* Temporary variable for XTread_socket.  */
- 
- static Lisp_Object previous_help_echo;
- 
  /* Non-zero means that a HELP_EVENT has been generated since Emacs
     start.  */
  
  static int any_help_event_p;
  
- /* Non-zero means autoselect window with the mouse cursor.  */
- 
- int mouse_autoselect_window;
- 
  /* Last window where we saw the mouse.  Used by mouse-autoselect-window.  */
  static Lisp_Object last_window;
  
- /* Non-zero means draw block and hollow cursor as wide as the glyph
-    under it.  For example, if a block cursor is over a tab, it will be
-    drawn as wide as that tab on the display.  */
- 
- int x_stretch_cursor_p;
- 
  /* Non-zero means make use of UNDERLINE_POSITION font properties.  */
  
  int x_use_underline_position_properties;
--- 158,177 ----
***************
*** 231,242 ****
  static String Xt_default_resources[] = {0};
  #endif /* USE_X_TOOLKIT */
  
- /* Nominal cursor position -- where to draw output.
-    HPOS and VPOS are window relative glyph matrix coordinates.
-    X and Y are window relative pixel coordinates.  */
- 
- struct cursor_pos output_cursor;
- 
  /* Non-zero means user is interacting with a toolkit scroll bar.  */
  
  static int toolkit_scroll_bar_interaction;
--- 205,210 ----
***************
*** 263,269 ****
  
  /* Where the mouse was last time we reported a mouse event.  */
  
- FRAME_PTR last_mouse_frame;
  static XRectangle last_mouse_glyph;
  static Lisp_Object last_mouse_press_frame;
  
--- 231,236 ----
***************
*** 333,362 ****
  extern Lisp_Object x_icon_type P_ ((struct frame *));
  
  
- static int cursor_in_mouse_face_p P_ ((struct window *));
- static int clear_mouse_face P_ ((struct x_display_info *));
  static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
  static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
  static const XColor *x_color_cells P_ ((Display *, int *));
  static void x_update_window_end P_ ((struct window *, int, int));
- static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
  void x_delete_display P_ ((struct x_display_info *));
  static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
                                                unsigned));
- static int fast_find_position P_ ((struct window *, int, int *, int *,
-                                  int *, int *, Lisp_Object));
- static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
-                                    int *, int *, int *, int *, int));
- static void set_output_cursor P_ ((struct cursor_pos *));
- static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
-                                          int *, int *, int *, int));
- static void note_mode_line_or_margin_highlight P_ ((struct window *, int,
-                                                   int, int));
- static void note_mouse_highlight P_ ((struct frame *, int, int));
- static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
- static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
- static void show_mouse_face P_ ((struct x_display_info *,
-                                enum draw_glyphs_face));
  static int x_io_error_quitter P_ ((Display *));
  int x_catch_errors P_ ((Display *));
  void x_uncatch_errors P_ ((Display *, int));
--- 300,312 ----
***************
*** 371,388 ****
  void x_initialize P_ ((void));
  static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
  static int x_compute_min_glyph_bounds P_ ((struct frame *));
- static void x_draw_phys_cursor_glyph P_ ((struct window *,
-                                         struct glyph_row *,
-                                         enum draw_glyphs_face));
  static void x_update_end P_ ((struct frame *));
  static void XTframe_up_to_date P_ ((struct frame *));
  static void XTset_terminal_modes P_ ((void));
  static void XTreset_terminal_modes P_ ((void));
- static void XTcursor_to P_ ((int, int, int, int));
- static void x_write_glyphs P_ ((struct glyph *, int));
- static void x_clear_end_of_line P_ ((int));
  static void x_clear_frame P_ ((void));
- static void x_clear_cursor P_ ((struct window *));
  static void frame_highlight P_ ((struct frame *));
  static void frame_unhighlight P_ ((struct frame *));
  static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
--- 321,331 ----
***************
*** 401,429 ****
  static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
  static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
                                   enum text_cursor_kinds));
- static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
-                                      XRectangle *));
- static void expose_frame P_ ((struct frame *, int, int, int, int));
- static int expose_window_tree P_ ((struct window *, XRectangle *));
- static void expose_overlaps P_ ((struct window *, struct glyph_row *,
-                                struct glyph_row *));
- static int expose_window P_ ((struct window *, XRectangle *));
- static void expose_area P_ ((struct window *, struct glyph_row *,
-                            XRectangle *, enum glyph_row_area));
- static int expose_line P_ ((struct window *, struct glyph_row *,
-                            XRectangle *));
- static void x_update_cursor_in_window_tree P_ ((struct window *, int));
- static void x_update_window_cursor P_ ((struct window *, int));
- static void x_erase_phys_cursor P_ ((struct window *));
- void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
  
  static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
                               GC, int));
- static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
  static void x_flush P_ ((struct frame *f));
  static void x_update_begin P_ ((struct frame *));
  static void x_update_window_begin P_ ((struct window *));
- static void x_draw_vertical_border P_ ((struct window *));
  static void x_after_update_window_line P_ ((struct glyph_row *));
  static INLINE void take_vertical_position_into_account P_ ((struct it *));
  static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
--- 344,355 ----
***************
*** 596,629 ****
  }
  
  
! /* Draw a vertical window border to the right of window W if W doesn't
!    have vertical scroll bars.  */
  
  static void
! x_draw_vertical_border (w)
       struct window *w;
  {
    struct frame *f = XFRAME (WINDOW_FRAME (w));
! 
!   /* Redraw borders between horizontally adjacent windows.  Don't
!      do it for frames with vertical scroll bars because either the
!      right scroll bar of a window, or the left scroll bar of its
!      neighbor will suffice as a border.  */
!   if (!WINDOW_RIGHTMOST_P (w)
!       && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
!     {
!       int x0, x1, y0, y1;
! 
!       window_box_edges (w, -1, &x0, &y0, &x1, &y1);
!       x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
!       y1 -= 1;
! 
!       XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
!                f->output_data.x->normal_gc, x1, y0, x1, y1);
!     }
  }
  
- 
  /* End update of window W (which is equal to updated_window).
  
     Draw vertical borders between horizontally adjacent windows, and
--- 522,540 ----
  }
  
  
! /* Draw a vertical window border from (x,y0) to (x,y1)  */
  
  static void
! x_draw_vertical_window_border (w, x, y0, y1)
       struct window *w;
+      int x, y0, y1;
  {
    struct frame *f = XFRAME (WINDOW_FRAME (w));
!   
!   XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
!            f->output_data.x->normal_gc, x, y0, x, y1);
  }
  
  /* End update of window W (which is equal to updated_window).
  
     Draw vertical borders between horizontally adjacent windows, and
***************
*** 649,657 ****
        BLOCK_INPUT;
  
        if (cursor_on_p)
!       x_display_and_set_cursor (w, 1, output_cursor.hpos,
!                                 output_cursor.vpos,
!                                 output_cursor.x, output_cursor.y);
  
        x_draw_vertical_border (w);
        UNBLOCK_INPUT;
--- 560,568 ----
        BLOCK_INPUT;
  
        if (cursor_on_p)
!       display_and_set_cursor (w, 1, output_cursor.hpos,
!                               output_cursor.vpos,
!                               output_cursor.x, output_cursor.y);
  
        x_draw_vertical_border (w);
        UNBLOCK_INPUT;
***************
*** 680,688 ****
--- 591,601 ----
    /* Mouse highlight may be displayed again.  */
    FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
  
+ #ifndef XFlush
    BLOCK_INPUT;
    XFlush (FRAME_X_DISPLAY (f));
    UNBLOCK_INPUT;
+ #endif
  }
  
  
***************
*** 843,907 ****
  
  
  /***********************************************************************
-                           Output Cursor
-  ***********************************************************************/
- 
- /* Set the global variable output_cursor to CURSOR.  All cursor
-    positions are relative to updated_window.  */
- 
- static void
- set_output_cursor (cursor)
-     struct cursor_pos *cursor;
- {
-   output_cursor.hpos = cursor->hpos;
-   output_cursor.vpos = cursor->vpos;
-   output_cursor.x = cursor->x;
-   output_cursor.y = cursor->y;
- }
- 
- 
- /* Set a nominal cursor position.
- 
-    HPOS and VPOS are column/row positions in a window glyph matrix.  X
-    and Y are window text area relative pixel positions.
- 
-    If this is done during an update, updated_window will contain the
-    window that is being updated and the position is the future output
-    cursor position for that window.  If updated_window is null, use
-    selected_window and display the cursor at the given position.  */
- 
- static void
- XTcursor_to (vpos, hpos, y, x)
-      int vpos, hpos, y, x;
- {
-   struct window *w;
- 
-   /* If updated_window is not set, work on selected_window.  */
-   if (updated_window)
-     w = updated_window;
-   else
-     w = XWINDOW (selected_window);
- 
-   /* Set the output cursor.  */
-   output_cursor.hpos = hpos;
-   output_cursor.vpos = vpos;
-   output_cursor.x = x;
-   output_cursor.y = y;
- 
-   /* If not called as part of an update, really display the cursor.
-      This will also set the cursor position of W.  */
-   if (updated_window == NULL)
-     {
-       BLOCK_INPUT;
-       x_display_cursor (w, 1, hpos, vpos, x, y);
-       XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
-       UNBLOCK_INPUT;
-     }
- }
- 
- 
- 
- /***********************************************************************
                           Display Iterator
   ***********************************************************************/
  
--- 756,761 ----
***************
*** 1046,1078 ****
  }
  
  
- /* Estimate the pixel height of the mode or top line on frame F.
-    FACE_ID specifies what line's height to estimate.  */
- 
- int
- x_estimate_mode_line_height (f, face_id)
-      struct frame *f;
-      enum face_id face_id;
- {
-   int height = FONT_HEIGHT (FRAME_FONT (f));
- 
-   /* This function is called so early when Emacs starts that the face
-      cache and mode line face are not yet initialized.  */
-   if (FRAME_FACE_CACHE (f))
-       {
-       struct face *face = FACE_FROM_ID (f, face_id);
-       if (face)
-         {
-           if (face->font)
-             height = FONT_HEIGHT (face->font);
-           if (face->box_line_width > 0)
-             height += 2 * face->box_line_width;
-         }
-       }
- 
-   return height;
- }
- 
  
  /***********************************************************************
                            Glyph display
--- 900,905 ----
***************
*** 1107,1114 ****
                                    int, int, int, int, XRectangle *));
  static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
                                 int, int, int, XRectangle *));
- static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
-                                       enum glyph_row_area));
  
  #if GLYPH_DEBUG
  static void x_check_font P_ ((struct frame *, XFontStruct *));
--- 934,939 ----
***************
*** 1281,1354 ****
  }
  
  
- /* Return in *R the clipping rectangle for glyph string S.  */
- 
- static void
- x_get_glyph_string_clip_rect (s, r)
-      struct glyph_string *s;
-      XRectangle *r;
- {
-   if (s->row->full_width_p)
-     {
-       /* Draw full-width.  X coordinates are relative to S->w->left.  */
-       int canon_x = CANON_X_UNIT (s->f);
- 
-       r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
-       r->width = XFASTINT (s->w->width) * canon_x;
- 
-       if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
-       {
-         int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
-         if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
-           r->x -= width;
-       }
- 
-       r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
- 
-       /* Unless displaying a mode or menu bar line, which are always
-        fully visible, clip to the visible part of the row.  */
-       if (s->w->pseudo_window_p)
-       r->height = s->row->visible_height;
-       else
-       r->height = s->height;
-     }
-   else
-     {
-       /* This is a text line that may be partially visible.  */
-       r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
-       r->width = window_box_width (s->w, s->area);
-       r->height = s->row->visible_height;
-     }
- 
-   /* If S draws overlapping rows, it's sufficient to use the top and
-      bottom of the window for clipping because this glyph string
-      intentionally draws over other lines.  */
-   if (s->for_overlaps_p)
-     {
-       r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
-       r->height = window_text_bottom_y (s->w) - r->y;
-     }
-   else
-     {
-       /* Don't use S->y for clipping because it doesn't take partially
-        visible lines into account.  For example, it can be negative for
-        partially visible lines at the top of a window.  */
-       if (!s->row->full_width_p
-         && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
-       r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
-       else
-       r->y = max (0, s->row->y);
- 
-       /* If drawing a tool-bar window, draw it over the internal border
-        at the top of the window.  */
-       if (s->w == XWINDOW (s->f->tool_bar_window))
-       r->y -= s->f->output_data.x->internal_border_width;
-     }
- 
-   r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
- }
- 
- 
  /* Set clipping for output of glyph string S.  S may be part of a mode
     line or menu if we don't have X toolkit support.  */
  
--- 1106,1111 ----
***************
*** 1357,1363 ****
       struct glyph_string *s;
  {
    XRectangle r;
!   x_get_glyph_string_clip_rect (s, &r);
    XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
  }
  
--- 1114,1120 ----
       struct glyph_string *s;
  {
    XRectangle r;
!   get_glyph_string_clip_rect (s, &r);
    XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
  }
  
***************
*** 2349,2355 ****
                 && (s->next == NULL
                     || s->next->hl != s->hl)));
  
!   x_get_glyph_string_clip_rect (s, &clip_rect);
  
    if (s->face->box == FACE_SIMPLE_BOX)
      x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
--- 2106,2112 ----
                 && (s->next == NULL
                     || s->next->hl != s->hl)));
  
!   get_glyph_string_clip_rect (s, &clip_rect);
  
    if (s->face->box == FACE_SIMPLE_BOX)
      x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
***************
*** 2405,2411 ****
          xgcv.function = GXcopy;
          XChangeGC (s->display, s->gc, mask, &xgcv);
  
!         x_get_glyph_string_clip_rect (s, &clip_rect);
          image_rect.x = x;
          image_rect.y = y;
          image_rect.width = s->img->width;
--- 2162,2168 ----
          xgcv.function = GXcopy;
          XChangeGC (s->display, s->gc, mask, &xgcv);
  
!         get_glyph_string_clip_rect (s, &clip_rect);
          image_rect.x = x;
          image_rect.y = y;
          image_rect.width = s->img->width;
***************
*** 2418,2424 ****
        {
          XRectangle clip_rect, image_rect, r;
  
!         x_get_glyph_string_clip_rect (s, &clip_rect);
          image_rect.x = x;
          image_rect.y = y;
          image_rect.width = s->img->width;
--- 2175,2181 ----
        {
          XRectangle clip_rect, image_rect, r;
  
!         get_glyph_string_clip_rect (s, &clip_rect);
          image_rect.x = x;
          image_rect.y = y;
          image_rect.width = s->img->width;
***************
*** 2491,2497 ****
    y1 = y + s->img->height + thick - 1;
  
    x_setup_relief_colors (s);
!   x_get_glyph_string_clip_rect (s, &r);
    x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
  }
  
--- 2248,2254 ----
    y1 = y + s->img->height + thick - 1;
  
    x_setup_relief_colors (s);
!   get_glyph_string_clip_rect (s, &r);
    x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
  }
  
***************
*** 2733,2739 ****
          else
            gc = s->face->gc;
  
!         x_get_glyph_string_clip_rect (s, &r);
          XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
  
          if (s->face->stipple)
--- 2490,2496 ----
          else
            gc = s->face->gc;
  
!         get_glyph_string_clip_rect (s, &r);
          XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
  
          if (s->face->stipple)
***************
*** 2920,3068 ****
    XSetClipMask (s->display, s->gc, None);
  }
  
  
! /* Fix the display of area AREA of overlapping row ROW in window W.  */
! 
! static void
! x_fix_overlapping_area (w, row, area)
!      struct window *w;
!      struct glyph_row *row;
!      enum glyph_row_area area;
! {
!   int i, x;
! 
!   BLOCK_INPUT;
! 
!   if (area == LEFT_MARGIN_AREA)
!     x = 0;
!   else if (area == TEXT_AREA)
!     x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
!   else
!     x = (window_box_width (w, LEFT_MARGIN_AREA)
!        + window_box_width (w, TEXT_AREA));
! 
!   for (i = 0; i < row->used[area];)
!     {
!       if (row->glyphs[area][i].overlaps_vertically_p)
!       {
!         int start = i, start_x = x;
! 
!         do
!           {
!             x += row->glyphs[area][i].pixel_width;
!             ++i;
!           }
!         while (i < row->used[area]
!                && row->glyphs[area][i].overlaps_vertically_p);
! 
!         x_draw_glyphs (w, start_x, row, area, start, i,
!                        DRAW_NORMAL_TEXT, 1);
!       }
!       else
!       {
!         x += row->glyphs[area][i].pixel_width;
!         ++i;
!       }
!     }
! 
!   UNBLOCK_INPUT;
! }
! 
! 
! /* Output LEN glyphs starting at START at the nominal cursor position.
!    Advance the nominal cursor over the text.  The global variable
!    updated_window contains the window being updated, updated_row is
!    the glyph row being updated, and updated_area is the area of that
!    row being updated.  */
! 
! static void
! x_write_glyphs (start, len)
!      struct glyph *start;
!      int len;
! {
!   int x, hpos;
! 
!   xassert (updated_window && updated_row);
!   BLOCK_INPUT;
! 
!   /* Write glyphs.  */
! 
!   hpos = start - updated_row->glyphs[updated_area];
!   x = x_draw_glyphs (updated_window, output_cursor.x,
!                    updated_row, updated_area,
!                    hpos, hpos + len,
!                    DRAW_NORMAL_TEXT, 0);
! 
!   /* Invalidate old phys cursor if the glyph at its hpos is redrawn.  */
!   if (updated_area == TEXT_AREA
!       && updated_window->phys_cursor_on_p
!       && updated_window->phys_cursor.vpos == output_cursor.vpos
!       && updated_window->phys_cursor.hpos >= hpos
!       && updated_window->phys_cursor.hpos < hpos + len)
!     updated_window->phys_cursor_on_p = 0;
! 
!   UNBLOCK_INPUT;
! 
!   /* Advance the output cursor.  */
!   output_cursor.hpos += len;
!   output_cursor.x = x;
! }
! 
! 
! /* Insert LEN glyphs from START at the nominal cursor position.   */
! 
! static void
! x_insert_glyphs (start, len)
!      struct glyph *start;
!      register int len;
  {
-   struct frame *f;
-   struct window *w;
-   int line_height, shift_by_width, shifted_region_width;
-   struct glyph_row *row;
-   struct glyph *glyph;
-   int frame_x, frame_y, hpos;
- 
-   xassert (updated_window && updated_row);
-   BLOCK_INPUT;
-   w = updated_window;
-   f = XFRAME (WINDOW_FRAME (w));
- 
-   /* Get the height of the line we are in.  */
-   row = updated_row;
-   line_height = row->height;
- 
-   /* Get the width of the glyphs to insert.  */
-   shift_by_width = 0;
-   for (glyph = start; glyph < start + len; ++glyph)
-     shift_by_width += glyph->pixel_width;
- 
-   /* Get the width of the region to shift right.  */
-   shifted_region_width = (window_box_width (w, updated_area)
-                         - output_cursor.x
-                         - shift_by_width);
- 
-   /* Shift right.  */
-   frame_x = window_box_left (w, updated_area) + output_cursor.x;
-   frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
    XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
             f->output_data.x->normal_gc,
!            frame_x, frame_y,
!            shifted_region_width, line_height,
!            frame_x + shift_by_width, frame_y);
! 
!   /* Write the glyphs.  */
!   hpos = start - row->glyphs[updated_area];
!   x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
!                DRAW_NORMAL_TEXT, 0);
! 
!   /* Advance the output cursor.  */
!   output_cursor.hpos += len;
!   output_cursor.x += shift_by_width;
!   UNBLOCK_INPUT;
  }
  
- 
  /* Delete N glyphs at the nominal cursor position.  Not implemented
     for X frames.  */
  
--- 2677,2695 ----
    XSetClipMask (s->display, s->gc, None);
  }
  
+ /* Shift display to make room for inserted glyphs.   */
  
! void
! x_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
!      struct frame *f;
!      int x, y, width, height, shift_by;
  {
    XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
             f->output_data.x->normal_gc,
!            x, y, width, height,
!            x + shift_by, y);
  }
  
  /* Delete N glyphs at the nominal cursor position.  Not implemented
     for X frames.  */
  
***************
*** 3090,3173 ****
  }
  
  
- /* Erase the current text line from the nominal cursor position
-    (inclusive) to pixel column TO_X (exclusive).  The idea is that
-    everything from TO_X onward is already erased.
- 
-    TO_X is a pixel position relative to updated_area of
-    updated_window.  TO_X == -1 means clear to the end of this area.  */
- 
- static void
- x_clear_end_of_line (to_x)
-      int to_x;
- {
-   struct frame *f;
-   struct window *w = updated_window;
-   int max_x, min_y, max_y;
-   int from_x, from_y, to_y;
- 
-   xassert (updated_window && updated_row);
-   f = XFRAME (w->frame);
- 
-   if (updated_row->full_width_p)
-     {
-       max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
-       if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
-         && !w->pseudo_window_p)
-       max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
-     }
-   else
-     max_x = window_box_width (w, updated_area);
-   max_y = window_text_bottom_y (w);
- 
-   /* TO_X == 0 means don't do anything.  TO_X < 0 means clear to end
-      of window.  For TO_X > 0, truncate to end of drawing area.  */
-   if (to_x == 0)
-     return;
-   else if (to_x < 0)
-     to_x = max_x;
-   else
-     to_x = min (to_x, max_x);
- 
-   to_y = min (max_y, output_cursor.y + updated_row->height);
- 
-   /* Notice if the cursor will be cleared by this operation.  */
-   if (!updated_row->full_width_p)
-     notice_overwritten_cursor (w, updated_area,
-                              output_cursor.x, -1,
-                              updated_row->y,
-                              MATRIX_ROW_BOTTOM_Y (updated_row));
- 
-   from_x = output_cursor.x;
- 
-   /* Translate to frame coordinates.  */
-   if (updated_row->full_width_p)
-     {
-       from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
-       to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
-     }
-   else
-     {
-       from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
-       to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
-     }
- 
-   min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
-   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
-   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
- 
-   /* Prevent inadvertently clearing to end of the X window.  */
-   if (to_x > from_x && to_y > from_y)
-     {
-       BLOCK_INPUT;
-       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                   from_x, from_y, to_x - from_x, to_y - from_y,
-                   False);
-       UNBLOCK_INPUT;
-     }
- }
- 
- 
  /* Clear entire frame.  If updating_frame is non-null, clear that
     frame.  Otherwise clear the selected frame.  */
  
--- 2717,2722 ----
***************
*** 3499,4007 ****
                           Exposure Events
   ***********************************************************************/
  
! /* Redisplay an exposed area of frame F.  X and Y are the upper-left
!    corner of the exposed rectangle.  W and H are width and height of
!    the exposed area.  All are pixel values.  W or H zero means redraw
!    the entire frame.  */
! 
  static void
! expose_frame (f, x, y, w, h)
       struct frame *f;
-      int x, y, w, h;
  {
!   XRectangle r;
!   int mouse_face_overwritten_p = 0;
! 
!   TRACE ((stderr, "expose_frame "));
! 
!   /* No need to redraw if frame will be redrawn soon.  */
!   if (FRAME_GARBAGED_P (f))
!     {
!       TRACE ((stderr, " garbaged\n"));
!       return;
!     }
! 
!   /* If basic faces haven't been realized yet, there is no point in
!      trying to redraw anything.  This can happen when we get an expose
!      event while Emacs is starting, e.g. by moving another window.  */
!   if (FRAME_FACE_CACHE (f) == NULL
!       || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
!     {
!       TRACE ((stderr, " no faces\n"));
!       return;
!     }
! 
!   if (w == 0 || h == 0)
!     {
!       r.x = r.y = 0;
!       r.width = CANON_X_UNIT (f) * f->width;
!       r.height = CANON_Y_UNIT (f) * f->height;
!     }
!   else
!     {
!       r.x = x;
!       r.y = y;
!       r.width = w;
!       r.height = h;
!     }
  
!   TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
!   mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), 
&r);
  
!   if (WINDOWP (f->tool_bar_window))
!     mouse_face_overwritten_p
!       |= expose_window (XWINDOW (f->tool_bar_window), &r);
  
! #ifndef USE_X_TOOLKIT
!   if (WINDOWP (f->menu_bar_window))
!     mouse_face_overwritten_p
!       |= expose_window (XWINDOW (f->menu_bar_window), &r);
! #endif /* not USE_X_TOOLKIT */
  
!   /* Some window managers support a focus-follows-mouse style with
!      delayed raising of frames.  Imagine a partially obscured frame,
!      and moving the mouse into partially obscured mouse-face on that
!      frame.  The visible part of the mouse-face will be highlighted,
!      then the WM raises the obscured frame.  With at least one WM, KDE
!      2.1, Emacs is not getting any event for the raising of the frame
!      (even tried with SubstructureRedirectMask), only Expose events.
!      These expose events will draw text normally, i.e. not
!      highlighted.  Which means we must redo the highlight here.
!      Subsume it under ``we love X''.  --gerd 2001-08-15  */
!   if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
      {
!       struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
!       if (f == dpyinfo->mouse_face_mouse_frame)
!       {
!         int x = dpyinfo->mouse_face_mouse_x;
!         int y = dpyinfo->mouse_face_mouse_y;
!         clear_mouse_face (dpyinfo);
!         note_mouse_highlight (f, x, y);
!       }
!     }
! }
! 
  
! /* Redraw (parts) of all windows in the window tree rooted at W that
!    intersect R.  R contains frame pixel coordinates.  Value is
!    non-zero if the exposure overwrites mouse-face.  */
  
! static int
! expose_window_tree (w, r)
!      struct window *w;
!      XRectangle *r;
! {
!   struct frame *f = XFRAME (w->frame);
!   int mouse_face_overwritten_p = 0;
  
!   while (w && !FRAME_GARBAGED_P (f))
!     {
!       if (!NILP (w->hchild))
!       mouse_face_overwritten_p
!         |= expose_window_tree (XWINDOW (w->hchild), r);
!       else if (!NILP (w->vchild))
!       mouse_face_overwritten_p
!         |= expose_window_tree (XWINDOW (w->vchild), r);
        else
!       mouse_face_overwritten_p |= expose_window (w, r);
! 
!       w = NILP (w->next) ? NULL : XWINDOW (w->next);
      }
  
!   return mouse_face_overwritten_p;
! }
! 
! 
! /* Redraw the part of glyph row area AREA of glyph row ROW on window W
!    which intersects rectangle R.  R is in window-relative coordinates.  */
! 
! static void
! expose_area (w, row, r, area)
!      struct window *w;
!      struct glyph_row *row;
!      XRectangle *r;
!      enum glyph_row_area area;
! {
!   struct glyph *first = row->glyphs[area];
!   struct glyph *end = row->glyphs[area] + row->used[area];
!   struct glyph *last;
!   int first_x, start_x, x;
! 
!   if (area == TEXT_AREA && row->fill_line_p)
!     /* If row extends face to end of line write the whole line.  */
!     x_draw_glyphs (w, 0, row, area, 0, row->used[area],
!                  DRAW_NORMAL_TEXT, 0);
!   else
!     {
!       /* Set START_X to the window-relative start position for drawing glyphs 
of
!        AREA.  The first glyph of the text area can be partially visible.
!        The first glyphs of other areas cannot.  */
!       if (area == LEFT_MARGIN_AREA)
!       start_x = 0;
!       else if (area == TEXT_AREA)
!       start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
!       else
!       start_x = (window_box_width (w, LEFT_MARGIN_AREA)
!                  + window_box_width (w, TEXT_AREA));
!       x = start_x;
! 
!       /* Find the first glyph that must be redrawn.  */
!       while (first < end
!            && x + first->pixel_width < r->x)
!       {
!         x += first->pixel_width;
!         ++first;
!       }
! 
!       /* Find the last one.  */
!       last = first;
!       first_x = x;
!       while (last < end
!            && x < r->x + r->width)
!       {
!         x += last->pixel_width;
!         ++last;
!       }
! 
!       /* Repaint.  */
!       if (last > first)
!       x_draw_glyphs (w, first_x - start_x, row, area,
!                      first - row->glyphs[area],
!                      last - row->glyphs[area],
!                      DRAW_NORMAL_TEXT, 0);
!     }
! }
! 
! 
! /* Redraw the parts of the glyph row ROW on window W intersecting
!    rectangle R.  R is in window-relative coordinates.  Value is
!    non-zero if mouse-face was overwritten.  */
! 
! static int
! expose_line (w, row, r)
!      struct window *w;
!      struct glyph_row *row;
!      XRectangle *r;
! {
!   xassert (row->enabled_p);
! 
!   if (row->mode_line_p || w->pseudo_window_p)
!     x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
!                  DRAW_NORMAL_TEXT, 0);
!   else
!     {
!       if (row->used[LEFT_MARGIN_AREA])
!       expose_area (w, row, r, LEFT_MARGIN_AREA);
!       if (row->used[TEXT_AREA])
!       expose_area (w, row, r, TEXT_AREA);
!       if (row->used[RIGHT_MARGIN_AREA])
!       expose_area (w, row, r, RIGHT_MARGIN_AREA);
!       draw_row_fringe_bitmaps (w, row);
!     }
! 
!   return row->mouse_face_p;
! }
! 
! 
! /* Return non-zero if W's cursor intersects rectangle R.  */
! 
! static int
! x_phys_cursor_in_rect_p (w, r)
!      struct window *w;
!      XRectangle *r;
! {
!   XRectangle cr, result;
!   struct glyph *cursor_glyph;
! 
!   cursor_glyph = get_phys_cursor_glyph (w);
!   if (cursor_glyph)
!     {
!       cr.x = w->phys_cursor.x;
!       cr.y = w->phys_cursor.y;
!       cr.width = cursor_glyph->pixel_width;
!       cr.height = w->phys_cursor_height;
!       return x_intersect_rectangles (&cr, r, &result);
!     }
!   else
!     return 0;
! }
! 
! 
! /* Redraw those parts of glyphs rows during expose event handling that
!    overlap other rows.  Redrawing of an exposed line writes over parts
!    of lines overlapping that exposed line; this function fixes that.
! 
!    W is the window being exposed.  FIRST_OVERLAPPING_ROW is the first
!    row in W's current matrix that is exposed and overlaps other rows.
!    LAST_OVERLAPPING_ROW is the last such row.  */
! 
! static void
! expose_overlaps (w, first_overlapping_row, last_overlapping_row)
!      struct window *w;
!      struct glyph_row *first_overlapping_row;
!      struct glyph_row *last_overlapping_row;
! {
!   struct glyph_row *row;
! 
!   for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
!     if (row->overlapping_p)
!       {
!       xassert (row->enabled_p && !row->mode_line_p);
! 
!       if (row->used[LEFT_MARGIN_AREA])
!         x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
! 
!       if (row->used[TEXT_AREA])
!         x_fix_overlapping_area (w, row, TEXT_AREA);
! 
!       if (row->used[RIGHT_MARGIN_AREA])
!         x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
!       }
! }
! 
! 
! /* Redraw the part of window W intersection rectangle FR.  Pixel
!    coordinates in FR are frame-relative.  Call this function with
!    input blocked.  Value is non-zero if the exposure overwrites
!    mouse-face.  */
! 
! static int
! expose_window (w, fr)
!      struct window *w;
!      XRectangle *fr;
! {
!   struct frame *f = XFRAME (w->frame);
!   XRectangle wr, r;
!   int mouse_face_overwritten_p = 0;
! 
!   /* If window is not yet fully initialized, do nothing.  This can
!      happen when toolkit scroll bars are used and a window is split.
!      Reconfiguring the scroll bar will generate an expose for a newly
!      created window.  */
!   if (w->current_matrix == NULL)
!     return 0;
! 
!   /* When we're currently updating the window, display and current
!      matrix usually don't agree.  Arrange for a thorough display
!      later.  */
!   if (w == updated_window)
!     {
!       SET_FRAME_GARBAGED (f);
!       return 0;
!     }
! 
!   /* Frame-relative pixel rectangle of W.  */
!   wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
!   wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
!   wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
!   wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
! 
!   if (x_intersect_rectangles (fr, &wr, &r))
!     {
!       int yb = window_text_bottom_y (w);
!       struct glyph_row *row;
!       int cursor_cleared_p;
!       struct glyph_row *first_overlapping_row, *last_overlapping_row;
! 
!       TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
!             r.x, r.y, r.width, r.height));
! 
!       /* Convert to window coordinates.  */
!       r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
!       r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
! 
!       /* Turn off the cursor.  */
!       if (!w->pseudo_window_p
!         && x_phys_cursor_in_rect_p (w, &r))
!       {
!         x_clear_cursor (w);
!         cursor_cleared_p = 1;
!       }
!       else
!       cursor_cleared_p = 0;
! 
!       /* Update lines intersecting rectangle R.  */
!       first_overlapping_row = last_overlapping_row = NULL;
!       for (row = w->current_matrix->rows;
!          row->enabled_p;
!          ++row)
!       {
!         int y0 = row->y;
!         int y1 = MATRIX_ROW_BOTTOM_Y (row);
! 
!         if ((y0 >= r.y && y0 < r.y + r.height)
!             || (y1 > r.y && y1 < r.y + r.height)
!             || (r.y >= y0 && r.y < y1)
!             || (r.y + r.height > y0 && r.y + r.height < y1))
!           {
!             if (row->overlapping_p)
!               {
!                 if (first_overlapping_row == NULL)
!                   first_overlapping_row = row;
!                 last_overlapping_row = row;
!               }
! 
!             if (expose_line (w, row, &r))
!               mouse_face_overwritten_p = 1;
!           }
! 
!         if (y1 >= yb)
!           break;
!       }
! 
!       /* Display the mode line if there is one.  */
!       if (WINDOW_WANTS_MODELINE_P (w)
!         && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
!             row->enabled_p)
!         && row->y < r.y + r.height)
!       {
!         if (expose_line (w, row, &r))
!           mouse_face_overwritten_p = 1;
!       }
! 
!       if (!w->pseudo_window_p)
!       {
!         /* Fix the display of overlapping rows.  */
!         if (first_overlapping_row)
!           expose_overlaps (w, first_overlapping_row, last_overlapping_row);
! 
!         /* Draw border between windows.  */
!         x_draw_vertical_border (w);
! 
!         /* Turn the cursor on again.  */
!         if (cursor_cleared_p)
!           x_update_window_cursor (w, 1);
!       }
!     }
! 
!   return mouse_face_overwritten_p;
! }
! 
! 
! /* Determine the intersection of two rectangles R1 and R2.  Return
!    the intersection in *RESULT.  Value is non-zero if RESULT is not
!    empty.  */
! 
! static int
! x_intersect_rectangles (r1, r2, result)
!      XRectangle *r1, *r2, *result;
! {
!   XRectangle *left, *right;
!   XRectangle *upper, *lower;
!   int intersection_p = 0;
! 
!   /* Rearrange so that R1 is the left-most rectangle.  */
!   if (r1->x < r2->x)
!     left = r1, right = r2;
!   else
!     left = r2, right = r1;
! 
!   /* X0 of the intersection is right.x0, if this is inside R1,
!      otherwise there is no intersection.  */
!   if (right->x <= left->x + left->width)
!     {
!       result->x = right->x;
! 
!       /* The right end of the intersection is the minimum of the
!        the right ends of left and right.  */
!       result->width = (min (left->x + left->width, right->x + right->width)
!                      - result->x);
! 
!       /* Same game for Y.  */
!       if (r1->y < r2->y)
!       upper = r1, lower = r2;
!       else
!       upper = r2, lower = r1;
! 
!       /* The upper end of the intersection is lower.y0, if this is inside
!        of upper.  Otherwise, there is no intersection.  */
!       if (lower->y <= upper->y + upper->height)
!       {
!         result->y = lower->y;
! 
!         /* The lower end of the intersection is the minimum of the lower
!            ends of upper and lower.  */
!         result->height = (min (lower->y + lower->height,
!                                upper->y + upper->height)
!                           - result->y);
!         intersection_p = 1;
!       }
!     }
! 
!   return intersection_p;
! }
! 
! 
! 
! 
! 
! static void
! frame_highlight (f)
!      struct frame *f;
! {
!   /* We used to only do this if Vx_no_window_manager was non-nil, but
!      the ICCCM (section 4.1.6) says that the window's border pixmap
!      and border pixel are window attributes which are "private to the
!      client", so we can always change it to whatever we want.  */
!   BLOCK_INPUT;
!   XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
!                   f->output_data.x->border_pixel);
!   UNBLOCK_INPUT;
!   x_update_cursor (f, 1);
! }
! 
! static void
! frame_unhighlight (f)
!      struct frame *f;
! {
!   /* We used to only do this if Vx_no_window_manager was non-nil, but
!      the ICCCM (section 4.1.6) says that the window's border pixmap
!      and border pixel are window attributes which are "private to the
!      client", so we can always change it to whatever we want.  */
!   BLOCK_INPUT;
!   XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
!                         f->output_data.x->border_tile);
!   UNBLOCK_INPUT;
!   x_update_cursor (f, 1);
! }
! 
! /* The focus has changed.  Update the frames as necessary to reflect
!    the new situation.  Note that we can't change the selected frame
!    here, because the Lisp code we are interrupting might become confused.
!    Each event gets marked with the frame in which it occurred, so the
!    Lisp code can tell when the switch took place by examining the events.  */
! 
! static void
! x_new_focus_frame (dpyinfo, frame)
!      struct x_display_info *dpyinfo;
!      struct frame *frame;
! {
!   struct frame *old_focus = dpyinfo->x_focus_frame;
! 
!   if (frame != dpyinfo->x_focus_frame)
!     {
!       /* Set this before calling other routines, so that they see
!        the correct value of x_focus_frame.  */
!       dpyinfo->x_focus_frame = frame;
! 
!       if (old_focus && old_focus->auto_lower)
!       x_lower_frame (old_focus);
! 
! #if 0
!       selected_frame = frame;
!       XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
!                selected_frame);
!       Fselect_window (selected_frame->selected_window);
!       choose_minibuf_frame ();
! #endif /* ! 0 */
! 
!       if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
!       pending_autoraise_frame = dpyinfo->x_focus_frame;
!       else
!       pending_autoraise_frame = 0;
!     }
! 
!   x_frame_rehighlight (dpyinfo);
  }
  
  /* Handle FocusIn and FocusOut state changes for FRAME.
--- 3048,3121 ----
                           Exposure Events
   ***********************************************************************/
  
! 
  static void
! frame_highlight (f)
       struct frame *f;
  {
!   /* We used to only do this if Vx_no_window_manager was non-nil, but
!      the ICCCM (section 4.1.6) says that the window's border pixmap
!      and border pixel are window attributes which are "private to the
!      client", so we can always change it to whatever we want.  */
!   BLOCK_INPUT;
!   XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
!                   f->output_data.x->border_pixel);
!   UNBLOCK_INPUT;
!   x_update_cursor (f, 1);
! }
  
! static void
! frame_unhighlight (f)
!      struct frame *f;
! {
!   /* We used to only do this if Vx_no_window_manager was non-nil, but
!      the ICCCM (section 4.1.6) says that the window's border pixmap
!      and border pixel are window attributes which are "private to the
!      client", so we can always change it to whatever we want.  */
!   BLOCK_INPUT;
!   XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
!                         f->output_data.x->border_tile);
!   UNBLOCK_INPUT;
!   x_update_cursor (f, 1);
! }
  
! /* The focus has changed.  Update the frames as necessary to reflect
!    the new situation.  Note that we can't change the selected frame
!    here, because the Lisp code we are interrupting might become confused.
!    Each event gets marked with the frame in which it occurred, so the
!    Lisp code can tell when the switch took place by examining the events.  */
  
! static void
! x_new_focus_frame (dpyinfo, frame)
!      struct x_display_info *dpyinfo;
!      struct frame *frame;
! {
!   struct frame *old_focus = dpyinfo->x_focus_frame;
  
!   if (frame != dpyinfo->x_focus_frame)
      {
!       /* Set this before calling other routines, so that they see
!        the correct value of x_focus_frame.  */
!       dpyinfo->x_focus_frame = frame;
  
!       if (old_focus && old_focus->auto_lower)
!       x_lower_frame (old_focus);
  
! #if 0
!       selected_frame = frame;
!       XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
!                selected_frame);
!       Fselect_window (selected_frame->selected_window);
!       choose_minibuf_frame ();
! #endif /* ! 0 */
  
!       if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
!       pending_autoraise_frame = dpyinfo->x_focus_frame;
        else
!       pending_autoraise_frame = 0;
      }
  
!   x_frame_rehighlight (dpyinfo);
  }
  
  /* Handle FocusIn and FocusOut state changes for FRAME.
***************
*** 4435,5753 ****
        *frame_x = row->x;
        while (glyph < end)
        {
!         *frame_x += glyph->pixel_width;
!         ++glyph;
!       }
! 
!       success_p = 1;
!     }
!   else
!     {
!       *frame_y = *frame_x = 0;
!       success_p = 0;
!     }
! 
!   *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
!   *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
!   return success_p;
! }
! 
! 
! /* Prepare a mouse-event in *RESULT for placement in the input queue.
! 
!    If the event is a button press, then note that we have grabbed
!    the mouse.  */
! 
! static Lisp_Object
! construct_mouse_click (result, event, f)
!      struct input_event *result;
!      XButtonEvent *event;
!      struct frame *f;
! {
!   /* Make the event type NO_EVENT; we'll change that when we decide
!      otherwise.  */
!   result->kind = MOUSE_CLICK_EVENT;
!   result->code = event->button - Button1;
!   result->timestamp = event->time;
!   result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
!                                              event->state)
!                      | (event->type == ButtonRelease
!                         ? up_modifier
!                         : down_modifier));
! 
!   XSETINT (result->x, event->x);
!   XSETINT (result->y, event->y);
!   XSETFRAME (result->frame_or_window, f);
!   result->arg = Qnil;
!   return Qnil;
! }
! 
! 
! /* Function to report a mouse movement to the mainstream Emacs code.
!    The input handler calls this.
! 
!    We have received a mouse movement event, which is given in *event.
!    If the mouse is over a different glyph than it was last time, tell
!    the mainstream emacs code by setting mouse_moved.  If not, ask for
!    another motion event, so we can check again the next time it moves.  */
! 
! static XMotionEvent last_mouse_motion_event;
! static Lisp_Object last_mouse_motion_frame;
! 
! static void
! note_mouse_movement (frame, event)
!      FRAME_PTR frame;
!      XMotionEvent *event;
! {
!   last_mouse_movement_time = event->time;
!   last_mouse_motion_event = *event;
!   XSETFRAME (last_mouse_motion_frame, frame);
! 
!   if (event->window != FRAME_X_WINDOW (frame))
!     {
!       frame->mouse_moved = 1;
!       last_mouse_scroll_bar = Qnil;
!       note_mouse_highlight (frame, -1, -1);
!     }
! 
!   /* Has the mouse moved off the glyph it was on at the last sighting?  */
!   else if (event->x < last_mouse_glyph.x
!          || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
!          || event->y < last_mouse_glyph.y
!          || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
!     {
!       frame->mouse_moved = 1;
!       last_mouse_scroll_bar = Qnil;
!       note_mouse_highlight (frame, event->x, event->y);
!     }
! }
! 
! 
! /************************************************************************
!                             Mouse Face
!  ************************************************************************/
! 
! /* Find the glyph under window-relative coordinates X/Y in window W.
!    Consider only glyphs from buffer text, i.e. no glyphs from overlay
!    strings.  Return in *HPOS and *VPOS the row and column number of
!    the glyph found.  Return in *AREA the glyph area containing X.
!    Value is a pointer to the glyph found or null if X/Y is not on
!    text, or we can't tell because W's current matrix is not up to
!    date.  */
! 
! static struct glyph *
! x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
!      struct window *w;
!      int x, y;
!      int *hpos, *vpos, *area;
!      int buffer_only_p;
! {
!   struct glyph *glyph, *end;
!   struct glyph_row *row = NULL;
!   int x0, i, left_area_width;
! 
!   /* Find row containing Y.  Give up if some row is not enabled.  */
!   for (i = 0; i < w->current_matrix->nrows; ++i)
!     {
!       row = MATRIX_ROW (w->current_matrix, i);
!       if (!row->enabled_p)
!       return NULL;
!       if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
!       break;
!     }
! 
!   *vpos = i;
!   *hpos = 0;
! 
!   /* Give up if Y is not in the window.  */
!   if (i == w->current_matrix->nrows)
!     return NULL;
! 
!   /* Get the glyph area containing X.  */
!   if (w->pseudo_window_p)
!     {
!       *area = TEXT_AREA;
!       x0 = 0;
!     }
!   else
!     {
!       left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
!       if (x < left_area_width)
!       {
!         *area = LEFT_MARGIN_AREA;
!         x0 = 0;
!       }
!       else if (x < left_area_width + window_box_width (w, TEXT_AREA))
!       {
!         *area = TEXT_AREA;
!         x0 = row->x + left_area_width;
!       }
!       else
!       {
!         *area = RIGHT_MARGIN_AREA;
!         x0 = left_area_width + window_box_width (w, TEXT_AREA);
!       }
!     }
! 
!   /* Find glyph containing X.  */
!   glyph = row->glyphs[*area];
!   end = glyph + row->used[*area];
!   while (glyph < end)
!     {
!       if (x < x0 + glyph->pixel_width)
!       {
!         if (w->pseudo_window_p)
!           break;
!         else if (!buffer_only_p || BUFFERP (glyph->object))
!           break;
!       }
! 
!       x0 += glyph->pixel_width;
!       ++glyph;
!     }
! 
!   if (glyph == end)
!     return NULL;
! 
!   *hpos = glyph - row->glyphs[*area];
!   return glyph;
! }
! 
! 
! /* Convert frame-relative x/y to coordinates relative to window W.
!    Takes pseudo-windows into account.  */
! 
! static void
! frame_to_window_pixel_xy (w, x, y)
!      struct window *w;
!      int *x, *y;
! {
!   if (w->pseudo_window_p)
!     {
!       /* A pseudo-window is always full-width, and starts at the
!        left edge of the frame, plus a frame border.  */
!       struct frame *f = XFRAME (w->frame);
!       *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
!       *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
!     }
!   else
!     {
!       *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
!       *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
!     }
! }
! 
! 
! /* Take proper action when mouse has moved to the mode or header line
!    or marginal area of window W, x-position X and y-position Y.  Area
!    is 1, 3, 6 or 7 for the mode line, header line, left and right
!    marginal area respectively.  X is relative to the start of the text
!    display area of W, so the width of bitmap areas and scroll bars
!    must be subtracted to get a position relative to the start of the
!    mode line.  */
! 
! static void
! note_mode_line_or_margin_highlight (w, x, y, portion)
!      struct window *w;
!      int x, y, portion;
! {
!   struct frame *f = XFRAME (w->frame);
!   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
!   Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
!   int charpos;
!   Lisp_Object string, help, map, pos;
! 
!   if (portion == 1 || portion == 3)
!     string = mode_line_string (w, x, y, portion == 1, &charpos);
!    else
!      string = marginal_area_string (w, x, y, portion, &charpos);
! 
!   if (STRINGP (string))
!     {
!       pos = make_number (charpos);
! 
!       /* If we're on a string with `help-echo' text property, arrange
!        for the help to be displayed.  This is done by setting the
!        global variable help_echo to the help string.  */
!       help = Fget_text_property (pos, Qhelp_echo, string);
!       if (!NILP (help))
!       {
!         help_echo = help;
!         XSETWINDOW (help_echo_window, w);
!         help_echo_object = string;
!         help_echo_pos = charpos;
!       }
! 
!      /* Change the mouse pointer according to what is under X/Y.  */
!       map = Fget_text_property (pos, Qlocal_map, string);
!       if (!KEYMAPP (map))
!       map = Fget_text_property (pos, Qkeymap, string);
!       if (KEYMAPP (map))
!       cursor = f->output_data.x->nontext_cursor;
!     }
! 
!   XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
! }
! 
! 
! /* Take proper action when the mouse has moved to position X, Y on
!    frame F as regards highlighting characters that have mouse-face
!    properties.  Also de-highlighting chars where the mouse was before.
!    X and Y can be negative or out of range.  */
! 
! static void
! note_mouse_highlight (f, x, y)
!      struct frame *f;
!      int x, y;
! {
!   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
!   int portion;
!   Lisp_Object window;
!   struct window *w;
!   Cursor cursor = None;
!   struct buffer *b;
! 
!   /* When a menu is active, don't highlight because this looks odd.  */
! #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
!   if (popup_activated ())
!     return;
! #endif
! 
!   if (NILP (Vmouse_highlight)
!       || !f->glyphs_initialized_p)
!     return;
! 
!   dpyinfo->mouse_face_mouse_x = x;
!   dpyinfo->mouse_face_mouse_y = y;
!   dpyinfo->mouse_face_mouse_frame = f;
! 
!   if (dpyinfo->mouse_face_defer)
!     return;
! 
!   if (gc_in_progress)
!     {
!       dpyinfo->mouse_face_deferred_gc = 1;
!       return;
!     }
! 
!   /* Which window is that in?  */
!   window = window_from_coordinates (f, x, y, &portion, 1);
! 
!   /* If we were displaying active text in another window, clear that.  */
!   if (! EQ (window, dpyinfo->mouse_face_window))
!     clear_mouse_face (dpyinfo);
! 
!   /* Not on a window -> return.  */
!   if (!WINDOWP (window))
!     return;
! 
!   /* Convert to window-relative pixel coordinates.  */
!   w = XWINDOW (window);
!   frame_to_window_pixel_xy (w, &x, &y);
! 
!   /* Handle tool-bar window differently since it doesn't display a
!      buffer.  */
!   if (EQ (window, f->tool_bar_window))
!     {
!       note_tool_bar_highlight (f, x, y);
!       return;
!     }
! 
!   /* Mouse is on the mode, header line or margin?  */
!   if (portion == 1 || portion == 3 || portion == 6 || portion == 7)
!     {
!       note_mode_line_or_margin_highlight (w, x, y, portion);
!       return;
!     }
! 
!   if (portion == 2)
!     cursor = f->output_data.x->horizontal_drag_cursor;
!   else
!     cursor = f->output_data.x->text_cursor;
! 
!   /* Are we in a window whose display is up to date?
!      And verify the buffer's text has not changed.  */
!   b = XBUFFER (w->buffer);
!   if (/* Within text portion of the window.  */
!       portion == 0
!       && EQ (w->window_end_valid, w->buffer)
!       && XFASTINT (w->last_modified) == BUF_MODIFF (b)
!       && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
!     {
!       int hpos, vpos, pos, i, area;
!       struct glyph *glyph;
!       Lisp_Object object;
!       Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
!       Lisp_Object *overlay_vec = NULL;
!       int len, noverlays;
!       struct buffer *obuf;
!       int obegv, ozv, same_region;
! 
!       /* Find the glyph under X/Y.  */
!       glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
! 
!       /* Clear mouse face if X/Y not over text.  */
!       if (glyph == NULL
!         || area != TEXT_AREA
!         || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
!       {
!         if (clear_mouse_face (dpyinfo))
!           cursor = None;
!         goto set_cursor;
!       }
! 
!       pos = glyph->charpos;
!       object = glyph->object;
!       if (!STRINGP (object) && !BUFFERP (object))
!       goto set_cursor;
! 
!       /* If we get an out-of-range value, return now; avoid an error.  */
!       if (BUFFERP (object) && pos > BUF_Z (b))
!       goto set_cursor;
! 
!       /* Make the window's buffer temporarily current for
!        overlays_at and compute_char_face.  */
!       obuf = current_buffer;
!       current_buffer = b;
!       obegv = BEGV;
!       ozv = ZV;
!       BEGV = BEG;
!       ZV = Z;
! 
!       /* Is this char mouse-active or does it have help-echo?  */
!       position = make_number (pos);
! 
!       if (BUFFERP (object))
!       {
!         /* Put all the overlays we want in a vector in overlay_vec.
!            Store the length in len.  If there are more than 10, make
!            enough space for all, and try again.  */
!         len = 10;
!         overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
!         noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
!         if (noverlays > len)
!           {
!             len = noverlays;
!             overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
!             noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, 
NULL,0);
!           }
! 
!         /* Sort overlays into increasing priority order.  */
!         noverlays = sort_overlays (overlay_vec, noverlays, w);
!       }
!       else
!       noverlays = 0;
! 
!       same_region = (EQ (window, dpyinfo->mouse_face_window)
!                    && vpos >= dpyinfo->mouse_face_beg_row
!                    && vpos <= dpyinfo->mouse_face_end_row
!                    && (vpos > dpyinfo->mouse_face_beg_row
!                        || hpos >= dpyinfo->mouse_face_beg_col)
!                    && (vpos < dpyinfo->mouse_face_end_row
!                        || hpos < dpyinfo->mouse_face_end_col
!                        || dpyinfo->mouse_face_past_end));
! 
!       if (same_region)
!       cursor = None;
! 
!       /* Check mouse-face highlighting.  */
!       if (! same_region
!         /* If there exists an overlay with mouse-face overlapping
!            the one we are currently highlighting, we have to
!            check if we enter the overlapping overlay, and then
!            highlight only that.  */
!         || (OVERLAYP (dpyinfo->mouse_face_overlay)
!             && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
!       {
!         /* Find the highest priority overlay that has a mouse-face
!            property.  */
!         overlay = Qnil;
!         for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
!           {
!             mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
!             if (!NILP (mouse_face))
!               overlay = overlay_vec[i];
!           }
! 
!         /* If we're actually highlighting the same overlay as
!            before, there's no need to do that again.  */
!         if (!NILP (overlay)
!             && EQ (overlay, dpyinfo->mouse_face_overlay))
!           goto check_help_echo;
! 
!         dpyinfo->mouse_face_overlay = overlay;
! 
!         /* Clear the display of the old active region, if any.  */
!         if (clear_mouse_face (dpyinfo))
!           cursor = None;
! 
!         /* If no overlay applies, get a text property.  */
!         if (NILP (overlay))
!           mouse_face = Fget_text_property (position, Qmouse_face, object);
! 
!         /* Handle the overlay case.  */
!         if (!NILP (overlay))
!           {
!             /* Find the range of text around this char that
!                should be active.  */
!             Lisp_Object before, after;
!             int ignore;
! 
!             before = Foverlay_start (overlay);
!             after = Foverlay_end (overlay);
!             /* Record this as the current active region.  */
!             fast_find_position (w, XFASTINT (before),
!                                 &dpyinfo->mouse_face_beg_col,
!                                 &dpyinfo->mouse_face_beg_row,
!                                 &dpyinfo->mouse_face_beg_x,
!                                 &dpyinfo->mouse_face_beg_y, Qnil);
! 
!             dpyinfo->mouse_face_past_end
!               = !fast_find_position (w, XFASTINT (after),
!                                      &dpyinfo->mouse_face_end_col,
!                                      &dpyinfo->mouse_face_end_row,
!                                      &dpyinfo->mouse_face_end_x,
!                                      &dpyinfo->mouse_face_end_y, Qnil);
!             dpyinfo->mouse_face_window = window;
!             dpyinfo->mouse_face_face_id
!               = face_at_buffer_position (w, pos, 0, 0,
!                                          &ignore, pos + 1,
!                                          !dpyinfo->mouse_face_hidden);
! 
!             /* Display it as active.  */
!             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
!             cursor = None;
!           }
!         /* Handle the text property case.  */
!         else if (!NILP (mouse_face) && BUFFERP (object))
!           {
!             /* Find the range of text around this char that
!                should be active.  */
!             Lisp_Object before, after, beginning, end;
!             int ignore;
! 
!             beginning = Fmarker_position (w->start);
!             end = make_number (BUF_Z (XBUFFER (object))
!                                - XFASTINT (w->window_end_pos));
!             before
!               = Fprevious_single_property_change (make_number (pos + 1),
!                                                   Qmouse_face,
!                                                   object, beginning);
!             after
!               = Fnext_single_property_change (position, Qmouse_face,
!                                               object, end);
! 
!             /* Record this as the current active region.  */
!             fast_find_position (w, XFASTINT (before),
!                                 &dpyinfo->mouse_face_beg_col,
!                                 &dpyinfo->mouse_face_beg_row,
!                                 &dpyinfo->mouse_face_beg_x,
!                                 &dpyinfo->mouse_face_beg_y, Qnil);
!             dpyinfo->mouse_face_past_end
!               = !fast_find_position (w, XFASTINT (after),
!                                      &dpyinfo->mouse_face_end_col,
!                                      &dpyinfo->mouse_face_end_row,
!                                      &dpyinfo->mouse_face_end_x,
!                                      &dpyinfo->mouse_face_end_y, Qnil);
!             dpyinfo->mouse_face_window = window;
! 
!             if (BUFFERP (object))
!               dpyinfo->mouse_face_face_id
!                 = face_at_buffer_position (w, pos, 0, 0,
!                                            &ignore, pos + 1,
!                                            !dpyinfo->mouse_face_hidden);
! 
!             /* Display it as active.  */
!             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
!             cursor = None;
!           }
!         else if (!NILP (mouse_face) && STRINGP (object))
!           {
!             Lisp_Object b, e;
!             int ignore;
! 
!             b = Fprevious_single_property_change (make_number (pos + 1),
!                                                   Qmouse_face,
!                                                   object, Qnil);
!             e = Fnext_single_property_change (position, Qmouse_face,
!                                               object, Qnil);
!             if (NILP (b))
!               b = make_number (0);
!             if (NILP (e))
!               e = make_number (SCHARS (object) - 1);
!             fast_find_string_pos (w, XINT (b), object,
!                                   &dpyinfo->mouse_face_beg_col,
!                                   &dpyinfo->mouse_face_beg_row,
!                                   &dpyinfo->mouse_face_beg_x,
!                                   &dpyinfo->mouse_face_beg_y, 0);
!             fast_find_string_pos (w, XINT (e), object,
!                                   &dpyinfo->mouse_face_end_col,
!                                   &dpyinfo->mouse_face_end_row,
!                                   &dpyinfo->mouse_face_end_x,
!                                   &dpyinfo->mouse_face_end_y, 1);
!             dpyinfo->mouse_face_past_end = 0;
!             dpyinfo->mouse_face_window = window;
!             dpyinfo->mouse_face_face_id
!               = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
!                                          glyph->face_id, 1);
!             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
!             cursor = None;
!           }
!         else if (STRINGP (object) && NILP (mouse_face))
!           {
!             /* A string which doesn't have mouse-face, but
!                the text ``under'' it might have.  */
!             struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
!             int start = MATRIX_ROW_START_CHARPOS (r);
! 
!             pos = string_buffer_position (w, object, start);
!             if (pos > 0)
!               mouse_face = get_char_property_and_overlay (make_number (pos),
!                                                           Qmouse_face,
!                                                           w->buffer,
!                                                           &overlay);
!             if (!NILP (mouse_face) && !NILP (overlay))
!               {
!                 Lisp_Object before = Foverlay_start (overlay);
!                 Lisp_Object after = Foverlay_end (overlay);
!                 int ignore;
! 
!                 /* Note that we might not be able to find position
!                    BEFORE in the glyph matrix if the overlay is
!                    entirely covered by a `display' property.  In
!                    this case, we overshoot.  So let's stop in
!                    the glyph matrix before glyphs for OBJECT.  */
!                 fast_find_position (w, XFASTINT (before),
!                                     &dpyinfo->mouse_face_beg_col,
!                                     &dpyinfo->mouse_face_beg_row,
!                                     &dpyinfo->mouse_face_beg_x,
!                                     &dpyinfo->mouse_face_beg_y,
!                                     object);
! 
!                 dpyinfo->mouse_face_past_end
!                   = !fast_find_position (w, XFASTINT (after),
!                                          &dpyinfo->mouse_face_end_col,
!                                          &dpyinfo->mouse_face_end_row,
!                                          &dpyinfo->mouse_face_end_x,
!                                          &dpyinfo->mouse_face_end_y,
!                                          Qnil);
!                 dpyinfo->mouse_face_window = window;
!                 dpyinfo->mouse_face_face_id
!                   = face_at_buffer_position (w, pos, 0, 0,
!                                              &ignore, pos + 1,
!                                              !dpyinfo->mouse_face_hidden);
! 
!                 /* Display it as active.  */
!                 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
!                 cursor = None;
!               }
!           }
!       }
! 
!     check_help_echo:
! 
!       /* Look for a `help-echo' property.  */
!       {
!       Lisp_Object help, overlay;
! 
!       /* Check overlays first.  */
!       help = overlay = Qnil;
!       for (i = noverlays - 1; i >= 0 && NILP (help); --i)
!         {
!           overlay = overlay_vec[i];
!           help = Foverlay_get (overlay, Qhelp_echo);
!         }
! 
!       if (!NILP (help))
!         {
!           help_echo = help;
!           help_echo_window = window;
!           help_echo_object = overlay;
!           help_echo_pos = pos;
!         }
!       else
!         {
!           Lisp_Object object = glyph->object;
!           int charpos = glyph->charpos;
! 
!           /* Try text properties.  */
!           if (STRINGP (object)
!               && charpos >= 0
!               && charpos < SCHARS (object))
!             {
!               help = Fget_text_property (make_number (charpos),
!                                          Qhelp_echo, object);
!               if (NILP (help))
!                 {
!                   /* If the string itself doesn't specify a help-echo,
!                      see if the buffer text ``under'' it does.  */
!                   struct glyph_row *r
!                     = MATRIX_ROW (w->current_matrix, vpos);
!                   int start = MATRIX_ROW_START_CHARPOS (r);
!                   int pos = string_buffer_position (w, object, start);
!                   if (pos > 0)
!                     {
!                       help = Fget_char_property (make_number (pos),
!                                                  Qhelp_echo, w->buffer);
!                       if (!NILP (help))
!                         {
!                           charpos = pos;
!                           object = w->buffer;
!                         }
!                     }
!                 }
!             }
!           else if (BUFFERP (object)
!                    && charpos >= BEGV
!                    && charpos < ZV)
!             help = Fget_text_property (make_number (charpos), Qhelp_echo,
!                                        object);
! 
!           if (!NILP (help))
!             {
!               help_echo = help;
!               help_echo_window = window;
!               help_echo_object = object;
!               help_echo_pos = charpos;
!             }
!         }
!       }
! 
!       BEGV = obegv;
!       ZV = ozv;
!       current_buffer = obuf;
!     }
! 
!  set_cursor:
! 
!   if (cursor != None)
!     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
! }
! 
! static void
! redo_mouse_highlight ()
! {
!   if (!NILP (last_mouse_motion_frame)
!       && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
!     note_mouse_highlight (XFRAME (last_mouse_motion_frame),
!                         last_mouse_motion_event.x,
!                         last_mouse_motion_event.y);
! }
! 
! 
! 
! /***********************************************************************
!                              Tool-bars
!  ***********************************************************************/
! 
! static int x_tool_bar_item P_ ((struct frame *, int, int,
!                               struct glyph **, int *, int *, int *));
! 
! /* Tool-bar item index of the item on which a mouse button was pressed
!    or -1.  */
! 
! static int last_tool_bar_item;
! 
! 
! /* Get information about the tool-bar item at position X/Y on frame F.
!    Return in *GLYPH a pointer to the glyph of the tool-bar item in
!    the current matrix of the tool-bar window of F, or NULL if not
!    on a tool-bar item.  Return in *PROP_IDX the index of the tool-bar
!    item in F->tool_bar_items.  Value is
! 
!    -1 if X/Y is not on a tool-bar item
!    0  if X/Y is on the same item that was highlighted before.
!    1  otherwise.  */
! 
! static int
! x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
!      struct frame *f;
!      int x, y;
!      struct glyph **glyph;
!      int *hpos, *vpos, *prop_idx;
! {
!   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
!   struct window *w = XWINDOW (f->tool_bar_window);
!   int area;
! 
!   /* Find the glyph under X/Y.  */
!   *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
!   if (*glyph == NULL)
!     return -1;
! 
!   /* Get the start of this tool-bar item's properties in
!      f->tool_bar_items.  */
!   if (!tool_bar_item_info (f, *glyph, prop_idx))
!     return -1;
! 
!   /* Is mouse on the highlighted item?  */
!   if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
!       && *vpos >= dpyinfo->mouse_face_beg_row
!       && *vpos <= dpyinfo->mouse_face_end_row
!       && (*vpos > dpyinfo->mouse_face_beg_row
!         || *hpos >= dpyinfo->mouse_face_beg_col)
!       && (*vpos < dpyinfo->mouse_face_end_row
!         || *hpos < dpyinfo->mouse_face_end_col
!         || dpyinfo->mouse_face_past_end))
!     return 0;
! 
!   return 1;
! }
! 
! 
! /* Handle mouse button event on the tool-bar of frame F, at
!    frame-relative coordinates X/Y.  EVENT_TYPE is either ButtonPress
!    or ButtonRelase.  */
! 
! static void
! x_handle_tool_bar_click (f, button_event)
!      struct frame *f;
!      XButtonEvent *button_event;
! {
!   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
!   struct window *w = XWINDOW (f->tool_bar_window);
!   int hpos, vpos, prop_idx;
!   struct glyph *glyph;
!   Lisp_Object enabled_p;
!   int x = button_event->x;
!   int y = button_event->y;
! 
!   /* If not on the highlighted tool-bar item, return.  */
!   frame_to_window_pixel_xy (w, &x, &y);
!   if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
!     return;
! 
!   /* If item is disabled, do nothing.  */
!   enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
!   if (NILP (enabled_p))
!     return;
! 
!   if (button_event->type == ButtonPress)
!     {
!       /* Show item in pressed state.  */
!       show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
!       dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
!       last_tool_bar_item = prop_idx;
!     }
!   else
!     {
!       Lisp_Object key, frame;
!       struct input_event event;
! 
!       /* Show item in released state.  */
!       show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
!       dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
! 
!       key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
! 
!       XSETFRAME (frame, f);
!       event.kind = TOOL_BAR_EVENT;
!       event.frame_or_window = frame;
!       event.arg = frame;
!       kbd_buffer_store_event (&event);
! 
!       event.kind = TOOL_BAR_EVENT;
!       event.frame_or_window = frame;
!       event.arg = key;
!       event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
!                                               button_event->state);
!       kbd_buffer_store_event (&event);
!       last_tool_bar_item = -1;
!     }
! }
! 
! 
! /* Possibly highlight a tool-bar item on frame F when mouse moves to
!    tool-bar window-relative coordinates X/Y.  Called from
!    note_mouse_highlight.  */
! 
! static void
! note_tool_bar_highlight (f, x, y)
!      struct frame *f;
!      int x, y;
! {
!   Lisp_Object window = f->tool_bar_window;
!   struct window *w = XWINDOW (window);
!   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
!   int hpos, vpos;
!   struct glyph *glyph;
!   struct glyph_row *row;
!   int i;
!   Lisp_Object enabled_p;
!   int prop_idx;
!   enum draw_glyphs_face draw;
!   int mouse_down_p, rc;
! 
!   /* Function note_mouse_highlight is called with negative x(y
!      values when mouse moves outside of the frame.  */
!   if (x <= 0 || y <= 0)
!     {
!       clear_mouse_face (dpyinfo);
!       return;
!     }
! 
!   rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
!   if (rc < 0)
!     {
!       /* Not on tool-bar item.  */
!       clear_mouse_face (dpyinfo);
!       return;
!     }
!   else if (rc == 0)
!     goto set_help_echo;
! 
!   clear_mouse_face (dpyinfo);
! 
!   /* Mouse is down, but on different tool-bar item?  */
!   mouse_down_p = (dpyinfo->grabbed
!                 && f == last_mouse_frame
!                 && FRAME_LIVE_P (f));
!   if (mouse_down_p
!       && last_tool_bar_item != prop_idx)
!     return;
! 
!   dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
!   draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
! 
!   /* If tool-bar item is not enabled, don't highlight it.  */
!   enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
!   if (!NILP (enabled_p))
!     {
!       /* Compute the x-position of the glyph.  In front and past the
!        image is a space.  We include this is the highlighted area.  */
!       row = MATRIX_ROW (w->current_matrix, vpos);
!       for (i = x = 0; i < hpos; ++i)
!       x += row->glyphs[TEXT_AREA][i].pixel_width;
! 
!       /* Record this as the current active region.  */
!       dpyinfo->mouse_face_beg_col = hpos;
!       dpyinfo->mouse_face_beg_row = vpos;
!       dpyinfo->mouse_face_beg_x = x;
!       dpyinfo->mouse_face_beg_y = row->y;
!       dpyinfo->mouse_face_past_end = 0;
! 
!       dpyinfo->mouse_face_end_col = hpos + 1;
!       dpyinfo->mouse_face_end_row = vpos;
!       dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
!       dpyinfo->mouse_face_end_y = row->y;
!       dpyinfo->mouse_face_window = window;
!       dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
! 
!       /* Display it as active.  */
!       show_mouse_face (dpyinfo, draw);
!       dpyinfo->mouse_face_image_state = draw;
!     }
! 
!  set_help_echo:
! 
!   /* Set help_echo to a help string to display for this tool-bar item.
!      XTread_socket does the rest.  */
!   help_echo_object = help_echo_window = Qnil;
!   help_echo_pos = -1;
!   help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
!   if (NILP (help_echo))
!     help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
! }
! 
! 
! 
! /* Find the glyph matrix position of buffer position CHARPOS in window
!    *W.  HPOS, *VPOS, *X, and *Y are set to the positions found.  W's
!    current glyphs must be up to date.  If CHARPOS is above window
!    start return (0, 0, 0, 0).  If CHARPOS is after end of W, return end
!    of last line in W.  In the row containing CHARPOS, stop before glyphs
!    having STOP as object.  */
! 
! #if 0 /* This is a version of fast_find_position that's more correct
!        in the presence of hscrolling, for example.  I didn't install
!        it right away because the problem fixed is minor, it failed
!        in 20.x as well, and I think it's too risky to install
!        so near the release of 21.1.  2001-09-25 gerd.  */
! 
! static int
! fast_find_position (w, charpos, hpos, vpos, x, y, stop)
!      struct window *w;
!      int charpos;
!      int *hpos, *vpos, *x, *y;
!      Lisp_Object stop;
! {
!   struct glyph_row *row, *first;
!   struct glyph *glyph, *end;
!   int i, past_end = 0;
! 
!   first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
!   row = row_containing_pos (w, charpos, first, NULL, 0);
!   if (row == NULL)
!     {
!       if (charpos < MATRIX_ROW_START_CHARPOS (first))
!       {
!         *x = *y = *hpos = *vpos = 0;
!         return 0;
!       }
!       else
!       {
!         row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
!         past_end = 1;
!       }
!     }
! 
!   *x = row->x;
!   *y = row->y;
!   *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
! 
!   glyph = row->glyphs[TEXT_AREA];
!   end = glyph + row->used[TEXT_AREA];
! 
!   /* Skip over glyphs not having an object at the start of the row.
!      These are special glyphs like truncation marks on terminal
!      frames.  */
!   if (row->displays_text_p)
!     while (glyph < end
!          && INTEGERP (glyph->object)
!          && !EQ (stop, glyph->object)
!          && glyph->charpos < 0)
!       {
!       *x += glyph->pixel_width;
!       ++glyph;
!       }
! 
!   while (glyph < end
!        && !INTEGERP (glyph->object)
!        && !EQ (stop, glyph->object)
!        && (!BUFFERP (glyph->object)
!            || glyph->charpos < charpos))
!     {
!       *x += glyph->pixel_width;
!       ++glyph;
!     }
! 
!   *hpos = glyph - row->glyphs[TEXT_AREA];
!   return past_end;
! }
! 
! #else /* not 0 */
! 
! static int
! fast_find_position (w, pos, hpos, vpos, x, y, stop)
!      struct window *w;
!      int pos;
!      int *hpos, *vpos, *x, *y;
!      Lisp_Object stop;
! {
!   int i;
!   int lastcol;
!   int maybe_next_line_p = 0;
!   int line_start_position;
!   int yb = window_text_bottom_y (w);
!   struct glyph_row *row, *best_row;
!   int row_vpos, best_row_vpos;
!   int current_x;
! 
!   row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
!   row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
! 
!   while (row->y < yb)
!     {
!       if (row->used[TEXT_AREA])
!       line_start_position = row->glyphs[TEXT_AREA]->charpos;
!       else
!       line_start_position = 0;
! 
!       if (line_start_position > pos)
!       break;
!       /* If the position sought is the end of the buffer,
!        don't include the blank lines at the bottom of the window.  */
!       else if (line_start_position == pos
!              && pos == BUF_ZV (XBUFFER (w->buffer)))
!       {
!         maybe_next_line_p = 1;
!         break;
!       }
!       else if (line_start_position > 0)
!       {
!         best_row = row;
!         best_row_vpos = row_vpos;
!       }
! 
!       if (row->y + row->height >= yb)
!       break;
! 
!       ++row;
!       ++row_vpos;
!     }
! 
!   /* Find the right column within BEST_ROW.  */
!   lastcol = 0;
!   current_x = best_row->x;
!   for (i = 0; i < best_row->used[TEXT_AREA]; i++)
!     {
!       struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
!       int charpos = glyph->charpos;
! 
!       if (BUFFERP (glyph->object))
!       {
!         if (charpos == pos)
!           {
!             *hpos = i;
!             *vpos = best_row_vpos;
!             *x = current_x;
!             *y = best_row->y;
!             return 1;
!           }
!         else if (charpos > pos)
!           break;
!       }
!       else if (EQ (glyph->object, stop))
!       break;
! 
!       if (charpos > 0)
!       lastcol = i;
!       current_x += glyph->pixel_width;
!     }
! 
!   /* If we're looking for the end of the buffer,
!      and we didn't find it in the line we scanned,
!      use the start of the following line.  */
!   if (maybe_next_line_p)
!     {
!       ++best_row;
!       ++best_row_vpos;
!       lastcol = 0;
!       current_x = best_row->x;
!     }
! 
!   *vpos = best_row_vpos;
!   *hpos = lastcol + 1;
!   *x = current_x;
!   *y = best_row->y;
!   return 0;
! }
! 
! #endif /* not 0 */
! 
! 
! /* Find the position of the glyph for position POS in OBJECT in
!    window W's current matrix, and return in *X, *Y the pixel
!    coordinates, and return in *HPOS, *VPOS the column/row of the glyph.
! 
!    RIGHT_P non-zero means return the position of the right edge of the
!    glyph, RIGHT_P zero means return the left edge position.
! 
!    If no glyph for POS exists in the matrix, return the position of
!    the glyph with the next smaller position that is in the matrix, if
!    RIGHT_P is zero.  If RIGHT_P is non-zero, and no glyph for POS
!    exists in the matrix, return the position of the glyph with the
!    next larger position in OBJECT.
! 
!    Value is non-zero if a glyph was found.  */
! 
! static int
! fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
!      struct window *w;
!      int pos;
!      Lisp_Object object;
!      int *hpos, *vpos, *x, *y;
!      int right_p;
! {
!   int yb = window_text_bottom_y (w);
!   struct glyph_row *r;
!   struct glyph *best_glyph = NULL;
!   struct glyph_row *best_row = NULL;
!   int best_x = 0;
! 
!   for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
!        r->enabled_p && r->y < yb;
!        ++r)
!     {
!       struct glyph *g = r->glyphs[TEXT_AREA];
!       struct glyph *e = g + r->used[TEXT_AREA];
!       int gx;
! 
!       for (gx = r->x; g < e; gx += g->pixel_width, ++g)
!       if (EQ (g->object, object))
!         {
!           if (g->charpos == pos)
!             {
!               best_glyph = g;
!               best_x = gx;
!               best_row = r;
!               goto found;
!             }
!           else if (best_glyph == NULL
!                    || ((abs (g->charpos - pos)
!                        < abs (best_glyph->charpos - pos))
!                        && (right_p
!                            ? g->charpos < pos
!                            : g->charpos > pos)))
!             {
!               best_glyph = g;
!               best_x = gx;
!               best_row = r;
!             }
!         }
!     }
! 
!  found:
! 
!   if (best_glyph)
!     {
!       *x = best_x;
!       *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
! 
!       if (right_p)
!       {
!         *x += best_glyph->pixel_width;
!         ++*hpos;
!       }
! 
!       *y = best_row->y;
!       *vpos = best_row - w->current_matrix->rows;
!     }
! 
!   return best_glyph != NULL;
! }
! 
! 
! /* Display the active region described by mouse_face_*
!    in its mouse-face if HL > 0, in its normal face if HL = 0.  */
! 
! static void
! show_mouse_face (dpyinfo, draw)
!      struct x_display_info *dpyinfo;
!      enum draw_glyphs_face draw;
! {
!   struct window *w = XWINDOW (dpyinfo->mouse_face_window);
!   struct frame *f = XFRAME (WINDOW_FRAME (w));
! 
!   if (/* If window is in the process of being destroyed, don't bother
!        to do anything.  */
!       w->current_matrix != NULL
!       /* Don't update mouse highlight if hidden */
!       && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
!       /* Recognize when we are called to operate on rows that don't exist
!        anymore.  This can happen when a window is split.  */
!       && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
!     {
!       int phys_cursor_on_p = w->phys_cursor_on_p;
!       struct glyph_row *row, *first, *last;
! 
!       first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
!       last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
! 
!       for (row = first; row <= last && row->enabled_p; ++row)
!       {
!         int start_hpos, end_hpos, start_x;
! 
!         /* For all but the first row, the highlight starts at column 0.  */
!         if (row == first)
!           {
!             start_hpos = dpyinfo->mouse_face_beg_col;
!             start_x = dpyinfo->mouse_face_beg_x;
!           }
!         else
!           {
!             start_hpos = 0;
!             start_x = 0;
!           }
! 
!         if (row == last)
!           end_hpos = dpyinfo->mouse_face_end_col;
!         else
!           end_hpos = row->used[TEXT_AREA];
! 
!         if (end_hpos > start_hpos)
!           {
!             x_draw_glyphs (w, start_x, row, TEXT_AREA,
!                            start_hpos, end_hpos, draw, 0);
! 
!             row->mouse_face_p
!               = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
!           }
        }
  
!       /* When we've written over the cursor, arrange for it to
!        be displayed again.  */
!       if (phys_cursor_on_p && !w->phys_cursor_on_p)
!       x_display_cursor (w, 1,
!                         w->phys_cursor.hpos, w->phys_cursor.vpos,
!                         w->phys_cursor.x, w->phys_cursor.y);
!     }
! 
!   /* Change the mouse cursor.  */
!   if (draw == DRAW_NORMAL_TEXT)
!     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
!                  f->output_data.x->text_cursor);
!   else if (draw == DRAW_MOUSE_FACE)
!     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
!                  f->output_data.x->cross_cursor);
!   else
!     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
!                  f->output_data.x->nontext_cursor);
! }
! 
! /* Clear out the mouse-highlighted active region.
!    Redraw it un-highlighted first.  Value is non-zero if mouse
!    face was actually drawn unhighlighted.  */
! 
! static int
! clear_mouse_face (dpyinfo)
!      struct x_display_info *dpyinfo;
! {
!   int cleared = 0;
! 
!   if (!NILP (dpyinfo->mouse_face_window))
      {
!       show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
!       cleared = 1;
      }
  
!   dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
!   dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
!   dpyinfo->mouse_face_window = Qnil;
!   dpyinfo->mouse_face_overlay = Qnil;
!   return cleared;
  }
  
  
! /* Clear any mouse-face on window W.  This function is part of the
!    redisplay interface, and is called from try_window_id and similar
!    functions to ensure the mouse-highlight is off.  */
  
! static void
! x_clear_mouse_face (w)
!      struct window *w;
  {
!   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
!   Lisp_Object window;
  
!   BLOCK_INPUT;
!   XSETWINDOW (window, w);
!   if (EQ (window, dpyinfo->mouse_face_window))
!     clear_mouse_face (dpyinfo);
!   UNBLOCK_INPUT;
  }
  
  
! /* Just discard the mouse face information for frame F, if any.
!    This is used when the size of F is changed.  */
  
! void
! cancel_mouse_face (f)
!      FRAME_PTR f;
  {
!   Lisp_Object window;
!   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
  
!   window = dpyinfo->mouse_face_window;
!   if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
      {
!       dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
!       dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
!       dpyinfo->mouse_face_window = Qnil;
      }
  }
  
  
  static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
  
  
--- 3549,3657 ----
        *frame_x = row->x;
        while (glyph < end)
        {
!         *frame_x += glyph->pixel_width;
!         ++glyph;
        }
  
!       success_p = 1;
!     }
!   else
      {
!       *frame_y = *frame_x = 0;
!       success_p = 0;
      }
  
!   *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
!   *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
!   return success_p;
  }
  
  
! /* Prepare a mouse-event in *RESULT for placement in the input queue.
  
!    If the event is a button press, then note that we have grabbed
!    the mouse.  */
! 
! static Lisp_Object
! construct_mouse_click (result, event, f)
!      struct input_event *result;
!      XButtonEvent *event;
!      struct frame *f;
  {
!   /* Make the event type NO_EVENT; we'll change that when we decide
!      otherwise.  */
!   result->kind = MOUSE_CLICK_EVENT;
!   result->code = event->button - Button1;
!   result->timestamp = event->time;
!   result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
!                                              event->state)
!                      | (event->type == ButtonRelease
!                         ? up_modifier
!                         : down_modifier));
  
!   XSETINT (result->x, event->x);
!   XSETINT (result->y, event->y);
!   XSETFRAME (result->frame_or_window, f);
!   result->arg = Qnil;
!   return Qnil;
  }
  
+ 
+ /* Function to report a mouse movement to the mainstream Emacs code.
+    The input handler calls this.
+ 
+    We have received a mouse movement event, which is given in *event.
+    If the mouse is over a different glyph than it was last time, tell
+    the mainstream emacs code by setting mouse_moved.  If not, ask for
+    another motion event, so we can check again the next time it moves.  */
  
! static XMotionEvent last_mouse_motion_event;
! static Lisp_Object last_mouse_motion_frame;
  
! static void
! note_mouse_movement (frame, event)
!      FRAME_PTR frame;
!      XMotionEvent *event;
  {
!   last_mouse_movement_time = event->time;
!   last_mouse_motion_event = *event;
!   XSETFRAME (last_mouse_motion_frame, frame);
  
!   if (event->window != FRAME_X_WINDOW (frame))
      {
!       frame->mouse_moved = 1;
!       last_mouse_scroll_bar = Qnil;
!       note_mouse_highlight (frame, -1, -1);
!     }
! 
!   /* Has the mouse moved off the glyph it was on at the last sighting?  */
!   else if (event->x < last_mouse_glyph.x
!          || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
!          || event->y < last_mouse_glyph.y
!          || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
!     {
!       frame->mouse_moved = 1;
!       last_mouse_scroll_bar = Qnil;
!       note_mouse_highlight (frame, event->x, event->y);
      }
  }
  
  
+ /************************************************************************
+                             Mouse Face
+  ************************************************************************/
+ 
+ static void
+ redo_mouse_highlight ()
+ {
+   if (!NILP (last_mouse_motion_frame)
+       && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
+     note_mouse_highlight (XFRAME (last_mouse_motion_frame),
+                         last_mouse_motion_event.x,
+                         last_mouse_motion_event.y);
+ }
+ 
+ 
  static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
  
  
***************
*** 5763,5771 ****
       XRectangle *rect;
  {
    Lisp_Object window;
!   int part, found = 0;
  
!   window = window_from_coordinates (f, x, y, &part, 0);
    if (!NILP (window))
      {
        struct window *w = XWINDOW (window);
--- 3667,3675 ----
       XRectangle *rect;
  {
    Lisp_Object window;
!   int found = 0;
  
!   window = window_from_coordinates (f, x, y, 0, 0);
    if (!NILP (window))
      {
        struct window *w = XWINDOW (window);
***************
*** 6022,6050 ****
  }
  
  
- #ifdef USE_X_TOOLKIT
- 
- /* Atimer callback function for TIMER.  Called every 0.1s to process
-    Xt timeouts, if needed.  We must avoid calling XtAppPending as
-    much as possible because that function does an implicit XFlush
-    that slows us down.  */
- 
- static void
- x_process_timeouts (timer)
-      struct atimer *timer;
- {
-   if (toolkit_scroll_bar_interaction || popup_activated ())
-     {
-       BLOCK_INPUT;
-       while (XtAppPending (Xt_app_con) & XtIMTimer)
-       XtAppProcessEvent (Xt_app_con, XtIMTimer);
-       UNBLOCK_INPUT;
-     }
- }
- 
- #endif /* USE_X_TOOLKIT */
- 
  
  /* Scroll bar support.  */
  
  /* Given an X window ID, find the struct scroll_bar which manages it.
--- 3926,3936 ----
  }
  
  
  
+ /***********************************************************************
+                              Scroll bars
+  ***********************************************************************/
+ 
  /* Scroll bar support.  */
  
  /* Given an X window ID, find the struct scroll_bar which manages it.
***************
*** 8811,8817 ****
                int n;
  
                XSETFRAME (frame, f);
!               help_echo = Qnil;
                n = gen_help_event (bufp, numchars,
                                    Qnil, frame, Qnil, Qnil, 0);
                bufp += n, count += n, numchars -= n;
--- 6697,6703 ----
                int n;
  
                XSETFRAME (frame, f);
!               help_echo_string = Qnil;
                n = gen_help_event (bufp, numchars,
                                    Qnil, frame, Qnil, Qnil, 0);
                bufp += n, count += n, numchars -= n;
***************
*** 8835,8842 ****
  
      case MotionNotify:
        {
!         previous_help_echo = help_echo;
!         help_echo = help_echo_object = help_echo_window = Qnil;
          help_echo_pos = -1;
  
          if (dpyinfo->grabbed && last_mouse_frame
--- 6721,6728 ----
  
      case MotionNotify:
        {
!         previous_help_echo_string = help_echo_string;
!         help_echo_string = help_echo_object = help_echo_window = Qnil;
          help_echo_pos = -1;
  
          if (dpyinfo->grabbed && last_mouse_frame
***************
*** 8858,8868 ****
              if (mouse_autoselect_window)
                {
                  Lisp_Object window;
-                 int area;
  
                  window = window_from_coordinates (f,
                                                    event.xmotion.x, 
event.xmotion.y,
!                                                   &area, 0);
  
                  /* Window will be selected only when it is not selected now 
and
                     last mouse movement event was not in it.  Minibuffer window
--- 6744,6753 ----
              if (mouse_autoselect_window)
                {
                  Lisp_Object window;
  
                  window = window_from_coordinates (f,
                                                    event.xmotion.x, 
event.xmotion.y,
!                                                   0, 0);
  
                  /* Window will be selected only when it is not selected now 
and
                     last mouse movement event was not in it.  Minibuffer window
***************
*** 8897,8906 ****
              clear_mouse_face (dpyinfo);
            }
  
!         /* If the contents of the global variable help_echo
             has changed, generate a HELP_EVENT.  */
!         if (!NILP (help_echo)
!             || !NILP (previous_help_echo))
            {
              Lisp_Object frame;
              int n;
--- 6782,6791 ----
              clear_mouse_face (dpyinfo);
            }
  
!         /* If the contents of the global variable help_echo_string
             has changed, generate a HELP_EVENT.  */
!         if (!NILP (help_echo_string)
!             || !NILP (previous_help_echo_string))
            {
              Lisp_Object frame;
              int n;
***************
*** 8911,8917 ****
                frame = Qnil;
  
              any_help_event_p = 1;
!             n = gen_help_event (bufp, numchars, help_echo, frame,
                                  help_echo_window, help_echo_object,
                                  help_echo_pos);
              bufp += n, count += n, numchars -= n;
--- 6796,6802 ----
                frame = Qnil;
  
              any_help_event_p = 1;
!             n = gen_help_event (bufp, numchars, help_echo_string, frame,
                                  help_echo_window, help_echo_object,
                                  help_echo_pos);
              bufp += n, count += n, numchars -= n;
***************
*** 9022,9038 ****
                  && XFASTINT (XWINDOW (f->tool_bar_window)->height))
                {
                  Lisp_Object window;
!                 int p, x, y;
! 
!                 x = event.xbutton.x;
!                 y = event.xbutton.y;
  
!                 /* Set x and y.  */
!                 window = window_from_coordinates (f, x, y, &p, 1);
                  if (EQ (window, f->tool_bar_window))
                    {
!                     x_handle_tool_bar_click (f, &event.xbutton);
!                     tool_bar_p = 1;
                    }
                }
  
--- 6907,6925 ----
                  && XFASTINT (XWINDOW (f->tool_bar_window)->height))
                {
                  Lisp_Object window;
!                 int x = event.xbutton.x;
!                 int y = event.xbutton.y;
  
!                 window = window_from_coordinates (f, x, y, 0, 1);
                  if (EQ (window, f->tool_bar_window))
                    {
!                   if (event.xbutton.type == ButtonPress)
!                     handle_tool_bar_click (f, x, y, 1, 0);
!                   else
!                     handle_tool_bar_click (f, x, y, 0,
!                                            x_x_to_emacs_modifiers (dpyinfo,
!                                                                    
event.xbutton.state));
!                   tool_bar_p = 1;
                    }
                }
  
***************
*** 9532,9538 ****
      {
        struct glyph_row *row;
        row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
!       x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
      }
    else
      {
--- 7419,7425 ----
      {
        struct glyph_row *row;
        row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
!       draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
      }
    else
      {
***************
*** 9587,9848 ****
  }
  
  
! /* Clear the cursor of window W to background color, and mark the
!    cursor as not shown.  This is used when the text where the cursor
!    is is about to be rewritten.  */
  
  static void
! x_clear_cursor (w)
!      struct window *w;
  {
!   if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
!     x_update_window_cursor (w, 0);
  }
  
  
! /* Draw the cursor glyph of window W in glyph row ROW.  See the
!    comment of x_draw_glyphs for the meaning of HL.  */
  
  static void
! x_draw_phys_cursor_glyph (w, row, hl)
!      struct window *w;
!      struct glyph_row *row;
!      enum draw_glyphs_face hl;
  {
!   /* If cursor hpos is out of bounds, don't draw garbage.  This can
!      happen in mini-buffer windows when switching between echo area
!      glyphs and mini-buffer.  */
!   if (w->phys_cursor.hpos < row->used[TEXT_AREA])
!     {
!       int on_p = w->phys_cursor_on_p;
!       int x1;
! 
!       x1 = x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
!                         w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
!                         hl, 0);
!       w->phys_cursor_on_p = on_p;
! 
!       if (hl == DRAW_CURSOR)
!       w->phys_cursor_width = x1 - w->phys_cursor.x;
! 
!       /* When we erase the cursor, and ROW is overlapped by other
!        rows, make sure that these overlapping parts of other rows
!        are redrawn.  */
!       else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
!       {
!         if (row > w->current_matrix->rows
!             && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
!           x_fix_overlapping_area (w, row - 1, TEXT_AREA);
! 
!         if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
!             && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
!           x_fix_overlapping_area (w, row + 1, TEXT_AREA);
!       }
!     }
  }
  
  
! /* Erase the image of a cursor of window W from the screen.  */
  
  static void
! x_erase_phys_cursor (w)
!      struct window *w;
! {
!   struct frame *f = XFRAME (w->frame);
!   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
!   int hpos = w->phys_cursor.hpos;
!   int vpos = w->phys_cursor.vpos;
!   int mouse_face_here_p = 0;
!   struct glyph_matrix *active_glyphs = w->current_matrix;
!   struct glyph_row *cursor_row;
!   struct glyph *cursor_glyph;
!   enum draw_glyphs_face hl;
! 
!   /* No cursor displayed or row invalidated => nothing to do on the
!      screen.  */
!   if (w->phys_cursor_type == NO_CURSOR)
!     goto mark_cursor_off;
! 
!   /* VPOS >= active_glyphs->nrows means that window has been resized.
!      Don't bother to erase the cursor.  */
!   if (vpos >= active_glyphs->nrows)
!     goto mark_cursor_off;
! 
!   /* If row containing cursor is marked invalid, there is nothing we
!      can do.  */
!   cursor_row = MATRIX_ROW (active_glyphs, vpos);
!   if (!cursor_row->enabled_p)
!     goto mark_cursor_off;
! 
!   /* If row is completely invisible, don't attempt to delete a cursor which
!      isn't there.  This can happen if cursor is at top of a window, and
!      we switch to a buffer with a header line in that window.  */
!   if (cursor_row->visible_height <= 0)
!     goto mark_cursor_off;
! 
!   /* This can happen when the new row is shorter than the old one.
!      In this case, either x_draw_glyphs or clear_end_of_line
!      should have cleared the cursor.  Note that we wouldn't be
!      able to erase the cursor in this case because we don't have a
!      cursor glyph at hand.  */
!   if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
!     goto mark_cursor_off;
! 
!   /* If the cursor is in the mouse face area, redisplay that when
!      we clear the cursor.  */
!   if (! NILP (dpyinfo->mouse_face_window)
!       && w == XWINDOW (dpyinfo->mouse_face_window)
!       && (vpos > dpyinfo->mouse_face_beg_row
!         || (vpos == dpyinfo->mouse_face_beg_row
!             && hpos >= dpyinfo->mouse_face_beg_col))
!       && (vpos < dpyinfo->mouse_face_end_row
!         || (vpos == dpyinfo->mouse_face_end_row
!             && hpos < dpyinfo->mouse_face_end_col))
!       /* Don't redraw the cursor's spot in mouse face if it is at the
!        end of a line (on a newline).  The cursor appears there, but
!        mouse highlighting does not.  */
!       && cursor_row->used[TEXT_AREA] > hpos)
!     mouse_face_here_p = 1;
! 
!   /* Maybe clear the display under the cursor.  */
!   if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
!     {
!       int x;
!       int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
! 
!       cursor_glyph = get_phys_cursor_glyph (w);
!       if (cursor_glyph == NULL)
!       goto mark_cursor_off;
! 
!       x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
! 
!       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
!                   x,
!                   WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
!                                                    cursor_row->y)),
!                   cursor_glyph->pixel_width,
!                   cursor_row->visible_height,
!                   False);
!     }
! 
!   /* Erase the cursor by redrawing the character underneath it.  */
!   if (mouse_face_here_p)
!     hl = DRAW_MOUSE_FACE;
!   else
!     hl = DRAW_NORMAL_TEXT;
!   x_draw_phys_cursor_glyph (w, cursor_row, hl);
! 
!  mark_cursor_off:
!   w->phys_cursor_on_p = 0;
!   w->phys_cursor_type = NO_CURSOR;
! }
! 
! 
! /* Non-zero if physical cursor of window W is within mouse face.  */
! 
! static int
! cursor_in_mouse_face_p (w)
!      struct window *w;
! {
!   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
!   int in_mouse_face = 0;
! 
!   if (WINDOWP (dpyinfo->mouse_face_window)
!       && XWINDOW (dpyinfo->mouse_face_window) == w)
!     {
!       int hpos = w->phys_cursor.hpos;
!       int vpos = w->phys_cursor.vpos;
! 
!       if (vpos >= dpyinfo->mouse_face_beg_row
!         && vpos <= dpyinfo->mouse_face_end_row
!         && (vpos > dpyinfo->mouse_face_beg_row
!             || hpos >= dpyinfo->mouse_face_beg_col)
!         && (vpos < dpyinfo->mouse_face_end_row
!             || hpos < dpyinfo->mouse_face_end_col
!             || dpyinfo->mouse_face_past_end))
!       in_mouse_face = 1;
!     }
! 
!   return in_mouse_face;
! }
! 
! 
! /* Display or clear cursor of window W.  If ON is zero, clear the
!    cursor.  If it is non-zero, display the cursor.  If ON is nonzero,
!    where to put the cursor is specified by HPOS, VPOS, X and Y.  */
! 
! void
! x_display_and_set_cursor (w, on, hpos, vpos, x, y)
       struct window *w;
!      int on, hpos, vpos, x, y;
  {
!   struct frame *f = XFRAME (w->frame);
!   int new_cursor_type;
!   int new_cursor_width;
!   int active_cursor;
!   struct glyph_matrix *current_glyphs;
!   struct glyph_row *glyph_row;
!   struct glyph *glyph;
! 
!   /* This is pointless on invisible frames, and dangerous on garbaged
!      windows and frames; in the latter case, the frame or window may
!      be in the midst of changing its size, and x and y may be off the
!      window.  */
!   if (! FRAME_VISIBLE_P (f)
!       || FRAME_GARBAGED_P (f)
!       || vpos >= w->current_matrix->nrows
!       || hpos >= w->current_matrix->matrix_w)
!     return;
! 
!   /* If cursor is off and we want it off, return quickly.  */
!   if (!on && !w->phys_cursor_on_p)
!     return;
! 
!   current_glyphs = w->current_matrix;
!   glyph_row = MATRIX_ROW (current_glyphs, vpos);
!   glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
! 
!   /* If cursor row is not enabled, we don't really know where to
!      display the cursor.  */
!   if (!glyph_row->enabled_p)
!     {
!       w->phys_cursor_on_p = 0;
!       return;
!     }
! 
!   xassert (interrupt_input_blocked);
! 
!   /* Set new_cursor_type to the cursor we want to be displayed.  */
!   new_cursor_type = get_window_cursor_type (w, &new_cursor_width, 
&active_cursor);
  
-   /* If cursor is currently being shown and we don't want it to be or
-      it is in the wrong place, or the cursor type is not what we want,
-      erase it.  */
-   if (w->phys_cursor_on_p
-       && (!on
-         || w->phys_cursor.x != x
-         || w->phys_cursor.y != y
-         || new_cursor_type != w->phys_cursor_type
-         || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
-             && new_cursor_width != w->phys_cursor_width)))
-     x_erase_phys_cursor (w);
- 
-   /* Don't check phys_cursor_on_p here because that flag is only set
-      to zero in some cases where we know that the cursor has been
-      completely erased, to avoid the extra work of erasing the cursor
-      twice.  In other words, phys_cursor_on_p can be 1 and the cursor
-      still not be visible, or it has only been partly erased.  */
    if (on)
      {
-       w->phys_cursor_ascent = glyph_row->ascent;
-       w->phys_cursor_height = glyph_row->height;
- 
-       /* Set phys_cursor_.* before x_draw_.* is called because some
-        of them may need the information.  */
-       w->phys_cursor.x = x;
-       w->phys_cursor.y = glyph_row->y;
-       w->phys_cursor.hpos = hpos;
-       w->phys_cursor.vpos = vpos;
        w->phys_cursor_type = new_cursor_type;
        w->phys_cursor_on_p = 1;
  
--- 7474,7515 ----
  }
  
  
! /* RIF: Define cursor CURSOR on frame F.  */
  
  static void
! x_define_frame_cursor (f, cursor)
!      struct frame *f;
!      Cursor cursor;
  {
!   XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
  }
  
  
! /* RIF: Clear area on frame F.  */
  
  static void
! x_clear_frame_area (f, x, y, width, height)
!      struct frame *f;
!      int x, y, width, height;
  {
!   x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
!               x, y, width, height, False);
  }
  
  
! /* RIF: Draw cursor on window W.  */
  
  static void
! x_draw_window_cursor (w, glyph_row, on, x, y, new_cursor_type, 
new_cursor_width)
       struct window *w;
!      struct glyph_row *glyph_row;
!      int on, x, y;
!      int new_cursor_type, new_cursor_width;
  {
!   struct frame *f = XFRAME (WINDOW_FRAME (w));
  
    if (on)
      {
        w->phys_cursor_type = new_cursor_type;
        w->phys_cursor_on_p = 1;
  
***************
*** 9853,9859 ****
          break;
  
        case FILLED_BOX_CURSOR:
!         x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
          break;
  
        case BAR_CURSOR:
--- 7520,7526 ----
          break;
  
        case FILLED_BOX_CURSOR:
!         draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
          break;
  
        case BAR_CURSOR:
***************
*** 9885,9963 ****
  #endif
  }
  
- 
- /* Display the cursor on window W, or clear it.  X and Y are window
-    relative pixel coordinates.  HPOS and VPOS are glyph matrix
-    positions.  If W is not the selected window, display a hollow
-    cursor.  ON non-zero means display the cursor at X, Y which
-    correspond to HPOS, VPOS, otherwise it is cleared.  */
- 
- void
- x_display_cursor (w, on, hpos, vpos, x, y)
-      struct window *w;
-      int on, hpos, vpos, x, y;
- {
-   BLOCK_INPUT;
-   x_display_and_set_cursor (w, on, hpos, vpos, x, y);
-   UNBLOCK_INPUT;
- }
- 
- 
- /* Display the cursor on window W, or clear it, according to ON_P.
-    Don't change the cursor's position.  */
- 
- void
- x_update_cursor (f, on_p)
-      struct frame *f;
-      int on_p;
- {
-   x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
- }
- 
- 
- /* Call x_update_window_cursor with parameter ON_P on all leaf windows
-    in the window tree rooted at W.  */
- 
- static void
- x_update_cursor_in_window_tree (w, on_p)
-      struct window *w;
-      int on_p;
- {
-   while (w)
-     {
-       if (!NILP (w->hchild))
-       x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
-       else if (!NILP (w->vchild))
-       x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
-       else
-       x_update_window_cursor (w, on_p);
- 
-       w = NILP (w->next) ? 0 : XWINDOW (w->next);
-     }
- }
- 
- 
- /* Switch the display of W's cursor on or off, according to the value
-    of ON.  */
- 
- static void
- x_update_window_cursor (w, on)
-      struct window *w;
-      int on;
- {
-   /* Don't update cursor in windows whose frame is in the process
-      of being deleted.  */
-   if (w->current_matrix)
-     {
-       BLOCK_INPUT;
-       x_display_and_set_cursor (w, on, w->phys_cursor.hpos, 
w->phys_cursor.vpos,
-                               w->phys_cursor.x, w->phys_cursor.y);
-       UNBLOCK_INPUT;
-     }
- }
- 
- 
- 
  
  /* Icons.  */
  
--- 7552,7557 ----
***************
*** 10852,10858 ****
  
            /* Wait for the change of frame size to occur */
            f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT;
- 
          }
      }
  }
--- 8446,8451 ----
***************
*** 13152,13157 ****
--- 10745,10772 ----
    xfree (dpyinfo);
  }
  
+ #ifdef USE_X_TOOLKIT
+ 
+ /* Atimer callback function for TIMER.  Called every 0.1s to process
+    Xt timeouts, if needed.  We must avoid calling XtAppPending as
+    much as possible because that function does an implicit XFlush
+    that slows us down.  */
+ 
+ static void
+ x_process_timeouts (timer)
+      struct atimer *timer;
+ {
+   if (toolkit_scroll_bar_interaction || popup_activated ())
+     {
+       BLOCK_INPUT;
+       while (XtAppPending (Xt_app_con) & XtIMTimer)
+       XtAppProcessEvent (Xt_app_con, XtIMTimer);
+       UNBLOCK_INPUT;
+     }
+ }
+ 
+ #endif /* USE_X_TOOLKIT */
+ 
  
  /* Set up use of X before we make the first connection.  */
  
***************
*** 13165,13180 ****
    x_after_update_window_line,
    x_update_window_begin,
    x_update_window_end,
!   XTcursor_to,
    x_flush,
!   x_clear_mouse_face,
    x_get_glyph_overhangs,
    x_fix_overlapping_area,
    x_draw_fringe_bitmap,
    x_per_char_metric,
    x_encode_char,
    x_compute_glyph_string_overhangs,
!   x_draw_glyph_string
  };
  
  void
--- 10780,10805 ----
    x_after_update_window_line,
    x_update_window_begin,
    x_update_window_end,
!   x_cursor_to,
!   x_flush,
! #ifndef XFlush
    x_flush,
! #else
!   0,  /* flush_display_optional */
! #endif
!   x_clear_window_mouse_face,
    x_get_glyph_overhangs,
    x_fix_overlapping_area,
    x_draw_fringe_bitmap,
    x_per_char_metric,
    x_encode_char,
    x_compute_glyph_string_overhangs,
!   x_draw_glyph_string,
!   x_define_frame_cursor,
!   x_clear_frame_area,
!   x_draw_window_cursor,
!   x_draw_vertical_window_border,
!   x_shift_glyphs_for_insert
  };
  
  void
***************
*** 13200,13206 ****
    condemn_scroll_bars_hook = XTcondemn_scroll_bars;
    redeem_scroll_bar_hook = XTredeem_scroll_bar;
    judge_scroll_bars_hook = XTjudge_scroll_bars;
-   estimate_mode_line_height_hook = x_estimate_mode_line_height;
  
    scroll_region_ok = 1;               /* we'll scroll partial frames */
    char_ins_del_ok = 1;
--- 10825,10830 ----
***************
*** 13291,13316 ****
  
    staticpro (&last_mouse_press_frame);
    last_mouse_press_frame = Qnil;
- 
-   help_echo = Qnil;
-   staticpro (&help_echo);
-   help_echo_object = Qnil;
-   staticpro (&help_echo_object);
-   help_echo_window = Qnil;
-   staticpro (&help_echo_window);
-   previous_help_echo = Qnil;
-   staticpro (&previous_help_echo);
-   help_echo_pos = -1;
- 
-   DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
-     doc: /* *Non-nil means autoselect window with mouse pointer.  */);
-   mouse_autoselect_window = 0;
- 
-   DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
-     doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
- For example, if a block cursor is over a tab, it will be drawn as
- wide as that tab on the display.  */);
-   x_stretch_cursor_p = 0;
  
    DEFVAR_BOOL ("x-use-underline-position-properties",
               &x_use_underline_position_properties,
--- 10915,10920 ----




reply via email to

[Prev in Thread] Current Thread [Next in Thread]