]> 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 bbbf37b68acef363d6c3d310171b258c3a3dfbe0..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
-   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.
@@ -318,29 +318,31 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
 Lisp_Object Qwindow_scroll_functions;
-Lisp_Object Qwindow_text_change_functions;
-Lisp_Object Qredisplay_end_trigger_functions;
+static Lisp_Object Qwindow_text_change_functions;
+static Lisp_Object Qredisplay_end_trigger_functions;
 Lisp_Object Qinhibit_point_motion_hooks;
-Lisp_Object QCeval, QCfile, QCdata, QCpropertize;
-Lisp_Object Qfontified;
-Lisp_Object Qgrow_only;
-Lisp_Object Qinhibit_eval_during_redisplay;
-Lisp_Object Qbuffer_position, Qposition, Qobject;
-Lisp_Object Qright_to_left, Qleft_to_right;
+static Lisp_Object QCeval, QCpropertize;
+Lisp_Object QCfile, QCdata;
+static Lisp_Object Qfontified;
+static Lisp_Object Qgrow_only;
+static Lisp_Object Qinhibit_eval_during_redisplay;
+static Lisp_Object Qbuffer_position, Qposition, Qobject;
+static Lisp_Object Qright_to_left, Qleft_to_right;
 
 /* Cursor shapes */
 Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
 
 /* Pointer shapes */
-Lisp_Object Qarrow, Qhand, Qtext;
+static Lisp_Object Qarrow, Qhand;
+Lisp_Object Qtext;
 
 /* Holds the list (error).  */
-Lisp_Object list_of_error;
+static Lisp_Object list_of_error;
 
-Lisp_Object Qfontification_functions;
+static Lisp_Object Qfontification_functions;
 
-Lisp_Object Qwrap_prefix;
-Lisp_Object Qline_prefix;
+static Lisp_Object Qwrap_prefix;
+static Lisp_Object Qline_prefix;
 
 /* Non-nil means don't actually do any redisplay.  */
 
@@ -350,12 +352,14 @@ Lisp_Object Qinhibit_redisplay;
 
 Lisp_Object Qdisplay;
 
-Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
-Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
-Lisp_Object Qslice;
+Lisp_Object Qspace, QCalign_to;
+static Lisp_Object QCrelative_width, QCrelative_height;
+Lisp_Object Qleft_margin, Qright_margin;
+static Lisp_Object Qspace_width, Qraise;
+static Lisp_Object Qslice;
 Lisp_Object Qcenter;
-Lisp_Object Qmargin, Qpointer;
-Lisp_Object Qline_height;
+static Lisp_Object Qmargin, Qpointer;
+static Lisp_Object Qline_height;
 
 #ifdef HAVE_WINDOW_SYSTEM
 
@@ -383,15 +387,15 @@ Lisp_Object Qline_height;
 
 /* Name of the face used to highlight trailing whitespace.  */
 
-Lisp_Object Qtrailing_whitespace;
+static Lisp_Object Qtrailing_whitespace;
 
 /* Name and number of the face used to highlight escape glyphs.  */
 
-Lisp_Object Qescape_glyph;
+static Lisp_Object Qescape_glyph;
 
 /* Name and number of the face used to highlight non-breaking spaces.  */
 
-Lisp_Object Qnobreak_space;
+static Lisp_Object Qnobreak_space;
 
 /* The symbol `image' which is the car of the lists used to represent
    images in Lisp.  Also a tool bar style.  */
@@ -399,8 +403,9 @@ Lisp_Object Qnobreak_space;
 Lisp_Object Qimage;
 
 /* The image map types.  */
-Lisp_Object QCmap, QCpointer;
-Lisp_Object Qrect, Qcircle, Qpoly;
+Lisp_Object QCmap;
+static Lisp_Object QCpointer;
+static Lisp_Object Qrect, Qcircle, Qpoly;
 
 /* Tool bar styles */
 Lisp_Object Qboth, Qboth_horiz, Qtext_image_horiz;
@@ -460,12 +465,12 @@ static struct buffer *this_line_buffer;
    Voverlay_arrow_position is a marker, last-arrow-position is its
    numerical position.  */
 
-Lisp_Object Qlast_arrow_position, Qlast_arrow_string;
+static Lisp_Object Qlast_arrow_position, Qlast_arrow_string;
 
 /* Alternative overlay-arrow-string and overlay-arrow-bitmap
    properties on a symbol in overlay-arrow-variable-list.  */
 
-Lisp_Object Qoverlay_arrow_string, Qoverlay_arrow_bitmap;
+static Lisp_Object Qoverlay_arrow_string, Qoverlay_arrow_bitmap;
 
 Lisp_Object Qmenu_bar_update_hook;
 
@@ -494,12 +499,12 @@ Lisp_Object echo_area_window;
    message_enable_multibyte on the stack, the function restore_message
    pops the stack and displays MESSAGE again.  */
 
-Lisp_Object Vmessage_stack;
+static Lisp_Object Vmessage_stack;
 
 /* Nonzero means multibyte characters were enabled when the echo area
    message was specified.  */
 
-int message_enable_multibyte;
+static int message_enable_multibyte;
 
 /* Nonzero if we should redraw the mode lines on the next redisplay.  */
 
@@ -517,7 +522,7 @@ int cursor_type_changed;
 /* Nonzero after display_mode_line if %l was used and it displayed a
    line number.  */
 
-int line_number_displayed;
+static int line_number_displayed;
 
 /* The name of the *Messages* buffer, a string.  */
 
@@ -544,12 +549,12 @@ static int display_last_displayed_message_p;
 /* Nonzero if echo area is being used by print; zero if being used by
    message.  */
 
-int message_buf_print;
+static int message_buf_print;
 
 /* The symbol `inhibit-menubar-update' and its DEFVAR_BOOL variable.  */
 
-Lisp_Object Qinhibit_menubar_update;
-Lisp_Object Qmessage_truncate_lines;
+static Lisp_Object Qinhibit_menubar_update;
+static Lisp_Object Qmessage_truncate_lines;
 
 /* Set to 1 in clear_message to make redisplay_internal aware
    of an emptied echo area.  */
@@ -560,7 +565,7 @@ static int message_cleared_p;
    glyphs.  Also used in direct_output_for_insert.  */
 
 #define MAX_SCRATCH_GLYPHS 100
-struct glyph_row scratch_glyph_row;
+static struct glyph_row scratch_glyph_row;
 static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
 
 /* Ascent and height of the last line processed by move_it_to.  */
@@ -603,11 +608,11 @@ int trace_move;
 #define TRACE_MOVE(x)  (void) 0
 #endif
 
-Lisp_Object Qauto_hscroll_mode;
+static Lisp_Object Qauto_hscroll_mode;
 
 /* Buffer being redisplayed -- for redisplay_window_error.  */
 
-struct buffer *displayed_buffer;
+static struct buffer *displayed_buffer;
 
 /* Value returned from text property handlers (see below).  */
 
@@ -708,7 +713,7 @@ static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
 
 int redisplaying_p;
 
-Lisp_Object Qinhibit_free_realized_faces;
+static Lisp_Object Qinhibit_free_realized_faces;
 
 /* If a string, XTread_socket generates an event to display that string.
    (The display is done in read_char.)  */
