aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2010-08-21 18:24:15 +0300
committerEli Zaretskii2010-08-21 18:24:15 +0300
commitefb6b75c91427015e4cf7c0fc0492e56a41b2c61 (patch)
tree79c710993865332df8aba357085c27ea889e6eeb /src
parent40629f171babe6087c32d3211beeb23b136155bd (diff)
downloademacs-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/ChangeLog3
-rw-r--r--src/xdisp.c181
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 @@
12010-08-21 Eli Zaretskii <eliz@gnu.org> 12010-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;