changeset 107596:866e76f8ad75

Retrospective commit from 2009-10-08. Finish up working on paragraph's base direction. Start working on display of right-to-left glyph rows. Rewrite set_cursor_from_row to support bidi. xdisp.c (string_buffer_position_lim): New function. (string_buffer_position): Most of code moved to string_buffer_position_lim. Last argument and return value are now EMACS_INT; all callers changed. (set_cursor_from_row): Rewritten to support bidirectional text and reversed glyph rows. dispextern.h <string_buffer_position>: Update prototype. bidi.c (bidi_paragraph_init): Fix initialization of POS. dispextern.h (struct glyph_row): New member reversed_p. buffer.c (syms_of_buffer): Remove DEFVAR_LISP_NOPRO for default-direction-reversed, default-bidi-display-reordering, and default-paragraph-direction.
author Eli Zaretskii <eliz@gnu.org>
date Fri, 01 Jan 2010 06:27:51 -0500
parents 69c12db7031d
children 7361a2f37d8e
files src/ChangeLog.bidi src/bidi.c src/buffer.c src/buffer.h src/dispextern.h src/xdisp.c
diffstat 6 files changed, 399 insertions(+), 208 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog.bidi	Fri Jan 01 06:22:52 2010 -0500
+++ b/src/ChangeLog.bidi	Fri Jan 01 06:27:51 2010 -0500
@@ -1,3 +1,26 @@
+2009-10-08  Eli Zaretskii  <eliz@gnu.org>
+
+	* xdisp.c (string_buffer_position_lim): New function.
+	(string_buffer_position): Most of code moved to
+	string_buffer_position_lim.  Last argument and return value are
+	now EMACS_INT; all callers changed.
+	(set_cursor_from_row): Rewritten to support bidirectional text and
+	reversed glyph rows.
+
+	dispextern.h <string_buffer_position>: Update prototype.
+
+2009-10-07  Eli Zaretskii  <eliz@gnu.org>
+
+	* bidi.c (bidi_paragraph_init): Fix initialization of POS.
+
+	* dispextern.h (struct glyph_row): New member reversed_p.
+
+2009-10-06  Eli Zaretskii  <eliz@gnu.org>
+
+	* buffer.c (syms_of_buffer): Remove DEFVAR_LISP_NOPRO for
+	default-direction-reversed, default-bidi-display-reordering, and
+	default-paragraph-direction.
+
 2009-10-05  Eli Zaretskii  <eliz@gnu.org>
 
 	* buffer.h (struct buffer): New member paragraph_direction.
--- a/src/bidi.c	Fri Jan 01 06:22:52 2010 -0500
+++ b/src/bidi.c	Fri Jan 01 06:27:51 2010 -0500
@@ -1,5 +1,5 @@
 /* Low-level bidirectional buffer-scanning functions for GNU Emacs.
-   Copyright (C) 2000, 2001, 2004, 2005	Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2004, 2005, 2009	Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -875,10 +875,11 @@
 
       /* If we are on a newline, get past it to where the next
 	 paragraph might start.  */
+      pos = bidi_it->charpos;
       if (FETCH_CHAR (bytepos) == '\n')
 	{
 	  bytepos++;
-	  pos = bidi_it->charpos + 1;
+	  pos++;
 	}
 
       /* We are either at the beginning of a paragraph or in the
--- a/src/buffer.c	Fri Jan 01 06:22:52 2010 -0500
+++ b/src/buffer.c	Fri Jan 01 06:27:51 2010 -0500
@@ -5532,26 +5532,11 @@
 		     doc: /* Default value of `ctl-arrow' for buffers that do not override it.
 This is the same as (default-value 'ctl-arrow).  */);
 