@@ -735,7 +740,7 @@ struct atimer *hourglass_atimer;
 Lisp_Object Qglyphless_char;
 
 /* Symbol for the purpose of Vglyphless_char_display.  */
-Lisp_Object Qglyphless_char_display;
+static Lisp_Object Qglyphless_char_display;
 
 /* Method symbols for Vglyphless_char_display.  */
 static Lisp_Object Qhex_code, Qempty_box, Qthin_space, Qzero_width;
@@ -751,6 +756,7 @@ static Lisp_Object Qhex_code, Qempty_box, Qthin_space, Qzero_width;
 /* Function prototypes.  */
 
 static void setup_for_ellipsis (struct it *, int);
+static void set_iterator_to_next (struct it *, int);
 static void mark_window_display_accurate_1 (struct window *, int);
 static int single_display_spec_string_p (Lisp_Object, Lisp_Object);
 static int display_prop_string_p (Lisp_Object, Lisp_Object);
@@ -763,7 +769,7 @@ static Lisp_Object get_it_property (struct it *it, Lisp_Object prop);
 static void handle_line_prefix (struct it *);
 
 static void pint2str (char *, int, EMACS_INT);
-static void pint2hrstr (char *, int, int);
+static void pint2hrstr (char *, int, EMACS_INT);
 static struct text_pos run_window_scroll_functions (Lisp_Object,
                                                     struct text_pos);
 static void reconsider_clip_changes (struct window *, struct buffer *);
@@ -773,7 +779,7 @@ 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 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 Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
@@ -782,7 +788,9 @@ static int with_echo_area_buffer (struct window *, int,
                                   EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT);
 static void clear_garbaged_frames (void);
 static int current_message_1 (EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT);
+static void pop_message (void);
 static int truncate_message_1 (EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT);
+static void set_message (const char *, Lisp_Object, EMACS_INT, int);
 static int set_message_1 (EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT);
 static int display_echo_area (struct window *);
 static int display_echo_area_1 (EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT);
@@ -802,19 +810,21 @@ static int cursor_row_fully_visible_p (struct window *, int, int);
 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,
-                                                     EMACS_INT, EMACS_INT);
-static void push_it (struct it *);
+static unsigned long int message_log_check_duplicate (EMACS_INT, EMACS_INT);
+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 redisplay_internal (int);
+static void redisplay_internal (void);
 static int echo_area_display (int);
 static void redisplay_windows (Lisp_Object);
 static void redisplay_window (Lisp_Object, int);
 static Lisp_Object redisplay_window_error (Lisp_Object);
 static Lisp_Object redisplay_window_0 (Lisp_Object);
 static Lisp_Object redisplay_window_1 (Lisp_Object);
+static int set_cursor_from_row (struct window *, struct glyph_row *,
+                               struct glyph_matrix *, EMACS_INT, EMACS_INT,
+                               int, int);
 static int update_menu_bar (struct frame *, int, int);
 static int try_window_reusing_current_matrix (struct window *);
 static int try_window_id (struct window *);
