diff options
| author | Gerd Moellmann | 2001-03-08 20:54:18 +0000 |
|---|---|---|
| committer | Gerd Moellmann | 2001-03-08 20:54:18 +0000 |
| commit | f9db2310cde2f3e558bdd5de7f44b59b17fbd53f (patch) | |
| tree | 26f2b7b9dfd6640808d37ecf22ea0e3c555fb057 /src/xterm.c | |
| parent | 96e8e603941652d417b4da35600dfe235e0fbd0c (diff) | |
| download | emacs-f9db2310cde2f3e558bdd5de7f44b59b17fbd53f.tar.gz emacs-f9db2310cde2f3e558bdd5de7f44b59b17fbd53f.zip | |
(note_mouse_highlight): Handle mouse-face and
help-echo in strings.
(x_y_to_hpos_vpos): Add parameter BUFFER_ONLY_P.
(fast_find_string_pos): New function.
Diffstat (limited to 'src/xterm.c')
| -rw-r--r-- | src/xterm.c | 209 |
1 files changed, 166 insertions, 43 deletions
diff --git a/src/xterm.c b/src/xterm.c index ae786d5058b..592c60ff2bc 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -405,9 +405,11 @@ static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *, | |||
| 405 | unsigned)); | 405 | unsigned)); |
| 406 | static int fast_find_position P_ ((struct window *, int, int *, int *, | 406 | static int fast_find_position P_ ((struct window *, int, int *, int *, |
| 407 | int *, int *)); | 407 | int *, int *)); |
| 408 | static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object, | ||
| 409 | int *, int *, int *, int *, int)); | ||
| 408 | static void set_output_cursor P_ ((struct cursor_pos *)); | 410 | static void set_output_cursor P_ ((struct cursor_pos *)); |
| 409 | static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int, | 411 | static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int, |
| 410 | int *, int *, int *)); | 412 | int *, int *, int *, int)); |
| 411 | static void note_mode_line_highlight P_ ((struct window *, int, int)); | 413 | static void note_mode_line_highlight P_ ((struct window *, int, int)); |
| 412 | static void note_mouse_highlight P_ ((struct frame *, int, int)); | 414 | static void note_mouse_highlight P_ ((struct frame *, int, int)); |
| 413 | static void note_tool_bar_highlight P_ ((struct frame *f, int, int)); | 415 | static void note_tool_bar_highlight P_ ((struct frame *f, int, int)); |
| @@ -6446,10 +6448,11 @@ note_mouse_movement (frame, event) | |||
| 6446 | date. */ | 6448 | date. */ |
| 6447 | 6449 | ||
| 6448 | static struct glyph * | 6450 | static struct glyph * |
| 6449 | x_y_to_hpos_vpos (w, x, y, hpos, vpos, area) | 6451 | x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p) |
| 6450 | struct window *w; | 6452 | struct window *w; |
| 6451 | int x, y; | 6453 | int x, y; |
| 6452 | int *hpos, *vpos, *area; | 6454 | int *hpos, *vpos, *area; |
| 6455 | int buffer_only_p; | ||
| 6453 | { | 6456 | { |
| 6454 | struct glyph *glyph, *end; | 6457 | struct glyph *glyph, *end; |
| 6455 | struct glyph_row *row = NULL; | 6458 | struct glyph_row *row = NULL; |
| @@ -6507,7 +6510,7 @@ x_y_to_hpos_vpos (w, x, y, hpos, vpos, area) | |||
| 6507 | { | 6510 | { |
| 6508 | if (w->pseudo_window_p) | 6511 | if (w->pseudo_window_p) |
| 6509 | break; | 6512 | break; |
| 6510 | else if (BUFFERP (glyph->object)) | 6513 | else if (!buffer_only_p || BUFFERP (glyph->object)) |
| 6511 | break; | 6514 | break; |
| 6512 | } | 6515 | } |
| 6513 | 6516 | ||
| @@ -6710,9 +6713,10 @@ note_mouse_highlight (f, x, y) | |||
| 6710 | { | 6713 | { |
| 6711 | int hpos, vpos, pos, i, area; | 6714 | int hpos, vpos, pos, i, area; |
| 6712 | struct glyph *glyph; | 6715 | struct glyph *glyph; |
| 6716 | Lisp_Object object; | ||
| 6713 | 6717 | ||
| 6714 | /* Find the glyph under X/Y. */ | 6718 | /* Find the glyph under X/Y. */ |
| 6715 | glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area); | 6719 | glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0); |
| 6716 | 6720 | ||
| 6717 | /* Clear mouse face if X/Y not over text. */ | 6721 | /* Clear mouse face if X/Y not over text. */ |
| 6718 | if (glyph == NULL | 6722 | if (glyph == NULL |
| @@ -6724,18 +6728,19 @@ note_mouse_highlight (f, x, y) | |||
| 6724 | } | 6728 | } |
| 6725 | 6729 | ||
| 6726 | pos = glyph->charpos; | 6730 | pos = glyph->charpos; |
| 6727 | xassert (w->pseudo_window_p || BUFFERP (glyph->object)); | 6731 | object = glyph->object; |
| 6732 | if (!STRINGP (object) && !BUFFERP (object)) | ||
| 6733 | return; | ||
| 6728 | 6734 | ||
| 6729 | /* Check for mouse-face and help-echo. */ | ||
| 6730 | { | 6735 | { |
| 6731 | Lisp_Object mouse_face = Qnil, overlay, position; | 6736 | Lisp_Object mouse_face = Qnil, overlay = Qnil, position; |
| 6732 | Lisp_Object *overlay_vec; | 6737 | Lisp_Object *overlay_vec = NULL; |
| 6733 | int len, noverlays; | 6738 | int len, noverlays; |
| 6734 | struct buffer *obuf; | 6739 | struct buffer *obuf; |
| 6735 | int obegv, ozv; | 6740 | int obegv, ozv; |
| 6736 | 6741 | ||
| 6737 | /* If we get an out-of-range value, return now; avoid an error. */ | 6742 | /* If we get an out-of-range value, return now; avoid an error. */ |
| 6738 | if (pos > BUF_Z (XBUFFER (w->buffer))) | 6743 | if (BUFFERP (object) && pos > BUF_Z (XBUFFER (w->buffer))) |
| 6739 | return; | 6744 | return; |
| 6740 | 6745 | ||
| 6741 | /* Make the window's buffer temporarily current for | 6746 | /* Make the window's buffer temporarily current for |
| @@ -6748,23 +6753,28 @@ note_mouse_highlight (f, x, y) | |||
| 6748 | ZV = Z; | 6753 | ZV = Z; |
| 6749 | 6754 | ||
| 6750 | /* Is this char mouse-active or does it have help-echo? */ | 6755 | /* Is this char mouse-active or does it have help-echo? */ |
| 6751 | XSETINT (position, pos); | 6756 | position = make_number (pos); |
| 6752 | 6757 | ||
| 6753 | /* Put all the overlays we want in a vector in overlay_vec. | 6758 | if (BUFFERP (object)) |
| 6754 | Store the length in len. If there are more than 10, make | ||
| 6755 | enough space for all, and try again. */ | ||
| 6756 | len = 10; | ||
| 6757 | overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); | ||
| 6758 | noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0); | ||
| 6759 | if (noverlays > len) | ||
| 6760 | { | 6759 | { |
| 6761 | len = noverlays; | 6760 | /* Put all the overlays we want in a vector in overlay_vec. |
| 6761 | Store the length in len. If there are more than 10, make | ||
| 6762 | enough space for all, and try again. */ | ||
| 6763 | len = 10; | ||
| 6762 | overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); | 6764 | overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); |
| 6763 | noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0); | 6765 | noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0); |
| 6764 | } | 6766 | if (noverlays > len) |
| 6767 | { | ||
| 6768 | len = noverlays; | ||
| 6769 | overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); | ||
| 6770 | noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0); | ||
| 6771 | } | ||
| 6765 | 6772 | ||
| 6766 | /* Sort overlays into increasing priority order. */ | 6773 | /* Sort overlays into increasing priority order. */ |
| 6767 | noverlays = sort_overlays (overlay_vec, noverlays, w); | 6774 | noverlays = sort_overlays (overlay_vec, noverlays, w); |
| 6775 | } | ||
| 6776 | else | ||
| 6777 | noverlays = 0; | ||
| 6768 | 6778 | ||
| 6769 | /* Check mouse-face highlighting. */ | 6779 | /* Check mouse-face highlighting. */ |
| 6770 | if (! (EQ (window, dpyinfo->mouse_face_window) | 6780 | if (! (EQ (window, dpyinfo->mouse_face_window) |
| @@ -6786,24 +6796,21 @@ note_mouse_highlight (f, x, y) | |||
| 6786 | /* Clear the display of the old active region, if any. */ | 6796 | /* Clear the display of the old active region, if any. */ |
| 6787 | clear_mouse_face (dpyinfo); | 6797 | clear_mouse_face (dpyinfo); |
| 6788 | 6798 | ||
| 6789 | /* Find the highest priority overlay that has a mouse-face prop. */ | 6799 | /* Find the highest priority overlay that has a mouse-face |
| 6800 | property. */ | ||
| 6790 | overlay = Qnil; | 6801 | overlay = Qnil; |
| 6791 | for (i = noverlays - 1; i >= 0; --i) | 6802 | for (i = noverlays - 1; i >= 0 && NILP (overlay); --i) |
| 6792 | { | 6803 | { |
| 6793 | mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face); | 6804 | mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face); |
| 6794 | if (!NILP (mouse_face)) | 6805 | if (!NILP (mouse_face)) |
| 6795 | { | 6806 | overlay = overlay_vec[i]; |
| 6796 | overlay = overlay_vec[i]; | ||
| 6797 | break; | ||
| 6798 | } | ||
| 6799 | } | 6807 | } |
| 6800 | 6808 | dpyinfo->mouse_face_overlay = overlay; | |
| 6809 | |||
| 6801 | /* If no overlay applies, get a text property. */ | 6810 | /* If no overlay applies, get a text property. */ |
| 6802 | if (NILP (overlay)) | 6811 | if (NILP (overlay)) |
| 6803 | mouse_face = Fget_text_property (position, Qmouse_face, w->buffer); | 6812 | mouse_face = Fget_text_property (position, Qmouse_face, object); |
| 6804 | 6813 | ||
| 6805 | dpyinfo->mouse_face_overlay = overlay; | ||
| 6806 | |||
| 6807 | /* Handle the overlay case. */ | 6814 | /* Handle the overlay case. */ |
| 6808 | if (!NILP (overlay)) | 6815 | if (!NILP (overlay)) |
| 6809 | { | 6816 | { |
| @@ -6835,7 +6842,7 @@ note_mouse_highlight (f, x, y) | |||
| 6835 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | 6842 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); |
| 6836 | } | 6843 | } |
| 6837 | /* Handle the text property case. */ | 6844 | /* Handle the text property case. */ |
| 6838 | else if (! NILP (mouse_face)) | 6845 | else if (!NILP (mouse_face) && BUFFERP (object)) |
| 6839 | { | 6846 | { |
| 6840 | /* Find the range of text around this char that | 6847 | /* Find the range of text around this char that |
| 6841 | should be active. */ | 6848 | should be active. */ |
| @@ -6843,15 +6850,16 @@ note_mouse_highlight (f, x, y) | |||
| 6843 | int ignore; | 6850 | int ignore; |
| 6844 | 6851 | ||
| 6845 | beginning = Fmarker_position (w->start); | 6852 | beginning = Fmarker_position (w->start); |
| 6846 | XSETINT (end, (BUF_Z (XBUFFER (w->buffer)) | 6853 | end = make_number (BUF_Z (XBUFFER (object)) |
| 6847 | - XFASTINT (w->window_end_pos))); | 6854 | - XFASTINT (w->window_end_pos)); |
| 6848 | before | 6855 | before |
| 6849 | = Fprevious_single_property_change (make_number (pos + 1), | 6856 | = Fprevious_single_property_change (make_number (pos + 1), |
| 6850 | Qmouse_face, | 6857 | Qmouse_face, |
| 6851 | w->buffer, beginning); | 6858 | object, beginning); |
| 6852 | after | 6859 | after |
| 6853 | = Fnext_single_property_change (position, Qmouse_face, | 6860 | = Fnext_single_property_change (position, Qmouse_face, |
| 6854 | w->buffer, end); | 6861 | object, end); |
| 6862 | |||
| 6855 | /* Record this as the current active region. */ | 6863 | /* Record this as the current active region. */ |
| 6856 | fast_find_position (w, XFASTINT (before), | 6864 | fast_find_position (w, XFASTINT (before), |
| 6857 | &dpyinfo->mouse_face_beg_col, | 6865 | &dpyinfo->mouse_face_beg_col, |
| @@ -6865,13 +6873,46 @@ note_mouse_highlight (f, x, y) | |||
| 6865 | &dpyinfo->mouse_face_end_x, | 6873 | &dpyinfo->mouse_face_end_x, |
| 6866 | &dpyinfo->mouse_face_end_y); | 6874 | &dpyinfo->mouse_face_end_y); |
| 6867 | dpyinfo->mouse_face_window = window; | 6875 | dpyinfo->mouse_face_window = window; |
| 6868 | dpyinfo->mouse_face_face_id | 6876 | |
| 6869 | = face_at_buffer_position (w, pos, 0, 0, | 6877 | if (BUFFERP (object)) |
| 6870 | &ignore, pos + 1, 1); | 6878 | dpyinfo->mouse_face_face_id |
| 6879 | = face_at_buffer_position (w, pos, 0, 0, | ||
| 6880 | &ignore, pos + 1, 1); | ||
| 6871 | 6881 | ||
| 6872 | /* Display it as active. */ | 6882 | /* Display it as active. */ |
| 6873 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | 6883 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); |
| 6874 | } | 6884 | } |
| 6885 | else if (!NILP (mouse_face) && STRINGP (object)) | ||
| 6886 | { | ||
| 6887 | Lisp_Object b, e; | ||
| 6888 | int ignore; | ||
| 6889 | |||
| 6890 | b = Fprevious_single_property_change (make_number (pos + 1), | ||
| 6891 | Qmouse_face, | ||
| 6892 | object, Qnil); | ||
| 6893 | e = Fnext_single_property_change (position, Qmouse_face, | ||
| 6894 | object, Qnil); | ||
| 6895 | if (NILP (b)) | ||
| 6896 | b = make_number (0); | ||
| 6897 | if (NILP (e)) | ||
| 6898 | e = make_number (XSTRING (object)->size) - 1; | ||
| 6899 | fast_find_string_pos (w, XINT (b), object, | ||
| 6900 | &dpyinfo->mouse_face_beg_col, | ||
| 6901 | &dpyinfo->mouse_face_beg_row, | ||
| 6902 | &dpyinfo->mouse_face_beg_x, | ||
| 6903 | &dpyinfo->mouse_face_beg_y, 0); | ||
| 6904 | fast_find_string_pos (w, XINT (e), object, | ||
| 6905 | &dpyinfo->mouse_face_end_col, | ||
| 6906 | &dpyinfo->mouse_face_end_row, | ||
| 6907 | &dpyinfo->mouse_face_end_x, | ||
| 6908 | &dpyinfo->mouse_face_end_y, 1); | ||
| 6909 | dpyinfo->mouse_face_past_end = 0; | ||
| 6910 | dpyinfo->mouse_face_window = window; | ||
| 6911 | dpyinfo->mouse_face_face_id | ||
| 6912 | = face_at_string_position (w, object, pos, 0, 0, 0, &ignore, | ||
| 6913 | glyph->face_id, 1); | ||
| 6914 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | ||
| 6915 | } | ||
| 6875 | } | 6916 | } |
| 6876 | 6917 | ||
| 6877 | /* Look for a `help-echo' property. */ | 6918 | /* Look for a `help-echo' property. */ |
| @@ -6969,7 +7010,7 @@ x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx) | |||
| 6969 | int area; | 7010 | int area; |
| 6970 | 7011 | ||
| 6971 | /* Find the glyph under X/Y. */ | 7012 | /* Find the glyph under X/Y. */ |
| 6972 | *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area); | 7013 | *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0); |
| 6973 | if (*glyph == NULL) | 7014 | if (*glyph == NULL) |
| 6974 | return -1; | 7015 | return -1; |
| 6975 | 7016 | ||
| @@ -7167,7 +7208,7 @@ fast_find_position (w, pos, hpos, vpos, x, y) | |||
| 7167 | int maybe_next_line_p = 0; | 7208 | int maybe_next_line_p = 0; |
| 7168 | int line_start_position; | 7209 | int line_start_position; |
| 7169 | int yb = window_text_bottom_y (w); | 7210 | int yb = window_text_bottom_y (w); |
| 7170 | struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0); | 7211 | struct glyph_row *row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); |
| 7171 | struct glyph_row *best_row = row; | 7212 | struct glyph_row *best_row = row; |
| 7172 | int row_vpos = 0, best_row_vpos = 0; | 7213 | int row_vpos = 0, best_row_vpos = 0; |
| 7173 | int current_x; | 7214 | int current_x; |
| @@ -7246,6 +7287,88 @@ fast_find_position (w, pos, hpos, vpos, x, y) | |||
| 7246 | } | 7287 | } |
| 7247 | 7288 | ||
| 7248 | 7289 | ||
| 7290 | /* Find the position of the the glyph for position POS in OBJECT in | ||
| 7291 | window W's current matrix, and return in *X/*Y the pixel | ||
| 7292 | coordinates, and return in *HPOS/*VPOS the column/row of the glyph. | ||
| 7293 | |||
| 7294 | RIGHT_P non-zero means return the position of the right edge of the | ||
| 7295 | glyph, RIGHT_P zero means return the left edge position. | ||
| 7296 | |||
| 7297 | If no glyph for POS exists in the matrix, return the position of | ||
| 7298 | the glyph with the next smaller position that is in the matrix, if | ||
| 7299 | RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS | ||
| 7300 | exists in the matrix, return the position of the glyph with the | ||
| 7301 | next larger position in OBJECT. | ||
| 7302 | |||
| 7303 | Value is non-zero if a glyph was found. */ | ||
| 7304 | |||
| 7305 | static int | ||
| 7306 | fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p) | ||
| 7307 | struct window *w; | ||
| 7308 | int pos; | ||
| 7309 | Lisp_Object object; | ||
| 7310 | int *hpos, *vpos, *x, *y; | ||
| 7311 | int right_p; | ||
| 7312 | { | ||
| 7313 | int yb = window_text_bottom_y (w); | ||
| 7314 | struct glyph_row *r; | ||
| 7315 | struct glyph *best_glyph = NULL; | ||
| 7316 | struct glyph_row *best_row = NULL; | ||
| 7317 | int best_x = 0; | ||
| 7318 | |||
| 7319 | for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | ||
| 7320 | r->enabled_p && r->y < yb; | ||
| 7321 | ++r) | ||
| 7322 | { | ||
| 7323 | struct glyph *g = r->glyphs[TEXT_AREA]; | ||
| 7324 | struct glyph *e = g + r->used[TEXT_AREA]; | ||
| 7325 | int gx; | ||
| 7326 | |||
| 7327 | for (gx = r->x; g < e; gx += g->pixel_width, ++g) | ||
| 7328 | if (EQ (g->object, object)) | ||
| 7329 | { | ||
| 7330 | if (g->charpos == pos) | ||
| 7331 | { | ||
| 7332 | best_glyph = g; | ||
| 7333 | best_x = gx; | ||
| 7334 | best_row = r; | ||
| 7335 | goto found; | ||
| 7336 | } | ||
| 7337 | else if (best_glyph == NULL | ||
| 7338 | || ((abs (g->charpos - pos) | ||
| 7339 | < abs (best_glyph->charpos - pos)) | ||
| 7340 | && (right_p | ||
| 7341 | ? g->charpos < pos | ||
| 7342 | : g->charpos > pos))) | ||
| 7343 | { | ||
| 7344 | best_glyph = g; | ||
| 7345 | best_x = gx; | ||
| 7346 | best_row = r; | ||
| 7347 | } | ||
| 7348 | } | ||
| 7349 | } | ||
| 7350 | |||
| 7351 | found: | ||
| 7352 | |||
| 7353 | if (best_glyph) | ||
| 7354 | { | ||
| 7355 | *x = best_x; | ||
| 7356 | *hpos = best_glyph - best_row->glyphs[TEXT_AREA]; | ||
| 7357 | |||
| 7358 | if (right_p) | ||
| 7359 | { | ||
| 7360 | *x += best_glyph->pixel_width; | ||
| 7361 | ++*hpos; | ||
| 7362 | } | ||
| 7363 | |||
| 7364 | *y = best_row->y; | ||
| 7365 | *vpos = best_row - w->current_matrix->rows; | ||
| 7366 | } | ||
| 7367 | |||
| 7368 | return best_glyph != NULL; | ||
| 7369 | } | ||
| 7370 | |||
| 7371 | |||
| 7249 | /* Display the active region described by mouse_face_* | 7372 | /* Display the active region described by mouse_face_* |
| 7250 | in its mouse-face if HL > 0, in its normal face if HL = 0. */ | 7373 | in its mouse-face if HL > 0, in its normal face if HL = 0. */ |
| 7251 | 7374 | ||