changeset 107996:8ef8b6523597

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.
author Eli Zaretskii <eliz@gnu.org>
date Tue, 20 Apr 2010 16:08:35 +0300
parents 1afd4d56683f
children 531d454c3a99
files src/ChangeLog src/term.c src/xdisp.c
diffstat 3 files changed, 102 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- 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  <eliz@gnu.org>
+
+	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  <eliz@gnu.org>
 
+	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.
--- 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;
--- 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;