@@ -825,8 +835,8 @@ static int display_mode_element (struct it *, int, int, int, Lisp_Object, Lisp_O
 static int store_mode_line_string (const char *, Lisp_Object, int, int, int, Lisp_Object);
 static const char *decode_mode_spec (struct window *, int, int, Lisp_Object *);
 static void display_menu_bar (struct window *);
-static int display_count_lines (EMACS_INT, EMACS_INT, EMACS_INT, int,
-                               EMACS_INT *);
+static EMACS_INT display_count_lines (EMACS_INT, EMACS_INT, EMACS_INT,
+                                     EMACS_INT *);
 static int display_string (const char *, Lisp_Object, Lisp_Object,
                            EMACS_INT, EMACS_INT, struct it *, int, int, int, int);
 static void compute_line_metrics (struct it *);
@@ -852,6 +862,7 @@ static int init_from_display_pos (struct it *, struct window *,
                                   struct display_pos *);
 static void reseat_to_string (struct it *, const char *,
                               Lisp_Object, EMACS_INT, EMACS_INT, int, int);
+static int get_next_display_element (struct it *);
 static enum move_it_result
        move_it_in_display_line_to (struct it *, EMACS_INT, int,
                                   enum move_operation_enum);
@@ -872,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);
+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,
-                                       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 *);
@@ -899,6 +912,7 @@ static void append_stretch_glyph (struct it *, Lisp_Object,
 
 #endif /* HAVE_WINDOW_SYSTEM */
 
+static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
 static int coords_in_mouse_face_p (struct window *, int, int);
 
 
@@ -913,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.  */
 
-INLINE int
+inline int
 window_text_bottom_y (struct window *w)
 {
   int height = WINDOW_TOTAL_HEIGHT (w);
@@ -927,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.  */
 
-INLINE int
+inline int
 window_box_width (struct window *w, int area)
 {
   int cols = XFASTINT (w->total_cols);
@@ -966,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.  */
 
-INLINE int
+inline int
 window_box_height (struct window *w)
 {
   struct frame *f = XFRAME (w->frame);
@@ -1013,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.  */
 
-INLINE int
+inline int
 window_box_left_offset (struct window *w, int area)
 {
   int x;
@@ -1045,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.  */
 
-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);
@@ -1055,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.  */
 
-INLINE int
+inline int
 window_box_left (struct window *w, int area)
 {
   struct frame *f = XFRAME (w->frame);
@@ -1075,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.  */
 
-INLINE int
+inline int
 window_box_right (struct window *w, int area)
 {
   return window_box_left (w, area) + window_box_width (w, area);
@@ -1088,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.  */
 
-INLINE void
+inline void
 window_box (struct window *w, int area, int *box_x, int *box_y,
            int *box_width, int *box_height)
 {
@@ -1115,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.  */
 
-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)
 {
@@ -1146,7 +1160,7 @@ line_bottom_y (struct it *it)
        line_height = last_height;
       else if (IT_CHARPOS (*it) < ZV)
        {
-         move_it_by_lines (it, 1, 1);
+         move_it_by_lines (it, 1);
          line_height = (it->max_ascent || it->max_descent
                         ? it->max_ascent + it->max_descent
                         : last_height);
@@ -1270,7 +1284,7 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y,
 
       it2 = it;
       if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
-       move_it_by_lines (&it, 1, 0);
+       move_it_by_lines (&it, 1);
       if (charpos < IT_CHARPOS (it)
          || (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
        {
@@ -1315,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.  */
 
-static INLINE int
+static inline int
 string_char_and_length (const unsigned char *str, int *len)
 {
   int c;
@@ -1363,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.  */
 
-static INLINE struct text_pos
+static inline struct text_pos
 string_pos (EMACS_INT charpos, Lisp_Object string)
 {
   struct text_pos pos;
@@ -1533,61 +1547,6 @@ pixel_to_glyph_coords (FRAME_PTR f, register int pix_x, register int pix_y,
 }
 
 
-/* Given HPOS/VPOS in the current matrix of W, return corresponding
-   frame-relative pixel positions in *FRAME_X and *FRAME_Y.  If we
-   can't tell the positions because W's display is not up to date,
-   return 0.  */
-
-int
-glyph_to_pixel_coords (struct window *w, int hpos, int vpos,
-                      int *frame_x, int *frame_y)
-{
-#ifdef HAVE_WINDOW_SYSTEM
-  if (FRAME_WINDOW_P (XFRAME (WINDOW_FRAME (w))))
-    {
-      int success_p;
-
-      xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
-      xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
-
-      if (display_completed)
-       {
-         struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
-         struct glyph *glyph = row->glyphs[TEXT_AREA];
-         struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
-
-         hpos = row->x;
-         vpos = row->y;
-         while (glyph < end)
-           {
-             hpos += glyph->pixel_width;
-             ++glyph;
-           }
-
-         /* If first glyph is partially visible, its first visible position is still 0.  */
-         if (hpos < 0)
-           hpos = 0;
-
-         success_p = 1;
-       }
-      else
-       {
-         hpos = vpos = 0;
-         success_p = 0;
-       }
-
-      *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, hpos);
-      *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, vpos);
-      return success_p;
-    }
-#endif
-
-  *frame_x = hpos;
-  *frame_y = vpos;
-  return 1;
-}
-
-
 /* Find the glyph under window-relative coordinates X/Y in window W.
    Consider only glyphs from buffer text, i.e. no glyphs from overlay
    strings.  Return in *HPOS and *VPOS the row and column number of
@@ -1670,11 +1629,10 @@ x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos,
   return glyph;
 }
 
-/* EXPORT:
-   Convert frame-relative x/y to coordinates relative to window W.
+/* Convert frame-relative x/y to coordinates relative to window W.
    Takes pseudo-windows into account.  */
 
-void
+static void
 frame_to_window_pixel_xy (struct window *w, int *x, int *y)
 {
   if (w->pseudo_window_p)
@@ -2607,7 +2565,7 @@ init_iterator (struct it *it, struct window *w,
        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,
@@ -3128,6 +3086,82 @@ next_overlay_change (EMACS_INT pos)
   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
 /***********************************************************************
@@ -3660,7 +3694,7 @@ handle_invisible_prop (struct it *it)
                 _after_ bidi iteration avoids affecting the visual
                 order of the displayed text when invisible properties
                 are added or removed.  */
-             if (it->bidi_it.first_elt)
+             if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
                {
                  /* If we were `reseat'ed to a new paragraph,
                     determine the paragraph base direction.  We need
@@ -3748,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;
-      it->dpend = v->contents + v->size;
+      it->dpend = v->contents + v->header.size;
     }
   else
     {
@@ -3786,8 +3820,9 @@ setup_for_ellipsis (struct it *it, int len)
 static enum prop_handled
 handle_display_prop (struct it *it)
 {
-  Lisp_Object prop, object, overlay;
+  Lisp_Object propval, object, overlay;
   struct text_pos *position;
+  EMACS_INT bufpos;
   /* Nonzero if some property replaces the display of the text itself.  */
   int display_replaced_p = 0;
 
@@ -3795,11 +3830,13 @@ handle_display_prop (struct it *it)
     {
       object = it->string;
       position = &it->current.string_pos;
+      bufpos = CHARPOS (it->current.pos);
     }
   else
     {
       XSETWINDOW (object, it->w);
       position = &it->current.pos;
+      bufpos = CHARPOS (*position);
     }
 
   /* Reset those iterator values set from display property values.  */
@@ -3814,9 +3851,9 @@ handle_display_prop (struct it *it)
   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.  */
@@ -3824,59 +3861,88 @@ handle_display_prop (struct it *it)
   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.  */
-      && !(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 (STRINGP (object))
+             if (!it || STRINGP (object))
                break;
            }
        }
     }
-  else if (VECTORP (prop))
+  else if (VECTORP (spec))
     {
       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 (STRINGP (object))
+           if (!it || STRINGP (object))
              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.  */
 
@@ -3898,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 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.
 
-   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.
 
+   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,
-                           int display_replaced_before_p)
+                           EMACS_INT bufpos, int display_replaced_p,
+                           int frame_window_p)
 {
   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.
@@ -3946,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.  */
+
+      if (NILP (object))
+       XSETBUFFER (object, current_buffer);
       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;
@@ -3965,63 +4039,66 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
       && 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;
@@ -4032,12 +4109,15 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
       && 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;
     }
@@ -4048,20 +4128,23 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
     {
       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))
                {
-                 it->slice.width = XCAR (tem);
+                 it->slice.y = XCAR (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);
+                   }
                }
            }
        }
@@ -4074,36 +4157,43 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
       && 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
-      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 */
+       }
 
       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.  */
-  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.  */
-  it->stop_charpos = position->charpos;
+  if (it)
+    it->stop_charpos = position->charpos;
 
   /* Handle `(left-fringe BITMAP [FACE])'
      and `(right-fringe BITMAP [FACE])'.  */
@@ -4112,12 +4202,16 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
          || EQ (XCAR (spec), Qright_fringe))
       && CONSP (XCDR (spec)))
     {
-      int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);
       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
@@ -4128,46 +4222,47 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
           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;
@@ -4210,18 +4305,19 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
 
   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)));
 
-  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_pos = it->position;
-      it->position = *position;
-      push_it (it);
-      it->position = save_pos;
+      push_it (it, position);
       it->from_overlay = overlay;
 
       if (NILP (location))
@@ -4278,83 +4374,31 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
   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
-   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
-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)
@@ -4368,6 +4412,16 @@ single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
       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);
     }
 
@@ -4384,7 +4438,7 @@ single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
          return 0;
       }
 
-  return CONSP (prop) && EQ (XCAR (prop), string);
+  return EQ (prop, string) || (CONSP (prop) && EQ (XCAR (prop), string));
 }
 
 
@@ -4394,8 +4448,8 @@ static int
 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))
@@ -4895,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))
-       push_it (it);
+       push_it (it, NULL);
 
       /* Set up IT to deliver display elements from the first overlay
         string.  */
@@ -4937,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
-   processed.  */
+   processed.  If POSITION is non-NULL, it is the position to save on
+   the stack instead of IT->position.  */
 
 static void
-push_it (struct it *it)
+push_it (struct it *it, struct text_pos *position)
 {
   struct iterator_stack_entry *p;
 
@@ -4967,7 +5022,7 @@ push_it (struct it *it)
       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;
@@ -5425,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.disp_pos = -1;
     }
 
   if (set_stop_p)
@@ -5583,9 +5639,19 @@ lookup_glyphless_char_display (int c, struct it *it)
 
   if (CHAR_TABLE_P (Vglyphless_char_display)
       && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1)