-  DEFVAR_LISP_NOPRO ("default-bidi-display-reordering",
-	      &buffer_defaults.bidi_display_reordering,
-	      doc: /* *Default value of `bidi-display-reordering' for buffers not overriding it.
-This is the same as (default-value 'bidi-display-reordering).  */);
-
-  DEFVAR_LISP_NOPRO ("default-direction-reversed",
-                     &buffer_defaults.direction_reversed,
-                     doc: /* Default value of `direction-reversed' for buffers that do not override it.
-This is the same as (default-value 'direction-reversed).  */);
-
   DEFVAR_LISP_NOPRO ("default-enable-multibyte-characters",
                      &buffer_defaults.enable_multibyte_characters,
                      doc: /* *Default value of `enable-multibyte-characters' for buffers not overriding it.
 This is the same as (default-value 'enable-multibyte-characters).  */);
 
-  DEFVAR_LISP_NOPRO ("default-paragraph-direction",
-		     &buffer_defaults.paragraph_direction,
-		     doc: /* Default value of `paragraph-direction' for buffers that do not override it.
-This is the same as (default-value 'paragraph-direction).  */);
-
   DEFVAR_LISP_NOPRO ("default-buffer-file-coding-system",
                      &buffer_defaults.buffer_file_coding_system,
                      doc: /* Default value of `buffer-file-coding-system' for buffers not overriding it.
@@ -5810,7 +5795,7 @@
 
   DEFVAR_PER_BUFFER ("bidi-display-reordering",
 		     &current_buffer->bidi_display_reordering, Qnil,
-		     doc: /*Non-nil means reorder bidirectional text for display in the visual order.
+		     doc: /* Non-nil means reorder bidirectional text for display in the visual order.
 See also the variable `direction-reversed'.  */);
 
   DEFVAR_PER_BUFFER ("paragraph-direction",
--- a/src/buffer.h	Fri Jan 01 06:22:52 2010 -0500
+++ b/src/buffer.h	Fri Jan 01 06:27:51 2010 -0500
@@ -664,9 +664,9 @@
   /* Non-nil means set beginning of lines at the right edge of
      windows.  */
   Lisp_Object direction_reversed;
-  /* If non-nil, specifies which direction of text to force in each
-     paragraph.  Nil means determine paragraph direction dynamically
-     for each paragraph.  */
+  /* If non-nil, specifies which direction of text to force in all the
+     paragraphs of the buffer.  Nil means determine paragraph
+     direction dynamically for each paragraph.  */
   Lisp_Object paragraph_direction;
   /* Non-nil means do selective display;
      see doc string in syms_of_buffer (buffer.c) for details.  */
--- a/src/dispextern.h	Fri Jan 01 06:22:52 2010 -0500
+++ b/src/dispextern.h	Fri Jan 01 06:27:51 2010 -0500
@@ -876,6 +876,10 @@
      the bottom line of the window, but not end of the buffer.  */
   unsigned indicate_bottom_line_p : 1;
 
+  /* Non-zero means the row was reversed to display text in a
+     right-to-left paragraph.  */
+  unsigned reversed_p : 1;
+
   /* Continuation lines width at the start of the row.  */
   int continuation_lines_width;
 
@@ -2811,7 +2815,8 @@
 struct glyph_row *row_containing_pos P_ ((struct window *, int,
 					  struct glyph_row *,
 					  struct glyph_row *, int));
-int string_buffer_position P_ ((struct window *, Lisp_Object, int));
+EMACS_INT string_buffer_position P_ ((struct window *, Lisp_Object,
+				      EMACS_INT));
 int line_bottom_y P_ ((struct it *));
 int display_prop_intangible_p P_ ((Lisp_Object));
 void resize_echo_area_exactly P_ ((void));
--- a/src/xdisp.c	Fri Jan 01 06:22:52 2010 -0500
+++ b/src/xdisp.c	Fri Jan 01 06:27:51 2010 -0500
@@ -4594,43 +4594,46 @@
   return 0;
 }
 
