]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Move some window-related functions from frame.c to window.c.
[gnu-emacs] / src / xdisp.c
index 91d1b6ea2e3dbc9dfbb7ffc4b6f7a3fad2c0804f..02467c7bedd7c82a373ced2d42779ee8a70aa3a1 100644 (file)
@@ -254,7 +254,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
    still left to right, i.e. the iterator "thinks" the first character
    is at the leftmost pixel position.  The iterator does not know that
    PRODUCE_GLYPHS reverses the order of the glyphs that the iterator
    still left to right, i.e. the iterator "thinks" the first character
    is at the leftmost pixel position.  The iterator does not know that
    PRODUCE_GLYPHS reverses the order of the glyphs that the iterator
-   delivers.  This is important when functions from the the move_it_*
+   delivers.  This is important when functions from the move_it_*
    family are used to get to certain screen position or to match
    screen coordinates with buffer coordinates: these functions use the
    iterator geometry, which is left to right even in R2L paragraphs.
    family are used to get to certain screen position or to match
    screen coordinates with buffer coordinates: these functions use the
    iterator geometry, which is left to right even in R2L paragraphs.
@@ -779,7 +779,6 @@ static void store_mode_line_noprop_char (char);
 static int store_mode_line_noprop (const char *, int, int);
 static void handle_stop (struct it *);
 static void handle_stop_backwards (struct it *, EMACS_INT);
 static int store_mode_line_noprop (const char *, int, int);
 static void handle_stop (struct it *);
 static void handle_stop_backwards (struct it *, EMACS_INT);
-static int single_display_spec_intangible_p (Lisp_Object);
 static void vmessage (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0);
 static void ensure_echo_area_buffers (void);
 static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object);
 static void vmessage (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0);
 static void ensure_echo_area_buffers (void);
 static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object);
@@ -812,7 +811,7 @@ static int try_scrolling (Lisp_Object, int, EMACS_INT, EMACS_INT, int, int);
 static int try_cursor_movement (Lisp_Object, struct text_pos, int *);
 static int trailing_whitespace_p (EMACS_INT);
 static unsigned long int message_log_check_duplicate (EMACS_INT, EMACS_INT);
 static int try_cursor_movement (Lisp_Object, struct text_pos, int *);
 static int trailing_whitespace_p (EMACS_INT);
 static unsigned long int message_log_check_duplicate (EMACS_INT, EMACS_INT);
-static void push_it (struct it *);
+static void push_it (struct it *, struct text_pos *);
 static void pop_it (struct it *);
 static void sync_frame_with_window_matrix_rows (struct window *);
 static void select_frame_for_redisplay (Lisp_Object);
 static void pop_it (struct it *);
 static void sync_frame_with_window_matrix_rows (struct window *);
 static void select_frame_for_redisplay (Lisp_Object);
@@ -884,9 +883,11 @@ static void compute_string_pos (struct text_pos *, struct text_pos,
                                 Lisp_Object);
 static int face_before_or_after_it_pos (struct it *, int);
 static EMACS_INT next_overlay_change (EMACS_INT);
                                 Lisp_Object);
 static int face_before_or_after_it_pos (struct it *, int);
 static EMACS_INT next_overlay_change (EMACS_INT);
+static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object,
+                               Lisp_Object, struct text_pos *, EMACS_INT, int);
 static int handle_single_display_spec (struct it *, Lisp_Object,
                                        Lisp_Object, Lisp_Object,
 static int handle_single_display_spec (struct it *, Lisp_Object,
                                        Lisp_Object, Lisp_Object,
-                                       struct text_pos *, int);
+                                       struct text_pos *, EMACS_INT, int, int);
 static int underlying_face_id (struct it *);
 static int in_ellipses_for_invisible_text_p (struct display_pos *,
                                              struct window *);
 static int underlying_face_id (struct it *);
 static int in_ellipses_for_invisible_text_p (struct display_pos *,
                                              struct window *);
@@ -926,7 +927,7 @@ static int coords_in_mouse_face_p (struct window *, int, int);
 
    This is the height of W minus the height of a mode line, if any.  */
 
 
    This is the height of W minus the height of a mode line, if any.  */
 