-    glyphless_method = (c >= 0
-                       ? CHAR_TABLE_REF (Vglyphless_char_display, c)
-                       : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
+    {
+      if (c >= 0)
+       {
+         glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c);
+         if (CONSP (glyphless_method))
+           glyphless_method = FRAME_WINDOW_P (it->f)
+             ? XCAR (glyphless_method)
+             : XCDR (glyphless_method);
+       }
+      else
+       glyphless_method = XCHAR_TABLE (Vglyphless_char_display)->extras[0];
+    }
+
  retry:
   if (NILP (glyphless_method))
     {
@@ -5632,7 +5698,7 @@ struct frame *last_glyphless_glyph_frame = NULL;
 unsigned last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
 int last_glyphless_glyph_merged_face_id = 0;
 
-int
+static int
 get_next_display_element (struct it *it)
 {
   /* Non-zero means that we found a display element.  Zero means that
@@ -5692,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.  */
-             if (v->size)
+             if (v->header.size)
                {
                  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;
@@ -5904,7 +5970,6 @@ get_next_display_element (struct it *it)
        }
     }
 
-#ifdef HAVE_WINDOW_SYSTEM
   /* Adjust face id for a multibyte character.  There are no multibyte
      character in unibyte text.  */
   if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION)
@@ -5924,14 +5989,25 @@ get_next_display_element (struct it *it)
       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;
+
+         if (it->what == IT_CHARACTER)
+           c = it->char_to_display;
+         else
+           {
+             struct composition *cmp = composition_table[it->cmp_it.id];
+             int i;
 
-         it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display, pos,
-                                      it->string);
+             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);
        }
     }
-#endif
 
  done:
   /* Is this character the last one of a run of characters with
@@ -7638,7 +7714,7 @@ move_it_vertically_backward (struct it *it, int dy)
       /* DY == 0 means move to the start of the screen line.  The
         value of nlines is > 0 if continuation lines were involved.  */
       if (nlines > 0)
-       move_it_by_lines (it, nlines, 1);
+       move_it_by_lines (it, nlines);
     }
   else
     {
@@ -7682,7 +7758,7 @@ move_it_vertically_backward (struct it *it, int dy)
            {
              do
                {
-                 move_it_by_lines (it, 1, 1);
+                 move_it_by_lines (it, 1);
                }
              while (target_y >= line_bottom_y (it) && IT_CHARPOS (*it) < ZV);
            }
@@ -7712,7 +7788,7 @@ move_it_vertically (struct it *it, int dy)
       if (IT_CHARPOS (*it) == ZV
          && ZV > BEGV
          && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
-       move_it_by_lines (it, 0, 0);
+       move_it_by_lines (it, 0);
     }
 }
 
@@ -7732,15 +7808,14 @@ move_it_past_eol (struct it *it)
 
 /* Move IT by a specified number DVPOS of screen lines down.  DVPOS
    negative means move up.  DVPOS == 0 means move to the start of the
-   screen line.  NEED_Y_P non-zero means calculate IT->current_y.  If
-   NEED_Y_P is zero, IT->current_y will be left unchanged.
+   screen line.
 
-   Further optimization ideas: If we would know that IT->f doesn't use
+   Optimization idea: If we would know that IT->f doesn't use
    a face with proportional font, we could be faster for
    truncate-lines nil.  */
 
 void
