aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2010-10-23 17:30:45 +0200
committerEli Zaretskii2010-10-23 17:30:45 +0200
commitd1d6801eb4badab97416d0b6294e1920d0f90c3e (patch)
tree83cc92ae8e0a28b767e3abe8cc2e2753f1c855c7 /src
parenta6ac7fc4fddadcf7939f5f8b6ec09fadb4f90fc8 (diff)
parenta4041a7121ee093ec81ef0cb4b8da62a54587596 (diff)
downloademacs-d1d6801eb4badab97416d0b6294e1920d0f90c3e.tar.gz
emacs-d1d6801eb4badab97416d0b6294e1920d0f90c3e.zip
Implement mouse highlight for bidi-reordered lines.
xdisp.c (fast_find_string_pos): #ifdef away, not used anymore. (mouse_face_from_string_pos): New function, replaces fast_find_string_pos. (note_mouse_highlight): Call it instead of fast_find_string_pos. (note_mode_line_or_margin_highlight): Support bidi-reordered strings and R2L glyph rows. Fix comments. (note_mouse_highlight): When bidi reordering is turned on in a buffer, call next-single-property-change and previous-single-property-change with last argument nil. Clear mouse highlight when mouse pointer is in a R2L row on the stretch glyph that stands for no text beyond the line end. (row_containing_pos): Don't return too early when CHARPOS is in a bidi-reordered continued line. Return immediately when the first hit is found in a line that is not continued, or when an exact match for CHARPOS is found. (rows_from_pos_range): New function. (mouse_face_from_buffer_pos): Use it instead of calling row_containing_pos for START_CHARPOS and END_CHARPOS. Rewrite the function to support mouse highlight in bidi-reordered lines and not to assume that START_CHARPOS is always in mouse_face_beg_row. If necessary, swap mouse_face_beg_row and mouse_face_end_row so that the former is always above the latter or identical to it. (show_mouse_face): Support drawing highlighted R2L lines. (coords_in_mouse_face_p): New function, bidi-aware. (cursor_in_mouse_face_p, note_mouse_highlight, erase_phys_cursor): Call it instead of comparing with mouse-face members of dpyinfo. (note_mode_line_or_margin_highlight): Fix confusingly swapped usage of hpos and vpos.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog35
-rw-r--r--src/xdisp.c950
2 files changed, 754 insertions, 231 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 05a0d442149..e4cd83a6236 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,36 @@
12010-10-23 Eli Zaretskii <eliz@gnu.org>
2
3 Implement mouse highlight for bidi-reordered lines.
4
5 * xdisp.c (fast_find_string_pos): #ifdef away, not used anymore.
6 (mouse_face_from_string_pos): New function, replaces
7 fast_find_string_pos.
8 (note_mouse_highlight): Call it instead of fast_find_string_pos.
9 (note_mode_line_or_margin_highlight): Support bidi-reordered
10 strings and R2L glyph rows. Fix comments.
11 (note_mouse_highlight): When bidi reordering is turned on in a
12 buffer, call next-single-property-change and
13 previous-single-property-change with last argument nil. Clear
14 mouse highlight when mouse pointer is in a R2L row on the stretch
15 glyph that stands for no text beyond the line end.
16 (row_containing_pos): Don't return too early when CHARPOS is in a
17 bidi-reordered continued line. Return immediately when the first
18 hit is found in a line that is not continued, or when an exact
19 match for CHARPOS is found.
20 (rows_from_pos_range): New function.
21 (mouse_face_from_buffer_pos): Use it instead of calling
22 row_containing_pos for START_CHARPOS and END_CHARPOS. Rewrite the
23 function to support mouse highlight in bidi-reordered lines and
24 not to assume that START_CHARPOS is always in mouse_face_beg_row.
25 If necessary, swap mouse_face_beg_row and mouse_face_end_row so
26 that the former is always above the latter or identical to it.
27 (show_mouse_face): Support drawing highlighted R2L lines.
28 (coords_in_mouse_face_p): New function, bidi-aware.
29 (cursor_in_mouse_face_p, note_mouse_highlight, erase_phys_cursor):
30 Call it instead of comparing with mouse-face members of dpyinfo.
31 (note_mode_line_or_margin_highlight): Fix confusingly swapped
32 usage of hpos and vpos.
33
12010-10-22 Jan Djärv <jan.h.d@swipnet.se> 342010-10-22 Jan Djärv <jan.h.d@swipnet.se>
2 35
3 * xrdb.c: Include keyboard.h for MOTIF. 36 * xrdb.c: Include keyboard.h for MOTIF.
@@ -1528,7 +1561,7 @@
1528 non-MSDOS, non-WINDOWSNT code, it's only defined for such systems 1561 non-MSDOS, non-WINDOWSNT code, it's only defined for such systems
1529 anyway. 1562 anyway.
1530 1563
15312010-08-21 Eli Zaretskii <eliz@gnu.org> 15642010-08-20 Eli Zaretskii <eliz@gnu.org>
1532 1565
1533 * dispnew.c (buffer_posn_from_coords): Fix off-by-one error in 1566 * dispnew.c (buffer_posn_from_coords): Fix off-by-one error in
1534 mirroring pixel positions. 1567 mirroring pixel positions.
diff --git a/src/xdisp.c b/src/xdisp.c
index 4c007e572ce..e2ec1360b49 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -1085,6 +1085,7 @@ static void notice_overwritten_cursor (struct window *,
1085 int, int, int, int); 1085 int, int, int, int);
1086static void append_stretch_glyph (struct it *, Lisp_Object, 1086static void append_stretch_glyph (struct it *, Lisp_Object,
1087 int, int, int); 1087 int, int, int);
1088static int coords_in_mouse_face_p (struct window *, int, int);
1088 1089
1089 1090
1090 1091
@@ -15333,10 +15334,12 @@ row_containing_pos (struct window *w, EMACS_INT charpos,
15333 { 15334 {
15334 struct glyph *g; 15335 struct glyph *g;
15335 15336
15336 if (NILP (XBUFFER (w->buffer)->bidi_display_reordering)) 15337 if (NILP (XBUFFER (w->buffer)->bidi_display_reordering)
15338 || (!best_row && !row->continued_p))
15337 return row; 15339 return row;
15338 /* In bidi-reordered rows, there could be several rows 15340 /* In bidi-reordered rows, there could be several rows
15339 occluding point. We need to find the one which fits 15341 occluding point, all of them belonging to the same
15342 continued line. We need to find the row which fits
15340 CHARPOS the best. */ 15343 CHARPOS the best. */
15341 for (g = row->glyphs[TEXT_AREA]; 15344 for (g = row->glyphs[TEXT_AREA];
15342 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; 15345 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
@@ -15348,11 +15351,14 @@ row_containing_pos (struct window *w, EMACS_INT charpos,
15348 { 15351 {
15349 mindif = eabs (g->charpos - charpos); 15352 mindif = eabs (g->charpos - charpos);
15350 best_row = row; 15353 best_row = row;
15354 /* Exact match always wins. */
15355 if (mindif == 0)
15356 return best_row;
15351 } 15357 }
15352 } 15358 }
15353 } 15359 }
15354 } 15360 }
15355 else if (best_row) 15361 else if (best_row && !row->continued_p)
15356 return best_row; 15362 return best_row;
15357 ++row; 15363 ++row;
15358 } 15364 }
@@ -23411,13 +23417,7 @@ erase_phys_cursor (struct window *w)
23411 /* If the cursor is in the mouse face area, redisplay that when 23417 /* If the cursor is in the mouse face area, redisplay that when
23412 we clear the cursor. */ 23418 we clear the cursor. */
23413 if (! NILP (dpyinfo->mouse_face_window) 23419 if (! NILP (dpyinfo->mouse_face_window)
23414 && w == XWINDOW (dpyinfo->mouse_face_window) 23420 && coords_in_mouse_face_p (w, hpos, vpos)
23415 && (vpos > dpyinfo->mouse_face_beg_row
23416 || (vpos == dpyinfo->mouse_face_beg_row
23417 && hpos >= dpyinfo->mouse_face_beg_col))
23418 && (vpos < dpyinfo->mouse_face_end_row
23419 || (vpos == dpyinfo->mouse_face_end_row
23420 && hpos < dpyinfo->mouse_face_end_col))
23421 /* Don't redraw the cursor's spot in mouse face if it is at the 23421 /* Don't redraw the cursor's spot in mouse face if it is at the
23422 end of a line (on a newline). The cursor appears there, but 23422 end of a line (on a newline). The cursor appears there, but
23423 mouse highlighting does not. */ 23423 mouse highlighting does not. */
@@ -23640,8 +23640,30 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw)
23640 /* For all but the first row, the highlight starts at column 0. */ 23640 /* For all but the first row, the highlight starts at column 0. */
23641 if (row == first) 23641 if (row == first)
23642 { 23642 {
23643 start_hpos = dpyinfo->mouse_face_beg_col; 23643 /* R2L rows have BEG and END in reversed order, but the
23644 start_x = dpyinfo->mouse_face_beg_x; 23644 screen drawing geometry is always left to right. So
23645 we need to mirror the beginning and end of the
23646 highlighted area in R2L rows. */
23647 if (!row->reversed_p)
23648 {
23649 start_hpos = dpyinfo->mouse_face_beg_col;
23650 start_x = dpyinfo->mouse_face_beg_x;
23651 }
23652 else if (row == last)
23653 {
23654 start_hpos = dpyinfo->mouse_face_end_col;
23655 start_x = dpyinfo->mouse_face_end_x;
23656 }
23657 else
23658 {
23659 start_hpos = 0;
23660 start_x = 0;
23661 }
23662 }
23663 else if (row->reversed_p && row == last)
23664 {
23665 start_hpos = dpyinfo->mouse_face_end_col;
23666 start_x = dpyinfo->mouse_face_end_x;
23645 } 23667 }
23646 else 23668 else
23647 { 23669 {
@@ -23650,7 +23672,20 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw)
23650 } 23672 }
23651 23673
23652 if (row == last) 23674 if (row == last)
23653 end_hpos = dpyinfo->mouse_face_end_col; 23675 {
23676 if (!row->reversed_p)
23677 end_hpos = dpyinfo->mouse_face_end_col;
23678 else if (row == first)
23679 end_hpos = dpyinfo->mouse_face_beg_col;
23680 else
23681 {
23682 end_hpos = row->used[TEXT_AREA];
23683 if (draw == DRAW_NORMAL_TEXT)
23684 row->fill_line_p = 1; /* Clear to end of line */
23685 }
23686 }
23687 else if (row->reversed_p && row == first)
23688 end_hpos = dpyinfo->mouse_face_beg_col;
23654 else 23689 else
23655 { 23690 {
23656 end_hpos = row->used[TEXT_AREA]; 23691 end_hpos = row->used[TEXT_AREA];
@@ -23713,6 +23748,53 @@ clear_mouse_face (Display_Info *dpyinfo)
23713 return cleared; 23748 return cleared;
23714} 23749}
23715 23750
23751/* Return non-zero if the coordinates HPOS and VPOS on windows W are
23752 within the mouse face on that window. */
23753static int
23754coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
23755{
23756 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
23757
23758 /* Quickly resolve the easy cases. */
23759 if (!(WINDOWP (dpyinfo->mouse_face_window)
23760 && XWINDOW (dpyinfo->mouse_face_window) == w))
23761 return 0;
23762 if (vpos < dpyinfo->mouse_face_beg_row
23763 || vpos > dpyinfo->mouse_face_end_row)
23764 return 0;
23765 if (vpos > dpyinfo->mouse_face_beg_row
23766 && vpos < dpyinfo->mouse_face_end_row)
23767 return 1;
23768
23769 if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
23770 {
23771 if (dpyinfo->mouse_face_beg_row == dpyinfo->mouse_face_end_row)
23772 {
23773 if (dpyinfo->mouse_face_beg_col <= hpos && hpos < dpyinfo->mouse_face_end_col)
23774 return 1;
23775 }
23776 else if ((vpos == dpyinfo->mouse_face_beg_row
23777 && hpos >= dpyinfo->mouse_face_beg_col)
23778 || (vpos == dpyinfo->mouse_face_end_row
23779 && hpos < dpyinfo->mouse_face_end_col))
23780 return 1;
23781 }
23782 else
23783 {
23784 if (dpyinfo->mouse_face_beg_row == dpyinfo->mouse_face_end_row)
23785 {
23786 if (dpyinfo->mouse_face_end_col < hpos && hpos <= dpyinfo->mouse_face_beg_col)
23787 return 1;
23788 }
23789 else if ((vpos == dpyinfo->mouse_face_beg_row
23790 && hpos <= dpyinfo->mouse_face_beg_col)
23791 || (vpos == dpyinfo->mouse_face_end_row
23792 && hpos > dpyinfo->mouse_face_end_col))
23793 return 1;
23794 }
23795 return 0;
23796}
23797
23716 23798
23717/* EXPORT: 23799/* EXPORT:
23718 Non-zero if physical cursor of window W is within mouse face. */ 23800 Non-zero if physical cursor of window W is within mouse face. */
@@ -23720,31 +23802,134 @@ clear_mouse_face (Display_Info *dpyinfo)
23720int 23802int
23721cursor_in_mouse_face_p (struct window *w) 23803cursor_in_mouse_face_p (struct window *w)
23722{ 23804{
23723 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame)); 23805 return coords_in_mouse_face_p (w, w->phys_cursor.hpos, w->phys_cursor.vpos);
23724 int in_mouse_face = 0; 23806}
23725 23807
23726 if (WINDOWP (dpyinfo->mouse_face_window)
23727 && XWINDOW (dpyinfo->mouse_face_window) == w)
23728 {
23729 int hpos = w->phys_cursor.hpos;
23730 int vpos = w->phys_cursor.vpos;
23731 23808
23732 if (vpos >= dpyinfo->mouse_face_beg_row 23809
23733 && vpos <= dpyinfo->mouse_face_end_row 23810/* Find the glyph rows START_ROW and END_ROW of window W that display
23734 && (vpos > dpyinfo->mouse_face_beg_row 23811 characters between buffer positions START_CHARPOS and END_CHARPOS
23735 || hpos >= dpyinfo->mouse_face_beg_col) 23812 (excluding END_CHARPOS). This is similar to row_containing_pos,
23736 && (vpos < dpyinfo->mouse_face_end_row 23813 but is more accurate when bidi reordering makes buffer positions
23737 || hpos < dpyinfo->mouse_face_end_col 23814 change non-linearly with glyph rows. */
23738 || dpyinfo->mouse_face_past_end)) 23815static void
23739 in_mouse_face = 1; 23816rows_from_pos_range (struct window *w,
23740 } 23817 EMACS_INT start_charpos, EMACS_INT end_charpos,
23818 struct glyph_row **start, struct glyph_row **end)
23819{
23820 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
23821 int last_y = window_text_bottom_y (w);
23822 struct glyph_row *row;
23741 23823
23742 return in_mouse_face; 23824 *start = NULL;
23743} 23825 *end = NULL;
23826
23827 while (!first->enabled_p
23828 && first < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w))
23829 first++;
23830
23831 /* Find the START row. */
23832 for (row = first;
23833 row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y;
23834 row++)
23835 {
23836 /* A row can potentially be the START row if the range of the
23837 characters it displays intersects the range
23838 [START_CHARPOS..END_CHARPOS). */
23839 if (! ((start_charpos < MATRIX_ROW_START_CHARPOS (row)
23840 && end_charpos < MATRIX_ROW_START_CHARPOS (row))
23841 /* See the commentary in row_containing_pos, for the
23842 explanation of the complicated way to check whether
23843 some position is beyond the end of the characters
23844 displayed by a row. */
23845 || ((start_charpos > MATRIX_ROW_END_CHARPOS (row)
23846 || (start_charpos == MATRIX_ROW_END_CHARPOS (row)
23847 && !row->ends_at_zv_p
23848 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
23849 && (end_charpos > MATRIX_ROW_END_CHARPOS (row)
23850 || (end_charpos == MATRIX_ROW_END_CHARPOS (row)
23851 && !row->ends_at_zv_p
23852 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))))))
23853 {
23854 /* Found a candidate row. Now make sure at least one of the
23855 glyphs it displays has a charpos from the range
23856 [START_CHARPOS..END_CHARPOS).
23857
23858 This is not obvious because bidi reordering could make
23859 buffer positions of a row be 1,2,3,102,101,100, and if we
23860 want to highlight characters in [50..60), we don't want
23861 this row, even though [50..60) does intersect [1..103),
23862 the range of character positions given by the row's start
23863 and end positions. */
23864 struct glyph *g = row->glyphs[TEXT_AREA];
23865 struct glyph *e = g + row->used[TEXT_AREA];
23866
23867 while (g < e)
23868 {
23869 if (BUFFERP (g->object)
23870 && start_charpos <= g->charpos && g->charpos < end_charpos)
23871 *start = row;
23872 g++;
23873 }
23874 if (*start)
23875 break;
23876 }
23877 }
23744 23878
23879 /* Find the END row. */
23880 if (!*start
23881 /* If the last row is partially visible, start looking for END
23882 from that row, instead of starting from FIRST. */
23883 && !(row->enabled_p
23884 && row->y < last_y && MATRIX_ROW_BOTTOM_Y (row) > last_y))
23885 row = first;
23886 for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++)
23887 {
23888 struct glyph_row *next = row + 1;
23889
23890 if (!next->enabled_p
23891 || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)
23892 /* The first row >= START whose range of displayed characters
23893 does NOT intersect the range [START_CHARPOS..END_CHARPOS]
23894 is the row END + 1. */
23895 || (start_charpos < MATRIX_ROW_START_CHARPOS (next)
23896 && end_charpos < MATRIX_ROW_START_CHARPOS (next))
23897 || ((start_charpos > MATRIX_ROW_END_CHARPOS (next)
23898 || (start_charpos == MATRIX_ROW_END_CHARPOS (next)
23899 && !next->ends_at_zv_p
23900 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))
23901 && (end_charpos > MATRIX_ROW_END_CHARPOS (next)
23902 || (end_charpos == MATRIX_ROW_END_CHARPOS (next)
23903 && !next->ends_at_zv_p
23904 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))))
23905 {
23906 *end = row;
23907 break;
23908 }
23909 else
23910 {
23911 /* If the next row's edges intersect [START_CHARPOS..END_CHARPOS],
23912 but none of the characters it displays are in the range, it is
23913 also END + 1. */
23914 struct glyph *g = next->glyphs[TEXT_AREA];
23915 struct glyph *e = g + next->used[TEXT_AREA];
23745 23916
23917 while (g < e)
23918 {
23919 if (BUFFERP (g->object)
23920 && start_charpos <= g->charpos && g->charpos < end_charpos)
23921 break;
23922 g++;
23923 }
23924 if (g == e)
23925 {
23926 *end = row;
23927 break;
23928 }
23929 }
23930 }
23931}
23746 23932
23747
23748/* This function sets the mouse_face_* elements of DPYINFO, assuming 23933/* This function sets the mouse_face_* elements of DPYINFO, assuming
23749 the mouse cursor is on a glyph with buffer charpos MOUSE_CHARPOS in 23934 the mouse cursor is on a glyph with buffer charpos MOUSE_CHARPOS in
23750 window WINDOW. START_CHARPOS and END_CHARPOS are buffer positions 23935 window WINDOW. START_CHARPOS and END_CHARPOS are buffer positions
@@ -23766,158 +23951,300 @@ mouse_face_from_buffer_pos (Lisp_Object window,
23766{ 23951{
23767 struct window *w = XWINDOW (window); 23952 struct window *w = XWINDOW (window);
23768 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); 23953 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
23769 struct glyph_row *row; 23954 struct glyph_row *r1, *r2;
23770 struct glyph *glyph, *end; 23955 struct glyph *glyph, *end;
23771 EMACS_INT ignore; 23956 EMACS_INT ignore, pos;
23772 int x; 23957 int x;
23773 23958
23774 xassert (NILP (display_string) || STRINGP (display_string)); 23959 xassert (NILP (display_string) || STRINGP (display_string));
23775 xassert (NILP (before_string) || STRINGP (before_string)); 23960 xassert (NILP (before_string) || STRINGP (before_string));
23776 xassert (NILP (after_string) || STRINGP (after_string)); 23961 xassert (NILP (after_string) || STRINGP (after_string));
23777 23962
23778 /* Find the first highlighted glyph. */ 23963 /* Find the rows corresponding to START_CHARPOS and END_CHARPOS. */
23779 if (start_charpos < MATRIX_ROW_START_CHARPOS (first)) 23964 rows_from_pos_range (w, start_charpos, end_charpos, &r1, &r2);
23965 if (r1 == NULL)
23966 r1 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
23967 /* If the before-string or display-string contains newlines,
23968 rows_from_pos_range skips to its last row. Move back. */
23969 if (!NILP (before_string) || !NILP (display_string))
23970 {
23971 struct glyph_row *prev;
23972 while ((prev = r1 - 1, prev >= first)
23973 && MATRIX_ROW_END_CHARPOS (prev) == start_charpos
23974 && prev->used[TEXT_AREA] > 0)
23975 {
23976 struct glyph *beg = prev->glyphs[TEXT_AREA];
23977 glyph = beg + prev->used[TEXT_AREA];
23978 while (--glyph >= beg && INTEGERP (glyph->object));
23979 if (glyph < beg
23980 || !(EQ (glyph->object, before_string)
23981 || EQ (glyph->object, display_string)))
23982 break;
23983 r1 = prev;
23984 }
23985 }
23986 if (r2 == NULL)
23780 { 23987 {
23781 dpyinfo->mouse_face_beg_col = 0; 23988 r2 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
23782 dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (first, w->current_matrix); 23989 dpyinfo->mouse_face_past_end = 1;
23783 dpyinfo->mouse_face_beg_x = first->x;
23784 dpyinfo->mouse_face_beg_y = first->y;
23785 } 23990 }
23786 else 23991 else if (!NILP (after_string))
23787 { 23992 {
23788 row = row_containing_pos (w, start_charpos, first, NULL, 0); 23993 /* If the after-string has newlines, advance to its last row. */
23789 if (row == NULL) 23994 struct glyph_row *next;
23790 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); 23995 struct glyph_row *last
23791 23996 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
23792 /* If the before-string or display-string contains newlines,
23793 row_containing_pos skips to its last row. Move back. */
23794 if (!NILP (before_string) || !NILP (display_string))
23795 {
23796 struct glyph_row *prev;
23797 while ((prev = row - 1, prev >= first)
23798 && MATRIX_ROW_END_CHARPOS (prev) == start_charpos
23799 && prev->used[TEXT_AREA] > 0)
23800 {
23801 struct glyph *beg = prev->glyphs[TEXT_AREA];
23802 glyph = beg + prev->used[TEXT_AREA];
23803 while (--glyph >= beg && INTEGERP (glyph->object));
23804 if (glyph < beg
23805 || !(EQ (glyph->object, before_string)
23806 || EQ (glyph->object, display_string)))
23807 break;
23808 row = prev;
23809 }
23810 }
23811 23997
23812 glyph = row->glyphs[TEXT_AREA]; 23998 for (next = r2 + 1;
23813 end = glyph + row->used[TEXT_AREA]; 23999 next <= last
23814 x = row->x; 24000 && next->used[TEXT_AREA] > 0
23815 dpyinfo->mouse_face_beg_y = row->y; 24001 && EQ (next->glyphs[TEXT_AREA]->object, after_string);
23816 dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (row, w->current_matrix); 24002 ++next)
24003 r2 = next;
24004 }
24005 /* The rest of the display engine assumes that mouse_face_beg_row is
24006 either above below mouse_face_end_row or identical to it. But
24007 with bidi-reordered continued lines, the row for START_CHARPOS
24008 could be below the row for END_CHARPOS. If so, swap the rows and
24009 store them in correct order. */
24010 if (r1->y > r2->y)
24011 {
24012 struct glyph_row *tem = r2;
24013
24014 r2 = r1;
24015 r1 = tem;
24016 }
24017
24018 dpyinfo->mouse_face_beg_y = r1->y;
24019 dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
24020 dpyinfo->mouse_face_end_y = r2->y;
24021 dpyinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
24022
24023 /* For a bidi-reordered row, the positions of BEFORE_STRING,
24024 AFTER_STRING, DISPLAY_STRING, START_CHARPOS, and END_CHARPOS
24025 could be anywhere in the row and in any order. The strategy
24026 below is to find the leftmost and the rightmost glyph that
24027 belongs to either of these 3 strings, or whose position is
24028 between START_CHARPOS and END_CHARPOS, and highlight all the
24029 glyphs between those two. This may cover more than just the text
24030 between START_CHARPOS and END_CHARPOS if the range of characters
24031 strides the bidi level boundary, e.g. if the beginning is in R2L
24032 text while the end is in L2R text or vice versa. */
24033 if (!r1->reversed_p)
24034 {
24035 /* This row is in a left to right paragraph. Scan it left to
24036 right. */
24037 glyph = r1->glyphs[TEXT_AREA];
24038 end = glyph + r1->used[TEXT_AREA];
24039 x = r1->x;
23817 24040
23818 /* Skip truncation glyphs at the start of the glyph row. */ 24041 /* Skip truncation glyphs at the start of the glyph row. */
23819 if (row->displays_text_p) 24042 if (r1->displays_text_p)
23820 for (; glyph < end 24043 for (; glyph < end
23821 && INTEGERP (glyph->object) 24044 && INTEGERP (glyph->object)
23822 && glyph->charpos < 0; 24045 && glyph->charpos < 0;
23823 ++glyph) 24046 ++glyph)
23824 x += glyph->pixel_width; 24047 x += glyph->pixel_width;
23825 24048
23826 /* Scan the glyph row, stopping before BEFORE_STRING or 24049 /* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING,
23827 DISPLAY_STRING or START_CHARPOS. */ 24050 or DISPLAY_STRING, and the first glyph from buffer whose
24051 position is between START_CHARPOS and END_CHARPOS. */
23828 for (; glyph < end 24052 for (; glyph < end
23829 && !INTEGERP (glyph->object) 24053 && !INTEGERP (glyph->object)
23830 && !EQ (glyph->object, before_string)
23831 && !EQ (glyph->object, display_string) 24054 && !EQ (glyph->object, display_string)
23832 && !(BUFFERP (glyph->object) 24055 && !(BUFFERP (glyph->object)
23833 && glyph->charpos >= start_charpos); 24056 && (glyph->charpos >= start_charpos
24057 && glyph->charpos < end_charpos));
23834 ++glyph) 24058 ++glyph)
23835 x += glyph->pixel_width; 24059 {
23836 24060 /* BEFORE_STRING or AFTER_STRING are only relevant if they
24061 are present at buffer positions between START_CHARPOS and
24062 END_CHARPOS, or if they come from an overlay. */
24063 if (EQ (glyph->object, before_string))
24064 {
24065 pos = string_buffer_position (w, before_string,
24066 start_charpos);
24067 /* If pos == 0, it means before_string came from an
24068 overlay, not from a buffer position. */
24069 if (!pos || pos >= start_charpos && pos < end_charpos)
24070 break;
24071 }
24072 else if (EQ (glyph->object, after_string))
24073 {
24074 pos = string_buffer_position (w, after_string, end_charpos);
24075 if (!pos || pos >= start_charpos && pos < end_charpos)
24076 break;
24077 }
24078 x += glyph->pixel_width;
24079 }
23837 dpyinfo->mouse_face_beg_x = x; 24080 dpyinfo->mouse_face_beg_x = x;
23838 dpyinfo->mouse_face_beg_col = glyph - row->glyphs[TEXT_AREA]; 24081 dpyinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
23839 } 24082 }
23840 24083 else
23841 /* Find the last highlighted glyph. */
23842 row = row_containing_pos (w, end_charpos, first, NULL, 0);
23843 if (row == NULL)
23844 {
23845 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
23846 dpyinfo->mouse_face_past_end = 1;
23847 }
23848 else if (!NILP (after_string))
23849 { 24084 {
23850 /* If the after-string has newlines, advance to its last row. */ 24085 /* This row is in a right to left paragraph. Scan it right to
23851 struct glyph_row *next; 24086 left. */
23852 struct glyph_row *last 24087 struct glyph *g;
23853 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
23854 24088
23855 for (next = row + 1; 24089 end = r1->glyphs[TEXT_AREA] - 1;
23856 next <= last 24090 glyph = end + r1->used[TEXT_AREA];
23857 && next->used[TEXT_AREA] > 0
23858 && EQ (next->glyphs[TEXT_AREA]->object, after_string);
23859 ++next)
23860 row = next;
23861 }
23862 24091
23863 glyph = row->glyphs[TEXT_AREA]; 24092 /* Skip truncation glyphs at the start of the glyph row. */
23864 end = glyph + row->used[TEXT_AREA]; 24093 if (r1->displays_text_p)
23865 x = row->x; 24094 for (; glyph > end
23866 dpyinfo->mouse_face_end_y = row->y; 24095 && INTEGERP (glyph->object)
23867 dpyinfo->mouse_face_end_row = MATRIX_ROW_VPOS (row, w->current_matrix); 24096 && glyph->charpos < 0;
24097 --glyph)
24098 ;
23868 24099
23869 /* Skip truncation glyphs at the start of the row. */ 24100 /* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING,
23870 if (row->displays_text_p) 24101 or DISPLAY_STRING, and the first glyph from buffer whose
23871 for (; glyph < end 24102 position is between START_CHARPOS and END_CHARPOS. */
23872 && INTEGERP (glyph->object) 24103 for (; glyph > end
23873 && glyph->charpos < 0; 24104 && !INTEGERP (glyph->object)
23874 ++glyph) 24105 && !EQ (glyph->object, display_string)
23875 x += glyph->pixel_width; 24106 && !(BUFFERP (glyph->object)
23876 24107 && (glyph->charpos >= start_charpos
23877 /* Scan the glyph row, stopping at END_CHARPOS or when we encounter 24108 && glyph->charpos < end_charpos));
23878 AFTER_STRING. */ 24109 --glyph)
23879 for (; glyph < end 24110 {
23880 && !INTEGERP (glyph->object) 24111 /* BEFORE_STRING or AFTER_STRING are only relevant if they
23881 && !EQ (glyph->object, after_string) 24112 are present at buffer positions between START_CHARPOS and
23882 && !(BUFFERP (glyph->object) && glyph->charpos >= end_charpos); 24113 END_CHARPOS, or if they come from an overlay. */
23883 ++glyph) 24114 if (EQ (glyph->object, before_string))
23884 x += glyph->pixel_width; 24115 {
24116 pos = string_buffer_position (w, before_string, start_charpos);
24117 /* If pos == 0, it means before_string came from an
24118 overlay, not from a buffer position. */
24119 if (!pos || pos >= start_charpos && pos < end_charpos)
24120 break;
24121 }
24122 else if (EQ (glyph->object, after_string))
24123 {
24124 pos = string_buffer_position (w, after_string, end_charpos);
24125 if (!pos || pos >= start_charpos && pos < end_charpos)
24126 break;
24127 }
24128 }
24129
24130 glyph++; /* first glyph to the right of the highlighted area */
24131 for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++)
24132 x += g->pixel_width;
24133 dpyinfo->mouse_face_beg_x = x;
24134 dpyinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
24135 }
23885 24136
23886 /* If we found AFTER_STRING, consume it and stop. */ 24137 /* If the highlight ends in a different row, compute GLYPH and END
23887 if (EQ (glyph->object, after_string)) 24138 for the end row. Otherwise, reuse the values computed above for
24139 the row where the highlight begins. */
24140 if (r2 != r1)
23888 { 24141 {
23889 for (; EQ (glyph->object, after_string) && glyph < end; ++glyph) 24142 if (!r2->reversed_p)
24143 {
24144 glyph = r2->glyphs[TEXT_AREA];
24145 end = glyph + r2->used[TEXT_AREA];
24146 x = r2->x;
24147 }
24148 else
24149 {
24150 end = r2->glyphs[TEXT_AREA] - 1;
24151 glyph = end + r2->used[TEXT_AREA];
24152 }
24153 }
24154
24155 if (!r2->reversed_p)
24156 {
24157 /* Skip truncation and continuation glyphs near the end of the
24158 row, and also blanks and stretch glyphs inserted by
24159 extend_face_to_end_of_line. */
24160 while (end > glyph
24161 && INTEGERP ((end - 1)->object)
24162 && (end - 1)->charpos <= 0)
24163 --end;
24164 /* Scan the rest of the glyph row from the end, looking for the
24165 first glyph that comes from BEFORE_STRING, AFTER_STRING, or
24166 DISPLAY_STRING, or whose position is between START_CHARPOS
24167 and END_CHARPOS */
24168 for (--end;
24169 end > glyph
24170 && !INTEGERP (end->object)
24171 && !EQ (end->object, display_string)
24172 && !(BUFFERP (end->object)
24173 && (end->charpos >= start_charpos
24174 && end->charpos < end_charpos));
24175 --end)
24176 {
24177 /* BEFORE_STRING or AFTER_STRING are only relevant if they
24178 are present at buffer positions between START_CHARPOS and
24179 END_CHARPOS, or if they come from an overlay. */
24180 if (EQ (end->object, before_string))
24181 {
24182 pos = string_buffer_position (w, before_string, start_charpos);
24183 if (!pos || pos >= start_charpos && pos < end_charpos)
24184 break;
24185 }
24186 else if (EQ (end->object, after_string))
24187 {
24188 pos = string_buffer_position (w, after_string, end_charpos);
24189 if (!pos || pos >= start_charpos && pos < end_charpos)
24190 break;
24191 }
24192 }
24193 /* Find the X coordinate of the last glyph to be highlighted. */
24194 for (; glyph <= end; ++glyph)
23890 x += glyph->pixel_width; 24195 x += glyph->pixel_width;
24196
24197 dpyinfo->mouse_face_end_x = x;
24198 dpyinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA];
23891 } 24199 }
23892 else 24200 else
23893 { 24201 {
23894 /* If there's no after-string, we must check if we overshot, 24202 /* Skip truncation and continuation glyphs near the end of the
23895 which might be the case if we stopped after a string glyph. 24203 row, and also blanks and stretch glyphs inserted by
23896 That glyph may belong to a before-string or display-string 24204 extend_face_to_end_of_line. */
23897 associated with the end position, which must not be 24205 x = r2->x;
23898 highlighted. */ 24206 end++;
23899 Lisp_Object prev_object; 24207 while (end < glyph
23900 EMACS_INT pos; 24208 && INTEGERP (end->object)
23901 24209 && end->charpos <= 0)
23902 while (glyph > row->glyphs[TEXT_AREA]) 24210 {
23903 { 24211 x += end->pixel_width;
23904 prev_object = (glyph - 1)->object; 24212 ++end;
23905 if (!STRINGP (prev_object) || EQ (prev_object, display_string)) 24213 }
23906 break; 24214 /* Scan the rest of the glyph row from the end, looking for the
23907 24215 first glyph that comes from BEFORE_STRING, AFTER_STRING, or
23908 pos = string_buffer_position (w, prev_object, end_charpos); 24216 DISPLAY_STRING, or whose position is between START_CHARPOS
23909 if (pos && pos < end_charpos) 24217 and END_CHARPOS */
23910 break; 24218 for ( ;
23911 24219 end < glyph
23912 for (; glyph > row->glyphs[TEXT_AREA] 24220 && !INTEGERP (end->object)
23913 && EQ ((glyph - 1)->object, prev_object); 24221 && !EQ (end->object, display_string)
23914 --glyph) 24222 && !(BUFFERP (end->object)
23915 x -= (glyph - 1)->pixel_width; 24223 && (end->charpos >= start_charpos
24224 && end->charpos < end_charpos));
24225 ++end)
24226 {
24227 /* BEFORE_STRING or AFTER_STRING are only relevant if they
24228 are present at buffer positions between START_CHARPOS and
24229 END_CHARPOS, or if they come from an overlay. */
24230 if (EQ (end->object, before_string))
24231 {
24232 pos = string_buffer_position (w, before_string, start_charpos);
24233 if (!pos || pos >= start_charpos && pos < end_charpos)
24234 break;
24235 }
24236 else if (EQ (end->object, after_string))
24237 {
24238 pos = string_buffer_position (w, after_string, end_charpos);
24239 if (!pos || pos >= start_charpos && pos < end_charpos)
24240 break;
24241 }
24242 x += end->pixel_width;
23916 } 24243 }
24244 dpyinfo->mouse_face_end_x = x;
24245 dpyinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
23917 } 24246 }
23918 24247
23919 dpyinfo->mouse_face_end_x = x;
23920 dpyinfo->mouse_face_end_col = glyph - row->glyphs[TEXT_AREA];
23921 dpyinfo->mouse_face_window = window; 24248 dpyinfo->mouse_face_window = window;
23922 dpyinfo->mouse_face_face_id 24249 dpyinfo->mouse_face_face_id
23923 = face_at_buffer_position (w, mouse_charpos, 0, 0, &ignore, 24250 = face_at_buffer_position (w, mouse_charpos, 0, 0, &ignore,
@@ -23926,6 +24253,11 @@ mouse_face_from_buffer_pos (Lisp_Object window,
23926 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); 24253 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
23927} 24254}
23928 24255
24256/* The following function is not used anymore (replaced with
24257 mouse_face_from_string_pos), but I leave it here for the time
24258 being, in case someone would. */
24259
24260#if 0 /* not used */
23929 24261
23930/* Find the position of the glyph for position POS in OBJECT in 24262/* Find the position of the glyph for position POS in OBJECT in
23931 window W's current matrix, and return in *X, *Y the pixel 24263 window W's current matrix, and return in *X, *Y the pixel
@@ -24003,7 +24335,130 @@ fast_find_string_pos (struct window *w, EMACS_INT pos, Lisp_Object object,
24003 24335
24004 return best_glyph != NULL; 24336 return best_glyph != NULL;
24005} 24337}
24338#endif /* not used */
24339
24340/* Find the positions of the first and the last glyphs in window W's
24341 current matrix that occlude positions [STARTPOS..ENDPOS] in OBJECT
24342 (assumed to be a string), and return in DPYINFO's mouse_face
24343 members the pixel and column/row coordinates of those glyphs. */
24344
24345static void
24346mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo,
24347 Lisp_Object object,
24348 EMACS_INT startpos, EMACS_INT endpos)
24349{
24350 int yb = window_text_bottom_y (w);
24351 struct glyph_row *r;
24352 struct glyph *g, *e;
24353 int gx;
24354 int found = 0;
24355
24356 /* Find the glyph row with at least one position in the range
24357 [STARTPOS..ENDPOS], and the first glyph in that row whose
24358 position belongs to that range. */
24359 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
24360 r->enabled_p && r->y < yb;
24361 ++r)
24362 {
24363 if (!r->reversed_p)
24364 {
24365 g = r->glyphs[TEXT_AREA];
24366 e = g + r->used[TEXT_AREA];
24367 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
24368 if (EQ (g->object, object)
24369 && startpos <= g->charpos && g->charpos <= endpos)
24370 {
24371 dpyinfo->mouse_face_beg_row = r - w->current_matrix->rows;
24372 dpyinfo->mouse_face_beg_y = r->y;
24373 dpyinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
24374 dpyinfo->mouse_face_beg_x = gx;
24375 found = 1;
24376 break;
24377 }
24378 }
24379 else
24380 {
24381 struct glyph *g1;
24382
24383 e = r->glyphs[TEXT_AREA];
24384 g = e + r->used[TEXT_AREA];
24385 for ( ; g > e; --g)
24386 if (EQ ((g-1)->object, object)
24387 && startpos <= (g-1)->charpos && (g-1)->charpos <= endpos)
24388 {
24389 dpyinfo->mouse_face_beg_row = r - w->current_matrix->rows;
24390 dpyinfo->mouse_face_beg_y = r->y;
24391 dpyinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
24392 for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
24393 gx += g1->pixel_width;
24394 dpyinfo->mouse_face_beg_x = gx;
24395 found = 1;
24396 break;
24397 }
24398 }
24399 if (found)
24400 break;
24401 }
24402
24403 if (!found)
24404 return;
24006 24405
24406 /* Starting with the next row, look for the first row which does NOT
24407 include any glyphs whose positions are in the range. */
24408 for (++r; r->enabled_p && r->y < yb; ++r)
24409 {
24410 g = r->glyphs[TEXT_AREA];
24411 e = g + r->used[TEXT_AREA];
24412 found = 0;
24413 for ( ; g < e; ++g)
24414 if (EQ (g->object, object)
24415 && startpos <= g->charpos && g->charpos <= endpos)
24416 {
24417 found = 1;
24418 break;
24419 }
24420 if (!found)
24421 break;
24422 }
24423
24424 /* The highlighted region ends on the previous row. */
24425 r--;
24426
24427 /* Set the end row and its vertical pixel coordinate. */
24428 dpyinfo->mouse_face_end_row = r - w->current_matrix->rows;
24429 dpyinfo->mouse_face_end_y = r->y;
24430
24431 /* Compute and set the end column and the end column's horizontal
24432 pixel coordinate. */
24433 if (!r->reversed_p)
24434 {
24435 g = r->glyphs[TEXT_AREA];
24436 e = g + r->used[TEXT_AREA];
24437 for ( ; e > g; --e)
24438 if (EQ ((e-1)->object, object)
24439 && startpos <= (e-1)->charpos && (e-1)->charpos <= endpos)
24440 break;
24441 dpyinfo->mouse_face_end_col = e - g;
24442
24443 for (gx = r->x; g < e; ++g)
24444 gx += g->pixel_width;
24445 dpyinfo->mouse_face_end_x = gx;
24446 }
24447 else
24448 {
24449 e = r->glyphs[TEXT_AREA];
24450 g = e + r->used[TEXT_AREA];
24451 for (gx = r->x ; e < g; ++e)
24452 {
24453 if (EQ (e->object, object)
24454 && startpos <= e->charpos && e->charpos <= endpos)
24455 break;
24456 gx += e->pixel_width;
24457 }
24458 dpyinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA];
24459 dpyinfo->mouse_face_end_x = gx;
24460 }
24461}
24007 24462
24008/* See if position X, Y is within a hot-spot of an image. */ 24463/* See if position X, Y is within a hot-spot of an image. */
24009 24464
@@ -24205,6 +24660,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
24205 int x0; 24660 int x0;
24206 struct glyph *end; 24661 struct glyph *end;
24207 24662
24663 /* Kludge alert: mode_line_string takes X/Y in pixels, but
24664 returns them in row/column units! */
24208 string = mode_line_string (w, area, &x, &y, &charpos, 24665 string = mode_line_string (w, area, &x, &y, &charpos,
24209 &object, &dx, &dy, &width, &height); 24666 &object, &dx, &dy, &width, &height);
24210 24667
@@ -24212,7 +24669,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
24212 ? MATRIX_MODE_LINE_ROW (w->current_matrix) 24669 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
24213 : MATRIX_HEADER_LINE_ROW (w->current_matrix)); 24670 : MATRIX_HEADER_LINE_ROW (w->current_matrix));
24214 24671
24215 /* Find glyph */ 24672 /* Find the glyph under the mouse pointer. */
24216 if (row->mode_line_p && row->enabled_p) 24673 if (row->mode_line_p && row->enabled_p)
24217 { 24674 {
24218 glyph = row_start_glyph = row->glyphs[TEXT_AREA]; 24675 glyph = row_start_glyph = row->glyphs[TEXT_AREA];
@@ -24230,6 +24687,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
24230 else 24687 else
24231 { 24688 {
24232 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w); 24689 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
24690 /* Kludge alert: marginal_area_string takes X/Y in pixels, but
24691 returns them in row/column units! */
24233 string = marginal_area_string (w, area, &x, &y, &charpos, 24692 string = marginal_area_string (w, area, &x, &y, &charpos,
24234 &object, &dx, &dy, &width, &height); 24693 &object, &dx, &dy, &width, &height);
24235 } 24694 }
@@ -24318,93 +24777,116 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
24318 int gpos; 24777 int gpos;
24319 int gseq_length; 24778 int gseq_length;
24320 int total_pixel_width; 24779 int total_pixel_width;
24321 EMACS_INT ignore; 24780 EMACS_INT begpos, endpos, ignore;
24322 24781
24323 int vpos, hpos; 24782 int vpos, hpos;
24324 24783
24325 b = Fprevious_single_property_change (make_number (charpos + 1), 24784 b = Fprevious_single_property_change (make_number (charpos + 1),
24326 Qmouse_face, string, Qnil); 24785 Qmouse_face, string, Qnil);
24327 if (NILP (b)) 24786 if (NILP (b))
24328 b = make_number (0); 24787 begpos = 0;
24788 else
24789 begpos = XINT (b);
24329 24790
24330 e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil); 24791 e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil);
24331 if (NILP (e)) 24792 if (NILP (e))
24332 e = make_number (SCHARS (string)); 24793 endpos = SCHARS (string);
24333 24794 else
24334 /* Calculate the position(glyph position: GPOS) of GLYPH in 24795 endpos = XINT (e);
24335 displayed string. GPOS is different from CHARPOS. 24796
24336 24797 /* Calculate the glyph position GPOS of GLYPH in the
24337 CHARPOS is the position of glyph in internal string 24798 displayed string, relative to the beginning of the
24338 object. A mode line string format has structures which 24799 highlighted part of the string.
24339 is converted to a flatten by emacs lisp interpreter. 24800
24340 The internal string is an element of the structures. 24801 Note: GPOS is different from CHARPOS. CHARPOS is the
24341 The displayed string is the flatten string. */ 24802 position of GLYPH in the internal string object. A mode
24342 gpos = 0; 24803 line string format has structures which are converted to
24343 if (glyph > row_start_glyph) 24804 a flattened string by the Emacs Lisp interpreter. The
24344 { 24805 internal string is an element of those structures. The
24345 tmp_glyph = glyph - 1; 24806 displayed string is the flattened string. */
24346 while (tmp_glyph >= row_start_glyph 24807 tmp_glyph = row_start_glyph;
24347 && tmp_glyph->charpos >= XINT (b) 24808 while (tmp_glyph < glyph
24348 && EQ (tmp_glyph->object, glyph->object)) 24809 && (!(EQ (tmp_glyph->object, glyph->object)
24349 { 24810 && begpos <= tmp_glyph->charpos
24350 tmp_glyph--; 24811 && tmp_glyph->charpos < endpos)))
24351 gpos++; 24812 tmp_glyph++;
24352 } 24813 gpos = glyph - tmp_glyph;
24353 } 24814
24354 24815 /* Calculate the length GSEQ_LENGTH of the glyph sequence of
24355 /* Calculate the lenght(glyph sequence length: GSEQ_LENGTH) of 24816 the highlighted part of the displayed string to which
24356 displayed string holding GLYPH. 24817 GLYPH belongs. Note: GSEQ_LENGTH is different from
24357 24818 SCHARS (STRING), because the latter returns the length of
24358 GSEQ_LENGTH is different from SCHARS (STRING). 24819 the internal string. */
24359 SCHARS (STRING) returns the length of the internal string. */ 24820 for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
24360 for (tmp_glyph = glyph, gseq_length = gpos; 24821 tmp_glyph > glyph
24361 tmp_glyph->charpos < XINT (e); 24822 && (!(EQ (tmp_glyph->object, glyph->object)
24362 tmp_glyph++, gseq_length++) 24823 && begpos <= tmp_glyph->charpos
24363 { 24824 && tmp_glyph->charpos < endpos));
24364 if (!EQ (tmp_glyph->object, glyph->object)) 24825 tmp_glyph--)
24365 break; 24826 ;
24366 } 24827 gseq_length = gpos + (tmp_glyph - glyph) + 1;
24367 24828
24829 /* Calculate the total pixel width of all the glyphs between
24830 the beginning of the highlighted area and GLYPH. */
24368 total_pixel_width = 0; 24831 total_pixel_width = 0;
24369 for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++) 24832 for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++)
24370 total_pixel_width += tmp_glyph->pixel_width; 24833 total_pixel_width += tmp_glyph->pixel_width;
24371 24834
24372 /* Pre calculation of re-rendering position */ 24835 /* Pre calculation of re-rendering position. Note: X is in
24373 vpos = (x - gpos); 24836 column units here, after the call to mode_line_string or
24374 hpos = (area == ON_MODE_LINE 24837 marginal_area_string. */
24838 hpos = x - gpos;
24839 vpos = (area == ON_MODE_LINE
24375 ? (w->current_matrix)->nrows - 1 24840 ? (w->current_matrix)->nrows - 1
24376 : 0); 24841 : 0);
24377 24842
24378 /* If the re-rendering position is included in the last 24843 /* If GLYPH's position is included in the region that is
24379 re-rendering area, we should do nothing. */ 24844 already drawn in mouse face, we have nothing to do. */
24380 if ( EQ (window, dpyinfo->mouse_face_window) 24845 if ( EQ (window, dpyinfo->mouse_face_window)
24381 && dpyinfo->mouse_face_beg_col <= vpos 24846 && (!row->reversed_p
24382 && vpos < dpyinfo->mouse_face_end_col 24847 ? (dpyinfo->mouse_face_beg_col <= hpos
24383 && dpyinfo->mouse_face_beg_row == hpos ) 24848 && hpos < dpyinfo->mouse_face_end_col)
24849 /* In R2L rows we swap BEG and END, see below. */
24850 : (dpyinfo->mouse_face_end_col <= hpos
24851 && hpos < dpyinfo->mouse_face_beg_col))
24852 && dpyinfo->mouse_face_beg_row == vpos )
24384 return; 24853 return;
24385 24854
24386 if (clear_mouse_face (dpyinfo)) 24855 if (clear_mouse_face (dpyinfo))
24387 cursor = No_Cursor; 24856 cursor = No_Cursor;
24388 24857
24389 dpyinfo->mouse_face_beg_col = vpos; 24858 if (!row->reversed_p)
24390 dpyinfo->mouse_face_beg_row = hpos; 24859 {
24391 24860 dpyinfo->mouse_face_beg_col = hpos;
24392 dpyinfo->mouse_face_beg_x = original_x_pixel - (total_pixel_width + dx); 24861 dpyinfo->mouse_face_beg_x = original_x_pixel
24393 dpyinfo->mouse_face_beg_y = 0; 24862 - (total_pixel_width + dx);
24394 24863 dpyinfo->mouse_face_end_col = hpos + gseq_length;
24395 dpyinfo->mouse_face_end_col = vpos + gseq_length; 24864 dpyinfo->mouse_face_end_x = 0;
24396 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_beg_row; 24865 }
24397 24866 else
24398 dpyinfo->mouse_face_end_x = 0; 24867 {
24399 dpyinfo->mouse_face_end_y = 0; 24868 /* In R2L rows, show_mouse_face expects BEG and END
24869 coordinates to be swapped. */
24870 dpyinfo->mouse_face_end_col = hpos;
24871 dpyinfo->mouse_face_end_x = original_x_pixel
24872 - (total_pixel_width + dx);
24873 dpyinfo->mouse_face_beg_col = hpos + gseq_length;
24874 dpyinfo->mouse_face_beg_x = 0;
24875 }
24400 24876
24877 dpyinfo->mouse_face_beg_row = vpos;
24878 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_beg_row;
24879 dpyinfo->mouse_face_beg_y = 0;
24880 dpyinfo->mouse_face_end_y = 0;
24401 dpyinfo->mouse_face_past_end = 0; 24881 dpyinfo->mouse_face_past_end = 0;
24402 dpyinfo->mouse_face_window = window; 24882 dpyinfo->mouse_face_window = window;
24403 24883
24404 dpyinfo->mouse_face_face_id = face_at_string_position (w, string, 24884 dpyinfo->mouse_face_face_id = face_at_string_position (w, string,
24405 charpos, 24885 charpos,
24406 0, 0, 0, &ignore, 24886 0, 0, 0,
24407 glyph->face_id, 1); 24887 &ignore,
24888 glyph->face_id,
24889 1);
24408 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); 24890 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
24409 24891
24410 if (NILP (pointer)) 24892 if (NILP (pointer))
@@ -24573,7 +25055,15 @@ note_mouse_highlight (struct frame *f, int x, int y)
24573 /* Clear mouse face if X/Y not over text. */ 25055 /* Clear mouse face if X/Y not over text. */
24574 if (glyph == NULL 25056 if (glyph == NULL
24575 || area != TEXT_AREA 25057 || area != TEXT_AREA
24576 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p) 25058 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p
25059 /* R2L rows have a stretch glyph at their front, which
25060 stands for no text, whereas L2R rows have no glyphs at
25061 all beyond the end of text. Treat such stretch glyphs
25062 like we do with NULL glyphs in L2R rows. */
25063 || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p
25064 && glyph == MATRIX_ROW (w->current_matrix, vpos)->glyphs[TEXT_AREA]
25065 && glyph->type == STRETCH_GLYPH
25066 && glyph->avoid_cursor_p))
24577 { 25067 {
24578 if (clear_mouse_face (dpyinfo)) 25068 if (clear_mouse_face (dpyinfo))
24579 cursor = No_Cursor; 25069 cursor = No_Cursor;
@@ -24618,14 +25108,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
24618 else 25108 else
24619 noverlays = 0; 25109 noverlays = 0;
24620 25110
24621 same_region = (EQ (window, dpyinfo->mouse_face_window) 25111 same_region = coords_in_mouse_face_p (w, hpos, vpos);
24622 && vpos >= dpyinfo->mouse_face_beg_row
24623 && vpos <= dpyinfo->mouse_face_end_row
24624 && (vpos > dpyinfo->mouse_face_beg_row
24625 || hpos >= dpyinfo->mouse_face_beg_col)
24626 && (vpos < dpyinfo->mouse_face_end_row
24627 || hpos < dpyinfo->mouse_face_end_col
24628 || dpyinfo->mouse_face_past_end));
24629 25112
24630 if (same_region) 25113 if (same_region)
24631 cursor = No_Cursor; 25114 cursor = No_Cursor;
@@ -24679,17 +25162,8 @@ note_mouse_highlight (struct frame *f, int x, int y)
24679 b = make_number (0); 25162 b = make_number (0);
24680 if (NILP (e)) 25163 if (NILP (e))
24681 e = make_number (SCHARS (object) - 1); 25164 e = make_number (SCHARS (object) - 1);
24682 25165 mouse_face_from_string_pos (w, dpyinfo, object,
24683 fast_find_string_pos (w, XINT (b), object, 25166 XINT (b), XINT (e));
24684 &dpyinfo->mouse_face_beg_col,
24685 &dpyinfo->mouse_face_beg_row,
24686 &dpyinfo->mouse_face_beg_x,
24687 &dpyinfo->mouse_face_beg_y, 0);
24688 fast_find_string_pos (w, XINT (e), object,
24689 &dpyinfo->mouse_face_end_col,
24690 &dpyinfo->mouse_face_end_row,
24691 &dpyinfo->mouse_face_end_x,
24692 &dpyinfo->mouse_face_end_y, 1);
24693 dpyinfo->mouse_face_past_end = 0; 25167 dpyinfo->mouse_face_past_end = 0;
24694 dpyinfo->mouse_face_window = window; 25168 dpyinfo->mouse_face_window = window;
24695 dpyinfo->mouse_face_face_id 25169 dpyinfo->mouse_face_face_id
@@ -24729,17 +25203,33 @@ note_mouse_highlight (struct frame *f, int x, int y)
24729 { 25203 {
24730 Lisp_Object before, after; 25204 Lisp_Object before, after;
24731 Lisp_Object before_string, after_string; 25205 Lisp_Object before_string, after_string;
25206 /* To correctly find the limits of mouse highlight
25207 in a bidi-reordered buffer, we must not use the
25208 optimization of limiting the search in
25209 previous-single-property-change and
25210 next-single-property-change, because
25211 rows_from_pos_range needs the real start and end
25212 positions to DTRT in this case. That's because
25213 the first row visible in a window does not
25214 necessarily display the character whose position
25215 is the smallest. */
25216 Lisp_Object lim1 =
25217 NILP (XBUFFER (buffer)->bidi_display_reordering)
25218 ? Fmarker_position (w->start)
25219 : Qnil;
25220 Lisp_Object lim2 =
25221 NILP (XBUFFER (buffer)->bidi_display_reordering)
25222 ? make_number (BUF_Z (XBUFFER (buffer))
25223 - XFASTINT (w->window_end_pos))
25224 : Qnil;
24732 25225
24733 if (NILP (overlay)) 25226 if (NILP (overlay))
24734 { 25227 {
24735 /* Handle the text property case. */ 25228 /* Handle the text property case. */
24736 before = Fprevious_single_property_change 25229 before = Fprevious_single_property_change
24737 (make_number (pos + 1), Qmouse_face, buffer, 25230 (make_number (pos + 1), Qmouse_face, buffer, lim1);
24738 Fmarker_position (w->start));
24739 after = Fnext_single_property_change 25231 after = Fnext_single_property_change
24740 (make_number (pos), Qmouse_face, buffer, 25232 (make_number (pos), Qmouse_face, buffer, lim2);
24741 make_number (BUF_Z (XBUFFER (buffer))
24742 - XFASTINT (w->window_end_pos)));
24743 before_string = after_string = Qnil; 25233 before_string = after_string = Qnil;
24744 } 25234 }
24745 else 25235 else