diff options
| author | Eli Zaretskii | 2010-10-16 14:52:54 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2010-10-16 14:52:54 +0200 |
| commit | d2038a612693faa218797ba5a8b39ce86ecbd675 (patch) | |
| tree | c4b353943e4b045b463fdbb79303b10da8a7cc62 /src | |
| parent | 9a3d704fa95b96df3ec9a6027b15a76a770c4154 (diff) | |
| download | emacs-d2038a612693faa218797ba5a8b39ce86ecbd675.tar.gz emacs-d2038a612693faa218797ba5a8b39ce86ecbd675.zip | |
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/ChangeLog | 5 | ||||
| -rw-r--r-- | src/xdisp.c | 121 |
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 @@ | |||
| 1 | 2010-10-16 Eli Zaretskii <eliz@gnu.org> | 1 | 2010-10-16 Eli Zaretskii <eliz@gnu.org> |
| 2 | 2 | ||
| 3 | * xdisp.c (note_mode_line_or_margin_highlight): Support | ||
| 4 | bidi-reordered strings and R2L glyph rows. Fix more comments. | ||
| 5 | |||
| 6 | 2010-10-16 Eli Zaretskii <eliz@gnu.org> | ||
| 7 | |||
| 3 | * xdisp.c (rows_from_pos_range, mouse_face_from_buffer_pos) | 8 | * xdisp.c (rows_from_pos_range, mouse_face_from_buffer_pos) |
| 4 | (note_mode_line_or_margin_highlight): Fix comments. | 9 | (note_mode_line_or_margin_highlight): Fix comments. |
| 5 | 10 | ||
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, | |||
| 24602 | int x0; | 24602 | int x0; |
| 24603 | struct glyph *end; | 24603 | struct glyph *end; |
| 24604 | 24604 | ||
| 24605 | /* Kludge alert: mode_line_string takes X/Y in pixels, but | ||
| 24606 | returns them in row/column units! */ | ||
| 24605 | string = mode_line_string (w, area, &x, &y, &charpos, | 24607 | string = mode_line_string (w, area, &x, &y, &charpos, |
| 24606 | &object, &dx, &dy, &width, &height); | 24608 | &object, &dx, &dy, &width, &height); |
| 24607 | 24609 | ||
| @@ -24627,6 +24629,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, | |||
| 24627 | else | 24629 | else |
| 24628 | { | 24630 | { |
| 24629 | x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w); | 24631 | x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w); |
| 24632 | /* Kludge alert: marginal_area_string takes X/Y in pixels, but | ||
| 24633 | returns them in row/column units! */ | ||
| 24630 | string = marginal_area_string (w, area, &x, &y, &charpos, | 24634 | string = marginal_area_string (w, area, &x, &y, &charpos, |
| 24631 | &object, &dx, &dy, &width, &height); | 24635 | &object, &dx, &dy, &width, &height); |
| 24632 | } | 24636 | } |
| @@ -24715,21 +24719,26 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, | |||
| 24715 | int gpos; | 24719 | int gpos; |
| 24716 | int gseq_length; | 24720 | int gseq_length; |
| 24717 | int total_pixel_width; | 24721 | int total_pixel_width; |
| 24718 | EMACS_INT ignore; | 24722 | EMACS_INT begpos, endpos, ignore; |
| 24719 | 24723 | ||
| 24720 | int vpos, hpos; | 24724 | int vpos, hpos; |
| 24721 | 24725 | ||
| 24722 | b = Fprevious_single_property_change (make_number (charpos + 1), | 24726 | b = Fprevious_single_property_change (make_number (charpos + 1), |
| 24723 | Qmouse_face, string, Qnil); | 24727 | Qmouse_face, string, Qnil); |
| 24724 | if (NILP (b)) | 24728 | if (NILP (b)) |
| 24725 | b = make_number (0); | 24729 | begpos = 0; |
| 24730 | else | ||
| 24731 | begpos = XINT (b); | ||
| 24726 | 24732 | ||
| 24727 | e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil); | 24733 | e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil); |
| 24728 | if (NILP (e)) | 24734 | if (NILP (e)) |
| 24729 | e = make_number (SCHARS (string)); | 24735 | endpos = SCHARS (string); |
| 24736 | else | ||
| 24737 | endpos = XINT (e); | ||
| 24730 | 24738 | ||
| 24731 | /* Calculate the glyph position GPOS of GLYPH in the | 24739 | /* Calculate the glyph position GPOS of GLYPH in the |
| 24732 | displayed string. | 24740 | displayed string, relative to the beginning of the |
| 24741 | highlighted part of the string. | ||
| 24733 | 24742 | ||
| 24734 | Note: GPOS is different from CHARPOS. CHARPOS is the | 24743 | Note: GPOS is different from CHARPOS. CHARPOS is the |
| 24735 | position of GLYPH in the internal string object. A mode | 24744 | 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, | |||
| 24737 | a flattened string by the Emacs Lisp interpreter. The | 24746 | a flattened string by the Emacs Lisp interpreter. The |
| 24738 | internal string is an element of those structures. The | 24747 | internal string is an element of those structures. The |
| 24739 | displayed string is the flattened string. */ | 24748 | displayed string is the flattened string. */ |
| 24740 | gpos = 0; | 24749 | tmp_glyph = row_start_glyph; |
| 24741 | if (glyph > row_start_glyph) | 24750 | while (tmp_glyph < glyph |
| 24742 | { | 24751 | && (!(EQ (tmp_glyph->object, glyph->object) |
| 24743 | tmp_glyph = glyph - 1; | 24752 | && begpos <= tmp_glyph->charpos |
| 24744 | while (tmp_glyph >= row_start_glyph | 24753 | && tmp_glyph->charpos < endpos))) |
| 24745 | && tmp_glyph->charpos >= XINT (b) | 24754 | tmp_glyph++; |
| 24746 | && EQ (tmp_glyph->object, glyph->object)) | 24755 | gpos = glyph - tmp_glyph; |
| 24747 | { | 24756 | |
| 24748 | tmp_glyph--; | 24757 | /* Calculate the length GSEQ_LENGTH of the glyph sequence of |
| 24749 | gpos++; | 24758 | the highlighted part of the displayed string to which |
| 24750 | } | 24759 | GLYPH belongs. Note: GSEQ_LENGTH is different from |
| 24751 | } | 24760 | SCHARS (STRING), because the latter returns the length of |
| 24752 | 24761 | the internal string. */ | |
| 24753 | /* Calculate the glyph sequence length GSEQ_LENGTH of the | 24762 | for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1; |
| 24754 | displayed string to which GLYPH belongs. Note: | 24763 | tmp_glyph > glyph |
| 24755 | GSEQ_LENGTH is different from SCHARS (STRING), because | 24764 | && (!(EQ (tmp_glyph->object, glyph->object) |
| 24756 | the latter returns the length of the internal string. */ | 24765 | && begpos <= tmp_glyph->charpos |
| 24757 | for (tmp_glyph = glyph, gseq_length = gpos; | 24766 | && tmp_glyph->charpos < endpos)); |
| 24758 | tmp_glyph->charpos < XINT (e); | 24767 | tmp_glyph--) |
| 24759 | tmp_glyph++, gseq_length++) | 24768 | ; |
| 24760 | { | 24769 | gseq_length = gpos + (tmp_glyph - glyph) + 1; |
| 24761 | if (!EQ (tmp_glyph->object, glyph->object)) | ||
| 24762 | break; | ||
| 24763 | } | ||
| 24764 | 24770 | ||
| 24771 | /* Calculate the total pixel width of all the glyphs between | ||
| 24772 | the beginning of the highlighted area and GLYPH. */ | ||
| 24765 | total_pixel_width = 0; | 24773 | total_pixel_width = 0; |
| 24766 | for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++) | 24774 | for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++) |
| 24767 | total_pixel_width += tmp_glyph->pixel_width; | 24775 | total_pixel_width += tmp_glyph->pixel_width; |
| 24768 | 24776 | ||
| 24769 | /* Pre calculation of re-rendering position. */ | 24777 | /* Pre calculation of re-rendering position. Note: X is in |
| 24778 | column units here, after the call to mode_line_string or | ||
| 24779 | marginal_area_string. */ | ||
| 24770 | hpos = x - gpos; | 24780 | hpos = x - gpos; |
| 24771 | vpos = (area == ON_MODE_LINE | 24781 | vpos = (area == ON_MODE_LINE |
| 24772 | ? (w->current_matrix)->nrows - 1 | 24782 | ? (w->current_matrix)->nrows - 1 |
| 24773 | : 0); | 24783 | : 0); |
| 24774 | 24784 | ||
| 24775 | /* If the re-rendering position is included in the last | 24785 | /* If GLYPH's position is included in the region that is |
| 24776 | re-rendering area, we should do nothing. */ | 24786 | already drawn in mouse face, we have nothing to do. */ |
| 24777 | if ( EQ (window, dpyinfo->mouse_face_window) | 24787 | if ( EQ (window, dpyinfo->mouse_face_window) |
| 24778 | && dpyinfo->mouse_face_beg_col <= hpos | 24788 | && (!row->reversed_p |
| 24779 | && hpos < dpyinfo->mouse_face_end_col | 24789 | ? (dpyinfo->mouse_face_beg_col <= hpos |
| 24790 | && hpos < dpyinfo->mouse_face_end_col) | ||
| 24791 | /* In R2L rows we swap BEG and END, see below. */ | ||
| 24792 | : (dpyinfo->mouse_face_end_col <= hpos | ||
| 24793 | && hpos < dpyinfo->mouse_face_beg_col)) | ||
| 24780 | && dpyinfo->mouse_face_beg_row == vpos ) | 24794 | && dpyinfo->mouse_face_beg_row == vpos ) |
| 24781 | return; | 24795 | return; |
| 24782 | 24796 | ||
| 24783 | if (clear_mouse_face (dpyinfo)) | 24797 | if (clear_mouse_face (dpyinfo)) |
| 24784 | cursor = No_Cursor; | 24798 | cursor = No_Cursor; |
| 24785 | 24799 | ||
| 24786 | dpyinfo->mouse_face_beg_col = hpos; | 24800 | if (!row->reversed_p) |
| 24787 | dpyinfo->mouse_face_beg_row = vpos; | 24801 | { |
| 24788 | 24802 | dpyinfo->mouse_face_beg_col = hpos; | |
| 24789 | dpyinfo->mouse_face_beg_x = original_x_pixel - (total_pixel_width + dx); | 24803 | dpyinfo->mouse_face_beg_x = original_x_pixel |
| 24790 | dpyinfo->mouse_face_beg_y = 0; | 24804 | - (total_pixel_width + dx); |
| 24791 | 24805 | dpyinfo->mouse_face_end_col = hpos + gseq_length; | |
| 24792 | dpyinfo->mouse_face_end_col = hpos + gseq_length; | 24806 | dpyinfo->mouse_face_end_x = 0; |
| 24793 | dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_beg_row; | 24807 | } |
| 24794 | 24808 | else | |
| 24795 | dpyinfo->mouse_face_end_x = 0; | 24809 | { |
| 24796 | dpyinfo->mouse_face_end_y = 0; | 24810 | /* In R2L rows, show_mouse_face expects BEG and END |
| 24811 | coordinates to be swapped. */ | ||
| 24812 | dpyinfo->mouse_face_end_col = hpos; | ||
| 24813 | dpyinfo->mouse_face_end_x = original_x_pixel | ||
| 24814 | - (total_pixel_width + dx); | ||
| 24815 | dpyinfo->mouse_face_beg_col = hpos + gseq_length; | ||
| 24816 | dpyinfo->mouse_face_beg_x = 0; | ||
| 24817 | } | ||
| 24797 | 24818 | ||
| 24819 | dpyinfo->mouse_face_beg_row = vpos; | ||
| 24820 | dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_beg_row; | ||
| 24821 | dpyinfo->mouse_face_beg_y = 0; | ||
| 24822 | dpyinfo->mouse_face_end_y = 0; | ||
| 24798 | dpyinfo->mouse_face_past_end = 0; | 24823 | dpyinfo->mouse_face_past_end = 0; |
| 24799 | dpyinfo->mouse_face_window = window; | 24824 | dpyinfo->mouse_face_window = window; |
| 24800 | 24825 | ||
| 24801 | dpyinfo->mouse_face_face_id = face_at_string_position (w, string, | 24826 | dpyinfo->mouse_face_face_id = face_at_string_position (w, string, |
| 24802 | charpos, | 24827 | charpos, |
| 24803 | 0, 0, 0, &ignore, | 24828 | 0, 0, 0, |
| 24804 | glyph->face_id, 1); | 24829 | &ignore, |
| 24830 | glyph->face_id, | ||
| 24831 | 1); | ||
| 24805 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | 24832 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); |
| 24806 | 24833 | ||
| 24807 | if (NILP (pointer)) | 24834 | if (NILP (pointer)) |