emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r99950: Implement GUI display of R2L


From: Eli Zaretskii
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r99950: Implement GUI display of R2L lines, fix TTY display of R2L lines.
Date: Tue, 20 Apr 2010 16:31:28 +0300
User-agent: Bazaar (2.0.3)

------------------------------------------------------------
revno: 99950 [merge]
committer: Eli Zaretskii <address@hidden>
branch nick: trunk
timestamp: Tue 2010-04-20 16:31:28 +0300
message:
  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.
modified:
  src/ChangeLog
  src/dispnew.c
  src/fringe.c
  src/term.c
  src/w32term.c
  src/xdisp.c
  src/xterm.c
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2010-04-20 11:38:30 +0000
+++ b/src/ChangeLog     2010-04-20 13:31:28 +0000
@@ -1,3 +1,70 @@
+2010-04-20  Eli Zaretskii  <address@hidden>
+
+       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  <address@hidden>
 
        * gtkutil.c (xg_event_is_for_scrollbar): Check if grabbed

=== modified file 'src/dispnew.c'
--- a/src/dispnew.c     2010-04-02 03:10:33 +0000
+++ b/src/dispnew.c     2010-04-10 16:28:30 +0000
@@ -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);

=== modified file 'src/fringe.c'
--- a/src/fringe.c      2010-01-13 08:35:10 +0000
+++ b/src/fringe.c      2010-04-17 12:33:05 +0000
@@ -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);

=== modified file 'src/term.c'
--- a/src/term.c        2010-04-20 01:50:52 +0000
+++ b/src/term.c        2010-04-20 13:31:28 +0000
@@ -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);
        }

=== modified file 'src/w32term.c'
--- a/src/w32term.c     2010-04-02 03:10:33 +0000
+++ b/src/w32term.c     2010-04-10 16:28:30 +0000
@@ -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;
        }
 

=== modified file 'src/xdisp.c'
--- a/src/xdisp.c       2010-04-20 01:50:52 +0000
+++ b/src/xdisp.c       2010-04-20 13:31:28 +0000
@@ -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);

=== modified file 'src/xterm.c'
--- a/src/xterm.c       2010-04-19 15:07:52 +0000
+++ b/src/xterm.c       2010-04-20 13:31:28 +0000
@@ -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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]