-
-/* Determine which buffer position in W's buffer STRING comes from.
-   AROUND_CHARPOS is an approximate position where it could come from.
-   Value is the buffer position or 0 if it couldn't be determined.
+/* Look for STRING in overlays and text properties in W's buffer,
+   between character positions FROM and TO (excluding TO).
+   BACK_P non-zero means look back (in this case, TO is supposed to be
+   less than FROM).
+   Value is the first character position where STRING was found, or
+   zero if it wasn't found before hitting TO.
 
    W's buffer must be current.
 
-   This function is necessary because we don't record buffer positions
-   in glyphs generated from strings (to keep struct glyph small).
    This function may only use code that doesn't eval because it is
    called asynchronously from note_mouse_highlight.  */
 
-int
-string_buffer_position (w, string, around_charpos)
+static EMACS_INT
+string_buffer_position_lim (w, string, from, to, back_p)
      struct window *w;
      Lisp_Object string;
-     int around_charpos;
+     EMACS_INT from, to;
+     int back_p;
 {
   Lisp_Object limit, prop, pos;
-  const int MAX_DISTANCE = 1000;
   int found = 0;
 
-  pos = make_number (around_charpos);
-  limit = make_number (min (XINT (pos) + MAX_DISTANCE, ZV));
-  while (!found && !EQ (pos, limit))
-    {
-      prop = Fget_char_property (pos, Qdisplay, Qnil);
-      if (!NILP (prop) && display_prop_string_p (prop, string))
-	found = 1;
-      else
-	pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil, limit);
-    }
-
-  if (!found)
-    {
-      pos = make_number (around_charpos);
-      limit = make_number (max (XINT (pos) - MAX_DISTANCE, BEGV));
+  pos = make_number (from);
+
+  if (!back_p)	/* looking forward */
+    {
+      limit = make_number (min (to, ZV));
+      while (!found && !EQ (pos, limit))
+	{
+	  prop = Fget_char_property (pos, Qdisplay, Qnil);
+	  if (!NILP (prop) && display_prop_string_p (prop, string))
+	    found = 1;
+	  else
+	    pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil,
+						     limit);
+	}
+    }
+  else		/* looking back */
+    {
+      limit = make_number (max (to, BEGV));
       while (!found && !EQ (pos, limit))
 	{
 	  prop = Fget_char_property (pos, Qdisplay, Qnil);
@@ -4645,6 +4648,35 @@
   return found ? XINT (pos) : 0;
 }
 
+/* Determine which buffer position in W's buffer STRING comes from.
+   AROUND_CHARPOS is an approximate position where it could come from.
+   Value is the buffer position or 0 if it couldn't be determined.
+
+   W's buffer must be current.
+
+   This function is necessary because we don't record buffer positions
+   in glyphs generated from strings (to keep struct glyph small).
+   This function may only use code that doesn't eval because it is
+   called asynchronously from note_mouse_highlight.  */
+
+EMACS_INT
+string_buffer_position (w, string, around_charpos)
+     struct window *w;
+     Lisp_Object string;
+     EMACS_INT around_charpos;
+{
+  Lisp_Object limit, prop, pos;
+  const int MAX_DISTANCE = 1000;
+  EMACS_INT found = string_buffer_position_lim (w, string, around_charpos,
+						around_charpos + MAX_DISTANCE,
+						0);
+
+  if (!found)
+    found = string_buffer_position_lim (w, string, around_charpos,
+					around_charpos - MAX_DISTANCE, 1);
+  return found;
+}
+
 
 
 /***********************************************************************
@@ -12405,160 +12437,299 @@
   struct glyph *glyph = row->glyphs[TEXT_AREA];
   struct glyph *end = glyph + row->used[TEXT_AREA];
   struct glyph *cursor = NULL;
-  /* The first glyph that starts a sequence of glyphs from a string
-     that is a value of a display property.  */
-  struct glyph *string_start;
-  /* The X coordinate of string_start.  */
-  int string_start_x;
   /* The last known character position in row.  */
   int last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
-  /* The last known character position before string_start.  */
-  int string_before_pos;
   int x = row->x;
   int cursor_x = x;
-  /* Last buffer position covered by an overlay.  */
-  int cursor_from_overlay_pos = 0;
-  int pt_old = PT - delta;
-
-  /* Skip over glyphs not having an object at the start of the row.
-     These are special glyphs like truncation marks on terminal
-     frames.  */
+  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;
+  struct glyph *glyph_before = glyph - 1, *glyph_after = end;
+  /* Non-zero means we've found a match for cursor position, but that
+     glyph has the avoid_cursor_p flag set.  */
+  int match_with_avoid_cursor = 0;
+  /* Non-zero means we've seen at least one glyph that came from a
+     display string.  */
+  int string_seen = 0;
+
+  /* Skip over glyphs not having an object at the start and the end of
+     the row.  These are special glyphs like truncation marks on
+     terminal frames.  */
   if (row->displays_text_p)
-    while (glyph < end
-	   && INTEGERP (glyph->object)
-	   && glyph->charpos < 0)
+    {
+      if (!row->reversed_p)
+	{
+	  while (glyph < end
+		 && INTEGERP (glyph->object)
+		 && glyph->charpos < 0)
+	    {
+	      x += glyph->pixel_width;
+	      ++glyph;
+	    }
+	  while (end > glyph
+		 && INTEGERP ((end - 1)->object)
+		 && (end - 1)->charpos < 0)
+	    --end;
+	  glyph_before = glyph - 1;
+	  glyph_after = end;
+	}
+      else
+	{
+	  struct glyph *g;
+
+	  /* If the glyph row is reversed, we need to process it from back
+	     to front, so swap the edge pointers.  */
+	  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)
+		 && glyph->charpos < 0)
+	    {
+	      --glyph;
+	      x -= glyph->pixel_width;
+	    }
+	  if (INTEGERP (glyph->object) && glyph->charpos < 0)
+	    --glyph;
+	  /* By default, put the cursor on the rightmost glyph.  */
+	  for (g = end + 1; g < glyph; g++)
+	    x += g->pixel_width;
+	  cursor_x = x;
+	  while (end < glyph
+		 && INTEGERP (end->object)
+		 && end->charpos < 0)
+	    ++end;
+	  glyph_before = glyph + 1;
+	  glyph_after = end;
+	}
+    }
+
+  /* Step 1: Try to find the glyph whose character position
+     corresponds to point.  If that's not possible, find 2 glyphs
+     whose character positions are the closest to point, one before
+     point, the other after it.  */
+  if (!row->reversed_p)
+    while (/* not marched to end of glyph row */
+	   glyph < end
+	   /* glyph was not inserted by redisplay for internal purposes */
+	   && !INTEGERP (glyph->object))
       {
+	if (BUFFERP (glyph->object))
+	  {
+	    EMACS_INT dpos = glyph->charpos - pt_old;
+
+	    if (!glyph->avoid_cursor_p)
+	      {
+		/* If we hit point, we've found the glyph on which to
+		   display the cursor.  */
+		if (dpos == 0)
+		  {
+		    match_with_avoid_cursor = 0;
+		    break;
+		  }
+		/* See if we've found a better approximation to
+		   POS_BEFORE or to POS_AFTER.  Note that we want the
+		   first (leftmost) glyph of all those that are the
+		   closest from below, and the last (rightmost) of all
+		   those from above.  */
+		if (0 > dpos && dpos > pos_before - pt_old)
+		  {
+		    pos_before = glyph->charpos;
+		    glyph_before = glyph;
+		  }
+		else if (0 < dpos && dpos <= pos_after - pt_old)
+		  {
+		    pos_after = glyph->charpos;
+		    glyph_after = glyph;
+		  }
+	      }
+	    else if (dpos == 0)
+	      match_with_avoid_cursor = 1;
+	  }
+	else if (STRINGP (glyph->object))
+	  string_seen = 1;
 	x += glyph->pixel_width;
 	++glyph;
       }