-move_it_by_lines (struct it *it, int dvpos, int need_y_p)
+move_it_by_lines (struct it *it, int dvpos)
 {
 
   /* The commented-out optimization uses vmotion on terminals.  This
@@ -8003,8 +8078,8 @@ message_dolog (const char *m, EMACS_INT nbytes, int nlflag, int multibyte)
              prev_bol = PT;
              prev_bol_byte = PT_BYTE;
 
-             dups = message_log_check_duplicate (prev_bol, prev_bol_byte,
-                                                 this_bol, this_bol_byte);
+             dups = message_log_check_duplicate (prev_bol_byte,
+                                                  this_bol_byte);
              if (dups)
                {
                  del_range_both (prev_bol, prev_bol_byte,
@@ -8079,8 +8154,7 @@ message_dolog (const char *m, EMACS_INT nbytes, int nlflag, int multibyte)
    value N > 1 if we should also append " [N times]".  */
 
 static unsigned long int
-message_log_check_duplicate (EMACS_INT prev_bol, EMACS_INT prev_bol_byte,
-                            EMACS_INT this_bol, EMACS_INT this_bol_byte)
+message_log_check_duplicate (EMACS_INT prev_bol_byte, EMACS_INT this_bol_byte)
 {
   EMACS_INT i;
   EMACS_INT len = Z_BYTE - 1 - this_bol_byte;
@@ -8410,7 +8484,7 @@ vmessage (const char *m, va_list ap)
        {
          if (m)
            {
-             EMACS_INT len;
+             size_t len;
 
              len = doprnt (FRAME_MESSAGE_BUF (f),
                            FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, ap);
@@ -8437,6 +8511,7 @@ message (const char *m, ...)
 }
 
 
+#if 0
 /* The non-logging version of message.  */
 
 void
@@ -8451,6 +8526,7 @@ message_nolog (const char *m, ...)
   Vmessage_log_max = old_log_max;
   va_end (ap);
 }
+#endif
 
 
 /* Display the current message in the current mini-buffer.  This is
@@ -8772,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,
-                            (EMACS_INT) w, Qnil, 0, 0);
+                            (intptr_t) w, Qnil, 0, 0);
 
   if (no_message_p)
     echo_area_buffer[i] = Qnil;
@@ -8791,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)
 {
-  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;
@@ -8833,12 +8910,13 @@ resize_echo_area_exactly (void)
        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;
          ++update_mode_lines;
-         redisplay_internal (0);
+         redisplay_internal ();
        }
     }
 }
@@ -8853,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)
 {
-  return resize_mini_window ((struct window *) a1, !NILP (exactly));
+  intptr_t i1 = a1;
+  return resize_mini_window ((struct window *) i1, !NILP (exactly));
 }
 
 
@@ -9019,7 +9098,7 @@ current_message (void)
   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;
     }
@@ -9031,7 +9110,8 @@ current_message (void)
 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);
@@ -9083,7 +9163,7 @@ pop_message_unwind (Lisp_Object dummy)
 
 /* Pop the top-most entry off Vmessage_stack.  */
 
-void
+static void
 pop_message (void)
 {
   xassert (CONSP (Vmessage_stack));
@@ -9153,7 +9233,7 @@ truncate_message_1 (EMACS_INT nchars, Lisp_Object a2, EMACS_INT a3, EMACS_INT a4
    to t before calling set_message_1 (which calls insert).
   */
 
-void
+static void
 set_message (const char *s, Lisp_Object string,
             EMACS_INT nbytes, int multibyte_p)
 {
@@ -9162,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,
-                        (EMACS_INT) s, string, nbytes, multibyte_p);
+                        (intptr_t) s, string, nbytes, multibyte_p);
   message_buf_print = 0;
   help_echo_showing_p = 0;
 }
@@ -9176,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)
 {
-  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;
 
@@ -9379,7 +9460,7 @@ echo_area_display (int update_frame_p)
              int count = SPECPDL_INDEX ();
              specbind (Qredisplay_dont_pause, Qt);
              windows_or_buffers_changed = 1;
-             redisplay_internal (0);
+             redisplay_internal ();
              unbind_to (count, Qnil);
            }
          else if (FRAME_WINDOW_P (f) && n == 0)
@@ -11079,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.  */
 
-static INLINE int
+static inline int
 text_outside_line_unchanged_p (struct window *w,
                               EMACS_INT start, EMACS_INT end)
 {
@@ -11150,7 +11231,7 @@ text_outside_line_unchanged_p (struct window *w,
 void
 redisplay (void)
 {
-  redisplay_internal (0);
+  redisplay_internal ();
 }
 
 
@@ -11303,7 +11384,7 @@ overlay_arrow_at_row (struct it *it, struct glyph_row *row)
    return 0.  PREV_BUF and PREV_PT are the last point buffer and
    position.  BUF and PT are the current point buffer and position.  */
 
-int
+static int
 check_point_in_composition (struct buffer *prev_buf, EMACS_INT prev_pt,
                            struct buffer *buf, EMACS_INT pt)
 {
@@ -11340,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.  */
 
-static INLINE void
+static inline void
 reconsider_clip_changes (struct window *w, struct buffer *b)
 {
   if (b->clip_changed
@@ -11414,14 +11495,11 @@ do { if (polling_stopped_here) start_polling ();      \
        polling_stopped_here = 0; } while (0)
 
 
-/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in
-   response to any user action; therefore, we should preserve the echo
-   area.  (Actually, our caller does that job.)  Perhaps in the future
-   avoid recentering windows if it is not necessary; currently that
-   causes some problems.  */
+/* Perhaps in the future avoid recentering windows if it
+   is not necessary; currently that causes some problems.  */
 
 static void
-redisplay_internal (int preserve_echo_area)
+redisplay_internal (void)
 {
   struct window *w = XWINDOW (selected_window);
   struct window *sw;
@@ -12181,11 +12259,11 @@ redisplay_preserve_echo_area (int from_where)
       /* We have a previously displayed message, but no current
         message.  Redisplay the previous message.  */
       display_last_displayed_message_p = 1;
-      redisplay_internal (1);
+      redisplay_internal ();
       display_last_displayed_message_p = 0;
     }
   else
-    redisplay_internal (1);
+    redisplay_internal ();
 
   if (FRAME_RIF (SELECTED_FRAME ()) != NULL
       && FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
@@ -12393,7 +12471,7 @@ redisplay_window_1 (Lisp_Object window)
 
    Return 0 if cursor is not on this row, 1 otherwise.  */
 
-int
+static int
 set_cursor_from_row (struct window *w, struct glyph_row *row,
                     struct glyph_matrix *matrix,
                     EMACS_INT delta, EMACS_INT delta_bytes,
@@ -12709,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.  */
-         struct glyph *stop = glyph_after;
+         struct glyph *start, *stop;
          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; )
            {
 
@@ -12904,7 +13001,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
 
    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);
@@ -12998,6 +13095,12 @@ enum
   SCROLLING_NEED_LARGER_MATRICES
 };
 
+/* If scroll-conservatively is more than this, never recenter.
+
+   If you change this, don't forget to update the doc string of
+   `scroll-conservatively' and the Emacs manual.  */
+#define SCROLL_LIMIT 100
+
 static int
 try_scrolling (Lisp_Object window, int just_this_one_p,
               EMACS_INT arg_scroll_conservatively, EMACS_INT scroll_step,
@@ -13011,7 +13114,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
   int dy = 0, amount_to_scroll = 0, scroll_down_p = 0;
   int extra_scroll_margin_lines = last_line_misfit ? 1 : 0;
   Lisp_Object aggressive;
-  int scroll_limit = INT_MAX / FRAME_LINE_HEIGHT (f);
+  /* We will never try scrolling more than this number of lines.  */
+  int scroll_limit = SCROLL_LIMIT;
 
 #if GLYPH_DEBUG
   debug_method_add (w, "try_scrolling");
@@ -13027,14 +13131,14 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
   else
     this_scroll_margin = 0;
 
-  /* Force arg_scroll_conservatively to have a reasonable value, to avoid
-     overflow while computing how much to scroll.  Note that the user
-     can supply scroll-conservatively equal to `most-positive-fixnum',
-     which can be larger than INT_MAX.  */
+  /* Force arg_scroll_conservatively to have a reasonable value, to
+     avoid scrolling too far away with slow move_it_* functions.  Note
+     that the user can supply scroll-conservatively equal to
+     `most-positive-fixnum', which can be larger than INT_MAX.  */
   if (arg_scroll_conservatively > scroll_limit)
     {
-      arg_scroll_conservatively = scroll_limit;
-      scroll_max = INT_MAX;
+      arg_scroll_conservatively = scroll_limit + 1;
+      scroll_max = scroll_limit * FRAME_LINE_HEIGHT (f);
     }
   else if (scroll_step || arg_scroll_conservatively || temp_scroll_step)
     /* Compute how much we should try to scroll maximally to bring
@@ -13071,13 +13175,10 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
          /* Compute how many pixels below window bottom to stop searching
             for PT.  This avoids costly search for PT that is far away if
             the user limited scrolling by a small number of lines, but
-            always finds PT if arg_scroll_conservatively is set to a large
+            always finds PT if scroll_conservatively is set to a large
             number, such as most-positive-fixnum.  */
          int slack = max (scroll_max, 10 * FRAME_LINE_HEIGHT (f));
-         int y_to_move =
-           slack >= INT_MAX - it.last_visible_y
-           ? INT_MAX
-           : it.last_visible_y + slack;
+         int y_to_move = it.last_visible_y + slack;
 
          /* Compute the distance from the scroll margin to PT or to
             the scroll limit, whichever comes first.  This should
@@ -13116,6 +13217,10 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
              amount_to_scroll = float_amount;
              if (amount_to_scroll == 0 && float_amount > 0)
                amount_to_scroll = 1;
+             /* Don't let point enter the scroll margin near top of
+                the window.  */
+             if (amount_to_scroll > height - 2*this_scroll_margin + dy)
+               amount_to_scroll = height - 2*this_scroll_margin + dy;
            }
        }
 
@@ -13123,12 +13228,12 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
        return SCROLLING_FAILED;
 
       start_display (&it, w, startp);
-      if (scroll_max < INT_MAX)
+      if (arg_scroll_conservatively <= scroll_limit)
        move_it_vertically (&it, amount_to_scroll);
       else
        {
          /* Extra precision for users who set scroll-conservatively
-            to most-positive-fixnum: make sure the amount we scroll
+            to a large number: make sure the amount we scroll
             the window start is never less than amount_to_scroll,
             which was computed as distance from window bottom to
             point.  This matters when lines at window top and lines
@@ -13139,14 +13244,14 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
          int start_y = line_bottom_y (&it1);
 
          do {
-           move_it_by_lines (&it, 1, 1);
+           move_it_by_lines (&it, 1);
            it1 = it;
          } while (line_bottom_y (&it1) - start_y < amount_to_scroll);
        }
 
       /* If STARTP is unchanged, move it down another screen line.  */
       if (CHARPOS (it.current.pos) == CHARPOS (startp))
-       move_it_by_lines (&it, 1, 1);
+       move_it_by_lines (&it, 1);
       startp = it.current.pos;
     }
   else
@@ -13166,16 +13271,19 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
        {
          /* Point is in the scroll margin at the top of the window or
             above what is displayed in the window.  */
-         int y0;
+         int y0, y_to_move;
 
          /* Compute the vertical distance from PT to the scroll
-            margin position.  Give up if distance is greater than
-            scroll_max.  */
+            margin position.  Move as far as scroll_max allows, or
+            one screenful, or 10 screen lines, whichever is largest.
+            Give up if distance is greater than scroll_max.  */
          SET_TEXT_POS (pos, PT, PT_BYTE);
          start_display (&it, w, pos);
          y0 = it.current_y;
+         y_to_move = max (it.last_visible_y,
+                          max (scroll_max, 10 * FRAME_LINE_HEIGHT (f)));
          move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
-                     it.last_visible_y, -1,
+                     y_to_move, -1,
                      MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
          dy = it.current_y - y0;
          if (dy > scroll_max)
@@ -13185,8 +13293,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
          start_display (&it, w, startp);
 
          if (arg_scroll_conservatively)
-           amount_to_scroll
-             = max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step));
+           amount_to_scroll = max (dy, FRAME_LINE_HEIGHT (f) *
+                                   max (scroll_step, temp_scroll_step));
          else if (scroll_step || temp_scroll_step)
            amount_to_scroll = scroll_max;
          else
@@ -13199,6 +13307,12 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
                  amount_to_scroll = float_amount;
                  if (amount_to_scroll == 0 && float_amount > 0)
                    amount_to_scroll = 1;
+                 amount_to_scroll -=
+                   this_scroll_margin - dy - FRAME_LINE_HEIGHT (f);
+                 /* Don't let point enter the scroll margin near
+                    bottom of the window.  */
+                 if (amount_to_scroll > height - 2*this_scroll_margin + dy)
+                   amount_to_scroll = height - 2*this_scroll_margin + dy;
                }
            }
 
@@ -13307,7 +13421,7 @@ compute_window_start_on_continuation_line (struct window *w)
            {
              min_distance = distance;
              pos = it.current.pos;
-             move_it_by_lines (&it, 1, 0);
+             move_it_by_lines (&it, 1);
            }
 
          /* Set the window start there.  */
@@ -13647,6 +13761,9 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
   return rc;
 }
 
+#if !defined USE_TOOLKIT_SCROLL_BARS || defined USE_GTK
+static
+#endif
 void
 set_vertical_scroll_bar (struct window *w)
 {
@@ -14196,11 +14313,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
        }
     }
 
