aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Rumney2001-10-21 15:20:03 +0000
committerJason Rumney2001-10-21 15:20:03 +0000
commit9f5a911b46577a2d573794ded1bd883685e901da (patch)
tree0661d81e204828bc6eda5cea2211f1e7dc088900
parenta3b10252a6f892598638bec3c3ecb5537411c188 (diff)
downloademacs-9f5a911b46577a2d573794ded1bd883685e901da.tar.gz
emacs-9f5a911b46577a2d573794ded1bd883685e901da.zip
(remember_mouse_glyph): New function.
(w32_mouse_position): Use it. (note_mouse_movement): If the mouse moved off the glyph, remember its new position. Sync with xterm.c: (notice_overwritten_cursor): Renamed from note_overwritten_text_cursor. Rewritten to take glyph widths into account. (x_y_to_hpos_vpos): Add parameter BUFFER_ONLY_P. (fast_find_string_pos): New function. (fast_find_position): Return the correct vpos. Add parameter STOP. In the final row, stop before glyphs having STOP as object. Don't consider glyphs that are not from a buffer. (fast_find_position) [0]: Add a presumably more correct version for after 21.1. (expose_window_tree, expose_frame): Don't compute intersections here. (expose_window): Do it here instead. (expose_window_tree, expose_window, expose_line): Return 1 when overwriting mouse-face. (expose_window): If W is the window currently being updated, mark the frame garbaged. (expose_frame): If mouse-face was overwritten, redo it. (x_use_underline_position_properties): New variable. (syms_of_xterm): DEFVAR_BOOL it. (x_draw_glyph_string): Add comment to use it in future. (x_draw_glyph_string): Restore clipping after drawing box. Fix a computation of the underline position. (w32_get_glyph_string_clip_rect): Minor cleanup. (x_fill_stretch_glyph_string): Remove an assertion. (x_produce_glyphs): Don't convert multibyte characters to unibyte characters in unibyte buffers. (cursor_in_mouse_face_p): New function. (x_draw_stretch_glyph_string): Use it to choose a different GC when drawing a cursor within highlighted text. Don't draw background again if it has already been drawn. (x_draw_glyph_string_box): Don't draw a full-width box just because the glyph row's full_width_p flag is set. (x_draw_glyphs): Fix computation of rightmost x for full-width rows. (x_dump_glyph_string): Put in #if GLYPH_DEBUG. (w32_draw_relief_rect): Extend left shadow to the bottom and left; change bottom shadow accordingly. Some cleanup. (x_update_window_end): Handle overwritten mouse face also for tool bar windows. (show_mouse_face): Set the glyph row's mouse_face_p flag also when DRAW is DRAW_IMAGE_RAISED. (clear_mouse_face): Return 1 if text with mouse face was actually redrawn. Make the function static. Reset dpyinfo->mouse_face_overlay otherwise note_mouse_highlight might optimize away highlighting if we pass over that same overlay again. (note_mouse_highlight): Call mouse_face_overlay_overlaps to detect a case where we have to highlight a different region despite not having left the currently highlighted region. Set mouse_face_overlay in the x_display_info. Avoid changing the mouse pointer shape when show_mouse_face has already done it, or there is no need. Handle mouse-face and help-echo in strings. (glyph_rect): New function. (w32_mouse_position): Use it to raise the threshold for mouse movement event generation. (w32_initialize_display_info): Initialize the x_display_info's mouse_face_overlay. (w32_set_vertical_scroll_bar): Don't clear a zero height or width area. (w32_set_vertical_scroll_bar, x_scroll_bar_create): Don't configure a widget to zero height.
-rw-r--r--src/w32term.c1439
1 files changed, 951 insertions, 488 deletions
diff --git a/src/w32term.c b/src/w32term.c
index 09a3295b8f3..1fe99c75acc 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -168,6 +168,10 @@ static int any_help_event_p;
168 168
169int x_stretch_cursor_p; 169int x_stretch_cursor_p;
170 170
171/* Non-zero means make use of UNDERLINE_POSITION font properties. */
172
173int x_use_underline_position_properties;
174
171extern unsigned int msh_mousewheel; 175extern unsigned int msh_mousewheel;
172 176
173extern void free_frame_menubar (); 177extern void free_frame_menubar ();
@@ -331,10 +335,12 @@ static void x_update_window_end P_ ((struct window *, int, int));
331static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *)); 335static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
332void w32_delete_display P_ ((struct w32_display_info *)); 336void w32_delete_display P_ ((struct w32_display_info *));
333static int fast_find_position P_ ((struct window *, int, int *, int *, 337static int fast_find_position P_ ((struct window *, int, int *, int *,
334 int *, int *)); 338 int *, int *, Lisp_Object));
339static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
340 int *, int *, int *, int *, int));
335static void set_output_cursor P_ ((struct cursor_pos *)); 341static void set_output_cursor P_ ((struct cursor_pos *));
336static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int, 342static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
337 int *, int *, int *)); 343 int *, int *, int *, int));
338static void note_mode_line_highlight P_ ((struct window *, int, int)); 344static void note_mode_line_highlight P_ ((struct window *, int, int));
339static void note_mouse_highlight P_ ((struct frame *, int, int)); 345static void note_mouse_highlight P_ ((struct frame *, int, int));
340static void note_tool_bar_highlight P_ ((struct frame *f, int, int)); 346static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
@@ -342,7 +348,8 @@ static void w32_handle_tool_bar_click P_ ((struct frame *,
342 struct input_event *)); 348 struct input_event *));
343static void show_mouse_face P_ ((struct w32_display_info *, 349static void show_mouse_face P_ ((struct w32_display_info *,
344 enum draw_glyphs_face)); 350 enum draw_glyphs_face));
345void clear_mouse_face P_ ((struct w32_display_info *)); 351static int cursor_in_mouse_face_p P_ ((struct window *));
352static int clear_mouse_face P_ ((struct w32_display_info *));
346 353
347void x_lower_frame P_ ((struct frame *)); 354void x_lower_frame P_ ((struct frame *));
348void x_scroll_bar_clear P_ ((struct frame *)); 355void x_scroll_bar_clear P_ ((struct frame *));
@@ -375,12 +382,12 @@ static void x_frame_rehighlight P_ ((struct w32_display_info *));
375static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); 382static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
376static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int)); 383static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
377static void expose_frame P_ ((struct frame *, int, int, int, int)); 384static void expose_frame P_ ((struct frame *, int, int, int, int));
378static void expose_window_tree P_ ((struct window *, RECT *)); 385static int expose_window_tree P_ ((struct window *, RECT *));
379static void expose_window P_ ((struct window *, RECT *)); 386static int expose_window P_ ((struct window *, RECT *));
380static void expose_area P_ ((struct window *, struct glyph_row *, 387static void expose_area P_ ((struct window *, struct glyph_row *,
381 RECT *, enum glyph_row_area)); 388 RECT *, enum glyph_row_area));
382static void expose_line P_ ((struct window *, struct glyph_row *, 389static int expose_line P_ ((struct window *, struct glyph_row *,
383 RECT *)); 390 RECT *));
384void x_update_cursor P_ ((struct frame *, int)); 391void x_update_cursor P_ ((struct frame *, int));
385static void x_update_cursor_in_window_tree P_ ((struct window *, int)); 392static void x_update_cursor_in_window_tree P_ ((struct window *, int));
386static void x_update_window_cursor P_ ((struct window *, int)); 393static void x_update_window_cursor P_ ((struct window *, int));
@@ -634,7 +641,8 @@ x_draw_vertical_border (w)
634 RECT r; 641 RECT r;
635 HDC hdc; 642 HDC hdc;
636 643
637 window_box_edges (w, -1, &r.left, &r.top, &r.right, &r.bottom); 644 window_box_edges (w, -1, (int *) &r.left, (int *) &r.top,
645 (int *) &r.right, (int *) &r.bottom);
638 r.left = r.right + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f); 646 r.left = r.right + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
639 r.right = r.left + 1; 647 r.right = r.left + 1;
640 r.bottom -= 1; 648 r.bottom -= 1;
@@ -664,22 +672,13 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
664 struct window *w; 672 struct window *w;
665 int cursor_on_p, mouse_face_overwritten_p; 673 int cursor_on_p, mouse_face_overwritten_p;
666{ 674{
675 struct w32_display_info *dpyinfo
676 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
677
667 if (!w->pseudo_window_p) 678 if (!w->pseudo_window_p)
668 { 679 {
669 struct w32_display_info *dpyinfo
670 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
671
672 BLOCK_INPUT; 680 BLOCK_INPUT;
673 681
674 /* If a row with mouse-face was overwritten, arrange for
675 XTframe_up_to_date to redisplay the mouse highlight. */
676 if (mouse_face_overwritten_p)
677 {
678 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
679 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
680 dpyinfo->mouse_face_window = Qnil;
681 }
682
683 if (cursor_on_p) 682 if (cursor_on_p)
684 x_display_and_set_cursor (w, 1, output_cursor.hpos, 683 x_display_and_set_cursor (w, 1, output_cursor.hpos,
685 output_cursor.vpos, 684 output_cursor.vpos,
@@ -688,7 +687,16 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
688 x_draw_vertical_border (w); 687 x_draw_vertical_border (w);
689 UNBLOCK_INPUT; 688 UNBLOCK_INPUT;
690 } 689 }
691 690
691 /* If a row with mouse-face was overwritten, arrange for
692 XTframe_up_to_date to redisplay the mouse highlight. */
693 if (mouse_face_overwritten_p)
694 {
695 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
696 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
697 dpyinfo->mouse_face_window = Qnil;
698 }
699
692 updated_window = NULL; 700 updated_window = NULL;
693} 701}
694 702
@@ -1981,8 +1989,7 @@ x_produce_glyphs (it)
1981 else if (!SINGLE_BYTE_CHAR_P (it->c) 1989 else if (!SINGLE_BYTE_CHAR_P (it->c)
1982 && !it->multibyte_p) 1990 && !it->multibyte_p)
1983 { 1991 {
1984 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil); 1992 it->multibyte_p = 1;
1985 it->multibyte_p = 0;
1986 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display); 1993 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1987 face = FACE_FROM_ID (it->f, it->face_id); 1994 face = FACE_FROM_ID (it->f, it->face_id);
1988 } 1995 }
@@ -2680,7 +2687,7 @@ void W32_TEXTOUT (s, x, y,chars,nchars)
2680 nchars * charset_dim, NULL); 2687 nchars * charset_dim, NULL);
2681} 2688}
2682 2689
2683#if 0 2690#if GLYPH_DEBUG
2684 2691
2685static void 2692static void
2686x_dump_glyph_string (s) 2693x_dump_glyph_string (s)
@@ -3030,20 +3037,6 @@ w32_get_glyph_string_clip_rect (s, r)
3030 r_height = s->row->visible_height; 3037 r_height = s->row->visible_height;
3031 } 3038 }
3032 3039
3033 /* Don't use S->y for clipping because it doesn't take partially
3034 visible lines into account. For example, it can be negative for
3035 partially visible lines at the top of a window. */
3036 if (!s->row->full_width_p
3037 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3038 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3039 else
3040 r->top = max (0, s->row->y);
3041
3042 /* If drawing a tool-bar window, draw it over the internal border
3043 at the top of the window. */
3044 if (s->w == XWINDOW (s->f->tool_bar_window))
3045 r->top -= s->f->output_data.w32->internal_border_width;
3046
3047 /* If S draws overlapping rows, it's sufficient to use the top and 3040 /* If S draws overlapping rows, it's sufficient to use the top and
3048 bottom of the window for clipping because this glyph string 3041 bottom of the window for clipping because this glyph string
3049 intentionally draws over other lines. */ 3042 intentionally draws over other lines. */
@@ -3052,7 +3045,23 @@ w32_get_glyph_string_clip_rect (s, r)
3052 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w); 3045 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3053 r_height = window_text_bottom_y (s->w) - r->top; 3046 r_height = window_text_bottom_y (s->w) - r->top;
3054 } 3047 }
3055 3048 else
3049 {
3050 /* Don't use S->y for clipping because it doesn't take partially
3051 visible lines into account. For example, it can be negative for
3052 partially visible lines at the top of a window. */
3053 if (!s->row->full_width_p
3054 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3055 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3056 else
3057 r->top = max (0, s->row->y);
3058
3059 /* If drawing a tool-bar window, draw it over the internal border
3060 at the top of the window. */
3061 if (s->w == XWINDOW (s->f->tool_bar_window))
3062 r->top -= s->f->output_data.w32->internal_border_width;
3063 }
3064
3056 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top); 3065 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3057 3066
3058 r->bottom = r->top + r_height; 3067 r->bottom = r->top + r_height;
@@ -3646,47 +3655,34 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3646 3655
3647 /* Top. */ 3656 /* Top. */
3648 for (i = 0; i < width; ++i) 3657 for (i = 0; i < width; ++i)
3649 { 3658 w32_fill_area (f, hdc, gc.foreground,
3650 w32_fill_area (f, hdc, gc.foreground, 3659 left_x + i * left_p, top_y + i,
3651 left_x + i * left_p, top_y + i, 3660 (right_x + 1 - i * right_p) - (left_x + i * left_p), 1);
3652 (right_x + 1 - i * right_p) - (left_x + i * left_p), 1);
3653 }
3654 3661
3655 /* Left. */ 3662 /* Left. */
3656 if (left_p) 3663 if (left_p)
3657 for (i = 0; i < width; ++i) 3664 for (i = 0; i < width; ++i)
3658 { 3665 w32_fill_area (f, hdc, gc.foreground,
3659 w32_fill_area (f, hdc, gc.foreground, 3666 left_x + i, top_y + i, 1,
3660 left_x + i, top_y + i, 1, 3667 (bottom_y - i + 1) - (top_y + i));
3661 (bottom_y - i) - (top_y + i));
3662 }
3663
3664 w32_set_clip_rectangle (hdc, NULL);
3665 3668
3666 if (raised_p) 3669 if (raised_p)
3667 gc.foreground = f->output_data.w32->black_relief.gc->foreground; 3670 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
3668 else 3671 else
3669 gc.foreground = f->output_data.w32->white_relief.gc->foreground; 3672 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
3670
3671
3672 w32_set_clip_rectangle (hdc, clip_rect);
3673 3673
3674 /* Bottom. */ 3674 /* Bottom. */
3675 for (i = 0; i < width; ++i) 3675 for (i = 0; i < width; ++i)
3676 { 3676 w32_fill_area (f, hdc, gc.foreground,
3677 w32_fill_area (f, hdc, gc.foreground, 3677 left_x + i * left_p, bottom_y - i,
3678 left_x + i * left_p, bottom_y - i, 3678 (right_x + 2 - i * right_p) - (left_x + i * left_p), 1);
3679 (right_x + 1 - i * right_p) - left_x + i * left_p, 1);
3680 }
3681 3679
3682 /* Right. */ 3680 /* Right. */
3683 if (right_p) 3681 if (right_p)
3684 for (i = 0; i < width; ++i) 3682 for (i = 0; i < width; ++i)
3685 { 3683 w32_fill_area (f, hdc, gc.foreground,
3686 w32_fill_area (f, hdc, gc.foreground, 3684 right_x - i, top_y + i + 1, 1,
3687 right_x - i, top_y + i + 1, 1, 3685 (bottom_y - i) - (top_y + i + 1));
3688 (bottom_y - i) - (top_y + i + 1));
3689 }
3690 3686
3691 w32_set_clip_rectangle (hdc, NULL); 3687 w32_set_clip_rectangle (hdc, NULL);
3692 3688
@@ -3764,7 +3760,7 @@ x_draw_glyph_string_box (s)
3764 width = abs (s->face->box_line_width); 3760 width = abs (s->face->box_line_width);
3765 raised_p = s->face->box == FACE_RAISED_BOX; 3761 raised_p = s->face->box == FACE_RAISED_BOX;
3766 left_x = s->x; 3762 left_x = s->x;
3767 right_x = ((s->row->full_width_p 3763 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
3768 ? last_x - 1 3764 ? last_x - 1
3769 : min (last_x, s->x + s->background_width) - 1)); 3765 : min (last_x, s->x + s->background_width) - 1));
3770 top_y = s->y; 3766 top_y = s->y;
@@ -4213,6 +4209,16 @@ x_draw_stretch_glyph_string (s)
4213 int w = s->background_width - width, h = s->height; 4209 int w = s->background_width - width, h = s->height;
4214 RECT r; 4210 RECT r;
4215 HDC hdc = s->hdc; 4211 HDC hdc = s->hdc;
4212
4213 if (s->row->mouse_face_p
4214 && cursor_in_mouse_face_p (s->w))
4215 {
4216 x_set_mouse_face_gc (s);
4217 gc = s->gc;
4218 }
4219 else
4220 gc = s->face->gc;
4221
4216 w32_get_glyph_string_clip_rect (s, &r); 4222 w32_get_glyph_string_clip_rect (s, &r);
4217 w32_set_clip_rectangle (hdc, &r); 4223 w32_set_clip_rectangle (hdc, &r);
4218 4224
@@ -4231,7 +4237,7 @@ x_draw_stretch_glyph_string (s)
4231 } 4237 }
4232 } 4238 }
4233 } 4239 }
4234 else 4240 else if (!s->background_filled_p)
4235 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width, 4241 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4236 s->height); 4242 s->height);
4237 4243
@@ -4260,7 +4266,6 @@ x_draw_glyph_string (s)
4260 4266
4261 /* Set up S->gc, set clipping and draw S. */ 4267 /* Set up S->gc, set clipping and draw S. */
4262 x_set_glyph_string_gc (s); 4268 x_set_glyph_string_gc (s);
4263 x_set_glyph_string_clipping (s);
4264 4269
4265 /* Draw relief (if any) in advance for char/composition so that the 4270 /* Draw relief (if any) in advance for char/composition so that the
4266 glyph string can be drawn over it. */ 4271 glyph string can be drawn over it. */
@@ -4270,10 +4275,14 @@ x_draw_glyph_string (s)
4270 || s->first_glyph->type == COMPOSITE_GLYPH)) 4275 || s->first_glyph->type == COMPOSITE_GLYPH))
4271 4276
4272 { 4277 {
4278 x_set_glyph_string_clipping (s);
4273 x_draw_glyph_string_background (s, 1); 4279 x_draw_glyph_string_background (s, 1);
4274 x_draw_glyph_string_box (s); 4280 x_draw_glyph_string_box (s);
4281 x_set_glyph_string_clipping (s);
4275 relief_drawn_p = 1; 4282 relief_drawn_p = 1;
4276 } 4283 }
4284 else
4285 x_set_glyph_string_clipping (s);
4277 4286
4278 switch (s->first_glyph->type) 4287 switch (s->first_glyph->type)
4279 { 4288 {
@@ -4314,6 +4323,8 @@ x_draw_glyph_string (s)
4314 unsigned long h = 1; 4323 unsigned long h = 1;
4315 unsigned long dy = s->height - h; 4324 unsigned long dy = s->height - h;
4316 4325
4326 /* TODO: Use font information for positioning and thickness
4327 of underline. See OUTLINETEXTMETRIC, and xterm.c. */
4317 if (s->face->underline_defaulted_p) 4328 if (s->face->underline_defaulted_p)
4318 { 4329 {
4319 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, 4330 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
@@ -4563,7 +4574,7 @@ x_fill_stretch_glyph_string (s, row, area, start, end)
4563 /* Adjust base line for subscript/superscript text. */ 4574 /* Adjust base line for subscript/superscript text. */
4564 s->ybase += voffset; 4575 s->ybase += voffset;
4565 4576
4566 xassert (s->face && s->face->gc); 4577 xassert (s->face);
4567 return glyph - s->row->glyphs[s->area]; 4578 return glyph - s->row->glyphs[s->area];
4568} 4579}
4569 4580
@@ -5440,6 +5451,7 @@ expose_frame (f, x, y, w, h)
5440 int x, y, w, h; 5451 int x, y, w, h;
5441{ 5452{
5442 RECT r; 5453 RECT r;
5454 int mouse_face_overwritten_p = 0;
5443 5455
5444 TRACE ((stderr, "expose_frame ")); 5456 TRACE ((stderr, "expose_frame "));
5445 5457
@@ -5475,23 +5487,35 @@ expose_frame (f, x, y, w, h)
5475 } 5487 }
5476 5488
5477 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom)); 5489 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
5478 expose_window_tree (XWINDOW (f->root_window), &r); 5490 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
5479 5491
5480 if (WINDOWP (f->tool_bar_window)) 5492 if (WINDOWP (f->tool_bar_window))
5493 mouse_face_overwritten_p
5494 |= expose_window (XWINDOW (f->tool_bar_window), &r);
5495
5496 /* Some window managers support a focus-follows-mouse style with
5497 delayed raising of frames. Imagine a partially obscured frame,
5498 and moving the mouse into partially obscured mouse-face on that
5499 frame. The visible part of the mouse-face will be highlighted,
5500 then the WM raises the obscured frame. With at least one WM, KDE
5501 2.1, Emacs is not getting any event for the raising of the frame
5502 (even tried with SubstructureRedirectMask), only Expose events.
5503 These expose events will draw text normally, i.e. not
5504 highlighted. Which means we must redo the highlight here.
5505 Subsume it under ``we love X''. --gerd 2001-08-15 */
5506 /* Included in Windows version because Windows most likely does not
5507 do the right thing if any third party tool offers
5508 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
5509 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
5481 { 5510 {
5482 struct window *w = XWINDOW (f->tool_bar_window); 5511 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5483 RECT window_rect; 5512 if (f == dpyinfo->mouse_face_mouse_frame)
5484 RECT intersection_rect; 5513 {
5485 int window_x, window_y, window_width, window_height; 5514 int x = dpyinfo->mouse_face_mouse_x;
5486 5515 int y = dpyinfo->mouse_face_mouse_y;
5487 window_box (w, -1, &window_x, &window_y, &window_width, &window_height); 5516 clear_mouse_face (dpyinfo);
5488 window_rect.left = window_x; 5517 note_mouse_highlight (f, x, y);
5489 window_rect.top = window_y; 5518 }
5490 window_rect.right = window_x + window_width;
5491 window_rect.bottom = window_y + window_height;
5492
5493 if (IntersectRect (&intersection_rect, &r, &window_rect))
5494 expose_window (w, &intersection_rect);
5495 } 5519 }
5496} 5520}
5497 5521
@@ -5499,45 +5523,29 @@ expose_frame (f, x, y, w, h)
5499/* Redraw (parts) of all windows in the window tree rooted at W that 5523/* Redraw (parts) of all windows in the window tree rooted at W that
5500 intersect R. R contains frame pixel coordinates. */ 5524 intersect R. R contains frame pixel coordinates. */
5501 5525
5502static void 5526static int
5503expose_window_tree (w, r) 5527expose_window_tree (w, r)
5504 struct window *w; 5528 struct window *w;
5505 RECT *r; 5529 RECT *r;
5506{ 5530{
5507 while (w) 5531 struct frame *f = XFRAME (w->frame);
5532 int mouse_face_overwritten_p = 0;
5533
5534 while (w && !FRAME_GARBAGED_P (f))
5508 { 5535 {
5509 if (!NILP (w->hchild)) 5536 if (!NILP (w->hchild))
5510 expose_window_tree (XWINDOW (w->hchild), r); 5537 mouse_face_overwritten_p
5538 |= expose_window_tree (XWINDOW (w->hchild), r);
5511 else if (!NILP (w->vchild)) 5539 else if (!NILP (w->vchild))
5512 expose_window_tree (XWINDOW (w->vchild), r); 5540 mouse_face_overwritten_p
5541 |= expose_window_tree (XWINDOW (w->vchild), r);
5513 else 5542 else
5514 { 5543 mouse_face_overwritten_p |= expose_window (w, r);
5515 RECT window_rect;
5516 RECT intersection_rect;
5517 struct frame *f = XFRAME (w->frame);
5518 int window_x, window_y, window_width, window_height;
5519
5520 /* Frame-relative pixel rectangle of W. */
5521 window_box (w, -1, &window_x, &window_y, &window_width,
5522 &window_height);
5523 window_rect.left
5524 = (window_x
5525 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5526 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_Y_UNIT (f));
5527 window_rect.top = window_y;
5528 window_rect.right = window_rect.left
5529 + (window_width
5530 + FRAME_X_FLAGS_AREA_WIDTH (f)
5531 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5532 window_rect.bottom = window_rect.top
5533 + window_height + CURRENT_MODE_LINE_HEIGHT (w);
5534
5535 if (IntersectRect (&intersection_rect, r, &window_rect))
5536 expose_window (w, &intersection_rect);
5537 }
5538 5544
5539 w = NILP (w->next) ? 0 : XWINDOW (w->next); 5545 w = NILP (w->next) ? NULL : XWINDOW (w->next);
5540 } 5546 }
5547
5548 return mouse_face_overwritten_p;
5541} 5549}
5542 5550
5543 5551
@@ -5606,9 +5614,10 @@ expose_area (w, row, r, area)
5606 5614
5607 5615
5608/* Redraw the parts of the glyph row ROW on window W intersecting 5616/* Redraw the parts of the glyph row ROW on window W intersecting
5609 rectangle R. R is in window-relative coordinates. */ 5617 rectangle R. R is in window-relative coordinates. Value is
5618 non-zero if mouse face was overwritten. */
5610 5619
5611static void 5620static int
5612expose_line (w, row, r) 5621expose_line (w, row, r)
5613 struct window *w; 5622 struct window *w;
5614 struct glyph_row *row; 5623 struct glyph_row *row;
@@ -5629,6 +5638,8 @@ expose_line (w, row, r)
5629 expose_area (w, row, r, RIGHT_MARGIN_AREA); 5638 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5630 x_draw_row_bitmaps (w, row); 5639 x_draw_row_bitmaps (w, row);
5631 } 5640 }
5641
5642 return row->mouse_face_p;
5632} 5643}
5633 5644
5634 5645
@@ -5656,82 +5667,110 @@ x_phys_cursor_in_rect_p (w, r)
5656} 5667}
5657 5668
5658 5669
5659/* Redraw a rectangle of window W. R is a rectangle in window 5670/* Redraw the part of window W intersection rectagle FR. Pixel
5660 relative coordinates. Call this function with input blocked. */ 5671 coordinates in FR are frame relative. Call this function with
5672 input blocked. Value is non-zero if the exposure overwrites
5673 mouse-face. */
5661 5674
5662static void 5675static int
5663expose_window (w, r) 5676expose_window (w, fr)
5664 struct window *w; 5677 struct window *w;
5665 RECT *r; 5678 RECT *fr;
5666{ 5679{
5667 struct glyph_row *row; 5680 struct frame *f = XFRAME (w->frame);
5668 int y; 5681 RECT wr, r;
5669 int yb = window_text_bottom_y (w); 5682 int mouse_face_overwritten_p = 0;
5670 int cursor_cleared_p;
5671 5683
5672 /* If window is not yet fully initialized, do nothing. This can 5684 /* If window is not yet fully initialized, do nothing. This can
5673 happen when toolkit scroll bars are used and a window is split. 5685 happen when toolkit scroll bars are used and a window is split.
5674 Reconfiguring the scroll bar will generate an expose for a newly 5686 Reconfiguring the scroll bar will generate an expose for a newly
5675 created window. */ 5687 created window. */
5676 if (w->current_matrix == NULL || w == updated_window) 5688 if (w->current_matrix == NULL)
5677 return; 5689 return 0;
5678
5679 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5680 r->left, r->top, r->right, r->bottom));
5681
5682 /* Convert to window coordinates. */
5683 r->left = FRAME_TO_WINDOW_PIXEL_X (w, r->left);
5684 r->top = FRAME_TO_WINDOW_PIXEL_Y (w, r->top);
5685 r->right = FRAME_TO_WINDOW_PIXEL_X (w, r->right);
5686 r->bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r->bottom);
5687 5690
5688 /* Turn off the cursor. */ 5691 /* When we're currently updating the window, display and current
5689 if (!w->pseudo_window_p 5692 matrix usually don't agree. Arrange for a thorough display
5690 && x_phys_cursor_in_rect_p (w, r)) 5693 later. */
5694 if (w == updated_window)
5691 { 5695 {
5692 x_clear_cursor (w); 5696 SET_FRAME_GARBAGED (f);
5693 cursor_cleared_p = 1; 5697 return 0;
5694 } 5698 }
5695 else
5696 cursor_cleared_p = 0;
5697 5699
5698 /* Find the first row intersecting the rectangle R. */ 5700 /* Frame-relative pixel rectangle of W. */
5699 row = w->current_matrix->rows; 5701 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
5700 y = 0; 5702 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
5701 while (row->enabled_p 5703 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
5702 && y < yb 5704 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
5703 && y + row->height < r->top) 5705
5704 { 5706 if (IntersectRect(&r, fr, &wr))
5705 y += row->height;
5706 ++row;
5707 }
5708
5709 /* Display the text in the rectangle, one text line at a time. */
5710 while (row->enabled_p
5711 && y < yb
5712 && y < r->bottom)
5713 { 5707 {
5714 expose_line (w, row, r); 5708 int yb = window_text_bottom_y (w);
5715 y += row->height; 5709 struct glyph_row *row;
5716 ++row; 5710 int cursor_cleared_p;
5717 }
5718 5711
5719 /* Display the mode line if there is one. */ 5712 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5720 if (WINDOW_WANTS_MODELINE_P (w) 5713 r.left, r.top, r.right, r.bottom));
5721 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5722 row->enabled_p)
5723 && row->y < r->bottom)
5724 expose_line (w, row, r);
5725 5714
5726 if (!w->pseudo_window_p) 5715 /* Convert to window coordinates. */
5727 { 5716 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
5728 /* Draw border between windows. */ 5717 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
5729 x_draw_vertical_border (w); 5718 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
5730 5719 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
5731 /* Turn the cursor on again. */ 5720
5732 if (cursor_cleared_p) 5721 /* Turn off the cursor. */
5733 x_update_window_cursor (w, 1); 5722 if (!w->pseudo_window_p
5723 && x_phys_cursor_in_rect_p (w, &r))
5724 {
5725 x_clear_cursor (w);
5726 cursor_cleared_p = 1;
5727 }
5728 else
5729 cursor_cleared_p = 0;
5730
5731 /* Find the first row intersecting the rectangle R. */
5732 for (row = w->current_matrix->rows;
5733 row->enabled_p;
5734 ++row)
5735 {
5736 int y0 = row->y;
5737 int y1 = MATRIX_ROW_BOTTOM_Y (row);
5738
5739 if ((y0 >= r.top && y0 < r.bottom)
5740 || (y1 > r.top && y1 < r.bottom)
5741 || (r.top >= y0 && r.top < y1)
5742 || (r.bottom > y0 && r.bottom < y1))
5743 {
5744 if (expose_line (w, row, &r))
5745 mouse_face_overwritten_p = 1;
5746 }
5747
5748 if (y1 >= yb)
5749 break;
5750 }
5751
5752 /* Display the mode line if there is one. */
5753 if (WINDOW_WANTS_MODELINE_P (w)
5754 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5755 row->enabled_p)
5756 && row->y < r.bottom)
5757 {
5758 if (expose_line (w, row, &r))
5759 mouse_face_overwritten_p = 1;
5760 }
5761
5762 if (!w->pseudo_window_p)
5763 {
5764 /* Draw border between windows. */
5765 x_draw_vertical_border (w);
5766
5767 /* Turn the cursor on again. */
5768 if (cursor_cleared_p)
5769 x_update_window_cursor (w, 1);
5770 }
5734 } 5771 }
5772
5773 return mouse_face_overwritten_p;
5735} 5774}
5736 5775
5737 5776
@@ -6134,11 +6173,16 @@ construct_drag_n_drop (result, msg, f)
6134static MSG last_mouse_motion_event; 6173static MSG last_mouse_motion_event;
6135static Lisp_Object last_mouse_motion_frame; 6174static Lisp_Object last_mouse_motion_frame;
6136 6175
6176static void remember_mouse_glyph P_ ((struct frame *, int, int));
6177
6137static void 6178static void
6138note_mouse_movement (frame, msg) 6179note_mouse_movement (frame, msg)
6139 FRAME_PTR frame; 6180 FRAME_PTR frame;
6140 MSG *msg; 6181 MSG *msg;
6141{ 6182{
6183 int mouse_x = LOWORD (msg->lParam);
6184 int mouse_y = HIWORD (msg->lParam);
6185
6142 last_mouse_movement_time = msg->time; 6186 last_mouse_movement_time = msg->time;
6143 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event)); 6187 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
6144 XSETFRAME (last_mouse_motion_frame, frame); 6188 XSETFRAME (last_mouse_motion_frame, frame);
@@ -6151,14 +6195,19 @@ note_mouse_movement (frame, msg)
6151 } 6195 }
6152 6196
6153 /* Has the mouse moved off the glyph it was on at the last sighting? */ 6197 /* Has the mouse moved off the glyph it was on at the last sighting? */
6154 else if (LOWORD (msg->lParam) < last_mouse_glyph.left 6198 else if (mouse_x < last_mouse_glyph.left
6155 || LOWORD (msg->lParam) > last_mouse_glyph.right 6199 || mouse_x > last_mouse_glyph.right
6156 || HIWORD (msg->lParam) < last_mouse_glyph.top 6200 || mouse_y < last_mouse_glyph.top
6157 || HIWORD (msg->lParam) > last_mouse_glyph.bottom) 6201 || mouse_y > last_mouse_glyph.bottom)
6158 { 6202 {
6159 frame->mouse_moved = 1; 6203 frame->mouse_moved = 1;
6160 last_mouse_scroll_bar = Qnil; 6204 last_mouse_scroll_bar = Qnil;
6161 note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam)); 6205 note_mouse_highlight (frame, mouse_x, mouse_y);
6206 /* Remember the mouse position here, as w32_mouse_position only
6207 gets called when mouse tracking is enabled but we also need
6208 to keep track of the mouse for help_echo and highlighting at
6209 other times. */
6210 remember_mouse_glyph (frame, mouse_x, mouse_y);
6162 } 6211 }
6163} 6212}
6164 6213
@@ -6181,10 +6230,11 @@ int disable_mouse_highlight;
6181 date. */ 6230 date. */
6182 6231
6183static struct glyph * 6232static struct glyph *
6184x_y_to_hpos_vpos (w, x, y, hpos, vpos, area) 6233x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6185 struct window *w; 6234 struct window *w;
6186 int x, y; 6235 int x, y;
6187 int *hpos, *vpos, *area; 6236 int *hpos, *vpos, *area;
6237 int buffer_only_p;
6188{ 6238{
6189 struct glyph *glyph, *end; 6239 struct glyph *glyph, *end;
6190 struct glyph_row *row = NULL; 6240 struct glyph_row *row = NULL;
@@ -6242,7 +6292,7 @@ x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6242 { 6292 {
6243 if (w->pseudo_window_p) 6293 if (w->pseudo_window_p)
6244 break; 6294 break;
6245 else if (BUFFERP (glyph->object)) 6295 else if (!buffer_only_p || BUFFERP (glyph->object))
6246 break; 6296 break;
6247 } 6297 }
6248 6298
@@ -6376,6 +6426,7 @@ note_mouse_highlight (f, x, y)
6376 int portion; 6426 int portion;
6377 Lisp_Object window; 6427 Lisp_Object window;
6378 struct window *w; 6428 struct window *w;
6429 struct buffer *b;
6379 6430
6380 /* When a menu is active, don't highlight because this looks odd. */ 6431 /* When a menu is active, don't highlight because this looks odd. */
6381 if (popup_activated ()) 6432 if (popup_activated ())
@@ -6421,35 +6472,38 @@ note_mouse_highlight (f, x, y)
6421 return; 6472 return;
6422 } 6473 }
6423 6474
6475 /* Mouse is on the mode or header line? */
6424 if (portion == 1 || portion == 3) 6476 if (portion == 1 || portion == 3)
6425 { 6477 {
6426 /* Mouse is on the mode or top line. */
6427 note_mode_line_highlight (w, x, portion == 1); 6478 note_mode_line_highlight (w, x, portion == 1);
6428 return; 6479 return;
6429 } 6480 }
6430#if 0 /* TODO: mouse cursor */ 6481#if 0 /* TODO: mouse cursor */
6431 else if (portion == 2) 6482 if (portion == 2)
6432 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6483 cursor = f->output_data.x->horizontal_drag_cursor;
6433 f->output_data.x->horizontal_drag_cursor);
6434 else 6484 else
6435 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6485 cursor = f->output_data.x->text_cursor;
6436 f->output_data.x->text_cursor);
6437#endif 6486#endif
6438
6439 /* Are we in a window whose display is up to date? 6487 /* Are we in a window whose display is up to date?
6440 And verify the buffer's text has not changed. */ 6488 And verify the buffer's text has not changed. */
6489 b = XBUFFER (w->buffer);
6441 if (/* Within text portion of the window. */ 6490 if (/* Within text portion of the window. */
6442 portion == 0 6491 portion == 0
6443 && EQ (w->window_end_valid, w->buffer) 6492 && EQ (w->window_end_valid, w->buffer)
6444 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer)) 6493 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
6445 && (XFASTINT (w->last_overlay_modified) 6494 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
6446 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
6447 { 6495 {
6448 int hpos, vpos, pos, i, area; 6496 int hpos, vpos, pos, i, area;
6449 struct glyph *glyph; 6497 struct glyph *glyph;
6498 Lisp_Object object;
6499 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
6500 Lisp_Object *overlay_vec = NULL;
6501 int len, noverlays;
6502 struct buffer *obuf;
6503 int obegv, ozv, same_region;
6450 6504
6451 /* Find the glyph under X/Y. */ 6505 /* Find the glyph under X/Y. */
6452 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area); 6506 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
6453 6507
6454 /* Clear mouse face if X/Y not over text. */ 6508 /* Clear mouse face if X/Y not over text. */
6455 if (glyph == NULL 6509 if (glyph == NULL
@@ -6457,197 +6511,333 @@ note_mouse_highlight (f, x, y)
6457 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p) 6511 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6458 { 6512 {
6459 clear_mouse_face (dpyinfo); 6513 clear_mouse_face (dpyinfo);
6460 return; 6514 /* TODO: mouse cursor */
6515 goto set_cursor;
6461 } 6516 }
6462 6517
6463 pos = glyph->charpos; 6518 pos = glyph->charpos;
6464 xassert (w->pseudo_window_p || BUFFERP (glyph->object)); 6519 object = glyph->object;
6520 if (!STRINGP (object) && !BUFFERP (object))
6521 goto set_cursor;
6522
6523 /* If we get an out-of-range value, return now; avoid an error. */
6524 if (BUFFERP (object) && pos > BUF_Z (b))
6525 goto set_cursor;
6526
6527 /* Make the window's buffer temporarily current for
6528 overlays_at and compute_char_face. */
6529 obuf = current_buffer;
6530 current_buffer = b;
6531 obegv = BEGV;
6532 ozv = ZV;
6533 BEGV = BEG;
6534 ZV = Z;
6535
6536 /* Is this char mouse-active or does it have help-echo? */
6537 position = make_number (pos);
6538
6539 if (BUFFERP (object))
6540 {
6541 /* Put all the overlays we want in a vector in overlay_vec.
6542 Store the length in len. If there are more than 10, make
6543 enough space for all, and try again. */
6544 len = 10;
6545 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6546 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6547 if (noverlays > len)
6548 {
6549 len = noverlays;
6550 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6551 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6552 }
6553
6554 /* Sort overlays into increasing priority order. */
6555 noverlays = sort_overlays (overlay_vec, noverlays, w);
6556 }
6557 else
6558 noverlays = 0;
6559
6560 same_region = (EQ (window, dpyinfo->mouse_face_window)
6561 && vpos >= dpyinfo->mouse_face_beg_row
6562 && vpos <= dpyinfo->mouse_face_end_row
6563 && (vpos > dpyinfo->mouse_face_beg_row
6564 || hpos >= dpyinfo->mouse_face_beg_col)
6565 && (vpos < dpyinfo->mouse_face_end_row
6566 || hpos < dpyinfo->mouse_face_end_col
6567 || dpyinfo->mouse_face_past_end));
6568
6569 /* TODO: if (same_region)
6570 mouse cursor */
6571
6572 /* Check mouse-face highlighting. */
6573 if (! same_region
6574 /* If there exists an overlay with mouse-face overlapping
6575 the one we are currently highlighting, we have to
6576 check if we enter the overlapping overlay, and then
6577 highlight that. */
6578 || (OVERLAYP (dpyinfo->mouse_face_overlay)
6579 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
6580 {
6581 /* Find the highest priority overlay that has a mouse-face
6582 property. */
6583 overlay = Qnil;
6584 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
6585 {
6586 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6587 if (!NILP (mouse_face))
6588 overlay = overlay_vec[i];
6589 }
6465 6590
6466 /* Check for mouse-face and help-echo. */ 6591 /* If we're actually highlighting the same overlay as
6592 before, there's no need to do that again. */
6593 if (!NILP (overlay)
6594 && EQ (overlay, dpyinfo->mouse_face_overlay))
6595 goto check_help_echo;
6596
6597 dpyinfo->mouse_face_overlay = overlay;
6598
6599 /* Clear the display of the old active region, if any. */
6600 clear_mouse_face (dpyinfo);
6601 /* TODO: mouse cursor changes. */
6602
6603 /* If no overlay applies, get a text property. */
6604 if (NILP (overlay))
6605 mouse_face = Fget_text_property (position, Qmouse_face, object);
6606
6607 /* Handle the overlay case. */
6608 if (!NILP (overlay))
6609 {
6610 /* Find the range of text around this char that
6611 should be active. */
6612 Lisp_Object before, after;
6613 int ignore;
6614
6615 before = Foverlay_start (overlay);
6616 after = Foverlay_end (overlay);
6617 /* Record this as the current active region. */
6618 fast_find_position (w, XFASTINT (before),
6619 &dpyinfo->mouse_face_beg_col,
6620 &dpyinfo->mouse_face_beg_row,
6621 &dpyinfo->mouse_face_beg_x,
6622 &dpyinfo->mouse_face_beg_y, Qnil);
6623
6624 dpyinfo->mouse_face_past_end
6625 = !fast_find_position (w, XFASTINT (after),
6626 &dpyinfo->mouse_face_end_col,
6627 &dpyinfo->mouse_face_end_row,
6628 &dpyinfo->mouse_face_end_x,
6629 &dpyinfo->mouse_face_end_y, Qnil);
6630 dpyinfo->mouse_face_window = window;
6631
6632 dpyinfo->mouse_face_face_id
6633 = face_at_buffer_position (w, pos, 0, 0,
6634 &ignore, pos + 1, 1);
6635
6636 /* Display it as active. */
6637 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6638 /* TODO: mouse cursor changes. */
6639 }
6640 /* Handle the text property case. */
6641 else if (! NILP (mouse_face) && BUFFERP (object))
6642 {
6643 /* Find the range of text around this char that
6644 should be active. */
6645 Lisp_Object before, after, beginning, end;
6646 int ignore;
6647
6648 beginning = Fmarker_position (w->start);
6649 end = make_number (BUF_Z (XBUFFER (object))
6650 - XFASTINT (w->window_end_pos));
6651 before
6652 = Fprevious_single_property_change (make_number (pos + 1),
6653 Qmouse_face,
6654 object, beginning);
6655 after
6656 = Fnext_single_property_change (position, Qmouse_face,
6657 object, end);
6658
6659 /* Record this as the current active region. */
6660 fast_find_position (w, XFASTINT (before),
6661 &dpyinfo->mouse_face_beg_col,
6662 &dpyinfo->mouse_face_beg_row,
6663 &dpyinfo->mouse_face_beg_x,
6664 &dpyinfo->mouse_face_beg_y, Qnil);
6665 dpyinfo->mouse_face_past_end
6666 = !fast_find_position (w, XFASTINT (after),
6667 &dpyinfo->mouse_face_end_col,
6668 &dpyinfo->mouse_face_end_row,
6669 &dpyinfo->mouse_face_end_x,
6670 &dpyinfo->mouse_face_end_y, Qnil);
6671 dpyinfo->mouse_face_window = window;
6672
6673 if (BUFFERP (object))
6674 dpyinfo->mouse_face_face_id
6675 = face_at_buffer_position (w, pos, 0, 0,
6676 &ignore, pos + 1, 1);
6677
6678 /* Display it as active. */
6679 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6680 /* TODO: mouse cursor changes. */
6681 }
6682 else if (!NILP (mouse_face) && STRINGP (object))
6683 {
6684 Lisp_Object b, e;
6685 int ignore;
6686
6687 b = Fprevious_single_property_change (make_number (pos + 1),
6688 Qmouse_face,
6689 object, Qnil);
6690 e = Fnext_single_property_change (position, Qmouse_face,
6691 object, Qnil);
6692 if (NILP (b))
6693 b = make_number (0);
6694 if (NILP (e))
6695 e = make_number (XSTRING (object)->size - 1);
6696 fast_find_string_pos (w, XINT (b), object,
6697 &dpyinfo->mouse_face_beg_col,
6698 &dpyinfo->mouse_face_beg_row,
6699 &dpyinfo->mouse_face_beg_x,
6700 &dpyinfo->mouse_face_beg_y, 0);
6701 fast_find_string_pos (w, XINT (e), object,
6702 &dpyinfo->mouse_face_end_col,
6703 &dpyinfo->mouse_face_end_row,
6704 &dpyinfo->mouse_face_end_x,
6705 &dpyinfo->mouse_face_end_y, 1);
6706 dpyinfo->mouse_face_past_end = 0;
6707 dpyinfo->mouse_face_window = window;
6708 dpyinfo->mouse_face_face_id
6709 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
6710 glyph->face_id, 1);
6711 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6712 /* TODO: mouse cursor changes. */
6713 }
6714 else if (STRINGP (object) && NILP (mouse_face))
6715 {
6716 /* A string which doesn't have mouse-face, but
6717 the text ``under'' it might have. */
6718 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
6719 int start = MATRIX_ROW_START_CHARPOS (r);
6720
6721 pos = string_buffer_position (w, object, start);
6722 if (pos > 0)
6723 mouse_face = get_char_property_and_overlay (make_number (pos),
6724 Qmouse_face,
6725 w->buffer,
6726 &overlay);
6727 if (!NILP (mouse_face) && !NILP (overlay))
6728 {
6729 Lisp_Object before = Foverlay_start (overlay);
6730 Lisp_Object after = Foverlay_end (overlay);
6731 Lisp_Object ignore;
6732
6733 /* Note that we might not be able to find position
6734 BEFORE in the glyph matrix if the overlay is
6735 entirely covered by a `display' property. In
6736 this case, we overshoot. So let's stop in
6737 the glyph matrix before glyphs for OBJECT. */
6738 fast_find_position (w, XFASTINT (before),
6739 &dpyinfo->mouse_face_beg_col,
6740 &dpyinfo->mouse_face_beg_row,
6741 &dpyinfo->mouse_face_beg_x,
6742 &dpyinfo->mouse_face_beg_y,
6743 object);
6744
6745 dpyinfo->mouse_face_past_end
6746 = !fast_find_position (w, XFASTINT (after),
6747 &dpyinfo->mouse_face_end_col,
6748 &dpyinfo->mouse_face_end_row,
6749 &dpyinfo->mouse_face_end_x,
6750 &dpyinfo->mouse_face_end_y,
6751 Qnil);
6752 dpyinfo->mouse_face_window = window;
6753 dpyinfo->mouse_face_face_id
6754 = face_at_buffer_position (w, pos, 0, 0,
6755 &ignore, pos + 1, 1);
6756
6757 /* Display it as active. */
6758 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6759 /* TODO: mouse cursor changes. */
6760 }
6761 }
6762 }
6763
6764 check_help_echo:
6765
6766 /* Look for a `help-echo' property. */
6467 { 6767 {
6468 Lisp_Object mouse_face, overlay, position; 6768 Lisp_Object help, overlay;
6469 Lisp_Object *overlay_vec; 6769
6470 int len, noverlays; 6770 /* Check overlays first. */
6471 struct buffer *obuf; 6771 help = overlay = Qnil;
6472 int obegv, ozv; 6772 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
6473
6474 /* If we get an out-of-range value, return now; avoid an error. */
6475 if (pos > BUF_Z (XBUFFER (w->buffer)))
6476 return;
6477
6478 /* Make the window's buffer temporarily current for
6479 overlays_at and compute_char_face. */
6480 obuf = current_buffer;
6481 current_buffer = XBUFFER (w->buffer);
6482 obegv = BEGV;
6483 ozv = ZV;
6484 BEGV = BEG;
6485 ZV = Z;
6486
6487 /* Is this char mouse-active or does it have help-echo? */
6488 XSETINT (position, pos);
6489
6490 /* Put all the overlays we want in a vector in overlay_vec.
6491 Store the length in len. If there are more than 10, make
6492 enough space for all, and try again. */
6493 len = 10;
6494 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6495 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6496 if (noverlays > len)
6497 { 6773 {
6498 len = noverlays; 6774 overlay = overlay_vec[i];
6499 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); 6775 help = Foverlay_get (overlay, Qhelp_echo);
6500 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6501 } 6776 }
6502 6777
6503 /* Sort overlays into increasing priority order. */ 6778 if (!NILP (help))
6504 noverlays = sort_overlays (overlay_vec, noverlays, w);
6505
6506 /* Check mouse-face highlighting. */
6507 if (! (EQ (window, dpyinfo->mouse_face_window)
6508 && vpos >= dpyinfo->mouse_face_beg_row
6509 && vpos <= dpyinfo->mouse_face_end_row
6510 && (vpos > dpyinfo->mouse_face_beg_row
6511 || hpos >= dpyinfo->mouse_face_beg_col)
6512 && (vpos < dpyinfo->mouse_face_end_row
6513 || hpos < dpyinfo->mouse_face_end_col
6514 || dpyinfo->mouse_face_past_end)))
6515 { 6779 {
6516 /* Clear the display of the old active region, if any. */ 6780 help_echo = help;
6517 clear_mouse_face (dpyinfo); 6781 help_echo_window = window;
6518 6782 help_echo_object = overlay;
6519 /* Find the highest priority overlay that has a mouse-face prop. */ 6783 help_echo_pos = pos;
6520 overlay = Qnil; 6784 }
6521 for (i = noverlays - 1; i >= 0; --i) 6785 else
6522 { 6786 {
6523 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face); 6787 Lisp_Object object = glyph->object;
6524 if (!NILP (mouse_face)) 6788 int charpos = glyph->charpos;
6525 {
6526 overlay = overlay_vec[i];
6527 break;
6528 }
6529 }
6530
6531 /* If no overlay applies, get a text property. */
6532 if (NILP (overlay))
6533 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6534
6535 /* Handle the overlay case. */
6536 if (! NILP (overlay))
6537 {
6538 /* Find the range of text around this char that
6539 should be active. */
6540 Lisp_Object before, after;
6541 int ignore;
6542
6543 before = Foverlay_start (overlay);
6544 after = Foverlay_end (overlay);
6545 /* Record this as the current active region. */
6546 fast_find_position (w, XFASTINT (before),
6547 &dpyinfo->mouse_face_beg_col,
6548 &dpyinfo->mouse_face_beg_row,
6549 &dpyinfo->mouse_face_beg_x,
6550 &dpyinfo->mouse_face_beg_y);
6551 dpyinfo->mouse_face_past_end
6552 = !fast_find_position (w, XFASTINT (after),
6553 &dpyinfo->mouse_face_end_col,
6554 &dpyinfo->mouse_face_end_row,
6555 &dpyinfo->mouse_face_end_x,
6556 &dpyinfo->mouse_face_end_y);
6557 dpyinfo->mouse_face_window = window;
6558 dpyinfo->mouse_face_face_id
6559 = face_at_buffer_position (w, pos, 0, 0,
6560 &ignore, pos + 1, 1);
6561
6562 /* Display it as active. */
6563 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6564 }
6565 /* Handle the text property case. */
6566 else if (! NILP (mouse_face))
6567 {
6568 /* Find the range of text around this char that
6569 should be active. */
6570 Lisp_Object before, after, beginning, end;
6571 int ignore;
6572
6573 beginning = Fmarker_position (w->start);
6574 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6575 - XFASTINT (w->window_end_pos)));
6576 before
6577 = Fprevious_single_property_change (make_number (pos + 1),
6578 Qmouse_face,
6579 w->buffer, beginning);
6580 after
6581 = Fnext_single_property_change (position, Qmouse_face,
6582 w->buffer, end);
6583 /* Record this as the current active region. */
6584 fast_find_position (w, XFASTINT (before),
6585 &dpyinfo->mouse_face_beg_col,
6586 &dpyinfo->mouse_face_beg_row,
6587 &dpyinfo->mouse_face_beg_x,
6588 &dpyinfo->mouse_face_beg_y);
6589 dpyinfo->mouse_face_past_end
6590 = !fast_find_position (w, XFASTINT (after),
6591 &dpyinfo->mouse_face_end_col,
6592 &dpyinfo->mouse_face_end_row,
6593 &dpyinfo->mouse_face_end_x,
6594 &dpyinfo->mouse_face_end_y);
6595 dpyinfo->mouse_face_window = window;
6596 dpyinfo->mouse_face_face_id
6597 = face_at_buffer_position (w, pos, 0, 0,
6598 &ignore, pos + 1, 1);
6599
6600 /* Display it as active. */
6601 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6602 }
6603 }
6604
6605 /* Look for a `help-echo' property. */
6606 {
6607 Lisp_Object help, overlay;
6608
6609 /* Check overlays first. */
6610 help = overlay = Qnil;
6611 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
6612 {
6613 overlay = overlay_vec[i];
6614 help = Foverlay_get (overlay, Qhelp_echo);
6615 }
6616 6789
6617 if (!NILP (help)) 6790 /* Try text properties. */
6618 { 6791 if (STRINGP (object)
6619 help_echo = help; 6792 && charpos >= 0
6620 help_echo_window = window; 6793 && charpos < XSTRING (object)->size)
6621 help_echo_object = overlay; 6794 {
6622 help_echo_pos = pos; 6795 help = Fget_text_property (make_number (charpos),
6623 } 6796 Qhelp_echo, object);
6624 else 6797 if (NILP (help))
6625 { 6798 {
6626 /* Try text properties. */ 6799 /* If the string itself doesn't specify a help-echo,
6627 if ((STRINGP (glyph->object) 6800 see if the buffer text ``under'' it does. */
6628 && glyph->charpos >= 0 6801 struct glyph_row *r
6629 && glyph->charpos < XSTRING (glyph->object)->size) 6802 = MATRIX_ROW (w->current_matrix, vpos);
6630 || (BUFFERP (glyph->object) 6803 int start = MATRIX_ROW_START_CHARPOS (r);
6631 && glyph->charpos >= BEGV 6804 int pos = string_buffer_position (w, object, start);
6632 && glyph->charpos < ZV)) 6805 if (pos > 0)
6633 help = Fget_text_property (make_number (glyph->charpos), 6806 {
6634 Qhelp_echo, glyph->object); 6807 help = Fget_char_property (make_number (pos),
6808 Qhelp_echo, w->buffer);
6809 if (!NILP (help))
6810 {
6811 charpos = pos;
6812 object = w->buffer;
6813 }
6814 }
6815 }
6816 }
6817 else if (BUFFERP (object)
6818 && charpos >= BEGV
6819 && charpos < ZV)
6820 help = Fget_text_property (make_number (charpos), Qhelp_echo,
6821 object);
6635 6822
6636 if (!NILP (help)) 6823 if (!NILP (help))
6637 { 6824 {
6638 help_echo = help; 6825 help_echo = help;
6639 help_echo_window = window; 6826 help_echo_window = window;
6640 help_echo_object = glyph->object; 6827 help_echo_object = object;
6641 help_echo_pos = glyph->charpos; 6828 help_echo_pos = charpos;
6642 } 6829 }
6643 } 6830 }
6644 }
6645
6646 BEGV = obegv;
6647 ZV = ozv;
6648 current_buffer = obuf;
6649 } 6831 }
6832
6833 BEGV = obegv;
6834 ZV = ozv;
6835 current_buffer = obuf;
6650 } 6836 }
6837
6838 set_cursor:
6839 /* TODO: mouse cursor changes. */
6840 ;
6651} 6841}
6652 6842
6653static void 6843static void
@@ -6697,7 +6887,7 @@ x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6697 int area; 6887 int area;
6698 6888
6699 /* Find the glyph under X/Y. */ 6889 /* Find the glyph under X/Y. */
6700 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area); 6890 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
6701 if (*glyph == NULL) 6891 if (*glyph == NULL)
6702 return -1; 6892 return -1;
6703 6893
@@ -6877,28 +7067,101 @@ note_tool_bar_highlight (f, x, y)
6877 7067
6878 7068
6879 7069
6880/* Find the glyph matrix position of buffer position POS in window W. 7070/* Find the glyph matrix position of buffer position CHARPOS in window
6881 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's 7071 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6882 current glyphs must be up to date. If POS is above window start 7072 current glyphs must be up to date. If CHARPOS is above window
6883 return (0, 0, 0, 0). If POS is after end of W, return end of 7073 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
6884 last line in W. */ 7074 of last line in W. In the row containing CHARPOS, stop before glyphs
7075 having STOP as object. */
7076
7077#if 0 /* This is a version of fast_find_position that's more correct
7078 in the presence of hscrolling, for example. I didn't install
7079 it right away because the problem fixed is minor, it failed
7080 in 20.x as well, and I think it's too risky to install
7081 so near the release of 21.1. 2001-09-25 gerd. */
6885 7082
6886static int 7083static int
6887fast_find_position (w, pos, hpos, vpos, x, y) 7084fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7085 struct window *w;
7086 int charpos;
7087 int *hpos, *vpos, *x, *y;
7088 Lisp_Object stop;
7089{
7090 struct glyph_row *row, *first;
7091 struct glyph *glyph, *end;
7092 int i, past_end = 0;
7093
7094 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7095 row = row_containing_pos (w, charpos, first, NULL);
7096 if (row == NULL)
7097 {
7098 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7099 {
7100 *x = *y = *hpos = *vpos = 0;
7101 return 0;
7102 }
7103 else
7104 {
7105 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7106 past_end = 1;
7107 }
7108 }
7109
7110 *x = row->x;
7111 *y = row->y;
7112 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7113
7114 glyph = row->glyphs[TEXT_AREA];
7115 end = glyph + row->used[TEXT_AREA];
7116
7117 /* Skip over glyphs not having an object at the start of the row.
7118 These are special glyphs like truncation marks on terminal
7119 frames. */
7120 if (row->displays_text_p)
7121 while (glyph < end
7122 && INTEGERP (glyph->object)
7123 && !EQ (stop, glyph->object)
7124 && glyph->charpos < 0)
7125 {
7126 *x += glyph->pixel_width;
7127 ++glyph;
7128 }
7129
7130 while (glyph < end
7131 && !INTEGERP (glyph->object)
7132 && !EQ (stop, glyph->object)
7133 && (!BUFFERP (glyph->object)
7134 || glyph->charpos < charpos))
7135 {
7136 *x += glyph->pixel_width;
7137 ++glyph;
7138 }
7139
7140 *hpos = glyph - row->glyphs[TEXT_AREA];
7141 return past_end;
7142}
7143
7144#else /* not 0 */
7145
7146static int
7147fast_find_position (w, pos, hpos, vpos, x, y, stop)
6888 struct window *w; 7148 struct window *w;
6889 int pos; 7149 int pos;
6890 int *hpos, *vpos, *x, *y; 7150 int *hpos, *vpos, *x, *y;
7151 Lisp_Object stop;
6891{ 7152{
6892 int i; 7153 int i;
6893 int lastcol; 7154 int lastcol;
6894 int maybe_next_line_p = 0; 7155 int maybe_next_line_p = 0;
6895 int line_start_position; 7156 int line_start_position;
6896 int yb = window_text_bottom_y (w); 7157 int yb = window_text_bottom_y (w);
6897 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0); 7158 struct glyph_row *row, *best_row;
6898 struct glyph_row *best_row = row; 7159 int row_vpos, best_row_vpos;
6899 int row_vpos = 0, best_row_vpos = 0;
6900 int current_x; 7160 int current_x;
6901 7161
7162 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7163 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7164
6902 while (row->y < yb) 7165 while (row->y < yb)
6903 { 7166 {
6904 if (row->used[TEXT_AREA]) 7167 if (row->used[TEXT_AREA])
@@ -6935,22 +7198,26 @@ fast_find_position (w, pos, hpos, vpos, x, y)
6935 for (i = 0; i < best_row->used[TEXT_AREA]; i++) 7198 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
6936 { 7199 {
6937 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i; 7200 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6938 int charpos; 7201 int charpos = glyph->charpos;
6939 7202
6940 charpos = glyph->charpos; 7203 if (BUFFERP (glyph->object))
6941 if (charpos == pos)
6942 { 7204 {
6943 *hpos = i; 7205 if (charpos == pos)
6944 *vpos = best_row_vpos; 7206 {
6945 *x = current_x; 7207 *hpos = i;
6946 *y = best_row->y; 7208 *vpos = best_row_vpos;
6947 return 1; 7209 *x = current_x;
7210 *y = best_row->y;
7211 return 1;
7212 }
7213 else if (charpos > pos)
7214 break;
6948 } 7215 }
6949 else if (charpos > pos) 7216 else if (EQ (glyph->object, stop))
6950 break; 7217 break;
6951 else if (charpos > 0)
6952 lastcol = i;
6953 7218
7219 if (charpos > 0)
7220 lastcol = i;
6954 current_x += glyph->pixel_width; 7221 current_x += glyph->pixel_width;
6955 } 7222 }
6956 7223
@@ -6972,6 +7239,90 @@ fast_find_position (w, pos, hpos, vpos, x, y)
6972 return 0; 7239 return 0;
6973} 7240}
6974 7241
7242#endif /* not 0 */
7243
7244
7245/* Find the position of the the glyph for position POS in OBJECT in
7246 window W's current matrix, and return in *X/*Y the pixel
7247 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7248
7249 RIGHT_P non-zero means return the position of the right edge of the
7250 glyph, RIGHT_P zero means return the left edge position.
7251
7252 If no glyph for POS exists in the matrix, return the position of
7253 the glyph with the next smaller position that is in the matrix, if
7254 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7255 exists in the matrix, return the position of the glyph with the
7256 next larger position in OBJECT.
7257
7258 Value is non-zero if a glyph was found. */
7259
7260static int
7261fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7262 struct window *w;
7263 int pos;
7264 Lisp_Object object;
7265 int *hpos, *vpos, *x, *y;
7266 int right_p;
7267{
7268 int yb = window_text_bottom_y (w);
7269 struct glyph_row *r;
7270 struct glyph *best_glyph = NULL;
7271 struct glyph_row *best_row = NULL;
7272 int best_x = 0;
7273
7274 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7275 r->enabled_p && r->y < yb;
7276 ++r)
7277 {
7278 struct glyph *g = r->glyphs[TEXT_AREA];
7279 struct glyph *e = g + r->used[TEXT_AREA];
7280 int gx;
7281
7282 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7283 if (EQ (g->object, object))
7284 {
7285 if (g->charpos == pos)
7286 {
7287 best_glyph = g;
7288 best_x = gx;
7289 best_row = r;
7290 goto found;
7291 }
7292 else if (best_glyph == NULL
7293 || ((abs (g->charpos - pos)
7294 < abs (best_glyph->charpos - pos))
7295 && (right_p
7296 ? g->charpos < pos
7297 : g->charpos > pos)))
7298 {
7299 best_glyph = g;
7300 best_x = gx;
7301 best_row = r;
7302 }
7303 }
7304 }
7305
7306 found:
7307
7308 if (best_glyph)
7309 {
7310 *x = best_x;
7311 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7312
7313 if (right_p)
7314 {
7315 *x += best_glyph->pixel_width;
7316 ++*hpos;
7317 }
7318
7319 *y = best_row->y;
7320 *vpos = best_row - w->current_matrix->rows;
7321 }
7322
7323 return best_glyph != NULL;
7324}
7325
6975 7326
6976/* Display the active region described by mouse_face_* 7327/* Display the active region described by mouse_face_*
6977 in its mouse-face if HL > 0, in its normal face if HL = 0. */ 7328 in its mouse-face if HL > 0, in its normal face if HL = 0. */
@@ -7045,7 +7396,7 @@ show_mouse_face (dpyinfo, draw)
7045 { 7396 {
7046 x_draw_glyphs (w, start_x, row, TEXT_AREA, 7397 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7047 start_hpos, end_hpos, draw, NULL, NULL, 0); 7398 start_hpos, end_hpos, draw, NULL, NULL, 0);
7048 row->mouse_face_p = draw == DRAW_MOUSE_FACE; 7399 row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
7049 } 7400 }
7050 } 7401 }
7051 7402
@@ -7076,22 +7427,23 @@ show_mouse_face (dpyinfo, draw)
7076/* Clear out the mouse-highlighted active region. 7427/* Clear out the mouse-highlighted active region.
7077 Redraw it un-highlighted first. */ 7428 Redraw it un-highlighted first. */
7078 7429
7079void 7430static int
7080clear_mouse_face (dpyinfo) 7431clear_mouse_face (dpyinfo)
7081 struct w32_display_info *dpyinfo; 7432 struct w32_display_info *dpyinfo;
7082{ 7433{
7083#if 0 /* This prevents redrawing tool bar items when changing from one 7434 int cleared = 0;
7084 to another while a tooltip is open, so don't do it. */
7085 if (!NILP (tip_frame))
7086 return;
7087#endif
7088 7435
7089 if (! NILP (dpyinfo->mouse_face_window)) 7436 if (! NILP (dpyinfo->mouse_face_window))
7090 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT); 7437 {
7438 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7439 cleared = 1;
7440 }
7091 7441
7092 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; 7442 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7093 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; 7443 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7094 dpyinfo->mouse_face_window = Qnil; 7444 dpyinfo->mouse_face_window = Qnil;
7445 dpyinfo->mouse_face_overlay = Qnil;
7446 return cleared;
7095} 7447}
7096 7448
7097 7449
@@ -7136,6 +7488,88 @@ cancel_mouse_face (f)
7136 7488
7137static struct scroll_bar *x_window_to_scroll_bar (); 7489static struct scroll_bar *x_window_to_scroll_bar ();
7138static void x_scroll_bar_report_motion (); 7490static void x_scroll_bar_report_motion ();
7491static int glyph_rect P_ ((struct frame *f, int, int, RECT *));
7492
7493
7494/* Try to determine frame pixel position and size of the glyph under
7495 frame pixel coordinates X/Y on frame F . Return the position and
7496 size in *RECT. Value is non-zero if we could compute these
7497 values. */
7498
7499static int
7500glyph_rect (f, x, y, rect)
7501 struct frame *f;
7502 int x, y;
7503 RECT *rect;
7504{
7505 Lisp_Object window;
7506 int part, found = 0;
7507
7508 window = window_from_coordinates (f, x, y, &part, 0);
7509 if (!NILP (window))
7510 {
7511 struct window *w = XWINDOW (window);
7512 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7513 struct glyph_row *end = r + w->current_matrix->nrows - 1;
7514 int area;
7515
7516 frame_to_window_pixel_xy (w, &x, &y);
7517
7518 for (; !found && r < end && r->enabled_p; ++r)
7519 if (r->y + r->height >= y)
7520 {
7521 struct glyph *g = r->glyphs[TEXT_AREA];
7522 struct glyph *end = g + r->used[TEXT_AREA];
7523 int gx;
7524
7525 for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
7526 if (gx + g->pixel_width >= x)
7527 {
7528 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7529 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
7530 rect->right = rect->left + g->pixel_width;
7531 rect->bottom = rect->top + r->height;
7532 found = 1;
7533 }
7534 }
7535 }
7536
7537 return found;
7538}
7539
7540/* Record the position of the mouse in last_mouse_glyph. */
7541static void remember_mouse_glyph (f1, gx, gy)
7542 struct frame * f1;
7543 int gx, gy;
7544{
7545 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
7546 {
7547 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7548 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7549
7550 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7551 round down even for negative values. */
7552 if (gx < 0)
7553 gx -= width - 1;
7554 if (gy < 0)
7555 gy -= height - 1;
7556#if 0
7557 /* This was the original code from XTmouse_position, but it seems
7558 to give the position of the glyph diagonally next to the one
7559 the mouse is over. */
7560 gx = (gx + width - 1) / width * width;
7561 gy = (gy + height - 1) / height * height;
7562#else
7563 gx = gx / width * width;
7564 gy = gy / height * height;
7565#endif
7566
7567 last_mouse_glyph.left = gx;
7568 last_mouse_glyph.top = gy;
7569 last_mouse_glyph.right = gx + width;
7570 last_mouse_glyph.bottom = gy + height;
7571 }
7572}
7139 7573
7140/* Return the current position of the mouse. 7574/* Return the current position of the mouse.
7141 *fp should be a frame which indicates which display to ask about. 7575 *fp should be a frame which indicates which display to ask about.
@@ -7199,7 +7633,7 @@ w32_mouse_position (fp, insist, bar_window, part, x, y, time)
7199 else 7633 else
7200 { 7634 {
7201 /* Is window under mouse one of our frames? */ 7635 /* Is window under mouse one of our frames? */
7202 f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp), 7636 f1 = x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
7203 WindowFromPoint (pt)); 7637 WindowFromPoint (pt));
7204 } 7638 }
7205 7639
@@ -7239,24 +7673,7 @@ w32_mouse_position (fp, insist, bar_window, part, x, y, time)
7239 || insist); 7673 || insist);
7240#else 7674#else
7241 ScreenToClient (FRAME_W32_WINDOW (f1), &pt); 7675 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
7242 { 7676 remember_mouse_glyph (f1, pt.x, pt.y);
7243 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7244 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7245 int x = pt.x;
7246 int y = pt.y;
7247
7248 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7249 round down even for negative values. */
7250 if (x < 0)
7251 x -= width - 1;
7252 if (y < 0)
7253 y -= height - 1;
7254
7255 last_mouse_glyph.left = (x + width - 1) / width * width;
7256 last_mouse_glyph.top = (y + height - 1) / height * height;
7257 last_mouse_glyph.right = last_mouse_glyph.left + width;
7258 last_mouse_glyph.bottom = last_mouse_glyph.top + height;
7259 }
7260#endif 7677#endif
7261 7678
7262 *bar_window = Qnil; 7679 *bar_window = Qnil;
@@ -7576,9 +7993,12 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
7576 { 7993 {
7577 HDC hdc; 7994 HDC hdc;
7578 BLOCK_INPUT; 7995 BLOCK_INPUT;
7579 hdc = get_frame_dc (f); 7996 if (width && height)
7580 w32_clear_area (f, hdc, left, top, width, height); 7997 {
7581 release_frame_dc (f, hdc); 7998 hdc = get_frame_dc (f);
7999 w32_clear_area (f, hdc, left, top, width, height);
8000 release_frame_dc (f, hdc);
8001 }
7582 UNBLOCK_INPUT; 8002 UNBLOCK_INPUT;
7583 8003
7584 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height); 8004 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
@@ -7605,22 +8025,24 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
7605 { 8025 {
7606 HDC hdc; 8026 HDC hdc;
7607 BLOCK_INPUT; 8027 BLOCK_INPUT;
7608 8028 if (width && height)
7609 hdc = get_frame_dc (f); 8029 {
7610 /* Since Windows scroll bars are smaller than the space reserved 8030 hdc = get_frame_dc (f);
7611 for them on the frame, we have to clear "under" them. */ 8031 /* Since Windows scroll bars are smaller than the space reserved
7612 w32_clear_area (f, hdc, 8032 for them on the frame, we have to clear "under" them. */
7613 left, 8033 w32_clear_area (f, hdc,
7614 top, 8034 left,
7615 width, 8035 top,
7616 height); 8036 width,
7617 release_frame_dc (f, hdc); 8037 height);
7618 8038 release_frame_dc (f, hdc);
8039 }
7619 /* Make sure scroll bar is "visible" before moving, to ensure the 8040 /* Make sure scroll bar is "visible" before moving, to ensure the
7620 area of the parent window now exposed will be refreshed. */ 8041 area of the parent window now exposed will be refreshed. */
7621 my_show_window (f, hwnd, SW_HIDE); 8042 my_show_window (f, hwnd, SW_HIDE);
7622 MoveWindow (hwnd, sb_left, top, 8043 MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7623 sb_width, height, TRUE); 8044 top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8045 max (height, 1), TRUE);
7624 if (pfnSetScrollInfo) 8046 if (pfnSetScrollInfo)
7625 { 8047 {
7626 SCROLLINFO si; 8048 SCROLLINFO si;
@@ -8057,58 +8479,58 @@ w32_read_socket (sd, bufp, numchars, expected)
8057 switch (msg.msg.message) 8479 switch (msg.msg.message)
8058 { 8480 {
8059 case WM_PAINT: 8481 case WM_PAINT:
8060 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); 8482 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8061 8483
8062 if (f) 8484 if (f)
8063 { 8485 {
8064 if (msg.rect.right == msg.rect.left || 8486 if (msg.rect.right == msg.rect.left ||
8065 msg.rect.bottom == msg.rect.top) 8487 msg.rect.bottom == msg.rect.top)
8066 { 8488 {
8067 /* We may get paint messages even though the client 8489 /* We may get paint messages even though the client
8068 area is clipped - these are not expose events. */ 8490 area is clipped - these are not expose events. */
8069 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f, 8491 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
8070 XSTRING (f->name)->data)); 8492 XSTRING (f->name)->data));
8071 } 8493 }
8072 else if (f->async_visible != 1) 8494 else if (f->async_visible != 1)
8073 { 8495 {
8074 /* Definitely not obscured, so mark as visible. */ 8496 /* Definitely not obscured, so mark as visible. */
8075 f->async_visible = 1; 8497 f->async_visible = 1;
8076 f->async_iconified = 0; 8498 f->async_iconified = 0;
8077 SET_FRAME_GARBAGED (f); 8499 SET_FRAME_GARBAGED (f);
8078 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f, 8500 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
8079 XSTRING (f->name)->data)); 8501 XSTRING (f->name)->data));
8080 8502
8081 /* WM_PAINT serves as MapNotify as well, so report 8503 /* WM_PAINT serves as MapNotify as well, so report
8082 visibility changes properly. */ 8504 visibility changes properly. */
8083 if (f->iconified) 8505 if (f->iconified)
8084 { 8506 {
8085 bufp->kind = deiconify_event; 8507 bufp->kind = deiconify_event;
8086 XSETFRAME (bufp->frame_or_window, f); 8508 XSETFRAME (bufp->frame_or_window, f);
8087 bufp->arg = Qnil; 8509 bufp->arg = Qnil;
8088 bufp++; 8510 bufp++;
8089 count++; 8511 count++;
8090 numchars--; 8512 numchars--;
8091 } 8513 }
8092 else if (! NILP (Vframe_list) 8514 else if (! NILP (Vframe_list)
8093 && ! NILP (XCDR (Vframe_list))) 8515 && ! NILP (XCDR (Vframe_list)))
8094 /* Force a redisplay sooner or later to update the 8516 /* Force a redisplay sooner or later to update the
8095 frame titles in case this is the second frame. */ 8517 frame titles in case this is the second frame. */
8096 record_asynch_buffer_change (); 8518 record_asynch_buffer_change ();
8097 } 8519 }
8098 else 8520 else
8099 { 8521 {
8100 HDC hdc = get_frame_dc (f); 8522 HDC hdc = get_frame_dc (f);
8101 8523
8102 /* Erase background again for safety. */ 8524 /* Erase background again for safety. */
8103 w32_clear_rect (f, hdc, &msg.rect); 8525 w32_clear_rect (f, hdc, &msg.rect);
8104 release_frame_dc (f, hdc); 8526 release_frame_dc (f, hdc);
8105 expose_frame (f, 8527 expose_frame (f,
8106 msg.rect.left, 8528 msg.rect.left,
8107 msg.rect.top, 8529 msg.rect.top,
8108 msg.rect.right - msg.rect.left, 8530 msg.rect.right - msg.rect.left,
8109 msg.rect.bottom - msg.rect.top); 8531 msg.rect.bottom - msg.rect.top);
8110 } 8532 }
8111 } 8533 }
8112 break; 8534 break;
8113 8535
8114 case WM_INPUTLANGCHANGE: 8536 case WM_INPUTLANGCHANGE:
@@ -8175,7 +8597,7 @@ w32_read_socket (sd, bufp, numchars, expected)
8175 8597
8176 case WM_MOUSEMOVE: 8598 case WM_MOUSEMOVE:
8177 previous_help_echo = help_echo; 8599 previous_help_echo = help_echo;
8178 help_echo = help_echo_object = help_echo_window = Qnil; 8600 help_echo_object = help_echo_window = Qnil;
8179 help_echo_pos = -1; 8601 help_echo_pos = -1;
8180 8602
8181 if (dpyinfo->grabbed && last_mouse_frame 8603 if (dpyinfo->grabbed && last_mouse_frame
@@ -8195,8 +8617,7 @@ w32_read_socket (sd, bufp, numchars, expected)
8195 8617
8196 /* If the contents of the global variable help_echo 8618 /* If the contents of the global variable help_echo
8197 has changed, generate a HELP_EVENT. */ 8619 has changed, generate a HELP_EVENT. */
8198 if (!NILP (help_echo) 8620 if (help_echo != previous_help_echo)
8199 || !NILP (previous_help_echo))
8200 { 8621 {
8201 Lisp_Object frame; 8622 Lisp_Object frame;
8202 int n; 8623 int n;
@@ -9005,6 +9426,8 @@ x_erase_phys_cursor (w)
9005 /* Erase the cursor by redrawing the character underneath it. */ 9426 /* Erase the cursor by redrawing the character underneath it. */
9006 if (mouse_face_here_p) 9427 if (mouse_face_here_p)
9007 hl = DRAW_MOUSE_FACE; 9428 hl = DRAW_MOUSE_FACE;
9429 else if (cursor_row->inverse_p)
9430 hl = DRAW_INVERSE_VIDEO;
9008 else 9431 else
9009 hl = DRAW_NORMAL_TEXT; 9432 hl = DRAW_NORMAL_TEXT;
9010 x_draw_phys_cursor_glyph (w, cursor_row, hl); 9433 x_draw_phys_cursor_glyph (w, cursor_row, hl);
@@ -9015,6 +9438,36 @@ x_erase_phys_cursor (w)
9015} 9438}
9016 9439
9017 9440
9441/* Non-zero if physical cursor of window W is within mouse face. */
9442
9443static int
9444cursor_in_mouse_face_p (w)
9445 struct window *w;
9446{
9447 struct w32_display_info *dpyinfo
9448 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
9449 int in_mouse_face = 0;
9450
9451 if (WINDOWP (dpyinfo->mouse_face_window)
9452 && XWINDOW (dpyinfo->mouse_face_window) == w)
9453 {
9454 int hpos = w->phys_cursor.hpos;
9455 int vpos = w->phys_cursor.vpos;
9456
9457 if (vpos >= dpyinfo->mouse_face_beg_row
9458 && vpos <= dpyinfo->mouse_face_end_row
9459 && (vpos > dpyinfo->mouse_face_beg_row
9460 || hpos >= dpyinfo->mouse_face_beg_col)
9461 && (vpos < dpyinfo->mouse_face_end_row
9462 || hpos < dpyinfo->mouse_face_end_col
9463 || dpyinfo->mouse_face_past_end))
9464 in_mouse_face = 1;
9465 }
9466
9467 return in_mouse_face;
9468}
9469
9470
9018/* Display or clear cursor of window W. If ON is zero, clear the 9471/* Display or clear cursor of window W. If ON is zero, clear the
9019 cursor. If it is non-zero, display the cursor. If ON is nonzero, 9472 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9020 where to put the cursor is specified by HPOS, VPOS, X and Y. */ 9473 where to put the cursor is specified by HPOS, VPOS, X and Y. */
@@ -10126,7 +10579,7 @@ w32_initialize_display_info (display_name)
10126 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; 10579 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
10127 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID; 10580 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
10128 dpyinfo->mouse_face_window = Qnil; 10581 dpyinfo->mouse_face_window = Qnil;
10129 10582 dpyinfo->mouse_face_overlay = Qnil;
10130 /* TODO: dpyinfo->gray */ 10583 /* TODO: dpyinfo->gray */
10131 10584
10132} 10585}
@@ -10470,6 +10923,16 @@ For example, if a block cursor is over a tab, it will be drawn as\n\
10470wide as that tab on the display."); 10923wide as that tab on the display.");
10471 x_stretch_cursor_p = 0; 10924 x_stretch_cursor_p = 0;
10472 10925
10926#if 0 /* TODO: Setting underline position from font properties. */
10927 DEFVAR_BOOL ("x-use-underline-position-properties",
10928 &x_use_underline_position_properties,
10929 "*Non-nil means make use of UNDERLINE_POSITION font properties.\n\
10930Nil means ignore them. If you encounter fonts with bogus\n\
10931UNDERLINE_POSITION font properties, for example 7x13 on XFree prior\n\
10932to 4.1, set this to nil.");
10933 x_use_underline_position_properties = 1;
10934#endif
10935
10473 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars, 10936 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
10474 "If not nil, Emacs uses toolkit scroll bars."); 10937 "If not nil, Emacs uses toolkit scroll bars.");
10475 Vx_toolkit_scroll_bars = Qt; 10938 Vx_toolkit_scroll_bars = Qt;