-
-  string_start = NULL;
-  while (glyph < end
-	 && !INTEGERP (glyph->object)
-	 && (!BUFFERP (glyph->object)
-	     || (last_pos = glyph->charpos) != pt_old
-	     || glyph->avoid_cursor_p))
-    {
-      if (! STRINGP (glyph->object))
-	{
-	  string_start = NULL;
-	  x += glyph->pixel_width;
-	  ++glyph;
-	  /* If we are beyond the cursor position computed from the
-	     last overlay seen, that overlay is not in effect for
-	     current cursor position.  Reset the cursor information
-	     computed from that overlay.  */
-	  if (cursor_from_overlay_pos
-	      && last_pos >= cursor_from_overlay_pos)
-	    {
-	      cursor_from_overlay_pos = 0;
-	      cursor = NULL;
-	    }
-	}
-      else
-	{
-	  if (string_start == NULL)
-	    {
-	      string_before_pos = last_pos;
-	      string_start = glyph;
-	      string_start_x = x;
-	    }
-	  /* Skip all glyphs from a string.  */
-	  do
-	    {
-	      Lisp_Object cprop;
-	      int pos;
-	      if ((cursor == NULL || glyph > cursor)
-		  && (cprop = Fget_char_property (make_number ((glyph)->charpos),
-						  Qcursor, (glyph)->object),
-		      !NILP (cprop))
-		  && (pos = string_buffer_position (w, glyph->object,
-						    string_before_pos),
-		      (pos == 0	  /* from overlay */
-		       || pos == pt_old)))
-		{
-		  /* Compute the first buffer position after the overlay.
-		     If the `cursor' property tells us how  many positions
-		     are associated with the overlay, use that.  Otherwise,
-		     estimate from the buffer positions of the glyphs
-		     before and after the overlay.  */
-		  cursor_from_overlay_pos = (pos ? 0 : last_pos
-					     + (INTEGERP (cprop) ? XINT (cprop) : 0));
-		  cursor = glyph;
-		  cursor_x = x;
-		}
+  else if (glyph > end)	/* row is reversed */
+    while (!INTEGERP (glyph->object))
+      {
+	if (BUFFERP (glyph->object))
+	  {
+	    EMACS_INT dpos = glyph->charpos - pt_old;
+
+	    if (!glyph->avoid_cursor_p)
+	      {
+		if (dpos == 0)
+		  {
+		    match_with_avoid_cursor = 0;
+		    break;
+		  }
+		if (0 > dpos && dpos > pos_before - pt_old)
+		  {
+		    pos_before = glyph->charpos;
+		    glyph_before = glyph;
+		  }
+		else if (0 < dpos && dpos <= pos_after - pt_old)
+		  {
+		    pos_after = glyph->charpos;
+		    glyph_after = glyph;
+		  }
+	      }
+	    else if (dpos == 0)
+	      match_with_avoid_cursor = 1;
+	  }
+	else if (STRINGP (glyph->object))
+	  string_seen = 1;
+	--glyph;
+	if (glyph == end)
+	  break;
+	x -= glyph->pixel_width;
+    }
+
+  /* Step 2: If we didn't find an exact match for point, we need to
+     look for a proper place to put the cursor among glyphs between
+     GLYPH_BEFORE and GLYPH_AFTER.  */
+  if (glyph->charpos != pt_old)
+    {
+      if (row->ends_in_ellipsis_p && pos_after == last_pos)
+	{
+	  EMACS_INT ellipsis_pos;
+
+	  /* Scan back over the ellipsis glyphs.  */
+	  if (!row->reversed_p)
+	    {
+	      ellipsis_pos = (glyph - 1)->charpos;
+	      while (glyph > row->glyphs[TEXT_AREA]
+		     && (glyph - 1)->charpos == ellipsis_pos)
+		glyph--, x -= glyph->pixel_width;
+	      /* That loop always goes one position too far, including
+		 the glyph before the ellipsis.  So scan forward over
+		 that one.  */
 	      x += glyph->pixel_width;
-	      ++glyph;
-	    }
-	  while (glyph < end && EQ (glyph->object, string_start->object));
-	}
-    }
-
+	      glyph++;
+	    }
+	  else	/* row is reversed */
+	    {
+	      ellipsis_pos = (glyph + 1)->charpos;
+	      while (glyph < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
+		     && (glyph + 1)->charpos == ellipsis_pos)
+		glyph++, x += glyph->pixel_width;
+	      x -= glyph->pixel_width;
+	      glyph--;
+	    }
+	}
+      else if (match_with_avoid_cursor)
+	{
+	  cursor = glyph_after;
+	  x = -1;
+	}
+      else if (string_seen)
+	{
+	  int incr = row->reversed_p ? -1 : +1;
+
+	  /* Need to find the glyph that came out of a string which is
+	     present at point.  That glyph is somewhere between
+	     GLYPH_BEFORE and GLYPH_AFTER, and it came from a string
+	     positioned between POS_BEFORE and POS_AFTER in the
+	     buffer.  */
+	  struct glyph *stop = glyph_after;
+	  EMACS_INT pos = pos_before;
+
+	  x = -1;
+	  for (glyph = glyph_before + incr;
+	       row->reversed_p ? glyph > stop : glyph < stop; )
+	    {
+
+	      /* Any glyphs that come from the buffer are here because
+		 of bidi reordering.  Skip them, and only pay
+		 attention to glyphs that came from some string.  */
+	      if (STRINGP (glyph->object))
+		{
+		  Lisp_Object str;
+		  EMACS_INT tem;
+
+		  str = glyph->object;
+		  tem = string_buffer_position_lim (w, str, pos, pos_after, 0);
+		  if (pos <= tem)
+		    {
+		      /* If the string from which this glyph came is
+			 found in the buffer at point, then we've
+			 found the glyph we've been looking for.  */
+		      if (tem == pt_old)
+			{
+			  /* The glyphs from this string could have
+			     been reordered.  Find the one with the
+			     smallest string position.  Or there could
+			     be a character in the string with the
+			     `cursor' property, which means display
+			     cursor on that character's glyph.  */
+			  int strpos = glyph->charpos;
+
+			  cursor = glyph;
+			  for (glyph += incr;
+			       EQ (glyph->object, str);
+			       glyph += incr)
+			    {
+			      Lisp_Object cprop;
+			      int gpos = glyph->charpos;
+
+			      cprop = Fget_char_property (make_number (gpos),
+							  Qcursor,
+							  glyph->object);
+			      if (!NILP (cprop))
+				{
+				  cursor = glyph;
+				  break;
+				}
+			      if (glyph->charpos < strpos)
+				{
+				  strpos = glyph->charpos;
+				  cursor = glyph;
+				}
+			    }
+
+			  goto compute_x;
+			}
+		      pos = tem + 1; /* don't find previous instances */
+		    }
+		  /* This string is not what we want; skip all of the
+		     glyphs that came from it.  */
+		  do
+		    glyph += incr;
+		  while ((row->reversed_p ? glyph > stop : glyph < stop)
+			 && EQ (glyph->object, str));
+		}
+	      else
+		glyph += incr;
+	    }
+
+	  /* If we reached the end of the line, and END was from a string,
+	     the cursor is not on this line.  */
+	  if (glyph == end
+	      && STRINGP ((glyph - incr)->object)
+	      && row->continued_p)
+	    return 0;
+	}
+    }
+
+ compute_x:
   if (cursor != NULL)
