diff options
| author | Eli Zaretskii | 2010-08-21 18:24:15 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2010-08-21 18:24:15 +0300 |
| commit | efb6b75c91427015e4cf7c0fc0492e56a41b2c61 (patch) | |
| tree | 79c710993865332df8aba357085c27ea889e6eeb /src | |
| parent | 40629f171babe6087c32d3211beeb23b136155bd (diff) | |
| download | emacs-efb6b75c91427015e4cf7c0fc0492e56a41b2c61.tar.gz emacs-efb6b75c91427015e4cf7c0fc0492e56a41b2c61.zip | |
Initial partial support for mouse highlight in bidi-reordered text.
xdisp.c (mouse_face_from_buffer_pos): Support mouse highlight in
bidi-reordered L2R lines. Continued lines are not yet supported.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 3 | ||||
| -rw-r--r-- | src/xdisp.c | 181 |
2 files changed, 113 insertions, 71 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 403a588df4c..242018c4061 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,8 @@ | |||
| 1 | 2010-08-21 Eli Zaretskii <eliz@gnu.org> | 1 | 2010-08-21 Eli Zaretskii <eliz@gnu.org> |
| 2 | 2 | ||
| 3 | * xdisp.c (mouse_face_from_buffer_pos): Support mouse highlight in | ||
| 4 | bidi-reordered L2R lines. Continued lines are not yet supported. | ||
| 5 | |||
| 3 | * dispnew.c (buffer_posn_from_coords): Fix off-by-one error in | 6 | * dispnew.c (buffer_posn_from_coords): Fix off-by-one error in |
| 4 | mirroring pixel positions. | 7 | mirroring pixel positions. |
| 5 | 8 | ||
diff --git a/src/xdisp.c b/src/xdisp.c index c80e1f35df3..7fcbab718b1 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -23839,7 +23839,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, | |||
| 23839 | struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | 23839 | struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); |
| 23840 | struct glyph_row *row; | 23840 | struct glyph_row *row; |
| 23841 | struct glyph *glyph, *end; | 23841 | struct glyph *glyph, *end; |
| 23842 | EMACS_INT ignore; | 23842 | EMACS_INT ignore, pos; |
| 23843 | int x; | 23843 | int x; |
| 23844 | 23844 | ||
| 23845 | xassert (NILP (display_string) || STRINGP (display_string)); | 23845 | xassert (NILP (display_string) || STRINGP (display_string)); |
| @@ -23847,7 +23847,9 @@ mouse_face_from_buffer_pos (Lisp_Object window, | |||
| 23847 | xassert (NILP (after_string) || STRINGP (after_string)); | 23847 | xassert (NILP (after_string) || STRINGP (after_string)); |
| 23848 | 23848 | ||
| 23849 | /* Find the first highlighted glyph. */ | 23849 | /* Find the first highlighted glyph. */ |
| 23850 | if (start_charpos < MATRIX_ROW_START_CHARPOS (first)) | 23850 | if (start_charpos < MATRIX_ROW_START_CHARPOS (first) |
| 23851 | && (NILP (XBUFFER (w->buffer)->bidi_display_reordering) | ||
| 23852 | || row_containing_pos (w, start_charpos, first, NULL, 0) == NULL)) | ||
| 23851 | { | 23853 | { |
| 23852 | dpyinfo->mouse_face_beg_col = 0; | 23854 | dpyinfo->mouse_face_beg_col = 0; |
| 23853 | dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (first, w->current_matrix); | 23855 | dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (first, w->current_matrix); |
| @@ -23856,6 +23858,10 @@ mouse_face_from_buffer_pos (Lisp_Object window, | |||
| 23856 | } | 23858 | } |
| 23857 | else | 23859 | else |
| 23858 | { | 23860 | { |
| 23861 | /* FIXME: this assumes that START_CHARPOS is in beg_row. This | ||
| 23862 | is false for reordered lines that are continued. Need to | ||
| 23863 | compute beg_row and end_row separately from beg_col and | ||
| 23864 | end_col. */ | ||
| 23859 | row = row_containing_pos (w, start_charpos, first, NULL, 0); | 23865 | row = row_containing_pos (w, start_charpos, first, NULL, 0); |
| 23860 | if (row == NULL) | 23866 | if (row == NULL) |
| 23861 | row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); | 23867 | row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); |
| @@ -23880,33 +23886,72 @@ mouse_face_from_buffer_pos (Lisp_Object window, | |||
| 23880 | } | 23886 | } |
| 23881 | } | 23887 | } |
| 23882 | 23888 | ||
| 23883 | glyph = row->glyphs[TEXT_AREA]; | ||
| 23884 | end = glyph + row->used[TEXT_AREA]; | ||
| 23885 | x = row->x; | ||
| 23886 | dpyinfo->mouse_face_beg_y = row->y; | 23889 | dpyinfo->mouse_face_beg_y = row->y; |
| 23887 | dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (row, w->current_matrix); | 23890 | dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (row, w->current_matrix); |
| 23888 | 23891 | ||
| 23889 | /* Skip truncation glyphs at the start of the glyph row. */ | 23892 | /* For a bidi-reordered row, the positions of BEFORE_STRING, |
| 23890 | if (row->displays_text_p) | 23893 | AFTER_STRING, DISPLAY_STRING, START_CHARPOS, and END_CHARPOS |
| 23891 | for (; glyph < end | 23894 | could be anywhere in the row and in any order. The strategy |
| 23892 | && INTEGERP (glyph->object) | 23895 | below is to find the leftmost and the rightmost glyph that |
| 23893 | && glyph->charpos < 0; | 23896 | belongs to either of these 3 strings, or whose position is |
| 23894 | ++glyph) | 23897 | between START_CHARPOS and END_CHARPOS, and highlight all the |
| 23895 | x += glyph->pixel_width; | 23898 | glyphs between those two. This may cover more than just the |
| 23896 | 23899 | text between START_CHARPOS and END_CHARPOS if the range of | |
| 23897 | /* Scan the glyph row, stopping before BEFORE_STRING or | 23900 | characters strides the the bidi level boundary, e.g. if the |
| 23898 | DISPLAY_STRING or START_CHARPOS. */ | 23901 | beginning is in R2L text while the end is in L2R text or vice |
| 23899 | for (; glyph < end | 23902 | versa. */ |
| 23900 | && !INTEGERP (glyph->object) | 23903 | if (!row->reversed_p) |
| 23901 | && !EQ (glyph->object, before_string) | 23904 | { |
| 23902 | && !EQ (glyph->object, display_string) | 23905 | /* This row is in a left to right paragraph. Scan it left |
| 23903 | && !(BUFFERP (glyph->object) | 23906 | to right. */ |
| 23904 | && glyph->charpos >= start_charpos); | 23907 | glyph = row->glyphs[TEXT_AREA]; |
| 23905 | ++glyph) | 23908 | end = glyph + row->used[TEXT_AREA]; |
| 23906 | x += glyph->pixel_width; | 23909 | x = row->x; |
| 23910 | |||
| 23911 | /* Skip truncation glyphs at the start of the glyph row. */ | ||
| 23912 | if (row->displays_text_p) | ||
| 23913 | for (; glyph < end | ||
| 23914 | && INTEGERP (glyph->object) | ||
| 23915 | && glyph->charpos < 0; | ||
| 23916 | ++glyph) | ||
| 23917 | x += glyph->pixel_width; | ||
| 23907 | 23918 | ||
| 23908 | dpyinfo->mouse_face_beg_x = x; | 23919 | /* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING, |
| 23909 | dpyinfo->mouse_face_beg_col = glyph - row->glyphs[TEXT_AREA]; | 23920 | or DISPLAY_STRING, and the first glyph whose position is |
| 23921 | between START_CHARPOS and END_CHARPOS. */ | ||
| 23922 | for (; glyph < end | ||
| 23923 | && !INTEGERP (glyph->object) | ||
| 23924 | && !EQ (glyph->object, display_string) | ||
| 23925 | && !(BUFFERP (glyph->object) | ||
| 23926 | && (glyph->charpos >= start_charpos | ||
| 23927 | && glyph->charpos < end_charpos)); | ||
| 23928 | ++glyph) | ||
| 23929 | { | ||
| 23930 | /* BEFORE_STRING or AFTER_STRING are only relevant if | ||
| 23931 | they are present at buffer positions between | ||
| 23932 | START_CHARPOS and END_CHARPOS. */ | ||
| 23933 | if (EQ (glyph->object, before_string)) | ||
| 23934 | { | ||
| 23935 | pos = string_buffer_position (w, before_string, | ||
| 23936 | start_charpos); | ||
| 23937 | if (pos && pos >= start_charpos && pos < end_charpos) | ||
| 23938 | break; | ||
| 23939 | } | ||
| 23940 | else if (EQ (glyph->object, after_string)) | ||
| 23941 | { | ||
| 23942 | pos = string_buffer_position (w, after_string, end_charpos); | ||
| 23943 | if (pos && pos >= start_charpos && pos < end_charpos) | ||
| 23944 | break; | ||
| 23945 | } | ||
| 23946 | x += glyph->pixel_width; | ||
| 23947 | } | ||
| 23948 | dpyinfo->mouse_face_beg_x = x; | ||
| 23949 | dpyinfo->mouse_face_beg_col = glyph - row->glyphs[TEXT_AREA]; | ||
| 23950 | } | ||
| 23951 | else | ||
| 23952 | { | ||
| 23953 | /* FIXME! */ | ||
| 23954 | } | ||
| 23910 | } | 23955 | } |
| 23911 | 23956 | ||
| 23912 | /* Find the last highlighted glyph. */ | 23957 | /* Find the last highlighted glyph. */ |
| @@ -23931,60 +23976,54 @@ mouse_face_from_buffer_pos (Lisp_Object window, | |||
| 23931 | row = next; | 23976 | row = next; |
| 23932 | } | 23977 | } |
| 23933 | 23978 | ||
| 23934 | glyph = row->glyphs[TEXT_AREA]; | ||
| 23935 | end = glyph + row->used[TEXT_AREA]; | ||
| 23936 | x = row->x; | ||
| 23937 | dpyinfo->mouse_face_end_y = row->y; | 23979 | dpyinfo->mouse_face_end_y = row->y; |
| 23938 | dpyinfo->mouse_face_end_row = MATRIX_ROW_VPOS (row, w->current_matrix); | 23980 | dpyinfo->mouse_face_end_row = MATRIX_ROW_VPOS (row, w->current_matrix); |
| 23939 | 23981 | ||
| 23940 | /* Skip truncation glyphs at the start of the row. */ | 23982 | if (!row->reversed_p) |
| 23941 | if (row->displays_text_p) | ||
| 23942 | for (; glyph < end | ||
| 23943 | && INTEGERP (glyph->object) | ||
| 23944 | && glyph->charpos < 0; | ||
| 23945 | ++glyph) | ||
| 23946 | x += glyph->pixel_width; | ||
| 23947 | |||
| 23948 | /* Scan the glyph row, stopping at END_CHARPOS or when we encounter | ||
| 23949 | AFTER_STRING. */ | ||
| 23950 | for (; glyph < end | ||
| 23951 | && !INTEGERP (glyph->object) | ||
| 23952 | && !EQ (glyph->object, after_string) | ||
| 23953 | && !(BUFFERP (glyph->object) && glyph->charpos >= end_charpos); | ||
| 23954 | ++glyph) | ||
| 23955 | x += glyph->pixel_width; | ||
| 23956 | |||
| 23957 | /* If we found AFTER_STRING, consume it and stop. */ | ||
| 23958 | if (EQ (glyph->object, after_string)) | ||
| 23959 | { | 23983 | { |
| 23960 | for (; EQ (glyph->object, after_string) && glyph < end; ++glyph) | 23984 | /* Skip truncation and continuation glyphs near the end of the |
| 23985 | row, and also blanks and stretch glyphs inserted by | ||
| 23986 | extend_face_to_end_of_line. */ | ||
| 23987 | while (end > glyph | ||
| 23988 | && INTEGERP ((end - 1)->object) | ||
| 23989 | && (end - 1)->charpos <= 0) | ||
| 23990 | --end; | ||
| 23991 | /* Scan the rest of the glyph row from the end, looking for the | ||
| 23992 | first glyph that comes from BEFORE_STRING, AFTER_STRING, or | ||
| 23993 | DISPLAY_STRING, or whose position is between START_CHARPOS | ||
| 23994 | and END_CHARPOS */ | ||
| 23995 | for (--end; | ||
| 23996 | end > glyph | ||
| 23997 | && !INTEGERP (end->object) | ||
| 23998 | && !EQ (end->object, display_string) | ||
| 23999 | && !(BUFFERP (end->object) | ||
| 24000 | && (end->charpos >= start_charpos | ||
| 24001 | && end->charpos < end_charpos)); | ||
| 24002 | --end) | ||
| 24003 | { | ||
| 24004 | /* BEFORE_STRING or AFTER_STRING are only relevant if | ||
| 24005 | they are present at buffer positions between | ||
| 24006 | START_CHARPOS and END_CHARPOS. */ | ||
| 24007 | if (EQ (end->object, before_string)) | ||
| 24008 | { | ||
| 24009 | pos = string_buffer_position (w, before_string, start_charpos); | ||
| 24010 | if (pos && pos >= start_charpos && pos < end_charpos) | ||
| 24011 | break; | ||
| 24012 | } | ||
| 24013 | else if (EQ (end->object, after_string)) | ||
| 24014 | { | ||
| 24015 | pos = string_buffer_position (w, after_string, end_charpos); | ||
| 24016 | if (pos && pos >= start_charpos && pos < end_charpos) | ||
| 24017 | break; | ||
| 24018 | } | ||
| 24019 | } | ||
| 24020 | /* Find the X coordinate of the last glyph to be highlighted. */ | ||
| 24021 | for (; glyph <= end; ++glyph) | ||
| 23961 | x += glyph->pixel_width; | 24022 | x += glyph->pixel_width; |
| 23962 | } | 24023 | } |
| 23963 | else | 24024 | else |
| 23964 | { | 24025 | { |
| 23965 | /* If there's no after-string, we must check if we overshot, | 24026 | /* FIXME! */ |
| 23966 | which might be the case if we stopped after a string glyph. | ||
| 23967 | That glyph may belong to a before-string or display-string | ||
| 23968 | associated with the end position, which must not be | ||
| 23969 | highlighted. */ | ||
| 23970 | Lisp_Object prev_object; | ||
| 23971 | EMACS_INT pos; | ||
| 23972 | |||
| 23973 | while (glyph > row->glyphs[TEXT_AREA]) | ||
| 23974 | { | ||
| 23975 | prev_object = (glyph - 1)->object; | ||
| 23976 | if (!STRINGP (prev_object) || EQ (prev_object, display_string)) | ||
| 23977 | break; | ||
| 23978 | |||
| 23979 | pos = string_buffer_position (w, prev_object, end_charpos); | ||
| 23980 | if (pos && pos < end_charpos) | ||
| 23981 | break; | ||
| 23982 | |||
| 23983 | for (; glyph > row->glyphs[TEXT_AREA] | ||
| 23984 | && EQ ((glyph - 1)->object, prev_object); | ||
| 23985 | --glyph) | ||
| 23986 | x -= (glyph - 1)->pixel_width; | ||
| 23987 | } | ||
| 23988 | } | 24027 | } |
| 23989 | 24028 | ||
| 23990 | dpyinfo->mouse_face_end_x = x; | 24029 | dpyinfo->mouse_face_end_x = x; |