# HG changeset patch # User Eli Zaretskii # Date 1271770288 -10800 # Node ID 531d454c3a995a083a1826529796eb50b3526219 # Parent d94009e7a0cc52ae3aa430a06e5ad21042faa374# Parent 8ef8b652359711ee27490dfe180aac92e22ef9f2 Implement GUI display of R2L lines, fix TTY display of R2L lines. xdisp.c [HAVE_WINDOW_SYSTEM]: Add prototype for append_stretch_glyph. (set_cursor_from_row) : Remove unused variable. Fix off-by-one error in computing x at end of text in the row. (append_stretch_glyph): In reversed row, prepend the glyph rather than append it. Set resolved_level and bidi_type of the glyph. (extend_face_to_end_of_line): If the row is reversed, prepend a stretch glyph whose width is such that the rightmost glyph will be drawn at the right margin of the window. Fix off-by-one error on TTY frames in testing whether a line needs face extension. Fix face extension at ZV. If this is the last glyph row, use DEFAULT_FACE_ID, to avoid painting the rest of the window with the region face. (set_cursor_from_row, display_line): Use MATRIX_ROW_CONTINUATION_LINE_P instead of testing value of row->continuation_lines_width. (next_element_from_buffer): Don't call bidi_paragraph_init if we are at ZV. Fixes a crash when reseated to ZV by try_window_reusing_current_matrix. (display_and_set_cursor, erase_phys_cursor): Handle negative HPOS, which happens with R2L glyph rows. Fixes a crash when inserting a character at end of an R2L line. (set_cursor_from_row): Don't be fooled by truncated rows: don't treat them as having zero-width characters. Improve comments. 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. (IT_OVERFLOW_NEWLINE_INTO_FRINGE): For R2L lines, consider the left fringe, not the right one. (notice_overwritten_cursor, draw_phys_cursor_glyph) (erase_phys_cursor): For reversed cursor_row, support cursor on the left fringe. fringe.c (update_window_fringes): For R2L rows, swap the bitmaps of continuation indicators on the fringes. (draw_fringe_bitmap): For reversed glyph rows, allow 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. 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 (unproduce_glyphs): New function. (display_line): Use it when produced glyphs are discarded from R2L glyph rows. (append_composite_glyph): In R2L rows, prepend the glyph rather than appending it. term.c (append_composite_glyph): In R2L rows, prepend the glyph rather than append it. Set up the resolved_level and bidi_type attributes of the appended glyph. (produce_special_glyphs): Mirror the backslash continuation character in R2L lines. diff -r d94009e7a0cc -r 531d454c3a99 src/ChangeLog --- a/src/ChangeLog Tue Apr 20 13:38:30 2010 +0200 +++ b/src/ChangeLog Tue Apr 20 16:31:28 2010 +0300 @@ -1,3 +1,70 @@ +2010-04-20 Eli Zaretskii + + Fix R2L paragraph display on TTY. + + * xdisp.c (unproduce_glyphs): New function. + (display_line): Use it when produced glyphs are discarded from R2L + glyph rows. + (append_composite_glyph): In R2L rows, prepend the glyph rather + than appending it. + + * term.c (append_composite_glyph): In R2L rows, prepend the glyph + rather than append it. Set up the resolved_level and bidi_type + attributes of the appended glyph. + (produce_special_glyphs): Mirror the backslash continuation + character in R2L lines. + + Implement display of R2L paragraphs in GUI sessions. + + * xdisp.c [HAVE_WINDOW_SYSTEM]: Add prototype for + append_stretch_glyph. + (set_cursor_from_row) : Remove unused variable. Fix + off-by-one error in computing x at end of text in the row. + (append_stretch_glyph): In reversed row, prepend the glyph rather + than append it. Set resolved_level and bidi_type of the glyph. + (extend_face_to_end_of_line): If the row is reversed, prepend a + stretch glyph whose width is such that the rightmost glyph will be + drawn at the right margin of the window. Fix off-by-one error on + TTY frames in testing whether a line needs face extension. Fix + face extension at ZV. If this is the last glyph row, use + DEFAULT_FACE_ID, to avoid painting the rest of the window with the + region face. + (set_cursor_from_row, display_line): Use + MATRIX_ROW_CONTINUATION_LINE_P instead of testing value of + row->continuation_lines_width. + (next_element_from_buffer): Don't call bidi_paragraph_init if we + are at ZV. Fixes a crash when reseated to ZV by + try_window_reusing_current_matrix. + (display_and_set_cursor, erase_phys_cursor): Handle negative HPOS, + which happens with R2L glyph rows. Fixes a crash when inserting a + character at end of an R2L line. + (set_cursor_from_row): Don't be fooled by truncated rows: don't + treat them as having zero-width characters. Improve comments. + 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. + (IT_OVERFLOW_NEWLINE_INTO_FRINGE): For R2L lines, consider the + left fringe, not the right one. + (notice_overwritten_cursor, draw_phys_cursor_glyph) + (erase_phys_cursor): For reversed cursor_row, support cursor on + the left fringe. + + * fringe.c (update_window_fringes): For R2L rows, swap the bitmaps + of continuation indicators on the fringes. + (draw_fringe_bitmap): For reversed glyph rows, allow 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. + + * 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. + 2010-04-20 Jan Djärv * gtkutil.c (xg_event_is_for_scrollbar): Check if grabbed diff -r d94009e7a0cc -r 531d454c3a99 src/dispnew.c --- a/src/dispnew.c Tue Apr 20 13:38:30 2010 +0200 +++ b/src/dispnew.c Tue Apr 20 16:31:28 2010 +0300 @@ -4251,7 +4251,9 @@ 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 @@ } /* 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 -r d94009e7a0cc -r 531d454c3a99 src/fringe.c --- a/src/fringe.c Tue Apr 20 13:38:30 2010 +0200 +++ b/src/fringe.c Tue Apr 20 16:31:28 2010 +0300 @@ -825,7 +825,7 @@ { 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 @@ 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; } } @@ -1090,7 +1090,8 @@ : LEFT_FRINGE (2, Qtop, 0)); else if (row->indicate_eob_p && EQ (boundary_bot, Qleft)) left = LEFT_FRINGE (3, Qbottom, row->ends_at_zv_p); - else if (MATRIX_ROW_CONTINUATION_LINE_P (row)) + else if ((!row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row)) + || (row->reversed_p && row->continued_p)) left = LEFT_FRINGE (4, Qcontinuation, 0); else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft)) left = LEFT_FRINGE (5, Qempty_line, 0); @@ -1117,7 +1118,8 @@ : RIGHT_FRINGE (2, Qtop, 0)); else if (row->indicate_eob_p && EQ (boundary_bot, Qright)) right = RIGHT_FRINGE (3, Qbottom, row->ends_at_zv_p); - else if (row->continued_p) + else if ((!row->reversed_p && row->continued_p) + || (row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row))) right = RIGHT_FRINGE (4, Qcontinuation, 0); else if (row->indicate_top_line_p && EQ (arrow_top, Qright)) right = RIGHT_FRINGE (6, Qup, 0); diff -r d94009e7a0cc -r 531d454c3a99 src/term.c --- a/src/term.c Tue Apr 20 13:38:30 2010 +0200 +++ b/src/term.c Tue Apr 20 16:31:28 2010 +0300 @@ -1589,7 +1589,6 @@ } } - /* Produce glyphs for the display element described by IT. *IT specifies what we want to produce a glyph for (character, image, ...), and where in the glyph matrix we currently are (glyph row and hpos). @@ -1808,6 +1807,17 @@ glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area]; if (glyph < it->glyph_row->glyphs[1 + it->area]) { + /* If the glyph row is reversed, we need to prepend the glyph + rather than append it. */ + if (it->glyph_row->reversed_p && it->area == TEXT_AREA) + { + struct glyph *g; + + /* Make room for the new glyph. */ + for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--) + g[1] = *g; + glyph = it->glyph_row->glyphs[it->area]; + } glyph->type = COMPOSITE_GLYPH; glyph->pixel_width = it->pixel_width; glyph->u.cmp.id = it->cmp_it.id; @@ -1828,6 +1838,18 @@ glyph->padding_p = 0; glyph->charpos = CHARPOS (it->position); glyph->object = it->object; + 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; + } + else + { + glyph->resolved_level = 0; + glyph->bidi_type = UNKNOWN_BT; + } ++it->glyph_row->used[it->area]; ++glyph; @@ -1889,12 +1911,16 @@ if (what == IT_CONTINUATION) { - /* Continuation glyph. */ - SET_GLYPH_FROM_CHAR (glyph, '\\'); + /* Continuation glyph. For R2L lines, we mirror it by hand. */ + if (it->bidi_it.paragraph_dir == R2L) + SET_GLYPH_FROM_CHAR (glyph, '/'); + else + SET_GLYPH_FROM_CHAR (glyph, '\\'); if (it->dp && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)) && GLYPH_CODE_CHAR_VALID_P (gc)) { + /* FIXME: Should we mirror GC for R2L lines? */ SET_GLYPH_FROM_GLYPH_CODE (glyph, gc); spec_glyph_lookup_face (XWINDOW (it->window), &glyph); } @@ -1907,6 +1933,7 @@ && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)) && GLYPH_CODE_CHAR_VALID_P (gc)) { + /* FIXME: Should we mirror GC for R2L lines? */ SET_GLYPH_FROM_GLYPH_CODE (glyph, gc); spec_glyph_lookup_face (XWINDOW (it->window), &glyph); } diff -r d94009e7a0cc -r 531d454c3a99 src/w32term.c --- a/src/w32term.c Tue Apr 20 13:38:30 2010 +0200 +++ b/src/w32term.c Tue Apr 20 16:31:28 2010 +0300 @@ -5136,10 +5136,12 @@ } 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 -r d94009e7a0cc -r 531d454c3a99 src/xdisp.c --- a/src/xdisp.c Tue Apr 20 13:38:30 2010 +0200 +++ b/src/xdisp.c Tue Apr 20 16:31:28 2010 +0300 @@ -404,12 +404,14 @@ /* 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 @@ -1077,6 +1079,8 @@ static void notice_overwritten_cursor P_ ((struct window *, enum glyph_row_area, int, int, int, int)); +static void append_stretch_glyph P_ ((struct it *, Lisp_Object, + int, int, int)); @@ -6709,13 +6713,20 @@ { it->bidi_it.charpos = IT_CHARPOS (*it); it->bidi_it.bytepos = IT_BYTEPOS (*it); - /* If we are at the beginning of a line, we can produce the next - element right away. */ - if (it->bidi_it.bytepos == BEGV_BYTE + if (it->bidi_it.bytepos == ZV_BYTE) + { + /* Nothing to do, but reset the FIRST_ELT flag, like + bidi_paragraph_init does, because we are not going to + call it. */ + it->bidi_it.first_elt = 0; + } + else if (it->bidi_it.bytepos == BEGV_BYTE /* FIXME: Should support all Unicode line separators. */ || FETCH_CHAR (it->bidi_it.bytepos - 1) == '\n' || FETCH_CHAR (it->bidi_it.bytepos) == '\n') { + /* If we are at the beginning of a line, we can produce the + next element right away. */ bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it); bidi_get_next_char_visually (&it->bidi_it); } @@ -12619,7 +12630,6 @@ /* The last known character position in row. */ int last_pos = MATRIX_ROW_START_CHARPOS (row) + delta; int x = row->x; - int cursor_x = x; EMACS_INT pt_old = PT - delta; EMACS_INT pos_before = MATRIX_ROW_START_CHARPOS (row) + delta; EMACS_INT pos_after = MATRIX_ROW_END_CHARPOS (row) + delta; @@ -12655,8 +12665,8 @@ } while (end > glyph && INTEGERP ((end - 1)->object) - /* CHARPOS is zero for blanks inserted by - extend_face_to_end_of_line. */ + /* CHARPOS is zero for blanks and stretch glyphs + inserted by extend_face_to_end_of_line. */ && (end - 1)->charpos <= 0) --end; glyph_before = glyph - 1; @@ -12670,9 +12680,6 @@ 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) @@ -12687,7 +12694,6 @@ rightmost (first in the reading order) glyph. */ for (g = end + 1; g < glyph; g++) x += g->pixel_width; - cursor_x = x; while (end < glyph && INTEGERP ((end + 1)->object) && (end + 1)->charpos <= 0) @@ -12702,7 +12708,7 @@ rightmost glyph. Case in point: an empty last line that is part of an R2L paragraph. */ cursor = end - 1; - x = -1; /* will be computed below, at lable compute_x */ + x = -1; /* will be computed below, at label compute_x */ } /* Step 1: Try to find the glyph whose character position @@ -12838,8 +12844,11 @@ string_seen = 1; } --glyph; - if (glyph == end) - break; + if (glyph == glyphs_end) /* don't dereference outside TEXT_AREA */ + { + x--; /* can't use any pixel_width */ + break; + } x -= glyph->pixel_width; } @@ -12879,7 +12888,10 @@ } else if (match_with_avoid_cursor /* zero-width characters produce no glyphs */ - || eabs (glyph_after - glyph_before) == 1) + || ((row->reversed_p + ? glyph_after > glyphs_end + : glyph_after < glyphs_end) + && eabs (glyph_after - glyph_before) == 1)) { cursor = glyph_after; x = -1; @@ -12998,16 +13010,17 @@ } } - /* ROW could be part of a continued line, which might have other - rows whose start and end charpos occlude point. Only set - w->cursor if we found a better approximation to the cursor - position than we have from previously examined rows. */ + /* ROW could be part of a continued line, which, under bidi + reordering, might have other rows whose start and end charpos + occlude point. Only set w->cursor if we found a better + approximation to the cursor position than we have from previously + examined candidate rows belonging to the same continued line. */ if (/* we already have a candidate row */ w->cursor.vpos >= 0 /* that candidate is not the row we are processing */ && MATRIX_ROW (matrix, w->cursor.vpos) != row - /* this row is part of a continued line */ - && (row->continued_p || row->continuation_lines_width) + /* the row we are processing is part of a continued line */ + && (row->continued_p || MATRIX_ROW_CONTINUATION_LINE_P (row)) /* Make sure cursor.vpos specifies a row whose start and end charpos occlude point. This is because some callers of this function leave cursor.vpos at the row where the cursor was @@ -16850,9 +16863,11 @@ /* Extend the face of the last glyph in the text area of IT->glyph_row - to the end of the display line. Called from display_line. - If the glyph row is empty, add a space glyph to it so that we - know the face to draw. Set the glyph row flag fill_line_p. */ + to the end of the display line. Called from display_line. If the + glyph row is empty, add a space glyph to it so that we know the + face to draw. Set the glyph row flag fill_line_p. If the glyph + row is R2L, prepend a stretch glyph to cover the empty space to the + left of the leftmost glyph. */ static void extend_face_to_end_of_line (it) @@ -16861,15 +16876,17 @@ struct face *face; struct frame *f = it->f; - /* If line is already filled, do nothing. */ - if (it->current_x >= it->last_visible_x) + /* If line is already filled, do nothing. Non window-system frames + get a grace of one more ``pixel'' because their characters are + 1-``pixel'' wide, so they hit the equality too early. */ + if (it->current_x >= it->last_visible_x + !FRAME_WINDOW_P (f)) return; /* Face extension extends the background and box of IT->face_id to the end of the line. If the background equals the background of the frame, we don't have to do anything. */ if (it->face_before_selective_p) - face = FACE_FROM_ID (it->f, it->saved_face_id); + face = FACE_FROM_ID (f, it->saved_face_id); else face = FACE_FROM_ID (f, it->face_id); @@ -16877,7 +16894,8 @@ && it->glyph_row->displays_text_p && face->box == FACE_NO_BOX && face->background == FRAME_BACKGROUND_PIXEL (f) - && !face->stipple) + && !face->stipple + && !it->glyph_row->reversed_p) return; /* Set the glyph row flag indicating that the face of the last glyph @@ -16904,6 +16922,50 @@ it->glyph_row->glyphs[TEXT_AREA][0].face_id = it->face_id; it->glyph_row->used[TEXT_AREA] = 1; } +#ifdef HAVE_WINDOW_SYSTEM + if (it->glyph_row->reversed_p) + { + /* Prepend a stretch glyph to the row, such that the + rightmost glyph will be drawn flushed all the way to the + right margin of the window. The stretch glyph that will + occupy the empty space, if any, to the left of the + glyphs. */ + struct font *font = face->font ? face->font : FRAME_FONT (f); + struct glyph *row_start = it->glyph_row->glyphs[TEXT_AREA]; + struct glyph *row_end = row_start + it->glyph_row->used[TEXT_AREA]; + struct glyph *g; + int row_width, stretch_ascent, stretch_width; + struct text_pos saved_pos; + int saved_face_id, saved_avoid_cursor; + + for (row_width = 0, g = row_start; g < row_end; g++) + row_width += g->pixel_width; + stretch_width = window_box_width (it->w, TEXT_AREA) - row_width; + if (stretch_width > 0) + { + stretch_ascent = + (((it->ascent + it->descent) + * FONT_BASE (font)) / FONT_HEIGHT (font)); + saved_pos = it->position; + bzero (&it->position, sizeof it->position); + saved_avoid_cursor = it->avoid_cursor_p; + it->avoid_cursor_p = 1; + saved_face_id = it->face_id; + /* The last row's stretch glyph should get the default + face, to avoid painting the rest of the window with + the region face, if the region ends at ZV. */ + if (it->glyph_row->ends_at_zv_p) + it->face_id = DEFAULT_FACE_ID; + else + 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 */ } else { @@ -16922,7 +16984,13 @@ it->object = make_number (0); it->c = ' '; it->len = 1; - it->face_id = face->id; + /* The last row's blank glyphs should get the default face, to + avoid painting the rest of the window with the region face, + if the region ends at ZV. */ + if (it->glyph_row->ends_at_zv_p) + it->face_id = DEFAULT_FACE_ID; + else + it->face_id = face->id; PRODUCE_GLYPHS (it); @@ -17208,6 +17276,31 @@ +/* Remove N glyphs at the start of a reversed IT->glyph_row. Called + only for R2L lines from display_line, when it decides that too many + glyphs were produced by PRODUCE_GLYPHS, and the line needs to be + continued. */ +static void +unproduce_glyphs (it, n) + struct it *it; + int n; +{ + struct glyph *glyph, *end; + + xassert (it->glyph_row); + xassert (it->glyph_row->reversed_p); + xassert (it->area == TEXT_AREA); + xassert (n <= it->glyph_row->used[TEXT_AREA]); + + if (n > it->glyph_row->used[TEXT_AREA]) + n = it->glyph_row->used[TEXT_AREA]; + glyph = it->glyph_row->glyphs[TEXT_AREA] + n; + end = it->glyph_row->glyphs[TEXT_AREA] + it->glyph_row->used[TEXT_AREA]; + for ( ; glyph < end; glyph++) + glyph[-n] = *glyph; +} + + /* Construct the glyph row IT->glyph_row in the desired matrix of IT->w from text at the current position of IT. See dispextern.h for an overview of struct it. Value is non-zero if @@ -17472,6 +17565,9 @@ /* A padding glyph that doesn't fit on this line. This means the whole character doesn't fit on the line. */ + if (row->reversed_p) + unproduce_glyphs (it, row->used[TEXT_AREA] + - n_glyphs_before); row->used[TEXT_AREA] = n_glyphs_before; /* Fill the rest of the row with continuation @@ -17494,6 +17590,9 @@ else if (wrap_row_used > 0) { back_to_wrap: + if (row->reversed_p) + unproduce_glyphs (it, + row->used[TEXT_AREA] - wrap_row_used); *it = wrap_it; it->continuation_lines_width += wrap_x; row->used[TEXT_AREA] = wrap_row_used; @@ -17529,6 +17628,9 @@ /* Something other than a TAB that draws past the right edge of the window. Restore positions to values before the element. */ + if (row->reversed_p) + unproduce_glyphs (it, row->used[TEXT_AREA] + - (n_glyphs_before + i)); row->used[TEXT_AREA] = n_glyphs_before + i; /* Display continuation glyphs. */ @@ -17634,9 +17736,22 @@ { int i, n; - for (i = row->used[TEXT_AREA] - 1; i > 0; --i) - if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i])) - break; + if (!row->reversed_p) + { + for (i = row->used[TEXT_AREA] - 1; i > 0; --i) + if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i])) + break; + } + else + { + for (i = 0; i < row->used[TEXT_AREA]; i++) + if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i])) + break; + /* Remove padding glyphs at the front of ROW, to + make room for the truncation glyphs we will be + adding below. */ + unproduce_glyphs (it, i); + } for (n = row->used[TEXT_AREA]; i < n; ++i) { @@ -17823,7 +17938,7 @@ *it = save_it; } else if (!row->continued_p - && row->continuation_lines_width + && MATRIX_ROW_CONTINUATION_LINE_P (row) && it->eol_pos.charpos > 0) { /* Last row of a continued line. Use the position @@ -21493,6 +21608,17 @@ 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 && it->area == TEXT_AREA) + { + struct glyph *g; + + /* Make room for the new glyph. */ + for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--) + g[1] = *g; + glyph = it->glyph_row->glyphs[it->area]; + } glyph->charpos = CHARPOS (it->position); glyph->object = it->object; glyph->pixel_width = it->pixel_width; @@ -21738,6 +21864,17 @@ 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 = object; glyph->pixel_width = width; @@ -21764,6 +21901,11 @@ abort (); glyph->bidi_type = it->bidi_it.type; } + else + { + glyph->resolved_level = 0; + glyph->bidi_type = UNKNOWN_BT; + } ++it->glyph_row->used[area]; } else @@ -23244,7 +23386,7 @@ 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; } @@ -23345,7 +23487,9 @@ /* 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; @@ -23425,7 +23569,7 @@ 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; } @@ -23434,7 +23578,9 @@ 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 @@ -23450,7 +23596,7 @@ /* 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. */ - && cursor_row->used[TEXT_AREA] > hpos) + && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0) mouse_face_here_p = 1; /* Maybe clear the display under the cursor. */ @@ -23532,7 +23678,7 @@ glyph = NULL; if (!glyph_row->exact_window_width_line_p - || hpos < glyph_row->used[TEXT_AREA]) + || (0 <= hpos && hpos < glyph_row->used[TEXT_AREA])) glyph = glyph_row->glyphs[TEXT_AREA] + hpos; xassert (interrupt_input_blocked); diff -r d94009e7a0cc -r 531d454c3a99 src/xterm.c --- a/src/xterm.c Tue Apr 20 13:38:30 2010 +0200 +++ b/src/xterm.c Tue Apr 20 16:31:28 2010 +0300 @@ -7492,36 +7492,40 @@ 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; - - 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 HBAR_CURSOR: - x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR); - break; - - case NO_CURSOR: - w->phys_cursor_width = 0; - break; - - default: - abort (); + 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 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 NO_CURSOR: + w->phys_cursor_width = 0; + break; + + default: + abort (); + } } #ifdef HAVE_X_I18N