changeset 107998:531d454c3a99

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) <cursor_x>: 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.
author Eli Zaretskii <eliz@gnu.org>
date Tue, 20 Apr 2010 16:31:28 +0300
parents d94009e7a0cc (current diff) 8ef8b6523597 (diff)
children 759500121599
files src/ChangeLog src/term.c src/xdisp.c
diffstat 7 files changed, 330 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- 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  <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.
+	(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) <cursor_x>: 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  <jan.h.d@swipnet.se>
 
 	* gtkutil.c (xg_event_is_for_scrollbar): Check if grabbed
--- 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);
--- 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);
--- 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);
 	}
--- 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;
 	}
 
--- 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);
--- 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