# HG changeset patch # User Eli Zaretskii # Date 1271768915 -10800 # Node ID 8ef8b652359711ee27490dfe180aac92e22ef9f2 # Parent 1afd4d56683f47d8c700f2262e16f6fa9450e8ff 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. diff -r 1afd4d56683f -r 8ef8b6523597 src/ChangeLog --- a/src/ChangeLog Sat Apr 17 19:02:18 2010 +0300 +++ b/src/ChangeLog Tue Apr 20 16:08:35 2010 +0300 @@ -1,5 +1,21 @@ +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. + 2010-04-17 Eli Zaretskii + Continue work on R2L paragraphs in GUI sessions. + * xdisp.c (extend_face_to_end_of_line): Fix off-by-one error on TTY frames in testing whether a line needs face extension. @@ -22,8 +38,6 @@ which happens with R2L glyph rows. Fixes a crash when inserting a character at end of an R2L line. - Continue work on R2L paragraphs in GUI sessions. - * xdisp.c (set_cursor_from_row): Don't be fooled by truncated rows: don't treat them as having zero-width characters. Improve comments. diff -r 1afd4d56683f -r 8ef8b6523597 src/term.c --- a/src/term.c Sat Apr 17 19:02:18 2010 +0300 +++ b/src/term.c Tue Apr 20 16:08:35 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; diff -r 1afd4d56683f -r 8ef8b6523597 src/xdisp.c --- a/src/xdisp.c Sat Apr 17 19:02:18 2010 +0300 +++ b/src/xdisp.c Tue Apr 20 16:08:35 2010 +0300 @@ -17203,6 +17203,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 @@ -17467,6 +17492,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 @@ -17489,6 +17517,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; @@ -17524,6 +17555,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. */ @@ -17629,9 +17663,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) { @@ -17882,7 +17929,8 @@ /* The next row should use same value of the reversed_p flag as this one. set_iterator_to_next decides when it's a new paragraph, and PRODUCE_GLYPHS recomputes the value of the flag accordingly. */ - it->glyph_row->reversed_p = row->reversed_p; + if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w)) + it->glyph_row->reversed_p = row->reversed_p; it->start = row_end; return row->displays_text_p; } @@ -21486,6 +21534,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;