From 32c9ff2bf1cc5eb2c4d395775e9b2d0077c30883 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 21 Aug 2010 18:24:15 +0300 Subject: 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. --- src/xdisp.c | 181 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 110 insertions(+), 71 deletions(-) (limited to 'src/xdisp.c') 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, struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); struct glyph_row *row; struct glyph *glyph, *end; - EMACS_INT ignore; + EMACS_INT ignore, pos; int x; xassert (NILP (display_string) || STRINGP (display_string)); @@ -23847,7 +23847,9 @@ mouse_face_from_buffer_pos (Lisp_Object window, xassert (NILP (after_string) || STRINGP (after_string)); /* Find the first highlighted glyph. */ - if (start_charpos < MATRIX_ROW_START_CHARPOS (first)) + if (start_charpos < MATRIX_ROW_START_CHARPOS (first) + && (NILP (XBUFFER (w->buffer)->bidi_display_reordering) + || row_containing_pos (w, start_charpos, first, NULL, 0) == NULL)) { dpyinfo->mouse_face_beg_col = 0; dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (first, w->current_matrix); @@ -23856,6 +23858,10 @@ mouse_face_from_buffer_pos (Lisp_Object window, } else { + /* FIXME: this assumes that START_CHARPOS is in beg_row. This + is false for reordered lines that are continued. Need to + compute beg_row and end_row separately from beg_col and + end_col. */ row = row_containing_pos (w, start_charpos, first, NULL, 0); if (row == NULL) row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); @@ -23880,33 +23886,72 @@ mouse_face_from_buffer_pos (Lisp_Object window, } } - glyph = row->glyphs[TEXT_AREA]; - end = glyph + row->used[TEXT_AREA]; - x = row->x; dpyinfo->mouse_face_beg_y = row->y; dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (row, w->current_matrix); - /* Skip truncation glyphs at the start of the glyph row. */ - if (row->displays_text_p) - for (; glyph < end - && INTEGERP (glyph->object) - && glyph->charpos < 0; - ++glyph) - x += glyph->pixel_width; - - /* Scan the glyph row, stopping before BEFORE_STRING or - DISPLAY_STRING or START_CHARPOS. */ - for (; glyph < end - && !INTEGERP (glyph->object) - && !EQ (glyph->object, before_string) - && !EQ (glyph->object, display_string) - && !(BUFFERP (glyph->object) - && glyph->charpos >= start_charpos); - ++glyph) - x += glyph->pixel_width; + /* For a bidi-reordered row, the positions of BEFORE_STRING, + AFTER_STRING, DISPLAY_STRING, START_CHARPOS, and END_CHARPOS + could be anywhere in the row and in any order. The strategy + below is to find the leftmost and the rightmost glyph that + belongs to either of these 3 strings, or whose position is + between START_CHARPOS and END_CHARPOS, and highlight all the + glyphs between those two. This may cover more than just the + text between START_CHARPOS and END_CHARPOS if the range of + characters strides the the bidi level boundary, e.g. if the + beginning is in R2L text while the end is in L2R text or vice + versa. */ + if (!row->reversed_p) + { + /* This row is in a left to right paragraph. Scan it left + to right. */ + glyph = row->glyphs[TEXT_AREA]; + end = glyph + row->used[TEXT_AREA]; + x = row->x; + + /* Skip truncation glyphs at the start of the glyph row. */ + if (row->displays_text_p) + for (; glyph < end + && INTEGERP (glyph->object) + && glyph->charpos < 0; + ++glyph) + x += glyph->pixel_width; - dpyinfo->mouse_face_beg_x = x; - dpyinfo->mouse_face_beg_col = glyph - row->glyphs[TEXT_AREA]; + /* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING, + or DISPLAY_STRING, and the first glyph whose position is + between START_CHARPOS and END_CHARPOS. */ + for (; glyph < end + && !INTEGERP (glyph->object) + && !EQ (glyph->object, display_string) + && !(BUFFERP (glyph->object) + && (glyph->charpos >= start_charpos + && glyph->charpos < end_charpos)); + ++glyph) + { + /* BEFORE_STRING or AFTER_STRING are only relevant if + they are present at buffer positions between + START_CHARPOS and END_CHARPOS. */ + if (EQ (glyph->object, before_string)) + { + pos = string_buffer_position (w, before_string, + start_charpos); + if (pos && pos >= start_charpos && pos < end_charpos) + break; + } + else if (EQ (glyph->object, after_string)) + { + pos = string_buffer_position (w, after_string, end_charpos); + if (pos && pos >= start_charpos && pos < end_charpos) + break; + } + x += glyph->pixel_width; + } + dpyinfo->mouse_face_beg_x = x; + dpyinfo->mouse_face_beg_col = glyph - row->glyphs[TEXT_AREA]; + } + else + { + /* FIXME! */ + } } /* Find the last highlighted glyph. */ @@ -23931,60 +23976,54 @@ mouse_face_from_buffer_pos (Lisp_Object window, row = next; } - glyph = row->glyphs[TEXT_AREA]; - end = glyph + row->used[TEXT_AREA]; - x = row->x; dpyinfo->mouse_face_end_y = row->y; dpyinfo->mouse_face_end_row = MATRIX_ROW_VPOS (row, w->current_matrix); - /* Skip truncation glyphs at the start of the row. */ - if (row->displays_text_p) - for (; glyph < end - && INTEGERP (glyph->object) - && glyph->charpos < 0; - ++glyph) - x += glyph->pixel_width; - - /* Scan the glyph row, stopping at END_CHARPOS or when we encounter - AFTER_STRING. */ - for (; glyph < end - && !INTEGERP (glyph->object) - && !EQ (glyph->object, after_string) - && !(BUFFERP (glyph->object) && glyph->charpos >= end_charpos); - ++glyph) - x += glyph->pixel_width; - - /* If we found AFTER_STRING, consume it and stop. */ - if (EQ (glyph->object, after_string)) + if (!row->reversed_p) { - for (; EQ (glyph->object, after_string) && glyph < end; ++glyph) + /* Skip truncation and continuation glyphs near the end of the + row, and also blanks and stretch glyphs inserted by + extend_face_to_end_of_line. */ + while (end > glyph + && INTEGERP ((end - 1)->object) + && (end - 1)->charpos <= 0) + --end; + /* Scan the rest of the glyph row from the end, looking for the + first glyph that comes from BEFORE_STRING, AFTER_STRING, or + DISPLAY_STRING, or whose position is between START_CHARPOS + and END_CHARPOS */ + for (--end; + end > glyph + && !INTEGERP (end->object) + && !EQ (end->object, display_string) + && !(BUFFERP (end->object) + && (end->charpos >= start_charpos + && end->charpos < end_charpos)); + --end) + { + /* BEFORE_STRING or AFTER_STRING are only relevant if + they are present at buffer positions between + START_CHARPOS and END_CHARPOS. */ + if (EQ (end->object, before_string)) + { + pos = string_buffer_position (w, before_string, start_charpos); + if (pos && pos >= start_charpos && pos < end_charpos) + break; + } + else if (EQ (end->object, after_string)) + { + pos = string_buffer_position (w, after_string, end_charpos); + if (pos && pos >= start_charpos && pos < end_charpos) + break; + } + } + /* Find the X coordinate of the last glyph to be highlighted. */ + for (; glyph <= end; ++glyph) x += glyph->pixel_width; } else { - /* If there's no after-string, we must check if we overshot, - which might be the case if we stopped after a string glyph. - That glyph may belong to a before-string or display-string - associated with the end position, which must not be - highlighted. */ - Lisp_Object prev_object; - EMACS_INT pos; - - while (glyph > row->glyphs[TEXT_AREA]) - { - prev_object = (glyph - 1)->object; - if (!STRINGP (prev_object) || EQ (prev_object, display_string)) - break; - - pos = string_buffer_position (w, prev_object, end_charpos); - if (pos && pos < end_charpos) - break; - - for (; glyph > row->glyphs[TEXT_AREA] - && EQ ((glyph - 1)->object, prev_object); - --glyph) - x -= (glyph - 1)->pixel_width; - } + /* FIXME! */ } dpyinfo->mouse_face_end_x = x; -- cgit v1.2.1 From 5b635ce2ac794ad3f8c74ea545bce73c8d574c0d Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 28 Aug 2010 12:32:44 +0300 Subject: Fix L2R code using bug #1220 as a test case. xdisp.c (mouse_face_from_buffer_pos): before_string and after_string are also relevant when they come from an overlay. --- src/xdisp.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 7fcbab718b1..c6d441fa6c1 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -23897,7 +23897,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, between START_CHARPOS and END_CHARPOS, and highlight all the glyphs between those two. This may cover more than just the text between START_CHARPOS and END_CHARPOS if the range of - characters strides the the bidi level boundary, e.g. if the + characters strides the bidi level boundary, e.g. if the beginning is in R2L text while the end is in L2R text or vice versa. */ if (!row->reversed_p) @@ -23929,18 +23929,21 @@ mouse_face_from_buffer_pos (Lisp_Object window, { /* BEFORE_STRING or AFTER_STRING are only relevant if they are present at buffer positions between - START_CHARPOS and END_CHARPOS. */ + START_CHARPOS and END_CHARPOS, or if they come from + an overlay. */ if (EQ (glyph->object, before_string)) { pos = string_buffer_position (w, before_string, start_charpos); - if (pos && pos >= start_charpos && pos < end_charpos) + /* If pos == 0, it means before_string came from an + overlay, not from a buffer position. */ + if (!pos || pos >= start_charpos && pos < end_charpos) break; } else if (EQ (glyph->object, after_string)) { pos = string_buffer_position (w, after_string, end_charpos); - if (pos && pos >= start_charpos && pos < end_charpos) + if (!pos || pos >= start_charpos && pos < end_charpos) break; } x += glyph->pixel_width; @@ -24001,19 +24004,19 @@ mouse_face_from_buffer_pos (Lisp_Object window, && end->charpos < end_charpos)); --end) { - /* BEFORE_STRING or AFTER_STRING are only relevant if - they are present at buffer positions between - START_CHARPOS and END_CHARPOS. */ + /* BEFORE_STRING or AFTER_STRING are only relevant if they + are present at buffer positions between START_CHARPOS and + END_CHARPOS, or if they come from an overlay. */ if (EQ (end->object, before_string)) { pos = string_buffer_position (w, before_string, start_charpos); - if (pos && pos >= start_charpos && pos < end_charpos) + if (!pos || pos >= start_charpos && pos < end_charpos) break; } else if (EQ (end->object, after_string)) { pos = string_buffer_position (w, after_string, end_charpos); - if (pos && pos >= start_charpos && pos < end_charpos) + if (!pos || pos >= start_charpos && pos < end_charpos) break; } } -- cgit v1.2.1 From ed5369474acbac87214b6b8c35b9bd047115e582 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 28 Aug 2010 14:09:02 +0300 Subject: Support R2L rows. Continued lines still don't work correctly. xdisp.c (mouse_face_from_buffer_pos): Fix code using bug#1220 as test case. Implement highlight for R2L rows. --- src/xdisp.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 111 insertions(+), 7 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index c6d441fa6c1..296fe5d2c59 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -23916,9 +23916,10 @@ mouse_face_from_buffer_pos (Lisp_Object window, ++glyph) x += glyph->pixel_width; - /* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING, - or DISPLAY_STRING, and the first glyph whose position is - between START_CHARPOS and END_CHARPOS. */ + /* Scan the glyph row, looking for BEFORE_STRING, + AFTER_STRING, or DISPLAY_STRING, and the first glyph from + buffer whose position is between START_CHARPOS and + END_CHARPOS. */ for (; glyph < end && !INTEGERP (glyph->object) && !EQ (glyph->object, display_string) @@ -23953,7 +23954,64 @@ mouse_face_from_buffer_pos (Lisp_Object window, } else { - /* FIXME! */ + /* This row is in a right to left paragraph. Scan it right + to left. */ + struct glyph *g; + + end = row->glyphs[TEXT_AREA] - 1; + glyph = end + row->used[TEXT_AREA]; + + /* Skip truncation glyphs at the start of the glyph row. */ + if (row->displays_text_p) + for (; glyph > end + && INTEGERP (glyph->object) + && glyph->charpos < 0; + --glyph) + ; + + /* Scan the glyph row, looking for BEFORE_STRING, + AFTER_STRING, or DISPLAY_STRING, and the first glyph from + buffer whose position is between START_CHARPOS and + END_CHARPOS. */ + for (; glyph > end + && !INTEGERP (glyph->object) + && !EQ (glyph->object, display_string) + && !(BUFFERP (glyph->object) + && (glyph->charpos >= start_charpos + && glyph->charpos < end_charpos)); + --glyph) + { + /* BEFORE_STRING or AFTER_STRING are only relevant if + they are present at buffer positions between + START_CHARPOS and END_CHARPOS, or if they come from + an overlay. */ + if (EQ (glyph->object, before_string)) + { + pos = string_buffer_position (w, before_string, + start_charpos); + /* If pos == 0, it means before_string came from an + overlay, not from a buffer position. */ + if (!pos || pos >= start_charpos && pos < end_charpos) + break; + } + else if (EQ (glyph->object, after_string)) + { + pos = string_buffer_position (w, after_string, end_charpos); + if (!pos || pos >= start_charpos && pos < end_charpos) + break; + } + } + + /* Mouse highlight uses the screen geometry, which is left + to right even in R2L paragraphs. Therefore, for R2L + paragraphs, the "first" highlighted glyph actually + determines the _end_ column and x of the highlighted + area. */ + glyph++; /* first glyph beyond the highlighted area */ + for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++) + x += g->pixel_width; + dpyinfo->mouse_face_end_x = x; + dpyinfo->mouse_face_end_col = glyph - row->glyphs[TEXT_AREA]; } } @@ -24023,14 +24081,60 @@ mouse_face_from_buffer_pos (Lisp_Object window, /* Find the X coordinate of the last glyph to be highlighted. */ for (; glyph <= end; ++glyph) x += glyph->pixel_width; + + dpyinfo->mouse_face_end_x = x; + dpyinfo->mouse_face_end_col = glyph - row->glyphs[TEXT_AREA]; } else { - /* FIXME! */ + /* Skip truncation and continuation glyphs near the end of the + row, and also blanks and stretch glyphs inserted by + extend_face_to_end_of_line. */ + x = row->x; + end++; + while (end < glyph + && INTEGERP (end->object) + && end->charpos <= 0) + { + x += end->pixel_width; + ++end; + } + /* Scan the rest of the glyph row from the end, looking for the + first glyph that comes from BEFORE_STRING, AFTER_STRING, or + DISPLAY_STRING, or whose position is between START_CHARPOS + and END_CHARPOS */ + for ( ; + end < glyph + && !INTEGERP (end->object) + && !EQ (end->object, display_string) + && !(BUFFERP (end->object) + && (end->charpos >= start_charpos + && end->charpos < end_charpos)); + ++end) + { + /* BEFORE_STRING or AFTER_STRING are only relevant if they + are present at buffer positions between START_CHARPOS and + END_CHARPOS, or if they come from an overlay. */ + if (EQ (end->object, before_string)) + { + pos = string_buffer_position (w, before_string, start_charpos); + if (!pos || pos >= start_charpos && pos < end_charpos) + break; + } + else if (EQ (end->object, after_string)) + { + pos = string_buffer_position (w, after_string, end_charpos); + if (!pos || pos >= start_charpos && pos < end_charpos) + break; + } + x += end->pixel_width; + } + /* In the left-to-right screen geometry, END is actually the + _beginning_ of the highlighted area for R2L paragraphs. */ + dpyinfo->mouse_face_beg_x = x; + dpyinfo->mouse_face_beg_col = end - row->glyphs[TEXT_AREA]; } - dpyinfo->mouse_face_end_x = x; - dpyinfo->mouse_face_end_col = glyph - row->glyphs[TEXT_AREA]; dpyinfo->mouse_face_window = window; dpyinfo->mouse_face_face_id = face_at_buffer_position (w, mouse_charpos, 0, 0, &ignore, -- cgit v1.2.1 From ee1ed7fcaedc43a9f8ddcdbeaf2165c3d413ddc3 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 28 Aug 2010 15:36:19 +0300 Subject: Support L2R continued lines. xdisp.c (mouse_face_from_buffer_pos): Fix the case of continued L2R lines. --- src/xdisp.c | 52 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 9 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 296fe5d2c59..92d3dbea319 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -23837,7 +23837,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, { struct window *w = XWINDOW (window); struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); - struct glyph_row *row; + struct glyph_row *row, *r; struct glyph *glyph, *end; EMACS_INT ignore, pos; int x; @@ -24016,10 +24016,10 @@ mouse_face_from_buffer_pos (Lisp_Object window, } /* Find the last highlighted glyph. */ - row = row_containing_pos (w, end_charpos, first, NULL, 0); - if (row == NULL) + r = row_containing_pos (w, end_charpos, first, NULL, 0); + if (r == NULL) { - row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); + r = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); dpyinfo->mouse_face_past_end = 1; } else if (!NILP (after_string)) @@ -24029,12 +24029,37 @@ mouse_face_from_buffer_pos (Lisp_Object window, struct glyph_row *last = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); - for (next = row + 1; + for (next = r + 1; next <= last && next->used[TEXT_AREA] > 0 && EQ (next->glyphs[TEXT_AREA]->object, after_string); ++next) - row = next; + r = next; + } + + /* If the highlight ends in a different row, compute GLYPH and END + for the end row. */ + if (r != row) + { + /* If the beginning row was an R2L row, we actually computed + above the beginning of the highlighted area, not its end. */ + if (row->reversed_p) + { + dpyinfo->mouse_face_beg_x = dpyinfo->mouse_face_end_x; + dpyinfo->mouse_face_beg_col = dpyinfo->mouse_face_end_col; + } + if (!r->reversed_p) + { + glyph = r->glyphs[TEXT_AREA]; + end = glyph + r->used[TEXT_AREA]; + x = r->x; + } + else + { + end = r->glyphs[TEXT_AREA] - 1; + glyph = end + r->used[TEXT_AREA]; + } + row = r; } dpyinfo->mouse_face_end_y = row->y; @@ -24130,9 +24155,18 @@ mouse_face_from_buffer_pos (Lisp_Object window, x += end->pixel_width; } /* In the left-to-right screen geometry, END is actually the - _beginning_ of the highlighted area for R2L paragraphs. */ - dpyinfo->mouse_face_beg_x = x; - dpyinfo->mouse_face_beg_col = end - row->glyphs[TEXT_AREA]; + _beginning_ of the highlighted area for R2L paragraphs, if + the highlight begins and ends in the same row. */ + if (dpyinfo->mouse_face_end_row == dpyinfo->mouse_face_beg_row) + { + dpyinfo->mouse_face_beg_x = x; + dpyinfo->mouse_face_beg_col = end - row->glyphs[TEXT_AREA]; + } + else + { + dpyinfo->mouse_face_end_x = x; + dpyinfo->mouse_face_end_col = end - row->glyphs[TEXT_AREA]; + } } dpyinfo->mouse_face_window = window; -- cgit v1.2.1 From 11b9a75013bcbc3707cf31ed4c4911067aa45820 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 28 Aug 2010 17:12:36 +0300 Subject: Fix mouse highlight in continued R2L lines. xdisp.c (show_mouse_face): Support drawing highlighted R2L lines. --- src/xdisp.c | 74 +++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 43 insertions(+), 31 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 92d3dbea319..3a99435123a 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -23711,8 +23711,30 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) /* For all but the first row, the highlight starts at column 0. */ if (row == first) { - start_hpos = dpyinfo->mouse_face_beg_col; - start_x = dpyinfo->mouse_face_beg_x; + /* R2L rows have BEG and END in reversed order, but the + screen drawing geometry is always left to right. So + we need to mirror the beginning and end of the + highlighted area in R2L rows. */ + if (!row->reversed_p) + { + start_hpos = dpyinfo->mouse_face_beg_col; + start_x = dpyinfo->mouse_face_beg_x; + } + else if (row == last) + { + start_hpos = dpyinfo->mouse_face_end_col; + start_x = dpyinfo->mouse_face_end_x; + } + else + { + start_hpos = 0; + start_x = 0; + } + } + else if (row->reversed_p && row == last) + { + start_hpos = dpyinfo->mouse_face_end_col; + start_x = dpyinfo->mouse_face_end_x; } else { @@ -23721,7 +23743,20 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) } if (row == last) - end_hpos = dpyinfo->mouse_face_end_col; + { + if (!row->reversed_p) + end_hpos = dpyinfo->mouse_face_end_col; + else if (row == first) + end_hpos = dpyinfo->mouse_face_beg_col; + else + { + end_hpos = row->used[TEXT_AREA]; + if (draw == DRAW_NORMAL_TEXT) + row->fill_line_p = 1; /* Clear to end of line */ + } + } + else if (row->reversed_p && row == first) + end_hpos = dpyinfo->mouse_face_beg_col; else { end_hpos = row->used[TEXT_AREA]; @@ -24002,16 +24037,11 @@ mouse_face_from_buffer_pos (Lisp_Object window, } } - /* Mouse highlight uses the screen geometry, which is left - to right even in R2L paragraphs. Therefore, for R2L - paragraphs, the "first" highlighted glyph actually - determines the _end_ column and x of the highlighted - area. */ - glyph++; /* first glyph beyond the highlighted area */ + glyph++; /* first glyph to the right of the highlighted area */ for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++) x += g->pixel_width; - dpyinfo->mouse_face_end_x = x; - dpyinfo->mouse_face_end_col = glyph - row->glyphs[TEXT_AREA]; + dpyinfo->mouse_face_beg_x = x; + dpyinfo->mouse_face_beg_col = glyph - row->glyphs[TEXT_AREA]; } } @@ -24041,13 +24071,6 @@ mouse_face_from_buffer_pos (Lisp_Object window, for the end row. */ if (r != row) { - /* If the beginning row was an R2L row, we actually computed - above the beginning of the highlighted area, not its end. */ - if (row->reversed_p) - { - dpyinfo->mouse_face_beg_x = dpyinfo->mouse_face_end_x; - dpyinfo->mouse_face_beg_col = dpyinfo->mouse_face_end_col; - } if (!r->reversed_p) { glyph = r->glyphs[TEXT_AREA]; @@ -24154,19 +24177,8 @@ mouse_face_from_buffer_pos (Lisp_Object window, } x += end->pixel_width; } - /* In the left-to-right screen geometry, END is actually the - _beginning_ of the highlighted area for R2L paragraphs, if - the highlight begins and ends in the same row. */ - if (dpyinfo->mouse_face_end_row == dpyinfo->mouse_face_beg_row) - { - dpyinfo->mouse_face_beg_x = x; - dpyinfo->mouse_face_beg_col = end - row->glyphs[TEXT_AREA]; - } - else - { - dpyinfo->mouse_face_end_x = x; - dpyinfo->mouse_face_end_col = end - row->glyphs[TEXT_AREA]; - } + dpyinfo->mouse_face_end_x = x; + dpyinfo->mouse_face_end_col = end - row->glyphs[TEXT_AREA]; } dpyinfo->mouse_face_window = window; -- cgit v1.2.1 From bcf6242f1c499ef6b5f6ba179a3ab273846ddc64 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 28 Aug 2010 18:23:10 +0300 Subject: Clean up mouse highlight in R2L lines. xdisp.c (coords_in_mouse_face_p): New function, bidi-aware. (cursor_in_mouse_face_p, note_mouse_highlight, erase_phys_cursor): Call it instead of comparing with mouse-face members of dpyinfo. (note_mode_line_or_margin_highlight): Fix confusingly swapped usage of hpos and vpos. --- src/xdisp.c | 93 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 49 insertions(+), 44 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 3a99435123a..40ba72a18bc 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1082,6 +1082,7 @@ static void notice_overwritten_cursor (struct window *, int, int, int, int); static void append_stretch_glyph (struct it *, Lisp_Object, int, int, int); +static int coords_in_mouse_face_p (struct window *, int, int); @@ -23482,13 +23483,7 @@ erase_phys_cursor (struct window *w) /* If the cursor is in the mouse face area, redisplay that when we clear the cursor. */ if (! NILP (dpyinfo->mouse_face_window) - && w == XWINDOW (dpyinfo->mouse_face_window) - && (vpos > dpyinfo->mouse_face_beg_row - || (vpos == dpyinfo->mouse_face_beg_row - && hpos >= dpyinfo->mouse_face_beg_col)) - && (vpos < dpyinfo->mouse_face_end_row - || (vpos == dpyinfo->mouse_face_end_row - && hpos < dpyinfo->mouse_face_end_col)) + && coords_in_mouse_face_p (w, hpos, vpos) /* Don't redraw the cursor's spot in mouse face if it is at the end of a line (on a newline). The cursor appears there, but mouse highlighting does not. */ @@ -23819,6 +23814,43 @@ clear_mouse_face (Display_Info *dpyinfo) return cleared; } +/* Return non-zero if the coordinates HPOS and VPOS on windows W are + within the mouse face on that window. */ +static int +coords_in_mouse_face_p (struct window *w, int hpos, int vpos) +{ + Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame)); + + /* Quickly resolve the easy cases. */ + if (!(WINDOWP (dpyinfo->mouse_face_window) + && XWINDOW (dpyinfo->mouse_face_window) == w)) + return 0; + if (vpos < dpyinfo->mouse_face_beg_row + || vpos > dpyinfo->mouse_face_end_row) + return 0; + if (vpos > dpyinfo->mouse_face_beg_row + && vpos < dpyinfo->mouse_face_end_row) + return 1; + + if (MATRIX_ROW (w->current_matrix, vpos)->reversed_p) + { + if ((vpos == dpyinfo->mouse_face_beg_row + && hpos <= dpyinfo->mouse_face_beg_col) + || (vpos == dpyinfo->mouse_face_end_row + && hpos > dpyinfo->mouse_face_end_col)) + return 1; + } + else + { + if ((vpos == dpyinfo->mouse_face_beg_row + && hpos >= dpyinfo->mouse_face_beg_col) + || (vpos == dpyinfo->mouse_face_end_row + && hpos < dpyinfo->mouse_face_end_col)) + return 1; + } + return 0; +} + /* EXPORT: Non-zero if physical cursor of window W is within mouse face. */ @@ -23826,30 +23858,10 @@ clear_mouse_face (Display_Info *dpyinfo) int cursor_in_mouse_face_p (struct window *w) { - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame)); - int in_mouse_face = 0; - - if (WINDOWP (dpyinfo->mouse_face_window) - && XWINDOW (dpyinfo->mouse_face_window) == w) - { - int hpos = w->phys_cursor.hpos; - int vpos = w->phys_cursor.vpos; - - if (vpos >= dpyinfo->mouse_face_beg_row - && vpos <= dpyinfo->mouse_face_end_row - && (vpos > dpyinfo->mouse_face_beg_row - || hpos >= dpyinfo->mouse_face_beg_col) - && (vpos < dpyinfo->mouse_face_end_row - || hpos < dpyinfo->mouse_face_end_col - || dpyinfo->mouse_face_past_end)) - in_mouse_face = 1; - } - - return in_mouse_face; + return coords_in_mouse_face_p (w, w->phys_cursor.hpos, w->phys_cursor.vpos); } - /* This function sets the mouse_face_* elements of DPYINFO, assuming the mouse cursor is on a glyph with buffer charpos MOUSE_CHARPOS in @@ -24632,29 +24644,29 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, total_pixel_width += tmp_glyph->pixel_width; /* Pre calculation of re-rendering position */ - vpos = (x - gpos); - hpos = (area == ON_MODE_LINE + 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 ( EQ (window, dpyinfo->mouse_face_window) - && dpyinfo->mouse_face_beg_col <= vpos - && vpos < dpyinfo->mouse_face_end_col - && dpyinfo->mouse_face_beg_row == hpos ) + && dpyinfo->mouse_face_beg_col <= hpos + && hpos < dpyinfo->mouse_face_end_col + && dpyinfo->mouse_face_beg_row == vpos ) return; if (clear_mouse_face (dpyinfo)) cursor = No_Cursor; - dpyinfo->mouse_face_beg_col = vpos; - dpyinfo->mouse_face_beg_row = hpos; + 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 = vpos + gseq_length; + dpyinfo->mouse_face_end_col = hpos + gseq_length; dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_beg_row; dpyinfo->mouse_face_end_x = 0; @@ -24879,14 +24891,7 @@ note_mouse_highlight (struct frame *f, int x, int y) else noverlays = 0; - same_region = (EQ (window, dpyinfo->mouse_face_window) - && vpos >= dpyinfo->mouse_face_beg_row - && vpos <= dpyinfo->mouse_face_end_row - && (vpos > dpyinfo->mouse_face_beg_row - || hpos >= dpyinfo->mouse_face_beg_col) - && (vpos < dpyinfo->mouse_face_end_row - || hpos < dpyinfo->mouse_face_end_col - || dpyinfo->mouse_face_past_end)); + same_region = coords_in_mouse_face_p (w, hpos, vpos); if (same_region) cursor = No_Cursor; -- cgit v1.2.1 From f0599d9280f043b490bbe007297a4e39ad3dbe38 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 2 Oct 2010 13:48:56 +0200 Subject: Fix minor bugs in mouse highlight. xdisp.c (coords_in_mouse_face_p): Fix the conditions for when mouse_face_beg_row and mouse_face_end_row are equal. (note_mouse_highlight): Clear mouse highlight when mouse pointer is in a R2L row on the stretch glyph that stands for no text beyond the line end. --- src/xdisp.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 40ba72a18bc..e19c26cbc19 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -23832,20 +23832,30 @@ coords_in_mouse_face_p (struct window *w, int hpos, int vpos) && vpos < dpyinfo->mouse_face_end_row) return 1; - if (MATRIX_ROW (w->current_matrix, vpos)->reversed_p) + if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p) { - if ((vpos == dpyinfo->mouse_face_beg_row - && hpos <= dpyinfo->mouse_face_beg_col) - || (vpos == dpyinfo->mouse_face_end_row - && hpos > dpyinfo->mouse_face_end_col)) + if (dpyinfo->mouse_face_beg_row == dpyinfo->mouse_face_end_row) + { + if (dpyinfo->mouse_face_beg_col <= hpos && hpos < dpyinfo->mouse_face_end_col) + return 1; + } + else if ((vpos == dpyinfo->mouse_face_beg_row + && hpos >= dpyinfo->mouse_face_beg_col) + || (vpos == dpyinfo->mouse_face_end_row + && hpos < dpyinfo->mouse_face_end_col)) return 1; } else { - if ((vpos == dpyinfo->mouse_face_beg_row - && hpos >= dpyinfo->mouse_face_beg_col) - || (vpos == dpyinfo->mouse_face_end_row - && hpos < dpyinfo->mouse_face_end_col)) + if (dpyinfo->mouse_face_beg_row == dpyinfo->mouse_face_end_row) + { + if (dpyinfo->mouse_face_end_col < hpos && hpos <= dpyinfo->mouse_face_beg_col) + return 1; + } + else if ((vpos == dpyinfo->mouse_face_beg_row + && hpos <= dpyinfo->mouse_face_beg_col) + || (vpos == dpyinfo->mouse_face_end_row + && hpos > dpyinfo->mouse_face_end_col)) return 1; } return 0; @@ -24846,7 +24856,15 @@ note_mouse_highlight (struct frame *f, int x, int y) /* Clear mouse face if X/Y not over text. */ if (glyph == NULL || area != TEXT_AREA - || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p) + || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p + /* R2L rows have a stretch glyph at their front, which + stands for no text, whereas L2R rows have no glyphs at + all beyond the end of text. Treat such stretch glyphs as + NULL glyphs in L2R rows. */ + || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p + && glyph == MATRIX_ROW (w->current_matrix, vpos)->glyphs[TEXT_AREA] + && glyph->type == STRETCH_GLYPH + && glyph->avoid_cursor_p)) { if (clear_mouse_face (dpyinfo)) cursor = No_Cursor; -- cgit v1.2.1 From c183caeafc29329f2676f8bdeca920be481944cb Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 2 Oct 2010 17:05:20 +0200 Subject: 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. --- src/xdisp.c | 328 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 167 insertions(+), 161 deletions(-) (limited to 'src/xdisp.c') 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, { struct glyph *g; - if (NILP (XBUFFER (w->buffer)->bidi_display_reordering)) + if (NILP (XBUFFER (w->buffer)->bidi_display_reordering) + || (!best_row && !row->continued_p)) return row; /* In bidi-reordered rows, there could be several rows - occluding point. We need to find the one which fits + occluding point, all of them belonging to the same + continued line. We need to find the row which fits CHARPOS the best. */ for (g = row->glyphs[TEXT_AREA]; 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, { mindif = eabs (g->charpos - charpos); best_row = row; + /* Exact match always wins. */ + if (mindif == 0) + return best_row; } } } } - else if (best_row) + else if (best_row && !row->continued_p) return best_row; ++row; } @@ -23894,7 +23899,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, { struct window *w = XWINDOW (window); struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); - struct glyph_row *row, *r; + struct glyph_row *r1, *r2; struct glyph *glyph, *end; EMACS_INT ignore, pos; int x; @@ -23903,7 +23908,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, xassert (NILP (before_string) || STRINGP (before_string)); xassert (NILP (after_string) || STRINGP (after_string)); - /* Find the first highlighted glyph. */ + /* Find the row with START_CHARPOS. */ if (start_charpos < MATRIX_ROW_START_CHARPOS (first) && (NILP (XBUFFER (w->buffer)->bidi_display_reordering) || row_containing_pos (w, start_charpos, first, NULL, 0) == NULL)) @@ -23915,20 +23920,16 @@ mouse_face_from_buffer_pos (Lisp_Object window, } else { - /* FIXME: this assumes that START_CHARPOS is in beg_row. This - is false for reordered lines that are continued. Need to - compute beg_row and end_row separately from beg_col and - end_col. */ - row = row_containing_pos (w, start_charpos, first, NULL, 0); - if (row == NULL) - row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); + r1 = row_containing_pos (w, start_charpos, first, NULL, 0); + if (r1 == NULL) + r1 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); /* If the before-string or display-string contains newlines, row_containing_pos skips to its last row. Move back. */ if (!NILP (before_string) || !NILP (display_string)) { struct glyph_row *prev; - while ((prev = row - 1, prev >= first) + while ((prev = r1 - 1, prev >= first) && MATRIX_ROW_END_CHARPOS (prev) == start_charpos && prev->used[TEXT_AREA] > 0) { @@ -23939,139 +23940,16 @@ mouse_face_from_buffer_pos (Lisp_Object window, || !(EQ (glyph->object, before_string) || EQ (glyph->object, display_string))) break; - row = prev; + r1 = prev; } } - - dpyinfo->mouse_face_beg_y = row->y; - dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (row, w->current_matrix); - - /* For a bidi-reordered row, the positions of BEFORE_STRING, - AFTER_STRING, DISPLAY_STRING, START_CHARPOS, and END_CHARPOS - could be anywhere in the row and in any order. The strategy - below is to find the leftmost and the rightmost glyph that - belongs to either of these 3 strings, or whose position is - between START_CHARPOS and END_CHARPOS, and highlight all the - glyphs between those two. This may cover more than just the - text between START_CHARPOS and END_CHARPOS if the range of - characters strides the bidi level boundary, e.g. if the - beginning is in R2L text while the end is in L2R text or vice - versa. */ - if (!row->reversed_p) - { - /* This row is in a left to right paragraph. Scan it left - to right. */ - glyph = row->glyphs[TEXT_AREA]; - end = glyph + row->used[TEXT_AREA]; - x = row->x; - - /* Skip truncation glyphs at the start of the glyph row. */ - if (row->displays_text_p) - for (; glyph < end - && INTEGERP (glyph->object) - && glyph->charpos < 0; - ++glyph) - x += glyph->pixel_width; - - /* Scan the glyph row, looking for BEFORE_STRING, - AFTER_STRING, or DISPLAY_STRING, and the first glyph from - buffer whose position is between START_CHARPOS and - END_CHARPOS. */ - for (; glyph < end - && !INTEGERP (glyph->object) - && !EQ (glyph->object, display_string) - && !(BUFFERP (glyph->object) - && (glyph->charpos >= start_charpos - && glyph->charpos < end_charpos)); - ++glyph) - { - /* BEFORE_STRING or AFTER_STRING are only relevant if - they are present at buffer positions between - START_CHARPOS and END_CHARPOS, or if they come from - an overlay. */ - if (EQ (glyph->object, before_string)) - { - pos = string_buffer_position (w, before_string, - start_charpos); - /* If pos == 0, it means before_string came from an - overlay, not from a buffer position. */ - if (!pos || pos >= start_charpos && pos < end_charpos) - break; - } - else if (EQ (glyph->object, after_string)) - { - pos = string_buffer_position (w, after_string, end_charpos); - if (!pos || pos >= start_charpos && pos < end_charpos) - break; - } - x += glyph->pixel_width; - } - dpyinfo->mouse_face_beg_x = x; - dpyinfo->mouse_face_beg_col = glyph - row->glyphs[TEXT_AREA]; - } - else - { - /* This row is in a right to left paragraph. Scan it right - to left. */ - struct glyph *g; - - end = row->glyphs[TEXT_AREA] - 1; - glyph = end + row->used[TEXT_AREA]; - - /* Skip truncation glyphs at the start of the glyph row. */ - if (row->displays_text_p) - for (; glyph > end - && INTEGERP (glyph->object) - && glyph->charpos < 0; - --glyph) - ; - - /* Scan the glyph row, looking for BEFORE_STRING, - AFTER_STRING, or DISPLAY_STRING, and the first glyph from - buffer whose position is between START_CHARPOS and - END_CHARPOS. */ - for (; glyph > end - && !INTEGERP (glyph->object) - && !EQ (glyph->object, display_string) - && !(BUFFERP (glyph->object) - && (glyph->charpos >= start_charpos - && glyph->charpos < end_charpos)); - --glyph) - { - /* BEFORE_STRING or AFTER_STRING are only relevant if - they are present at buffer positions between - START_CHARPOS and END_CHARPOS, or if they come from - an overlay. */ - if (EQ (glyph->object, before_string)) - { - pos = string_buffer_position (w, before_string, - start_charpos); - /* If pos == 0, it means before_string came from an - overlay, not from a buffer position. */ - if (!pos || pos >= start_charpos && pos < end_charpos) - break; - } - else if (EQ (glyph->object, after_string)) - { - pos = string_buffer_position (w, after_string, end_charpos); - if (!pos || pos >= start_charpos && pos < end_charpos) - break; - } - } - - glyph++; /* first glyph to the right of the highlighted area */ - for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++) - x += g->pixel_width; - dpyinfo->mouse_face_beg_x = x; - dpyinfo->mouse_face_beg_col = glyph - row->glyphs[TEXT_AREA]; - } } - /* Find the last highlighted glyph. */ - r = row_containing_pos (w, end_charpos, first, NULL, 0); - if (r == NULL) + /* Find the row with END_CHARPOS. */ + r2 = row_containing_pos (w, end_charpos, first, NULL, 0); + if (r2 == NULL) { - r = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); + r2 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); dpyinfo->mouse_face_past_end = 1; } else if (!NILP (after_string)) @@ -24081,36 +23959,164 @@ mouse_face_from_buffer_pos (Lisp_Object window, struct glyph_row *last = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); - for (next = r + 1; + for (next = r2 + 1; next <= last && next->used[TEXT_AREA] > 0 && EQ (next->glyphs[TEXT_AREA]->object, after_string); ++next) - r = next; + r2 = next; + } + + /* The rest of the display engine assumes that mouse_face_beg_row is + either above below mouse_face_end_row or identical to it. But + with bidi-reordered continued lines, the row for START_CHARPOS + could be below the row for END_CHARPOS. If so, swap the rows and + store them in correct order. */ + if (r1->y > r2->y) + { + struct glyph_row *tem = r2; + + r2 = r1; + r1 = tem; + } + dpyinfo->mouse_face_beg_y = r1->y; + dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix); + dpyinfo->mouse_face_end_y = r2->y; + dpyinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix); + + /* For a bidi-reordered row, the positions of BEFORE_STRING, + AFTER_STRING, DISPLAY_STRING, START_CHARPOS, and END_CHARPOS + could be anywhere in the row and in any order. The strategy + below is to find the leftmost and the rightmost glyph that + belongs to either of these 3 strings, or whose position is + between START_CHARPOS and END_CHARPOS, and highlight all the + glyphs between those two. This may cover more than just the text + between START_CHARPOS and END_CHARPOS if the range of characters + strides the bidi level boundary, e.g. if the beginning is in R2L + text while the end is in L2R text or vice versa. */ + if (!r1->reversed_p) + { + /* This row is in a left to right paragraph. Scan it left to + right. */ + glyph = r1->glyphs[TEXT_AREA]; + end = glyph + r1->used[TEXT_AREA]; + x = r1->x; + + /* Skip truncation glyphs at the start of the glyph row. */ + if (r1->displays_text_p) + for (; glyph < end + && INTEGERP (glyph->object) + && glyph->charpos < 0; + ++glyph) + x += glyph->pixel_width; + + /* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING, + or DISPLAY_STRING, and the first glyph from buffer whose + position is between START_CHARPOS and END_CHARPOS. */ + for (; glyph < end + && !INTEGERP (glyph->object) + && !EQ (glyph->object, display_string) + && !(BUFFERP (glyph->object) + && (glyph->charpos >= start_charpos + && glyph->charpos < end_charpos)); + ++glyph) + { + /* BEFORE_STRING or AFTER_STRING are only relevant if they + are present at buffer positions between START_CHARPOS and + END_CHARPOS, or if they come from an overlay. */ + if (EQ (glyph->object, before_string)) + { + pos = string_buffer_position (w, before_string, + start_charpos); + /* If pos == 0, it means before_string came from an + overlay, not from a buffer position. */ + if (!pos || pos >= start_charpos && pos < end_charpos) + break; + } + else if (EQ (glyph->object, after_string)) + { + pos = string_buffer_position (w, after_string, end_charpos); + if (!pos || pos >= start_charpos && pos < end_charpos) + break; + } + x += glyph->pixel_width; + } + dpyinfo->mouse_face_beg_x = x; + dpyinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA]; + } + else + { + /* This row is in a right to left paragraph. Scan it right to + left. */ + struct glyph *g; + + end = r1->glyphs[TEXT_AREA] - 1; + glyph = end + r1->used[TEXT_AREA]; + + /* Skip truncation glyphs at the start of the glyph row. */ + if (r1->displays_text_p) + for (; glyph > end + && INTEGERP (glyph->object) + && glyph->charpos < 0; + --glyph) + ; + + /* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING, + or DISPLAY_STRING, and the first glyph from buffer whose + position is between START_CHARPOS and END_CHARPOS. */ + for (; glyph > end + && !INTEGERP (glyph->object) + && !EQ (glyph->object, display_string) + && !(BUFFERP (glyph->object) + && (glyph->charpos >= start_charpos + && glyph->charpos < end_charpos)); + --glyph) + { + /* BEFORE_STRING or AFTER_STRING are only relevant if they + are present at buffer positions between START_CHARPOS and + END_CHARPOS, or if they come from an overlay. */ + if (EQ (glyph->object, before_string)) + { + pos = string_buffer_position (w, before_string, start_charpos); + /* If pos == 0, it means before_string came from an + overlay, not from a buffer position. */ + if (!pos || pos >= start_charpos && pos < end_charpos) + break; + } + else if (EQ (glyph->object, after_string)) + { + pos = string_buffer_position (w, after_string, end_charpos); + if (!pos || pos >= start_charpos && pos < end_charpos) + break; + } + } + + glyph++; /* first glyph to the right of the highlighted area */ + for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++) + x += g->pixel_width; + dpyinfo->mouse_face_beg_x = x; + dpyinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA]; } /* If the highlight ends in a different row, compute GLYPH and END - for the end row. */ - if (r != row) + for the end row. Otherwise, reuse the values computed above for + the row where the highlight begins. */ + if (r2 != r1) { - if (!r->reversed_p) + if (!r2->reversed_p) { - glyph = r->glyphs[TEXT_AREA]; - end = glyph + r->used[TEXT_AREA]; - x = r->x; + glyph = r2->glyphs[TEXT_AREA]; + end = glyph + r2->used[TEXT_AREA]; + x = r2->x; } else { - end = r->glyphs[TEXT_AREA] - 1; - glyph = end + r->used[TEXT_AREA]; + end = r2->glyphs[TEXT_AREA] - 1; + glyph = end + r2->used[TEXT_AREA]; } - row = r; } - dpyinfo->mouse_face_end_y = row->y; - dpyinfo->mouse_face_end_row = MATRIX_ROW_VPOS (row, w->current_matrix); - - if (!row->reversed_p) + if (!r2->reversed_p) { /* Skip truncation and continuation glyphs near the end of the row, and also blanks and stretch glyphs inserted by @@ -24153,14 +24159,14 @@ mouse_face_from_buffer_pos (Lisp_Object window, x += glyph->pixel_width; dpyinfo->mouse_face_end_x = x; - dpyinfo->mouse_face_end_col = glyph - row->glyphs[TEXT_AREA]; + dpyinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA]; } else { /* Skip truncation and continuation glyphs near the end of the row, and also blanks and stretch glyphs inserted by extend_face_to_end_of_line. */ - x = row->x; + x = r2->x; end++; while (end < glyph && INTEGERP (end->object) @@ -24200,7 +24206,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, x += end->pixel_width; } dpyinfo->mouse_face_end_x = x; - dpyinfo->mouse_face_end_col = end - row->glyphs[TEXT_AREA]; + dpyinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA]; } dpyinfo->mouse_face_window = window; @@ -24859,8 +24865,8 @@ note_mouse_highlight (struct frame *f, int x, int y) || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p /* R2L rows have a stretch glyph at their front, which stands for no text, whereas L2R rows have no glyphs at - all beyond the end of text. Treat such stretch glyphs as - NULL glyphs in L2R rows. */ + all beyond the end of text. Treat such stretch glyphs + like we do with NULL glyphs in L2R rows. */ || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p && glyph == MATRIX_ROW (w->current_matrix, vpos)->glyphs[TEXT_AREA] && glyph->type == STRETCH_GLYPH -- cgit v1.2.1 From 3e7fb5c0a57ce02042f568d8ca56d56a270987e6 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 2 Oct 2010 19:42:53 +0200 Subject: Fix beg_col calculation when painting from window start. xdisp.c (mouse_face_from_buffer_pos): Don't compute beg_col if already decided to paint from beginning of window. --- src/xdisp.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 9e65d8f1bb0..eeea4cb4333 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -23903,12 +23903,17 @@ mouse_face_from_buffer_pos (Lisp_Object window, struct glyph *glyph, *end; EMACS_INT ignore, pos; int x; + int beg_set = 0; xassert (NILP (display_string) || STRINGP (display_string)); xassert (NILP (before_string) || STRINGP (before_string)); xassert (NILP (after_string) || STRINGP (after_string)); /* Find the row with START_CHARPOS. */ + /* FIXME: Sometimes the caller gets "wise" and gives us the window + start position instead of the real start of the mouse face + property. This completely messes up the logic of finding the + beg_row and end_row. */ if (start_charpos < MATRIX_ROW_START_CHARPOS (first) && (NILP (XBUFFER (w->buffer)->bidi_display_reordering) || row_containing_pos (w, start_charpos, first, NULL, 0) == NULL)) @@ -23917,6 +23922,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (first, w->current_matrix); dpyinfo->mouse_face_beg_x = first->x; dpyinfo->mouse_face_beg_y = first->y; + beg_set = 1; } else { @@ -23994,7 +24000,9 @@ mouse_face_from_buffer_pos (Lisp_Object window, between START_CHARPOS and END_CHARPOS if the range of characters strides the bidi level boundary, e.g. if the beginning is in R2L text while the end is in L2R text or vice versa. */ - if (!r1->reversed_p) + if (beg_set) + ; + else if (!r1->reversed_p) { /* This row is in a left to right paragraph. Scan it left to right. */ -- cgit v1.2.1 From 4b77b066124bb20419c6eff1e1d9a8bac4d622ed Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 9 Oct 2010 18:37:15 +0200 Subject: Finished work on mouse_face_from_buffer_pos for bidi-reordered rows. Need lots of testing, including bug#1220. Next task: get rid of fast_find_position, call mouse_face_from_buffer_pos instead. xdisp.c (rows_from_pos_range): New function. (mouse_face_from_buffer_pos): Use it instead of calling row_containing_pos for START_CHARPOS and END_CHARPOS. (note_mouse_highlight): When bidi reordering is turned on in a buffer, call next-single-property-change and previous-single-property-change with last argument nil. --- src/xdisp.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 164 insertions(+), 47 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index eeea4cb4333..9f39046b1f5 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -23878,6 +23878,129 @@ cursor_in_mouse_face_p (struct window *w) +/* Find the glyph rows START_ROW and END_ROW of window W that display + characters between buffer positions START_CHARPOS and END_CHARPOS + (excluding END_CHARPOS). This is similar to row_containing_pos, + but is more accurate when bidi reordering makes buffer positions + change non-linearly with glyph rows. */ +static void +rows_from_pos_range (struct window *w, + EMACS_INT start_charpos, EMACS_INT end_charpos, + struct glyph_row **start, struct glyph_row **end) +{ + struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); + int last_y = window_text_bottom_y (w); + struct glyph_row *row; + + *start = NULL; + *end = NULL; + + while (!first->enabled_p + && first < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)) + first++; + + /* Find the START row. */ + for (row = first; + row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; + row++) + { + /* A row can potentially be the START row if the range of the + characters it displays intersects the range + [START_CHARPOS..END_CHARPOS). */ + if (! ((start_charpos < MATRIX_ROW_START_CHARPOS (row) + && end_charpos < MATRIX_ROW_START_CHARPOS (row)) + /* See the commentary in row_containing_pos, for the + explanation of the complicated way to check whether + some position is beyond the end of the characters + displayed by a row. */ + || ((start_charpos > MATRIX_ROW_END_CHARPOS (row) + || (start_charpos == MATRIX_ROW_END_CHARPOS (row) + && !row->ends_at_zv_p + && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))) + && (end_charpos > MATRIX_ROW_END_CHARPOS (row) + || (end_charpos == MATRIX_ROW_END_CHARPOS (row) + && !row->ends_at_zv_p + && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))))) + { + /* Found a candidate row. Now make sure at least one of the + glyphs it displays has a charpos from the range + [START_CHARPOS..END_CHARPOS). + + This is not obvious because bidi reordering could have + buffer positions of a row be 1,2,3,102,101,100, and if we + want to highlight characters in [50..60), we don't want + this row, even though [50..60) does intersect [1..103), + the range of character positions given by the row's start + and end positions. */ + struct glyph *g = row->glyphs[TEXT_AREA]; + struct glyph *e = g + row->used[TEXT_AREA]; + + while (g < e) + { + if (BUFFERP (g->object) + && start_charpos <= g->charpos && g->charpos < end_charpos) + *start = row; + g++; + } + if (*start) + break; + } + } + + /* Find the END row. */ + if (!*start + /* If the last row is partially visible, start looking for END + from that row, instead of starting from FIRST. */ + && !(row->enabled_p + && row->y < last_y && MATRIX_ROW_BOTTOM_Y (row) > last_y)) + row = first; + for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++) + { + struct glyph_row *next = row + 1; + + if (!next->enabled_p + || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w) + /* The first row >= START whose range of displayed characters + does NOT intersect the range [START_CHARPOS..END_CHARPOS] + is the row END + 1. */ + || (start_charpos < MATRIX_ROW_START_CHARPOS (next) + && end_charpos < MATRIX_ROW_START_CHARPOS (next)) + || ((start_charpos > MATRIX_ROW_END_CHARPOS (next) + || (start_charpos == MATRIX_ROW_END_CHARPOS (next) + && !next->ends_at_zv_p + && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next))) + && (end_charpos > MATRIX_ROW_END_CHARPOS (next) + || (end_charpos == MATRIX_ROW_END_CHARPOS (next) + && !next->ends_at_zv_p + && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next))))) + { + *end = row; + break; + } + else + { + /* If the next row's edges intersect [START_CHARPOS..END_CHARPOS], + but none of the characters it displays are in the range, it is + also END + 1. */ + struct glyph *g = next->glyphs[TEXT_AREA]; + struct glyph *e = g + next->used[TEXT_AREA]; + + while (g < e) + { + if (BUFFERP (g->object) + && start_charpos <= g->charpos && g->charpos < end_charpos) + break; + g++; + } + if (g == e) + { + *end = row; + break; + } + } + } +} + /* This function sets the mouse_face_* elements of DPYINFO, assuming the mouse cursor is on a glyph with buffer charpos MOUSE_CHARPOS in window WINDOW. START_CHARPOS and END_CHARPOS are buffer positions @@ -23903,56 +24026,39 @@ mouse_face_from_buffer_pos (Lisp_Object window, struct glyph *glyph, *end; EMACS_INT ignore, pos; int x; - int beg_set = 0; xassert (NILP (display_string) || STRINGP (display_string)); xassert (NILP (before_string) || STRINGP (before_string)); xassert (NILP (after_string) || STRINGP (after_string)); - /* Find the row with START_CHARPOS. */ /* FIXME: Sometimes the caller gets "wise" and gives us the window start position instead of the real start of the mouse face property. This completely messes up the logic of finding the beg_row and end_row. */ - if (start_charpos < MATRIX_ROW_START_CHARPOS (first) - && (NILP (XBUFFER (w->buffer)->bidi_display_reordering) - || row_containing_pos (w, start_charpos, first, NULL, 0) == NULL)) - { - dpyinfo->mouse_face_beg_col = 0; - dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (first, w->current_matrix); - dpyinfo->mouse_face_beg_x = first->x; - dpyinfo->mouse_face_beg_y = first->y; - beg_set = 1; - } - else - { - r1 = row_containing_pos (w, start_charpos, first, NULL, 0); - if (r1 == NULL) - r1 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); - /* If the before-string or display-string contains newlines, - row_containing_pos skips to its last row. Move back. */ - if (!NILP (before_string) || !NILP (display_string)) - { - struct glyph_row *prev; - while ((prev = r1 - 1, prev >= first) - && MATRIX_ROW_END_CHARPOS (prev) == start_charpos - && prev->used[TEXT_AREA] > 0) - { - struct glyph *beg = prev->glyphs[TEXT_AREA]; - glyph = beg + prev->used[TEXT_AREA]; - while (--glyph >= beg && INTEGERP (glyph->object)); - if (glyph < beg - || !(EQ (glyph->object, before_string) - || EQ (glyph->object, display_string))) - break; - r1 = prev; - } + /* Find the rows corresponding to START_CHARPOS and END_CHARPOS. */ + rows_from_pos_range (w, start_charpos, end_charpos, &r1, &r2); + if (r1 == NULL) + r1 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); + /* If the before-string or display-string contains newlines, + row_containing_pos skips to its last row. Move back. */ + if (!NILP (before_string) || !NILP (display_string)) + { + struct glyph_row *prev; + while ((prev = r1 - 1, prev >= first) + && MATRIX_ROW_END_CHARPOS (prev) == start_charpos + && prev->used[TEXT_AREA] > 0) + { + struct glyph *beg = prev->glyphs[TEXT_AREA]; + glyph = beg + prev->used[TEXT_AREA]; + while (--glyph >= beg && INTEGERP (glyph->object)); + if (glyph < beg + || !(EQ (glyph->object, before_string) + || EQ (glyph->object, display_string))) + break; + r1 = prev; } } - - /* Find the row with END_CHARPOS. */ - r2 = row_containing_pos (w, end_charpos, first, NULL, 0); if (r2 == NULL) { r2 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); @@ -23972,7 +24078,6 @@ mouse_face_from_buffer_pos (Lisp_Object window, ++next) r2 = next; } - /* The rest of the display engine assumes that mouse_face_beg_row is either above below mouse_face_end_row or identical to it. But with bidi-reordered continued lines, the row for START_CHARPOS @@ -23985,6 +24090,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, r2 = r1; r1 = tem; } + dpyinfo->mouse_face_beg_y = r1->y; dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix); dpyinfo->mouse_face_end_y = r2->y; @@ -24000,9 +24106,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, between START_CHARPOS and END_CHARPOS if the range of characters strides the bidi level boundary, e.g. if the beginning is in R2L text while the end is in L2R text or vice versa. */ - if (beg_set) - ; - else if (!r1->reversed_p) + if (!r1->reversed_p) { /* This row is in a left to right paragraph. Scan it left to right. */ @@ -25027,17 +25131,30 @@ note_mouse_highlight (struct frame *f, int x, int y) { Lisp_Object before, after; Lisp_Object before_string, after_string; + /* To correctly find the limits of mouse highlight + in a bidi-reordered buffer, we must not use the + optimization of limiting the search in + previous-single-property-change and + next-single-property-change, because + rows_from_pos_range needs the real start and end + positions to DTRT in this case. */ + Lisp_Object lim1 = + NILP (XBUFFER (buffer)->bidi_display_reordering) + ? Fmarker_position (w->start) + : Qnil; + Lisp_Object lim2 = + NILP (XBUFFER (buffer)->bidi_display_reordering) + ? make_number (BUF_Z (XBUFFER (buffer)) + - XFASTINT (w->window_end_pos)) + : Qnil; if (NILP (overlay)) { /* Handle the text property case. */ before = Fprevious_single_property_change - (make_number (pos + 1), Qmouse_face, buffer, - Fmarker_position (w->start)); + (make_number (pos + 1), Qmouse_face, buffer, lim1); after = Fnext_single_property_change - (make_number (pos), Qmouse_face, buffer, - make_number (BUF_Z (XBUFFER (buffer)) - - XFASTINT (w->window_end_pos))); + (make_number (pos), Qmouse_face, buffer, lim2); before_string = after_string = Qnil; } else -- cgit v1.2.1 From 3e606ad914fcc829a2f0b52147d134ab7df14f4a Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 16 Oct 2010 12:04:03 +0200 Subject: Start working on mouse highlight of mode- and header-lines. xdisp.c (rows_from_pos_range, mouse_face_from_buffer_pos) (note_mode_line_or_margin_highlight): Fix comments. --- src/xdisp.c | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 9f39046b1f5..4a7cc275c47 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -23926,7 +23926,7 @@ rows_from_pos_range (struct window *w, glyphs it displays has a charpos from the range [START_CHARPOS..END_CHARPOS). - This is not obvious because bidi reordering could have + This is not obvious because bidi reordering could make buffer positions of a row be 1,2,3,102,101,100, and if we want to highlight characters in [50..60), we don't want this row, even though [50..60) does intersect [1..103), @@ -24031,17 +24031,12 @@ mouse_face_from_buffer_pos (Lisp_Object window, xassert (NILP (before_string) || STRINGP (before_string)); xassert (NILP (after_string) || STRINGP (after_string)); - /* FIXME: Sometimes the caller gets "wise" and gives us the window - start position instead of the real start of the mouse face - property. This completely messes up the logic of finding the - beg_row and end_row. */ - /* Find the rows corresponding to START_CHARPOS and END_CHARPOS. */ rows_from_pos_range (w, start_charpos, end_charpos, &r1, &r2); if (r1 == NULL) r1 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); /* If the before-string or display-string contains newlines, - row_containing_pos skips to its last row. Move back. */ + rows_from_pos_range skips to its last row. Move back. */ if (!NILP (before_string) || !NILP (display_string)) { struct glyph_row *prev; @@ -24614,7 +24609,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, ? MATRIX_MODE_LINE_ROW (w->current_matrix) : MATRIX_HEADER_LINE_ROW (w->current_matrix)); - /* Find glyph */ + /* Find the glyph under the mouse pointer. */ if (row->mode_line_p && row->enabled_p) { glyph = row_start_glyph = row->glyphs[TEXT_AREA]; @@ -24733,14 +24728,15 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, if (NILP (e)) e = make_number (SCHARS (string)); - /* Calculate the position(glyph position: GPOS) of GLYPH in - displayed string. GPOS is different from CHARPOS. + /* Calculate the glyph position GPOS of GLYPH in the + displayed string. - CHARPOS is the position of glyph in internal string - object. A mode line string format has structures which - is converted to a flatten by emacs lisp interpreter. - The internal string is an element of the structures. - The displayed string is the flatten string. */ + Note: GPOS is different from CHARPOS. CHARPOS is the + position of GLYPH in the internal string object. A mode + line string format has structures which are converted to + 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) { @@ -24754,11 +24750,10 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, } } - /* Calculate the lenght(glyph sequence length: GSEQ_LENGTH) of - displayed string holding GLYPH. - - GSEQ_LENGTH is different from SCHARS (STRING). - SCHARS (STRING) returns the length of the internal string. */ + /* 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++) @@ -24771,14 +24766,14 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++) total_pixel_width += tmp_glyph->pixel_width; - /* Pre calculation of re-rendering position */ - hpos = (x - gpos); + /* Pre calculation of re-rendering position. */ + 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. */ + re-rendering area, we should do nothing. */ if ( EQ (window, dpyinfo->mouse_face_window) && dpyinfo->mouse_face_beg_col <= hpos && hpos < dpyinfo->mouse_face_end_col @@ -25137,7 +25132,10 @@ note_mouse_highlight (struct frame *f, int x, int y) previous-single-property-change and next-single-property-change, because rows_from_pos_range needs the real start and end - positions to DTRT in this case. */ + positions to DTRT in this case. That's because + the first row visible in a window does not + necessarily display the character whose position + is the smallest. */ Lisp_Object lim1 = NILP (XBUFFER (buffer)->bidi_display_reordering) ? Fmarker_position (w->start) -- cgit v1.2.1 From f454f8d96530ac655084622603fec60d5a4dc912 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 16 Oct 2010 14:52:54 +0200 Subject: 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. --- src/xdisp.c | 121 +++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 74 insertions(+), 47 deletions(-) (limited to 'src/xdisp.c') 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)) -- cgit v1.2.1 From fcbbd8e4530500d471b9eaaa255454478d813a3c Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 16 Oct 2010 18:14:16 +0200 Subject: Finished work on mouse highlight that comes from display strings. Not tested yet. xdisp.c (fast_find_string_pos): #ifdef away, not used anymore. (mouse_face_from_string_pos): New function, replaces fast_find_string_pos. (note_mouse_highlight): Call it instead of fast_find_string_pos. --- src/xdisp.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 96 insertions(+), 11 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 41be01c407f..9b58e70176d 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -24324,6 +24324,11 @@ mouse_face_from_buffer_pos (Lisp_Object window, show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); } +/* The following function is not used anymore (replaced with + mouse_face_from_string_pos), but I leave it here for the time + being, in case someone would. */ + +#if 0 /* not used */ /* Find the position of the glyph for position POS in OBJECT in window W's current matrix, and return in *X, *Y the pixel @@ -24401,7 +24406,96 @@ fast_find_string_pos (struct window *w, EMACS_INT pos, Lisp_Object object, return best_glyph != NULL; } +#endif /* not used */ + +/* Find the positions of the first and the last glyphs in window W's + current matrix that occlude positions [STARTPOS..ENDPOS) in OBJECT + (assumed to be a string), and return in DPYINFO's mouse_face + members the pixel and column/row coordinates of those glyphs. */ +static void +mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, + Lisp_Object object, + EMACS_INT startpos, EMACS_INT endpos) +{ + int yb = window_text_bottom_y (w); + struct glyph_row *r; + struct glyph *g, *e; + int gx; + int found; + + /* Find the glyph row with at least one position in the range + [STARTPOS..ENDPOS), and the leftmost glyph in that row whose + position belongs to that range. */ + for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); + r->enabled_p && r->y < yb; + ++r) + { + g = r->glyphs[TEXT_AREA]; + e = g + r->used[TEXT_AREA]; + for (gx = r->x; g < e; gx += g->pixel_width, ++g) + if (EQ (g->object, object) + && startpos <= g->charpos && g->charpos < endpos) + { + dpyinfo->mouse_face_beg_row = r - w->current_matrix->rows; + dpyinfo->mouse_face_beg_y = r->y; + if (!r->reversed_p) + { + dpyinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA]; + dpyinfo->mouse_face_beg_x = gx; + } + else + { + /* R2L rows want BEG and END swapped, see + show_mouse_face. */ + dpyinfo->mouse_face_end_col = g - r->glyphs[TEXT_AREA]; + dpyinfo->mouse_face_end_x = gx; + } + break; + } + } + + /* Starting with the next row, look for the first row which does NOT + include any glyphs whose positions are in the range. */ + for (++r; r->enabled_p && r->y < yb; ++r) + { + g = r->glyphs[TEXT_AREA]; + e = g + r->used[TEXT_AREA]; + found = 0; + for ( ; g < e; ++g) + if (EQ (g->object, object) + && startpos <= g->charpos && g->charpos < endpos) + { + found = 1; + break; + } + if (!found) + break; + } + + if (!found) + r--; + dpyinfo->mouse_face_end_row = r - w->current_matrix->rows; + dpyinfo->mouse_face_end_y = r->y; + + g = r->glyphs[TEXT_AREA]; + e = g + r->used[TEXT_AREA]; + for ( ; e > g; --e) + if (EQ ((e-1)->object, object) + && startpos <= (e-1)->charpos && (e-1)->charpos < endpos) + break; + if (!r->reversed_p) + dpyinfo->mouse_face_end_col = e - g; + else + dpyinfo->mouse_face_beg_col = e - g; + + for (gx = r->x; g < e; ++g) + gx += g->pixel_width; + if (!r->reversed_p) + dpyinfo->mouse_face_end_x = gx; + else + dpyinfo->mouse_face_beg_x = gx; +} /* See if position X, Y is within a hot-spot of an image. */ @@ -25103,17 +25197,8 @@ note_mouse_highlight (struct frame *f, int x, int y) b = make_number (0); if (NILP (e)) e = make_number (SCHARS (object) - 1); - - fast_find_string_pos (w, XINT (b), object, - &dpyinfo->mouse_face_beg_col, - &dpyinfo->mouse_face_beg_row, - &dpyinfo->mouse_face_beg_x, - &dpyinfo->mouse_face_beg_y, 0); - fast_find_string_pos (w, XINT (e), object, - &dpyinfo->mouse_face_end_col, - &dpyinfo->mouse_face_end_row, - &dpyinfo->mouse_face_end_x, - &dpyinfo->mouse_face_end_y, 1); + mouse_face_from_string_pos (w, dpyinfo, object, + XINT (b), XINT (e)); dpyinfo->mouse_face_past_end = 0; dpyinfo->mouse_face_window = window; dpyinfo->mouse_face_face_id -- cgit v1.2.1 From 31549eb572532bae56aad705611e1c9d9b4ae4b0 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 23 Oct 2010 14:28:28 +0200 Subject: Tested with L2R rows and mouse highlight on a single line. xdisp.c (mouse_face_from_string_pos): Initialize the `found' flag to zero, and exit the outer loop when it's non-zero. Bail our early if no row in the window belongs to the highlighted string. Always back up after exiting the second loop. --- src/xdisp.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 9b58e70176d..5a7ba32b678 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -24422,7 +24422,7 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, struct glyph_row *r; struct glyph *g, *e; int gx; - int found; + int found = 0; /* Find the glyph row with at least one position in the range [STARTPOS..ENDPOS), and the leftmost glyph in that row whose @@ -24451,10 +24451,16 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, dpyinfo->mouse_face_end_col = g - r->glyphs[TEXT_AREA]; dpyinfo->mouse_face_end_x = gx; } + found = 1; break; } + if (found) + break; } + if (!found) + return; + /* Starting with the next row, look for the first row which does NOT include any glyphs whose positions are in the range. */ for (++r; r->enabled_p && r->y < yb; ++r) @@ -24472,9 +24478,8 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, if (!found) break; } + r--; - if (!found) - r--; dpyinfo->mouse_face_end_row = r - w->current_matrix->rows; dpyinfo->mouse_face_end_y = r->y; -- cgit v1.2.1 From 902bbbf3d89233e2ac7fcdb7d884d736ab002fc7 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 23 Oct 2010 14:58:12 +0200 Subject: The range [STARTPOS..ENDPOS] is inclusive in strings. Tested with multiline display strings. xdisp.c (mouse_face_from_string_pos): Fix off-by-one error when testing against ENDPOS. --- src/xdisp.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 5a7ba32b678..2db6ab8dbd1 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -24409,7 +24409,7 @@ fast_find_string_pos (struct window *w, EMACS_INT pos, Lisp_Object object, #endif /* not used */ /* Find the positions of the first and the last glyphs in window W's - current matrix that occlude positions [STARTPOS..ENDPOS) in OBJECT + current matrix that occlude positions [STARTPOS..ENDPOS] in OBJECT (assumed to be a string), and return in DPYINFO's mouse_face members the pixel and column/row coordinates of those glyphs. */ @@ -24425,7 +24425,7 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, int found = 0; /* Find the glyph row with at least one position in the range - [STARTPOS..ENDPOS), and the leftmost glyph in that row whose + [STARTPOS..ENDPOS], and the leftmost glyph in that row whose position belongs to that range. */ for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); r->enabled_p && r->y < yb; @@ -24435,7 +24435,7 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, e = g + r->used[TEXT_AREA]; for (gx = r->x; g < e; gx += g->pixel_width, ++g) if (EQ (g->object, object) - && startpos <= g->charpos && g->charpos < endpos) + && startpos <= g->charpos && g->charpos <= endpos) { dpyinfo->mouse_face_beg_row = r - w->current_matrix->rows; dpyinfo->mouse_face_beg_y = r->y; @@ -24470,7 +24470,7 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, found = 0; for ( ; g < e; ++g) if (EQ (g->object, object) - && startpos <= g->charpos && g->charpos < endpos) + && startpos <= g->charpos && g->charpos <= endpos) { found = 1; break; @@ -24478,22 +24478,27 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, if (!found) break; } + + /* The highlighted region ends on the previous row. */ r--; + /* Set the end row and its vertical pixel coordinate. */ dpyinfo->mouse_face_end_row = r - w->current_matrix->rows; dpyinfo->mouse_face_end_y = r->y; + /* Compute and set the end column. */ g = r->glyphs[TEXT_AREA]; e = g + r->used[TEXT_AREA]; for ( ; e > g; --e) if (EQ ((e-1)->object, object) - && startpos <= (e-1)->charpos && (e-1)->charpos < endpos) + && startpos <= (e-1)->charpos && (e-1)->charpos <= endpos) break; if (!r->reversed_p) dpyinfo->mouse_face_end_col = e - g; else dpyinfo->mouse_face_beg_col = e - g; + /* Compute and set the end column's horizontal pixel coordinate. */ for (gx = r->x; g < e; ++g) gx += g->pixel_width; if (!r->reversed_p) -- cgit v1.2.1 From b4244a9c4dca5af18b58c6a8bc2bffd2787ce399 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 23 Oct 2010 16:41:50 +0200 Subject: Fix support for R2L lines. Tested with reordered text. xdisp.c (mouse_face_from_string_pos): Fix support for R2L lines. --- src/xdisp.c | 92 ++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 34 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 2db6ab8dbd1..fe3eeec982b 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -24425,35 +24425,48 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, int found = 0; /* Find the glyph row with at least one position in the range - [STARTPOS..ENDPOS], and the leftmost glyph in that row whose + [STARTPOS..ENDPOS], and the first glyph in that row whose position belongs to that range. */ for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); r->enabled_p && r->y < yb; ++r) { - g = r->glyphs[TEXT_AREA]; - e = g + r->used[TEXT_AREA]; - for (gx = r->x; g < e; gx += g->pixel_width, ++g) - if (EQ (g->object, object) - && startpos <= g->charpos && g->charpos <= endpos) - { - dpyinfo->mouse_face_beg_row = r - w->current_matrix->rows; - dpyinfo->mouse_face_beg_y = r->y; - if (!r->reversed_p) + if (!r->reversed_p) + { + g = r->glyphs[TEXT_AREA]; + e = g + r->used[TEXT_AREA]; + for (gx = r->x; g < e; gx += g->pixel_width, ++g) + if (EQ (g->object, object) + && startpos <= g->charpos && g->charpos <= endpos) { + dpyinfo->mouse_face_beg_row = r - w->current_matrix->rows; + dpyinfo->mouse_face_beg_y = r->y; dpyinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA]; dpyinfo->mouse_face_beg_x = gx; + found = 1; + break; } - else + } + else + { + struct glyph *g1; + + e = r->glyphs[TEXT_AREA]; + g = e + r->used[TEXT_AREA]; + for ( ; g > e; --g) + if (EQ ((g-1)->object, object) + && startpos <= (g-1)->charpos && (g-1)->charpos <= endpos) { - /* R2L rows want BEG and END swapped, see - show_mouse_face. */ - dpyinfo->mouse_face_end_col = g - r->glyphs[TEXT_AREA]; - dpyinfo->mouse_face_end_x = gx; + dpyinfo->mouse_face_beg_row = r - w->current_matrix->rows; + dpyinfo->mouse_face_beg_y = r->y; + dpyinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA]; + for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1) + gx += g1->pixel_width; + dpyinfo->mouse_face_beg_x = gx; + found = 1; + break; } - found = 1; - break; - } + } if (found) break; } @@ -24486,25 +24499,36 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, dpyinfo->mouse_face_end_row = r - w->current_matrix->rows; dpyinfo->mouse_face_end_y = r->y; - /* Compute and set the end column. */ - g = r->glyphs[TEXT_AREA]; - e = g + r->used[TEXT_AREA]; - for ( ; e > g; --e) - if (EQ ((e-1)->object, object) - && startpos <= (e-1)->charpos && (e-1)->charpos <= endpos) - break; + /* Compute and set the end column and the end column's horizontal + pixel coordinate. */ if (!r->reversed_p) - dpyinfo->mouse_face_end_col = e - g; - else - dpyinfo->mouse_face_beg_col = e - g; + { + g = r->glyphs[TEXT_AREA]; + e = g + r->used[TEXT_AREA]; + for ( ; e > g; --e) + if (EQ ((e-1)->object, object) + && startpos <= (e-1)->charpos && (e-1)->charpos <= endpos) + break; + dpyinfo->mouse_face_end_col = e - g; - /* Compute and set the end column's horizontal pixel coordinate. */ - for (gx = r->x; g < e; ++g) - gx += g->pixel_width; - if (!r->reversed_p) - dpyinfo->mouse_face_end_x = gx; + for (gx = r->x; g < e; ++g) + gx += g->pixel_width; + dpyinfo->mouse_face_end_x = gx; + } else - dpyinfo->mouse_face_beg_x = gx; + { + e = r->glyphs[TEXT_AREA]; + g = e + r->used[TEXT_AREA]; + for (gx = r->x ; e < g; ++e) + { + if (EQ (e->object, object) + && startpos <= e->charpos && e->charpos <= endpos) + break; + gx += e->pixel_width; + } + dpyinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA]; + dpyinfo->mouse_face_end_x = gx; + } } /* See if position X, Y is within a hot-spot of an image. */ -- cgit v1.2.1 From 790fe5a02618831a411b0a056d2f82f2763e96ff Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Sat, 23 Oct 2010 14:02:44 -0700 Subject: Sync docs of C and Lisp version of auto-hscroll-mode. * lisp/frame.el (auto-hscroll-mode): Sync doc with C version. * src/xdisp.c (syms_of_xdisp) : Sync doc with Lisp. --- src/xdisp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index e2ec1360b49..359d25342ab 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1,8 +1,8 @@ /* Display generation from window structure and buffer text. - Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, - 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + +Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1997, 1998, + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, + 2010 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -26464,7 +26464,9 @@ the frame's other specifications determine how to blink the cursor off. */); Vblink_cursor_alist = Qnil; DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p, - doc: /* *Non-nil means scroll the display automatically to make point visible. */); + doc: /* Allow or disallow automatic horizontal scrolling of windows. +If non-nil, windows are automatically scrolled horizontally to make +point visible. */); automatic_hscrolling_p = 1; Qauto_hscroll_mode = intern_c_string ("auto-hscroll-mode"); staticpro (&Qauto_hscroll_mode); @@ -26706,5 +26708,3 @@ cancel_hourglass (void) } #endif /* ! WINDOWSNT */ -/* arch-tag: eacc864d-bb6a-4b74-894a-1a4399a1358b - (do not change this comment) */ -- cgit v1.2.1 From 3269caf58ecfd84b7f94f37ee0fb05a6602b9861 Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Sat, 23 Oct 2010 14:16:39 -0700 Subject: * src/xdisp.c (syms_of_xdisp) : Sync doc with Lisp. --- src/xdisp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 359d25342ab..ce679b2d75e 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -26581,7 +26581,9 @@ baseline. The default value is 1. */); underline_minimum_offset = 1; DEFVAR_BOOL ("display-hourglass", &display_hourglass_p, - doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */); + doc: /* Non-nil means show an hourglass pointer, when Emacs is busy. +This feature only works when on a window system that can change +cursor shapes. */); display_hourglass_p = 1; DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay, -- cgit v1.2.1 From 4acbd99d5d13b3ddafd98841252f2e17ceec768d Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Sat, 23 Oct 2010 14:19:02 -0700 Subject: * src/xdisp.c (syms_of_xdisp) : Sync doc with Lisp. --- src/xdisp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index ce679b2d75e..c9af2ba88ec 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -26587,8 +26587,7 @@ cursor shapes. */); display_hourglass_p = 1; DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay, - doc: /* *Seconds to wait before displaying an hourglass pointer. -Value must be an integer or float. */); + doc: /* *Seconds to wait before displaying an hourglass pointer when Emacs is busy. */); Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY); hourglass_atimer = NULL; -- cgit v1.2.1 From 20d6f8d4e37b87cb5e0c43add9fea5ccc922f565 Mon Sep 17 00:00:00 2001 From: Kenichi Handa Date: Fri, 29 Oct 2010 09:50:13 +0900 Subject: Implement various display methods for glyphless characters. --- src/xdisp.c | 443 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 419 insertions(+), 24 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index c9af2ba88ec..52938417aac 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -932,6 +932,21 @@ struct atimer *hourglass_atimer; /* Number of seconds to wait before displaying an hourglass cursor. */ Lisp_Object Vhourglass_delay; +/* Name of the face used to display glyphless characters. */ +Lisp_Object Qglyphless_char; + +/* Char-table to control the display of glyphless characters. */ +Lisp_Object Vglyphless_char_display; + +/* Symbol for the purpose of Vglyphless_char_display. */ +Lisp_Object Qglyphless_char_display; + +/* Method symbols for Vglyphless_char_display. */ +static Lisp_Object Qhexa_code, Qempty_box, Qthin_space, Qzero_width; + +/* Default pixel width of `thin-space' display method. */ +#define THIN_SPACE_WIDTH 1 + /* Default number of seconds to wait before displaying an hourglass cursor. */ #define DEFAULT_HOURGLASS_DELAY 1 @@ -5732,6 +5747,57 @@ static int (* get_next_element[NUM_IT_METHODS]) (struct it *it) = (IT)->string))) +/* Lookup the char-table Vglyphless_char_display for character C (-1 + if we want information for no-font case), and return the display + method symbol. By side-effect, update it->what and + it->glyphless_method. This function is called from + get_next_display_element for each character element, and from + x_produce_glyphs when no suitable font was found. */ + +static Lisp_Object +lookup_glyphless_char_display (int c, struct it *it) +{ + Lisp_Object glyphless_method = Qnil; + + if (CHAR_TABLE_P (Vglyphless_char_display) + && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1) + glyphless_method = (c >= 0 + ? CHAR_TABLE_REF (Vglyphless_char_display, c) + : XCHAR_TABLE (Vglyphless_char_display)->extras[0]); + retry: + if (NILP (glyphless_method)) + { + if (c >= 0) + /* The default is to display the character by a proper font. */ + return Qnil; + /* The default for the no-font case is to display an empty box. */ + glyphless_method = Qempty_box; + } + if (EQ (glyphless_method, Qzero_width)) + { + if (c >= 0) + return glyphless_method; + /* This method can't be used for the no-font case. */ + glyphless_method = Qempty_box; + } + it->what = IT_GLYPHLESS; + if (EQ (glyphless_method, Qthin_space)) + it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE; + else if (EQ (glyphless_method, Qempty_box)) + it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX; + else if (EQ (glyphless_method, Qhexa_code)) + it->glyphless_method = GLYPHLESS_DISPLAY_HEXA_CODE; + else if (STRINGP (glyphless_method)) + it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM; + else + { + /* Invalid value. We use the default method. */ + glyphless_method = Qnil; + goto retry; + } + return glyphless_method; +} + /* Load IT's display element fields with information about the next display element from the current position of IT. Value is zero if end of buffer (or C string) is reached. */ @@ -5740,6 +5806,10 @@ static struct frame *last_escape_glyph_frame = NULL; static unsigned last_escape_glyph_face_id = (1 << FACE_ID_BITS); static int last_escape_glyph_merged_face_id = 0; +static struct frame *last_glyphless_glyph_frame = NULL; +static unsigned last_glyphless_glyph_face_id = (1 << FACE_ID_BITS); +static int last_glyphless_glyph_merged_face_id = 0; + int get_next_display_element (struct it *it) { @@ -5818,6 +5888,15 @@ get_next_display_element (struct it *it) goto get_next; } + if (! NILP (lookup_glyphless_char_display (c, it))) + { + if (it->what == IT_GLYPHLESS) + goto done; + /* Don't display this character. */ + set_iterator_to_next (it, 0); + goto get_next; + } + if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display)) nbsp_or_shy = (c == 0xA0 ? char_is_nbsp : c == 0xAD ? char_is_soft_hyphen @@ -6032,6 +6111,7 @@ get_next_display_element (struct it *it) } #endif + done: /* Is this character the last one of a run of characters with box? If yes, set IT->end_of_box_run_p to 1. */ if (it->face_box_p @@ -11579,6 +11659,8 @@ redisplay_internal (int preserve_echo_area) reconsider_clip_changes (w, current_buffer); last_escape_glyph_frame = NULL; last_escape_glyph_face_id = (1 << FACE_ID_BITS); + last_glyphless_glyph_frame = NULL; + last_glyphless_glyph_face_id = (1 << FACE_ID_BITS); /* If new fonts have been loaded that make a glyph matrix adjustment necessary, do it. */ @@ -20657,6 +20739,42 @@ fill_gstring_glyph_string (struct glyph_string *s, int face_id, } +/* Fill glyph string S from a sequence glyphs for glyphless characters. + See the comment of fill_glyph_string for arguments. + Value is the index of the first glyph not in S. */ + + +static int +fill_glyphless_glyph_string (struct glyph_string *s, int face_id, + int start, int end, int overlaps) +{ + struct glyph *glyph, *last; + int voffset; + + xassert (s->first_glyph->type == GLYPHLESS_GLYPH); + s->for_overlaps = overlaps; + glyph = s->row->glyphs[s->area] + start; + last = s->row->glyphs[s->area] + end; + voffset = glyph->voffset; + s->face = FACE_FROM_ID (s->f, face_id); + s->font = s->face->font; + s->nchars = 1; + s->width = glyph->pixel_width; + glyph++; + while (glyph < last + && glyph->type == GLYPHLESS_GLYPH + && glyph->voffset == voffset + && glyph->face_id == face_id) + { + s->nchars++; + s->width += glyph->pixel_width; + glyph++; + } + s->ybase += voffset; + return glyph - s->row->glyphs[s->area]; +} + + /* Fill glyph string S from a sequence of character glyphs. FACE_ID is the face id of the string. START is the index of the @@ -21167,6 +21285,28 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p) } while (0) +/* Add a glyph string for a sequence of glyphless character's glyphs + to the list of strings between HEAD and TAIL. The meanings of + arguments are the same as those of BUILD_CHAR_GLYPH_STRINGS. */ + +#define BUILD_GLYPHLESS_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \ + do \ + { \ + int face_id; \ + XChar2b *char2b; \ + \ + face_id = (row)->glyphs[area][START].face_id; \ + \ + s = (struct glyph_string *) alloca (sizeof *s); \ + INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \ + append_glyph_string (&HEAD, &TAIL, s); \ + s->x = (X); \ + START = fill_glyphless_glyph_string (s, face_id, START, END, \ + overlaps); \ + } \ + while (0) + + /* Build a list of glyph strings between HEAD and TAIL for the glyphs of AREA of glyph row ROW on window W between indices START and END. HL overrides the face for drawing glyph strings, e.g. it is @@ -21190,7 +21330,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p) BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \ HL, X, LAST_X); \ break; \ - \ + \ case COMPOSITE_GLYPH: \ if (first_glyph->u.cmp.automatic) \ BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \ @@ -21199,21 +21339,26 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p) BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \ HL, X, LAST_X); \ break; \ - \ + \ case STRETCH_GLYPH: \ BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \ HL, X, LAST_X); \ break; \ - \ + \ case IMAGE_GLYPH: \ BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \ HL, X, LAST_X); \ break; \ - \ + \ + case GLYPHLESS_GLYPH: \ + BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \ + HL, X, LAST_X); \ + break; \ + \ default: \ abort (); \ } \ - \ + \ if (s) \ { \ set_glyph_string_background_width (s, START, LAST_X); \ @@ -22109,6 +22254,229 @@ calc_line_height_property (struct it *it, Lisp_Object val, struct font *font, } +/* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID + is a face ID to be used for the glyph. FOR_NO_FONT is nonzero if + and only if this is for a character for which no font was found. + + If the display method (it->glyphless_method) is + GLYPHLESS_DISPLAY_ACRONYM or GLYPHLESS_DISPLAY_HEXA_CODE, LEN is a + length of the acronym or the hexadecimal string, UPPER_XOFF and + UPPER_YOFF are pixel offsets for the upper part of the string, + LOWER_XOFF and LOWER_YOFF are for the lower part. + + For the other display methods, LEN through LOWER_YOFF are zero. */ + +static void +append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len, + short upper_xoff, short upper_yoff, + short lower_xoff, short lower_yoff) +{ + struct glyph *glyph; + enum glyph_row_area area = it->area; + + glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; + if (glyph < it->glyph_row->glyphs[area + 1]) + { + /* If the glyph row is reversed, we need to prepend the glyph + rather than append it. */ + if (it->glyph_row->reversed_p && area == TEXT_AREA) + { + struct glyph *g; + + /* Make room for the additional glyph. */ + for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--) + g[1] = *g; + glyph = it->glyph_row->glyphs[area]; + } + glyph->charpos = CHARPOS (it->position); + glyph->object = it->object; + glyph->pixel_width = it->pixel_width; + glyph->ascent = it->ascent; + glyph->descent = it->descent; + glyph->voffset = it->voffset; + glyph->type = GLYPHLESS_GLYPH; + glyph->u.glyphless.method = it->glyphless_method; + glyph->u.glyphless.for_no_font = for_no_font; + glyph->u.glyphless.len = len; + glyph->u.glyphless.ch = it->c; + glyph->slice.glyphless.upper_xoff = upper_xoff; + glyph->slice.glyphless.upper_yoff = upper_yoff; + glyph->slice.glyphless.lower_xoff = lower_xoff; + glyph->slice.glyphless.lower_yoff = lower_yoff; + glyph->avoid_cursor_p = it->avoid_cursor_p; + glyph->multibyte_p = it->multibyte_p; + glyph->left_box_line_p = it->start_of_box_run_p; + glyph->right_box_line_p = it->end_of_box_run_p; + glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent + || it->phys_descent > it->descent); + glyph->padding_p = 0; + glyph->glyph_not_available_p = 0; + glyph->face_id = face_id; + glyph->font_type = FONT_TYPE_UNKNOWN; + if (it->bidi_p) + { + glyph->resolved_level = it->bidi_it.resolved_level; + if ((it->bidi_it.type & 7) != it->bidi_it.type) + abort (); + glyph->bidi_type = it->bidi_it.type; + } + ++it->glyph_row->used[area]; + } + else + IT_EXPAND_MATRIX_WIDTH (it, area); +} + + +/* Produce a glyph for a glyphless character for iterator IT. + IT->glyphless_method specifies which method to use for displaying + the glyph. See the description of enum glyphless_display_method in + dispextern.h for the default of the display methods. + + FOR_NO_FONT is nonzero if and only if this is for a character for + which no font was found. ACRONYM, if non-nil, is an acronym string + for the character. */ + +static void +produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) +{ + int face_id; + struct face *face; + struct font *font; + int base_width, base_height, width, height; + short upper_xoff, upper_yoff, lower_xoff, lower_yoff; + int len; + + /* Get the metrics of the base font. We always refer to the current + ASCII face. */ + face = FACE_FROM_ID (it->f, it->face_id)->ascii_face; + font = face->font ? face->font : FRAME_FONT (it->f); + it->ascent = FONT_BASE (font) + font->baseline_offset; + it->descent = FONT_DESCENT (font) - font->baseline_offset; + base_height = it->ascent + it->descent; + base_width = font->average_width; + + /* Get a face ID for the glyph by utilizing a cache (the same way as + doen for `escape-glyph' in get_next_display_element). */ + if (it->f == last_glyphless_glyph_frame + && it->face_id == last_glyphless_glyph_face_id) + { + face_id = last_glyphless_glyph_merged_face_id; + } + else + { + /* Merge the `glyphless-char' face into the current face. */ + face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id); + last_glyphless_glyph_frame = it->f; + last_glyphless_glyph_face_id = it->face_id; + last_glyphless_glyph_merged_face_id = face_id; + } + + if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE) + { + it->pixel_width = THIN_SPACE_WIDTH; + len = 0; + upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0; + } + else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX) + { + width = CHAR_WIDTH (it->c); + if (width == 0) + width = 1; + else if (width > 4) + width = 4; + it->pixel_width = base_width * width; + len = 0; + upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0; + } + else + { + char buf[7], *str; + unsigned int code[6]; + int upper_len; + int ascent, descent; + struct font_metrics metrics_upper, metrics_lower; + + face = FACE_FROM_ID (it->f, face_id); + font = face->font ? face->font : FRAME_FONT (it->f); + PREPARE_FACE_FOR_DISPLAY (it->f, face); + + if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM) + { + if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display)) + acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c); + str = STRINGP (acronym) ? (char *) SDATA (acronym) : ""; + } + else + { + xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEXA_CODE); + sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c); + str = buf; + } + for (len = 0; str[len] && ASCII_BYTE_P (str[len]); len++) + code[len] = font->driver->encode_char (font, str[len]); + upper_len = (len + 1) / 2; + font->driver->text_extents (font, code, upper_len, + &metrics_upper); + font->driver->text_extents (font, code + upper_len, len - upper_len, + &metrics_lower); + + + + /* +4 is for vertical bars of a box plus 1-pixel spaces at both side. */ + width = max (metrics_upper.width, metrics_lower.width) + 4; + upper_xoff = upper_yoff = 2; /* the typical case */ + if (base_width >= width) + { + /* Align the upper to the left, the lower to the right. */ + it->pixel_width = base_width; + lower_xoff = base_width - 2 - metrics_lower.width; + } + else + { + /* Center the shorter one. */ + it->pixel_width = width; + if (metrics_upper.width >= metrics_lower.width) + lower_xoff = (width - metrics_lower.width) / 2; + else + upper_xoff = (width - metrics_upper.width) / 2; + } + + /* +5 is for horizontal bars of a box plus 1-pixel spaces at + top, bottom, and between upper and lower strings. */ + height = (metrics_upper.ascent + metrics_upper.descent + + metrics_lower.ascent + metrics_lower.descent) + 5; + /* Center vertically. + H:base_height, D:base_descent + h:height, ld:lower_descent, la:lower_ascent, ud:upper_descent + + ascent = - (D - H/2 - h/2 + 1); "+ 1" for rounding up + descent = D - H/2 + h/2; + lower_yoff = descent - 2 - ld; + upper_yoff = lower_yoff - la - 1 - ud; */ + ascent = - (it->descent - (base_height + height + 1) / 2); + descent = it->descent - (base_height - height) / 2; + lower_yoff = descent - 2 - metrics_lower.descent; + upper_yoff = (lower_yoff - metrics_lower.ascent - 1 + - metrics_upper.descent); + /* Don't make the height shorter than the base height. */ + if (height > base_height) + { + it->ascent = ascent; + it->descent = descent; + } + } + + it->phys_ascent = it->ascent; + it->phys_descent = it->descent; + if (it->glyph_row) + append_glyphless_glyph (it, face_id, for_no_font, len, + upper_xoff, upper_yoff, + lower_xoff, lower_yoff); + it->nglyphs = 1; + take_vertical_position_into_account (it); +} + + /* RIF: Produce glyphs/get display metrics for the display element IT is loaded with. See the description of struct it in dispextern.h @@ -22126,29 +22494,25 @@ x_produce_glyphs (struct it *it) XChar2b char2b; struct face *face = FACE_FROM_ID (it->f, it->face_id); struct font *font = face->font; - int font_not_found_p = font == NULL; struct font_metrics *pcm = NULL; int boff; /* baseline offset */ - if (font_not_found_p) - { - /* When no suitable font found, display an empty box based - on the metrics of the font of the default face (or what - remapped). */ - struct face *no_font_face - = FACE_FROM_ID (it->f, - NILP (Vface_remapping_alist) ? DEFAULT_FACE_ID - : lookup_basic_face (it->f, DEFAULT_FACE_ID)); - font = no_font_face->font; - boff = font->baseline_offset; - } - else + if (font == NULL) { - boff = font->baseline_offset; - if (font->vertical_centering) - boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff; + /* When no suitable font is found, display this character by + the method specified in the first extra slot of + Vglyphless_char_display. */ + Lisp_Object acronym = lookup_glyphless_char_display (-1, it); + + xassert (it->what == IT_GLYPHLESS); + produce_glyphless_glyph (it, 1, STRINGP (acronym) ? acronym : Qnil); + goto done; } + boff = font->baseline_offset; + if (font->vertical_centering) + boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff; + if (it->char_to_display != '\n' && it->char_to_display != '\t') { int stretched_p; @@ -22167,8 +22531,7 @@ x_produce_glyphs (struct it *it) it->descent = FONT_DESCENT (font) - boff; } - if (! font_not_found_p - && get_char_glyph_code (it->char_to_display, font, &char2b)) + if (get_char_glyph_code (it->char_to_display, font, &char2b)) { pcm = get_per_char_metric (it->f, font, &char2b); if (pcm->width == 0 @@ -22758,11 +23121,14 @@ x_produce_glyphs (struct it *it) if (it->glyph_row) append_composite_glyph (it); } + else if (it->what == IT_GLYPHLESS) + produce_glyphless_glyph (it, 0, Qnil); else if (it->what == IT_IMAGE) produce_image_glyph (it); else if (it->what == IT_STRETCH) produce_stretch_glyph (it); + done: /* Accumulate dimensions. Note: can't assume that it->descent > 0 because this isn't true for images with `:ascent 100'. */ xassert (it->ascent >= 0 && it->descent >= 0); @@ -26592,6 +26958,35 @@ cursor shapes. */); hourglass_atimer = NULL; hourglass_shown_p = 0; + + DEFSYM (Qglyphless_char, "glyphless-char"); + DEFSYM (Qhexa_code, "hexa-code"); + DEFSYM (Qempty_box, "empty-box"); + DEFSYM (Qthin_space, "thin-space"); + DEFSYM (Qzero_width, "zero-width"); + + DEFSYM (Qglyphless_char_display, "glyphless-char-display"); + /* Intern this now in case it isn't already done. + Setting this variable twice is harmless. + But don't staticpro it here--that is done in alloc.c. */ + Qchar_table_extra_slots = intern_c_string ("char-table-extra-slots"); + Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_number (1)); + + DEFVAR_LISP ("glyphless-char-display", &Vglyphless_char_display, + doc: /* Char-table to control displaying of glyphless characters. +Each element, if non-nil, is an ASCII acronym string (displayed in a box) +or one of these symbols: + hexa-code: display with hexadecimal character code in a box + empty-box: display with an empty box + thin-space: display with 1-pixel width space + zero-width: don't display + +It has one extra slot to control the display of a character for which +no font is found. The value of the slot is `hexa-code' or `empty-box'. +The default is `empty-box'. */); + Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil); + Fset_char_table_extra_slot (Vglyphless_char_display, make_number (0), + Qempty_box); } -- cgit v1.2.1 From 4318ee08b161d55b4a32b3f831a69b19a14e8482 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 30 Oct 2010 15:09:52 +0200 Subject: Unify mouse highlight code of MSDOS and GUI sessions. xdisp.c (coords_in_mouse_face_p): Move prototype out of the HAVE_WINDOW_SYSTEM conditional. (x_y_to_hpos_vpos, frame_to_window_pixel_xy): Move out of the HAVE_WINDOW_SYSTEM block. (try_window_id) [HAVE_GPM || MSDOS]: Call x_clear_window_mouse_face. (draw_row_with_mouse_face): Implementation for HAVE_WINDOW_SYSTEM systems. (show_mouse_face): Call it, instead of calling draw_glyphs directly. (show_mouse_face, clear_mouse_face, coords_in_mouse_face_p) (cursor_in_mouse_face_p, rows_from_pos_range) (mouse_face_from_buffer_pos, mouse_face_from_string_pos) (note_mode_line_or_margin_highlight, note_mouse_highlight) (x_clear_window_mouse_face, cancel_mouse_face): Move out of the HAVE_WINDOW_SYSTEM block. Ifdef away window-system specific fragments. (note_mouse_highlight): Call popup_activated for MSDOS as well. Clear mouse highlight if pointer is over glyphs whose OBJECT is an integer. (mouse_face_from_buffer_pos): Add parentheses around && within ||. xmenu.c (popup_activated): Don't define on MSDOS. dispnew.c (mirror_make_current): Set Y coordinate of the mode-line and header-line rows. termchar.h (struct tty_display_info): Define mouse_face_* members not only for MSDOS. Delete stray whitespace. : New struct members. dispextern.h (DPYINFO_DEFINED) [HAVE_X_WINDOWS]: Define. (DPYINFO_DEFINED) [HAVE_NTGUI]: Define. (DPYINFO_DEFINED) [HAVE_NS]: Define. (Display_Info) [!DPYINFO_DEFINED]: Define here. (FRAME_X_DISPLAY_INFO) [HAVE_GPM]: Define. (FRAME_X_DISPLAY_INFO): Define to NULL if not defined. (frame_to_window_pixel_xy, note_mouse_highlight) (x_clear_window_mouse_face, cancel_mouse_face, clear_mouse_face) (show_mouse_face, cursor_in_mouse_face_p): Move prototypes out of HAVE_WINDOW_SYSTEM conditional. (draw_row_with_mouse_face): Declare prototype. msdos.h (Display_Info): Don't define here. msdos.c (show_mouse_face, clear_mouse_face) (fast_find_position, IT_note_mode_line_highlight) (IT_note_mouse_highlight): Functions deleted. (IT_frame_up_to_date, dos_rawgetc): Call note_mouse_highlight instead of IT_note_mouse_highlight. (draw_row_with_mouse_face, popup_activated): New functions. --- src/xdisp.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 70 insertions(+), 19 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index c9af2ba88ec..6339bb900af 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1085,12 +1085,13 @@ static void notice_overwritten_cursor (struct window *, int, int, int, int); static void append_stretch_glyph (struct it *, Lisp_Object, int, int, int); -static int coords_in_mouse_face_p (struct window *, int, int); - #endif /* HAVE_WINDOW_SYSTEM */ +static int coords_in_mouse_face_p (struct window *, int, int); + + /*********************************************************************** Window display dimensions @@ -1782,8 +1783,6 @@ glyph_to_pixel_coords (struct window *w, int hpos, int vpos, } -#ifdef HAVE_WINDOW_SYSTEM - /* Find the glyph under window-relative coordinates X/Y in window W. Consider only glyphs from buffer text, i.e. no glyphs from overlay strings. Return in *HPOS and *VPOS the row and column number of @@ -1866,7 +1865,6 @@ x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos, return glyph; } - /* EXPORT: Convert frame-relative x/y to coordinates relative to window W. Takes pseudo-windows into account. */ @@ -1889,6 +1887,8 @@ frame_to_window_pixel_xy (struct window *w, int *x, int *y) } } +#ifdef HAVE_WINDOW_SYSTEM + /* EXPORT: Return in RECTS[] at most N clipping rectangles for glyph string S. Return the number of stored rectangles. */ @@ -15903,6 +15903,9 @@ try_window_id (struct window *w) + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0) + window_internal_height (w)); +#if defined (HAVE_GPM) || defined (MSDOS) + x_clear_window_mouse_face (w); +#endif /* Perform the operation on the screen. */ if (dvpos > 0) { @@ -23608,6 +23611,16 @@ x_clear_cursor (struct window *w) update_window_cursor (w, 0); } +void +draw_row_with_mouse_face (struct frame *w, int start_x, struct glyph_row *row, + int start_hpos, int end_hpos, + enum draw_glyphs_face draw) +{ + draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0); +} + + +#endif /* HAVE_WINDOW_SYSTEM */ /* EXPORT: Display the active region described by mouse_face_* according to DRAW. */ @@ -23695,15 +23708,15 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) if (end_hpos > start_hpos) { - draw_glyphs (w, start_x, row, TEXT_AREA, - start_hpos, end_hpos, - draw, 0); + draw_row_with_mouse_face (w, start_x, row, + start_hpos, end_hpos, draw); row->mouse_face_p = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED; } } +#ifdef HAVE_WINDOW_SYSTEM /* When we've written over the cursor, arrange for it to be displayed again. */ if (phys_cursor_on_p && !w->phys_cursor_on_p) @@ -23714,8 +23727,10 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) w->phys_cursor.x, w->phys_cursor.y); UNBLOCK_INPUT; } +#endif /* HAVE_WINDOW_SYSTEM */ } +#ifdef HAVE_WINDOW_SYSTEM /* Change the mouse cursor. */ if (draw == DRAW_NORMAL_TEXT && !EQ (dpyinfo->mouse_face_window, f->tool_bar_window)) FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor); @@ -23723,6 +23738,8 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor); else FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor); + +#endif /* HAVE_WINDOW_SYSTEM */ } /* EXPORT: @@ -24066,13 +24083,13 @@ mouse_face_from_buffer_pos (Lisp_Object window, start_charpos); /* If pos == 0, it means before_string came from an overlay, not from a buffer position. */ - if (!pos || pos >= start_charpos && pos < end_charpos) + if (!pos || (pos >= start_charpos && pos < end_charpos)) break; } else if (EQ (glyph->object, after_string)) { pos = string_buffer_position (w, after_string, end_charpos); - if (!pos || pos >= start_charpos && pos < end_charpos) + if (!pos || (pos >= start_charpos && pos < end_charpos)) break; } x += glyph->pixel_width; @@ -24116,13 +24133,13 @@ mouse_face_from_buffer_pos (Lisp_Object window, pos = string_buffer_position (w, before_string, start_charpos); /* If pos == 0, it means before_string came from an overlay, not from a buffer position. */ - if (!pos || pos >= start_charpos && pos < end_charpos) + if (!pos || (pos >= start_charpos && pos < end_charpos)) break; } else if (EQ (glyph->object, after_string)) { pos = string_buffer_position (w, after_string, end_charpos); - if (!pos || pos >= start_charpos && pos < end_charpos) + if (!pos || (pos >= start_charpos && pos < end_charpos)) break; } } @@ -24180,13 +24197,13 @@ mouse_face_from_buffer_pos (Lisp_Object window, if (EQ (end->object, before_string)) { pos = string_buffer_position (w, before_string, start_charpos); - if (!pos || pos >= start_charpos && pos < end_charpos) + if (!pos || (pos >= start_charpos && pos < end_charpos)) break; } else if (EQ (end->object, after_string)) { pos = string_buffer_position (w, after_string, end_charpos); - if (!pos || pos >= start_charpos && pos < end_charpos) + if (!pos || (pos >= start_charpos && pos < end_charpos)) break; } } @@ -24230,13 +24247,13 @@ mouse_face_from_buffer_pos (Lisp_Object window, if (EQ (end->object, before_string)) { pos = string_buffer_position (w, before_string, start_charpos); - if (!pos || pos >= start_charpos && pos < end_charpos) + if (!pos || (pos >= start_charpos && pos < end_charpos)) break; } else if (EQ (end->object, after_string)) { pos = string_buffer_position (w, after_string, end_charpos); - if (!pos || pos >= start_charpos && pos < end_charpos) + if (!pos || (pos >= start_charpos && pos < end_charpos)) break; } x += end->pixel_width; @@ -24460,6 +24477,8 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, } } +#ifdef HAVE_WINDOW_SYSTEM + /* See if position X, Y is within a hot-spot of an image. */ static int @@ -24630,6 +24649,8 @@ define_frame_cursor1 (struct frame *f, Cursor cursor, Lisp_Object pointer) FRAME_RIF (f)->define_frame_cursor (f, cursor); } +#endif /* HAVE_WINDOW_SYSTEM */ + /* Take proper action when mouse has moved to the mode or header line or marginal area AREA of window W, x-position X and y-position Y. X is relative to the start of the text display area of W, so the @@ -24643,7 +24664,11 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, struct window *w = XWINDOW (window); struct frame *f = XFRAME (w->frame); Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); +#ifdef HAVE_WINDOW_SYSTEM Cursor cursor = FRAME_X_OUTPUT (f)->nontext_cursor; +#else + Cursor cursor = No_Cursor; +#endif Lisp_Object pointer = Qnil; int dx, dy, width, height; EMACS_INT charpos; @@ -24695,6 +24720,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, help = Qnil; +#ifdef HAVE_WINDOW_SYSTEM if (IMAGEP (object)) { Lisp_Object image_map, hotspot; @@ -24731,6 +24757,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, if (NILP (pointer)) pointer = Fplist_get (XCDR (object), QCpointer); } +#endif /* HAVE_WINDOW_SYSTEM */ if (STRINGP (string)) { @@ -24750,6 +24777,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, } } +#ifdef HAVE_WINDOW_SYSTEM if (NILP (pointer)) pointer = Fget_text_property (pos, Qpointer, string); @@ -24763,6 +24791,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, if (!KEYMAPP (map)) cursor = dpyinfo->vertical_scroll_bar_cursor; } +#endif /* Change the mouse face according to what is under X/Y. */ mouse_face = Fget_text_property (pos, Qmouse_face, string); @@ -24895,7 +24924,9 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, else if ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)) clear_mouse_face (dpyinfo); } +#ifdef HAVE_WINDOW_SYSTEM define_frame_cursor1 (f, cursor, pointer); +#endif } @@ -24917,7 +24948,7 @@ note_mouse_highlight (struct frame *f, int x, int y) struct buffer *b; /* When a menu is active, don't highlight because this looks odd. */ -#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (MSDOS) if (popup_activated ()) return; #endif @@ -24961,6 +24992,7 @@ note_mouse_highlight (struct frame *f, int x, int y) w = XWINDOW (window); frame_to_window_pixel_xy (w, &x, &y); +#ifdef HAVE_WINDOW_SYSTEM /* Handle tool-bar window differently since it doesn't display a buffer. */ if (EQ (window, f->tool_bar_window)) @@ -24968,6 +25000,7 @@ note_mouse_highlight (struct frame *f, int x, int y) note_tool_bar_highlight (f, x, y); return; } +#endif /* Mouse is on the mode, header line or margin? */ if (part == ON_MODE_LINE || part == ON_HEADER_LINE @@ -24977,6 +25010,7 @@ note_mouse_highlight (struct frame *f, int x, int y) return; } +#ifdef HAVE_WINDOW_SYSTEM if (part == ON_VERTICAL_BORDER) { cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor; @@ -24987,6 +25021,7 @@ note_mouse_highlight (struct frame *f, int x, int y) cursor = FRAME_X_OUTPUT (f)->nontext_cursor; else cursor = FRAME_X_OUTPUT (f)->text_cursor; +#endif /* Are we in a window whose display is up to date? And verify the buffer's text has not changed. */ @@ -25010,6 +25045,7 @@ note_mouse_highlight (struct frame *f, int x, int y) /* Find the glyph under X/Y. */ glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area); +#ifdef HAVE_WINDOW_SYSTEM /* Look for :pointer property on image. */ if (glyph != NULL && glyph->type == IMAGE_GLYPH) { @@ -25051,11 +25087,18 @@ note_mouse_highlight (struct frame *f, int x, int y) pointer = Fplist_get (XCDR (img->spec), QCpointer); } } +#endif /* HAVE_WINDOW_SYSTEM */ /* Clear mouse face if X/Y not over text. */ if (glyph == NULL || area != TEXT_AREA || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p + /* Glyph's OBJECT is an integer for glyphs inserted by the + display engine for its internal purposes, like truncation + and continuation glyphs and blanks beyond the end of + line's text on text terminals. If we are over such a + glyph, we are not over any text. */ + || INTEGERP (glyph->object) /* R2L rows have a stretch glyph at their front, which stands for no text, whereas L2R rows have no glyphs at all beyond the end of text. Treat such stretch glyphs @@ -25067,6 +25110,7 @@ note_mouse_highlight (struct frame *f, int x, int y) { if (clear_mouse_face (dpyinfo)) cursor = No_Cursor; +#ifdef HAVE_WINDOW_SYSTEM if (NILP (pointer)) { if (area != TEXT_AREA) @@ -25074,6 +25118,7 @@ note_mouse_highlight (struct frame *f, int x, int y) else pointer = Vvoid_text_area_pointer; } +#endif goto set_cursor; } @@ -25323,6 +25368,7 @@ note_mouse_highlight (struct frame *f, int x, int y) } } +#ifdef HAVE_WINDOW_SYSTEM /* Look for a `pointer' property. */ if (NILP (pointer)) { @@ -25363,6 +25409,7 @@ note_mouse_highlight (struct frame *f, int x, int y) Qpointer, object); } } +#endif /* HAVE_WINDOW_SYSTEM */ BEGV = obegv; ZV = ozv; @@ -25371,7 +25418,13 @@ note_mouse_highlight (struct frame *f, int x, int y) set_cursor: +#ifdef HAVE_WINDOW_SYSTEM define_frame_cursor1 (f, cursor, pointer); +#else + /* This is here to prevent a compiler error, due to "label at end of + compound statement". */ + return; +#endif } @@ -25414,8 +25467,6 @@ cancel_mouse_face (struct frame *f) } -#endif /* HAVE_WINDOW_SYSTEM */ - /*********************************************************************** Exposure Events -- cgit v1.2.1 From 4c5111faf4a7e2be7dd87dd3e249c39cb3be252f Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 31 Oct 2010 20:50:02 +0200 Subject: Start redesigning portable mouse highlight. Not compiled. xdisp.c (get_tool_bar_item, handle_tool_bar_click) (note_tool_bar_highlight, draw_glyphs, erase_phys_cursor) (show_mouse_face, clear_mouse_face, coords_in_mouse_face_p) (note_mode_line_or_margin_highlight, note_mouse_highlight) (x_clear_window_mouse_face, cancel_mouse_face, expose_frame): Replace Display_Info with Mouse_HLInfo everywhere where mouse_face_* members were accessed for mouse highlight purposes. frame.h (MOUSE_HL_INFO): New macro. lisp.h (Mouse_HLInfo): New data type. xterm.h (struct x_display_info): w32term.h (struct w32_display_info): nsterm.h (struct ns_display_info): termchar.h (struct tty_display_info): Use it instead of mouse_face_* members. dispextern.h (DPYINFO_DEFINED): Remove definition. (FRAME_X_DISPLAY_INFO): Remove definition. (show_mouse_face, clear_mouse_face): Update type of 1st argument. --- src/xdisp.c | 386 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 200 insertions(+), 186 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 6339bb900af..97c2caeaeb7 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -10738,7 +10738,7 @@ static int get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph, int *hpos, int *vpos, int *prop_idx) { - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); struct window *w = XWINDOW (f->tool_bar_window); int area; @@ -10753,14 +10753,14 @@ get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph, return -1; /* Is mouse on the highlighted item? */ - if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window) - && *vpos >= dpyinfo->mouse_face_beg_row - && *vpos <= dpyinfo->mouse_face_end_row - && (*vpos > dpyinfo->mouse_face_beg_row - || *hpos >= dpyinfo->mouse_face_beg_col) - && (*vpos < dpyinfo->mouse_face_end_row - || *hpos < dpyinfo->mouse_face_end_col - || dpyinfo->mouse_face_past_end)) + if (EQ (f->tool_bar_window, hlinfo->mouse_face_window) + && *vpos >= hlinfo->mouse_face_beg_row + && *vpos <= hlinfo->mouse_face_end_row + && (*vpos > hlinfo->mouse_face_beg_row + || *hpos >= hlinfo->mouse_face_beg_col) + && (*vpos < hlinfo->mouse_face_end_row + || *hpos < hlinfo->mouse_face_end_col + || hlinfo->mouse_face_past_end)) return 0; return 1; @@ -10777,7 +10777,7 @@ void handle_tool_bar_click (struct frame *f, int x, int y, int down_p, unsigned int modifiers) { - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); struct window *w = XWINDOW (f->tool_bar_window); int hpos, vpos, prop_idx; struct glyph *glyph; @@ -10796,8 +10796,8 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, if (down_p) { /* Show item in pressed state. */ - show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN); - dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN; + show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN); + hlinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN; last_tool_bar_item = prop_idx; } else @@ -10807,8 +10807,8 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, EVENT_INIT (event); /* Show item in released state. */ - show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED); - dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED; + show_mouse_face (hlinfo, DRAW_IMAGE_RAISED); + hlinfo->mouse_face_image_state = DRAW_IMAGE_RAISED; key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY); @@ -10838,6 +10838,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y) Lisp_Object window = f->tool_bar_window; struct window *w = XWINDOW (window); Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); int hpos, vpos; struct glyph *glyph; struct glyph_row *row; @@ -10851,7 +10852,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y) values when mouse moves outside of the frame. */ if (x <= 0 || y <= 0) { - clear_mouse_face (dpyinfo); + clear_mouse_face (hlinfo); return; } @@ -10859,14 +10860,14 @@ note_tool_bar_highlight (struct frame *f, int x, int y) if (rc < 0) { /* Not on tool-bar item. */ - clear_mouse_face (dpyinfo); + clear_mouse_face (hlinfo); return; } else if (rc == 0) /* On same tool-bar item as before. */ goto set_help_echo; - clear_mouse_face (dpyinfo); + clear_mouse_face (hlinfo); /* Mouse is down, but on different tool-bar item? */ mouse_down_p = (dpyinfo->grabbed @@ -10876,7 +10877,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y) && last_tool_bar_item != prop_idx) return; - dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT; + hlinfo->mouse_face_image_state = DRAW_NORMAL_TEXT; draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED; /* If tool-bar item is not enabled, don't highlight it. */ @@ -10890,22 +10891,22 @@ note_tool_bar_highlight (struct frame *f, int x, int y) x += row->glyphs[TEXT_AREA][i].pixel_width; /* Record this as the current active region. */ - dpyinfo->mouse_face_beg_col = hpos; - dpyinfo->mouse_face_beg_row = vpos; - dpyinfo->mouse_face_beg_x = x; - dpyinfo->mouse_face_beg_y = row->y; - dpyinfo->mouse_face_past_end = 0; - - dpyinfo->mouse_face_end_col = hpos + 1; - dpyinfo->mouse_face_end_row = vpos; - dpyinfo->mouse_face_end_x = x + glyph->pixel_width; - dpyinfo->mouse_face_end_y = row->y; - dpyinfo->mouse_face_window = window; - dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID; + hlinfo->mouse_face_beg_col = hpos; + hlinfo->mouse_face_beg_row = vpos; + hlinfo->mouse_face_beg_x = x; + hlinfo->mouse_face_beg_y = row->y; + hlinfo->mouse_face_past_end = 0; + + hlinfo->mouse_face_end_col = hpos + 1; + hlinfo->mouse_face_end_row = vpos; + hlinfo->mouse_face_end_x = x + glyph->pixel_width; + hlinfo->mouse_face_end_y = row->y; + hlinfo->mouse_face_window = window; + hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID; /* Display it as active. */ - show_mouse_face (dpyinfo, draw); - dpyinfo->mouse_face_image_state = draw; + show_mouse_face (hlinfo, draw); + hlinfo->mouse_face_image_state = draw; } set_help_echo: @@ -21300,7 +21301,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, if (head && !overlaps && row->contains_overlapping_glyphs_p) { struct glyph_string *h, *t; - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); int mouse_beg_col, mouse_end_col, check_mouse_face = 0; int dummy_x = 0; @@ -21310,16 +21311,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, { struct glyph_row *mouse_beg_row, *mouse_end_row; - mouse_beg_row = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row); - mouse_end_row = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row); + mouse_beg_row = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row); + mouse_end_row = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row); if (row >= mouse_beg_row && row <= mouse_end_row) { check_mouse_face = 1; mouse_beg_col = (row == mouse_beg_row) - ? dpyinfo->mouse_face_beg_col : 0; + ? hlinfo->mouse_face_beg_col : 0; mouse_end_col = (row == mouse_end_row) - ? dpyinfo->mouse_face_end_col + ? hlinfo->mouse_face_end_col : row->used[TEXT_AREA]; } } @@ -23363,7 +23364,7 @@ void erase_phys_cursor (struct window *w) { struct frame *f = XFRAME (w->frame); - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); int hpos = w->phys_cursor.hpos; int vpos = w->phys_cursor.vpos; int mouse_face_here_p = 0; @@ -23419,7 +23420,7 @@ erase_phys_cursor (struct window *w) /* If the cursor is in the mouse face area, redisplay that when we clear the cursor. */ - if (! NILP (dpyinfo->mouse_face_window) + if (! NILP (hlinfo->mouse_face_window) && coords_in_mouse_face_p (w, hpos, vpos) /* Don't redraw the cursor's spot in mouse face if it is at the end of a line (on a newline). The cursor appears there, but @@ -23611,40 +23612,52 @@ x_clear_cursor (struct window *w) update_window_cursor (w, 0); } +#endif /* HAVE_WINDOW_SYSTEM */ + +/* Implementation of draw_row_with_mouse_face for GUI sessions and + GPM. MSDOS has its own implementation on msdos.c. */ +#ifndef MSDOS void -draw_row_with_mouse_face (struct frame *w, int start_x, struct glyph_row *row, +draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row, int start_hpos, int end_hpos, enum draw_glyphs_face draw) { - draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0); +#ifdef HAVE_WINDOW_SYSTEM + if (FRAME_WINDOW_P (XFRAME (w->frame))) + { + draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0); + return; + } +#endif +#ifdef HAVE_GPM + tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw); +#endif } - - -#endif /* HAVE_WINDOW_SYSTEM */ +#endif /* not MSDOS */ /* EXPORT: Display the active region described by mouse_face_* according to DRAW. */ void -show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) +show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) { - struct window *w = XWINDOW (dpyinfo->mouse_face_window); + struct window *w = XWINDOW (hlinfo->mouse_face_window); struct frame *f = XFRAME (WINDOW_FRAME (w)); if (/* If window is in the process of being destroyed, don't bother to do anything. */ w->current_matrix != NULL /* Don't update mouse highlight if hidden */ - && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden) + && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden) /* Recognize when we are called to operate on rows that don't exist anymore. This can happen when a window is split. */ - && dpyinfo->mouse_face_end_row < w->current_matrix->nrows) + && hlinfo->mouse_face_end_row < w->current_matrix->nrows) { int phys_cursor_on_p = w->phys_cursor_on_p; struct glyph_row *row, *first, *last; - first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row); - last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row); + first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row); + last = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row); for (row = first; row <= last && row->enabled_p; ++row) { @@ -23659,13 +23672,13 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) highlighted area in R2L rows. */ if (!row->reversed_p) { - start_hpos = dpyinfo->mouse_face_beg_col; - start_x = dpyinfo->mouse_face_beg_x; + start_hpos = hlinfo->mouse_face_beg_col; + start_x = hlinfo->mouse_face_beg_x; } else if (row == last) { - start_hpos = dpyinfo->mouse_face_end_col; - start_x = dpyinfo->mouse_face_end_x; + start_hpos = hlinfo->mouse_face_end_col; + start_x = hlinfo->mouse_face_end_x; } else { @@ -23675,8 +23688,8 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) } else if (row->reversed_p && row == last) { - start_hpos = dpyinfo->mouse_face_end_col; - start_x = dpyinfo->mouse_face_end_x; + start_hpos = hlinfo->mouse_face_end_col; + start_x = hlinfo->mouse_face_end_x; } else { @@ -23687,9 +23700,9 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) if (row == last) { if (!row->reversed_p) - end_hpos = dpyinfo->mouse_face_end_col; + end_hpos = hlinfo->mouse_face_end_col; else if (row == first) - end_hpos = dpyinfo->mouse_face_beg_col; + end_hpos = hlinfo->mouse_face_beg_col; else { end_hpos = row->used[TEXT_AREA]; @@ -23698,7 +23711,7 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) } } else if (row->reversed_p && row == first) - end_hpos = dpyinfo->mouse_face_beg_col; + end_hpos = hlinfo->mouse_face_beg_col; else { end_hpos = row->used[TEXT_AREA]; @@ -23732,7 +23745,7 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) #ifdef HAVE_WINDOW_SYSTEM /* Change the mouse cursor. */ - if (draw == DRAW_NORMAL_TEXT && !EQ (dpyinfo->mouse_face_window, f->tool_bar_window)) + if (draw == DRAW_NORMAL_TEXT && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)) FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor); else if (draw == DRAW_MOUSE_FACE) FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor); @@ -23748,20 +23761,20 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) face was actually drawn unhighlighted. */ int -clear_mouse_face (Display_Info *dpyinfo) +clear_mouse_face (Mouse_HLInfo *hlinfo) { int cleared = 0; - if (!dpyinfo->mouse_face_hidden && !NILP (dpyinfo->mouse_face_window)) + if (!hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window)) { - show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT); + show_mouse_face (hlinfo, DRAW_NORMAL_TEXT); cleared = 1; } - dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; - dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; - dpyinfo->mouse_face_window = Qnil; - dpyinfo->mouse_face_overlay = Qnil; + hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; + hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; + hlinfo->mouse_face_window = Qnil; + hlinfo->mouse_face_overlay = Qnil; return cleared; } @@ -23770,43 +23783,43 @@ clear_mouse_face (Display_Info *dpyinfo) static int coords_in_mouse_face_p (struct window *w, int hpos, int vpos) { - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame)); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); /* Quickly resolve the easy cases. */ - if (!(WINDOWP (dpyinfo->mouse_face_window) - && XWINDOW (dpyinfo->mouse_face_window) == w)) + if (!(WINDOWP (hlinfo->mouse_face_window) + && XWINDOW (hlinfo->mouse_face_window) == w)) return 0; - if (vpos < dpyinfo->mouse_face_beg_row - || vpos > dpyinfo->mouse_face_end_row) + if (vpos < hlinfo->mouse_face_beg_row + || vpos > hlinfo->mouse_face_end_row) return 0; - if (vpos > dpyinfo->mouse_face_beg_row - && vpos < dpyinfo->mouse_face_end_row) + if (vpos > hlinfo->mouse_face_beg_row + && vpos < hlinfo->mouse_face_end_row) return 1; if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p) { - if (dpyinfo->mouse_face_beg_row == dpyinfo->mouse_face_end_row) + if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row) { - if (dpyinfo->mouse_face_beg_col <= hpos && hpos < dpyinfo->mouse_face_end_col) + if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col) return 1; } - else if ((vpos == dpyinfo->mouse_face_beg_row - && hpos >= dpyinfo->mouse_face_beg_col) - || (vpos == dpyinfo->mouse_face_end_row - && hpos < dpyinfo->mouse_face_end_col)) + else if ((vpos == hlinfo->mouse_face_beg_row + && hpos >= hlinfo->mouse_face_beg_col) + || (vpos == hlinfo->mouse_face_end_row + && hpos < hlinfo->mouse_face_end_col)) return 1; } else { - if (dpyinfo->mouse_face_beg_row == dpyinfo->mouse_face_end_row) + if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row) { - if (dpyinfo->mouse_face_end_col < hpos && hpos <= dpyinfo->mouse_face_beg_col) + if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col) return 1; } - else if ((vpos == dpyinfo->mouse_face_beg_row - && hpos <= dpyinfo->mouse_face_beg_col) - || (vpos == dpyinfo->mouse_face_end_row - && hpos > dpyinfo->mouse_face_end_col)) + else if ((vpos == hlinfo->mouse_face_beg_row + && hpos <= hlinfo->mouse_face_beg_col) + || (vpos == hlinfo->mouse_face_end_row + && hpos > hlinfo->mouse_face_end_col)) return 1; } return 0; @@ -23947,7 +23960,7 @@ rows_from_pos_range (struct window *w, } } -/* This function sets the mouse_face_* elements of DPYINFO, assuming +/* This function sets the mouse_face_* elements of HLINFO, assuming the mouse cursor is on a glyph with buffer charpos MOUSE_CHARPOS in window WINDOW. START_CHARPOS and END_CHARPOS are buffer positions for the overlay or run of text properties specifying the mouse @@ -23958,7 +23971,7 @@ rows_from_pos_range (struct window *w, static void mouse_face_from_buffer_pos (Lisp_Object window, - Display_Info *dpyinfo, + Mouse_HLInfo *hlinfo, EMACS_INT mouse_charpos, EMACS_INT start_charpos, EMACS_INT end_charpos, @@ -24003,7 +24016,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, if (r2 == NULL) { r2 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); - dpyinfo->mouse_face_past_end = 1; + hlinfo->mouse_face_past_end = 1; } else if (!NILP (after_string)) { @@ -24032,10 +24045,10 @@ mouse_face_from_buffer_pos (Lisp_Object window, r1 = tem; } - dpyinfo->mouse_face_beg_y = r1->y; - dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix); - dpyinfo->mouse_face_end_y = r2->y; - dpyinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix); + hlinfo->mouse_face_beg_y = r1->y; + hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix); + hlinfo->mouse_face_end_y = r2->y; + hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix); /* For a bidi-reordered row, the positions of BEFORE_STRING, AFTER_STRING, DISPLAY_STRING, START_CHARPOS, and END_CHARPOS @@ -24094,8 +24107,8 @@ mouse_face_from_buffer_pos (Lisp_Object window, } x += glyph->pixel_width; } - dpyinfo->mouse_face_beg_x = x; - dpyinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA]; + hlinfo->mouse_face_beg_x = x; + hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA]; } else { @@ -24147,8 +24160,8 @@ mouse_face_from_buffer_pos (Lisp_Object window, glyph++; /* first glyph to the right of the highlighted area */ for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++) x += g->pixel_width; - dpyinfo->mouse_face_beg_x = x; - dpyinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA]; + hlinfo->mouse_face_beg_x = x; + hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA]; } /* If the highlight ends in a different row, compute GLYPH and END @@ -24211,8 +24224,8 @@ mouse_face_from_buffer_pos (Lisp_Object window, for (; glyph <= end; ++glyph) x += glyph->pixel_width; - dpyinfo->mouse_face_end_x = x; - dpyinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA]; + hlinfo->mouse_face_end_x = x; + hlinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA]; } else { @@ -24258,16 +24271,16 @@ mouse_face_from_buffer_pos (Lisp_Object window, } x += end->pixel_width; } - dpyinfo->mouse_face_end_x = x; - dpyinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA]; + hlinfo->mouse_face_end_x = x; + hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA]; } - dpyinfo->mouse_face_window = window; - dpyinfo->mouse_face_face_id + hlinfo->mouse_face_window = window; + hlinfo->mouse_face_face_id = face_at_buffer_position (w, mouse_charpos, 0, 0, &ignore, mouse_charpos + 1, - !dpyinfo->mouse_face_hidden, -1); - show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); + !hlinfo->mouse_face_hidden, -1); + show_mouse_face (hlinfo, DRAW_MOUSE_FACE); } /* The following function is not used anymore (replaced with @@ -24356,11 +24369,11 @@ fast_find_string_pos (struct window *w, EMACS_INT pos, Lisp_Object object, /* Find the positions of the first and the last glyphs in window W's current matrix that occlude positions [STARTPOS..ENDPOS] in OBJECT - (assumed to be a string), and return in DPYINFO's mouse_face + (assumed to be a string), and return in HLINFO's mouse_face_* members the pixel and column/row coordinates of those glyphs. */ static void -mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, +mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo, Lisp_Object object, EMACS_INT startpos, EMACS_INT endpos) { @@ -24385,10 +24398,10 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, if (EQ (g->object, object) && startpos <= g->charpos && g->charpos <= endpos) { - dpyinfo->mouse_face_beg_row = r - w->current_matrix->rows; - dpyinfo->mouse_face_beg_y = r->y; - dpyinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA]; - dpyinfo->mouse_face_beg_x = gx; + hlinfo->mouse_face_beg_row = r - w->current_matrix->rows; + hlinfo->mouse_face_beg_y = r->y; + hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA]; + hlinfo->mouse_face_beg_x = gx; found = 1; break; } @@ -24403,12 +24416,12 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, if (EQ ((g-1)->object, object) && startpos <= (g-1)->charpos && (g-1)->charpos <= endpos) { - dpyinfo->mouse_face_beg_row = r - w->current_matrix->rows; - dpyinfo->mouse_face_beg_y = r->y; - dpyinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA]; + hlinfo->mouse_face_beg_row = r - w->current_matrix->rows; + hlinfo->mouse_face_beg_y = r->y; + hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA]; for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1) gx += g1->pixel_width; - dpyinfo->mouse_face_beg_x = gx; + hlinfo->mouse_face_beg_x = gx; found = 1; break; } @@ -24442,8 +24455,8 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, r--; /* Set the end row and its vertical pixel coordinate. */ - dpyinfo->mouse_face_end_row = r - w->current_matrix->rows; - dpyinfo->mouse_face_end_y = r->y; + hlinfo->mouse_face_end_row = r - w->current_matrix->rows; + hlinfo->mouse_face_end_y = r->y; /* Compute and set the end column and the end column's horizontal pixel coordinate. */ @@ -24455,11 +24468,11 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, if (EQ ((e-1)->object, object) && startpos <= (e-1)->charpos && (e-1)->charpos <= endpos) break; - dpyinfo->mouse_face_end_col = e - g; + hlinfo->mouse_face_end_col = e - g; for (gx = r->x; g < e; ++g) gx += g->pixel_width; - dpyinfo->mouse_face_end_x = gx; + hlinfo->mouse_face_end_x = gx; } else { @@ -24472,8 +24485,8 @@ mouse_face_from_string_pos (struct window *w, Display_Info *dpyinfo, break; gx += e->pixel_width; } - dpyinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA]; - dpyinfo->mouse_face_end_x = gx; + hlinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA]; + hlinfo->mouse_face_end_x = gx; } } @@ -24663,8 +24676,9 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, { struct window *w = XWINDOW (window); struct frame *f = XFRAME (w->frame); - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); #ifdef HAVE_WINDOW_SYSTEM + Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); Cursor cursor = FRAME_X_OUTPUT (f)->nontext_cursor; #else Cursor cursor = No_Cursor; @@ -24871,58 +24885,58 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, /* 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) + if ( EQ (window, hlinfo->mouse_face_window) && (!row->reversed_p - ? (dpyinfo->mouse_face_beg_col <= hpos - && hpos < dpyinfo->mouse_face_end_col) + ? (hlinfo->mouse_face_beg_col <= hpos + && hpos < hlinfo->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 ) + : (hlinfo->mouse_face_end_col <= hpos + && hpos < hlinfo->mouse_face_beg_col)) + && hlinfo->mouse_face_beg_row == vpos ) return; - if (clear_mouse_face (dpyinfo)) + if (clear_mouse_face (hlinfo)) cursor = No_Cursor; if (!row->reversed_p) { - dpyinfo->mouse_face_beg_col = hpos; - dpyinfo->mouse_face_beg_x = original_x_pixel + hlinfo->mouse_face_beg_col = hpos; + hlinfo->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; + hlinfo->mouse_face_end_col = hpos + gseq_length; + hlinfo->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 + hlinfo->mouse_face_end_col = hpos; + hlinfo->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; + hlinfo->mouse_face_beg_col = hpos + gseq_length; + hlinfo->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_face_id = face_at_string_position (w, string, - charpos, - 0, 0, 0, - &ignore, - glyph->face_id, - 1); - show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); + hlinfo->mouse_face_beg_row = vpos; + hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row; + hlinfo->mouse_face_beg_y = 0; + hlinfo->mouse_face_end_y = 0; + hlinfo->mouse_face_past_end = 0; + hlinfo->mouse_face_window = window; + + hlinfo->mouse_face_face_id = face_at_string_position (w, string, + charpos, + 0, 0, 0, + &ignore, + glyph->face_id, + 1); + show_mouse_face (hlinfo, DRAW_MOUSE_FACE); if (NILP (pointer)) pointer = Qhand; } else if ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)) - clear_mouse_face (dpyinfo); + clear_mouse_face (hlinfo); } #ifdef HAVE_WINDOW_SYSTEM define_frame_cursor1 (f, cursor, pointer); @@ -24939,7 +24953,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, void note_mouse_highlight (struct frame *f, int x, int y) { - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); enum window_part part; Lisp_Object window; struct window *w; @@ -24958,16 +24972,16 @@ note_mouse_highlight (struct frame *f, int x, int y) || f->pointer_invisible) return; - dpyinfo->mouse_face_mouse_x = x; - dpyinfo->mouse_face_mouse_y = y; - dpyinfo->mouse_face_mouse_frame = f; + hlinfo->mouse_face_mouse_x = x; + hlinfo->mouse_face_mouse_y = y; + hlinfo->mouse_face_mouse_frame = f; - if (dpyinfo->mouse_face_defer) + if (hlinfo->mouse_face_defer) return; if (gc_in_progress) { - dpyinfo->mouse_face_deferred_gc = 1; + hlinfo->mouse_face_deferred_gc = 1; return; } @@ -24976,10 +24990,10 @@ note_mouse_highlight (struct frame *f, int x, int y) /* If we were displaying active text in another window, clear that. Also clear if we move out of text area in same window. */ - if (! EQ (window, dpyinfo->mouse_face_window) + if (! EQ (window, hlinfo->mouse_face_window) || (part != ON_TEXT && part != ON_MODE_LINE && part != ON_HEADER_LINE - && !NILP (dpyinfo->mouse_face_window))) - clear_mouse_face (dpyinfo); + && !NILP (hlinfo->mouse_face_window))) + clear_mouse_face (hlinfo); /* Not on a window -> return. */ if (!WINDOWP (window)) @@ -25108,7 +25122,7 @@ note_mouse_highlight (struct frame *f, int x, int y) && glyph->type == STRETCH_GLYPH && glyph->avoid_cursor_p)) { - if (clear_mouse_face (dpyinfo)) + if (clear_mouse_face (hlinfo)) cursor = No_Cursor; #ifdef HAVE_WINDOW_SYSTEM if (NILP (pointer)) @@ -25164,8 +25178,8 @@ note_mouse_highlight (struct frame *f, int x, int y) the one we are currently highlighting, we have to check if we enter the overlapping overlay, and then highlight only that. */ - || (OVERLAYP (dpyinfo->mouse_face_overlay) - && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay))) + || (OVERLAYP (hlinfo->mouse_face_overlay) + && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay))) { /* Find the highest priority overlay with a mouse-face. */ overlay = Qnil; @@ -25178,12 +25192,12 @@ note_mouse_highlight (struct frame *f, int x, int y) /* If we're highlighting the same overlay as before, there's no need to do that again. */ - if (!NILP (overlay) && EQ (overlay, dpyinfo->mouse_face_overlay)) + if (!NILP (overlay) && EQ (overlay, hlinfo->mouse_face_overlay)) goto check_help_echo; - dpyinfo->mouse_face_overlay = overlay; + hlinfo->mouse_face_overlay = overlay; /* Clear the display of the old active region, if any. */ - if (clear_mouse_face (dpyinfo)) + if (clear_mouse_face (hlinfo)) cursor = No_Cursor; /* If no overlay applies, get a text property. */ @@ -25207,14 +25221,14 @@ note_mouse_highlight (struct frame *f, int x, int y) b = make_number (0); if (NILP (e)) e = make_number (SCHARS (object) - 1); - mouse_face_from_string_pos (w, dpyinfo, object, + mouse_face_from_string_pos (w, hlinfo, object, XINT (b), XINT (e)); - dpyinfo->mouse_face_past_end = 0; - dpyinfo->mouse_face_window = window; - dpyinfo->mouse_face_face_id + hlinfo->mouse_face_past_end = 0; + hlinfo->mouse_face_window = window; + hlinfo->mouse_face_face_id = face_at_string_position (w, object, pos, 0, 0, 0, &ignore, glyph->face_id, 1); - show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); + show_mouse_face (hlinfo, DRAW_MOUSE_FACE); cursor = No_Cursor; } else @@ -25289,7 +25303,7 @@ note_mouse_highlight (struct frame *f, int x, int y) if (!STRINGP (after_string)) after_string = Qnil; } - mouse_face_from_buffer_pos (window, dpyinfo, pos, + mouse_face_from_buffer_pos (window, hlinfo, pos, XFASTINT (before), XFASTINT (after), before_string, after_string, @@ -25436,13 +25450,13 @@ note_mouse_highlight (struct frame *f, int x, int y) void x_clear_window_mouse_face (struct window *w) { - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame)); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); Lisp_Object window; BLOCK_INPUT; XSETWINDOW (window, w); - if (EQ (window, dpyinfo->mouse_face_window)) - clear_mouse_face (dpyinfo); + if (EQ (window, hlinfo->mouse_face_window)) + clear_mouse_face (hlinfo); UNBLOCK_INPUT; } @@ -25455,14 +25469,14 @@ void cancel_mouse_face (struct frame *f) { Lisp_Object window; - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); - window = dpyinfo->mouse_face_window; + window = hlinfo->mouse_face_window; if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f) { - dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; - dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; - dpyinfo->mouse_face_window = Qnil; + hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; + hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; + hlinfo->mouse_face_window = Qnil; } } @@ -25923,12 +25937,12 @@ expose_frame (struct frame *f, int x, int y, int w, int h) focus-follows-mouse with delayed raise. --jason 2001-10-12 */ if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f)) { - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); - if (f == dpyinfo->mouse_face_mouse_frame) + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); + if (f == hlinfo->mouse_face_mouse_frame) { - int x = dpyinfo->mouse_face_mouse_x; - int y = dpyinfo->mouse_face_mouse_y; - clear_mouse_face (dpyinfo); + int x = hlinfo->mouse_face_mouse_x; + int y = hlinfo->mouse_face_mouse_y; + clear_mouse_face (hlinfo); note_mouse_highlight (f, x, y); } } -- cgit v1.2.1 From f38880d344717f7d0f192c3e51dc56f7d2149748 Mon Sep 17 00:00:00 2001 From: Kenichi Handa Date: Mon, 1 Nov 2010 13:09:26 +0900 Subject: Handle glyphless characters on tty. --- src/xdisp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 52938417aac..ad90d57865b 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -5754,7 +5754,7 @@ static int (* get_next_element[NUM_IT_METHODS]) (struct it *it) = get_next_display_element for each character element, and from x_produce_glyphs when no suitable font was found. */ -static Lisp_Object +Lisp_Object lookup_glyphless_char_display (int c, struct it *it) { Lisp_Object glyphless_method = Qnil; @@ -5780,7 +5780,6 @@ lookup_glyphless_char_display (int c, struct it *it) /* This method can't be used for the no-font case. */ glyphless_method = Qempty_box; } - it->what = IT_GLYPHLESS; if (EQ (glyphless_method, Qthin_space)) it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE; else if (EQ (glyphless_method, Qempty_box)) @@ -5795,6 +5794,7 @@ lookup_glyphless_char_display (int c, struct it *it) glyphless_method = Qnil; goto retry; } + it->what = IT_GLYPHLESS; return glyphless_method; } @@ -5806,9 +5806,9 @@ static struct frame *last_escape_glyph_frame = NULL; static unsigned last_escape_glyph_face_id = (1 << FACE_ID_BITS); static int last_escape_glyph_merged_face_id = 0; -static struct frame *last_glyphless_glyph_frame = NULL; -static unsigned last_glyphless_glyph_face_id = (1 << FACE_ID_BITS); -static int last_glyphless_glyph_merged_face_id = 0; +struct frame *last_glyphless_glyph_frame = NULL; +unsigned last_glyphless_glyph_face_id = (1 << FACE_ID_BITS); +int last_glyphless_glyph_merged_face_id = 0; int get_next_display_element (struct it *it) @@ -22329,8 +22329,8 @@ append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len, /* Produce a glyph for a glyphless character for iterator IT. IT->glyphless_method specifies which method to use for displaying - the glyph. See the description of enum glyphless_display_method in - dispextern.h for the default of the display methods. + the character. See the description of enum + glyphless_display_method in dispextern.h for the detail. FOR_NO_FONT is nonzero if and only if this is for a character for which no font was found. ACRONYM, if non-nil, is an acronym string -- cgit v1.2.1 From e6fd145c233dca24da39bf988ed71fbdac420157 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 1 Nov 2010 22:09:03 +0200 Subject: Finish coding mouse highlight redesigned for portability. Not compiled yet. nsterm.m (ns_update_window_begin, ns_update_window_end) (ns_update_end, x_destroy_window, ns_frame_up_to_date) (ns_dumpglyphs_box_or_relief, ns_maybe_dumpglyphs_background) (ns_dumpglyphs_image, ns_dumpglyphs_stretch) (ns_initialize_display_info, keyDown, mouseMoved, mouseExited): Replace Display_Info with Mouse_HLInfo everywhere where mouse_face_* members were accessed for mouse highlight purposes. xterm.c (x_update_window_begin, x_update_window_end) (x_update_end, XTframe_up_to_date, x_set_mouse_face_gc) (handle_one_xevent, x_free_frame_resources, x_term_init): Replace Display_Info with Mouse_HLInfo everywhere where mouse_face_* members were accessed for mouse highlight purposes. w32term.c (x_update_window_begin, x_update_window_end) (x_update_end, w32_read_socket, x_free_frame_resources) (w32_initialize_display_info): Replace Display_Info with Mouse_HLInfo everywhere where mouse_face_* members were accessed for mouse highlight purposes. xdisp.c (show_mouse_face, note_mode_line_or_margin_highlight) (note_mouse_highlight) [HAVE_WINDOW_SYSTEM]: Don't run GUI code unless the frame is on a window-system. --- src/xdisp.c | 64 ++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 26 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 97c2caeaeb7..73dd7452ad0 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -23732,7 +23732,8 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) #ifdef HAVE_WINDOW_SYSTEM /* When we've written over the cursor, arrange for it to be displayed again. */ - if (phys_cursor_on_p && !w->phys_cursor_on_p) + if (FRAME_WINDOW_P (f) + && phys_cursor_on_p && !w->phys_cursor_on_p) { BLOCK_INPUT; display_and_set_cursor (w, 1, @@ -23745,13 +23746,16 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) #ifdef HAVE_WINDOW_SYSTEM /* Change the mouse cursor. */ - if (draw == DRAW_NORMAL_TEXT && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)) - FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor); - else if (draw == DRAW_MOUSE_FACE) - FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor); - else - FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor); - + if (FRAME_WINDOW_P (f)) + { + if (draw == DRAW_NORMAL_TEXT + && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)) + FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor); + else if (draw == DRAW_MOUSE_FACE) + FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor); + else + FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor); + } #endif /* HAVE_WINDOW_SYSTEM */ } @@ -24678,8 +24682,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, struct frame *f = XFRAME (w->frame); Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); #ifdef HAVE_WINDOW_SYSTEM - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); - Cursor cursor = FRAME_X_OUTPUT (f)->nontext_cursor; + Display_Info *dpyinfo; + Cursor cursor; #else Cursor cursor = No_Cursor; #endif @@ -24792,18 +24796,24 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, } #ifdef HAVE_WINDOW_SYSTEM - if (NILP (pointer)) - pointer = Fget_text_property (pos, Qpointer, string); - - /* Change the mouse pointer according to what is under X/Y. */ - if (NILP (pointer) && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE))) + if (FRAME_WINDOW_P (f)) { - Lisp_Object map; - map = Fget_text_property (pos, Qlocal_map, string); - if (!KEYMAPP (map)) - map = Fget_text_property (pos, Qkeymap, string); - if (!KEYMAPP (map)) - cursor = dpyinfo->vertical_scroll_bar_cursor; + dpyinfo = FRAME_X_DISPLAY_INFO (f); + cursor = FRAME_X_OUTPUT (f)->nontext_cursor; + if (NILP (pointer)) + pointer = Fget_text_property (pos, Qpointer, string); + + /* Change the mouse pointer according to what is under X/Y. */ + if (NILP (pointer) + && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE))) + { + Lisp_Object map; + map = Fget_text_property (pos, Qlocal_map, string); + if (!KEYMAPP (map)) + map = Fget_text_property (pos, Qkeymap, string); + if (!KEYMAPP (map)) + cursor = dpyinfo->vertical_scroll_bar_cursor; + } } #endif @@ -24939,7 +24949,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, clear_mouse_face (hlinfo); } #ifdef HAVE_WINDOW_SYSTEM - define_frame_cursor1 (f, cursor, pointer); + if (FRAME_WINDOW_P (f)) + define_frame_cursor1 (f, cursor, pointer); #endif } @@ -25125,7 +25136,7 @@ note_mouse_highlight (struct frame *f, int x, int y) if (clear_mouse_face (hlinfo)) cursor = No_Cursor; #ifdef HAVE_WINDOW_SYSTEM - if (NILP (pointer)) + if (FRAME_WINDOW_P (f) && NILP (pointer)) { if (area != TEXT_AREA) cursor = FRAME_X_OUTPUT (f)->nontext_cursor; @@ -25384,7 +25395,7 @@ note_mouse_highlight (struct frame *f, int x, int y) #ifdef HAVE_WINDOW_SYSTEM /* Look for a `pointer' property. */ - if (NILP (pointer)) + if (FRAME_WINDOW_P (f) && NILP (pointer)) { /* Check overlays first. */ for (i = noverlays - 1; i >= 0 && NILP (pointer); --i) @@ -25433,9 +25444,10 @@ note_mouse_highlight (struct frame *f, int x, int y) set_cursor: #ifdef HAVE_WINDOW_SYSTEM - define_frame_cursor1 (f, cursor, pointer); + if (FRAME_WINDOW_P (f)) + define_frame_cursor1 (f, cursor, pointer); #else - /* This is here to prevent a compiler error, due to "label at end of + /* This is here to prevent a compiler error, about "label at end of compound statement". */ return; #endif -- cgit v1.2.1 From 36f4c88d2fcb250044f76e50db76d0723b7f4873 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 5 Nov 2010 12:03:17 +0200 Subject: Cleanup fallout from redesigning mouse highlight. dispextern.h (tty_draw_row_with_mouse_face): Add prototype. xdisp.c (draw_row_with_mouse_face): Don't #ifdef away on MSDOS. Call tty_draw_row_with_mouse_face on MSDOS as well. msdos.c (tty_draw_row_with_mouse_face): Renamed from draw_row_with_mouse_face. Make the argument list identical to the GPM implementation. msdos.h (Display_Info): Restore typedef. --- src/xdisp.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 73dd7452ad0..275f762caa8 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -23614,9 +23614,8 @@ x_clear_cursor (struct window *w) #endif /* HAVE_WINDOW_SYSTEM */ -/* Implementation of draw_row_with_mouse_face for GUI sessions and - GPM. MSDOS has its own implementation on msdos.c. */ -#ifndef MSDOS +/* Implementation of draw_row_with_mouse_face for GUI sessions, GPM, + and MSDOS. */ void draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row, int start_hpos, int end_hpos, @@ -23629,11 +23628,10 @@ draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row, return; } #endif -#ifdef HAVE_GPM +#if defined (HAVE_GPM) || defined (MSDOS) tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw); #endif } -#endif /* not MSDOS */ /* EXPORT: Display the active region described by mouse_face_* according to DRAW. */ -- cgit v1.2.1 From 5a0ca18548b72856b8027977df773a4b6c425f40 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 5 Nov 2010 20:07:42 +0200 Subject: Fix unified mouse highlight after compiling on Unix. xdisp.c (x_consider_frame_title, tool_bar_lines_needed): Move prototypes to HAVE_WINDOW_SYSTEM-only part. frame.h (MOUSE_HL_INFO): Fix definition to work both for TTY-only and GUI builds. --- src/xdisp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 275f762caa8..732df80a2ac 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -960,10 +960,8 @@ static int text_outside_line_unchanged_p (struct window *, EMACS_INT, EMACS_INT); static void store_mode_line_noprop_char (char); static int store_mode_line_noprop (const unsigned char *, int, int); -static void x_consider_frame_title (Lisp_Object); static void handle_stop (struct it *); static void handle_stop_backwards (struct it *, EMACS_INT); -static int tool_bar_lines_needed (struct frame *, int *); static int single_display_spec_intangible_p (Lisp_Object); static void ensure_echo_area_buffers (void); static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object); @@ -1076,6 +1074,8 @@ static int in_ellipses_for_invisible_text_p (struct display_pos *, #ifdef HAVE_WINDOW_SYSTEM +static void x_consider_frame_title (Lisp_Object); +static int tool_bar_lines_needed (struct frame *, int *); static void update_tool_bar (struct frame *, int); static void build_desired_tool_bar_string (struct frame *f); static int redisplay_tool_bar (struct frame *); -- cgit v1.2.1 From 039874e124a55d630b2caf93f59848257b609828 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 5 Nov 2010 23:47:58 +0200 Subject: Cleanup -Wall warnings. xdisp.c (get_window_cursor_type): Move inside a HAVE_WINDOW_SYSTEM-only part. Remove "#ifdef HAVE_WINDOW_SYSTEM" from body of function. (null_glyph_slice): Move declaration into HAVE_WINDOW_SYSTEM-only part. --- src/xdisp.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 732df80a2ac..c3759da9a8f 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -888,6 +888,9 @@ static int clear_face_cache_count; #ifdef HAVE_WINDOW_SYSTEM #define CLEAR_IMAGE_CACHE_COUNT 101 static int clear_image_cache_count; + +/* Null glyph slice */ +static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 }; #endif /* Non-zero while redisplay_internal is in progress. */ @@ -913,10 +916,6 @@ EMACS_INT help_echo_pos; Lisp_Object previous_help_echo_string; -/* Null glyph slice */ - -static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 }; - /* Platform-independent portion of hourglass implementation. */ /* Non-zero means we're allowed to display a hourglass pointer. */ @@ -23038,6 +23037,8 @@ set_frame_cursor_types (struct frame *f, Lisp_Object arg) } +#ifdef HAVE_WINDOW_SYSTEM + /* Return the cursor we want to be displayed in window W. Return width of bar/hbar cursor through WIDTH arg. Return with ACTIVE_CURSOR arg set to 1 if cursor in window W is `active' @@ -23083,10 +23084,7 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width, /* Detect a nonselected window or nonselected frame. */ else if (w != XWINDOW (f->selected_window) -#ifdef HAVE_WINDOW_SYSTEM - || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame -#endif - ) + || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame) { *active_cursor = 0; @@ -23127,7 +23125,6 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width, /* Use normal cursor if not blinked off. */ if (!w->cursor_off_p) { -#ifdef HAVE_WINDOW_SYSTEM if (glyph != NULL && glyph->type == IMAGE_GLYPH) { if (cursor_type == FILLED_BOX_CURSOR) @@ -23155,7 +23152,6 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width, cursor_type = HOLLOW_BOX_CURSOR; } } -#endif return cursor_type; } @@ -23197,8 +23193,6 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width, } -#ifdef HAVE_WINDOW_SYSTEM - /* Notice when the text cursor of window W has been completely overwritten by a drawing operation that outputs glyphs in AREA starting at X0 and ending at X1 in the line starting at Y0 and -- cgit v1.2.1 From eaa8d1c82aa9e9cb253e530f60aa2a2904b92d3a Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 6 Nov 2010 20:19:32 +0200 Subject: xdisp.c: Add commentary about character compositions in bidirectional text. --- src/xdisp.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 0fb480980cb..b3da4654213 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -214,11 +214,41 @@ along with GNU Emacs. If not, see . */ leftmost character with special glyphs, which will display as, well, empty. On text terminals, these special glyphs are simply blank characters. On graphics terminals, there's a single stretch - glyph with suitably computed width. Both the blanks and the + glyph of a suitably computed width. Both the blanks and the stretch glyph are given the face of the background of the line. This way, the terminal-specific back-end can still draw the glyphs left to right, even for R2L lines. + Bidirectional display and character compositions + + Some scripts cannot be displayed by drawing each character + individually, because adjacent characters change each other's shape + on display. For example, Arabic and Indic scripts belong to this + category. + + Emacs display supports this by providing "character compositions", + most of which is implemented in composite.c. During the buffer + scan that delivers characters to PRODUCE_GLYPHS, if the next + character to be delivered is a composed character, the iteration + calls composition_reseat_it and next_element_from_composition. If + they succeed to compose the character with one or more of the + following characters, the whole sequence of characters that where + composed is recorded in the `struct composition_it' object that is + part of the buffer iterator. The composed sequence could produce + one or more font glyphs (called "grapheme clusters") on the screen. + Each of these grapheme clusters is then delivered to PRODUCE_GLYPHS + in the direction corresponding to the current bidi scan direction + (recorded in the scan_dir member of the `struct bidi_it' object + that is part of the buffer iterator). In particular, if the bidi + iterator currently scans the buffer backwards, the grapheme + clusters are delivered back to front. This reorders the grapheme + clusters as appropriate for the current bidi context. Note that + this means that the grapheme clusters are always stored in the + LGSTRING object (see composite.c) in the logical order. + + Moving an iterator in bidirectional text + without producing glyphs + Note one important detail mentioned above: that the bidi reordering engine, driven by the iterator, produces characters in R2L rows starting at the character that will be the rightmost on display. -- cgit v1.2.1 From 327500d6095e9f2ead25a8a207587c8865fa627a Mon Sep 17 00:00:00 2001 From: Jan D Date: Sun, 7 Nov 2010 12:16:54 +0100 Subject: * src/xdisp.c (note_mode_line_or_margin_highlight): Initialize Cursor to No_Cursor for HAVE_WINDOW_SYSTEM also. --- src/xdisp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index b3da4654213..928a37a2b50 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -25071,10 +25071,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); #ifdef HAVE_WINDOW_SYSTEM Display_Info *dpyinfo; - Cursor cursor; -#else - Cursor cursor = No_Cursor; #endif + Cursor cursor = No_Cursor; Lisp_Object pointer = Qnil; int dx, dy, width, height; EMACS_INT charpos; -- cgit v1.2.1 From 7cb1eea626efab87874ce030642dd4f60c2c0328 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 13 Nov 2010 15:29:31 +0200 Subject: Fix and document display of glyphless characters. src/xdisp.c (set_cursor_from_row): Fix cursor positioning on zero-width characters. (syms_of_xdisp) : Doc fix. src/.gdbinit (pgx): Adapt to latest changes in `struct glyph'. src/w32term.c (x_draw_glyphless_glyph_string_foreground): Draw the box before drawing the glyphs inside it. src/dispextern.h (enum glyphless_display_method): Rename GLYPHLESS_DISPLAY_HEXA_CODE to GLYPHLESS_DISPLAY_HEX_CODE. All users changed. src/term.c (append_glyphless_glyph, produce_glyphless_glyph): Fix comments. (produce_glyphless_glyph): Enclose "U+nnnn" and "empty box" whitespace in "[]", to simulate a box. Don't use uninitialized variable `width'. lisp/international/characters.el (glyphless-char-display-control): Renamed from glyphless-char-control; all users changed. Doc fix. Signal an error if display method is not one of the recognized symbols. doc/emacs/rmail.texi (Rmail Coding): Characters with no fonts are not necessarily displayed as empty boxes. doc/emacs/mule.texi (Language Environments, Fontsets): Characters with no fonts are not necessarily displayed as empty boxes. doc/emacs/display.texi (Text Display): Document display of glyphless characters. doc/lispref/display.texi (Usual Display): Characters with no fonts are not necessarily displayed as empty boxes. etc/NEWS: Document display of glyphless characters. --- src/xdisp.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 928a37a2b50..21c89088383 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -971,7 +971,7 @@ Lisp_Object Vglyphless_char_display; Lisp_Object Qglyphless_char_display; /* Method symbols for Vglyphless_char_display. */ -static Lisp_Object Qhexa_code, Qempty_box, Qthin_space, Qzero_width; +static Lisp_Object Qhex_code, Qempty_box, Qthin_space, Qzero_width; /* Default pixel width of `thin-space' display method. */ #define THIN_SPACE_WIDTH 1 @@ -5813,8 +5813,8 @@ lookup_glyphless_char_display (int c, struct it *it) it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE; else if (EQ (glyphless_method, Qempty_box)) it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX; - else if (EQ (glyphless_method, Qhexa_code)) - it->glyphless_method = GLYPHLESS_DISPLAY_HEXA_CODE; + else if (EQ (glyphless_method, Qhex_code)) + it->glyphless_method = GLYPHLESS_DISPLAY_HEX_CODE; else if (STRINGP (glyphless_method)) it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM; else @@ -12871,10 +12871,10 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, || (row->truncated_on_left_p && pt_old < bpos_min) || (row->truncated_on_right_p && pt_old > bpos_max) /* Zero-width characters produce no glyphs. */ - || ((row->reversed_p - ? glyph_after > glyphs_end - : glyph_after < glyphs_end) - && eabs (glyph_after - glyph_before) == 1)) + || (!string_seen + && (row->reversed_p + ? glyph_after > glyphs_end + : glyph_after < glyphs_end))) { cursor = glyph_after; x = -1; @@ -22292,7 +22292,7 @@ calc_line_height_property (struct it *it, Lisp_Object val, struct font *font, and only if this is for a character for which no font was found. If the display method (it->glyphless_method) is - GLYPHLESS_DISPLAY_ACRONYM or GLYPHLESS_DISPLAY_HEXA_CODE, LEN is a + GLYPHLESS_DISPLAY_ACRONYM or GLYPHLESS_DISPLAY_HEX_CODE, LEN is a length of the acronym or the hexadecimal string, UPPER_XOFF and UPPER_YOFF are pixel offsets for the upper part of the string, LOWER_XOFF and LOWER_YOFF are for the lower part. @@ -22441,7 +22441,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) } else { - xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEXA_CODE); + xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE); sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c); str = buf; } @@ -27057,7 +27057,7 @@ cursor shapes. */); hourglass_shown_p = 0; DEFSYM (Qglyphless_char, "glyphless-char"); - DEFSYM (Qhexa_code, "hexa-code"); + DEFSYM (Qhex_code, "hex-code"); DEFSYM (Qempty_box, "empty-box"); DEFSYM (Qthin_space, "thin-space"); DEFSYM (Qzero_width, "zero-width"); @@ -27073,13 +27073,13 @@ cursor shapes. */); doc: /* Char-table to control displaying of glyphless characters. Each element, if non-nil, is an ASCII acronym string (displayed in a box) or one of these symbols: - hexa-code: display with hexadecimal character code in a box - empty-box: display with an empty box - thin-space: display with 1-pixel width space + hex-code: display the hexadecimal code of a character in a box + empty-box: display as an empty box + thin-space: display as 1-pixel width space zero-width: don't display It has one extra slot to control the display of a character for which -no font is found. The value of the slot is `hexa-code' or `empty-box'. +no font is found. The value of the slot is `hex-code' or `empty-box'. The default is `empty-box'. */); Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil); Fset_char_table_extra_slot (Vglyphless_char_display, make_number (0), -- cgit v1.2.1 From b29e53668ce07192c39e019d1c31264535a9fde4 Mon Sep 17 00:00:00 2001 From: Chong Yidong Date: Tue, 16 Nov 2010 14:59:24 -0500 Subject: Cleanup of window coordinate positioning code. Now, text area click input events measure Y from the top of the text area, excluding the header line if any. * src/dispnew.c (buffer_posn_from_coords): Assume that X counts from the start of the text area. * src/keyboard.c (make_lispy_position): For text area clicks, record Y pixel position relative to the text area, excluding header line. Also change X and Y to Lisp_Objects, not pointers; don't return coordinate values via pointers. Pass ON_TEXT_AREA coordinate to buffer_posn_from_coords counting from the start of the text area. (Fposn_at_x_y, make_lispy_event): Callers changed. * src/w32term.c (w32_read_socket): * src/msdos.c (dos_rawgetc): * src/xterm.c (handle_one_xevent): Likewise. * src/window.c (coordinates_in_window): Change X and Y to ints rather than pointers; don't return coordinates via pointers. (struct check_window_data): Change X and Y from pointers to ints. (window_from_coordinates): Remove args WX and WY; don't return coordinates via pointers. (Fcoordinates_in_window_p, window_from_coordinates): (check_window_containing, Fwindow_at): Callers changed. (window_relative_x_coord): New function. * src/window.h (window_from_coordinates, window_relative_x_coord): Update prototypes. * src/xdisp.c (remember_mouse_glyph): Change window_from_coordinates call. Use window_relative_x_coord. (note_mouse_highlight): Change window_from_coordinates call. --- src/xdisp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 21c89088383..d3ebc1a4a8a 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2218,7 +2218,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) frame pixel coordinates X/Y on frame F. */ if (!f->glyphs_initialized_p - || (window = window_from_coordinates (f, gx, gy, &part, &x, &y, 0), + || (window = window_from_coordinates (f, gx, gy, &part, 0), NILP (window))) { width = FRAME_SMALLEST_CHAR_WIDTH (f); @@ -2230,6 +2230,9 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) width = WINDOW_FRAME_COLUMN_WIDTH (w); height = WINDOW_FRAME_LINE_HEIGHT (w); + x = window_relative_x_coord (w, part, gx); + y = gy - WINDOW_TOP_EDGE_Y (w); + r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w); @@ -25383,7 +25386,7 @@ note_mouse_highlight (struct frame *f, int x, int y) } /* Which window is that in? */ - window = window_from_coordinates (f, x, y, &part, 0, 0, 1); + window = window_from_coordinates (f, x, y, &part, 1); /* If we were displaying active text in another window, clear that. Also clear if we move out of text area in same window. */ -- cgit v1.2.1 From 795e66cb3abfa02f1347c45ac97f0047470ef568 Mon Sep 17 00:00:00 2001 From: Chong Yidong Date: Tue, 16 Nov 2010 16:47:43 -0500 Subject: Revert changes in revision 102407 --- src/xdisp.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index d3ebc1a4a8a..21c89088383 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2218,7 +2218,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) frame pixel coordinates X/Y on frame F. */ if (!f->glyphs_initialized_p - || (window = window_from_coordinates (f, gx, gy, &part, 0), + || (window = window_from_coordinates (f, gx, gy, &part, &x, &y, 0), NILP (window))) { width = FRAME_SMALLEST_CHAR_WIDTH (f); @@ -2230,9 +2230,6 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) width = WINDOW_FRAME_COLUMN_WIDTH (w); height = WINDOW_FRAME_LINE_HEIGHT (w); - x = window_relative_x_coord (w, part, gx); - y = gy - WINDOW_TOP_EDGE_Y (w); - r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w); @@ -25386,7 +25383,7 @@ note_mouse_highlight (struct frame *f, int x, int y) } /* Which window is that in? */ - window = window_from_coordinates (f, x, y, &part, 1); + window = window_from_coordinates (f, x, y, &part, 0, 0, 1); /* If we were displaying active text in another window, clear that. Also clear if we move out of text area in same window. */ -- cgit v1.2.1 From 3cbbd1c570fbb39dd5c291aa2e202cea79e1031c Mon Sep 17 00:00:00 2001 From: Chong Yidong Date: Tue, 16 Nov 2010 21:37:45 -0500 Subject: Cleanup of window coordinate positioning code. Now, text area click input events measure Y from the top of the text area, excluding the header line if any. * src/dispnew.c (buffer_posn_from_coords): Assume that X counts from the start of the text area. * src/keyboard.c (make_lispy_position): For text area clicks, record Y pixel position relative to the text area, excluding header line. Also change X and Y to Lisp_Objects, not pointers; don't return coordinate values via pointers. Pass ON_TEXT_AREA coordinate to buffer_posn_from_coords counting from the start of the text area. (Fposn_at_x_y, make_lispy_event): Callers changed. * src/w32term.c (w32_read_socket): * src/msdos.c (dos_rawgetc): * src/xterm.c (handle_one_xevent): Likewise. * src/window.c (coordinates_in_window): Change X and Y to ints rather than pointers; don't return coordinates via pointers. (struct check_window_data): Change X and Y from pointers to ints. (window_from_coordinates): Remove args WX and WY; don't return coordinates via pointers. (Fcoordinates_in_window_p, window_from_coordinates): (check_window_containing, Fwindow_at): Callers changed. (window_relative_x_coord): New function. * src/window.h (window_from_coordinates, window_relative_x_coord): Update prototypes. * src/xdisp.c (remember_mouse_glyph): Change window_from_coordinates call. Use window_relative_x_coord. (note_mouse_highlight): Change window_from_coordinates call. --- src/xdisp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index 21c89088383..d3ebc1a4a8a 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2218,7 +2218,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) frame pixel coordinates X/Y on frame F. */ if (!f->glyphs_initialized_p - || (window = window_from_coordinates (f, gx, gy, &part, &x, &y, 0), + || (window = window_from_coordinates (f, gx, gy, &part, 0), NILP (window))) { width = FRAME_SMALLEST_CHAR_WIDTH (f); @@ -2230,6 +2230,9 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) width = WINDOW_FRAME_COLUMN_WIDTH (w); height = WINDOW_FRAME_LINE_HEIGHT (w); + x = window_relative_x_coord (w, part, gx); + y = gy - WINDOW_TOP_EDGE_Y (w); + r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w); @@ -25383,7 +25386,7 @@ note_mouse_highlight (struct frame *f, int x, int y) } /* Which window is that in? */ - window = window_from_coordinates (f, x, y, &part, 0, 0, 1); + window = window_from_coordinates (f, x, y, &part, 1); /* If we were displaying active text in another window, clear that. Also clear if we move out of text area in same window. */ -- cgit v1.2.1 From 9a8be9c89d8dd0348b59e4c21eae5649ebcfe9c8 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Wed, 17 Nov 2010 21:15:24 +0200 Subject: Fix bug #7417 with cursor positioning on empty lines. xdisp.c (set_cursor_from_row): Fix cursor positioning in empty lines on text-mode terminals. --- src/xdisp.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index d3ebc1a4a8a..e02abf6a5b5 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -12839,6 +12839,15 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, && BUFFERP (glyph->object) && glyph->charpos == pt_old) && bpos_covered < pt_old) { + /* An empty line has a single glyph whose OBJECT is zero and + whose CHARPOS is the position of a newline on that line. + Note that on a TTY, there are more glyphs after that, which + were produced by extend_face_to_end_of_line, but their + CHARPOS is zero or negative. */ + int empty_line_p = + (row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end) + && INTEGERP (glyph->object) && glyph->charpos > 0; + if (row->ends_in_ellipsis_p && pos_after == last_pos) { EMACS_INT ellipsis_pos; @@ -12875,6 +12884,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, || (row->truncated_on_right_p && pt_old > bpos_max) /* Zero-width characters produce no glyphs. */ || (!string_seen + && !empty_line_p && (row->reversed_p ? glyph_after > glyphs_end : glyph_after < glyphs_end))) -- cgit v1.2.1 From 275ef532eae62a9e98df6e5811725044da40125c Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 19 Nov 2010 18:34:22 +0200 Subject: Fix bug #6687 with cursor positioning after before-string from overlays. xdisp.c (set_cursor_from_row): Display cursor after all the glyphs that come from an overlay. Don't overstep the last glyph when skipping glyphs from an overlay. --- src/xdisp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index e02abf6a5b5..b2d81cb60e9 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -12941,7 +12941,8 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, cursor on that character's glyph. */ EMACS_INT strpos = glyph->charpos; - cursor = glyph; + if (tem) + cursor = glyph; for (glyph += incr; (row->reversed_p ? glyph > stop : glyph < stop) && EQ (glyph->object, str); @@ -12958,7 +12959,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, cursor = glyph; break; } - if (glyph->charpos < strpos) + if (tem && glyph->charpos < strpos) { strpos = glyph->charpos; cursor = glyph; @@ -12973,10 +12974,9 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, } /* This string is not what we want; skip all of the glyphs that came from it. */ - do - glyph += incr; while ((row->reversed_p ? glyph > stop : glyph < stop) - && EQ (glyph->object, str)); + && EQ (glyph->object, str)) + glyph += incr; } else glyph += incr; -- cgit v1.2.1 From ee548aaae755d02a12533e09e224bc41f65e6db1 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Thu, 25 Nov 2010 20:38:09 +0200 Subject: Fix bug #7474 with cursor positioning in overlay strings. xdisp.c (set_cursor_from_row): Don't forget to consider the `cursor' property of the first character in overlay strings. --- src/xdisp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index b2d81cb60e9..fd80d7a0208 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -12943,7 +12943,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, if (tem) cursor = glyph; - for (glyph += incr; + for ( ; (row->reversed_p ? glyph > stop : glyph < stop) && EQ (glyph->object, str); glyph += incr) -- cgit v1.2.1 From 37d08cf9f4f2d4dabef7c5d5eb5b5bb44e722744 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 26 Nov 2010 21:10:26 +0200 Subject: Force left-to-right paragraph direction in echo area and prog-mode buffers. src/xdisp.c (set_message_1): Force paragraph direction in echo area be left-to-right. lisp/simple.el (prog-mode): Set bidi-paragraph-direction to left-to-right. --- src/xdisp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/xdisp.c') diff --git a/src/xdisp.c b/src/xdisp.c index fd80d7a0208..77e9db2e5eb 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -9384,6 +9384,8 @@ set_message_1 (EMACS_INT a1, Lisp_Object a2, EMACS_INT nbytes, EMACS_INT multiby Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil); current_buffer->truncate_lines = message_truncate_lines ? Qt : Qnil; + if (!NILP (current_buffer->bidi_display_reordering)) + current_buffer->bidi_paragraph_direction = Qleft_to_right; /* Insert new message at BEG. */ TEMP_SET_PT_BOTH (BEG, BEG_BYTE); -- cgit v1.2.1