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 /src | |
| 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.
Diffstat (limited to 'src')
| -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 |