-  /* Finally, just choose place to start which centers point */
+  /* Finally, just choose a place to start which positions point
+     according to user preferences.  */
 
  recenter:
-  if (centering_position < 0)
-    centering_position = window_box_height (w) / 2;
 
 #if GLYPH_DEBUG
   debug_method_add (w, "recenter");
@@ -14212,10 +14328,84 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   if (!buffer_unchanged_p)
     w->base_line_number = Qnil;
 
-  /* Move backward half the height of the window.  */
+  /* Determine the window start relative to point.  */
   init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
   it.current_y = it.last_visible_y;
+  if (centering_position < 0)
+    {
+      int margin =
+       scroll_margin > 0
+       ? min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
+       : 0;
+      EMACS_INT margin_pos = CHARPOS (startp);
+      int scrolling_up;
+      Lisp_Object aggressive;
+
+      /* If there is a scroll margin at the top of the window, find
+        its character position.  */
+      if (margin
+         /* Cannot call start_display if startp is not in the
+            accessible region of the buffer.  This can happen when we
+            have just switched to a different buffer and/or changed
+            its restriction.  In that case, startp is initialized to
+            the character position 1 (BEG) because we did not yet
+            have chance to display the buffer even once.  */
+         && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
+       {
+         struct it it1;
+
+         start_display (&it1, w, startp);
+         move_it_vertically (&it1, margin);
+         margin_pos = IT_CHARPOS (it1);
+       }
+      scrolling_up = PT > margin_pos;
+      aggressive =
+       scrolling_up
+       ? BVAR (current_buffer, scroll_up_aggressively)
+       : BVAR (current_buffer, scroll_down_aggressively);
+
+      if (!MINI_WINDOW_P (w)
+         && (scroll_conservatively > SCROLL_LIMIT || NUMBERP (aggressive)))
+       {
+         int pt_offset = 0;
+
+         /* Setting scroll-conservatively overrides
+            scroll-*-aggressively.  */
+         if (!scroll_conservatively && NUMBERP (aggressive))
+           {
+             double float_amount = XFLOATINT (aggressive);
+
+             pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
+             if (pt_offset == 0 && float_amount > 0)
+               pt_offset = 1;
+             if (pt_offset)
+               margin -= 1;
+           }
+         /* Compute how much to move the window start backward from
+            point so that point will be displayed where the user
+            wants it.  */
+         if (scrolling_up)
+           {
+             centering_position = it.last_visible_y;
+             if (pt_offset)
+               centering_position -= pt_offset;
+             centering_position -=
+               FRAME_LINE_HEIGHT (f) * (1 + margin + (last_line_misfit != 0));
+             /* Don't let point enter the scroll margin near top of
+                the window.  */
+             if (centering_position < margin * FRAME_LINE_HEIGHT (f))
+               centering_position = margin * FRAME_LINE_HEIGHT (f);
+           }
+         else
+           centering_position = margin * FRAME_LINE_HEIGHT (f) + pt_offset;
+       }
+      else
+       /* Set the window start half the height of the window backward
+          from point.  */
+       centering_position = window_box_height (w) / 2;
+    }
   move_it_vertically_backward (&it, centering_position);
+
   xassert (IT_CHARPOS (it) >= BEGV);
 
   /* The function move_it_vertically_backward may move over more
@@ -14232,8 +14422,9 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
   it.current_x = it.hpos = 0;
 
-  /* Set startp here explicitly in case that helps avoid an infinite loop
-     in case the window-scroll-functions functions get errors.  */
+  /* Set the window start position here explicitly, to avoid an
+     infinite loop in case the functions in window-scroll-functions
+     get errors.  */
   set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
 
   /* Run scroll hooks.  */
@@ -14269,13 +14460,13 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
          && PT >= Z - XFASTINT (w->window_end_pos))
        {
          clear_glyph_matrix (w->desired_matrix);
-         move_it_by_lines (&it, 1, 0);
+         move_it_by_lines (&it, 1);
          try_window (window, it.current.pos, 0);
        }
       else if (PT < IT_CHARPOS (it))
        {
          clear_glyph_matrix (w->desired_matrix);
-         move_it_by_lines (&it, -1, 0);
+         move_it_by_lines (&it, -1);
          try_window (window, it.current.pos, 0);
        }
       else
@@ -14382,7 +14573,6 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
       && EQ (FRAME_SELECTED_WINDOW (f), window))
     {
       int redisplay_menu_p = 0;
-      int redisplay_tool_bar_p = 0;
 
       if (FRAME_WINDOW_P (f))
        {
@@ -14403,17 +14593,15 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
       if (FRAME_WINDOW_P (f))
         {
 #if defined (USE_GTK) || defined (HAVE_NS)
-          redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
+         if (FRAME_EXTERNAL_TOOL_BAR (f))
+           redisplay_tool_bar (f);
 #else
-          redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
-            && (FRAME_TOOL_BAR_LINES (f) > 0
-                || !NILP (Vauto_resize_tool_bars));
+         if (WINDOWP (f->tool_bar_window)
+             && (FRAME_TOOL_BAR_LINES (f) > 0
+                 || !NILP (Vauto_resize_tool_bars))
+             && redisplay_tool_bar (f))
+           ignore_mouse_drag_p = 1;
 #endif
-
-          if (redisplay_tool_bar_p && redisplay_tool_bar (f))
-           {
-             ignore_mouse_drag_p = 1;
-           }
         }
 #endif
     }
@@ -14759,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->redraw_fringe_bitmaps_p = 1;
+             if (row->fringe_bitmap_periodic_p)
+               row->redraw_fringe_bitmaps_p = 1;
 
              it.current_y += row->height;
 
@@ -14921,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->redraw_fringe_bitmaps_p = 1;
+         if (row->fringe_bitmap_periodic_p)
+           row->redraw_fringe_bitmaps_p = 1;
        }
 
       /* Scroll the current matrix.  */
