From 5e65aec01a9bc5a147e492f11dd0115c98bedef4 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 1 Jan 2010 06:39:56 -0500 Subject: [PATCH] Retrospective commit from 2009-10-17. Continue working on display of R2L glyph rows. Reverse glyphs in term.c:append_glyph rather than in extend_face_to_end_of_line. Fix bidi iteration near BEGV and ZV. dispextern.h (struct glyph): New members resolved_level and bidi_type. xdisp.c (append_glyph, append_composite_glyph) (produce_image_glyph, append_stretch_glyph): Set them. term.c (append_glyph): Ditto. xdisp.c (display_line, next_element_from_buffer): Set the glyph row's reversed_p flag if the paragraph base direction is odd. (extend_face_to_end_of_line): Don't reverse the glyphs here. term.c (append_glyph): Reverse glyphs here. bidi.c (bidi_get_next_char_visually): Don't exit early when at ZV. (bidi_paragraph_init): Don't step over a newline if at BEGV. (bidi_paragraph_init): Handle empty buffers. --- src/ChangeLog.bidi | 24 ++++++++++++++++++++++++ src/bidi.c | 13 ++++++++----- src/dispextern.h | 7 +++++++ src/term.c | 25 +++++++++++++++++++++++++ src/xdisp.c | 53 ++++++++++++++++++++++++++++++++--------------------- 5 files changed, 96 insertions(+), 26 deletions(-) diff --git a/src/ChangeLog.bidi b/src/ChangeLog.bidi index ae5807ce13a..9824981c086 100644 --- a/src/ChangeLog.bidi +++ b/src/ChangeLog.bidi @@ -1,3 +1,27 @@ +2009-10-17 Eli Zaretskii + + * dispextern.h (struct glyph): New members resolved_level and + bidi_type. + + * xdisp.c (append_glyph, append_composite_glyph) + (produce_image_glyph, append_stretch_glyph): Set them. + + * term.c (append_glyph): Ditto. + + * xdisp.c (display_line, next_element_from_buffer): Set the glyph + row's reversed_p flag if the paragraph base direction is odd. + (extend_face_to_end_of_line): Don't reverse the glyphs here. + + * term.c (append_glyph): Reverse glyphs here. + + * bidi.c (bidi_get_next_char_visually): Don't exit early when at + ZV. + (bidi_paragraph_init): Don't step over a newline if at BEGV. + +2009-10-16 Eli Zaretskii + + * bidi.c (bidi_paragraph_init): Handle empty buffers. + 2009-10-10 Eli Zaretskii * xdisp.c (set_cursor_from_row): Skip over glyphs near end of row diff --git a/src/bidi.c b/src/bidi.c index f6ca8cd20e9..3a2d45cdb4d 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -853,8 +853,11 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it) { EMACS_INT bytepos = bidi_it->bytepos; + /* Special case for an empty buffer. */ + if (bytepos == BEGV_BYTE && bytepos == ZV_BYTE) + dir = L2R; /* We should never be called at EOB or before BEGV. */ - if (bytepos >= ZV_BYTE || bytepos < BEGV_BYTE) + else if (bytepos >= ZV_BYTE || bytepos < BEGV_BYTE) abort (); if (dir == L2R) @@ -883,9 +886,11 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it) return; /* If we are on a newline, get past it to where the next - paragraph might start. */ + paragraph might start. But don't do that at BEGV since then + we are potentially in a new paragraph that doesn't yet + exist. */ pos = bidi_it->charpos; - if (FETCH_CHAR (bytepos) == '\n') + if (bytepos > BEGV_BYTE && FETCH_CHAR (bytepos) == '\n') { bytepos++; pos++; @@ -1900,8 +1905,6 @@ bidi_get_next_char_visually (struct bidi_it *bidi_it) old_level = bidi_it->resolved_level; new_level = bidi_level_of_next_char (bidi_it); - if (bidi_it->ch == BIDI_EOB) - return; /* Reordering of resolved levels (clause L2) is implemented by jumping to the other edge of the level and flipping direction of diff --git a/src/dispextern.h b/src/dispextern.h index ae6ecbb0d5c..5f18b7f3a4a 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -370,6 +370,13 @@ struct glyph /* Non-zero means don't display cursor here. */ unsigned avoid_cursor_p : 1; + /* Resolved bidirection level of the characters [0..63]. */ + unsigned resolved_level : 6; + + /* Resolved bidirectional type of this character, see enum + bidi_type_t below. */ + unsigned bidi_type : 5; + #define FACE_ID_BITS 20 /* Face of the glyph. This is a realized face ID, diff --git a/src/term.c b/src/term.c index fda06d6b2ed..7c9e05f36b2 100644 --- a/src/term.c +++ b/src/term.c @@ -1545,6 +1545,26 @@ append_glyph (it) + it->glyph_row->used[it->area]); end = 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; + int move_by = it->pixel_width; + + /* Make room for the new glyphs. */ + if (move_by > end - glyph) /* don't overstep end of this area */ + move_by = end - glyph; + for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--) + g[move_by] = *g; + glyph = it->glyph_row->glyphs[it->area]; + end = glyph + move_by; + } + + /* BIDI Note: we put the glyphs of a "multi-pixel" character left to + right, even in the REVERSED_P case, since (a) all of its u.ch are + identical, and (b) the PADDING_P flag needs to be set for the + leftmost one, because we write to the terminal left-to-right. */ for (i = 0; i < it->pixel_width && glyph < end; ++i) @@ -1556,6 +1576,11 @@ append_glyph (it) glyph->padding_p = i > 0; glyph->charpos = CHARPOS (it->position); glyph->object = it->object; + if (it->bidi_p) + { + glyph->resolved_level = it->bidi_it.resolved_level; + glyph->bidi_type = it->bidi_it.type; + } ++it->glyph_row->used[it->area]; ++glyph; diff --git a/src/xdisp.c b/src/xdisp.c index 581a7a0faa2..90f16b938c0 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -6571,6 +6571,12 @@ next_element_from_buffer (it) || FETCH_CHAR (it->bidi_it.bytepos) == '\n') { bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it); + /* If the paragraph base direction is R2L, its glyphs should + be reversed. */ + if (it->glyph_row && (it->bidi_it.level_stack[0].level & 1) != 0) + it->glyph_row->reversed_p = 1; + if (it->glyph_row && (it->bidi_it.level_stack[0].level & 1) != 0) + it->glyph_row->reversed_p = 1; bidi_get_next_char_visually (&it->bidi_it); } else @@ -6585,6 +6591,8 @@ next_element_from_buffer (it) it->bidi_it.charpos = IT_CHARPOS (*it); it->bidi_it.bytepos = IT_BYTEPOS (*it); bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it); + if (it->glyph_row && (it->bidi_it.level_stack[0].level & 1) != 0) + it->glyph_row->reversed_p = 1; do { /* Now return to buffer position where we were asked to get the next display element, and produce that. */ @@ -16538,27 +16546,6 @@ extend_face_to_end_of_line (it) while (it->current_x <= it->last_visible_x) PRODUCE_GLYPHS (it); - /* If the paragraph base direction is right to left, reverse the - glyphs of a non-empty glyph row. */ - if (it->bidi_p && it->bidi_it.level_stack[0].level == 1) - { - if (text_len > 0) - { - struct glyph *gleft = it->glyph_row->glyphs[TEXT_AREA]; - struct glyph *gright = - gleft + it->glyph_row->used[TEXT_AREA] - 1; - struct glyph tem; - - for ( ; gleft < gright; gleft++, gright--) - { - tem = *gleft; - *gleft = *gright; - *gright = tem; - } - } - it->glyph_row->reversed_p = 1; - } - /* Don't count these blanks really. It would let us insert a left truncation glyph below and make us set the cursor on them, maybe. */ it->current_x = saved_x; @@ -16850,6 +16837,10 @@ display_line (it) row->displays_text_p = 1; row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p; it->starts_in_middle_of_char_p = 0; + /* If the paragraph base direction is R2L, its glyphs should be + reversed. */ + if (it->bidi_p && (it->bidi_it.level_stack[0].level & 1) != 0) + row->reversed_p = 1; /* Arrange the overlays nicely for our purposes. Usually, we call display_line on only one line at a time, in which case this @@ -20932,6 +20923,11 @@ append_glyph (it) glyph->u.ch = it->char_to_display; glyph->slice = null_glyph_slice; glyph->font_type = FONT_TYPE_UNKNOWN; + if (it->bidi_p) + { + glyph->resolved_level = it->bidi_it.resolved_level; + glyph->bidi_type = it->bidi_it.type; + } ++it->glyph_row->used[area]; } else @@ -20984,6 +20980,11 @@ append_composite_glyph (it) glyph->face_id = it->face_id; glyph->slice = null_glyph_slice; glyph->font_type = FONT_TYPE_UNKNOWN; + if (it->bidi_p) + { + glyph->resolved_level = it->bidi_it.resolved_level; + glyph->bidi_type = it->bidi_it.type; + } ++it->glyph_row->used[area]; } else @@ -21158,6 +21159,11 @@ produce_image_glyph (it) glyph->u.img_id = img->id; glyph->slice = slice; glyph->font_type = FONT_TYPE_UNKNOWN; + if (it->bidi_p) + { + glyph->resolved_level = it->bidi_it.resolved_level; + glyph->bidi_type = it->bidi_it.type; + } ++it->glyph_row->used[area]; } else @@ -21204,6 +21210,11 @@ append_stretch_glyph (it, object, width, height, ascent) glyph->u.stretch.height = height; glyph->slice = null_glyph_slice; glyph->font_type = FONT_TYPE_UNKNOWN; + if (it->bidi_p) + { + glyph->resolved_level = it->bidi_it.resolved_level; + glyph->bidi_type = it->bidi_it.type; + } ++it->glyph_row->used[area]; } else -- 2.11.4.GIT