summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2010-10-16 14:52:54 +0200
committerEli Zaretskii <eliz@gnu.org>2010-10-16 14:52:54 +0200
commitd2038a612693faa218797ba5a8b39ce86ecbd675 (patch)
treec4b353943e4b045b463fdbb79303b10da8a7cc62 /src
parent9a3d704fa95b96df3ec9a6027b15a76a770c4154 (diff)
downloademacs-d2038a612693faa218797ba5a8b39ce86ecbd675.tar.gz
Support bidi-reordered text in mouse-highlighted mode- and header-lines.
Note: Not tested with actually bidi-reordered strings. xdisp.c (note_mode_line_or_margin_highlight): Support bidi-reordered strings and R2L glyph rows. Fix more comments.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog5
-rw-r--r--src/xdisp.c121
2 files changed, 79 insertions, 47 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 0f7d39e4d8a..5f6fed12620 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,10 @@
2010-10-16 Eli Zaretskii <eliz@gnu.org>
+ * xdisp.c (note_mode_line_or_margin_highlight): Support
+ bidi-reordered strings and R2L glyph rows. Fix more comments.
+
+2010-10-16 Eli Zaretskii <eliz@gnu.org>
+
* xdisp.c (rows_from_pos_range, mouse_face_from_buffer_pos)
(note_mode_line_or_margin_highlight): Fix comments.
diff --git a/src/xdisp.c b/src/xdisp.c
index 4a7cc275c47..41be01c407f 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -24602,6 +24602,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
int x0;
struct glyph *end;
+ /* Kludge alert: mode_line_string takes X/Y in pixels, but
+ returns them in row/column units! */
string = mode_line_string (w, area, &x, &y, &charpos,
&object, &dx, &dy, &width, &height);
@@ -24627,6 +24629,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
else
{
x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
+ /* Kludge alert: marginal_area_string takes X/Y in pixels, but
+ returns them in row/column units! */
string = marginal_area_string (w, area, &x, &y, &charpos,
&object, &dx, &dy, &width, &height);
}
@@ -24715,21 +24719,26 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
int gpos;
int gseq_length;
int total_pixel_width;
- EMACS_INT ignore;
+ EMACS_INT begpos, endpos, ignore;
int vpos, hpos;
b = Fprevious_single_property_change (make_number (charpos + 1),
Qmouse_face, string, Qnil);
if (NILP (b))
- b = make_number (0);
+ begpos = 0;
+ else
+ begpos = XINT (b);
e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil);
if (NILP (e))
- e = make_number (SCHARS (string));
+ endpos = SCHARS (string);
+ else
+ endpos = XINT (e);
/* Calculate the glyph position GPOS of GLYPH in the
- displayed string.
+ displayed string, relative to the beginning of the
+ highlighted part of the string.
Note: GPOS is different from CHARPOS. CHARPOS is the
position of GLYPH in the internal string object. A mode
@@ -24737,71 +24746,89 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
a flattened string by the Emacs Lisp interpreter. The
internal string is an element of those structures. The
displayed string is the flattened string. */
- gpos = 0;
- if (glyph > row_start_glyph)
- {
- tmp_glyph = glyph - 1;
- while (tmp_glyph >= row_start_glyph
- && tmp_glyph->charpos >= XINT (b)
- && EQ (tmp_glyph->object, glyph->object))
- {
- tmp_glyph--;
- gpos++;
- }
- }
-
- /* Calculate the glyph sequence length GSEQ_LENGTH of the
- displayed string to which GLYPH belongs. Note:
- GSEQ_LENGTH is different from SCHARS (STRING), because
- the latter returns the length of the internal string. */
- for (tmp_glyph = glyph, gseq_length = gpos;
- tmp_glyph->charpos < XINT (e);
- tmp_glyph++, gseq_length++)
- {
- if (!EQ (tmp_glyph->object, glyph->object))
- break;
- }
+ tmp_glyph = row_start_glyph;
+ while (tmp_glyph < glyph
+ && (!(EQ (tmp_glyph->object, glyph->object)
+ && begpos <= tmp_glyph->charpos
+ && tmp_glyph->charpos < endpos)))
+ tmp_glyph++;
+ gpos = glyph - tmp_glyph;
+
+ /* Calculate the length GSEQ_LENGTH of the glyph sequence of
+ the highlighted part of the displayed string to which
+ GLYPH belongs. Note: GSEQ_LENGTH is different from
+ SCHARS (STRING), because the latter returns the length of
+ the internal string. */
+ for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
+ tmp_glyph > glyph
+ && (!(EQ (tmp_glyph->object, glyph->object)
+ && begpos <= tmp_glyph->charpos
+ && tmp_glyph->charpos < endpos));
+ tmp_glyph--)
+ ;
+ gseq_length = gpos + (tmp_glyph - glyph) + 1;
+ /* Calculate the total pixel width of all the glyphs between
+ the beginning of the highlighted area and GLYPH. */
total_pixel_width = 0;
for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++)
total_pixel_width += tmp_glyph->pixel_width;
- /* Pre calculation of re-rendering position. */
+ /* Pre calculation of re-rendering position. Note: X is in
+ column units here, after the call to mode_line_string or
+ marginal_area_string. */
hpos = x - gpos;
vpos = (area == ON_MODE_LINE
? (w->current_matrix)->nrows - 1
: 0);
- /* If the re-rendering position is included in the last
- re-rendering area, we should do nothing. */
+ /* If GLYPH's position is included in the region that is
+ already drawn in mouse face, we have nothing to do. */
if ( EQ (window, dpyinfo->mouse_face_window)
- && dpyinfo->mouse_face_beg_col <= hpos
- && hpos < dpyinfo->mouse_face_end_col
+ && (!row->reversed_p
+ ? (dpyinfo->mouse_face_beg_col <= hpos
+ && hpos < dpyinfo->mouse_face_end_col)
+ /* In R2L rows we swap BEG and END, see below. */
+ : (dpyinfo->mouse_face_end_col <= hpos
+ && hpos < dpyinfo->mouse_face_beg_col))
&& dpyinfo->mouse_face_beg_row == vpos )
return;
if (clear_mouse_face (dpyinfo))
cursor = No_Cursor;
- dpyinfo->mouse_face_beg_col = hpos;
- dpyinfo->mouse_face_beg_row = vpos;
-
- dpyinfo->mouse_face_beg_x = original_x_pixel - (total_pixel_width + dx);
- dpyinfo->mouse_face_beg_y = 0;
-
- dpyinfo->mouse_face_end_col = hpos + gseq_length;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_beg_row;
-
- dpyinfo->mouse_face_end_x = 0;
- dpyinfo->mouse_face_end_y = 0;
+ if (!row->reversed_p)
+ {
+ dpyinfo->mouse_face_beg_col = hpos;
+ dpyinfo->mouse_face_beg_x = original_x_pixel
+ - (total_pixel_width + dx);
+ dpyinfo->mouse_face_end_col = hpos + gseq_length;
+ dpyinfo->mouse_face_end_x = 0;
+ }
+ else
+ {
+ /* In R2L rows, show_mouse_face expects BEG and END
+ coordinates to be swapped. */
+ dpyinfo->mouse_face_end_col = hpos;
+ dpyinfo->mouse_face_end_x = original_x_pixel
+ - (total_pixel_width + dx);
+ dpyinfo->mouse_face_beg_col = hpos + gseq_length;
+ dpyinfo->mouse_face_beg_x = 0;
+ }
+ dpyinfo->mouse_face_beg_row = vpos;
+ dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_beg_row;
+ dpyinfo->mouse_face_beg_y = 0;
+ dpyinfo->mouse_face_end_y = 0;
dpyinfo->mouse_face_past_end = 0;
- dpyinfo->mouse_face_window = window;
+ dpyinfo->mouse_face_window = window;
dpyinfo->mouse_face_face_id = face_at_string_position (w, string,
charpos,
- 0, 0, 0, &ignore,
- glyph->face_id, 1);
+ 0, 0, 0,
+ &ignore,
+ glyph->face_id,
+ 1);
show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
if (NILP (pointer))