diff options
| author | Eli Zaretskii | 2010-10-02 17:05:20 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2010-10-02 17:05:20 +0200 |
| commit | 1f382a02c1ca5043c2b2cbaca314578da98af24c (patch) | |
| tree | 6f7e5ab36a11fddebd3596691bdec7dfd64f5036 | |
| parent | 12d54c2e095dee28d8829c93d14ae18f92f474fb (diff) | |
| download | emacs-1f382a02c1ca5043c2b2cbaca314578da98af24c.tar.gz emacs-1f382a02c1ca5043c2b2cbaca314578da98af24c.zip | |
Fix mouse highlight in bidi-reordered continued lines.
xdisp.c (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.
(mouse_face_from_buffer_pos): Rewrite to not 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.
Continued lines that begin or end outside of the visible region
still don't work.
| -rw-r--r-- | src/ChangeLog | 8 | ||||
| -rw-r--r-- | src/xdisp.c | 328 |
2 files changed, 175 insertions, 161 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 2b77f081f52..61afecff203 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -5,6 +5,14 @@ | |||
| 5 | (note_mouse_highlight): Clear mouse highlight when mouse pointer | 5 | (note_mouse_highlight): Clear mouse highlight when mouse pointer |
| 6 | is in a R2L row on the stretch glyph that stands for no text | 6 | is in a R2L row on the stretch glyph that stands for no text |
| 7 | beyond the line end. | 7 | beyond the line end. |
| 8 | (row_containing_pos): Don't return too early when CHARPOS is in a | ||
| 9 | bidi-reordered continued line. Return immediately when the first | ||
| 10 | hit is found in a line that is not continued, or when an exact | ||
| 11 | match for CHARPOS is found. | ||
| 12 | (mouse_face_from_buffer_pos): Rewrite to not assume that | ||
| 13 | START_CHARPOS is always in mouse_face_beg_row. If necessary, swap | ||
| 14 | mouse_face_beg_row and mouse_face_end_row so that the former is | ||
| 15 | always above the latter or identical to it. | ||
| 8 | 16 | ||
| 9 | 2010-08-28 Eli Zaretskii <eliz@gnu.org> | 17 | 2010-08-28 Eli Zaretskii <eliz@gnu.org> |
| 10 | 18 | ||
diff --git a/src/xdisp.c b/src/xdisp.c index e19c26cbc19..9e65d8f1bb0 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -15329,10 +15329,12 @@ row_containing_pos (struct window *w, int charpos, struct glyph_row *start, | |||
| 15329 | { | 15329 | { |
| 15330 | struct glyph *g; | 15330 | struct glyph *g; |
| 15331 | 15331 | ||
| 15332 | if (NILP (XBUFFER (w->buffer)->bidi_display_reordering)) | 15332 | if (NILP (XBUFFER (w->buffer)->bidi_display_reordering) |
| 15333 | || (!best_row && !row->continued_p)) | ||
| 15333 | return row; | 15334 | return row; |
| 15334 | /* In bidi-reordered rows, there could be several rows | 15335 | /* In bidi-reordered rows, there could be several rows |
| 15335 | occluding point. We need to find the one which fits | 15336 | occluding point, all of them belonging to the same |
| 15337 | continued line. We need to find the row which fits | ||
| 15336 | CHARPOS the best. */ | 15338 | CHARPOS the best. */ |
| 15337 | for (g = row->glyphs[TEXT_AREA]; | 15339 | for (g = row->glyphs[TEXT_AREA]; |
| 15338 | g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | 15340 | g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; |
| @@ -15344,11 +15346,14 @@ row_containing_pos (struct window *w, int charpos, struct glyph_row *start, | |||
| 15344 | { | 15346 | { |
| 15345 | mindif = eabs (g->charpos - charpos); | 15347 | mindif = eabs (g->charpos - charpos); |
| 15346 | best_row = row; | 15348 | best_row = row; |
| 15349 | /* Exact match always wins. */ | ||
| 15350 | if (mindif == 0) | ||
| 15351 | return best_row; | ||
| 15347 | } | 15352 | } |
| 15348 | } | 15353 | } |
| 15349 | } | 15354 | } |
| 15350 | } | 15355 | } |
| 15351 | else if (best_row) | 15356 | else if (best_row && !row->continued_p) |
| 15352 | return best_row; | 15357 | return best_row; |
| 15353 | ++row; | 15358 | ++row; |
| 15354 | } | 15359 | } |
| @@ -23894,7 +23899,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, | |||
| 23894 | { | 23899 | { |
| 23895 | struct window *w = XWINDOW (window); | 23900 | struct window *w = XWINDOW (window); |
| 23896 | struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | 23901 | struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); |
| 23897 | struct glyph_row *row, *r; | 23902 | struct glyph_row *r1, *r2; |
| 23898 | struct glyph *glyph, *end; | 23903 | struct glyph *glyph, *end; |
| 23899 | EMACS_INT ignore, pos; | 23904 | EMACS_INT ignore, pos; |
| 23900 | int x; | 23905 | int x; |
| @@ -23903,7 +23908,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, | |||
| 23903 | xassert (NILP (before_string) || STRINGP (before_string)); | 23908 | xassert (NILP (before_string) || STRINGP (before_string)); |
| 23904 | xassert (NILP (after_string) || STRINGP (after_string)); | 23909 | xassert (NILP (after_string) || STRINGP (after_string)); |
| 23905 | 23910 | ||
| 23906 | /* Find the first highlighted glyph. */ | 23911 | /* Find the row with START_CHARPOS. */ |
| 23907 | if (start_charpos < MATRIX_ROW_START_CHARPOS (first) | 23912 | if (start_charpos < MATRIX_ROW_START_CHARPOS (first) |
| 23908 | && (NILP (XBUFFER (w->buffer)->bidi_display_reordering) | 23913 | && (NILP (XBUFFER (w->buffer)->bidi_display_reordering) |
| 23909 | || row_containing_pos (w, start_charpos, first, NULL, 0) == NULL)) | 23914 | || row_containing_pos (w, start_charpos, first, NULL, 0) == NULL)) |
| @@ -23915,20 +23920,16 @@ mouse_face_from_buffer_pos (Lisp_Object window, | |||
| 23915 | } | 23920 | } |
| 23916 | else | 23921 | else |
| 23917 | { | 23922 | { |
| 23918 | /* FIXME: this assumes that START_CHARPOS is in beg_row. This | 23923 | r1 = row_containing_pos (w, start_charpos, first, NULL, 0); |
| 23919 | is false for reordered lines that are continued. Need to | 23924 | if (r1 == NULL) |
| 23920 | compute beg_row and end_row separately from beg_col and | 23925 | r1 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); |
| 23921 | end_col. */ | ||
| 23922 | row = row_containing_pos (w, start_charpos, first, NULL, 0); | ||
| 23923 | if (row == NULL) | ||
| 23924 | row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); | ||
| 23925 | 23926 | ||
| 23926 | /* If the before-string or display-string contains newlines, | 23927 | /* If the before-string or display-string contains newlines, |
| 23927 | row_containing_pos skips to its last row. Move back. */ | 23928 | row_containing_pos skips to its last row. Move back. */ |
| 23928 | if (!NILP (before_string) || !NILP (display_string)) | 23929 | if (!NILP (before_string) || !NILP (display_string)) |
| 23929 | { | 23930 | { |
| 23930 | struct glyph_row *prev; | 23931 | struct glyph_row *prev; |
| 23931 | while ((prev = row - 1, prev >= first) | 23932 | while ((prev = r1 - 1, prev >= first) |
| 23932 | && MATRIX_ROW_END_CHARPOS (prev) == start_charpos | 23933 | && MATRIX_ROW_END_CHARPOS (prev) == start_charpos |
| 23933 | && prev->used[TEXT_AREA] > 0) | 23934 | && prev->used[TEXT_AREA] > 0) |
| 23934 | { | 23935 | { |
| @@ -23939,139 +23940,16 @@ mouse_face_from_buffer_pos (Lisp_Object window, | |||
| 23939 | || !(EQ (glyph->object, before_string) | 23940 | || !(EQ (glyph->object, before_string) |
| 23940 | || EQ (glyph->object, display_string))) | 23941 | || EQ (glyph->object, display_string))) |
| 23941 | break; | 23942 | break; |
| 23942 | row = prev; | 23943 | r1 = prev; |
| 23943 | } | 23944 | } |
| 23944 | } | 23945 | } |
| 23945 | |||
| 23946 | dpyinfo->mouse_face_beg_y = row->y; | ||
| 23947 | dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (row, w->current_matrix); | ||
| 23948 | |||
| 23949 | /* For a bidi-reordered row, the positions of BEFORE_STRING, | ||
| 23950 | AFTER_STRING, DISPLAY_STRING, START_CHARPOS, and END_CHARPOS | ||
| 23951 | could be anywhere in the row and in any order. The strategy | ||
| 23952 | below is to find the leftmost and the rightmost glyph that | ||
| 23953 | belongs to either of these 3 strings, or whose position is | ||
| 23954 | between START_CHARPOS and END_CHARPOS, and highlight all the | ||
| 23955 | glyphs between those two. This may cover more than just the | ||
| 23956 | text between START_CHARPOS and END_CHARPOS if the range of | ||
| 23957 | characters strides the bidi level boundary, e.g. if the | ||
| 23958 | beginning is in R2L text while the end is in L2R text or vice | ||
| 23959 | versa. */ | ||
| 23960 | if (!row->reversed_p) | ||
| 23961 | { | ||
| 23962 | /* This row is in a left to right paragraph. Scan it left | ||
| 23963 | to right. */ | ||
| 23964 | glyph = row->glyphs[TEXT_AREA]; | ||
| 23965 | end = glyph + row->used[TEXT_AREA]; | ||
| 23966 | x = row->x; | ||
| 23967 | |||
| 23968 | /* Skip truncation glyphs at the start of the glyph row. */ | ||
| 23969 | if (row->displays_text_p) | ||
| 23970 | for (; glyph < end | ||
| 23971 | && INTEGERP (glyph->object) | ||
| 23972 | && glyph->charpos < 0; | ||
| 23973 | ++glyph) | ||
| 23974 | x += glyph->pixel_width; | ||
| 23975 | |||
| 23976 | /* Scan the glyph row, looking for BEFORE_STRING, | ||
| 23977 | AFTER_STRING, or DISPLAY_STRING, and the first glyph from | ||
| 23978 | buffer whose position is between START_CHARPOS and | ||
| 23979 | END_CHARPOS. */ | ||
| 23980 | for (; glyph < end | ||
| 23981 | && !INTEGERP (glyph->object) | ||
| 23982 | && !EQ (glyph->object, display_string) | ||
| 23983 | && !(BUFFERP (glyph->object) | ||
| 23984 | && (glyph->charpos >= start_charpos | ||
| 23985 | && glyph->charpos < end_charpos)); | ||
| 23986 | ++glyph) | ||
| 23987 | { | ||
| 23988 | /* BEFORE_STRING or AFTER_STRING are only relevant if | ||
| 23989 | they are present at buffer positions between | ||
| 23990 | START_CHARPOS and END_CHARPOS, or if they come from | ||
| 23991 | an overlay. */ | ||
| 23992 | if (EQ (glyph->object, before_string)) | ||
| 23993 | { | ||
| 23994 | pos = string_buffer_position (w, before_string, | ||
| 23995 | start_charpos); | ||
| 23996 | /* If pos == 0, it means before_string came from an | ||
| 23997 | overlay, not from a buffer position. */ | ||
| 23998 | if (!pos || pos >= start_charpos && pos < end_charpos) | ||
| 23999 | break; | ||
| 24000 | } | ||
| 24001 | else if (EQ (glyph->object, after_string)) | ||
| 24002 | { | ||
| 24003 | pos = string_buffer_position (w, after_string, end_charpos); | ||
| 24004 | if (!pos || pos >= start_charpos && pos < end_charpos) | ||
| 24005 | break; | ||
| 24006 | } | ||
| 24007 | x += glyph->pixel_width; | ||
| 24008 | } | ||
| 24009 | dpyinfo->mouse_face_beg_x = x; | ||
| 24010 | dpyinfo->mouse_face_beg_col = glyph - row->glyphs[TEXT_AREA]; | ||
| 24011 | } | ||
| 24012 | else | ||
| 24013 | { | ||
| 24014 | /* This row is in a right to left paragraph. Scan it right | ||
| 24015 | to left. */ | ||
| 24016 | struct glyph *g; | ||
| 24017 | |||
| 24018 | end = row->glyphs[TEXT_AREA] - 1; | ||
| 24019 | glyph = end + row->used[TEXT_AREA]; | ||
| 24020 | |||
| 24021 | /* Skip truncation glyphs at the start of the glyph row. */ | ||
| 24022 | if (row->displays_text_p) | ||
| 24023 | for (; glyph > end | ||
| 24024 | && INTEGERP (glyph->object) | ||
| 24025 | && glyph->charpos < 0; | ||
| 24026 | --glyph) | ||
| 24027 | ; | ||
| 24028 | |||
| 24029 | /* Scan the glyph row, looking for BEFORE_STRING, | ||
| 24030 | AFTER_STRING, or DISPLAY_STRING, and the first glyph from | ||
| 24031 | buffer whose position is between START_CHARPOS and | ||
| 24032 | END_CHARPOS. */ | ||
| 24033 | for (; glyph > end | ||
| 24034 | && !INTEGERP (glyph->object) | ||
| 24035 | && !EQ (glyph->object, display_string) | ||
| 24036 | && !(BUFFERP (glyph->object) | ||
| 24037 | && (glyph->charpos >= start_charpos | ||
| 24038 | && glyph->charpos < end_charpos)); | ||
| 24039 | --glyph) | ||
| 24040 | { | ||
| 24041 | /* BEFORE_STRING or AFTER_STRING are only relevant if | ||
| 24042 | they are present at buffer positions between | ||
| 24043 | START_CHARPOS and END_CHARPOS, or if they come from | ||
| 24044 | an overlay. */ | ||
| 24045 | if (EQ (glyph->object, before_string)) | ||
| 24046 | { | ||
| 24047 | pos = string_buffer_position (w, before_string, | ||
| 24048 | start_charpos); | ||
| 24049 | /* If pos == 0, it means before_string came from an | ||
| 24050 | overlay, not from a buffer position. */ | ||
| 24051 | if (!pos || pos >= start_charpos && pos < end_charpos) | ||
| 24052 | break; | ||
| 24053 | } | ||
| 24054 | else if (EQ (glyph->object, after_string)) | ||
| 24055 | { | ||
| 24056 | pos = string_buffer_position (w, after_string, end_charpos); | ||
| 24057 | if (!pos || pos >= start_charpos && pos < end_charpos) | ||
| 24058 | break; | ||
| 24059 | } | ||
| 24060 | } | ||
| 24061 | |||
| 24062 | glyph++; /* first glyph to the right of the highlighted area */ | ||
| 24063 | for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++) | ||
| 24064 | x += g->pixel_width; | ||
| 24065 | dpyinfo->mouse_face_beg_x = x; | ||
| 24066 | dpyinfo->mouse_face_beg_col = glyph - row->glyphs[TEXT_AREA]; | ||
| 24067 | } | ||
| 24068 | } | 23946 | } |
| 24069 | 23947 | ||
| 24070 | /* Find the last highlighted glyph. */ | 23948 | /* Find the row with END_CHARPOS. */ |
| 24071 | r = row_containing_pos (w, end_charpos, first, NULL, 0); | 23949 | r2 = row_containing_pos (w, end_charpos, first, NULL, 0); |
| 24072 | if (r == NULL) | 23950 | if (r2 == NULL) |
| 24073 | { | 23951 | { |
| 24074 | r = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); | 23952 | r2 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); |
| 24075 | dpyinfo->mouse_face_past_end = 1; | 23953 | dpyinfo->mouse_face_past_end = 1; |
| 24076 | } | 23954 | } |
| 24077 | else if (!NILP (after_string)) | 23955 | else if (!NILP (after_string)) |
| @@ -24081,36 +23959,164 @@ mouse_face_from_buffer_pos (Lisp_Object window, | |||
| 24081 | struct glyph_row *last | 23959 | struct glyph_row *last |
| 24082 | = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); | 23960 | = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); |
| 24083 | 23961 | ||
| 24084 | for (next = r + 1; | 23962 | for (next = r2 + 1; |
| 24085 | next <= last | 23963 | next <= last |
| 24086 | && next->used[TEXT_AREA] > 0 | 23964 | && next->used[TEXT_AREA] > 0 |
| 24087 | && EQ (next->glyphs[TEXT_AREA]->object, after_string); | 23965 | && EQ (next->glyphs[TEXT_AREA]->object, after_string); |
| 24088 | ++next) | 23966 | ++next) |
| 24089 | r = next; | 23967 | r2 = next; |
| 23968 | } | ||
| 23969 | |||
| 23970 | /* The rest of the display engine assumes that mouse_face_beg_row is | ||
| 23971 | either above below mouse_face_end_row or identical to it. But | ||
| 23972 | with bidi-reordered continued lines, the row for START_CHARPOS | ||
| 23973 | could be below the row for END_CHARPOS. If so, swap the rows and | ||
| 23974 | store them in correct order. */ | ||
| 23975 | if (r1->y > r2->y) | ||
| 23976 | { | ||
| 23977 | struct glyph_row *tem = r2; | ||
| 23978 | |||
| 23979 | r2 = r1; | ||
| 23980 | r1 = tem; | ||
| 23981 | } | ||
| 23982 | dpyinfo->mouse_face_beg_y = r1->y; | ||
| 23983 | dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix); | ||
| 23984 | dpyinfo->mouse_face_end_y = r2->y; | ||
| 23985 | dpyinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix); | ||
| 23986 | |||
| 23987 | /* For a bidi-reordered row, the positions of BEFORE_STRING, | ||
| 23988 | AFTER_STRING, DISPLAY_STRING, START_CHARPOS, and END_CHARPOS | ||
| 23989 | could be anywhere in the row and in any order. The strategy | ||
| 23990 | below is to find the leftmost and the rightmost glyph that | ||
| 23991 | belongs to either of these 3 strings, or whose position is | ||
| 23992 | between START_CHARPOS and END_CHARPOS, and highlight all the | ||
| 23993 | glyphs between those two. This may cover more than just the text | ||
| 23994 | between START_CHARPOS and END_CHARPOS if the range of characters | ||
| 23995 | strides the bidi level boundary, e.g. if the beginning is in R2L | ||
| 23996 | text while the end is in L2R text or vice versa. */ | ||
| 23997 | if (!r1->reversed_p) | ||
| 23998 | { | ||
| 23999 | /* This row is in a left to right paragraph. Scan it left to | ||
| 24000 | right. */ | ||
| 24001 | glyph = r1->glyphs[TEXT_AREA]; | ||
| 24002 | end = glyph + r1->used[TEXT_AREA]; | ||
| 24003 | x = r1->x; | ||
| 24004 | |||
| 24005 | /* Skip truncation glyphs at the start of the glyph row. */ | ||
| 24006 | if (r1->displays_text_p) | ||
| 24007 | for (; glyph < end | ||
| 24008 | && INTEGERP (glyph->object) | ||
| 24009 | && glyph->charpos < 0; | ||
| 24010 | ++glyph) | ||
| 24011 | x += glyph->pixel_width; | ||
| 24012 | |||
| 24013 | /* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING, | ||
| 24014 | or DISPLAY_STRING, and the first glyph from buffer whose | ||
| 24015 | position is between START_CHARPOS and END_CHARPOS. */ | ||
| 24016 | for (; glyph < end | ||
| 24017 | && !INTEGERP (glyph->object) | ||
| 24018 | && !EQ (glyph->object, display_string) | ||
| 24019 | && !(BUFFERP (glyph->object) | ||
| 24020 | && (glyph->charpos >= start_charpos | ||
| 24021 | && glyph->charpos < end_charpos)); | ||
| 24022 | ++glyph) | ||
| 24023 | { | ||
| 24024 | /* BEFORE_STRING or AFTER_STRING are only relevant if they | ||
| 24025 | are present at buffer positions between START_CHARPOS and | ||
| 24026 | END_CHARPOS, or if they come from an overlay. */ | ||
| 24027 | if (EQ (glyph->object, before_string)) | ||
| 24028 | { | ||
| 24029 | pos = string_buffer_position (w, before_string, | ||
| 24030 | start_charpos); | ||
| 24031 | /* If pos == 0, it means before_string came from an | ||
| 24032 | overlay, not from a buffer position. */ | ||
| 24033 | if (!pos || pos >= start_charpos && pos < end_charpos) | ||
| 24034 | break; | ||
| 24035 | } | ||
| 24036 | else if (EQ (glyph->object, after_string)) | ||
| 24037 | { | ||
| 24038 | pos = string_buffer_position (w, after_string, end_charpos); | ||
| 24039 | if (!pos || pos >= start_charpos && pos < end_charpos) | ||
| 24040 | break; | ||
| 24041 | } | ||
| 24042 | x += glyph->pixel_width; | ||
| 24043 | } | ||
| 24044 | dpyinfo->mouse_face_beg_x = x; | ||
| 24045 | dpyinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA]; | ||
| 24046 | } | ||
| 24047 | else | ||
| 24048 | { | ||
| 24049 | /* This row is in a right to left paragraph. Scan it right to | ||
| 24050 | left. */ | ||
| 24051 | struct glyph *g; | ||
| 24052 | |||
| 24053 | end = r1->glyphs[TEXT_AREA] - 1; | ||
| 24054 | glyph = end + r1->used[TEXT_AREA]; | ||
| 24055 | |||
| 24056 | /* Skip truncation glyphs at the start of the glyph row. */ | ||
| 24057 | if (r1->displays_text_p) | ||
| 24058 | for (; glyph > end | ||
| 24059 | && INTEGERP (glyph->object) | ||
| 24060 | && glyph->charpos < 0; | ||
| 24061 | --glyph) | ||
| 24062 | ; | ||
| 24063 | |||
| 24064 | /* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING, | ||
| 24065 | or DISPLAY_STRING, and the first glyph from buffer whose | ||
| 24066 | position is between START_CHARPOS and END_CHARPOS. */ | ||
| 24067 | for (; glyph > end | ||
| 24068 | && !INTEGERP (glyph->object) | ||
| 24069 | && !EQ (glyph->object, display_string) | ||
| 24070 | && !(BUFFERP (glyph->object) | ||
| 24071 | && (glyph->charpos >= start_charpos | ||
| 24072 | && glyph->charpos < end_charpos)); | ||
| 24073 | --glyph) | ||
| 24074 | { | ||
| 24075 | /* BEFORE_STRING or AFTER_STRING are only relevant if they | ||
| 24076 | are present at buffer positions between START_CHARPOS and | ||
| 24077 | END_CHARPOS, or if they come from an overlay. */ | ||
| 24078 | if (EQ (glyph->object, before_string)) | ||
| 24079 | { | ||
| 24080 | pos = string_buffer_position (w, before_string, start_charpos); | ||
| 24081 | /* If pos == 0, it means before_string came from an | ||
| 24082 | overlay, not from a buffer position. */ | ||
| 24083 | if (!pos || pos >= start_charpos && pos < end_charpos) | ||
| 24084 | break; | ||
| 24085 | } | ||
| 24086 | else if (EQ (glyph->object, after_string)) | ||
| 24087 | { | ||
| 24088 | pos = string_buffer_position (w, after_string, end_charpos); | ||
| 24089 | if (!pos || pos >= start_charpos && pos < end_charpos) | ||
| 24090 | break; | ||
| 24091 | } | ||
| 24092 | } | ||
| 24093 | |||
| 24094 | glyph++; /* first glyph to the right of the highlighted area */ | ||
| 24095 | for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++) | ||
| 24096 | x += g->pixel_width; | ||
| 24097 | dpyinfo->mouse_face_beg_x = x; | ||
| 24098 | dpyinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA]; | ||
| 24090 | } | 24099 | } |
| 24091 | 24100 | ||
| 24092 | /* If the highlight ends in a different row, compute GLYPH and END | 24101 | /* If the highlight ends in a different row, compute GLYPH and END |
| 24093 | for the end row. */ | 24102 | for the end row. Otherwise, reuse the values computed above for |
| 24094 | if (r != row) | 24103 | the row where the highlight begins. */ |
| 24104 | if (r2 != r1) | ||
| 24095 | { | 24105 | { |
| 24096 | if (!r->reversed_p) | 24106 | if (!r2->reversed_p) |
| 24097 | { | 24107 | { |
| 24098 | glyph = r->glyphs[TEXT_AREA]; | 24108 | glyph = r2->glyphs[TEXT_AREA]; |
| 24099 | end = glyph + r->used[TEXT_AREA]; | 24109 | end = glyph + r2->used[TEXT_AREA]; |
| 24100 | x = r->x; | 24110 | x = r2->x; |
| 24101 | } | 24111 | } |
| 24102 | else | 24112 | else |
| 24103 | { | 24113 | { |
| 24104 | end = r->glyphs[TEXT_AREA] - 1; | 24114 | end = r2->glyphs[TEXT_AREA] - 1; |
| 24105 | glyph = end + r->used[TEXT_AREA]; | 24115 | glyph = end + r2->used[TEXT_AREA]; |
| 24106 | } | 24116 | } |
| 24107 | row = r; | ||
| 24108 | } | 24117 | } |
| 24109 | 24118 | ||
| 24110 | dpyinfo->mouse_face_end_y = row->y; | 24119 | if (!r2->reversed_p) |
| 24111 | dpyinfo->mouse_face_end_row = MATRIX_ROW_VPOS (row, w->current_matrix); | ||
| 24112 | |||
| 24113 | if (!row->reversed_p) | ||
| 24114 | { | 24120 | { |
| 24115 | /* Skip truncation and continuation glyphs near the end of the | 24121 | /* Skip truncation and continuation glyphs near the end of the |
| 24116 | row, and also blanks and stretch glyphs inserted by | 24122 | row, and also blanks and stretch glyphs inserted by |
| @@ -24153,14 +24159,14 @@ mouse_face_from_buffer_pos (Lisp_Object window, | |||
| 24153 | x += glyph->pixel_width; | 24159 | x += glyph->pixel_width; |
| 24154 | 24160 | ||
| 24155 | dpyinfo->mouse_face_end_x = x; | 24161 | dpyinfo->mouse_face_end_x = x; |
| 24156 | dpyinfo->mouse_face_end_col = glyph - row->glyphs[TEXT_AREA]; | 24162 | dpyinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA]; |
| 24157 | } | 24163 | } |
| 24158 | else | 24164 | else |
| 24159 | { | 24165 | { |
| 24160 | /* Skip truncation and continuation glyphs near the end of the | 24166 | /* Skip truncation and continuation glyphs near the end of the |
| 24161 | row, and also blanks and stretch glyphs inserted by | 24167 | row, and also blanks and stretch glyphs inserted by |
| 24162 | extend_face_to_end_of_line. */ | 24168 | extend_face_to_end_of_line. */ |
| 24163 | x = row->x; | 24169 | x = r2->x; |
| 24164 | end++; | 24170 | end++; |
| 24165 | while (end < glyph | 24171 | while (end < glyph |
| 24166 | && INTEGERP (end->object) | 24172 | && INTEGERP (end->object) |
| @@ -24200,7 +24206,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, | |||
| 24200 | x += end->pixel_width; | 24206 | x += end->pixel_width; |
| 24201 | } | 24207 | } |
| 24202 | dpyinfo->mouse_face_end_x = x; | 24208 | dpyinfo->mouse_face_end_x = x; |
| 24203 | dpyinfo->mouse_face_end_col = end - row->glyphs[TEXT_AREA]; | 24209 | dpyinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA]; |
| 24204 | } | 24210 | } |
| 24205 | 24211 | ||
| 24206 | dpyinfo->mouse_face_window = window; | 24212 | dpyinfo->mouse_face_window = window; |
| @@ -24859,8 +24865,8 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24859 | || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p | 24865 | || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p |
| 24860 | /* R2L rows have a stretch glyph at their front, which | 24866 | /* R2L rows have a stretch glyph at their front, which |
| 24861 | stands for no text, whereas L2R rows have no glyphs at | 24867 | stands for no text, whereas L2R rows have no glyphs at |
| 24862 | all beyond the end of text. Treat such stretch glyphs as | 24868 | all beyond the end of text. Treat such stretch glyphs |
| 24863 | NULL glyphs in L2R rows. */ | 24869 | like we do with NULL glyphs in L2R rows. */ |
| 24864 | || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p | 24870 | || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p |
| 24865 | && glyph == MATRIX_ROW (w->current_matrix, vpos)->glyphs[TEXT_AREA] | 24871 | && glyph == MATRIX_ROW (w->current_matrix, vpos)->glyphs[TEXT_AREA] |
| 24866 | && glyph->type == STRETCH_GLYPH | 24872 | && glyph->type == STRETCH_GLYPH |