aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChong Yidong2009-06-22 01:53:11 +0000
committerChong Yidong2009-06-22 01:53:11 +0000
commit8a668709c216fe2deab4e22967c89a66381fd9de (patch)
treefc05798d0570941b12ca0e5cbca40f9e8661b67a /src
parent70243478757ed60bfdc1a6ec26997409d8619a5a (diff)
downloademacs-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/ChangeLog10
-rw-r--r--src/xdisp.c519
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 @@
12009-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
12009-06-21 Chong Yidong <cyd@stupidchicken.com> 112009-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;
235extern Lisp_Object Qmenu_item; 235extern Lisp_Object Qmenu_item;
236extern Lisp_Object Qwhen; 236extern Lisp_Object Qwhen;
237extern Lisp_Object Qhelp_echo; 237extern Lisp_Object Qhelp_echo;
238extern Lisp_Object Qbefore_string, Qafter_string;
238 239
239Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; 240Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
240Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; 241Lisp_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
22934static 22931static void
22935int 22932mouse_face_from_buffer_pos (Lisp_Object window,
22936fast_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
23023static int 23040 /* Skip truncation glyphs at the start of the row. */
23024fast_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 }