@@ -16889,7 +17079,7 @@ trailing_whitespace_p (EMACS_INT charpos)
 
 /* Highlight trailing whitespace, if any, in ROW.  */
 
-void
+static void
 highlight_trailing_whitespace (struct frame *f, struct glyph_row *row)
 {
   int used = row->used[TEXT_AREA];
@@ -17039,7 +17229,7 @@ cursor_row_p (struct glyph_row *row)
 static int
 push_display_prop (struct it *it, Lisp_Object prop)
 {
-  push_it (it);
+  push_it (it, NULL);
 
   if (STRINGP (prop))
     {
@@ -17968,6 +18158,8 @@ See also `bidi-paragraph-direction'.  */)
        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;
@@ -18071,7 +18263,7 @@ display_menu_bar (struct window *w)
 
   /* 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;
 
@@ -19029,11 +19221,11 @@ static const char power_letter[] =
   };
 
 static void
-pint2hrstr (char *buf, int width, int d)
+pint2hrstr (char *buf, int width, EMACS_INT d)
 {
   /* We aim to represent the nonnegative integer D as
      QUOTIENT.TENTHS * 10 ^ (3 * EXPONENT). */
-  int quotient = d;
+  EMACS_INT quotient = d;
   int remainder = 0;
   /* -1 means: do not use TENTHS. */
   int tenths = -1;
@@ -19359,7 +19551,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
     case 'l':
       {
        EMACS_INT startpos, startpos_byte, line, linepos, linepos_byte;
-       int topline, nlines, height;
+       EMACS_INT topline, nlines, height;
        EMACS_INT junk;
 
        /* %c and %l are ignored in `frame-title-format'.  */
@@ -19403,7 +19595,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
          }
 
        /* Count lines from base line to window start position.  */
-       nlines = display_count_lines (linepos, linepos_byte,
+       nlines = display_count_lines (linepos_byte,
                                      startpos_byte,
                                      startpos, &junk);
 
@@ -19424,7 +19616,8 @@ decode_mode_spec (struct window *w, register int c, int field_width,
            EMACS_INT limit = BUF_BEGV (b);
            EMACS_INT limit_byte = BUF_BEGV_BYTE (b);
            EMACS_INT position;
-           int distance = (height * 2 + 30) * line_number_display_limit_width;
+           EMACS_INT distance =
+             (height * 2 + 30) * line_number_display_limit_width;
 
            if (startpos - distance > limit)
              {
@@ -19432,7 +19625,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
                limit_byte = CHAR_TO_BYTE (limit);
              }
 
-           nlines = display_count_lines (startpos, startpos_byte,
+           nlines = display_count_lines (startpos_byte,
                                          limit_byte,
                                          - (height * 2 + 30),
                                          &position);
@@ -19451,7 +19644,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
          }
 
        /* Now count lines from the start pos to point.  */
-       nlines = display_count_lines (startpos, startpos_byte,
+       nlines = display_count_lines (startpos_byte,
                                      PT_BYTE, PT, &junk);
 
        /* Record that we did display the line number.  */
@@ -19508,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;
-           sprintf (decode_mode_spec_buf, "%2ld%%", (long)total);
+           sprintf (decode_mode_spec_buf, "%2"pI"d%%", total);
            return decode_mode_spec_buf;
          }
       }
@@ -19539,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))
-             sprintf (decode_mode_spec_buf, "Top%2ld%%", (long)total);
+             sprintf (decode_mode_spec_buf, "Top%2"pI"d%%", total);
            else
-             sprintf (decode_mode_spec_buf, "%2ld%%", (long)total);
+             sprintf (decode_mode_spec_buf, "%2"pI"d%%", total);
            return decode_mode_spec_buf;
          }
       }
@@ -19621,23 +19814,23 @@ decode_mode_spec (struct window *w, register int c, int field_width,
 }
 
 
-/* Count up to COUNT lines starting from START / START_BYTE.
+/* Count up to COUNT lines starting from START_BYTE.
    But don't go beyond LIMIT_BYTE.
    Return the number of lines thus found (always nonnegative).
 
    Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT.  */
 
