diff options
| author | Chong Yidong | 2009-06-22 01:53:11 +0000 |
|---|---|---|
| committer | Chong Yidong | 2009-06-22 01:53:11 +0000 |
| commit | 8a668709c216fe2deab4e22967c89a66381fd9de (patch) | |
| tree | fc05798d0570941b12ca0e5cbca40f9e8661b67a /src | |
| parent | 70243478757ed60bfdc1a6ec26997409d8619a5a (diff) | |
| download | emacs-8a668709c216fe2deab4e22967c89a66381fd9de.tar.gz emacs-8a668709c216fe2deab4e22967c89a66381fd9de.zip | |
* xdisp.c (Qbefore_string, Qafter_string): Add externs.
(load_overlay_strings): Remove externs.
(fast_find_position): Function deleted.
(mouse_face_from_buffer_pos): New function, based on
fast_find_position. Correctly handle before-strings,
display-strings, and after-strings (Bug#1220).
(note_mouse_highlight): Use mouse_face_from_buffer_pos.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 10 | ||||
| -rw-r--r-- | src/xdisp.c | 519 |
2 files changed, 225 insertions, 304 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index da3c09d2501..5ffadfb9f86 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,13 @@ | |||
| 1 | 2009-06-22 Chong Yidong <cyd@stupidchicken.com> | ||
| 2 | |||
| 3 | * xdisp.c (Qbefore_string, Qafter_string): Add externs. | ||
| 4 | (load_overlay_strings): Remove externs. | ||
| 5 | (fast_find_position): Function deleted. | ||
| 6 | (mouse_face_from_buffer_pos): New function, based on | ||
| 7 | fast_find_position. Correctly handle before-strings, | ||
| 8 | display-strings, and after-strings (Bug#1220). | ||
| 9 | (note_mouse_highlight): Use mouse_face_from_buffer_pos. | ||
| 10 | |||
| 1 | 2009-06-21 Chong Yidong <cyd@stupidchicken.com> | 11 | 2009-06-21 Chong Yidong <cyd@stupidchicken.com> |
| 2 | 12 | ||
| 3 | * xdisp.c (IT_DISPLAYING_WHITESPACE): Define for | 13 | * xdisp.c (IT_DISPLAYING_WHITESPACE): Define for |
diff --git a/src/xdisp.c b/src/xdisp.c index f1572600566..68f2a4fc7b0 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -235,6 +235,7 @@ extern Lisp_Object Voverriding_local_map_menu_flag; | |||
| 235 | extern Lisp_Object Qmenu_item; | 235 | extern Lisp_Object Qmenu_item; |
| 236 | extern Lisp_Object Qwhen; | 236 | extern Lisp_Object Qwhen; |
| 237 | extern Lisp_Object Qhelp_echo; | 237 | extern Lisp_Object Qhelp_echo; |
| 238 | extern Lisp_Object Qbefore_string, Qafter_string; | ||
| 238 | 239 | ||
| 239 | Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; | 240 | Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; |
| 240 | Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; | 241 | Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; |
| @@ -4870,7 +4871,7 @@ load_overlay_strings (it, charpos) | |||
| 4870 | struct it *it; | 4871 | struct it *it; |
| 4871 | int charpos; | 4872 | int charpos; |
| 4872 | { | 4873 | { |
| 4873 | extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority; | 4874 | extern Lisp_Object Qwindow, Qpriority; |
| 4874 | Lisp_Object overlay, window, str, invisible; | 4875 | Lisp_Object overlay, window, str, invisible; |
| 4875 | struct Lisp_Overlay *ov; | 4876 | struct Lisp_Overlay *ov; |
| 4876 | int start, end; | 4877 | int start, end; |
| @@ -22918,206 +22919,181 @@ cursor_in_mouse_face_p (w) | |||
| 22918 | 22919 | ||
| 22919 | 22920 | ||
| 22920 | 22921 | ||
| 22921 | /* Find the glyph matrix position of buffer position CHARPOS in window | 22922 | /* This function sets the mouse_face_* elements of DPYINFO, assuming |
| 22922 | *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's | 22923 | the mouse cursor is on a glyph with buffer charpos MOUSE_CHARPOS in |
| 22923 | current glyphs must be up to date. If CHARPOS is above window | 22924 | window WINDOW. START_CHARPOS and END_CHARPOS are buffer positions |
| 22924 | start return (0, 0, 0, 0). If CHARPOS is after end of W, return end | 22925 | for the overlay or run of text properties specifying the mouse |
| 22925 | of last line in W. In the row containing CHARPOS, stop before glyphs | 22926 | face. BEFORE_STRING and AFTER_STRING, if non-nil, are a |
| 22926 | having STOP as object. */ | 22927 | before-string and after-string that must also be highlighted. |
| 22927 | 22928 | DISPLAY_STRING, if non-nil, is a display string that may cover some | |
| 22928 | #if 1 /* This is a version of fast_find_position that's more correct | 22929 | or all of the highlighted text. */ |
| 22929 | in the presence of hscrolling, for example. I didn't install | ||
| 22930 | it right away because the problem fixed is minor, it failed | ||
| 22931 | in 20.x as well, and I think it's too risky to install | ||
| 22932 | so near the release of 21.1. 2001-09-25 gerd. */ | ||
| 22933 | 22930 | ||
| 22934 | static | 22931 | static void |
| 22935 | int | 22932 | mouse_face_from_buffer_pos (Lisp_Object window, |
| 22936 | fast_find_position (w, charpos, hpos, vpos, x, y, stop) | 22933 | Display_Info *dpyinfo, |
| 22937 | struct window *w; | 22934 | EMACS_INT mouse_charpos, |
| 22938 | EMACS_INT charpos; | 22935 | EMACS_INT start_charpos, |
| 22939 | int *hpos, *vpos, *x, *y; | 22936 | EMACS_INT end_charpos, |
| 22940 | Lisp_Object stop; | 22937 | Lisp_Object before_string, |
| 22938 | Lisp_Object after_string, | ||
| 22939 | Lisp_Object display_string) | ||
| 22941 | { | 22940 | { |
| 22942 | struct glyph_row *row, *first; | 22941 | struct window *w = XWINDOW (window); |
| 22942 | struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | ||
| 22943 | struct glyph_row *row; | ||
| 22943 | struct glyph *glyph, *end; | 22944 | struct glyph *glyph, *end; |
| 22944 | int past_end = 0; | 22945 | EMACS_INT ignore; |
| 22946 | int x; | ||
| 22945 | 22947 | ||
| 22946 | first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | 22948 | xassert (NILP (display_string) || STRINGP (display_string)); |
| 22947 | if (charpos < MATRIX_ROW_START_CHARPOS (first)) | 22949 | xassert (NILP (before_string) || STRINGP (before_string)); |
| 22948 | { | 22950 | xassert (NILP (after_string) || STRINGP (after_string)); |
| 22949 | *x = first->x; | ||
| 22950 | *y = first->y; | ||
| 22951 | *hpos = 0; | ||
| 22952 | *vpos = MATRIX_ROW_VPOS (first, w->current_matrix); | ||
| 22953 | return 1; | ||
| 22954 | } | ||
| 22955 | 22951 | ||
| 22956 | row = row_containing_pos (w, charpos, first, NULL, 0); | 22952 | /* Find the first highlighted glyph. */ |
| 22957 | if (row == NULL) | 22953 | if (start_charpos < MATRIX_ROW_START_CHARPOS (first)) |
| 22958 | { | 22954 | { |
| 22959 | row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); | 22955 | dpyinfo->mouse_face_beg_col = 0; |
| 22960 | past_end = 1; | 22956 | dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (first, w->current_matrix); |
| 22957 | dpyinfo->mouse_face_beg_x = first->x; | ||
| 22958 | dpyinfo->mouse_face_beg_y = first->y; | ||
| 22961 | } | 22959 | } |
| 22962 | 22960 | else | |
| 22963 | /* If whole rows or last part of a row came from a display overlay, | ||
| 22964 | row_containing_pos will skip over such rows because their end pos | ||
| 22965 | equals the start pos of the overlay or interval. | ||
| 22966 | |||
| 22967 | Move back if we have a STOP object and previous row's | ||
| 22968 | end glyph came from STOP. */ | ||
| 22969 | if (!NILP (stop)) | ||
| 22970 | { | 22961 | { |
| 22971 | struct glyph_row *prev; | 22962 | row = row_containing_pos (w, start_charpos, first, NULL, 0); |
| 22972 | while ((prev = row - 1, prev >= first) | 22963 | if (row == NULL) |
| 22973 | && MATRIX_ROW_END_CHARPOS (prev) == charpos | 22964 | row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); |
| 22974 | && prev->used[TEXT_AREA] > 0) | 22965 | |
| 22966 | /* If the before-string or display-string contains newlines, | ||
| 22967 | row_containing_pos skips to its last row. Move back. */ | ||
| 22968 | if (!NILP (before_string) || !NILP (display_string)) | ||
| 22975 | { | 22969 | { |
| 22976 | struct glyph *beg = prev->glyphs[TEXT_AREA]; | 22970 | struct glyph_row *prev; |
| 22977 | glyph = beg + prev->used[TEXT_AREA]; | 22971 | while ((prev = row - 1, prev >= first) |
| 22978 | while (--glyph >= beg | 22972 | && MATRIX_ROW_END_CHARPOS (prev) == start_charpos |
| 22979 | && INTEGERP (glyph->object)); | 22973 | && prev->used[TEXT_AREA] > 0) |
| 22980 | if (glyph < beg | 22974 | { |
| 22981 | || !EQ (stop, glyph->object)) | 22975 | struct glyph *beg = prev->glyphs[TEXT_AREA]; |
| 22982 | break; | 22976 | glyph = beg + prev->used[TEXT_AREA]; |
| 22983 | row = prev; | 22977 | while (--glyph >= beg && INTEGERP (glyph->object)); |
| 22978 | if (glyph < beg | ||
| 22979 | || !(EQ (glyph->object, before_string) | ||
| 22980 | || EQ (glyph->object, display_string))) | ||
| 22981 | break; | ||
| 22982 | row = prev; | ||
| 22983 | } | ||
| 22984 | } | 22984 | } |
| 22985 | } | ||
| 22986 | 22985 | ||
| 22987 | *x = row->x; | 22986 | glyph = row->glyphs[TEXT_AREA]; |
| 22988 | *y = row->y; | 22987 | end = glyph + row->used[TEXT_AREA]; |
| 22989 | *vpos = MATRIX_ROW_VPOS (row, w->current_matrix); | 22988 | x = row->x; |
| 22989 | dpyinfo->mouse_face_beg_y = row->y; | ||
| 22990 | dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (row, w->current_matrix); | ||
| 22990 | 22991 | ||
| 22991 | glyph = row->glyphs[TEXT_AREA]; | 22992 | /* Skip truncation glyphs at the start of the glyph row. */ |
| 22992 | end = glyph + row->used[TEXT_AREA]; | 22993 | if (row->displays_text_p) |
| 22994 | for (; glyph < end && INTEGERP (glyph->object); ++glyph) | ||
| 22995 | x += glyph->pixel_width; | ||
| 22993 | 22996 | ||
| 22994 | /* Skip over glyphs not having an object at the start of the row. | 22997 | /* Scan the glyph row, stopping before BEFORE_STRING or |
| 22995 | These are special glyphs like truncation marks on terminal | 22998 | DISPLAY_STRING or START_CHARPOS. */ |
| 22996 | frames. */ | 22999 | for (; glyph < end |
| 22997 | if (row->displays_text_p) | 23000 | && !INTEGERP (glyph->object) |
| 22998 | while (glyph < end | 23001 | && !EQ (glyph->object, before_string) |
| 22999 | && INTEGERP (glyph->object) | 23002 | && !EQ (glyph->object, display_string) |
| 23000 | && !EQ (stop, glyph->object) | 23003 | && !(BUFFERP (glyph->object) |
| 23001 | && glyph->charpos < 0) | 23004 | && glyph->charpos >= start_charpos); |
| 23002 | { | 23005 | ++glyph) |
| 23003 | *x += glyph->pixel_width; | 23006 | x += glyph->pixel_width; |
| 23004 | ++glyph; | ||
| 23005 | } | ||
| 23006 | 23007 | ||
| 23007 | while (glyph < end | 23008 | dpyinfo->mouse_face_beg_x = x; |
| 23008 | && !INTEGERP (glyph->object) | 23009 | dpyinfo->mouse_face_beg_col = glyph - row->glyphs[TEXT_AREA]; |
| 23009 | && !EQ (stop, glyph->object) | 23010 | } |
| 23010 | && (!BUFFERP (glyph->object) | 23011 | |
| 23011 | || glyph->charpos < charpos)) | 23012 | /* Find the last highlighted glyph. */ |
| 23013 | row = row_containing_pos (w, end_charpos, first, NULL, 0); | ||
| 23014 | if (row == NULL) | ||
| 23012 | { | 23015 | { |
| 23013 | *x += glyph->pixel_width; | 23016 | row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); |
| 23014 | ++glyph; | 23017 | dpyinfo->mouse_face_past_end = 1; |
| 23015 | } | 23018 | } |
| 23019 | else if (!NILP (after_string)) | ||
| 23020 | { | ||
| 23021 | /* If the after-string has newlines, advance to its last row. */ | ||
| 23022 | struct glyph_row *next; | ||
| 23023 | struct glyph_row *last | ||
| 23024 | = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); | ||
| 23016 | 23025 | ||
| 23017 | *hpos = glyph - row->glyphs[TEXT_AREA]; | 23026 | for (next = row + 1; |
| 23018 | return !past_end; | 23027 | next <= last |
| 23019 | } | 23028 | && next->used[TEXT_AREA] > 0 |
| 23029 | && EQ (next->glyphs[TEXT_AREA]->object, after_string); | ||
| 23030 | ++next) | ||
| 23031 | row = next; | ||
| 23032 | } | ||
| 23020 | 23033 | ||
| 23021 | #else /* not 1 */ | 23034 | glyph = row->glyphs[TEXT_AREA]; |
| 23035 | end = glyph + row->used[TEXT_AREA]; | ||
| 23036 | x = row->x; | ||
| 23037 | dpyinfo->mouse_face_end_y = row->y; | ||
| 23038 | dpyinfo->mouse_face_end_row = MATRIX_ROW_VPOS (row, w->current_matrix); | ||
| 23022 | 23039 | ||
| 23023 | static int | 23040 | /* Skip truncation glyphs at the start of the row. */ |
| 23024 | fast_find_position (w, pos, hpos, vpos, x, y, stop) | 23041 | if (row->displays_text_p) |
| 23025 | struct window *w; | 23042 | for (; glyph < end && INTEGERP (glyph->object); ++glyph) |
| 23026 | EMACS_INT pos; | 23043 | x += glyph->pixel_width; |
| 23027 | int *hpos, *vpos, *x, *y; | ||
| 23028 | Lisp_Object stop; | ||
| 23029 | { | ||
| 23030 | int i; | ||
| 23031 | int lastcol; | ||
| 23032 | int maybe_next_line_p = 0; | ||
| 23033 | int line_start_position; | ||
| 23034 | int yb = window_text_bottom_y (w); | ||
| 23035 | struct glyph_row *row, *best_row; | ||
| 23036 | int row_vpos, best_row_vpos; | ||
| 23037 | int current_x; | ||
| 23038 | 23044 | ||
| 23039 | row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | 23045 | /* Scan the glyph row, stopping at END_CHARPOS or when we encounter |
| 23040 | row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix); | 23046 | AFTER_STRING. */ |
| 23047 | for (; glyph < end | ||
| 23048 | && !INTEGERP (glyph->object) | ||
| 23049 | && !EQ (glyph->object, after_string) | ||
| 23050 | && !(BUFFERP (glyph->object) && glyph->charpos >= end_charpos); | ||
| 23051 | ++glyph) | ||
| 23052 | x += glyph->pixel_width; | ||
| 23041 | 23053 | ||
| 23042 | while (row->y < yb) | 23054 | /* If we found AFTER_STRING, consume it and stop. */ |
| 23055 | if (EQ (glyph->object, after_string)) | ||
| 23043 | { | 23056 | { |
| 23044 | if (row->used[TEXT_AREA]) | 23057 | for (; EQ (glyph->object, after_string) && glyph < end; ++glyph) |
| 23045 | line_start_position = row->glyphs[TEXT_AREA]->charpos; | 23058 | x += glyph->pixel_width; |
| 23046 | else | ||
| 23047 | line_start_position = 0; | ||
| 23048 | |||
| 23049 | if (line_start_position > pos) | ||
| 23050 | break; | ||
| 23051 | /* If the position sought is the end of the buffer, | ||
| 23052 | don't include the blank lines at the bottom of the window. */ | ||
| 23053 | else if (line_start_position == pos | ||
| 23054 | && pos == BUF_ZV (XBUFFER (w->buffer))) | ||
| 23055 | { | ||
| 23056 | maybe_next_line_p = 1; | ||
| 23057 | break; | ||
| 23058 | } | ||
| 23059 | else if (line_start_position > 0) | ||
| 23060 | { | ||
| 23061 | best_row = row; | ||
| 23062 | best_row_vpos = row_vpos; | ||
| 23063 | } | ||
| 23064 | |||
| 23065 | if (row->y + row->height >= yb) | ||
| 23066 | break; | ||
| 23067 | |||
| 23068 | ++row; | ||
| 23069 | ++row_vpos; | ||
| 23070 | } | 23059 | } |
| 23071 | 23060 | else | |
| 23072 | /* Find the right column within BEST_ROW. */ | ||
| 23073 | lastcol = 0; | ||
| 23074 | current_x = best_row->x; | ||
| 23075 | for (i = 0; i < best_row->used[TEXT_AREA]; i++) | ||
| 23076 | { | 23061 | { |
| 23077 | struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i; | 23062 | /* If there's no after-string, we must check if we overshot, |
| 23078 | int charpos = glyph->charpos; | 23063 | which might be the case if we stopped after a string glyph. |
| 23064 | That glyph may belong to a before-string or display-string | ||
| 23065 | associated with the end position, which must not be | ||
| 23066 | highlighted. */ | ||
| 23067 | Lisp_Object prev_object; | ||
| 23068 | int pos; | ||
| 23079 | 23069 | ||
| 23080 | if (BUFFERP (glyph->object)) | 23070 | while (glyph > row->glyphs[TEXT_AREA]) |
| 23081 | { | 23071 | { |
| 23082 | if (charpos == pos) | 23072 | prev_object = (glyph - 1)->object; |
| 23083 | { | 23073 | if (!STRINGP (prev_object) || EQ (prev_object, display_string)) |
| 23084 | *hpos = i; | ||
| 23085 | *vpos = best_row_vpos; | ||
| 23086 | *x = current_x; | ||
| 23087 | *y = best_row->y; | ||
| 23088 | return 1; | ||
| 23089 | } | ||
| 23090 | else if (charpos > pos) | ||
| 23091 | break; | 23074 | break; |
| 23092 | } | ||
| 23093 | else if (EQ (glyph->object, stop)) | ||
| 23094 | break; | ||
| 23095 | 23075 | ||
| 23096 | if (charpos > 0) | 23076 | pos = string_buffer_position (w, prev_object, end_charpos); |
| 23097 | lastcol = i; | 23077 | if (pos && pos < end_charpos) |
| 23098 | current_x += glyph->pixel_width; | 23078 | break; |
| 23099 | } | ||
| 23100 | 23079 | ||
| 23101 | /* If we're looking for the end of the buffer, | 23080 | for (; glyph > row->glyphs[TEXT_AREA] |
| 23102 | and we didn't find it in the line we scanned, | 23081 | && EQ ((glyph - 1)->object, prev_object); |
| 23103 | use the start of the following line. */ | 23082 | --glyph) |
| 23104 | if (maybe_next_line_p) | 23083 | x -= (glyph - 1)->pixel_width; |
| 23105 | { | 23084 | } |
| 23106 | ++best_row; | ||
| 23107 | ++best_row_vpos; | ||
| 23108 | lastcol = 0; | ||
| 23109 | current_x = best_row->x; | ||
| 23110 | } | 23085 | } |
| 23111 | 23086 | ||
| 23112 | *vpos = best_row_vpos; | 23087 | dpyinfo->mouse_face_end_x = x; |
| 23113 | *hpos = lastcol + 1; | 23088 | dpyinfo->mouse_face_end_col = glyph - row->glyphs[TEXT_AREA]; |
| 23114 | *x = current_x; | 23089 | dpyinfo->mouse_face_window = window; |
| 23115 | *y = best_row->y; | 23090 | dpyinfo->mouse_face_face_id |
| 23116 | return 0; | 23091 | = face_at_buffer_position (w, mouse_charpos, 0, 0, &ignore, |
| 23092 | mouse_charpos + 1, | ||
| 23093 | !dpyinfo->mouse_face_hidden, -1); | ||
| 23094 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | ||
| 23117 | } | 23095 | } |
| 23118 | 23096 | ||
| 23119 | #endif /* not 1 */ | ||
| 23120 | |||
| 23121 | 23097 | ||
| 23122 | /* Find the position of the glyph for position POS in OBJECT in | 23098 | /* Find the position of the glyph for position POS in OBJECT in |
| 23123 | window W's current matrix, and return in *X, *Y the pixel | 23099 | window W's current matrix, and return in *X, *Y the pixel |
| @@ -23844,8 +23820,7 @@ note_mouse_highlight (f, x, y) | |||
| 23844 | || (OVERLAYP (dpyinfo->mouse_face_overlay) | 23820 | || (OVERLAYP (dpyinfo->mouse_face_overlay) |
| 23845 | && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay))) | 23821 | && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay))) |
| 23846 | { | 23822 | { |
| 23847 | /* Find the highest priority overlay that has a mouse-face | 23823 | /* Find the highest priority overlay with a mouse-face. */ |
| 23848 | property. */ | ||
| 23849 | overlay = Qnil; | 23824 | overlay = Qnil; |
| 23850 | for (i = noverlays - 1; i >= 0 && NILP (overlay); --i) | 23825 | for (i = noverlays - 1; i >= 0 && NILP (overlay); --i) |
| 23851 | { | 23826 | { |
| @@ -23854,12 +23829,10 @@ note_mouse_highlight (f, x, y) | |||
| 23854 | overlay = overlay_vec[i]; | 23829 | overlay = overlay_vec[i]; |
| 23855 | } | 23830 | } |
| 23856 | 23831 | ||
| 23857 | /* If we're actually highlighting the same overlay as | 23832 | /* If we're highlighting the same overlay as before, there's |
| 23858 | before, there's no need to do that again. */ | 23833 | no need to do that again. */ |
| 23859 | if (!NILP (overlay) | 23834 | if (!NILP (overlay) && EQ (overlay, dpyinfo->mouse_face_overlay)) |
| 23860 | && EQ (overlay, dpyinfo->mouse_face_overlay)) | ||
| 23861 | goto check_help_echo; | 23835 | goto check_help_echo; |
| 23862 | |||
| 23863 | dpyinfo->mouse_face_overlay = overlay; | 23836 | dpyinfo->mouse_face_overlay = overlay; |
| 23864 | 23837 | ||
| 23865 | /* Clear the display of the old active region, if any. */ | 23838 | /* Clear the display of the old active region, if any. */ |
| @@ -23870,95 +23843,19 @@ note_mouse_highlight (f, x, y) | |||
| 23870 | if (NILP (overlay)) | 23843 | if (NILP (overlay)) |
| 23871 | mouse_face = Fget_text_property (position, Qmouse_face, object); | 23844 | mouse_face = Fget_text_property (position, Qmouse_face, object); |
| 23872 | 23845 | ||
| 23873 | /* Handle the overlay case. */ | 23846 | /* Next, compute the bounds of the mouse highlighting and |
| 23874 | if (!NILP (overlay)) | 23847 | display it. */ |
| 23875 | { | 23848 | if (!NILP (mouse_face) && STRINGP (object)) |
| 23876 | /* Find the range of text around this char that | ||
| 23877 | should be active. */ | ||
| 23878 | Lisp_Object before, after; | ||
| 23879 | EMACS_INT ignore; | ||
| 23880 | |||
| 23881 | before = Foverlay_start (overlay); | ||
| 23882 | after = Foverlay_end (overlay); | ||
| 23883 | /* Record this as the current active region. */ | ||
| 23884 | fast_find_position (w, XFASTINT (before), | ||
| 23885 | &dpyinfo->mouse_face_beg_col, | ||
| 23886 | &dpyinfo->mouse_face_beg_row, | ||
| 23887 | &dpyinfo->mouse_face_beg_x, | ||
| 23888 | &dpyinfo->mouse_face_beg_y, Qnil); | ||
| 23889 | |||
| 23890 | dpyinfo->mouse_face_past_end | ||
| 23891 | = !fast_find_position (w, XFASTINT (after), | ||
| 23892 | &dpyinfo->mouse_face_end_col, | ||
| 23893 | &dpyinfo->mouse_face_end_row, | ||
| 23894 | &dpyinfo->mouse_face_end_x, | ||
| 23895 | &dpyinfo->mouse_face_end_y, Qnil); | ||
| 23896 | dpyinfo->mouse_face_window = window; | ||
| 23897 | |||
| 23898 | dpyinfo->mouse_face_face_id | ||
| 23899 | = face_at_buffer_position (w, pos, 0, 0, | ||
| 23900 | &ignore, pos + 1, | ||
| 23901 | !dpyinfo->mouse_face_hidden, | ||
| 23902 | -1); | ||
| 23903 | |||
| 23904 | /* Display it as active. */ | ||
| 23905 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | ||
| 23906 | cursor = No_Cursor; | ||
| 23907 | } | ||
| 23908 | /* Handle the text property case. */ | ||
| 23909 | else if (!NILP (mouse_face) && BUFFERP (object)) | ||
| 23910 | { | ||
| 23911 | /* Find the range of text around this char that | ||
| 23912 | should be active. */ | ||
| 23913 | Lisp_Object before, after, beginning, end; | ||
| 23914 | EMACS_INT ignore; | ||
| 23915 | |||
| 23916 | beginning = Fmarker_position (w->start); | ||
| 23917 | end = make_number (BUF_Z (XBUFFER (object)) | ||
| 23918 | - XFASTINT (w->window_end_pos)); | ||
| 23919 | before | ||
| 23920 | = Fprevious_single_property_change (make_number (pos + 1), | ||
| 23921 | Qmouse_face, | ||
| 23922 | object, beginning); | ||
| 23923 | after | ||
| 23924 | = Fnext_single_property_change (position, Qmouse_face, | ||
| 23925 | object, end); | ||
| 23926 | |||
| 23927 | /* Record this as the current active region. */ | ||
| 23928 | fast_find_position (w, XFASTINT (before), | ||
| 23929 | &dpyinfo->mouse_face_beg_col, | ||
| 23930 | &dpyinfo->mouse_face_beg_row, | ||
| 23931 | &dpyinfo->mouse_face_beg_x, | ||
| 23932 | &dpyinfo->mouse_face_beg_y, Qnil); | ||
| 23933 | dpyinfo->mouse_face_past_end | ||
| 23934 | = !fast_find_position (w, XFASTINT (after), | ||
| 23935 | &dpyinfo->mouse_face_end_col, | ||
| 23936 | &dpyinfo->mouse_face_end_row, | ||
| 23937 | &dpyinfo->mouse_face_end_x, | ||
| 23938 | &dpyinfo->mouse_face_end_y, Qnil); | ||
| 23939 | dpyinfo->mouse_face_window = window; | ||
| 23940 | |||
| 23941 | if (BUFFERP (object)) | ||
| 23942 | dpyinfo->mouse_face_face_id | ||
| 23943 | = face_at_buffer_position (w, pos, 0, 0, | ||
| 23944 | &ignore, pos + 1, | ||
| 23945 | !dpyinfo->mouse_face_hidden, | ||
| 23946 | -1); | ||
| 23947 | |||
| 23948 | /* Display it as active. */ | ||
| 23949 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | ||
| 23950 | cursor = No_Cursor; | ||
| 23951 | } | ||
| 23952 | else if (!NILP (mouse_face) && STRINGP (object)) | ||
| 23953 | { | 23849 | { |
| 23850 | /* The mouse-highlighting comes from a display string | ||
| 23851 | with a mouse-face. */ | ||
| 23954 | Lisp_Object b, e; | 23852 | Lisp_Object b, e; |
| 23955 | EMACS_INT ignore; | 23853 | EMACS_INT ignore; |
| 23956 | 23854 | ||
| 23957 | b = Fprevious_single_property_change (make_number (pos + 1), | 23855 | b = Fprevious_single_property_change |
| 23958 | Qmouse_face, | 23856 | (make_number (pos + 1), Qmouse_face, object, Qnil); |
| 23959 | object, Qnil); | 23857 | e = Fnext_single_property_change |
| 23960 | e = Fnext_single_property_change (position, Qmouse_face, | 23858 | (position, Qmouse_face, object, Qnil); |
| 23961 | object, Qnil); | ||
| 23962 | if (NILP (b)) | 23859 | if (NILP (b)) |
| 23963 | b = make_number (0); | 23860 | b = make_number (0); |
| 23964 | if (NILP (e)) | 23861 | if (NILP (e)) |
| @@ -23982,53 +23879,67 @@ note_mouse_highlight (f, x, y) | |||
| 23982 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | 23879 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); |
| 23983 | cursor = No_Cursor; | 23880 | cursor = No_Cursor; |
| 23984 | } | 23881 | } |
| 23985 | else if (STRINGP (object) && NILP (mouse_face)) | 23882 | else |
| 23986 | { | 23883 | { |
| 23987 | /* A string which doesn't have mouse-face, but | 23884 | /* The mouse-highlighting, if any, comes from an overlay |
| 23988 | the text ``under'' it might have. */ | 23885 | or text property in the buffer. */ |
| 23989 | struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos); | 23886 | Lisp_Object buffer, display_string; |
| 23990 | int start = MATRIX_ROW_START_CHARPOS (r); | 23887 | |
| 23991 | 23888 | if (STRINGP (object)) | |
| 23992 | pos = string_buffer_position (w, object, start); | ||
| 23993 | if (pos > 0) | ||
| 23994 | mouse_face = get_char_property_and_overlay (make_number (pos), | ||
| 23995 | Qmouse_face, | ||
| 23996 | w->buffer, | ||
| 23997 | &overlay); | ||
| 23998 | if (!NILP (mouse_face) && !NILP (overlay)) | ||
| 23999 | { | 23889 | { |
| 24000 | Lisp_Object before = Foverlay_start (overlay); | 23890 | /* If we are on a display string with no mouse-face, |
| 24001 | Lisp_Object after = Foverlay_end (overlay); | 23891 | check if the text under it has one. */ |
| 24002 | EMACS_INT ignore; | 23892 | struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos); |
| 23893 | int start = MATRIX_ROW_START_CHARPOS (r); | ||
| 23894 | pos = string_buffer_position (w, object, start); | ||
| 23895 | if (pos > 0) | ||
| 23896 | { | ||
| 23897 | mouse_face = get_char_property_and_overlay | ||
| 23898 | (make_number (pos), Qmouse_face, w->buffer, &overlay); | ||
| 23899 | buffer = w->buffer; | ||
| 23900 | display_string = object; | ||
| 23901 | } | ||
| 23902 | } | ||
| 23903 | else | ||
| 23904 | { | ||
| 23905 | buffer = object; | ||
| 23906 | display_string = Qnil; | ||
| 23907 | } | ||
| 23908 | |||
| 23909 | if (!NILP (mouse_face)) | ||
| 23910 | { | ||
| 23911 | Lisp_Object before, after; | ||
| 23912 | Lisp_Object before_string, after_string; | ||
| 23913 | |||
| 23914 | if (NILP (overlay)) | ||
| 23915 | { | ||
| 23916 | /* Handle the text property case. */ | ||
| 23917 | before = Fprevious_single_property_change | ||
| 23918 | (make_number (pos + 1), Qmouse_face, buffer, | ||
| 23919 | Fmarker_position (w->start)); | ||
| 23920 | after = Fnext_single_property_change | ||
| 23921 | (make_number (pos), Qmouse_face, buffer, | ||
| 23922 | make_number (BUF_Z (XBUFFER (buffer)) | ||
| 23923 | - XFASTINT (w->window_end_pos))); | ||
| 23924 | before_string = after_string = Qnil; | ||
| 23925 | } | ||
| 23926 | else | ||
| 23927 | { | ||
| 23928 | /* Handle the overlay case. */ | ||
| 23929 | before = Foverlay_start (overlay); | ||
| 23930 | after = Foverlay_end (overlay); | ||
| 23931 | before_string = Foverlay_get (overlay, Qbefore_string); | ||
| 23932 | after_string = Foverlay_get (overlay, Qafter_string); | ||
| 23933 | |||
| 23934 | if (!STRINGP (before_string)) before_string = Qnil; | ||
| 23935 | if (!STRINGP (after_string)) after_string = Qnil; | ||
| 23936 | } | ||
| 24003 | 23937 | ||
| 24004 | /* Note that we might not be able to find position | 23938 | mouse_face_from_buffer_pos (window, dpyinfo, pos, |
| 24005 | BEFORE in the glyph matrix if the overlay is | 23939 | XFASTINT (before), |
| 24006 | entirely covered by a `display' property. In | 23940 | XFASTINT (after), |
| 24007 | this case, we overshoot. So let's stop in | 23941 | before_string, after_string, |
| 24008 | the glyph matrix before glyphs for OBJECT. */ | 23942 | display_string); |
| 24009 | fast_find_position (w, XFASTINT (before), | ||
| 24010 | &dpyinfo->mouse_face_beg_col, | ||
| 24011 | &dpyinfo->mouse_face_beg_row, | ||
| 24012 | &dpyinfo->mouse_face_beg_x, | ||
| 24013 | &dpyinfo->mouse_face_beg_y, | ||
| 24014 | object); | ||
| 24015 | |||
| 24016 | dpyinfo->mouse_face_past_end | ||
| 24017 | = !fast_find_position (w, XFASTINT (after), | ||
| 24018 | &dpyinfo->mouse_face_end_col, | ||
| 24019 | &dpyinfo->mouse_face_end_row, | ||
| 24020 | &dpyinfo->mouse_face_end_x, | ||
| 24021 | &dpyinfo->mouse_face_end_y, | ||
| 24022 | Qnil); | ||
| 24023 | dpyinfo->mouse_face_window = window; | ||
| 24024 | dpyinfo->mouse_face_face_id | ||
| 24025 | = face_at_buffer_position (w, pos, 0, 0, | ||
| 24026 | &ignore, pos + 1, | ||
| 24027 | !dpyinfo->mouse_face_hidden, | ||
| 24028 | -1); | ||
| 24029 | |||
| 24030 | /* Display it as active. */ | ||
| 24031 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | ||
| 24032 | cursor = No_Cursor; | 23943 | cursor = No_Cursor; |
| 24033 | } | 23944 | } |
| 24034 | } | 23945 | } |