-INLINE int
+inline int
 window_text_bottom_y (struct window *w)
 {
   int height = WINDOW_TOTAL_HEIGHT (w);
 window_text_bottom_y (struct window *w)
 {
   int height = WINDOW_TOTAL_HEIGHT (w);
@@ -940,7 +941,7 @@ window_text_bottom_y (struct window *w)
    means return the total width of W, not including fringes to
    the left and right of the window.  */
 
    means return the total width of W, not including fringes to
    the left and right of the window.  */
 
-INLINE int
+inline int
 window_box_width (struct window *w, int area)
 {
   int cols = XFASTINT (w->total_cols);
 window_box_width (struct window *w, int area)
 {
   int cols = XFASTINT (w->total_cols);
@@ -979,7 +980,7 @@ window_box_width (struct window *w, int area)
 /* Return the pixel height of the display area of window W, not
    including mode lines of W, if any.  */
 
 /* Return the pixel height of the display area of window W, not
    including mode lines of W, if any.  */
 
-INLINE int
+inline int
 window_box_height (struct window *w)
 {
   struct frame *f = XFRAME (w->frame);
 window_box_height (struct window *w)
 {
   struct frame *f = XFRAME (w->frame);
@@ -1026,7 +1027,7 @@ window_box_height (struct window *w)
    area AREA of window W.  AREA < 0 means return the left edge of the
    whole window, to the right of the left fringe of W.  */
 
    area AREA of window W.  AREA < 0 means return the left edge of the
    whole window, to the right of the left fringe of W.  */
 
-INLINE int
+inline int
 window_box_left_offset (struct window *w, int area)
 {
   int x;
 window_box_left_offset (struct window *w, int area)
 {
   int x;
@@ -1058,7 +1059,7 @@ window_box_left_offset (struct window *w, int area)
    area AREA of window W.  AREA < 0 means return the right edge of the
    whole window, to the left of the right fringe of W.  */
 
    area AREA of window W.  AREA < 0 means return the right edge of the
    whole window, to the left of the right fringe of W.  */
 
-INLINE int
+inline int
 window_box_right_offset (struct window *w, int area)
 {
   return window_box_left_offset (w, area) + window_box_width (w, area);
 window_box_right_offset (struct window *w, int area)
 {
   return window_box_left_offset (w, area) + window_box_width (w, area);
@@ -1068,7 +1069,7 @@ window_box_right_offset (struct window *w, int area)
    area AREA of window W.  AREA < 0 means return the left edge of the
    whole window, to the right of the left fringe of W.  */
 
    area AREA of window W.  AREA < 0 means return the left edge of the
    whole window, to the right of the left fringe of W.  */
 
-INLINE int
+inline int
 window_box_left (struct window *w, int area)
 {
   struct frame *f = XFRAME (w->frame);
 window_box_left (struct window *w, int area)
 {
   struct frame *f = XFRAME (w->frame);
@@ -1088,7 +1089,7 @@ window_box_left (struct window *w, int area)
    area AREA of window W.  AREA < 0 means return the right edge of the
    whole window, to the left of the right fringe of W.  */
 
    area AREA of window W.  AREA < 0 means return the right edge of the
    whole window, to the left of the right fringe of W.  */
 
-INLINE int
+inline int
 window_box_right (struct window *w, int area)
 {
   return window_box_left (w, area) + window_box_width (w, area);
 window_box_right (struct window *w, int area)
 {
   return window_box_left (w, area) + window_box_width (w, area);
@@ -1101,7 +1102,7 @@ window_box_right (struct window *w, int area)
    coordinates of the upper-left corner of the box.  Return in
    *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box.  */
 
    coordinates of the upper-left corner of the box.  Return in
    *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box.  */
 
-INLINE void
+inline void
 window_box (struct window *w, int area, int *box_x, int *box_y,
            int *box_width, int *box_height)
 {
 window_box (struct window *w, int area, int *box_x, int *box_y,
            int *box_width, int *box_height)
 {
@@ -1128,7 +1129,7 @@ window_box (struct window *w, int area, int *box_x, int *box_y,
    *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
    box.  */
 
    *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
    box.  */
 
-static INLINE void
+static inline void
 window_box_edges (struct window *w, int area, int *top_left_x, int *top_left_y,
                   int *bottom_right_x, int *bottom_right_y)
 {
 window_box_edges (struct window *w, int area, int *top_left_x, int *top_left_y,
                   int *bottom_right_x, int *bottom_right_y)
 {
@@ -1328,7 +1329,7 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y,
    returns an invalid character.  If we find one, we return a `?', but
    with the length of the invalid character.  */
 
    returns an invalid character.  If we find one, we return a `?', but
    with the length of the invalid character.  */
 
-static INLINE int
+static inline int
 string_char_and_length (const unsigned char *str, int *len)
 {
   int c;
 string_char_and_length (const unsigned char *str, int *len)
 {
   int c;
@@ -1376,7 +1377,7 @@ string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, EMACS_INT ncha
 /* Value is the text position, i.e. character and byte position,
    for character position CHARPOS in STRING.  */
 
 /* Value is the text position, i.e. character and byte position,
    for character position CHARPOS in STRING.  */
 
-static INLINE struct text_pos
+static inline struct text_pos
 string_pos (EMACS_INT charpos, Lisp_Object string)
 {
   struct text_pos pos;
 string_pos (EMACS_INT charpos, Lisp_Object string)
 {
   struct text_pos pos;
@@ -2564,7 +2565,7 @@ init_iterator (struct it *it, struct window *w,
        it->paragraph_embedding = R2L;
       else
        it->paragraph_embedding = NEUTRAL_DIR;
        it->paragraph_embedding = R2L;
       else
        it->paragraph_embedding = NEUTRAL_DIR;
-      bidi_init_it (charpos, bytepos, &it->bidi_it);
+      bidi_init_it (charpos, bytepos, FRAME_WINDOW_P (it->f), &it->bidi_it);
     }
 
   /* If a buffer position was specified, set the iterator there,
     }
 
   /* If a buffer position was specified, set the iterator there,
@@ -3085,6 +3086,82 @@ next_overlay_change (EMACS_INT pos)
   return endpos;
 }
 
   return endpos;
 }
 
+/* Return the character position of a display string at or after CHARPOS.
+   If no display string exists at or after CHARPOS, return ZV.  A
+   display string is either an overlay with `display' property whose
+   value is a string, or a `display' text property whose value is a
+   string.  FRAME_WINDOW_P is non-zero when we are displaying a window
+   on a GUI frame.  */
+EMACS_INT
+compute_display_string_pos (EMACS_INT charpos, int frame_window_p)
+{
+  /* FIXME: Support display properties on strings (object = Qnil means
+     current buffer).  */
+  Lisp_Object object = Qnil;
+  Lisp_Object pos, spec;
+  struct text_pos position;
+  EMACS_INT bufpos;
+
+  if (charpos >= ZV)
+    return ZV;
+
+  /* If the character at CHARPOS is where the display string begins,
+     return CHARPOS.  */
+  pos = make_number (charpos);
+  CHARPOS (position) = charpos;
+  BYTEPOS (position) = CHAR_TO_BYTE (charpos);
+  bufpos = charpos;    /* FIXME! support strings as well */
+  if (!NILP (spec = Fget_char_property (pos, Qdisplay, object))
+      && (charpos <= BEGV
+         || !EQ (Fget_char_property (make_number (charpos - 1), Qdisplay,
+                                     object),
+                 spec))
+      && handle_display_spec (NULL, spec, object, Qnil, &position, bufpos,
+                             frame_window_p))
+    return charpos;
+
+  /* Look forward for the first character with a `display' property
+     that will replace the underlying text when displayed.  */
+  do {
+    pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
+    CHARPOS (position) = XFASTINT (pos);
+    BYTEPOS (position) = CHAR_TO_BYTE (CHARPOS (position));
+    if (CHARPOS (position) >= ZV)
+      break;
+    spec = Fget_char_property (pos, Qdisplay, object);
+    bufpos = CHARPOS (position);       /* FIXME! support strings as well */
+  } while (NILP (spec)
+          || !handle_display_spec (NULL, spec, object, Qnil, &position, bufpos,
+                                   frame_window_p));
+
+  return CHARPOS (position);
+}
+
+/* Return the character position of the end of the display string that
+   started at CHARPOS.  A display string is either an overlay with
+   `display' property whose value is a string or a `display' text
+   property whose value is a string.  */
+EMACS_INT
+compute_display_string_end (EMACS_INT charpos)
+{
+  /* FIXME: Support display properties on strings (object = Qnil means
+     current buffer).  */
+  Lisp_Object object = Qnil;
+  Lisp_Object pos = make_number (charpos);
+
+  if (charpos >= ZV)
+    return ZV;
+
+  if (NILP (Fget_char_property (pos, Qdisplay, object)))
+    abort ();
+
+  /* Look forward for the first character where the `display' property
+     changes.  */
+  pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
+
+  return XFASTINT (pos);
+}
+
 
 \f
 /***********************************************************************
 
 \f
 /***********************************************************************
@@ -3705,7 +3782,7 @@ setup_for_ellipsis (struct it *it, int len)
     {
       struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
       it->dpvec = v->contents;
     {
       struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
       it->dpvec = v->contents;
-      it->dpend = v->contents + v->size;
+      it->dpend = v->contents + v->header.size;
     }
   else
     {
     }
   else
     {
@@ -3743,8 +3820,9 @@ setup_for_ellipsis (struct it *it, int len)
 static enum prop_handled
 handle_display_prop (struct it *it)
 {
 static enum prop_handled
 handle_display_prop (struct it *it)
 {
-  Lisp_Object prop, object, overlay;
+  Lisp_Object propval, object, overlay;
   struct text_pos *position;
   struct text_pos *position;
+  EMACS_INT bufpos;
   /* Nonzero if some property replaces the display of the text itself.  */
   int display_replaced_p = 0;
 
   /* Nonzero if some property replaces the display of the text itself.  */
   int display_replaced_p = 0;
 
@@ -3752,11 +3830,13 @@ handle_display_prop (struct it *it)
     {
       object = it->string;
       position = &it->current.string_pos;
     {
       object = it->string;
       position = &it->current.string_pos;
+      bufpos = CHARPOS (it->current.pos);
     }
   else
     {
       XSETWINDOW (object, it->w);
       position = &it->current.pos;
     }
   else
     {
       XSETWINDOW (object, it->w);
       position = &it->current.pos;
+      bufpos = CHARPOS (*position);
     }
 
   /* Reset those iterator values set from display property values.  */
     }
 
   /* Reset those iterator values set from display property values.  */
@@ -3771,9 +3851,9 @@ handle_display_prop (struct it *it)
   if (!it->string_from_display_prop_p)
     it->area = TEXT_AREA;
 
   if (!it->string_from_display_prop_p)
     it->area = TEXT_AREA;
 
-  prop = get_char_property_and_overlay (make_number (position->charpos),
-                                       Qdisplay, object, &overlay);
-  if (NILP (prop))
+  propval = get_char_property_and_overlay (make_number (position->charpos),
+                                          Qdisplay, object, &overlay);
+  if (NILP (propval))
     return HANDLED_NORMALLY;
   /* Now OVERLAY is the overlay that gave us this property, or nil
      if it was a text property.  */
     return HANDLED_NORMALLY;
   /* Now OVERLAY is the overlay that gave us this property, or nil
      if it was a text property.  */
@@ -3781,59 +3861,88 @@ handle_display_prop (struct it *it)
   if (!STRINGP (it->string))
     object = it->w->buffer;
 
   if (!STRINGP (it->string))
     object = it->w->buffer;
 
-  if (CONSP (prop)
-      /* Simple properties.  */
-      && !EQ (XCAR (prop), Qimage)
-      && !EQ (XCAR (prop), Qspace)
-      && !EQ (XCAR (prop), Qwhen)
-      && !EQ (XCAR (prop), Qslice)
-      && !EQ (XCAR (prop), Qspace_width)
-      && !EQ (XCAR (prop), Qheight)
-      && !EQ (XCAR (prop), Qraise)
+  display_replaced_p = handle_display_spec (it, propval, object, overlay,
+                                           position, bufpos,
+                                           FRAME_WINDOW_P (it->f));
+
+  return display_replaced_p ? HANDLED_RETURN : HANDLED_NORMALLY;
+}
+
+/* Subroutine of handle_display_prop.  Returns non-zero if the display
+   specification in SPEC is a replacing specification, i.e. it would
+   replace the text covered by `display' property with something else,
+   such as an image or a display string.
+
+   See handle_single_display_spec for documentation of arguments.
+   frame_window_p is non-zero if the window being redisplayed is on a
+   GUI frame; this argument is used only if IT is NULL, see below.
+
+   IT can be NULL, if this is called by the bidi reordering code
+   through compute_display_string_pos, which see.  In that case, this
+   function only examines SPEC, but does not otherwise "handle" it, in
+   the sense that it doesn't set up members of IT from the display
+   spec.  */
+static int
+handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
+                    Lisp_Object overlay, struct text_pos *position,
+                    EMACS_INT bufpos, int frame_window_p)
+{
+  int replacing_p = 0;
+
+  if (CONSP (spec)
+      /* Simple specerties.  */
+      && !EQ (XCAR (spec), Qimage)
+      && !EQ (XCAR (spec), Qspace)
+      && !EQ (XCAR (spec), Qwhen)
+      && !EQ (XCAR (spec), Qslice)
+      && !EQ (XCAR (spec), Qspace_width)
+      && !EQ (XCAR (spec), Qheight)
+      && !EQ (XCAR (spec), Qraise)
       /* Marginal area specifications.  */
       /* Marginal area specifications.  */
-      && !(CONSP (XCAR (prop)) && EQ (XCAR (XCAR (prop)), Qmargin))
-      && !EQ (XCAR (prop), Qleft_fringe)
-      && !EQ (XCAR (prop), Qright_fringe)
-      && !NILP (XCAR (prop)))
+      && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin))
+      && !EQ (XCAR (spec), Qleft_fringe)
+      && !EQ (XCAR (spec), Qright_fringe)
+      && !NILP (XCAR (spec)))
     {
     {
-      for (; CONSP (prop); prop = XCDR (prop))
+      for (; CONSP (spec); spec = XCDR (spec))
        {
        {
-         if (handle_single_display_spec (it, XCAR (prop), object, overlay,
-                                         position, display_replaced_p))
+         if (handle_single_display_spec (it, XCAR (spec), object, overlay,
+                                         position, bufpos, replacing_p,
+                                         frame_window_p))
            {
            {
-             display_replaced_p = 1;
+             replacing_p = 1;
              /* If some text in a string is replaced, `position' no
                 longer points to the position of `object'.  */
              /* If some text in a string is replaced, `position' no
                 longer points to the position of `object'.  */
-             if (STRINGP (object))
+             if (!it || STRINGP (object))
                break;
            }
        }
     }
                break;
            }
        }
     }
-  else if (VECTORP (prop))
+  else if (VECTORP (spec))
     {
       int i;
     {
       int i;
-      for (i = 0; i < ASIZE (prop); ++i)
-       if (handle_single_display_spec (it, AREF (prop, i), object, overlay,
-                                       position, display_replaced_p))
+      for (i = 0; i < ASIZE (spec); ++i)
+       if (handle_single_display_spec (it, AREF (spec, i), object, overlay,
+                                       position, bufpos, replacing_p,
+                                       frame_window_p))
          {
          {
-           display_replaced_p = 1;
+           replacing_p = 1;
            /* If some text in a string is replaced, `position' no
               longer points to the position of `object'.  */
            /* If some text in a string is replaced, `position' no
               longer points to the position of `object'.  */
-           if (STRINGP (object))
+           if (!it || STRINGP (object))
              break;
          }
     }
   else
     {
              break;
          }
     }
   else
     {
-      if (handle_single_display_spec (it, prop, object, overlay,
-                                     position, 0))
-       display_replaced_p = 1;
+      if (handle_single_display_spec (it, spec, object, overlay,
+                                     position, bufpos, 0, frame_window_p))
+       replacing_p = 1;
     }
 
     }
 
-  return display_replaced_p ? HANDLED_RETURN : HANDLED_NORMALLY;
+  return replacing_p;
 }
 
 }
 
-
 /* Value is the position of the end of the `display' property starting
    at START_POS in OBJECT.  */
 
 /* Value is the position of the end of the `display' property starting
    at START_POS in OBJECT.  */
 
@@ -3855,31 +3964,38 @@ display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
 }
 
 
 }
 
 
-/* Set up IT from a single `display' specification PROP.  OBJECT
+/* Set up IT from a single `display' property specification SPEC.  OBJECT
    is the object in which the `display' property was found.  *POSITION
    is the object in which the `display' property was found.  *POSITION
-   is the position at which it was found.  DISPLAY_REPLACED_P non-zero
-   means that we previously saw a display specification which already
-   replaced text display with something else, for example an image;
-   we ignore such properties after the first one has been processed.
+   is the position in OBJECT at which the `display' property was found.
+   BUFPOS is the buffer position of OBJECT (different from POSITION if
+   OBJECT is not a buffer).  DISPLAY_REPLACED_P non-zero means that we
+   previously saw a display specification which already replaced text
+   display with something else, for example an image; we ignore such
+   properties after the first one has been processed.
 
    OVERLAY is the overlay this `display' property came from,
    or nil if it was a text property.
 
 
    OVERLAY is the overlay this `display' property came from,
    or nil if it was a text property.
 
-   If PROP is a `space' or `image' specification, and in some other
+   If SPEC is a `space' or `image' specification, and in some other
    cases too, set *POSITION to the position where the `display'
    property ends.
 
    cases too, set *POSITION to the position where the `display'
    property ends.
 
+   If IT is NULL, only examine the property specification in SPEC, but
+   don't set up IT.  In that case, FRAME_WINDOW_P non-zero means SPEC
+   is intended to be displayed in a window on a GUI frame.
+
    Value is non-zero if something was found which replaces the display
    of buffer or string text.  */
 
 static int
 handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
                            Lisp_Object overlay, struct text_pos *position,
    Value is non-zero if something was found which replaces the display
    of buffer or string text.  */
 
 static int
 handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
                            Lisp_Object overlay, struct text_pos *position,
-                           int display_replaced_before_p)
+                           EMACS_INT bufpos, int display_replaced_p,
+                           int frame_window_p)
 {
   Lisp_Object form;
   Lisp_Object location, value;
 {
   Lisp_Object form;
   Lisp_Object location, value;
-  struct text_pos start_pos, save_pos;
+  struct text_pos start_pos = *position;
   int valid_p;
 
   /* If SPEC is a list of the form `(when FORM . VALUE)', evaluate FORM.
   int valid_p;
 
   /* If SPEC is a list of the form `(when FORM . VALUE)', evaluate FORM.
@@ -3903,11 +4019,12 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
         buffer or string.  Bind `position' to the position in the
         object where the property was found, and `buffer-position'
         to the current position in the buffer.  */
         buffer or string.  Bind `position' to the position in the
         object where the property was found, and `buffer-position'
         to the current position in the buffer.  */
+
+      if (NILP (object))
+       XSETBUFFER (object, current_buffer);
       specbind (Qobject, object);
       specbind (Qposition, make_number (CHARPOS (*position)));
       specbind (Qobject, object);
       specbind (Qposition, make_number (CHARPOS (*position)));
-      specbind (Qbuffer_position,
-               make_number (STRINGP (object)
-                            ? IT_CHARPOS (*it) : CHARPOS (*position)));
+      specbind (Qbuffer_position, make_number (bufpos));
       GCPRO1 (form);
       form = safe_eval (form);
       UNGCPRO;
       GCPRO1 (form);
       form = safe_eval (form);
       UNGCPRO;
@@ -3922,63 +4039,66 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
       && EQ (XCAR (spec), Qheight)
       && CONSP (XCDR (spec)))
     {
       && EQ (XCAR (spec), Qheight)
       && CONSP (XCDR (spec)))
     {
-      if (!FRAME_WINDOW_P (it->f))
-       return 0;
-
-      it->font_height = XCAR (XCDR (spec));
-      if (!NILP (it->font_height))
+      if (it)
        {
        {
-         struct face *face = FACE_FROM_ID (it->f, it->face_id);
-         int new_height = -1;
+         if (!FRAME_WINDOW_P (it->f))
+           return 0;
 
 
-         if (CONSP (it->font_height)
-             && (EQ (XCAR (it->font_height), Qplus)
-                 || EQ (XCAR (it->font_height), Qminus))
-             && CONSP (XCDR (it->font_height))
-             && INTEGERP (XCAR (XCDR (it->font_height))))
+         it->font_height = XCAR (XCDR (spec));
+         if (!NILP (it->font_height))
            {
            {
-             /* `(+ N)' or `(- N)' where N is an integer.  */
-             int steps = XINT (XCAR (XCDR (it->font_height)));
-             if (EQ (XCAR (it->font_height), Qplus))
-               steps = - steps;
-             it->face_id = smaller_face (it->f, it->face_id, steps);
-           }
-         else if (FUNCTIONP (it->font_height))
-           {
-             /* Call function with current height as argument.
-                Value is the new height.  */
-             Lisp_Object height;
-             height = safe_call1 (it->font_height,
-                                  face->lface[LFACE_HEIGHT_INDEX]);
-             if (NUMBERP (height))
-               new_height = XFLOATINT (height);
-           }
-         else if (NUMBERP (it->font_height))
-           {
-             /* Value is a multiple of the canonical char height.  */
-             struct face *f;
+             struct face *face = FACE_FROM_ID (it->f, it->face_id);
+             int new_height = -1;
+
+             if (CONSP (it->font_height)
+                 && (EQ (XCAR (it->font_height), Qplus)
+                     || EQ (XCAR (it->font_height), Qminus))
+                 && CONSP (XCDR (it->font_height))
+                 && INTEGERP (XCAR (XCDR (it->font_height))))
+               {
+                 /* `(+ N)' or `(- N)' where N is an integer.  */
+                 int steps = XINT (XCAR (XCDR (it->font_height)));
+                 if (EQ (XCAR (it->font_height), Qplus))
+                   steps = - steps;
+                 it->face_id = smaller_face (it->f, it->face_id, steps);
+               }
+             else if (FUNCTIONP (it->font_height))
+               {
+                 /* Call function with current height as argument.
+                    Value is the new height.  */
+                 Lisp_Object height;
+                 height = safe_call1 (it->font_height,
+                                      face->lface[LFACE_HEIGHT_INDEX]);
+                 if (NUMBERP (height))
+                   new_height = XFLOATINT (height);
+               }
+             else if (NUMBERP (it->font_height))
+               {
+                 /* Value is a multiple of the canonical char height.  */
+                 struct face *f;
 
 
-             f = FACE_FROM_ID (it->f,
-                               lookup_basic_face (it->f, DEFAULT_FACE_ID));
-             new_height = (XFLOATINT (it->font_height)
-                           * XINT (f->lface[LFACE_HEIGHT_INDEX]));
-           }
-         else
-           {
-             /* Evaluate IT->font_height with `height' bound to the
-                current specified height to get the new height.  */
-             int count = SPECPDL_INDEX ();
+                 f = FACE_FROM_ID (it->f,
+                                   lookup_basic_face (it->f, DEFAULT_FACE_ID));
+                 new_height = (XFLOATINT (it->font_height)
+                               * XINT (f->lface[LFACE_HEIGHT_INDEX]));
+               }
+             else
+               {
+                 /* Evaluate IT->font_height with `height' bound to the
+                    current specified height to get the new height.  */
+                 int count = SPECPDL_INDEX ();
 
 
-             specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
-             value = safe_eval (it->font_height);
-             unbind_to (count, Qnil);
+                 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
+                 value = safe_eval (it->font_height);
+                 unbind_to (count, Qnil);
 
 
-             if (NUMBERP (value))
-               new_height = XFLOATINT (value);
-           }
+                 if (NUMBERP (value))
+                   new_height = XFLOATINT (value);
+               }
 
 
-         if (new_height > 0)
-           it->face_id = face_with_height (it->f, it->face_id, new_height);
+             if (new_height > 0)
+               it->face_id = face_with_height (it->f, it->face_id, new_height);
+           }
        }
 
       return 0;
        }
 
       return 0;
@@ -3989,12 +4109,15 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
       && EQ (XCAR (spec), Qspace_width)
       && CONSP (XCDR (spec)))
     {
       && EQ (XCAR (spec), Qspace_width)
       && CONSP (XCDR (spec)))
     {
-      if (!FRAME_WINDOW_P (it->f))
-       return 0;
+      if (it)
+       {
+         if (!FRAME_WINDOW_P (it->f))
+           return 0;
 
 
-      value = XCAR (XCDR (spec));
-      if (NUMBERP (value) && XFLOATINT (value) > 0)
-       it->space_width = value;
+         value = XCAR (XCDR (spec));
+         if (NUMBERP (value) && XFLOATINT (value) > 0)
+           it->space_width = value;
+       }
 
       return 0;
     }
 
       return 0;
     }
@@ -4005,20 +4128,23 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
     {
       Lisp_Object tem;
 
     {
       Lisp_Object tem;
 
-      if (!FRAME_WINDOW_P (it->f))
-       return 0;
-
-      if (tem = XCDR (spec), CONSP (tem))
+      if (it)
        {
        {
-         it->slice.x = XCAR (tem);
-         if (tem = XCDR (tem), CONSP (tem))
+         if (!FRAME_WINDOW_P (it->f))
+           return 0;
+
+         if (tem = XCDR (spec), CONSP (tem))
            {
            {
-             it->slice.y = XCAR (tem);
+             it->slice.x = XCAR (tem);
              if (tem = XCDR (tem), CONSP (tem))
                {
              if (tem = XCDR (tem), CONSP (tem))
                {
-                 it->slice.width = XCAR (tem);
+                 it->slice.y = XCAR (tem);
                  if (tem = XCDR (tem), CONSP (tem))
                  if (tem = XCDR (tem), CONSP (tem))
-                   it->slice.height = XCAR (tem);
+                   {
+                     it->slice.width = XCAR (tem);
+                     if (tem = XCDR (tem), CONSP (tem))
+                       it->slice.height = XCAR (tem);
+                   }
                }
            }
        }
                }
            }
        }
@@ -4031,36 +4157,43 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
       && EQ (XCAR (spec), Qraise)
       && CONSP (XCDR (spec)))
     {
       && EQ (XCAR (spec), Qraise)
       && CONSP (XCDR (spec)))
     {
-      if (!FRAME_WINDOW_P (it->f))
-       return 0;
+      if (it)
+       {
+         if (!FRAME_WINDOW_P (it->f))
+           return 0;
 
 #ifdef HAVE_WINDOW_SYSTEM
 
 #ifdef HAVE_WINDOW_SYSTEM
-      value = XCAR (XCDR (spec));
-      if (NUMBERP (value))
-       {
-         struct face *face = FACE_FROM_ID (it->f, it->face_id);
-         it->voffset = - (XFLOATINT (value)
-                          * (FONT_HEIGHT (face->font)));
-       }
+         value = XCAR (XCDR (spec));
+         if (NUMBERP (value))
+           {
+             struct face *face = FACE_FROM_ID (it->f, it->face_id);
+             it->voffset = - (XFLOATINT (value)
+                              * (FONT_HEIGHT (face->font)));
+           }
 #endif /* HAVE_WINDOW_SYSTEM */
 #endif /* HAVE_WINDOW_SYSTEM */
+       }
 
       return 0;
     }
 
   /* Don't handle the other kinds of display specifications
      inside a string that we got from a `display' property.  */
 
       return 0;
     }
 
   /* Don't handle the other kinds of display specifications
      inside a string that we got from a `display' property.  */
-  if (it->string_from_display_prop_p)
+  if (it && it->string_from_display_prop_p)
     return 0;
 
   /* Characters having this form of property are not displayed, so
      we have to find the end of the property.  */
     return 0;
 
   /* Characters having this form of property are not displayed, so
      we have to find the end of the property.  */
-  start_pos = *position;
-  *position = display_prop_end (it, object, start_pos);
+  if (it)
+    {
+      start_pos = *position;
+      *position = display_prop_end (it, object, start_pos);
+    }
   value = Qnil;
 
   /* Stop the scan at that end position--we assume that all
      text properties change there.  */
   value = Qnil;
 
   /* Stop the scan at that end position--we assume that all
      text properties change there.  */
-  it->stop_charpos = position->charpos;
+  if (it)
+    it->stop_charpos = position->charpos;
 
   /* Handle `(left-fringe BITMAP [FACE])'
      and `(right-fringe BITMAP [FACE])'.  */
 
   /* Handle `(left-fringe BITMAP [FACE])'
      and `(right-fringe BITMAP [FACE])'.  */
@@ -4069,12 +4202,16 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
          || EQ (XCAR (spec), Qright_fringe))
       && CONSP (XCDR (spec)))
     {
          || EQ (XCAR (spec), Qright_fringe))
       && CONSP (XCDR (spec)))
     {
-      int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);
       int fringe_bitmap;
 
       int fringe_bitmap;
 
-      if (!FRAME_WINDOW_P (it->f))
-       /* If we return here, POSITION has been advanced
-          across the text with this property.  */
+      if (it)
+       {
+         if (!FRAME_WINDOW_P (it->f))
+           /* If we return here, POSITION has been advanced
+              across the text with this property.  */
+           return 0;
+       }
+      else if (!frame_window_p)
        return 0;
 
 #ifdef HAVE_WINDOW_SYSTEM
        return 0;
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -4085,46 +4222,47 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
           across the text with this property.  */
        return 0;
 
           across the text with this property.  */
        return 0;
 
-      if (CONSP (XCDR (XCDR (spec))))
+      if (it)
        {
        {
-         Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
-         int face_id2 = lookup_derived_face (it->f, face_name,
-                                             FRINGE_FACE_ID, 0);
-         if (face_id2 >= 0)
-           face_id = face_id2;
-       }
+         int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);;
 
 
-      /* Save current settings of IT so that we can restore them
-        when we are finished with the glyph property value.  */
+         if (CONSP (XCDR (XCDR (spec))))
+           {
+             Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
+             int face_id2 = lookup_derived_face (it->f, face_name,
+                                                 FRINGE_FACE_ID, 0);
+             if (face_id2 >= 0)
+               face_id = face_id2;
+           }
 
 
-      save_pos = it->position;
-      it->position = *position;
-      push_it (it);
-      it->position = save_pos;
+         /* Save current settings of IT so that we can restore them
+            when we are finished with the glyph property value.  */
+         push_it (it, position);
 
 
-      it->area = TEXT_AREA;
-      it->what = IT_IMAGE;
-      it->image_id = -1; /* no image */
-      it->position = start_pos;
-      it->object = NILP (object) ? it->w->buffer : object;
-      it->method = GET_FROM_IMAGE;
-      it->from_overlay = Qnil;
-      it->face_id = face_id;
+         it->area = TEXT_AREA;
+         it->what = IT_IMAGE;
+         it->image_id = -1; /* no image */
+         it->position = start_pos;
+         it->object = NILP (object) ? it->w->buffer : object;
+         it->method = GET_FROM_IMAGE;
+         it->from_overlay = Qnil;
+         it->face_id = face_id;
 
 
-      /* Say that we haven't consumed the characters with
-        `display' property yet.  The call to pop_it in
-        set_iterator_to_next will clean this up.  */
-      *position = start_pos;
+         /* Say that we haven't consumed the characters with
+            `display' property yet.  The call to pop_it in
+            set_iterator_to_next will clean this up.  */
+         *position = start_pos;
 
 
-      if (EQ (XCAR (spec), Qleft_fringe))
-       {
-         it->left_user_fringe_bitmap = fringe_bitmap;
-         it->left_user_fringe_face_id = face_id;
-       }
-      else
-        {
-         it->right_user_fringe_bitmap = fringe_bitmap;
-         it->right_user_fringe_face_id = face_id;
+         if (EQ (XCAR (spec), Qleft_fringe))
+           {
+             it->left_user_fringe_bitmap = fringe_bitmap;
+             it->left_user_fringe_face_id = face_id;
+           }
+         else
+           {
+             it->right_user_fringe_bitmap = fringe_bitmap;
+             it->right_user_fringe_face_id = face_id;
+           }
        }
 #endif /* HAVE_WINDOW_SYSTEM */
       return 1;
        }
 #endif /* HAVE_WINDOW_SYSTEM */
       return 1;
@@ -4167,18 +4305,19 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
 
   valid_p = (STRINGP (value)
 #ifdef HAVE_WINDOW_SYSTEM
 
   valid_p = (STRINGP (value)
 #ifdef HAVE_WINDOW_SYSTEM
-             || (FRAME_WINDOW_P (it->f) && valid_image_p (value))
+             || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
+                && valid_image_p (value))
 #endif /* not HAVE_WINDOW_SYSTEM */
              || (CONSP (value) && EQ (XCAR (value), Qspace)));
 
 #endif /* not HAVE_WINDOW_SYSTEM */
              || (CONSP (value) && EQ (XCAR (value), Qspace)));
 
-  if (valid_p && !display_replaced_before_p)
+  if (valid_p && !display_replaced_p)
     {
     {
+      if (!it)
+       return 1;
+
       /* Save current settings of IT so that we can restore them
         when we are finished with the glyph property value.  */
       /* Save current settings of IT so that we can restore them
         when we are finished with the glyph property value.  */
-      save_pos = it->position;
-      it->position = *position;
-      push_it (it);
-      it->position = save_pos;
+      push_it (it, position);
       it->from_overlay = overlay;
 
       if (NILP (location))
       it->from_overlay = overlay;
 
       if (NILP (location))
@@ -4235,83 +4374,31 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
   return 0;
 }
 
   return 0;
 }
 
-
-/* Check if SPEC is a display sub-property value whose text should be
-   treated as intangible.  */
-
-static int
-single_display_spec_intangible_p (Lisp_Object prop)
-{
-  /* Skip over `when FORM'.  */
-  if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
-    {
-      prop = XCDR (prop);
-      if (!CONSP (prop))
-       return 0;
-      prop = XCDR (prop);
-    }
-
-  if (STRINGP (prop))
-    return 1;
-
-  if (!CONSP (prop))
-    return 0;
-
-  /* Skip over `margin LOCATION'.  If LOCATION is in the margins,
-     we don't need to treat text as intangible.  */
-  if (EQ (XCAR (prop), Qmargin))
-    {
-      prop = XCDR (prop);
-      if (!CONSP (prop))
-       return 0;
-
-      prop = XCDR (prop);
-      if (!CONSP (prop)
-         || EQ (XCAR (prop), Qleft_margin)
-         || EQ (XCAR (prop), Qright_margin))
-       return 0;
-    }
-
-  return (CONSP (prop)
-         && (EQ (XCAR (prop), Qimage)
-             || EQ (XCAR (prop), Qspace)));
-}
-
-
 /* Check if PROP is a display property value whose text should be
 /* Check if PROP is a display property value whose text should be
-   treated as intangible.  */
+   treated as intangible.  OVERLAY is the overlay from which PROP
+   came, or nil if it came from a text property.  CHARPOS and BYTEPOS
+   specify the buffer position covered by PROP.  */
 
 int
 
 int
-display_prop_intangible_p (Lisp_Object prop)
+display_prop_intangible_p (Lisp_Object prop, Lisp_Object overlay,
+                          EMACS_INT charpos, EMACS_INT bytepos)
 {
 {
-  if (CONSP (prop)
-      && CONSP (XCAR (prop))
-      && !EQ (Qmargin, XCAR (XCAR (prop))))
-    {
-      /* A list of sub-properties.  */
-      while (CONSP (prop))
-       {
-         if (single_display_spec_intangible_p (XCAR (prop)))
-           return 1;
-         prop = XCDR (prop);
-       }
-    }
-  else if (VECTORP (prop))
-    {
-      /* A vector of sub-properties.  */
-      int i;
-      for (i = 0; i < ASIZE (prop); ++i)
-       if (single_display_spec_intangible_p (AREF (prop, i)))
-         return 1;
-    }
-  else
-    return single_display_spec_intangible_p (prop);
+  int frame_window_p = FRAME_WINDOW_P (XFRAME (selected_frame));
+  struct text_pos position;
 
 
-  return 0;
+  SET_TEXT_POS (position, charpos, bytepos);
+  return handle_display_spec (NULL, prop, Qnil, overlay,
+                             &position, charpos, frame_window_p);
 }
 
 
 }
 
 
-/* Return 1 if PROP is a display sub-property value containing STRING.  */
+/* Return 1 if PROP is a display sub-property value containing STRING.
+
+   Implementation note: this and the following function are really
+   special cases of handle_display_spec and
+   handle_single_display_spec, and should ideally use the same code.
+   Until they do, these two pairs must be consistent and must be
+   modified in sync.  */
 
 static int
 single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
 
 static int
 single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
@@ -4325,6 +4412,16 @@ single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
       prop = XCDR (prop);
       if (!CONSP (prop))
        return 0;
       prop = XCDR (prop);
       if (!CONSP (prop))
        return 0;
+      /* Actually, the condition following `when' should be eval'ed,
+        like handle_single_display_spec does, and we should return
+        zero if it evaluates to nil.  However, this function is
+        called only when the buffer was already displayed and some
+        glyph in the glyph matrix was found to come from a display
+        string.  Therefore, the condition was already evaluated, and
+        the result was non-nil, otherwise the display string wouldn't
+        have been displayed and we would have never been called for
+        this property.  Thus, we can skip the evaluation and assume
+        its result is non-nil.  */
       prop = XCDR (prop);
     }
 
       prop = XCDR (prop);
     }
 
@@ -4341,7 +4438,7 @@ single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
          return 0;
       }
 
          return 0;
       }
 
-  return CONSP (prop) && EQ (XCAR (prop), string);
+  return EQ (prop, string) || (CONSP (prop) && EQ (XCAR (prop), string));
 }
 
 
 }
 
 
@@ -4351,8 +4448,8 @@ static int
 display_prop_string_p (Lisp_Object prop, Lisp_Object string)
 {
   if (CONSP (prop)
 display_prop_string_p (Lisp_Object prop, Lisp_Object string)
 {
   if (CONSP (prop)
-      && CONSP (XCAR (prop))
-      && !EQ (Qmargin, XCAR (XCAR (prop))))
+      && !EQ (XCAR (prop), Qwhen)
+      && !(CONSP (XCAR (prop)) && EQ (Qmargin, XCAR (XCAR (prop)))))
     {
       /* A list of sub-properties.  */
       while (CONSP (prop))
     {
       /* A list of sub-properties.  */
       while (CONSP (prop))
@@ -4852,7 +4949,7 @@ get_overlay_strings_1 (struct it *it, EMACS_INT charpos, int compute_stop_p)
       /* When called from handle_stop, there might be an empty display
          string loaded.  In that case, don't bother saving it.  */
       if (!STRINGP (it->string) || SCHARS (it->string))
       /* When called from handle_stop, there might be an empty display
          string loaded.  In that case, don't bother saving it.  */
       if (!STRINGP (it->string) || SCHARS (it->string))
-       push_it (it);
+       push_it (it, NULL);
 
       /* Set up IT to deliver display elements from the first overlay
         string.  */
 
       /* Set up IT to deliver display elements from the first overlay
         string.  */
@@ -4894,10 +4991,11 @@ get_overlay_strings (struct it *it, EMACS_INT charpos)
 /* Save current settings of IT on IT->stack.  Called, for example,
    before setting up IT for an overlay string, to be able to restore
    IT's settings to what they were after the overlay string has been
 /* Save current settings of IT on IT->stack.  Called, for example,
    before setting up IT for an overlay string, to be able to restore
    IT's settings to what they were after the overlay string has been
-   processed.  */
+   processed.  If POSITION is non-NULL, it is the position to save on
+   the stack instead of IT->position.  */
 
 static void
 
 static void
-push_it (struct it *it)
+push_it (struct it *it, struct text_pos *position)
 {
   struct iterator_stack_entry *p;
 
 {
   struct iterator_stack_entry *p;
 
@@ -4924,7 +5022,7 @@ push_it (struct it *it)
       p->u.stretch.object = it->object;
       break;
     }
       p->u.stretch.object = it->object;
       break;
     }
-  p->position = it->position;
+  p->position = position ? *position : it->position;
   p->current = it->current;
   p->end_charpos = it->end_charpos;
   p->string_nchars = it->string_nchars;
   p->current = it->current;
   p->end_charpos = it->end_charpos;
   p->string_nchars = it->string_nchars;
@@ -5382,6 +5480,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
     {
       it->bidi_it.first_elt = 1;
       it->bidi_it.paragraph_dir = NEUTRAL_DIR;
     {
       it->bidi_it.first_elt = 1;
       it->bidi_it.paragraph_dir = NEUTRAL_DIR;
+      it->bidi_it.disp_pos = -1;
     }
 
   if (set_stop_p)
     }
 
   if (set_stop_p)
@@ -5659,11 +5758,11 @@ get_next_display_element (struct it *it)
              /* Return the first character from the display table
                 entry, if not empty.  If empty, don't display the
                 current character.  */
              /* Return the first character from the display table
                 entry, if not empty.  If empty, don't display the
                 current character.  */
-             if (v->size)
+             if (v->header.size)
                {
                  it->dpvec_char_len = it->len;
                  it->dpvec = v->contents;
                {
                  it->dpvec_char_len = it->len;
                  it->dpvec = v->contents;
-                 it->dpend = v->contents + v->size;
+                 it->dpend = v->contents + v->header.size;
                  it->current.dpvec_index = 0;
                  it->dpvec_face_id = -1;
                  it->saved_face_id = it->face_id;
                  it->current.dpvec_index = 0;
                  it->dpvec_face_id = -1;
                  it->saved_face_id = it->face_id;
@@ -5890,11 +5989,23 @@ get_next_display_element (struct it *it)
       else
        {
          EMACS_INT pos = (it->s ? -1
       else
        {
          EMACS_INT pos = (it->s ? -1
-                          : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
-                          : IT_CHARPOS (*it));
+                    : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
+                    : IT_CHARPOS (*it));
+         int c;
 
 
-         it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display, pos,
-                                      it->string);
+         if (it->what == IT_CHARACTER)
+           c = it->char_to_display;
+         else
+           {
+             struct composition *cmp = composition_table[it->cmp_it.id];
+             int i;
+
+             c = ' ';
+             for (i = 0; i < cmp->glyph_len; i++)
+               if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
+                 break;
+           }
+         it->face_id = FACE_FOR_CHAR (it->f, face, c, pos, it->string);
        }
     }
 
        }
     }
 
@@ -8737,7 +8848,7 @@ display_echo_area (struct window *w)
   window_height_changed_p
     = with_echo_area_buffer (w, display_last_displayed_message_p,
                             display_echo_area_1,
   window_height_changed_p
     = with_echo_area_buffer (w, display_last_displayed_message_p,
                             display_echo_area_1,
-                            (EMACS_INT) w, Qnil, 0, 0);
+                            (intptr_t) w, Qnil, 0, 0);
 
   if (no_message_p)
     echo_area_buffer[i] = Qnil;
 
   if (no_message_p)
     echo_area_buffer[i] = Qnil;
@@ -8756,7 +8867,8 @@ display_echo_area (struct window *w)
 static int
 display_echo_area_1 (EMACS_INT a1, Lisp_Object a2, EMACS_INT a3, EMACS_INT a4)
 {
 static int
 display_echo_area_1 (EMACS_INT a1, Lisp_Object a2, EMACS_INT a3, EMACS_INT a4)
 {
-  struct window *w = (struct window *) a1;
+  intptr_t i1 = a1;
+  struct window *w = (struct window *) i1;
   Lisp_Object window;
   struct text_pos start;
   int window_height_changed_p = 0;
   Lisp_Object window;
   struct text_pos start;
   int window_height_changed_p = 0;
@@ -8798,7 +8910,8 @@ resize_echo_area_exactly (void)
        resize_exactly = Qnil;
 
       resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
        resize_exactly = Qnil;
 
       resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
-                                        (EMACS_INT) w, resize_exactly, 0, 0);
+                                        (intptr_t) w, resize_exactly,
+                                        0, 0);
       if (resized_p)
        {
          ++windows_or_buffers_changed;
       if (resized_p)
        {
          ++windows_or_buffers_changed;
@@ -8818,7 +8931,8 @@ resize_echo_area_exactly (void)
 static int
 resize_mini_window_1 (EMACS_INT a1, Lisp_Object exactly, EMACS_INT a3, EMACS_INT a4)
 {
 static int
 resize_mini_window_1 (EMACS_INT a1, Lisp_Object exactly, EMACS_INT a3, EMACS_INT a4)
 {
-  return resize_mini_window ((struct window *) a1, !NILP (exactly));
+  intptr_t i1 = a1;
+  return resize_mini_window ((struct window *) i1, !NILP (exactly));
 }
 
 
 }
 
 
@@ -8984,7 +9098,7 @@ current_message (void)
   else
     {
       with_echo_area_buffer (0, 0, current_message_1,
   else
     {
       with_echo_area_buffer (0, 0, current_message_1,
-                            (EMACS_INT) &msg, Qnil, 0, 0);
+                            (intptr_t) &msg, Qnil, 0, 0);
       if (NILP (msg))
        echo_area_buffer[0] = Qnil;
     }
       if (NILP (msg))
        echo_area_buffer[0] = Qnil;
     }
@@ -8996,7 +9110,8 @@ current_message (void)
 static int
 current_message_1 (EMACS_INT a1, Lisp_Object a2, EMACS_INT a3, EMACS_INT a4)
 {
 static int
 current_message_1 (EMACS_INT a1, Lisp_Object a2, EMACS_INT a3, EMACS_INT a4)
 {
-  Lisp_Object *msg = (Lisp_Object *) a1;
+  intptr_t i1 = a1;
+  Lisp_Object *msg = (Lisp_Object *) i1;
 
   if (Z > BEG)
     *msg = make_buffer_string (BEG, Z, 1);
 
   if (Z > BEG)
     *msg = make_buffer_string (BEG, Z, 1);
@@ -9127,7 +9242,7 @@ set_message (const char *s, Lisp_Object string,
        || (STRINGP (string) && STRING_MULTIBYTE (string)));
 
   with_echo_area_buffer (0, -1, set_message_1,
        || (STRINGP (string) && STRING_MULTIBYTE (string)));
 
   with_echo_area_buffer (0, -1, set_message_1,
-                        (EMACS_INT) s, string, nbytes, multibyte_p);
+                        (intptr_t) s, string, nbytes, multibyte_p);
   message_buf_print = 0;
   help_echo_showing_p = 0;
 }
   message_buf_print = 0;
   help_echo_showing_p = 0;
 }
@@ -9141,7 +9256,8 @@ set_message (const char *s, Lisp_Object string,
 static int
 set_message_1 (EMACS_INT a1, Lisp_Object a2, EMACS_INT nbytes, EMACS_INT multibyte_p)
 {
 static int
 set_message_1 (EMACS_INT a1, Lisp_Object a2, EMACS_INT nbytes, EMACS_INT multibyte_p)
 {
-  const char *s = (const char *) a1;
+  intptr_t i1 = a1;
+  const char *s = (const char *) i1;
   const unsigned char *msg = (const unsigned char *) s;
   Lisp_Object string = a2;
 
   const unsigned char *msg = (const unsigned char *) s;
   Lisp_Object string = a2;
 
@@ -11044,7 +11160,7 @@ debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
    buffer position, END is given as a distance from Z.  Used in
    redisplay_internal for display optimization.  */
 
    buffer position, END is given as a distance from Z.  Used in
    redisplay_internal for display optimization.  */
 
-static INLINE int
+static inline int
 text_outside_line_unchanged_p (struct window *w,
                               EMACS_INT start, EMACS_INT end)
 {
 text_outside_line_unchanged_p (struct window *w,
                               EMACS_INT start, EMACS_INT end)
 {
@@ -11305,7 +11421,7 @@ check_point_in_composition (struct buffer *prev_buf, EMACS_INT prev_pt,
 /* Reconsider the setting of B->clip_changed which is displayed
    in window W.  */
 
 /* Reconsider the setting of B->clip_changed which is displayed
    in window W.  */
 
-static INLINE void
+static inline void
 reconsider_clip_changes (struct window *w, struct buffer *b)
 {
   if (b->clip_changed
 reconsider_clip_changes (struct window *w, struct buffer *b)
 {
   if (b->clip_changed
@@ -12671,11 +12787,30 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
             GLYPH_BEFORE and GLYPH_AFTER, and it came from a string
             positioned between POS_BEFORE and POS_AFTER in the
             buffer.  */
             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;
+         struct glyph *start, *stop;
          EMACS_INT pos = pos_before;
 
          x = -1;
          EMACS_INT pos = pos_before;
 
          x = -1;
-         for (glyph = glyph_before + incr;
+
+         /* GLYPH_BEFORE and GLYPH_AFTER are the glyphs that
+            correspond to POS_BEFORE and POS_AFTER, respectively.  We
+            need START and STOP in the order that corresponds to the
+            row's direction as given by its reversed_p flag.  If the
+            directionality of characters between POS_BEFORE and
+            POS_AFTER is the opposite of the row's base direction,
+            these characters will have been reordered for display,
+            and we need to reverse START and STOP.  */
+         if (!row->reversed_p)
+           {
+             start = min (glyph_before, glyph_after);
+             stop = max (glyph_before, glyph_after);
+           }
+         else
+           {
+             start = max (glyph_before, glyph_after);
+             stop = min (glyph_before, glyph_after);
+           }
+         for (glyph = start + incr;
               row->reversed_p ? glyph > stop : glyph < stop; )
            {
 
               row->reversed_p ? glyph > stop : glyph < stop; )
            {
 
@@ -12866,7 +13001,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
 
    We assume that the window's buffer is really current.  */
 
 
    We assume that the window's buffer is really current.  */
 
-static INLINE struct text_pos
+static inline struct text_pos
 run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
 {
   struct window *w = XWINDOW (window);
 run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
 {
   struct window *w = XWINDOW (window);
@@ -14812,7 +14947,8 @@ try_window_reusing_current_matrix (struct window *w)
                row->visible_height -= min_y - row->y;
              if (row->y + row->height > max_y)
                row->visible_height -= row->y + row->height - max_y;
                row->visible_height -= min_y - row->y;
              if (row->y + row->height > max_y)
                row->visible_height -= row->y + row->height - max_y;
-             row->redraw_fringe_bitmaps_p = 1;
+             if (row->fringe_bitmap_periodic_p)
+               row->redraw_fringe_bitmaps_p = 1;
 
              it.current_y += row->height;
 
 
              it.current_y += row->height;
 
@@ -14974,7 +15110,8 @@ try_window_reusing_current_matrix (struct window *w)
            row->visible_height -= min_y - row->y;
          if (row->y + row->height > max_y)
            row->visible_height -= row->y + row->height - max_y;
            row->visible_height -= min_y - row->y;
          if (row->y + row->height > max_y)
            row->visible_height -= row->y + row->height - max_y;
-         row->redraw_fringe_bitmaps_p = 1;
+         if (row->fringe_bitmap_periodic_p)
+           row->redraw_fringe_bitmaps_p = 1;
        }
 
       /* Scroll the current matrix.  */
        }
 
       /* Scroll the current matrix.  */
@@ -17092,7 +17229,7 @@ cursor_row_p (struct glyph_row *row)
 static int
 push_display_prop (struct it *it, Lisp_Object prop)
 {
 static int
 push_display_prop (struct it *it, Lisp_Object prop)
 {
-  push_it (it);
+  push_it (it, NULL);
 
   if (STRINGP (prop))
     {
 
   if (STRINGP (prop))
     {
@@ -18021,6 +18158,8 @@ See also `bidi-paragraph-direction'.  */)
        bytepos--;
       itb.charpos = pos;
       itb.bytepos = bytepos;
        bytepos--;
       itb.charpos = pos;
       itb.bytepos = bytepos;
+      itb.nchars = -1;
+      itb.frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ()); /* guesswork */
       itb.first_elt = 1;
       itb.separator_limit = -1;
       itb.paragraph_dir = NEUTRAL_DIR;
       itb.first_elt = 1;
       itb.separator_limit = -1;
       itb.paragraph_dir = NEUTRAL_DIR;
@@ -18124,7 +18263,7 @@ display_menu_bar (struct window *w)
 
   /* Display all items of the menu bar.  */
   items = FRAME_MENU_BAR_ITEMS (it.f);
 
   /* Display all items of the menu bar.  */
   items = FRAME_MENU_BAR_ITEMS (it.f);
-  for (i = 0; i < XVECTOR (items)->size; i += 4)
+  for (i = 0; i < ASIZE (items); i += 4)
     {
       Lisp_Object string;
 
     {
       Lisp_Object string;
 
@@ -19562,7 +19701,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
               so get us a 2-digit number that is close.  */
            if (total == 100)
              total = 99;
               so get us a 2-digit number that is close.  */
            if (total == 100)
              total = 99;
-           sprintf (decode_mode_spec_buf, "%2ld%%", (long)total);
+           sprintf (decode_mode_spec_buf, "%2"pI"d%%", total);
            return decode_mode_spec_buf;
          }
       }
            return decode_mode_spec_buf;
          }
       }
@@ -19593,9 +19732,9 @@ decode_mode_spec (struct window *w, register int c, int field_width,
            if (total == 100)
              total = 99;
            if (toppos <= BUF_BEGV (b))
            if (total == 100)
              total = 99;
            if (toppos <= BUF_BEGV (b))
-             sprintf (decode_mode_spec_buf, "Top%2ld%%", (long)total);
+             sprintf (decode_mode_spec_buf, "Top%2"pI"d%%", total);
            else
            else
-             sprintf (decode_mode_spec_buf, "%2ld%%", (long)total);
+             sprintf (decode_mode_spec_buf, "%2"pI"d%%", total);
            return decode_mode_spec_buf;
          }
       }
            return decode_mode_spec_buf;
          }
       }
@@ -20398,7 +20537,7 @@ init_glyph_string (struct glyph_string *s,
 /* Append the list of glyph strings with head H and tail T to the list
    with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the result.  */
 
 /* Append the list of glyph strings with head H and tail T to the list
    with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the result.  */
 
-static INLINE void
+static inline void
 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
                           struct glyph_string *h, struct glyph_string *t)
 {
 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
                           struct glyph_string *h, struct glyph_string *t)
 {
@@ -20418,7 +20557,7 @@ append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tai
    list with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the
    result.  */
 
    list with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the
    result.  */
 
-static INLINE void
+static inline void
 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
                            struct glyph_string *h, struct glyph_string *t)
 {
 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
                            struct glyph_string *h, struct glyph_string *t)
 {
@@ -20437,7 +20576,7 @@ prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **ta
 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
    Set *HEAD and *TAIL to the resulting list.  */
 
 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
    Set *HEAD and *TAIL to the resulting list.  */
 
-static INLINE void
+static inline void
 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
                     struct glyph_string *s)
 {
 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
                     struct glyph_string *s)
 {
@@ -20452,7 +20591,7 @@ append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
    Value is a pointer to a realized face that is ready for display if
    DISPLAY_P is non-zero.  */
 
    Value is a pointer to a realized face that is ready for display if
    DISPLAY_P is non-zero.  */
 
-static INLINE struct face *
+static inline struct face *
 get_char_face_and_encoding (struct frame *f, int c, int face_id,
                            XChar2b *char2b, int display_p)
 {
 get_char_face_and_encoding (struct frame *f, int c, int face_id,
                            XChar2b *char2b, int display_p)
 {
@@ -20485,7 +20624,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id,
    The encoding of GLYPH->u.ch is returned in *CHAR2B.  Value is
    a pointer to a realized face that is ready for display.  */
 
    The encoding of GLYPH->u.ch is returned in *CHAR2B.  Value is
    a pointer to a realized face that is ready for display.  */
 
-static INLINE struct face *
+static inline struct face *
 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
                             XChar2b *char2b, int *two_byte_p)
 {
 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
                             XChar2b *char2b, int *two_byte_p)
 {
@@ -20522,7 +20661,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
 /* Get glyph code of character C in FONT in the two-byte form CHAR2B.
    Retunr 1 if FONT has a glyph for C, otherwise return 0.  */
 
 /* Get glyph code of character C in FONT in the two-byte form CHAR2B.
    Retunr 1 if FONT has a glyph for C, otherwise return 0.  */
 
-static INLINE int
+static inline int
 get_char_glyph_code (int c, struct font *font, XChar2b *char2b)
 {
   unsigned code;
 get_char_glyph_code (int c, struct font *font, XChar2b *char2b)
 {
   unsigned code;
@@ -20986,7 +21125,7 @@ right_overwriting (struct glyph_string *s)
    first glyph following S.  LAST_X is the right-most x-position + 1
    in the drawing area.  */
 
    first glyph following S.  LAST_X is the right-most x-position + 1
    in the drawing area.  */
 
-static INLINE void
+static inline void
 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
 {
   /* If the face of this glyph string has to be drawn to the end of
 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
 {
   /* If the face of this glyph string has to be drawn to the end of
@@ -21548,7 +21687,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
 /* Store one glyph for IT->char_to_display in IT->glyph_row.
    Called from x_produce_glyphs when IT->glyph_row is non-null.  */
 
 /* Store one glyph for IT->char_to_display in IT->glyph_row.
    Called from x_produce_glyphs when IT->glyph_row is non-null.  */
 
-static INLINE void
+static inline void
 append_glyph (struct it *it)
 {
   struct glyph *glyph;
 append_glyph (struct it *it)
 {
   struct glyph *glyph;
@@ -21622,7 +21761,7 @@ append_glyph (struct it *it)
    IT->glyph_row.  Called from x_produce_glyphs when IT->glyph_row is
    non-null.  */
 
    IT->glyph_row.  Called from x_produce_glyphs when IT->glyph_row is
    non-null.  */
 
-static INLINE void
+static inline void
 append_composite_glyph (struct it *it)
 {
   struct glyph *glyph;
 append_composite_glyph (struct it *it)
 {
   struct glyph *glyph;
@@ -21691,7 +21830,7 @@ append_composite_glyph (struct it *it)
 /* Change IT->ascent and IT->height according to the setting of
    IT->voffset.  */
 
 /* Change IT->ascent and IT->height according to the setting of
    IT->voffset.  */
 
-static INLINE void
+static inline void
 take_vertical_position_into_account (struct it *it)
 {
   if (it->voffset)
 take_vertical_position_into_account (struct it *it)
 {
   if (it->voffset)
@@ -24816,7 +24955,7 @@ on_hot_spot_p (Lisp_Object hot_spot, int x, int y)
        {
          struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
          Lisp_Object *poly = v->contents;
        {
          struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
          Lisp_Object *poly = v->contents;
-         int n = v->size;
+         int n = v->header.size;
          int i;
          int inside = 0;
          Lisp_Object lx, ly;
          int i;
          int inside = 0;
          Lisp_Object lx, ly;
@@ -26249,7 +26388,7 @@ x_intersect_rectangles (XRectangle *r1, XRectangle *r2, XRectangle *result)
     {
       result->x = right->x;
 
     {
       result->x = right->x;
 
-      /* The right end of the intersection is the minimum of the
+      /* The right end of the intersection is the minimum of
         the right ends of left and right.  */
       result->width = (min (left->x + left->width, right->x + right->width)
                       - result->x);
         the right ends of left and right.  */
       result->width = (min (left->x + left->width, right->x + right->width)
                       - result->x);