changeset 107598:4bad2c6338cc

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.
author Eli Zaretskii <eliz@gnu.org>
date Fri, 01 Jan 2010 06:39:56 -0500
parents 7361a2f37d8e
children 23f8a579b56e
files src/ChangeLog.bidi src/bidi.c src/dispextern.h src/term.c src/xdisp.c
diffstat 5 files changed, 96 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog.bidi	Fri Jan 01 06:35:03 2010 -0500
+++ b/src/ChangeLog.bidi	Fri Jan 01 06:39:56 2010 -0500
@@ -1,3 +1,27 @@
+2009-10-17  Eli Zaretskii  <eliz@gnu.org>
+
+	* 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  <eliz@gnu.org>
+
+	* bidi.c (bidi_paragraph_init): Handle empty buffers.
+
 2009-10-10  Eli Zaretskii  <eliz@gnu.org>
 
 	* xdisp.c (set_cursor_from_row): Skip over glyphs near end of row
--- a/src/bidi.c	Fri Jan 01 06:35:03 2010 -0500
+++ b/src/bidi.c	Fri Jan 01 06:39:56 2010 -0500
@@ -853,8 +853,11 @@
 {
   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 @@
 	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 @@
 
   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
--- a/src/dispextern.h	Fri Jan 01 06:35:03 2010 -0500
+++ b/src/dispextern.h	Fri Jan 01 06:39:56 2010 -0500
@@ -370,6 +370,13 @@
   /* 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,
--- a/src/term.c	Fri Jan 01 06:35:03 2010 -0500
+++ b/src/term.c	Fri Jan 01 06:39:56 2010 -0500
@@ -1545,6 +1545,26 @@
 	   + 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 @@
       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;
--- a/src/xdisp.c	Fri Jan 01 06:35:03 2010 -0500
+++ b/src/xdisp.c	Fri Jan 01 06:39:56 2010 -0500
@@ -6571,6 +6571,12 @@
 	  || 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 @@
 	  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 @@
       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 @@
   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 @@
       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 @@
       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 @@
 	  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 @@
       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