-    {
-      glyph = cursor;
-      x = cursor_x;
-    }
-  else if (row->ends_in_ellipsis_p && glyph == end)
-    {
-      /* Scan back over the ellipsis glyphs, decrementing positions.  */
-      while (glyph > row->glyphs[TEXT_AREA]
-	     && (glyph - 1)->charpos == last_pos)
-	glyph--, x -= glyph->pixel_width;
-      /* That loop always goes one position too far, including the
-	 glyph before the ellipsis.  So scan forward over that one.  */
-      x += glyph->pixel_width;
-      glyph++;
-    }
-  else if (string_start
-	   && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old))
-    {
-      /* We may have skipped over point because the previous glyphs
-	 are from string.  As there's no easy way to know the
-	 character position of the current glyph, find the correct
-	 glyph on point by scanning from string_start again.  */
-      Lisp_Object limit;
-      Lisp_Object string;
-      struct glyph *stop = glyph;
-      int pos;
-
-      limit = make_number (pt_old + 1);
-      glyph = string_start;
-      x = string_start_x;
-      string = glyph->object;
-      pos = string_buffer_position (w, string, string_before_pos);
-      /* If POS == 0, STRING is from overlay.  We skip such glyphs
-	 because we always put the cursor after overlay strings.  */
-      while (pos == 0 && glyph < stop)
-	{
-	  string = glyph->object;
-	  SKIP_GLYPHS (glyph, stop, x, EQ (glyph->object, string));
-	  if (glyph < stop)
-	    pos = string_buffer_position (w, glyph->object, string_before_pos);
-	}
-
-      while (glyph < stop)
-	{
-	  pos = XINT (Fnext_single_char_property_change
-		      (make_number (pos), Qdisplay, Qnil, limit));
-	  if (pos > pt_old)
-	    break;
-	  /* Skip glyphs from the same string.  */
-	  string = glyph->object;
-	  SKIP_GLYPHS (glyph, stop, x, EQ (glyph->object, string));
-	  /* Skip glyphs from an overlay.  */
-	  while (glyph < stop
-		 && ! string_buffer_position (w, glyph->object, pos))
-	    {
-	      string = glyph->object;
-	      SKIP_GLYPHS (glyph, stop, x, EQ (glyph->object, string));
-	    }
-	}
-
-      /* If we reached the end of the line, and END was from a string,
-	 the cursor is not on this line.  */
-      if (glyph == end && row->continued_p)
-	return 0;
+    glyph = cursor;
+  if (x < 0)
+    {
+      struct glyph *g;
+
+      /* Need to compute x that corresponds to GLYPH.  */
+      for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
+	{
+	  if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
+	    abort ();
+	  x += g->pixel_width;
+	}
     }
 
   w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
@@ -16343,20 +16514,24 @@
 	PRODUCE_GLYPHS (it);
 
       /* If the paragraph base direction is right to left, reverse the
-	 glyphs of non-empty line.  */
-      if (it->bidi_p && it->bidi_it.level_stack[0].level == 1
-	  && 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;
-	    }
+	 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
@@ -23181,7 +23356,7 @@
 	 associated with the end position, which must not be
 	 highlighted.  */
       Lisp_Object prev_object;
-      int pos;
+      EMACS_INT pos;
 
       while (glyph > row->glyphs[TEXT_AREA])
 	{
@@ -23813,7 +23988,8 @@
       && XFASTINT (w->last_modified) == BUF_MODIFF (b)
       && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
     {
-      int hpos, vpos, pos, i, dx, dy, area;
+      int hpos, vpos, i, dx, dy, area;
+      EMACS_INT pos;
       struct glyph *glyph;
       Lisp_Object object;
       Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
@@ -24101,7 +24277,7 @@
 		    struct glyph_row *r
 		      = MATRIX_ROW (w->current_matrix, vpos);
 		    int start = MATRIX_ROW_START_CHARPOS (r);
-		    int pos = string_buffer_position (w, object, start);
+		    EMACS_INT pos = string_buffer_position (w, object, start);
 		    if (pos > 0)
 		      {
 			help = Fget_char_property (make_number (pos),
@@ -24156,7 +24332,8 @@
 		      struct glyph_row *r
 			= MATRIX_ROW (w->current_matrix, vpos);
 		      int start = MATRIX_ROW_START_CHARPOS (r);
-		      int pos = string_buffer_position (w, object, start);
+		      EMACS_INT pos = string_buffer_position (w, object,
+							      start);
 		      if (pos > 0)
 			pointer = Fget_char_property (make_number (pos),
 						      Qpointer, w->buffer);