-static int
-display_count_lines (EMACS_INT start, EMACS_INT start_byte,
-                    EMACS_INT limit_byte, int count,
+static EMACS_INT
+display_count_lines (EMACS_INT start_byte,
+                    EMACS_INT limit_byte, EMACS_INT count,
                     EMACS_INT *byte_pos_ptr)
 {
   register unsigned char *cursor;
   unsigned char *base;
 
-  register int ceiling;
+  register EMACS_INT ceiling;
   register unsigned char *ceiling_addr;
-  int orig_count = count;
+  EMACS_INT orig_count = count;
 
   /* If we are not in selective display mode,
      check only for newlines.  */
@@ -20344,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.  */
 
-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)
 {
@@ -20364,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.  */
 
-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)
 {
@@ -20383,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.  */
 
-static INLINE void
+static inline void
 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
                     struct glyph_string *s)
 {
@@ -20392,16 +20585,15 @@ append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
 }
 
 
-/* Get face and two-byte form of character C in face FACE_ID on frame
-   F.  The encoding of C is returned in *CHAR2B.  MULTIBYTE_P non-zero
-   means we want to display multibyte text.  DISPLAY_P non-zero means
+/* Get face and two-byte form of character C in face FACE_ID on frame F.
+   The encoding of C is returned in *CHAR2B.  DISPLAY_P non-zero means
    make sure that X resources for the face returned are allocated.
    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 multibyte_p, int display_p)
+                           XChar2b *char2b, int display_p)
 {
   struct face *face = FACE_FROM_ID (f, face_id);
 
@@ -20432,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.  */
 
-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)
 {
@@ -20469,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.  */
 
-static INLINE int
+static inline int
 get_char_glyph_code (int c, struct font *font, XChar2b *char2b)
 {
   unsigned code;
@@ -20521,7 +20713,7 @@ fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
                                       -1, Qnil);
 
          face = get_char_face_and_encoding (s->f, c, face_id,
-                                            s->char2b + i, 1, 1);
+                                            s->char2b + i, 1);
          if (face)
            {
              if (! s->face)
@@ -20720,15 +20912,13 @@ fill_image_glyph_string (struct glyph_string *s)
 
 /* Fill glyph string S from a sequence of stretch glyphs.
 
-   ROW is the glyph row in which the glyphs are found, AREA is the
-   area within the row.  START is the index of the first glyph to
-   consider, END is the index of the last + 1.
+   START is the index of the first glyph to consider,
+   END is the index of the last + 1.
 
    Value is the index of the first glyph not in S.  */
 
 static int
-fill_stretch_glyph_string (struct glyph_string *s, struct glyph_row *row,
-                          enum glyph_row_area area, int start, int end)
+fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
 {
   struct glyph *glyph, *last;
   int voffset, face_id;
@@ -20762,7 +20952,7 @@ fill_stretch_glyph_string (struct glyph_string *s, struct glyph_row *row,
 }
 
 static struct font_metrics *
-get_per_char_metric (struct frame *f, struct font *font, XChar2b *char2b)
+get_per_char_metric (struct font *font, XChar2b *char2b)
 {
   static struct font_metrics metrics;
   unsigned code = (XCHAR2B_BYTE1 (char2b) << 8) | XCHAR2B_BYTE2 (char2b);
@@ -20790,7 +20980,7 @@ x_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *rig
       struct font_metrics *pcm;
 
       face = get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
-      if (face->font && (pcm = get_per_char_metric (f, face->font, &char2b)))
+      if (face->font && (pcm = get_per_char_metric (face->font, &char2b)))
        {
          if (pcm->rbearing > pcm->width)
            *right = pcm->rbearing - pcm->width;
@@ -20935,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.  */
 
-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
@@ -21024,7 +21214,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
        {                                                                   \
         s = (struct glyph_string *) alloca (sizeof *s);                    \
         INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL);              \
-        START = fill_stretch_glyph_string (s, row, area, START, END);      \
+        START = fill_stretch_glyph_string (s, START, END);                 \
         append_glyph_string (&HEAD, &TAIL, s);                             \
          s->x = (X);                                                       \
        }                                                                   \
@@ -21497,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.  */
 
-static INLINE void
+static inline void
 append_glyph (struct it *it)
 {
   struct glyph *glyph;
@@ -21571,7 +21761,7 @@ append_glyph (struct it *it)
    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;
@@ -21640,7 +21830,7 @@ append_composite_glyph (struct it *it)
 /* 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)
@@ -22262,6 +22452,8 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
        {
          if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
            acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
+         if (CONSP (acronym))
+           acronym = XCAR (acronym);
          str = STRINGP (acronym) ? SSDATA (acronym) : "";
        }
       else
@@ -22397,7 +22589,7 @@ x_produce_glyphs (struct it *it)
 
          if (get_char_glyph_code (it->char_to_display, font, &char2b))
            {
-             pcm = get_per_char_metric (it->f, font, &char2b);
+             pcm = get_per_char_metric (font, &char2b);
              if (pcm->width == 0
                  && pcm->rbearing == 0 && pcm->lbearing == 0)
                pcm = NULL;
@@ -22657,7 +22849,7 @@ x_produce_glyphs (struct it *it)
          int lbearing, rbearing;
          int i, width, ascent, descent;
          int left_padded = 0, right_padded = 0;
-         int c;
+         int c IF_LINT (= 0); /* cmp->glyph_len can't be zero; see Bug#8512 */
          XChar2b char2b;
          struct font_metrics *pcm;
          int font_not_found_p;
@@ -22699,8 +22891,8 @@ x_produce_glyphs (struct it *it)
          if (! font_not_found_p)
            {
              get_char_face_and_encoding (it->f, c, it->face_id,
-                                         &char2b, it->multibyte_p, 0);
-             pcm = get_per_char_metric (it->f, font, &char2b);
+                                         &char2b, 0);
+             pcm = get_per_char_metric (font, &char2b);
            }
 
          /* Initialize the bounding box.  */
@@ -22760,8 +22952,8 @@ x_produce_glyphs (struct it *it)
              else
                {
                  get_char_face_and_encoding (it->f, ch, face_id,
-                                             &char2b, it->multibyte_p, 0);
-                 pcm = get_per_char_metric (it->f, font, &char2b);
+                                             &char2b, 0);
+                 pcm = get_per_char_metric (font, &char2b);
                }
              if (! pcm)
                cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
@@ -23833,7 +24025,7 @@ x_clear_cursor (struct window *w)
 
 /* Implementation of draw_row_with_mouse_face for GUI sessions, GPM,
    and MSDOS.  */
-void
+static void
 draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
                          int start_hpos, int end_hpos,
                          enum draw_glyphs_face draw)
@@ -23850,10 +24042,9 @@ draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
 #endif
 }
 
-/* EXPORT:
-   Display the active region described by mouse_face_* according to DRAW.  */
+/* Display the active region described by mouse_face_* according to DRAW.  */
 
-void
+static void
 show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
 {
   struct window *w = XWINDOW (hlinfo->mouse_face_window);
@@ -24764,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;
-         int n = v->size;
+         int n = v->header.size;
          int i;
          int inside = 0;
          Lisp_Object lx, ly;
@@ -26197,7 +26388,7 @@ x_intersect_rectangles (XRectangle *r1, XRectangle *r2, XRectangle *result)
     {
       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);
@@ -26510,6 +26701,10 @@ If point moves off-screen, redisplay will scroll by up to
 onto the screen again.  If that cannot be done, then redisplay
 recenters point as usual.
 
+If the value is greater than 100, redisplay will never recenter point,
+but will always scroll just enough text to bring point into view, even
+if you move far away.
+
 A value of zero means always recenter point if it moves off screen.  */);
   scroll_conservatively = 0;
 
@@ -26894,17 +27089,21 @@ cursor shapes.  */);
   Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_number (1));
 
   DEFVAR_LISP ("glyphless-char-display", Vglyphless_char_display,
-              doc: /* Char-table to control displaying of glyphless characters.
-Each element, if non-nil, is an ASCII acronym string (displayed in a box)
-or one of these symbols:
-  hex-code:   display the hexadecimal code of a character in a box
-  empty-box:  display as an empty box
-  thin-space: display as 1-pixel width space
-  zero-width: don't display
-
-It has one extra slot to control the display of a character for which
-no font is found.  The value of the slot is `hex-code' or `empty-box'.
-The default is `empty-box'.  */);
+              doc: /* Char-table defining glyphless characters.
+Each element, if non-nil, should be one of the following:
+  an ASCII acronym string: display this string in a box
+  `hex-code':   display the hexadecimal code of a character in a box
+  `empty-box':  display as an empty box
+  `thin-space': display as 1-pixel width space
+  `zero-width': don't display
+An element may also be a cons cell (GRAPHICAL . TEXT), which specifies the
+display method for graphical terminals and text terminals respectively.
+GRAPHICAL and TEXT should each have one of the values listed above.
+
+The char-table has one extra slot to control the display of a character for
+which no font is found.  This slot only takes effect on graphical terminals.
+Its value should be an ASCII acronym string, `hex-code', `empty-box', or
+`thin-space'.  The default is `empty-box'.  */);
   Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
   Fset_char_table_extra_slot (Vglyphless_char_display, make_number (0),
                              Qempty_box);
@@ -26925,6 +27124,7 @@ init_xdisp (void)
 
   mini_w = XWINDOW (minibuf_window);
   root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
+  echo_area_window = minibuf_window;
 
   if (!noninteractive)
     {