diff options
| author | Jason Rumney | 2001-10-21 15:20:03 +0000 |
|---|---|---|
| committer | Jason Rumney | 2001-10-21 15:20:03 +0000 |
| commit | 9f5a911b46577a2d573794ded1bd883685e901da (patch) | |
| tree | 0661d81e204828bc6eda5cea2211f1e7dc088900 /src | |
| parent | a3b10252a6f892598638bec3c3ecb5537411c188 (diff) | |
| download | emacs-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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32term.c | 1439 |
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 | ||
| 169 | int x_stretch_cursor_p; | 169 | int x_stretch_cursor_p; |
| 170 | 170 | ||
| 171 | /* Non-zero means make use of UNDERLINE_POSITION font properties. */ | ||
| 172 | |||
| 173 | int x_use_underline_position_properties; | ||
| 174 | |||
| 171 | extern unsigned int msh_mousewheel; | 175 | extern unsigned int msh_mousewheel; |
| 172 | 176 | ||
| 173 | extern void free_frame_menubar (); | 177 | extern void free_frame_menubar (); |
| @@ -331,10 +335,12 @@ static void x_update_window_end P_ ((struct window *, int, int)); | |||
| 331 | static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *)); | 335 | static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *)); |
| 332 | void w32_delete_display P_ ((struct w32_display_info *)); | 336 | void w32_delete_display P_ ((struct w32_display_info *)); |
| 333 | static int fast_find_position P_ ((struct window *, int, int *, int *, | 337 | static int fast_find_position P_ ((struct window *, int, int *, int *, |
| 334 | int *, int *)); | 338 | int *, int *, Lisp_Object)); |
| 339 | static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object, | ||
| 340 | int *, int *, int *, int *, int)); | ||
| 335 | static void set_output_cursor P_ ((struct cursor_pos *)); | 341 | static void set_output_cursor P_ ((struct cursor_pos *)); |
| 336 | static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int, | 342 | static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int, |
| 337 | int *, int *, int *)); | 343 | int *, int *, int *, int)); |
| 338 | static void note_mode_line_highlight P_ ((struct window *, int, int)); | 344 | static void note_mode_line_highlight P_ ((struct window *, int, int)); |
| 339 | static void note_mouse_highlight P_ ((struct frame *, int, int)); | 345 | static void note_mouse_highlight P_ ((struct frame *, int, int)); |
| 340 | static void note_tool_bar_highlight P_ ((struct frame *f, int, int)); | 346 | static 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 *)); |
| 343 | static void show_mouse_face P_ ((struct w32_display_info *, | 349 | static void show_mouse_face P_ ((struct w32_display_info *, |
| 344 | enum draw_glyphs_face)); | 350 | enum draw_glyphs_face)); |
| 345 | void clear_mouse_face P_ ((struct w32_display_info *)); | 351 | static int cursor_in_mouse_face_p P_ ((struct window *)); |
| 352 | static int clear_mouse_face P_ ((struct w32_display_info *)); | ||
| 346 | 353 | ||
| 347 | void x_lower_frame P_ ((struct frame *)); | 354 | void x_lower_frame P_ ((struct frame *)); |
| 348 | void x_scroll_bar_clear P_ ((struct frame *)); | 355 | void x_scroll_bar_clear P_ ((struct frame *)); |
| @@ -375,12 +382,12 @@ static void x_frame_rehighlight P_ ((struct w32_display_info *)); | |||
| 375 | static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); | 382 | static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); |
| 376 | static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int)); | 383 | static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int)); |
| 377 | static void expose_frame P_ ((struct frame *, int, int, int, int)); | 384 | static void expose_frame P_ ((struct frame *, int, int, int, int)); |
| 378 | static void expose_window_tree P_ ((struct window *, RECT *)); | 385 | static int expose_window_tree P_ ((struct window *, RECT *)); |
| 379 | static void expose_window P_ ((struct window *, RECT *)); | 386 | static int expose_window P_ ((struct window *, RECT *)); |
| 380 | static void expose_area P_ ((struct window *, struct glyph_row *, | 387 | static void expose_area P_ ((struct window *, struct glyph_row *, |
| 381 | RECT *, enum glyph_row_area)); | 388 | RECT *, enum glyph_row_area)); |
| 382 | static void expose_line P_ ((struct window *, struct glyph_row *, | 389 | static int expose_line P_ ((struct window *, struct glyph_row *, |
| 383 | RECT *)); | 390 | RECT *)); |
| 384 | void x_update_cursor P_ ((struct frame *, int)); | 391 | void x_update_cursor P_ ((struct frame *, int)); |
| 385 | static void x_update_cursor_in_window_tree P_ ((struct window *, int)); | 392 | static void x_update_cursor_in_window_tree P_ ((struct window *, int)); |
| 386 | static void x_update_window_cursor P_ ((struct window *, int)); | 393 | static 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 | ||
| 2685 | static void | 2692 | static void |
| 2686 | x_dump_glyph_string (s) | 2693 | x_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 | ||
| 5502 | static void | 5526 | static int |
| 5503 | expose_window_tree (w, r) | 5527 | expose_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 | ||
| 5611 | static void | 5620 | static int |
| 5612 | expose_line (w, row, r) | 5621 | expose_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 | ||
| 5662 | static void | 5675 | static int |
| 5663 | expose_window (w, r) | 5676 | expose_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) | |||
| 6134 | static MSG last_mouse_motion_event; | 6173 | static MSG last_mouse_motion_event; |
| 6135 | static Lisp_Object last_mouse_motion_frame; | 6174 | static Lisp_Object last_mouse_motion_frame; |
| 6136 | 6175 | ||
| 6176 | static void remember_mouse_glyph P_ ((struct frame *, int, int)); | ||
| 6177 | |||
| 6137 | static void | 6178 | static void |
| 6138 | note_mouse_movement (frame, msg) | 6179 | note_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 | ||
| 6183 | static struct glyph * | 6232 | static struct glyph * |
| 6184 | x_y_to_hpos_vpos (w, x, y, hpos, vpos, area) | 6233 | x_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 | ||
| 6653 | static void | 6843 | static 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 | ||
| 6886 | static int | 7083 | static int |
| 6887 | fast_find_position (w, pos, hpos, vpos, x, y) | 7084 | fast_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 | |||
| 7146 | static int | ||
| 7147 | fast_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 | |||
| 7260 | static int | ||
| 7261 | fast_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 | ||
| 7079 | void | 7430 | static int |
| 7080 | clear_mouse_face (dpyinfo) | 7431 | clear_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 | ||
| 7137 | static struct scroll_bar *x_window_to_scroll_bar (); | 7489 | static struct scroll_bar *x_window_to_scroll_bar (); |
| 7138 | static void x_scroll_bar_report_motion (); | 7490 | static void x_scroll_bar_report_motion (); |
| 7491 | static 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 | |||
| 7499 | static int | ||
| 7500 | glyph_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. */ | ||
| 7541 | static 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 | |||
| 9443 | static int | ||
| 9444 | cursor_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\ | |||
| 10470 | wide as that tab on the display."); | 10923 | wide 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\ | ||
| 10930 | Nil means ignore them. If you encounter fonts with bogus\n\ | ||
| 10931 | UNDERLINE_POSITION font properties, for example 7x13 on XFree prior\n\ | ||
| 10932 | to 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; |