From f951a50681995aa58a427f0be801c682df6e5baa Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 10 Apr 2010 19:28:30 +0300 Subject: [PATCH] Implement cursor on the left fringe for R2L lines. xdisp.c (IT_OVERFLOW_NEWLINE_INTO_FRINGE): For R2L lines, consider the left fringe, not the right one. (set_cursor_from_row): Don't reverse pos_before and pos_after for reversed glyph rows. Set cursor.x to negative value when the cursor might be on the left fringe. (extend_face_to_end_of_line): Append the stretch glyph only if its width is positive. (notice_overwritten_cursor, draw_phys_cursor_glyph) (erase_phys_cursor): For reversed cursor_row, support cursor on the left fringe. w32term.c (w32_draw_window_cursor): For reversed glyph rows, draw cursor on the left fringe. xterm.c (x_draw_window_cursor): For reversed glyph rows, draw cursor on the left fringe. fringe.c (draw_fringe_bitmap): For reversed glyph rows, allow cursor on the left fringe. dispnew.c (update_text_area): Handle reversed desired rows when the cursor is on the left fringe. (set_window_cursor_after_update): Limit cursor's hpos by -1 from below, not by 0, for when the cursor is on the left fringe. --- src/ChangeLog | 25 ++++++++++++++++++++ src/dispnew.c | 6 +++-- src/fringe.c | 4 ++-- src/w32term.c | 6 +++-- src/xdisp.c | 65 +++++++++++++++++++++++++++++---------------------- src/xterm.c | 44 ++++++++++++++++++---------------- 6 files changed, 96 insertions(+), 54 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 268a245caf3..e6faa0a4c9e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -2,6 +2,31 @@ Implement display of R2L paragraphs in GUI sessions. + * xdisp.c (IT_OVERFLOW_NEWLINE_INTO_FRINGE): For R2L lines, + consider the left fringe, not the right one. + (set_cursor_from_row): Don't reverse pos_before and pos_after for + reversed glyph rows. Set cursor.x to negative value when the + cursor might be on the left fringe. + (extend_face_to_end_of_line): Append the stretch glyph only if its + width is positive. + (notice_overwritten_cursor, draw_phys_cursor_glyph) + (erase_phys_cursor): For reversed cursor_row, support cursor on + the left fringe. + + * w32term.c (w32_draw_window_cursor): For reversed glyph rows, + draw cursor on the left fringe. + + * xterm.c (x_draw_window_cursor): For reversed glyph rows, draw + cursor on the left fringe. + + * fringe.c (draw_fringe_bitmap): For reversed glyph rows, allow + cursor on the left fringe. + + * dispnew.c (update_text_area): Handle reversed desired rows when + the cursor is on the left fringe. + (set_window_cursor_after_update): Limit cursor's hpos by -1 from + below, not by 0, for when the cursor is on the left fringe. + * xdisp.c [HAVE_WINDOW_SYSTEM]: Add prototype for append_stretch_glyph. (set_cursor_from_row) : Remove unused variable. Fix diff --git a/src/dispnew.c b/src/dispnew.c index 2be00c9c3b0..7ab2bf35811 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -4251,7 +4251,9 @@ update_text_area (w, vpos) doesn't work with lbearing/rbearing), so we must do it this way. */ if (vpos == w->phys_cursor.vpos - && w->phys_cursor.hpos >= desired_row->used[TEXT_AREA]) + && (desired_row->reversed_p + ? (w->phys_cursor.hpos < 0) + : (w->phys_cursor.hpos >= desired_row->used[TEXT_AREA]))) { w->phys_cursor_on_p = 0; x = -1; @@ -4415,7 +4417,7 @@ set_window_cursor_after_update (w) } /* Window cursor can be out of sync for horizontally split windows. */ - hpos = max (0, hpos); + hpos = max (-1, hpos); /* -1 is for when cursor is on the left fringe */ hpos = min (w->current_matrix->matrix_w - 1, hpos); vpos = max (0, vpos); vpos = min (w->current_matrix->nrows - 1, vpos); diff --git a/src/fringe.c b/src/fringe.c index 952e95a5517..335dde03c8a 100644 --- a/src/fringe.c +++ b/src/fringe.c @@ -825,7 +825,7 @@ draw_fringe_bitmap (w, row, left_p) { int overlay = 0; - if (!left_p && row->cursor_in_fringe_p) + if (left_p == row->reversed_p && row->cursor_in_fringe_p) { Lisp_Object cursor = Qnil; @@ -857,7 +857,7 @@ draw_fringe_bitmap (w, row, left_p) int bm = get_logical_cursor_bitmap (w, cursor); if (bm != NO_FRINGE_BITMAP) { - draw_fringe_bitmap_1 (w, row, 0, 2, bm); + draw_fringe_bitmap_1 (w, row, left_p, 2, bm); overlay = EQ (cursor, Qbox) ? 3 : 1; } } diff --git a/src/w32term.c b/src/w32term.c index 7222e26efd2..0b71b7e02b7 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -5136,10 +5136,12 @@ w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, act } if (glyph_row->exact_window_width_line_p - && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA]) + && (glyph_row->reversed_p + ? (w->phys_cursor.hpos < 0) + : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA]))) { glyph_row->cursor_in_fringe_p = 1; - draw_fringe_bitmap (w, glyph_row, 0); + draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p); return; } diff --git a/src/xdisp.c b/src/xdisp.c index f93ed533c28..1320b8a7380 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -326,12 +326,14 @@ extern Lisp_Object Voverflow_newline_into_fringe; /* Test if overflow newline into fringe. Called with iterator IT at or past right window margin, and with IT->current_x set. */ -#define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) \ - (!NILP (Voverflow_newline_into_fringe) \ - && FRAME_WINDOW_P (it->f) \ - && WINDOW_RIGHT_FRINGE_WIDTH (it->w) > 0 \ - && it->current_x == it->last_visible_x \ - && it->line_wrap != WORD_WRAP) +#define IT_OVERFLOW_NEWLINE_INTO_FRINGE(IT) \ + (!NILP (Voverflow_newline_into_fringe) \ + && FRAME_WINDOW_P ((IT)->f) \ + && ((IT)->bidi_it.paragraph_dir == R2L \ + ? (WINDOW_LEFT_FRINGE_WIDTH ((IT)->w) > 0) \ + : (WINDOW_RIGHT_FRINGE_WIDTH ((IT)->w) > 0)) \ + && (IT)->current_x == (IT)->last_visible_x \ + && (IT)->line_wrap != WORD_WRAP) #else /* !HAVE_WINDOW_SYSTEM */ #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) 0 @@ -12600,9 +12602,6 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) to front, so swap the edge pointers. */ glyphs_end = end = glyph - 1; glyph += row->used[TEXT_AREA] - 1; - /* Reverse the known positions in the row. */ - last_pos = pos_after = MATRIX_ROW_START_CHARPOS (row) + delta; - pos_before = MATRIX_ROW_END_CHARPOS (row) + delta; while (glyph > end + 1 && INTEGERP (glyph->object) @@ -12768,7 +12767,10 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) } --glyph; if (glyph == glyphs_end) /* don't dereference outside TEXT_AREA */ - break; + { + x--; /* can't use any pixel_width */ + break; + } x -= glyph->pixel_width; } @@ -16851,20 +16853,23 @@ extend_face_to_end_of_line (it) - WINDOW_BOX_LEFT_EDGE_X(it->w) - WINDOW_TOTAL_FRINGE_WIDTH(it->w) - row_width; - stretch_ascent = - (((it->ascent + it->descent) - * FONT_BASE (font)) / FONT_HEIGHT (font)); - saved_pos = it->position; - saved_avoid_cursor = it->avoid_cursor_p; - saved_face_id = it->face_id; - bzero (&it->position, sizeof it->position); - it->avoid_cursor_p = 1; - it->face_id = face->id; - append_stretch_glyph (it, make_number (0), stretch_width, - it->ascent + it->descent, stretch_ascent); - it->position = saved_pos; - it->avoid_cursor_p = saved_avoid_cursor; - it->face_id = saved_face_id; + if (stretch_width > 0) + { + stretch_ascent = + (((it->ascent + it->descent) + * FONT_BASE (font)) / FONT_HEIGHT (font)); + saved_pos = it->position; + saved_avoid_cursor = it->avoid_cursor_p; + saved_face_id = it->face_id; + bzero (&it->position, sizeof it->position); + it->avoid_cursor_p = 1; + it->face_id = face->id; + append_stretch_glyph (it, make_number (0), stretch_width, + it->ascent + it->descent, stretch_ascent); + it->position = saved_pos; + it->avoid_cursor_p = saved_avoid_cursor; + it->face_id = saved_face_id; + } } #endif /* HAVE_WINDOW_SYSTEM */ } @@ -23221,7 +23226,7 @@ notice_overwritten_cursor (w, area, x0, x1, y0, y1) if (row->cursor_in_fringe_p) { row->cursor_in_fringe_p = 0; - draw_fringe_bitmap (w, row, 0); + draw_fringe_bitmap (w, row, row->reversed_p); w->phys_cursor_on_p = 0; return; } @@ -23322,7 +23327,9 @@ draw_phys_cursor_glyph (w, row, hl) /* If cursor hpos is out of bounds, don't draw garbage. This can happen in mini-buffer windows when switching between echo area glyphs and mini-buffer. */ - if (w->phys_cursor.hpos < row->used[TEXT_AREA]) + if ((row->reversed_p + ? (w->phys_cursor.hpos >= 0) + : (w->phys_cursor.hpos < row->used[TEXT_AREA]))) { int on_p = w->phys_cursor_on_p; int x1; @@ -23402,7 +23409,7 @@ erase_phys_cursor (w) if (cursor_row->cursor_in_fringe_p) { cursor_row->cursor_in_fringe_p = 0; - draw_fringe_bitmap (w, cursor_row, 0); + draw_fringe_bitmap (w, cursor_row, cursor_row->reversed_p); goto mark_cursor_off; } @@ -23411,7 +23418,9 @@ erase_phys_cursor (w) should have cleared the cursor. Note that we wouldn't be able to erase the cursor in this case because we don't have a cursor glyph at hand. */ - if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA]) + if ((cursor_row->reversed_p + ? (w->phys_cursor.hpos < 0) + : (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA]))) goto mark_cursor_off; /* If the cursor is in the mouse face area, redisplay that when diff --git a/src/xterm.c b/src/xterm.c index 29ed5bb865c..712d4aaa162 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -7492,36 +7492,40 @@ x_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, activ w->phys_cursor_on_p = 1; if (glyph_row->exact_window_width_line_p - && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA]) + && (glyph_row->reversed_p + ? (w->phys_cursor.hpos < 0) + : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA]))) { glyph_row->cursor_in_fringe_p = 1; - draw_fringe_bitmap (w, glyph_row, 0); + draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p); } else - switch (cursor_type) { - case HOLLOW_BOX_CURSOR: - x_draw_hollow_cursor (w, glyph_row); - break; + switch (cursor_type) + { + case HOLLOW_BOX_CURSOR: + x_draw_hollow_cursor (w, glyph_row); + break; - case FILLED_BOX_CURSOR: - draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); - break; + case FILLED_BOX_CURSOR: + draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); + break; - case BAR_CURSOR: - x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR); - break; + case BAR_CURSOR: + x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR); + break; - case HBAR_CURSOR: - x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR); - break; + case HBAR_CURSOR: + x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR); + break; - case NO_CURSOR: - w->phys_cursor_width = 0; - break; + case NO_CURSOR: + w->phys_cursor_width = 0; + break; - default: - abort (); + default: + abort (); + } } #ifdef HAVE_X_I18N -- 2.39.2