]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
* macterm.c: Remove consolidated defines and code.
[gnu-emacs] / src / xdisp.c
index b649cb2f04fc64f55839cecdfcafa54a58a64572..20111e4988ad4bac29a7d4564bf81f5dc8667ee7 100644 (file)
@@ -1,5 +1,5 @@
 /* Display generation from window structure and buffer text.
-   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 99, 2000, 2001, 2002
+   Copyright (C) 1985,86,87,88,93,94,95,97,98,99, 2000, 2001, 2002, 2003
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -47,7 +47,7 @@ Boston, MA 02111-1307, USA.  */
    you will encounter bugs which are very hard to explain.
 
             (Direct functions, see below)
-             direct_output_for_insert, 
+             direct_output_for_insert,
              direct_forward_char (dispnew.c)
          +---------------------------------+
           |                                 |
@@ -64,7 +64,7 @@ Boston, MA 02111-1307, USA.  */
                                                          |
                                   X expose events  -----+
 
-   What does redisplay?  Obviously, it has to figure out somehow what
+   What does redisplay do?  Obviously, it has to figure out somehow what
    has been changed since the last time the display has been updated,
    and to make these changes visible.  Preferably it would do that in
    a moderately intelligent way, i.e. fast.
@@ -106,7 +106,7 @@ Boston, MA 02111-1307, USA.  */
    `direct_output_for_insert' and `direct_output_forward_char' in
    dispnew.c.
 
-   
+
    Desired matrices.
 
    Desired matrices are always built per Emacs window.  The function
@@ -120,7 +120,7 @@ Boston, MA 02111-1307, USA.  */
    on various settings of buffers and windows, on overlays and text
    properties, on display tables, on selective display.  The good news
    is that all this hairy stuff is hidden behind a small set of
-   interface functions taking a iterator structure (struct it)
+   interface functions taking an iterator structure (struct it)
    argument.
 
    Iteration over things to be displayed is then simple.  It is
@@ -187,6 +187,7 @@ Boston, MA 02111-1307, USA.  */
 #include "process.h"
 #include "region-cache.h"
 #include "fontset.h"
+#include "blockinput.h"
 
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
@@ -194,13 +195,14 @@ Boston, MA 02111-1307, USA.  */
 #ifdef WINDOWSNT
 #include "w32term.h"
 #endif
-#ifdef macintosh
+#ifdef MAC_OS
 #include "macterm.h"
 #endif
 
 #define INFINITY 10000000
 
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+    || defined (USE_GTK)
 extern void set_frame_menubar P_ ((struct frame *f, int, int));
 extern int pending_menu_activation;
 #endif
@@ -209,23 +211,34 @@ extern int interrupt_input;
 extern int command_loop_level;
 
 extern int minibuffer_auto_raise;
+extern Lisp_Object Vminibuffer_list;
 
 extern Lisp_Object Qface;
+extern Lisp_Object Qmode_line, Qmode_line_inactive, Qheader_line;
 
 extern Lisp_Object Voverriding_local_map;
 extern Lisp_Object Voverriding_local_map_menu_flag;
 extern Lisp_Object Qmenu_item;
+extern Lisp_Object Qwhen;
 
 Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
 Lisp_Object Qredisplay_end_trigger_functions;
 Lisp_Object Qinhibit_point_motion_hooks;
-Lisp_Object QCeval, Qwhen, QCfile, QCdata, QCpropertize;
+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;
 
+/* Cursor shapes */
+Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
+
+Lisp_Object Qrisky_local_variable;
+
+/* Holds the list (error).  */
+Lisp_Object list_of_error;
+
 /* Functions called to fontify regions of text.  */
 
 Lisp_Object Vfontification_functions;
@@ -268,6 +281,7 @@ Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
 Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
 Lisp_Object Qmargin;
 extern Lisp_Object Qheight;
+extern Lisp_Object QCwidth, QCheight, QCascent;
 
 /* Non-nil means highlight trailing whitespace.  */
 
@@ -333,7 +347,7 @@ int truncate_partial_width_windows;
 /* A flag to control how to display unibyte 8-bit character.  */
 
 int unibyte_display_via_language_environment;
+
 /* Nonzero means we have more than one non-mini-buffer-only frame.
    Not guaranteed to be accurate except while parsing
    frame-title-format.  */
@@ -423,7 +437,6 @@ Lisp_Object minibuf_prompt;
    of the line that contains the prompt.  */
 
 int minibuf_prompt_width;
-int minibuf_prompt_pixel_width;
 
 /* This is the window where the echo area message was displayed.  It
    is always a mini-buffer window, but it may not be the same window
@@ -452,6 +465,10 @@ int update_mode_lines;
 
 int windows_or_buffers_changed;
 
+/* Nonzero means a frame's cursor type has been changed.  */
+
+int cursor_type_changed;
+
 /* Nonzero after display_mode_line if %l was used and it displayed a
    line number.  */
 
@@ -522,9 +539,12 @@ static int message_cleared_p;
 /* Non-zero means we want a hollow cursor in windows that are not
    selected.  Zero means there's no cursor in such windows.  */
 
-int cursor_in_non_selected_windows;
+Lisp_Object Vcursor_in_non_selected_windows;
 Lisp_Object Qcursor_in_non_selected_windows;
 
+/* How to blink the default frame cursor off.  */
+Lisp_Object Vblink_cursor_alist;
+
 /* A scratch glyph row with contents used for generating truncation
    glyphs.  Also used in direct_output_for_insert.  */
 
@@ -547,7 +567,7 @@ int help_echo_showing_p;
 int current_mode_line_height, current_header_line_height;
 
 /* The maximum distance to look ahead for text properties.  Values
-   that are too small let us call compute_char_face and similar 
+   that are too small let us call compute_char_face and similar
    functions too often which is expensive.  Values that are too large
    let us call compute_char_face and alike too often because we
    might not be interested in text properties that far away.  */
@@ -576,7 +596,7 @@ int trace_move;
 #else
 #define TRACE_MOVE(x)  (void) 0
 #endif
+
 /* Non-zero means automatically scroll windows horizontally to make
    point visible.  */
 
@@ -672,7 +692,7 @@ enum move_it_result
   /* Move within a line ended at the end of a line that must be
      continued.  */
   MOVE_LINE_CONTINUED,
-  
+
   /* Move within a line ended at the end of a line that would
      be displayed truncated.  */
   MOVE_LINE_TRUNCATED,
@@ -681,6 +701,28 @@ enum move_it_result
   MOVE_NEWLINE_OR_CR
 };
 
+/* This counter is used to clear the face cache every once in a while
+   in redisplay_internal.  It is incremented for each redisplay.
+   Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is
+   cleared.  */
+
+#define CLEAR_FACE_CACHE_COUNT 500
+static int clear_face_cache_count;
+
+/* Record the previous terminal frame we displayed.  */
+
+static struct frame *previous_terminal_frame;
+
+/* Non-zero while redisplay_internal is in progress.  */
+
+int redisplaying_p;
+
+/* Non-zero means don't free realized faces.  Bound while freeing
+   realized faces is dangerous because glyph matrices might still
+   reference them.  */
+
+int inhibit_free_realized_faces;
+Lisp_Object Qinhibit_free_realized_faces;
 
 \f
 /* Function prototypes.  */
@@ -704,7 +746,7 @@ static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
 static void reconsider_clip_changes P_ ((struct window *, struct buffer *));
 static int text_outside_line_unchanged_p P_ ((struct window *, int, int));
 static void store_frame_title_char P_ ((char));
-static int store_frame_title P_ ((unsigned char *, int, int));
+static int store_frame_title P_ ((const unsigned char *, int, int));
 static void x_consider_frame_title P_ ((Lisp_Object));
 static void handle_stop P_ ((struct it *));
 static int tool_bar_lines_needed P_ ((struct frame *));
@@ -723,7 +765,7 @@ static int display_echo_area P_ ((struct window *));
 static int display_echo_area_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
 static int resize_mini_window_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
 static Lisp_Object unwind_redisplay P_ ((Lisp_Object));
-static int string_char_and_length P_ ((unsigned char *, int, int *));
+static int string_char_and_length P_ ((const unsigned char *, int, int *));
 static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object,
                                             struct text_pos));
 static int compute_window_start_on_continuation_line P_ ((struct window *));
@@ -733,7 +775,7 @@ static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
 static void extend_face_to_end_of_line P_ ((struct it *));
 static int append_space P_ ((struct it *, int));
 static int make_cursor_line_fully_visible P_ ((struct window *));
-static int try_scrolling P_ ((Lisp_Object, int, EMACS_INT, EMACS_INT, int));
+static int try_scrolling P_ ((Lisp_Object, int, EMACS_INT, EMACS_INT, int, int));
 static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
 static int trailing_whitespace_p P_ ((int));
 static int message_log_check_duplicate P_ ((int, int, int, int));
@@ -753,7 +795,8 @@ static int try_window_id P_ ((struct window *));
 static int display_line P_ ((struct it *));
 static int display_mode_lines P_ ((struct window *));
 static int display_mode_line P_ ((struct window *, enum face_id, Lisp_Object));
-static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object, Lisp_Object));
+static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object, Lisp_Object, int));
+static int store_mode_line_string P_ ((char *, Lisp_Object, int, int, int, Lisp_Object));
 static char *decode_mode_spec P_ ((struct window *, int, int, int, int *));
 static void display_menu_bar P_ ((struct window *));
 static int display_count_lines P_ ((int, int, int, int, int *));
@@ -823,9 +866,11 @@ static void display_tool_bar_line P_ ((struct it *));
                      Window display dimensions
  ***********************************************************************/
 
-/* Return the window-relative maximum y + 1 for glyph rows displaying
-   text in window W.  This is the height of W minus the height of a
-   mode line, if any.  */
+/* Return the bottom boundary y-position for text lines in window W.
+   This is the first y position at which a line cannot start.
+   It is relative to the top of the window.
+
+   This is the height of W minus the height of a mode line, if any.  */
 
 INLINE int
 window_text_bottom_y (w)
@@ -851,11 +896,11 @@ window_box_width (w, area)
 {
   struct frame *f = XFRAME (w->frame);
   int width = XFASTINT (w->width);
-  
+
   if (!w->pseudo_window_p)
     {
       width -= FRAME_SCROLL_BAR_WIDTH (f) + FRAME_FRINGE_COLS (f);
-      
+
       if (area == TEXT_AREA)
        {
          if (INTEGERP (w->left_margin_width))
@@ -886,7 +931,7 @@ window_box_height (w)
   int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
 
   xassert (height >= 0);
-  
+
   /* Note: the code below that determines the mode-line/header-line
      height is essentially the same as that contained in the macro
      CURRENT_{MODE,HEADER}_LINE_HEIGHT, except that it checks whether
@@ -939,7 +984,7 @@ window_box_left (w, area)
     {
       x += (WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f)
            + FRAME_LEFT_FRINGE_WIDTH (f));
-      
+
       if (area == TEXT_AREA)
        x += window_box_width (w, LEFT_MARGIN_AREA);
       else if (area == RIGHT_MARGIN_AREA)
@@ -948,7 +993,7 @@ window_box_left (w, area)
     }
 
   return x;
-}     
+}
 
 
 /* Return the frame-relative coordinate of the right edge of display
@@ -961,8 +1006,8 @@ window_box_right (w, area)
      int area;
 {
   return window_box_left (w, area) + window_box_width (w, area);
-}     
-     
+}
+
 
 /* Get the bounding box of the display area AREA of window W, without
    mode lines, in frame-relative coordinates.  AREA < 0 means the
@@ -978,7 +1023,7 @@ window_box (w, area, box_x, box_y, box_width, box_height)
      int *box_x, *box_y, *box_width, *box_height;
 {
   struct frame *f = XFRAME (w->frame);
-  
+
   *box_width = window_box_width (w, area);
   *box_height = window_box_height (w);
   *box_x = window_box_left (w, area);
@@ -1025,7 +1070,7 @@ line_bottom_y (it)
 {
   int line_height = it->max_ascent + it->max_descent;
   int line_top_y = it->current_y;
-  
+
   if (line_height == 0)
     {
       if (last_height)
@@ -1040,7 +1085,7 @@ line_bottom_y (it)
       else
        {
          struct glyph_row *row = it->glyph_row;
-         
+
          /* Use the default character height.  */
          it->glyph_row = NULL;
          it->what = IT_CHARACTER;
@@ -1079,7 +1124,7 @@ pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
 
   *fully = visible_p = 0;
   SET_TEXT_POS_FROM_MARKER (top, w->start);
-  
+
   /* Compute exact mode line heights, if requested.  */
   if (exact_mode_line_heights_p)
     {
@@ -1087,7 +1132,7 @@ pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
        current_mode_line_height
          = display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
                               current_buffer->mode_line_format);
-  
+
       if (WINDOW_WANTS_HEADER_LINE_P (w))
        current_header_line_height
          = display_mode_line (w, HEADER_LINE_FACE_ID,
@@ -1104,7 +1149,7 @@ pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
       int top_y = it.current_y;
       int bottom_y = line_bottom_y (&it);
       int window_top_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
-      
+
       if (top_y < window_top_y)
        visible_p = bottom_y > window_top_y;
       else if (top_y < it.last_visible_y)
@@ -1139,7 +1184,7 @@ pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
 
 static INLINE int
 string_char_and_length (str, maxlen, len)
-     unsigned char *str;
+     const unsigned char *str;
      int maxlen, *len;
 {
   int c;
@@ -1169,8 +1214,8 @@ string_pos_nchars_ahead (pos, string, nchars)
 
   if (STRING_MULTIBYTE (string))
     {
-      int rest = STRING_BYTES (XSTRING (string)) - BYTEPOS (pos);
-      unsigned char *p = XSTRING (string)->data + BYTEPOS (pos);
+      int rest = SBYTES (string) - BYTEPOS (pos);
+      const unsigned char *p = SDATA (string) + BYTEPOS (pos);
       int len;
 
       while (nchars--)
@@ -1250,7 +1295,7 @@ number_of_chars (s, multibyte_p)
      int multibyte_p;
 {
   int nchars;
-  
+
   if (multibyte_p)
     {
       int rest = strlen (s), len;
@@ -1268,7 +1313,7 @@ number_of_chars (s, multibyte_p)
   return nchars;
 }
 
-     
+
 /* Compute byte position NEWPOS->bytepos corresponding to
    NEWPOS->charpos.  POS is a known position in string STRING.
    NEWPOS->charpos must be >= POS.charpos.  */
@@ -1280,7 +1325,7 @@ compute_string_pos (newpos, pos, string)
 {
   xassert (STRINGP (string));
   xassert (CHARPOS (*newpos) >= CHARPOS (pos));
-  
+
   if (STRING_MULTIBYTE (string))
     *newpos = string_pos_nchars_ahead (pos, string,
                                       CHARPOS (*newpos) - CHARPOS (pos));
@@ -1313,22 +1358,24 @@ safe_eval (sexpr)
      Lisp_Object sexpr;
 {
   Lisp_Object val;
-  
+
   if (inhibit_eval_during_redisplay)
     val = Qnil;
   else
     {
-      int count = BINDING_STACK_SIZE ();
+      int count = SPECPDL_INDEX ();
       struct gcpro gcpro1;
 
       GCPRO1 (sexpr);
       specbind (Qinhibit_redisplay, Qt);
-      val = internal_condition_case_1 (Feval, sexpr, Qerror,
+      /* Use Qt to ensure debugger does not run,
+        so there is no possibility of wanting to redisplay.  */
+      val = internal_condition_case_1 (Feval, sexpr, Qt,
                                       safe_eval_handler);
       UNGCPRO;
       val = unbind_to (count, val);
     }
-  
+
   return val;
 }
 
@@ -1343,18 +1390,20 @@ safe_call (nargs, args)
      Lisp_Object *args;
 {
   Lisp_Object val;
-  
+
   if (inhibit_eval_during_redisplay)
     val = Qnil;
   else
     {
-      int count = BINDING_STACK_SIZE ();
+      int count = SPECPDL_INDEX ();
       struct gcpro gcpro1;
 
       GCPRO1 (args[0]);
       gcpro1.nvars = nargs;
       specbind (Qinhibit_redisplay, Qt);
-      val = internal_condition_case_2 (Ffuncall, nargs, args, Qerror,
+      /* Use Qt to ensure debugger does not run,
+        so there is no possibility of wanting to redisplay.  */
+      val = internal_condition_case_2 (Ffuncall, nargs, args, Qt,
                                       safe_eval_handler);
       UNGCPRO;
       val = unbind_to (count, val);
@@ -1466,7 +1515,7 @@ check_window_end (w)
    DEFAULT_FACE_ID for normal text, MODE_LINE_FACE_ID,
    MODE_LINE_INACTIVE_FACE_ID, or HEADER_LINE_FACE_ID for displaying
    mode lines, or TOOL_BAR_FACE_ID for displaying the tool-bar.
-   
+
    If ROW is null and BASE_FACE_ID is equal to MODE_LINE_FACE_ID,
    MODE_LINE_INACTIVE_FACE_ID, or HEADER_LINE_FACE_ID, the iterator
    will be initialized to use the corresponding mode line glyph row of
@@ -1489,8 +1538,9 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
 
   /* If face attributes have been changed since the last redisplay,
      free realized faces now because they depend on face definitions
-     that might have changed.  */
-  if (face_change_count)
+     that might have changed.  Don't free faces while there might be
+     desired matrices pending which reference these faces.  */
+  if (face_change_count && !inhibit_free_realized_faces)
     {
       face_change_count = 0;
       free_all_realized_faces (Qnil);
@@ -1506,7 +1556,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
       else if (base_face_id == HEADER_LINE_FACE_ID)
        row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
     }
-  
+
   /* Clear IT.  */
   bzero (it, sizeof *it);
   it->current.overlay_string_index = -1;
@@ -1544,7 +1594,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
   /* Current value of the `space-width', and 'height' properties.  */
   it->space_width = Qnil;
   it->font_height = Qnil;
-  
+
   /* Are control characters displayed as `^C'?  */
   it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
 
@@ -1553,7 +1603,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
      invisible.  */
   it->selective = (INTEGERP (current_buffer->selective_display)
                   ? XFASTINT (current_buffer->selective_display)
-                  : (!NILP (current_buffer->selective_display) 
+                  : (!NILP (current_buffer->selective_display)
                      ? -1 : 0));
   it->selective_display_ellipsis_p
     = !NILP (current_buffer->selective_display_ellipses);
@@ -1575,7 +1625,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
      -1 to indicate no region.  */
   if (highlight_region_p
       /* Maybe highlight only in selected window.  */
-      && (/* Either show region everywhere.  */ 
+      && (/* Either show region everywhere.  */
          highlight_nonselected_windows
          /* Or show region in the selected window.  */
          || w == XWINDOW (selected_window)
@@ -1691,7 +1741,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
   if (base_face_id != DEFAULT_FACE_ID)
     {
       struct face *face;
-      
+
       it->face_id = base_face_id;
 
       /* If we have a boxed mode line, make the first character appear
@@ -1708,7 +1758,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
       it->end_charpos = ZV;
       it->face_id = -1;
       IT_CHARPOS (*it) = charpos;
-      
+
       /* Compute byte position if not specified.  */
       if (bytepos < charpos)
        IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos);
@@ -1718,7 +1768,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
       /* Compute faces etc.  */
       reseat (it, it->current.pos, 1);
     }
-  
+
   CHECK_IT (it);
 }
 
@@ -1741,23 +1791,34 @@ start_display (it, w, pos)
     {
       int start_at_line_beg_p;
       int first_y = it->current_y;
-  
+
       /* If window start is not at a line start, skip forward to POS to
         get the correct continuation lines width.  */
       start_at_line_beg_p = (CHARPOS (pos) == BEGV
                             || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
       if (!start_at_line_beg_p)
        {
+         int new_x;
+
          reseat_at_previous_visible_line_start (it);
          move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
 
+         new_x = it->current_x + it->pixel_width;
+
          /* If lines are continued, this line may end in the middle
             of a multi-glyph character (e.g. a control character
             displayed as \003, or in the middle of an overlay
             string).  In this case move_it_to above will not have
             taken us to the start of the continuation line but to the
             end of the continued line.  */
-         if (it->current_x > 0)
+         if (it->current_x > 0
+             && !it->truncate_lines_p /* Lines are continued.  */
+             && (/* And glyph doesn't fit on the line.  */
+                 new_x > it->last_visible_x
+                 /* Or it fits exactly and we're on a window
+                    system frame.  */
+                 || (new_x == it->last_visible_x
+                     && FRAME_WINDOW_P (it->f))))
            {
              if (it->current.dpvec_index >= 0
                  || it->current.overlay_string_index >= 0)
@@ -1765,7 +1826,7 @@ start_display (it, w, pos)
                  set_iterator_to_next (it, 1);
                  move_it_in_display_line_to (it, -1, -1, 0);
                }
-             
+
              it->continuation_lines_width += it->current_x;
            }
 
@@ -1774,7 +1835,7 @@ start_display (it, w, pos)
             fields in the iterator structure.  */
          it->max_ascent = it->max_descent = 0;
          it->max_phys_ascent = it->max_phys_descent = 0;
-      
+
          it->current_y = first_y;
          it->vpos = 0;
          it->current_x = it->hpos = 0;
@@ -1784,7 +1845,7 @@ start_display (it, w, pos)
 #if 0 /* Don't assert the following because start_display is sometimes
          called intentionally with a window start that is not at a
         line start.  Please leave this code in as a comment.  */
-  
+
   /* Window start should be on a line start, now.  */
   xassert (it->continuation_lines_width
           || IT_CHARPOS (it) == BEGV
@@ -1804,7 +1865,7 @@ in_ellipses_for_invisible_text_p (pos, w)
   Lisp_Object prop, window;
   int ellipses_p = 0;
   int charpos = CHARPOS (pos->pos);
-  
+
   /* If POS specifies a position in a display vector, this might
      be for an ellipsis displayed for invisible text.  We won't
      get the iterator set up for delivering that ellipsis unless
@@ -1840,7 +1901,7 @@ init_from_display_pos (it, w, pos)
 {
   int charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
   int i, overlay_strings_with_newlines = 0;
-  
+
   /* If POS specifies a position in a display vector, this might
      be for an ellipsis displayed for invisible text.  We won't
      get the iterator set up for delivering that ellipsis unless
@@ -1850,7 +1911,7 @@ init_from_display_pos (it, w, pos)
       --charpos;
       bytepos = 0;
     }
-    
+
   /* Keep in mind: the call to reseat in init_iterator skips invisible
      text, so we might end up at a position different from POS.  This
      is only a problem when POS is a row start after a newline and an
@@ -1864,9 +1925,9 @@ init_from_display_pos (it, w, pos)
 
   for (i = 0; i < it->n_overlay_strings; ++i)
     {
-      char *s = XSTRING (it->overlay_strings[i])->data;
-      char *e = s + STRING_BYTES (XSTRING (it->overlay_strings[i]));
-      
+      const char *s = SDATA (it->overlay_strings[i]);
+      const char *e = s + SBYTES (it->overlay_strings[i]);
+
       while (s < e && *s != '\n')
        ++s;
 
@@ -1889,7 +1950,7 @@ init_from_display_pos (it, w, pos)
         correct the overlay string index.  */
       if (it->method == next_element_from_image)
        pop_it (it);
-      
+
       /* We already have the first chunk of overlay strings in
         IT->overlay_strings.  Load more until the one for
         pos->overlay_string_index is in IT->overlay_strings.  */
@@ -1903,7 +1964,7 @@ init_from_display_pos (it, w, pos)
              it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
            }
        }
-      
+
       it->current.overlay_string_index = pos->overlay_string_index;
       relative_index = (it->current.overlay_string_index
                        % OVERLAY_STRING_CHUNK_SIZE);
@@ -1912,7 +1973,7 @@ init_from_display_pos (it, w, pos)
       it->current.string_pos = pos->string_pos;
       it->method = next_element_from_string;
     }
-  
+
 #if 0 /* This is bogus because POS not having an overlay string
         position does not mean it's after the string.  Example: A
         line starting with a before-string and initialization of IT
@@ -1931,7 +1992,7 @@ init_from_display_pos (it, w, pos)
        it->overlay_strings_at_end_processed_p = 1;
     }
 #endif /* 0 */
-  
+
   if (CHARPOS (pos->string_pos) >= 0)
     {
       /* Recorded position is not in an overlay string, but in another
@@ -1950,7 +2011,7 @@ init_from_display_pos (it, w, pos)
       xassert (it->dpvec && it->current.dpvec_index == 0);
       it->current.dpvec_index = pos->dpvec_index;
     }
-  
+
   CHECK_IT (it);
   return !overlay_strings_with_newlines;
 }
@@ -1970,7 +2031,7 @@ init_to_row_start (it, w, row)
   CHECK_IT (it);
 }
 
-     
+
 /* Initialize IT for stepping through current_buffer in window W
    starting in the line following ROW, i.e. starting at ROW->end.
    Value is zero if there are overlay strings with newlines at ROW's
@@ -1983,7 +2044,7 @@ init_to_row_end (it, w, row)
      struct glyph_row *row;
 {
   int success = 0;
-  
+
   if (init_from_display_pos (it, w, &row->end))
     {
       if (row->continued_p)
@@ -1992,7 +2053,7 @@ init_to_row_end (it, w, row)
       CHECK_IT (it);
       success = 1;
     }
-  
+
   return success;
 }
 
@@ -2021,7 +2082,7 @@ handle_stop (it)
   do
     {
       handled = HANDLED_NORMALLY;
-      
+
       /* Call text property handlers.  */
       for (p = it_props; p->handler; ++p)
        {
@@ -2045,7 +2106,7 @@ handle_stop (it)
          /* Handle overlay changes.  */
          if (handle_overlay_change_p)
            handled = handle_overlay_change (it);
-      
+
          /* Determine where to stop next.  */
          if (handled == HANDLED_NORMALLY)
            compute_stop_pos (it);
@@ -2067,7 +2128,7 @@ compute_stop_pos (it)
 
   /* If nowhere else, stop at the end.  */
   it->stop_charpos = it->end_charpos;
-  
+
   if (STRINGP (it->string))
     {
       /* Strings are usually short, so don't limit the search for
@@ -2097,7 +2158,7 @@ compute_stop_pos (it)
          else if (IT_CHARPOS (*it) < it->region_end_charpos)
            it->stop_charpos = min (it->stop_charpos, it->region_end_charpos);
        }
-      
+
       /* Set up variables for computing the stop position from text
          property changes.  */
       XSETBUFFER (object, current_buffer);
@@ -2134,7 +2195,7 @@ compute_stop_pos (it)
              if (!EQ (values_here[p->idx], new_value))
                break;
            }
-         
+
          if (p->handler)
            break;
        }
@@ -2227,12 +2288,12 @@ handle_fontified_prop (it)
          prop = Fget_char_property (pos, Qfontified, Qnil),
          NILP (prop)))
     {
-      int count = BINDING_STACK_SIZE ();
+      int count = SPECPDL_INDEX ();
       Lisp_Object val;
 
       val = Vfontification_functions;
       specbind (Qfontification_functions, Qnil);
-  
+
       if (!CONSP (val) || EQ (XCAR (val), Qlambda))
        safe_call1 (val, pos);
       else
@@ -2242,11 +2303,11 @@ handle_fontified_prop (it)
 
          globals = Qnil;
          GCPRO2 (val, globals);
-         
+
          for (; CONSP (val); val = XCDR (val))
            {
              fn = XCAR (val);
-             
+
              if (EQ (fn, Qt))
                {
                  /* A value of t indicates this hook has a local
@@ -2296,7 +2357,7 @@ handle_face_prop (it)
      struct it *it;
 {
   int new_face_id, next_stop;
-  
+
   if (!STRINGP (it->string))
     {
       new_face_id
@@ -2308,7 +2369,7 @@ handle_face_prop (it)
                                   (IT_CHARPOS (*it)
                                    + TEXT_PROP_DISTANCE_LIMIT),
                                   0);
-      
+
       /* Is this a start of a run of characters with box face?
         Caveat: this can be called for a freshly initialized
         iterator; face_id is -1 in this case.  We know that the new
@@ -2318,7 +2379,7 @@ handle_face_prop (it)
       if (new_face_id != it->face_id)
        {
          struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
-         
+
          /* If new face has a box but old face has not, this is
             the start of a run of characters with box, i.e. it has
             a shadow on the left side.  The value of face_id of the
@@ -2341,14 +2402,14 @@ handle_face_prop (it)
        bufpos = IT_CHARPOS (*it);
       else
        bufpos = 0;
-      
+
       /* For strings from a buffer, i.e. overlay strings or strings
         from a `display' property, use the face at IT's current
         buffer position as the base face to merge with, so that
         overlay strings appear in the same face as surrounding
         text, unless they specify their own faces.  */
       base_face_id = underlying_face_id (it);
-      
+
       new_face_id = face_at_string_position (it->w,
                                             it->string,
                                             IT_STRING_CHARPOS (*it),
@@ -2357,7 +2418,7 @@ handle_face_prop (it)
                                             it->region_end_charpos,
                                             &next_stop,
                                             base_face_id, 0);
-      
+
 #if 0 /* This shouldn't be neccessary.  Let's check it.  */
       /* If IT is used to display a mode line we would really like to
         use the mode line face instead of the frame's default face.  */
@@ -2365,7 +2426,7 @@ handle_face_prop (it)
          && new_face_id == DEFAULT_FACE_ID)
        new_face_id = CURRENT_MODE_LINE_FACE_ID (it->w);
 #endif
-      
+
       /* Is this a start of a run of characters with box?  Caveat:
         this can be called for a freshly allocated iterator; face_id
         is -1 is this case.  We know that the new face will not
@@ -2377,7 +2438,7 @@ handle_face_prop (it)
        {
          struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
          struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
-         
+
          /* If new face has a box but old face hasn't, this is the
             start of a run of characters with box, i.e. it has a
             shadow on the left side.  */
@@ -2386,7 +2447,7 @@ handle_face_prop (it)
          it->face_box_p = new_face->box != FACE_NO_BOX;
        }
     }
-  
+
   it->face_id = new_face_id;
   return HANDLED_NORMALLY;
 }
@@ -2427,15 +2488,15 @@ face_before_or_after_it_pos (it, before_p)
   struct text_pos pos;
 
   xassert (it->s == NULL);
-    
+
   if (STRINGP (it->string))
     {
       int bufpos, base_face_id;
-      
+
       /* No face change past the end of the string (for the case
         we are padding with spaces).  No face change before the
         string start.  */
-      if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size
+      if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
          || (IT_STRING_CHARPOS (*it) == 0 && before_p))
        return it->face_id;
 
@@ -2471,11 +2532,11 @@ face_before_or_after_it_pos (it, before_p)
         suitable for unibyte text if IT->string is unibyte.  */
       if (STRING_MULTIBYTE (it->string))
        {
-         unsigned char *p = XSTRING (it->string)->data + BYTEPOS (pos);
-         int rest = STRING_BYTES (XSTRING (it->string)) - BYTEPOS (pos);
+         const unsigned char *p = SDATA (it->string) + BYTEPOS (pos);
+         int rest = SBYTES (it->string) - BYTEPOS (pos);
          int c, len;
          struct face *face = FACE_FROM_ID (it->f, face_id);
-      
+
          c = string_char_and_length (p, rest, &len);
          face_id = FACE_FOR_CHAR (it->f, face, c);
        }
@@ -2485,10 +2546,10 @@ face_before_or_after_it_pos (it, before_p)
       if ((IT_CHARPOS (*it) >= ZV && !before_p)
          || (IT_CHARPOS (*it) <= BEGV && before_p))
        return it->face_id;
-      
+
       limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
       pos = it->current.pos;
-      
+
       if (before_p)
        DEC_TEXT_POS (pos, it->multibyte_p);
       else
@@ -2500,7 +2561,7 @@ face_before_or_after_it_pos (it, before_p)
          else
            INC_TEXT_POS (pos, it->multibyte_p);
        }
-      
+
       /* Determine face for CHARSET_ASCII, or unibyte.  */
       face_id = face_at_buffer_position (it->w,
                                         CHARPOS (pos),
@@ -2514,12 +2575,12 @@ face_before_or_after_it_pos (it, before_p)
         suitable for unibyte text if current_buffer is unibyte.  */
       if (it->multibyte_p)
        {
-         int c = FETCH_MULTIBYTE_CHAR (CHARPOS (pos));
+         int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
          struct face *face = FACE_FROM_ID (it->f, face_id);
          face_id = FACE_FOR_CHAR (it->f, face, c);
        }
     }
-  
+
   return face_id;
 }
 
@@ -2553,15 +2614,15 @@ handle_invisible_prop (it)
          && IT_STRING_CHARPOS (*it) < it->end_charpos)
        {
          handled = HANDLED_RECOMPUTE_PROPS;
-         
+
          /* Get the position at which the next change of the
             invisible text property can be found in IT->string.
             Value will be nil if the property value is the same for
             all the rest of IT->string.  */
-         XSETINT (limit, XSTRING (it->string)->size);
+         XSETINT (limit, SCHARS (it->string));
          end_charpos = Fnext_single_property_change (charpos, Qinvisible,
-                                                 it->string, limit);
-         
+                                                     it->string, limit);
+
          /* Text at current position is invisible.  The next
             change in the property is at position end_charpos.
             Move IT's current position to that position.  */
@@ -2587,9 +2648,8 @@ handle_invisible_prop (it)
                }
              else
                {
-                 struct Lisp_String *s = XSTRING (it->string);
-                 IT_STRING_CHARPOS (*it) = s->size;
-                 IT_STRING_BYTEPOS (*it) = STRING_BYTES (s);
+                 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
+                 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
                }
            }
        }
@@ -2614,7 +2674,7 @@ handle_invisible_prop (it)
          int display_ellipsis_p = invis_p == 2;
 
          handled = HANDLED_RECOMPUTE_PROPS;
-         
+
          /* Loop skipping over invisible text.  The loop is left at
             ZV or with IT on the first char being visible again.  */
          do
@@ -2644,7 +2704,7 @@ handle_invisible_prop (it)
                  prop = Fget_char_property (pos, Qinvisible, it->window);
                  invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
                }
-             
+
              /* If we ended up on invisible text, proceed to
                 skip starting with next_stop.  */
              if (invis_p)
@@ -2655,7 +2715,7 @@ handle_invisible_prop (it)
          /* The position newpos is now either ZV or on visible text.  */
          IT_CHARPOS (*it) = newpos;
          IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
-         
+
          /* If there are before-strings at the start of invisible
             text, and the text is invisible because of a text
             property, arrange to show before-strings because 20.x did
@@ -2683,25 +2743,25 @@ static void
 setup_for_ellipsis (it)
      struct it *it;
 {
-  if (it->dp 
+  if (it->dp
       && VECTORP (DISP_INVIS_VECTOR (it->dp)))
     {
       struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
       it->dpvec = v->contents;
       it->dpend = v->contents + v->size;
     }
-  else 
+  else
     {
       /* Default `...'.  */
       it->dpvec = default_invis_vector;
       it->dpend = default_invis_vector + 3;
     }
-  
+
   /* The ellipsis display does not replace the display of the
      character at the new position.  Indicate this by setting
      IT->dpvec_char_len to zero.  */
   it->dpvec_char_len = 0;
-  
+
   it->current.dpvec_index = 0;
   it->method = next_element_from_display_vector;
 }
@@ -2851,7 +2911,7 @@ handle_single_display_prop (it, prop, object, position,
 
   if (!NILP (form) && !EQ (form, Qt))
     {
-      int count = BINDING_STACK_SIZE ();
+      int count = SPECPDL_INDEX ();
       struct gcpro gcpro1;
 
       /* Bind `object' to the object having the `display' property, a
@@ -2868,7 +2928,7 @@ handle_single_display_prop (it, prop, object, position,
       UNGCPRO;
       unbind_to (count, Qnil);
     }
-  
+
   if (NILP (form))
     return 0;
 
@@ -2878,7 +2938,7 @@ handle_single_display_prop (it, prop, object, position,
     {
       if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
        return 0;
-      
+
       /* `(height HEIGHT)'.  */
       it->font_height = XCAR (XCDR (prop));
       if (!NILP (it->font_height))
@@ -2912,7 +2972,7 @@ handle_single_display_prop (it, prop, object, position,
            {
              /* Value is a multiple of the canonical char height.  */
              struct face *face;
-             
+
              face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID);
              new_height = (XFLOATINT (it->font_height)
                            * XINT (face->lface[LFACE_HEIGHT_INDEX]));
@@ -2922,16 +2982,16 @@ handle_single_display_prop (it, prop, object, position,
              /* Evaluate IT->font_height with `height' bound to the
                 current specified height to get the new height.  */
              Lisp_Object value;
-             int count = BINDING_STACK_SIZE ();
-             
+             int count = SPECPDL_INDEX ();
+
              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 (new_height > 0)
            it->face_id = face_with_height (it->f, it->face_id, new_height);
        }
@@ -2943,7 +3003,7 @@ handle_single_display_prop (it, prop, object, position,
       /* `(space_width WIDTH)'.  */
       if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
        return 0;
-      
+
       value = XCAR (XCDR (prop));
       if (NUMBERP (value) && XFLOATINT (value) > 0)
        it->space_width = value;
@@ -2955,7 +3015,7 @@ handle_single_display_prop (it, prop, object, position,
       /* `(raise FACTOR)'.  */
       if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
        return 0;
-      
+
 #ifdef HAVE_WINDOW_SYSTEM
       value = XCAR (XCDR (prop));
       if (NUMBERP (value))
@@ -2988,7 +3048,7 @@ handle_single_display_prop (it, prop, object, position,
       if (CONSP (prop) && CONSP (XCAR (prop)))
        {
          Lisp_Object tem;
-         
+
          value = XCDR (prop);
          if (CONSP (value))
            value = XCAR (value);
@@ -3019,7 +3079,7 @@ handle_single_display_prop (it, prop, object, position,
 #else /* not HAVE_WINDOW_SYSTEM */
       valid_p = STRINGP (value);
 #endif /* not HAVE_WINDOW_SYSTEM */
-      
+
       if ((EQ (location, Qleft_margin)
           || EQ (location, Qright_margin)
           || NILP (location))
@@ -3027,26 +3087,25 @@ handle_single_display_prop (it, prop, object, position,
          && !display_replaced_before_p)
        {
          replaces_text_display_p = 1;
-         
+
          /* Save current settings of IT so that we can restore them
             when we are finished with the glyph property value.  */
          push_it (it);
-         
+
          if (NILP (location))
            it->area = TEXT_AREA;
          else if (EQ (location, Qleft_margin))
            it->area = LEFT_MARGIN_AREA;
          else
            it->area = RIGHT_MARGIN_AREA;
-         
+
          if (STRINGP (value))
            {
              it->string = value;
              it->multibyte_p = STRING_MULTIBYTE (it->string);
              it->current.overlay_string_index = -1;
              IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
-             it->end_charpos = it->string_nchars
-               = XSTRING (it->string)->size;
+             it->end_charpos = it->string_nchars = SCHARS (it->string);
              it->method = next_element_from_string;
              it->stop_charpos = 0;
              it->string_from_display_prop_p = 1;
@@ -3069,7 +3128,7 @@ handle_single_display_prop (it, prop, object, position,
              it->position = start_pos;
              it->object = NILP (object) ? it->w->buffer : object;
              it->method = next_element_from_image;
-             
+
              /* 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.  */
@@ -3103,6 +3162,9 @@ single_display_prop_intangible_p (prop)
       prop = XCDR (prop);
     }
 
+  if (STRINGP (prop))
+    return 1;
+
   if (!CONSP (prop))
     return 0;
 
@@ -3120,7 +3182,7 @@ single_display_prop_intangible_p (prop)
          || EQ (XCAR (prop), Qright_margin))
        return 0;
     }
-  
+
   return CONSP (prop) && EQ (XCAR (prop), Qimage);
 }
 
@@ -3167,7 +3229,7 @@ single_display_prop_string_p (prop, string)
 {
   if (EQ (string, prop))
     return 1;
-  
+
   /* Skip over `when FORM'.  */
   if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
     {
@@ -3189,7 +3251,7 @@ single_display_prop_string_p (prop, string)
        if (!CONSP (prop))
          return 0;
       }
-  
+
   return CONSP (prop) && EQ (XCAR (prop), string);
 }
 
@@ -3374,7 +3436,7 @@ handle_overlay_change (it)
    overlay strings to display, IT->string and
    IT->current.overlay_string_index are set appropriately here.
    Otherwise IT->string is set to nil.  */
-   
+
 static void
 next_overlay_string (it)
      struct it *it;
@@ -3386,7 +3448,7 @@ next_overlay_string (it)
         they were before overlay strings were processed, and
         continue to deliver from current_buffer.  */
       int display_ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
-      
+
       pop_it (it);
       xassert (it->stop_charpos >= BEGV
               && it->stop_charpos <= it->end_charpos);
@@ -3414,7 +3476,7 @@ next_overlay_string (it)
         where we must load IT->overlay_strings with more strings, do
         it.  */
       int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
-  
+
       if (it->current.overlay_string_index && i == 0)
        load_overlay_strings (it, 0);
 
@@ -3426,7 +3488,7 @@ next_overlay_string (it)
       it->method = next_element_from_string;
       it->stop_charpos = 0;
     }
-  
+
   CHECK_IT (it);
 }
 
@@ -3437,7 +3499,7 @@ next_overlay_string (it)
 
    1. All after-strings come in front of before-strings, except
    when they come from the same overlay.
-   
+
    2. Within after-strings, strings are sorted so that overlay strings
    from overlays with higher priorities come first.
 
@@ -3446,7 +3508,7 @@ next_overlay_string (it)
 
    Value is analogous to strcmp.  */
 
-  
+
 static int
 compare_overlay_entries (e1, e2)
      void *e1, *e2;
@@ -3498,7 +3560,7 @@ compare_overlay_entries (e1, e2)
    front of before-string strings.  Within before and after-strings,
    strings are sorted by overlay priority.  See also function
    compare_overlay_entries.  */
-   
+
 static void
 load_overlay_strings (it, charpos)
      struct it *it;
@@ -3551,7 +3613,7 @@ load_overlay_strings (it, charpos)
       xassert (OVERLAYP (overlay));
       start = OVERLAY_POSITION (OVERLAY_START (overlay));
       end = OVERLAY_POSITION (OVERLAY_END (overlay));
-      
+
       if (end < charpos)
        break;
 
@@ -3559,7 +3621,7 @@ load_overlay_strings (it, charpos)
         position.  */
       if (end != charpos && start != charpos)
        continue;
-      
+
       /* Skip this overlay if it doesn't apply to IT->w.  */
       window = Foverlay_get (overlay, Qwindow);
       if (WINDOWP (window) && XWINDOW (window) != it->w)
@@ -3574,16 +3636,16 @@ load_overlay_strings (it, charpos)
       /* If overlay has a non-empty before-string, record it.  */
       if ((start == charpos || (end == charpos && invis_p))
          && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
-         && XSTRING (str)->size)
+         && SCHARS (str))
        RECORD_OVERLAY_STRING (overlay, str, 0);
-      
+
       /* If overlay has a non-empty after-string, record it.  */
       if ((end == charpos || (start == charpos && invis_p))
          && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
-         && XSTRING (str)->size)
+         && SCHARS (str))
        RECORD_OVERLAY_STRING (overlay, str, 1);
     }
-      
+
   /* Process overlays after the overlay center.  */
   for (ov = current_buffer->overlays_after; CONSP (ov); ov = XCDR (ov))
     {
@@ -3594,7 +3656,7 @@ load_overlay_strings (it, charpos)
 
       if (start > charpos)
        break;
-      
+
       /* Skip this overlay if it doesn't start or end at IT's current
         position.  */
       if (end != charpos && start != charpos)
@@ -3604,7 +3666,7 @@ load_overlay_strings (it, charpos)
       window = Foverlay_get (overlay, Qwindow);
       if (WINDOWP (window) && XWINDOW (window) != it->w)
        continue;
-      
+
       /* If the text ``under'' the overlay is invisible, it has a zero
         dimension, and both before- and after-strings apply.  */
       invisible = Foverlay_get (overlay, Qinvisible);
@@ -3613,18 +3675,18 @@ load_overlay_strings (it, charpos)
       /* If overlay has a non-empty before-string, record it.  */
       if ((start == charpos || (end == charpos && invis_p))
          && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
-         && XSTRING (str)->size)
+         && SCHARS (str))
        RECORD_OVERLAY_STRING (overlay, str, 0);
-                              
+
       /* If overlay has a non-empty after-string, record it.  */
       if ((end == charpos || (start == charpos && invis_p))
          && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
-         && XSTRING (str)->size)
+         && SCHARS (str))
        RECORD_OVERLAY_STRING (overlay, str, 1);
     }
 
 #undef RECORD_OVERLAY_STRING
-   
+
   /* Sort entries.  */
   if (n > 1)
     qsort (entries, n, sizeof *entries, compare_overlay_entries);
@@ -3673,7 +3735,7 @@ get_overlay_strings (it, charpos)
         strings.  */
       compute_stop_pos (it);
       xassert (it->face_id >= 0);
-      
+
       /* Save IT's settings.  They are restored after all overlay
         strings have been processed.  */
       xassert (it->sp == 0);
@@ -3684,9 +3746,9 @@ get_overlay_strings (it, charpos)
       IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
       it->string = it->overlay_strings[0];
       it->stop_charpos = 0;
-      it->end_charpos = XSTRING (it->string)->size;
-      it->multibyte_p = STRING_MULTIBYTE (it->string);
       xassert (STRINGP (it->string));
+      it->end_charpos = SCHARS (it->string);
+      it->multibyte_p = STRING_MULTIBYTE (it->string);
       it->method = next_element_from_string;
     }
   else
@@ -3718,7 +3780,7 @@ push_it (it)
      struct it *it;
 {
   struct iterator_stack_entry *p;
-  
+
   xassert (it->sp < 2);
   p = it->stack + it->sp;
 
@@ -3751,7 +3813,7 @@ pop_it (it)
      struct it *it;
 {
   struct iterator_stack_entry *p;
-  
+
   xassert (it->sp > 0);
   --it->sp;
   p = it->stack + it->sp;
@@ -3787,12 +3849,12 @@ back_to_previous_line_start (it)
 
 
 /* Move IT to the next line start.
-   
+
    Value is non-zero if a newline was found.  Set *SKIPPED_P to 1 if
    we skipped over part of the text (as opposed to moving the iterator
    continuously over the text).  Otherwise, don't change the value
    of *SKIPPED_P.
-   
+
    Newlines may come from buffer text, overlay strings, or strings
    displayed via the `display' property.  That's the reason we can't
    simply use find_next_newline_no_quit.
@@ -3837,14 +3899,14 @@ forward_to_next_line_start (it, skipped_p)
        n += STRINGP (it->string) ? 0 : 1)
     {
       if (!get_next_display_element (it))
-       break;
+       return 0;
       newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
       set_iterator_to_next (it, 0);
     }
 
   /* If we didn't find a newline near enough, see if we can use a
      short-cut.  */
-  if (n == MAX_NEWLINE_DISTANCE)
+  if (!newline_found_p)
     {
       int start = IT_CHARPOS (*it);
       int limit = find_next_newline_no_quit (start, 1);
@@ -3908,9 +3970,9 @@ back_to_previous_visible_line_start (it)
         are invisible.  */
       if (it->selective > 0
          && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
-                               it->selective))
+                               (double) it->selective)) /* iftc */
        visible_p = 0;
-      else 
+      else
        {
          Lisp_Object prop;
 
@@ -3968,7 +4030,7 @@ reseat_at_next_visible_line_start (it, on_newline_p)
   if (it->selective > 0)
     while (IT_CHARPOS (*it) < ZV
           && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
-                                it->selective))
+                                (double) it->selective)) /* iftc */
       {
        xassert (FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
        newline_found_p = forward_to_next_line_start (it, &skipped_p);
@@ -3994,7 +4056,7 @@ reseat_at_next_visible_line_start (it, on_newline_p)
     }
   else if (skipped_p)
     reseat (it, it->current.pos, 0);
-  
+
   CHECK_IT (it);
 }
 
@@ -4067,7 +4129,7 @@ reseat_1 (it, pos, set_stop_p)
 /* Set up IT for displaying a string, starting at CHARPOS in window W.
    If S is non-null, it is a C string to iterate over.  Otherwise,
    STRING gives a Lisp string to iterate over.
-   
+
    If PRECISION > 0, don't return more then PRECISION number of
    characters from the string.
 
@@ -4101,18 +4163,18 @@ reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
   it->current.overlay_string_index = -1;
   it->current.dpvec_index = -1;
   xassert (charpos >= 0);
-  
+
   /* If STRING is specified, use its multibyteness, otherwise use the
      setting of MULTIBYTE, if specified.  */
   if (multibyte >= 0)
     it->multibyte_p = multibyte > 0;
-  
+
   if (s == NULL)
     {
       xassert (STRINGP (string));
       it->string = string;
       it->s = NULL;
-      it->end_charpos = it->string_nchars = XSTRING (string)->size;
+      it->end_charpos = it->string_nchars = SCHARS (string);
       it->method = next_element_from_string;
       it->current.string_pos = string_pos (charpos, string);
     }
@@ -4134,7 +4196,7 @@ reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
          IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
          it->end_charpos = it->string_nchars = strlen (s);
        }
-      
+
       it->method = next_element_from_c_string;
     }
 
@@ -4174,7 +4236,7 @@ int
 get_next_display_element (it)
      struct it *it;
 {
-  /* Non-zero means that we found an display element.  Zero means that
+  /* Non-zero means that we found a display element.  Zero means that
      we hit the end of what we iterate over.  Performance note: the
      function pointer `method' used here turns out to be faster than
      using a sequence of if-statements.  */
@@ -4226,14 +4288,22 @@ get_next_display_element (it)
             the translation.  This could easily be changed but I
             don't believe that it is worth doing.
 
-            Non-printable multibyte characters are also translated
-            octal form.  */
+            If it->multibyte_p is nonzero, eight-bit characters and
+            non-printable multibyte characters are also translated to
+            octal form.
+
+            If it->multibyte_p is zero, eight-bit characters that
+            don't have corresponding multibyte char code are also
+            translated to octal form.  */
          else if ((it->c < ' '
                    && (it->area != TEXT_AREA
                        || (it->c != '\n' && it->c != '\t')))
-                  || (it->c >= 127
-                      && it->len == 1)
-                  || !CHAR_PRINTABLE_P (it->c))
+                  || (it->multibyte_p
+                      ? ((it->c >= 127
+                          && it->len == 1)
+                         || !CHAR_PRINTABLE_P (it->c))
+                      : (it->c >= 127
+                         && it->c == unibyte_char_to_multibyte (it->c))))
            {
              /* IT->c is a control character which must be displayed
                 either as '\003' or as `^C' where the '\\' and '^'
@@ -4304,11 +4374,11 @@ get_next_display_element (it)
                      XSETINT (it->ctl_chars[i * 4], escape_glyph);
                      /* Insert three more glyphs into IT->ctl_chars for
                         the octal display of the character.  */
-                     g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0); 
+                     g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0);
                      XSETINT (it->ctl_chars[i * 4 + 1], g);
-                     g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0); 
+                     g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0);
                      XSETINT (it->ctl_chars[i * 4 + 2], g);
-                     g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0); 
+                     g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0);
                      XSETINT (it->ctl_chars[i * 4 + 3], g);
                    }
 
@@ -4379,7 +4449,7 @@ set_iterator_to_next (it, reseat_p)
      with box.  Reset them at the start of this function because
      moving the iterator to a new position might set them.  */
   it->start_of_box_run_p = it->end_of_box_run_p = 0;
-  
+
   if (it->method == next_element_from_buffer)
     {
       /* The current display element of IT is a character from
@@ -4429,7 +4499,7 @@ set_iterator_to_next (it, reseat_p)
       /* Restore face of the iterator to what they were before the
          display vector entry (these entries may contain faces).  */
       it->face_id = it->saved_face_id;
-      
+
       if (it->dpvec + it->current.dpvec_index == it->dpend)
        {
          if (it->s)
@@ -4458,14 +4528,14 @@ set_iterator_to_next (it, reseat_p)
       xassert (it->s == NULL && STRINGP (it->string));
       IT_STRING_BYTEPOS (*it) += it->len;
       IT_STRING_CHARPOS (*it) += 1;
-      
+
     consider_string_end:
 
       if (it->current.overlay_string_index >= 0)
        {
          /* IT->string is an overlay string.  Advance to the
             next, if there is one.  */
-         if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size)
+         if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
            next_overlay_string (it);
        }
       else
@@ -4474,7 +4544,7 @@ set_iterator_to_next (it, reseat_p)
             its end, and there is something on IT->stack, proceed
             with what is on the stack.  This can be either another
             string, this time an overlay string, or a buffer.  */
-         if (IT_STRING_CHARPOS (*it) == XSTRING (it->string)->size
+         if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
              && it->sp > 0)
            {
              pop_it (it);
@@ -4526,7 +4596,7 @@ next_element_from_display_vector (it)
   /* Remember the current face id in case glyphs specify faces.
      IT's face is restored in set_iterator_to_next.  */
   it->saved_face_id = it->face_id;
-  
+
   if (INTEGERP (*it->dpvec)
       && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
     {
@@ -4592,22 +4662,21 @@ next_element_from_string (it)
       /* Get the next character from an overlay string.  In overlay
         strings, There is no field width or padding with spaces to
         do.  */
-      if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size)
+      if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
        {
          it->what = IT_EOB;
          return 0;
        }
       else if (STRING_MULTIBYTE (it->string))
        {
-         int remaining = (STRING_BYTES (XSTRING (it->string))
-                          - IT_STRING_BYTEPOS (*it));
-         unsigned char *s = (XSTRING (it->string)->data
-                             + IT_STRING_BYTEPOS (*it));
+         int remaining = SBYTES (it->string) - IT_STRING_BYTEPOS (*it);
+         const unsigned char *s = (SDATA (it->string)
+                                   + IT_STRING_BYTEPOS (*it));
          it->c = string_char_and_length (s, remaining, &it->len);
        }
       else
        {
-         it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)];
+         it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
          it->len = 1;
        }
     }
@@ -4630,15 +4699,14 @@ next_element_from_string (it)
        }
       else if (STRING_MULTIBYTE (it->string))
        {
-         int maxlen = (STRING_BYTES (XSTRING (it->string))
-                       - IT_STRING_BYTEPOS (*it));
-         unsigned char *s = (XSTRING (it->string)->data
-                             + IT_STRING_BYTEPOS (*it));
+         int maxlen = SBYTES (it->string) - IT_STRING_BYTEPOS (*it);
+         const unsigned char *s = (SDATA (it->string)
+                                   + IT_STRING_BYTEPOS (*it));
          it->c = string_char_and_length (s, maxlen, &it->len);
        }
       else
        {
-         it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)];
+         it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
          it->len = 1;
        }
     }
@@ -4665,12 +4733,12 @@ next_element_from_c_string (it)
      struct it *it;
 {
   int success_p = 1;
-  
+
   xassert (it->s);
   it->what = IT_CHARACTER;
   BYTEPOS (it->position) = CHARPOS (it->position) = 0;
   it->object = Qnil;
-  
+
   /* IT's position can be greater IT->string_nchars in case a field
      width or precision has been specified when the iterator was
      initialized.  */
@@ -4697,7 +4765,7 @@ next_element_from_c_string (it)
     }
   else
     it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
-  
+
   return success_p;
 }
 
@@ -4745,7 +4813,7 @@ next_element_from_ellipsis (it)
       reseat_at_next_visible_line_start (it, 1);
       it->face_before_selective_p = 1;
     }
-  
+
   return get_next_display_element (it);
 }
 
@@ -4753,7 +4821,7 @@ next_element_from_ellipsis (it)
 /* Deliver an image display element.  The iterator IT is already
    filled with image information (done in handle_display_prop).  Value
    is always 1.  */
-  
+
 
 static int
 next_element_from_image (it)
@@ -4798,7 +4866,7 @@ next_element_from_buffer (it)
       if (IT_CHARPOS (*it) >= it->end_charpos)
        {
          int overlay_strings_follow_p;
-         
+
          /* End of the game, except when overlay strings follow that
             haven't been returned yet.  */
          if (it->overlay_strings_at_end_processed_p)
@@ -4865,7 +4933,7 @@ next_element_from_buffer (it)
                  && IT_CHARPOS (*it) + 1 < ZV
                  && indented_beyond_p (IT_CHARPOS (*it) + 1,
                                        IT_BYTEPOS (*it) + 1,
-                                       it->selective))
+                                       (double) it->selective)) /* iftc */
                {
                  success_p = next_element_from_ellipsis (it);
                  it->dpvec_char_len = -1;
@@ -4887,7 +4955,7 @@ next_element_from_buffer (it)
   return success_p;
 }
 
-     
+
 /* Run the redisplay end trigger hook for IT.  */
 
 static void
@@ -4910,7 +4978,7 @@ run_redisplay_end_trigger_hook (it)
      them again, even if they get an error.  */
   it->w->redisplay_end_trigger = Qnil;
   Frun_hook_with_args (3, args);
-  
+
   /* Notice if it changed the face of the character we are on.  */
   handle_face_prop (it);
 }
@@ -4940,28 +5008,28 @@ next_element_from_composition (it)
 /* Move iterator IT to a specified buffer or X position within one
    line on the display without producing glyphs.
 
-   Begin to skip at IT's current position.  Skip to TO_CHARPOS or TO_X
-   whichever is reached first.
-
-   TO_CHARPOS <= 0 means no TO_CHARPOS is specified.
+   OP should be a bit mask including some or all of these bits:
+    MOVE_TO_X: Stop on reaching x-position TO_X.
+    MOVE_TO_POS: Stop on reaching buffer or string position TO_CHARPOS.
+   Regardless of OP's value, stop in reaching the end of the display line.
 
-   TO_X < 0 means that no TO_X is specified.  TO_X is normally a value
-   0 <= TO_X <= IT->last_visible_x.  This means in particular, that
-   TO_X includes the amount by which a window is horizontally
-   scrolled.
+   TO_X is normally a value 0 <= TO_X <= IT->last_visible_x.
+   This means, in particular, that TO_X includes window's horizontal
+   scroll amount.
 
-   Value is
+   The return value has several possible values that
+   say what condition caused the scan to stop:
 
    MOVE_POS_MATCH_OR_ZV
      - when TO_POS or ZV was reached.
-       
+
    MOVE_X_REACHED
      -when TO_X was reached before TO_POS or ZV were reached.
-       
+
    MOVE_LINE_CONTINUED
      - when we reached the end of the display area and the line must
      be continued.
-                          
+
    MOVE_LINE_TRUNCATED
      - when we reached the end of the display area and the line is
      truncated.
@@ -4985,7 +5053,7 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
   while (1)
     {
       int x, i, ascent = 0, descent = 0;
-      
+
       /* Stop when ZV or TO_CHARPOS reached.  */
       if (!get_next_display_element (it)
          || ((op & MOVE_TO_POS) != 0
@@ -4995,13 +5063,13 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
          result = MOVE_POS_MATCH_OR_ZV;
          break;
        }
-         
+
       /* The call to produce_glyphs will get the metrics of the
         display element IT is loaded with.  We record in x the
         x-position before this display element in case it does not
         fit on the line.  */
       x = it->current_x;
-      
+
       /* Remember the line height so far in case the next element doesn't
         fit on the line.  */
       if (!it->truncate_lines_p)
@@ -5009,7 +5077,7 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
          ascent = it->max_ascent;
          descent = it->max_descent;
        }
-      
+
       PRODUCE_GLYPHS (it);
 
       if (it->area != TEXT_AREA)
@@ -5042,7 +5110,7 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
             glyphs have the same width.  */
          int single_glyph_width = it->pixel_width / it->nglyphs;
          int new_x;
-         
+
          for (i = 0; i < it->nglyphs; ++i, x = new_x)
            {
              new_x = x + single_glyph_width;
@@ -5080,7 +5148,7 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
                      it->max_ascent = ascent;
                      it->max_descent = descent;
                    }
-                 
+
                  TRACE_MOVE ((stderr, "move_it_in: continued at %d\n",
                               IT_CHARPOS (*it)));
                  result = MOVE_LINE_CONTINUED;
@@ -5094,7 +5162,7 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
                }
              else
                {
-                 /* Glyph is completely off the left margin of the display 
+                 /* Glyph is completely off the left margin of the display
                     area.  Nothing to do.  */
                }
            }
@@ -5112,18 +5180,18 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
          result = MOVE_X_REACHED;
          break;
        }
-  
+
       /* Is this a line end?  If yes, we're done.  */
       if (ITERATOR_AT_END_OF_LINE_P (it))
        {
          result = MOVE_NEWLINE_OR_CR;
          break;
        }
-      
+
       /* The current display element has been consumed.  Advance
         to the next.  */
       set_iterator_to_next (it, 1);
-      
+
       /* Stop if lines are truncated and IT's current x-position is
         past the right edge of the window now.  */
       if (it->truncate_lines_p
@@ -5141,10 +5209,13 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
 }
 
 
-/* Move IT forward to a specified buffer position TO_CHARPOS, TO_X,
-   TO_Y, TO_VPOS.  OP is a bit-mask that specifies where to stop.  See
-   the description of enum move_operation_enum.
-   
+/* Move IT forward until it satisfies one or more of the criteria in
+   TO_CHARPOS, TO_X, TO_Y, and TO_VPOS.
+
+   OP is a bit-mask that specifies where to stop, and in particular,
+   which of those four position arguments makes a difference.  See the
+   description of enum move_operation_enum.
+
    If TO_CHARPOS is in invisible text, e.g. a truncated part of a
    screen line, this function will set IT to the next position >
    TO_CHARPOS.  */
@@ -5184,7 +5255,7 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
                  reached = 2;
                  break;
                }
-             
+
              skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
 
              if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
@@ -5208,7 +5279,7 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
       else if (op & MOVE_TO_Y)
        {
          struct it it_backup;
-         
+
          /* TO_Y specified means stop at TO_X in the line containing
             TO_Y---or at TO_CHARPOS if this is reached first.  The
             problem is that we can't really tell whether the line
@@ -5233,7 +5304,7 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
              reached = 5;
              break;
            }
-         
+
          /* If TO_X was reached, we would like to know whether TO_Y
             is in the line.  This can only be said if we know the
             total line height which requires us to scan the rest of
@@ -5250,7 +5321,7 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
          /* Now, decide whether TO_Y is in this line.  */
          line_height = it->max_ascent + it->max_descent;
          TRACE_MOVE ((stderr, "move_it: line_height = %d\n", line_height));
-         
+
          if (to_y >= it->current_y
              && to_y < it->current_y + line_height)
            {
@@ -5313,7 +5384,7 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
       last_max_ascent = it->max_ascent;
       it->max_ascent = it->max_descent = 0;
     }
-  
+
  out:
 
   TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
@@ -5336,7 +5407,7 @@ move_it_vertically_backward (it, dy)
   int nlines, h;
   struct it it2, it3;
   int start_pos = IT_CHARPOS (*it);
-  
+
   xassert (dy >= 0);
 
   /* Estimate how many newlines we must move back.  */
@@ -5354,6 +5425,7 @@ move_it_vertically_backward (it, dy)
 
   /* We are now surely at a line start.  */
   it->current_x = it->hpos = 0;
+  it->continuation_lines_width = 0;
 
   /* Move forward and see what y-distance we moved.  First move to the
      start of the next line so that we get its height.  We need this
@@ -5365,7 +5437,7 @@ move_it_vertically_backward (it, dy)
              MOVE_TO_POS | MOVE_TO_VPOS);
   xassert (IT_CHARPOS (*it) >= BEGV);
   it3 = it2;
-  
+
   move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
   xassert (IT_CHARPOS (*it) >= BEGV);
   h = it2.current_y - it->current_y;
@@ -5374,7 +5446,7 @@ move_it_vertically_backward (it, dy)
   /* Correct IT's y and vpos position.  */
   it->vpos -= nlines;
   it->current_y -= h;
-  
+
   if (dy == 0)
     {
       /* DY == 0 means move to the start of the screen line.  The
@@ -5410,12 +5482,24 @@ move_it_vertically_backward (it, dy)
       else if (target_y >= it->current_y + line_height
               && IT_CHARPOS (*it) < ZV)
        {
-         /* Should move forward by at least one line, maybe more.  */
-         do
+         /* Should move forward by at least one line, maybe more.
+
+            Note: Calling move_it_by_lines can be expensive on
+            terminal frames, where compute_motion is used (via
+            vmotion) to do the job, when there are very long lines
+            and truncate-lines is nil.  That's the reason for
+            treating terminal frames specially here.  */
+
+         if (!FRAME_WINDOW_P (it->f))
+           move_it_vertically (it, target_y - (it->current_y + line_height));
+         else
            {
-             move_it_by_lines (it, 1, 1);
+             do
+               {
+                 move_it_by_lines (it, 1, 1);
+               }
+             while (target_y >= line_bottom_y (it) && IT_CHARPOS (*it) < ZV);
            }
-         while (target_y >= line_bottom_y (it) && IT_CHARPOS (*it) < ZV);
 
          xassert (IT_CHARPOS (*it) >= BEGV);
        }
@@ -5427,7 +5511,7 @@ move_it_vertically_backward (it, dy)
    move backwards.  DY = 0 means move to start of screen line.  At the
    end, IT will be on the start of a screen line.  */
 
-void 
+void
 move_it_vertically (it, dy)
     struct it *it;
     int dy;
@@ -5457,7 +5541,7 @@ move_it_past_eol (it)
      struct it *it;
 {
   enum move_it_result rc;
-  
+
   rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
   if (rc == MOVE_NEWLINE_OR_CR)
     set_iterator_to_next (it, 0);
@@ -5477,7 +5561,7 @@ invisible_text_between_p (it, start_charpos, end_charpos)
 {
   Lisp_Object prop, limit;
   int invisible_found_p;
-  
+
   xassert (it != NULL && start_charpos <= end_charpos);
 
   /* Is text at START invisible?  */
@@ -5514,11 +5598,11 @@ move_it_by_lines (it, dvpos, need_y_p)
      int dvpos, need_y_p;
 {
   struct position pos;
-  
+
   if (!FRAME_WINDOW_P (it->f))
     {
       struct text_pos textpos;
-      
+
       /* We can use vmotion on frames without proportional fonts.  */
       pos = *vmotion (IT_CHARPOS (*it), dvpos, it->w);
       SET_TEXT_POS (textpos, pos.bufpos, pos.bytepos);
@@ -5538,11 +5622,11 @@ move_it_by_lines (it, dvpos, need_y_p)
     {
       struct it it2;
       int start_charpos, i;
-      
+
       /* Start at the beginning of the screen line containing IT's
         position.  */
       move_it_vertically_backward (it, 0);
-      
+
       /* Go back -DVPOS visible lines and reseat the iterator there.  */
       start_charpos = IT_CHARPOS (*it);
       for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i)
@@ -5568,6 +5652,16 @@ move_it_by_lines (it, dvpos, need_y_p)
     }
 }
 
+/* Return 1 if IT points into the middle of a display vector.  */
+
+int
+in_display_vector_p (it)
+     struct it *it;
+{
+  return (it->method == next_element_from_display_vector
+         && it->current.dpvec_index > 0
+         && it->dpvec + it->current.dpvec_index != it->dpend);
+}
 
 \f
 /***********************************************************************
@@ -5597,16 +5691,16 @@ add_to_log (format, arg1, arg2)
 
   fmt = msg = Qnil;
   GCPRO4 (fmt, msg, arg1, arg2);
-  
+
   args[0] = fmt = build_string (format);
   args[1] = arg1;
   args[2] = arg2;
   msg = Fformat (3, args);
 
-  len = STRING_BYTES (XSTRING (msg)) + 1;
+  len = SBYTES (msg) + 1;
   buffer = (char *) alloca (len);
-  bcopy (XSTRING (msg)->data, buffer, len);
-  
+  bcopy (SDATA (msg), buffer, len);
+
   message_dolog (buffer, len - 1, 1, 0);
   UNGCPRO;
 }
@@ -5630,9 +5724,12 @@ message_log_maybe_newline ()
 
 void
 message_dolog (m, nbytes, nlflag, multibyte)
-     char *m;
+     const char *m;
      int nbytes, nlflag, multibyte;
 {
+  if (!NILP (Vmemory_full))
+    return;
+
   if (!NILP (Vmessage_log_max))
     {
       struct buffer *oldbuf;
@@ -5674,10 +5771,10 @@ message_dolog (m, nbytes, nlflag, multibyte)
        {
          int i, c, char_bytes;
          unsigned char work[1];
-         
+
          /* Convert a multibyte string to single-byte
             for the *Message* buffer.  */
-         for (i = 0; i < nbytes; i += nbytes)
+         for (i = 0; i < nbytes; i += char_bytes)
            {
              c = string_char_and_length (m + i, nbytes - i, &char_bytes);
              work[0] = (SINGLE_BYTE_CHAR_P (c)
@@ -5841,7 +5938,7 @@ message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
 
 void
 message2 (m, nbytes, multibyte)
-     char *m;
+     const char *m;
      int nbytes;
      int multibyte;
 {
@@ -5857,8 +5954,8 @@ message2 (m, nbytes, multibyte)
 
 void
 message2_nolog (m, nbytes, multibyte)
-     char *m;
-     int nbytes;
+     const char *m;
+     int nbytes, multibyte;
 {
   struct frame *sf = SELECTED_FRAME ();
   message_enable_multibyte = multibyte;
@@ -5877,7 +5974,7 @@ message2_nolog (m, nbytes, multibyte)
   /* A null message buffer means that the frame hasn't really been
      initialized yet.  Error messages get reported properly by
      cmd_error, so this must be just an informative message; toss it.  */
-  else if (INTERACTIVE 
+  else if (INTERACTIVE
           && sf->glyphs_initialized_p
           && FRAME_MESSAGE_BUF (sf))
     {
@@ -5926,11 +6023,11 @@ message3 (m, nbytes, multibyte)
   struct gcpro gcpro1;
 
   GCPRO1 (m);
-  
+
   /* First flush out any partial line written with print.  */
   message_log_maybe_newline ();
   if (STRINGP (m))
-    message_dolog (XSTRING (m)->data, nbytes, 1, multibyte);
+    message_dolog (SDATA (m), nbytes, 1, multibyte);
   message3_nolog (m, nbytes, multibyte);
 
   UNGCPRO;
@@ -5953,7 +6050,7 @@ message3_nolog (m, nbytes, multibyte)
        putc ('\n', stderr);
       noninteractive_need_newline = 0;
       if (STRINGP (m))
-       fwrite (XSTRING (m)->data, nbytes, 1, stderr);
+       fwrite (SDATA (m), nbytes, 1, stderr);
       if (cursor_in_echo_area == 0)
        fprintf (stderr, "\n");
       fflush (stderr);
@@ -5961,7 +6058,7 @@ message3_nolog (m, nbytes, multibyte)
   /* A null message buffer means that the frame hasn't really been
      initialized yet.  Error messages get reported properly by
      cmd_error, so this must be just an informative message; toss it.  */
-  else if (INTERACTIVE 
+  else if (INTERACTIVE
           && sf->glyphs_initialized_p
           && FRAME_MESSAGE_BUF (sf))
     {
@@ -5980,7 +6077,7 @@ message3_nolog (m, nbytes, multibyte)
          && !FRAME_VISIBLE_P (f))
        Fmake_frame_visible (frame);
 
-      if (STRINGP (m) && XSTRING (m)->size)
+      if (STRINGP (m) && SCHARS (m) > 0)
        {
          set_message (NULL, m, nbytes, multibyte);
          if (minibuffer_auto_raise)
@@ -6032,6 +6129,8 @@ message_with_string (m, string, log)
      Lisp_Object string;
      int log;
 {
+  CHECK_STRING (string);
+
   if (noninteractive)
     {
       if (m)
@@ -6039,7 +6138,7 @@ message_with_string (m, string, log)
          if (noninteractive_need_newline)
            putc ('\n', stderr);
          noninteractive_need_newline = 0;
-         fprintf (stderr, m, XSTRING (string)->data);
+         fprintf (stderr, m, SDATA (string));
          if (cursor_in_echo_area == 0)
            fprintf (stderr, "\n");
          fflush (stderr);
@@ -6063,19 +6162,22 @@ message_with_string (m, string, log)
         cmd_error, so this must be just an informative message; toss it.  */
       if (FRAME_MESSAGE_BUF (f))
        {
-         int len;
-         char *a[1];
-         a[0] = (char *) XSTRING (string)->data;
+         Lisp_Object args[2], message;
+         struct gcpro gcpro1, gcpro2;
+
+         args[0] = build_string (m);
+         args[1] = message = string;
+         GCPRO2 (args[0], message);
+         gcpro1.nvars = 2;
 
-         len = doprnt (FRAME_MESSAGE_BUF (f),
-                       FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
+         message = Fformat (2, args);
 
          if (log)
-           message2 (FRAME_MESSAGE_BUF (f), len,
-                     STRING_MULTIBYTE (string));
+           message3 (message, SBYTES (message), STRING_MULTIBYTE (message));
          else
-           message2_nolog (FRAME_MESSAGE_BUF (f), len,
-                           STRING_MULTIBYTE (string));
+           message3_nolog (message, SBYTES (message), STRING_MULTIBYTE (message));
+
+         UNGCPRO;
 
          /* Print should start at the beginning of the message
             buffer next time.  */
@@ -6182,14 +6284,14 @@ update_echo_area ()
     {
       Lisp_Object string;
       string = Fcurrent_message ();
-      message3 (string, XSTRING (string)->size, 
+      message3 (string, SBYTES (string),
                !NILP (current_buffer->enable_multibyte_characters));
     }
 }
 
 
-/* Make sure echo area buffers in echo_buffers[] are life.  If they
-   aren't, make new ones.  */
+/* Make sure echo area buffers in `echo_buffers' are live.
+   If they aren't, make new ones.  */
 
 static void
 ensure_echo_area_buffers ()
@@ -6243,13 +6345,13 @@ with_echo_area_buffer (w, which, fn, a1, a2, a3, a4)
 {
   Lisp_Object buffer;
   int this_one, the_other, clear_buffer_p, rc;
-  int count = BINDING_STACK_SIZE ();
+  int count = SPECPDL_INDEX ();
 
-  /* If buffers aren't life, make new ones.  */
+  /* If buffers aren't live, make new ones.  */
   ensure_echo_area_buffers ();
 
   clear_buffer_p = 0;
-  
+
   if (which == 0)
     this_one = 0, the_other = 1;
   else if (which > 0)
@@ -6258,7 +6360,7 @@ with_echo_area_buffer (w, which, fn, a1, a2, a3, a4)
     {
       this_one = 0, the_other = 1;
       clear_buffer_p = 1;
-      
+
       /* We need a fresh one in case the current echo buffer equals
         the one containing the last displayed echo area message.  */
       if (!NILP (echo_area_buffer[this_one])
@@ -6336,14 +6438,14 @@ with_echo_area_buffer_unwind_data (w)
      Vwith_echo_area_save_vector.  */
   vector = Vwith_echo_area_save_vector;
   Vwith_echo_area_save_vector = Qnil;
-  
+
   if (NILP (vector))
     vector = Fmake_vector (make_number (7), Qnil);
-  
+
   XSETBUFFER (AREF (vector, i), current_buffer); ++i;
   AREF (vector, i) = Vdeactivate_mark, ++i;
   AREF (vector, i) = make_number (windows_or_buffers_changed), ++i;
-  
+
   if (w)
     {
       XSETWINDOW (AREF (vector, i), w); ++i;
@@ -6378,12 +6480,12 @@ unwind_with_echo_area_buffer (vector)
     {
       struct window *w;
       Lisp_Object buffer, charpos, bytepos;
-      
+
       w = XWINDOW (AREF (vector, 3));
       buffer = AREF (vector, 4);
       charpos = AREF (vector, 5);
       bytepos = AREF (vector, 6);
-      
+
       w->buffer = buffer;
       set_marker_both (w->pointm, buffer,
                       XFASTINT (charpos), XFASTINT (bytepos));
@@ -6401,6 +6503,10 @@ void
 setup_echo_area_for_printing (multibyte_p)
      int multibyte_p;
 {
+  /* If we can't find an echo area any more, exit.  */
+  if (! FRAME_LIVE_P (XFRAME (selected_frame)))
+    Fkill_emacs (Qnil);
+
   ensure_echo_area_buffers ();
 
   if (!message_buf_print)
@@ -6408,18 +6514,19 @@ setup_echo_area_for_printing (multibyte_p)
       /* A message has been output since the last time we printed.
         Choose a fresh echo area buffer.  */
       if (EQ (echo_area_buffer[1], echo_buffer[0]))
-       echo_area_buffer[0] = echo_buffer[1]; 
+       echo_area_buffer[0] = echo_buffer[1];
       else
        echo_area_buffer[0] = echo_buffer[0];
 
       /* Switch to that buffer and clear it.  */
       set_buffer_internal (XBUFFER (echo_area_buffer[0]));
       current_buffer->truncate_lines = Qnil;
-      
+
       if (Z > BEG)
        {
-         int count = BINDING_STACK_SIZE ();
+         int count = SPECPDL_INDEX ();
          specbind (Qinhibit_read_only, Qt);
+         /* Note that undo recording is always disabled.  */
          del_range (BEG, Z);
          unbind_to (count, Qnil);
        }
@@ -6447,11 +6554,11 @@ setup_echo_area_for_printing (multibyte_p)
       if (NILP (echo_area_buffer[0]))
        {
          if (EQ (echo_area_buffer[1], echo_buffer[0]))
-           echo_area_buffer[0] = echo_buffer[1]; 
+           echo_area_buffer[0] = echo_buffer[1];
          else
            echo_area_buffer[0] = echo_buffer[0];
        }
-      
+
       if (current_buffer != XBUFFER (echo_area_buffer[0]))
        {
          /* Someone switched buffers between print requests.  */
@@ -6486,7 +6593,7 @@ display_echo_area (w)
      with_echo_area_buffer will sets it to an empty buffer.  */
   i = display_last_displayed_message_p ? 1 : 0;
   no_message_p = NILP (echo_area_buffer[i]);
-  
+
   window_height_changed_p
     = with_echo_area_buffer (w, display_last_displayed_message_p,
                             display_echo_area_1,
@@ -6549,7 +6656,7 @@ resize_echo_area_exactly ()
        resize_exactly = Qt;
       else
        resize_exactly = Qnil;
-      
+
       resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
                                         (EMACS_INT) w, resize_exactly, 0, 0);
       if (resized_p)
@@ -6601,12 +6708,12 @@ resize_mini_window (w, exact_p)
      functions with safe_call which binds inhibit-redisplay to t.  */
   if (!NILP (Vinhibit_redisplay))
     return 0;
-  
+
   /* Nil means don't try to resize.  */
   if (NILP (Vresize_mini_windows)
       || (FRAME_X_P (f) && f->output_data.x == NULL))
     return 0;
-  
+
   if (!FRAME_MINIBUF_ONLY_P (f))
     {
       struct it it;
@@ -6632,11 +6739,11 @@ resize_mini_window (w, exact_p)
        max_height = XINT (Vmax_mini_window_height);
       else
        max_height = total_height / 4;
-      
+
       /* Correct that max. height if it's bogus.  */
       max_height = max (1, max_height);
       max_height = min (total_height, max_height);
-      
+
       /* Find out the height of the text in the window.  */
       if (it.truncate_lines_p)
        height = 1;
@@ -6651,7 +6758,7 @@ resize_mini_window (w, exact_p)
          height -= it.extra_line_spacing;
          height = (height + unit - 1) / unit;
        }
-      
+
       /* Compute a suitable window start.  */
       if (height > max_height)
        {
@@ -6684,7 +6791,7 @@ resize_mini_window (w, exact_p)
              window_height_changed_p = XFASTINT (w->height) != old_height;
            }
        }
-      else 
+      else
        {
          /* Always resize to exact size needed.  */
          if (height > XFASTINT (w->height))
@@ -6705,7 +6812,7 @@ resize_mini_window (w, exact_p)
                  freeze_window_starts (f, 1);
                  grow_mini_window (w, height - XFASTINT (w->height));
                }
-             
+
              window_height_changed_p = XFASTINT (w->height) != old_height;
            }
        }
@@ -6735,7 +6842,7 @@ current_message ()
       if (NILP (msg))
        echo_area_buffer[0] = Qnil;
     }
-  
+
   return msg;
 }
 
@@ -6747,7 +6854,7 @@ current_message_1 (a1, a2, a3, a4)
      EMACS_INT a3, a4;
 {
   Lisp_Object *msg = (Lisp_Object *) a1;
-  
+
   if (Z > BEG)
     *msg = make_buffer_string (BEG, Z, 1);
   else
@@ -6771,33 +6878,32 @@ push_message ()
 }
 
 
-/* Handler for record_unwind_protect calling pop_message.  */
+/* Restore message display from the top of Vmessage_stack.  */
 
-Lisp_Object
-push_message_unwind (dummy)
-     Lisp_Object dummy;
-{
-  pop_message ();
-  return Qnil;
-}
-
-
-/* Restore message display from the top of Vmessage_stack.  */
-
-void
-restore_message ()
+void
+restore_message ()
 {
   Lisp_Object msg;
-  
+
   xassert (CONSP (Vmessage_stack));
   msg = XCAR (Vmessage_stack);
   if (STRINGP (msg))
-    message3_nolog (msg, STRING_BYTES (XSTRING (msg)), STRING_MULTIBYTE (msg));
+    message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg));
   else
     message3_nolog (msg, 0, 0);
 }
 
 
+/* Handler for record_unwind_protect calling pop_message.  */
+
+Lisp_Object
+pop_message_unwind (dummy)
+     Lisp_Object dummy;
+{
+  pop_message ();
+  return Qnil;
+}
+
 /* Pop the top-most entry off Vmessage_stack.  */
 
 void
@@ -6872,14 +6978,14 @@ truncate_message_1 (nchars, a2, a3, a4)
 
 void
 set_message (s, string, nbytes, multibyte_p)
-     char *s;
+     const char *s;
      Lisp_Object string;
-     int nbytes;
+     int nbytes, multibyte_p;
 {
   message_enable_multibyte
     = ((s && multibyte_p)
        || (STRINGP (string) && STRING_MULTIBYTE (string)));
-  
+
   with_echo_area_buffer (0, -1, set_message_1,
                         (EMACS_INT) s, string, nbytes, multibyte_p);
   message_buf_print = 0;
@@ -6898,29 +7004,29 @@ set_message_1 (a1, a2, nbytes, multibyte_p)
      Lisp_Object a2;
      EMACS_INT nbytes, multibyte_p;
 {
-  char *s = (char *) a1;
+  const char *s = (const char *) a1;
   Lisp_Object string = a2;
-  
+
   xassert (BEG == Z);
-  
+
   /* Change multibyteness of the echo buffer appropriately.  */
   if (message_enable_multibyte
       != !NILP (current_buffer->enable_multibyte_characters))
     Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
 
   current_buffer->truncate_lines = message_truncate_lines ? Qt : Qnil;
-  
+
   /* Insert new message at BEG.  */
   TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
 
   if (STRINGP (string))
     {
       int nchars;
-      
+
       if (nbytes == 0)
-       nbytes = XSTRING (string)->size_byte;
+       nbytes = SBYTES (string);
       nchars = string_byte_to_char (string, nbytes);
-      
+
       /* This function takes care of single/multibyte conversion.  We
          just have to ensure that the echo area buffer has the right
          setting of enable_multibyte_characters.  */
@@ -6930,13 +7036,13 @@ set_message_1 (a1, a2, nbytes, multibyte_p)
     {
       if (nbytes == 0)
        nbytes = strlen (s);
-      
+
       if (multibyte_p && NILP (current_buffer->enable_multibyte_characters))
        {
          /* Convert from multi-byte to single-byte.  */
          int i, c, n;
          unsigned char work[1];
-         
+
          /* Convert a multibyte string to single-byte.  */
          for (i = 0; i < nbytes; i += n)
            {
@@ -6952,9 +7058,9 @@ set_message_1 (a1, a2, nbytes, multibyte_p)
        {
          /* Convert from single-byte to multi-byte.  */
          int i, c, n;
-         unsigned char *msg = (unsigned char *) s;
+         const unsigned char *msg = (const unsigned char *) s;
          unsigned char str[MAX_MULTIBYTE_LENGTH];
-      
+
          /* Convert a single-byte string to multibyte.  */
          for (i = 0; i < nbytes; i++)
            {
@@ -6984,10 +7090,10 @@ clear_message (current_p, last_displayed_p)
       echo_area_buffer[0] = Qnil;
       message_cleared_p = 1;
     }
-  
+
   if (last_displayed_p)
     echo_area_buffer[1] = Qnil;
-  
+
   message_buf_print = 0;
 }
 
@@ -7006,23 +7112,26 @@ clear_garbaged_frames ()
   if (frame_garbaged)
     {
       Lisp_Object tail, frame;
-      
+      int changed_count = 0;
+
       FOR_EACH_FRAME (tail, frame)
        {
          struct frame *f = XFRAME (frame);
-         
+
          if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
            {
              if (f->resized_p)
                Fredraw_frame (frame);
              clear_current_matrices (f);
+             changed_count++;
              f->garbaged = 0;
              f->resized_p = 0;
            }
        }
 
       frame_garbaged = 0;
-      ++windows_or_buffers_changed;
+      if (changed_count)
+       ++windows_or_buffers_changed;
     }
 }
 
@@ -7050,12 +7159,12 @@ echo_area_display (update_frame_p)
     return 0;
 
 /* The terminal frame is used as the first Emacs frame on the Mac OS.  */
-#ifndef macintosh
+#ifndef MAC_OS8
 #ifdef HAVE_WINDOW_SYSTEM
   /* When Emacs starts, selected_frame may be a visible terminal
      frame, even if we run under a window system.  If we let this
      through, a message would be displayed on the terminal.  */
-  if (EQ (selected_frame, Vterminal_frame) 
+  if (EQ (selected_frame, Vterminal_frame)
       && !NILP (Vwindow_system))
     return 0;
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -7086,7 +7195,7 @@ echo_area_display (update_frame_p)
             garbaged.  This looks odd, so we prevent it here.  */
          if (!display_completed)
            n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), 0);
-           
+
          if (window_height_changed_p
              /* Don't do this if Emacs is shutting down.  Redisplay
                 needs to run hooks.  */
@@ -7095,7 +7204,7 @@ echo_area_display (update_frame_p)
              /* Must update other windows.  Likewise as in other
                 cases, don't let this update be interrupted by
                 pending input.  */
-             int count = BINDING_STACK_SIZE ();
+             int count = SPECPDL_INDEX ();
              specbind (Qredisplay_dont_pause, Qt);
              windows_or_buffers_changed = 1;
              redisplay_internal (0);
@@ -7124,7 +7233,7 @@ echo_area_display (update_frame_p)
 
   /* Last displayed message is now the current message.  */
   echo_area_buffer[1] = echo_area_buffer[0];
-      
+
   /* Prevent redisplay optimization in redisplay_internal by resetting
      this_line_start_pos.  This is done because the mini-buffer now
      displays the message instead of its buffer text.  */
@@ -7141,7 +7250,8 @@ echo_area_display (update_frame_p)
  ***********************************************************************/
 
 
-#ifdef HAVE_WINDOW_SYSTEM
+/* The frame title buffering code is also used by Fformat_mode_line.
+   So it is not conditioned by HAVE_WINDOW_SYSTEM.  */
 
 /* A buffer for constructing frame titles in it; allocated from the
    heap in init_xdisp and resized as needed in store_frame_title_char.  */
@@ -7158,8 +7268,12 @@ static char *frame_title_ptr;
    Re-allocate frame_title_buf if necessary.  */
 
 static void
+#ifdef PROTOTYPES
+store_frame_title_char (char c)
+#else
 store_frame_title_char (c)
     char c;
+#endif
 {
   /* If output position has reached the end of the allocated buffer,
      double the buffer's size.  */
@@ -7186,7 +7300,7 @@ store_frame_title_char (c)
 
 static int
 store_frame_title (str, field_width, precision)
-     unsigned char *str;
+     const unsigned char *str;
      int field_width, precision;
 {
   int n = 0;
@@ -7209,6 +7323,7 @@ store_frame_title (str, field_width, precision)
   return n;
 }
 
+#ifdef HAVE_WINDOW_SYSTEM
 
 /* Set the title of FRAME, if it has changed.  The title format is
    Vicon_title_format if FRAME is iconified, otherwise it is
@@ -7236,7 +7351,7 @@ x_consider_frame_title (frame)
          Lisp_Object other_frame = XCAR (tail);
          struct frame *tf = XFRAME (other_frame);
 
-         if (tf != f 
+         if (tf != f
              && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
              && !FRAME_MINIBUF_ONLY_P (tf)
              && !EQ (other_frame, tip_frame)
@@ -7256,7 +7371,7 @@ x_consider_frame_title (frame)
       frame_title_ptr = frame_title_buf;
       init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
                     NULL, DEFAULT_FACE_ID);
-      display_mode_element (&it, 0, -1, -1, fmt, Qnil);
+      display_mode_element (&it, 0, -1, -1, fmt, Qnil, 0);
       len = frame_title_ptr - frame_title_buf;
       frame_title_ptr = NULL;
       set_buffer_internal_1 (obuf);
@@ -7266,18 +7381,13 @@ x_consider_frame_title (frame)
         already wasted too much time by walking through the list with
         display_mode_element, then we might need to optimize at a
         higher level than this.)  */
-      if (! STRINGP (f->name) 
-         || STRING_BYTES (XSTRING (f->name)) != len
-         || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
+      if (! STRINGP (f->name)
+         || SBYTES (f->name) != len
+         || bcmp (frame_title_buf, SDATA (f->name), len) != 0)
        x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
     }
 }
 
-#else /* not HAVE_WINDOW_SYSTEM */
-
-#define frame_title_ptr ((char *)0)
-#define store_frame_title(str, mincol, maxcol) 0
-
 #endif /* not HAVE_WINDOW_SYSTEM */
 
 
@@ -7325,13 +7435,13 @@ prepare_menu_bars ()
 
   /* Update the menu bar item lists, if appropriate.  This has to be
      done before any actual redisplay or generation of display lines.  */
-  all_windows = (update_mode_lines 
+  all_windows = (update_mode_lines
                 || buffer_shared > 1
                 || windows_or_buffers_changed);
   if (all_windows)
     {
       Lisp_Object tail, frame;
-      int count = BINDING_STACK_SIZE ();
+      int count = SPECPDL_INDEX ();
 
       record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
 
@@ -7342,18 +7452,18 @@ prepare_menu_bars ()
          /* Ignore tooltip frame.  */
          if (EQ (frame, tooltip_frame))
            continue;
-         
+
          /* If a window on this frame changed size, report that to
             the user and clear the size-change flag.  */
          if (FRAME_WINDOW_SIZES_CHANGED (f))
            {
              Lisp_Object functions;
-             
+
              /* Clear flag first in case we get an error below.  */
              FRAME_WINDOW_SIZES_CHANGED (f) = 0;
              functions = Vwindow_size_change_functions;
              GCPRO2 (tail, functions);
-             
+
              while (CONSP (functions))
                {
                  call1 (XCAR (functions), frame);
@@ -7361,7 +7471,7 @@ prepare_menu_bars ()
                }
              UNGCPRO;
            }
-         
+
          GCPRO1 (tail);
          update_menu_bar (f, 0);
 #ifdef HAVE_WINDOW_SYSTEM
@@ -7411,14 +7521,21 @@ update_menu_bar (f, save_match_data)
 
   window = FRAME_SELECTED_WINDOW (f);
   w = XWINDOW (window);
-  
+
+#if 0 /* The if statement below this if statement used to include the
+         condition !NILP (w->update_mode_line), rather than using
+         update_mode_lines directly, and this if statement may have
+         been added to make that condition work.  Now the if
+         statement below matches its comment, this isn't needed.  */
   if (update_mode_lines)
     w->update_mode_line = Qt;
+#endif
 
   if (FRAME_WINDOW_P (f)
       ?
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
-      FRAME_EXTERNAL_MENU_BAR (f) 
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+    || defined (USE_GTK)
+      FRAME_EXTERNAL_MENU_BAR (f)
 #else
       FRAME_MENU_BAR_LINES (f) > 0
 #endif
@@ -7432,7 +7549,9 @@ update_menu_bar (f, save_match_data)
         the rest of the redisplay algorithm is about the same as
         windows_or_buffers_changed anyway.  */
       if (windows_or_buffers_changed
-         || !NILP (w->update_mode_line)
+         /* This used to test w->update_mode_line, but we believe
+            there is no need to recompute the menu in that case.  */
+         || update_mode_lines
          || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
               < BUF_MODIFF (XBUFFER (w->buffer)))
              != !NILP (w->last_had_star))
@@ -7441,7 +7560,7 @@ update_menu_bar (f, save_match_data)
              != !NILP (w->region_showing)))
        {
          struct buffer *prev = current_buffer;
-         int count = BINDING_STACK_SIZE ();
+         int count = SPECPDL_INDEX ();
 
          specbind (Qinhibit_menubar_update, Qt);
 
@@ -7456,19 +7575,20 @@ update_menu_bar (f, save_match_data)
 
          /* Run the Lucid hook.  */
          safe_run_hooks (Qactivate_menubar_hook);
-         
+
          /* If it has changed current-menubar from previous value,
             really recompute the menu-bar from the value.  */
          if (! NILP (Vlucid_menu_bar_dirty_flag))
            call0 (Qrecompute_lucid_menubar);
-         
+
          safe_run_hooks (Qmenu_bar_update_hook);
          FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
-         
+
          /* Redisplay the menu bar in case we changed it.  */
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+    || defined (USE_GTK)
          if (FRAME_WINDOW_P (f)
-#if defined (macintosh)
+#if defined (MAC_OS)
               /* All frames on Mac OS share the same menubar.  So only the
                  selected frame should be allowed to set it.  */
               && f == SELECTED_FRAME ()
@@ -7479,11 +7599,11 @@ update_menu_bar (f, save_match_data)
            /* On a terminal screen, the menu bar is an ordinary screen
               line, and this makes it get updated.  */
            w->update_mode_line = Qt;
-#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
+#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */
          /* In the non-toolkit version, the menu bar is an ordinary screen
             line, and this makes it get updated.  */
          w->update_mode_line = Qt;
-#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
+#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */
 
          unbind_to (count, Qnil);
          set_buffer_internal_1 (prev);
@@ -7509,15 +7629,21 @@ update_tool_bar (f, save_match_data)
      struct frame *f;
      int save_match_data;
 {
-  if (WINDOWP (f->tool_bar_window)
-      && XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0)
+#ifdef USE_GTK
+  int do_update = FRAME_EXTERNAL_TOOL_BAR(f);
+#else
+  int do_update = WINDOWP (f->tool_bar_window)
+    && XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0;
+#endif
+
+  if (do_update)
     {
       Lisp_Object window;
       struct window *w;
 
       window = FRAME_SELECTED_WINDOW (f);
       w = XWINDOW (window);
-  
+
       /* If the user has switched buffers or windows, we need to
         recompute to reflect the new bindings.  But we'll
         recompute when update_mode_lines is set too; that means
@@ -7535,7 +7661,7 @@ update_tool_bar (f, save_match_data)
              != !NILP (w->region_showing)))
        {
          struct buffer *prev = current_buffer;
-         int count = BINDING_STACK_SIZE ();
+         int count = SPECPDL_INDEX ();
 
          /* Set current_buffer to the buffer of the selected
             window of the frame, so that we get the right local
@@ -7556,7 +7682,7 @@ update_tool_bar (f, save_match_data)
          /* Build desired tool-bar items from keymaps.  */
          f->tool_bar_items
            = tool_bar_items (f->tool_bar_items, &f->n_tool_bar_items);
-         
+
          /* Redisplay the tool-bar in case we changed it.  */
          w->update_mode_line = Qt;
 
@@ -7584,15 +7710,15 @@ build_desired_tool_bar_string (f)
 
   /* Prepare F->desired_tool_bar_string.  If we can reuse it, do so.
      Otherwise, make a new string.  */
-  
+
   /* The size of the string we might be able to reuse.  */
   size = (STRINGP (f->desired_tool_bar_string)
-         ? XSTRING (f->desired_tool_bar_string)->size
+         ? SCHARS (f->desired_tool_bar_string)
          : 0);
 
   /* We need one space in the string for each image.  */
   size_needed = f->n_tool_bar_items;
-  
+
   /* Reuse f->desired_tool_bar_string, if possible.  */
   if (size < size_needed || NILP (f->desired_tool_bar_string))
     f->desired_tool_bar_string = Fmake_string (make_number (size_needed),
@@ -7629,7 +7755,7 @@ build_desired_tool_bar_string (f)
            idx = (selected_p
                   ? TOOL_BAR_IMAGE_DISABLED_SELECTED
                   : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
-         
+
          xassert (ASIZE (image) >= idx);
          image = AREF (image, idx);
        }
@@ -7660,12 +7786,12 @@ build_desired_tool_bar_string (f)
          if (INTEGERP (XCAR (Vtool_bar_button_margin))
              && XINT (XCAR (Vtool_bar_button_margin)) > 0)
            hmargin += XFASTINT (XCAR (Vtool_bar_button_margin));
-         
+
          if (INTEGERP (XCDR (Vtool_bar_button_margin))
              && XINT (XCDR (Vtool_bar_button_margin)) > 0)
            vmargin += XFASTINT (XCDR (Vtool_bar_button_margin));
        }
-      
+
       if (auto_raise_tool_bar_buttons_p)
        {
          /* Add a `:relief' property to the image spec if the item is
@@ -7700,13 +7826,13 @@ build_desired_tool_bar_string (f)
                                Fcons (make_number (hmargin),
                                       make_number (vmargin)));
        }
-         
+
       /* If button is not enabled, and we don't have special images
         for the disabled state, make the image appear disabled by
         applying an appropriate algorithm to it.  */
       if (!enabled_p && idx < 0)
        plist = Fplist_put (plist, QCconversion, Qdisabled);
-      
+
       /* Put a `display' text property on the string for the image to
         display.  Put a `menu-item' property on the string that gives
         the start of this item's properties in the tool-bar items
@@ -7719,7 +7845,7 @@ build_desired_tool_bar_string (f)
          string.  The string can be longer than needed when we reuse a
          previous string.  */
       if (i + 1 == f->n_tool_bar_items)
-       end = XSTRING (f->desired_tool_bar_string)->size;
+       end = SCHARS (f->desired_tool_bar_string);
       else
        end = i + 1;
       Fadd_text_properties (make_number (i), make_number (end),
@@ -7740,14 +7866,14 @@ display_tool_bar_line (it)
   struct glyph_row *row = it->glyph_row;
   int max_x = it->last_visible_x;
   struct glyph *last;
-  
+
   prepare_desired_row (row);
   row->y = it->current_y;
 
   /* Note that this isn't made use of if the face hasn't a box,
      so there's no need to check the face here.  */
   it->start_of_box_run_p = 1;
-  
+
   while (it->current_x < max_x)
     {
       int x_before, x, n_glyphs_before, i, nglyphs;
@@ -7767,7 +7893,7 @@ display_tool_bar_line (it)
       while (i < nglyphs)
        {
          struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
-         
+
          if (x + glyph->pixel_width > max_x)
            {
              /* Glyph doesn't fit on line.  */
@@ -7797,14 +7923,14 @@ display_tool_bar_line (it)
   if (last == row->glyphs[TEXT_AREA])
     last->left_box_line_p = 1;
   compute_line_metrics (it);
-  
+
   /* If line is empty, make it occupy the rest of the tool-bar.  */
   if (!row->displays_text_p)
     {
       row->height = row->phys_height = it->last_visible_y - row->y;
       row->ascent = row->phys_ascent = 0;
     }
-  
+
   row->full_width_p = 1;
   row->continued_p = 0;
   row->truncated_on_left_p = 0;
@@ -7826,7 +7952,7 @@ tool_bar_lines_needed (f)
 {
   struct window *w = XWINDOW (f->tool_bar_window);
   struct it it;
-  
+
   /* Initialize an iterator for iteration over
      F->desired_tool_bar_string in the tool-bar window of frame F.  */
   init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
@@ -7860,7 +7986,7 @@ DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
   else
     CHECK_FRAME (frame);
   f = XFRAME (frame);
-  
+
   if (WINDOWP (f->tool_bar_window)
       || (w = XWINDOW (f->tool_bar_window),
          XFASTINT (w->height) > 0))
@@ -7888,14 +8014,20 @@ redisplay_tool_bar (f)
   struct it it;
   struct glyph_row *row;
   int change_height_p = 0;
-  
+
+#ifdef USE_GTK
+  if (FRAME_EXTERNAL_TOOL_BAR(f))
+    update_frame_tool_bar (f);
+  return 0;
+#endif
+
   /* If frame hasn't a tool-bar window or if it is zero-height, don't
      do anything.  This means you must start with tool-bar-lines
      non-zero to get the auto-sizing effect.  Or in other words, you
      can turn off tool-bars by specifying tool-bar-lines zero.  */
   if (!WINDOWP (f->tool_bar_window)
       || (w = XWINDOW (f->tool_bar_window),
-         XFASTINT (w->height) == 0))
+          XFASTINT (w->height) == 0))
     return 0;
 
   /* Set up an iterator for the tool-bar window.  */
@@ -7925,7 +8057,7 @@ redisplay_tool_bar (f)
         height.  */
       if (IT_STRING_CHARPOS (it) < it.end_charpos)
        change_height_p = 1;
-      
+
       /* If there are blank lines at the end, except for a partially
         visible blank line at the end that is smaller than
         CANON_Y_UNIT, change the tool-bar's height.  */
@@ -7949,7 +8081,7 @@ redisplay_tool_bar (f)
          extern Lisp_Object Qtool_bar_lines;
          Lisp_Object frame;
          int old_height = XFASTINT (w->height);
-         
+
          XSETFRAME (frame, f);
          clear_glyph_matrix (w->desired_matrix);
          Fmodify_frame_parameters (frame,
@@ -7983,9 +8115,9 @@ tool_bar_item_info (f, glyph, prop_idx)
   /* This function can be called asynchronously, which means we must
      exclude any possibility that Fget_text_property signals an
      error.  */
-  charpos = min (XSTRING (f->current_tool_bar_string)->size, glyph->charpos);
+  charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
   charpos = max (0, charpos);
-  
+
   /* Get the text property `menu-item' at pos. The value of that
      property is the start index of this item's properties in
      F->tool_bar_items.  */
@@ -8001,7 +8133,282 @@ tool_bar_item_info (f, glyph, prop_idx)
 
   return success_p;
 }
-  
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
+
+\f
+/***********************************************************************
+                              Fringes
+ ***********************************************************************/
+
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* An arrow like this: `<-'.  */
+static unsigned char left_bits[] = {
+   0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
+
+/* Right truncation arrow bitmap `->'.  */
+static unsigned char right_bits[] = {
+   0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
+
+/* Marker for continued lines.  */
+static unsigned char continued_bits[] = {
+   0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
+
+/* Marker for continuation lines.  */
+static unsigned char continuation_bits[] = {
+   0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
+
+/* Overlay arrow bitmap.  A triangular arrow.  */
+static unsigned char ov_bits[] = {
+   0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
+
+/* Bitmap drawn to indicate lines not displaying text if
+   `indicate-empty-lines' is non-nil.  */
+static unsigned char zv_bits[] = {
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
+
+struct fringe_bitmap fringe_bitmaps[MAX_FRINGE_BITMAPS] =
+{
+  { 0, 0, 0, NULL /* NO_FRINGE_BITMAP */ },
+  { 8, sizeof (left_bits), 0, left_bits },
+  { 8, sizeof (right_bits), 0, right_bits },
+  { 8, sizeof (continued_bits), 0, continued_bits },
+  { 8, sizeof (continuation_bits), 0, continuation_bits },
+  { 8, sizeof (ov_bits), 0, ov_bits },
+  { 8, sizeof (zv_bits), 3, zv_bits }
+};
+
+
+/* Draw the bitmap WHICH in one of the left or right fringes of
+   window W.  ROW is the glyph row for which to display the bitmap; it
+   determines the vertical position at which the bitmap has to be
+   drawn.  */
+
+static void
+draw_fringe_bitmap (w, row, which, left_p)
+     struct window *w;
+     struct glyph_row *row;
+     enum fringe_bitmap_type which;
+     int left_p;
+{
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  struct draw_fringe_bitmap_params p;
+
+  /* Convert row to frame coordinates.  */
+  p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+
+  p.which = which;
+  p.wd = fringe_bitmaps[which].width;
+
+  p.h = fringe_bitmaps[which].height;
+  p.dh = (fringe_bitmaps[which].period
+         ? (p.y % fringe_bitmaps[which].period)
+         : 0);
+  p.h -= p.dh;
+  /* Clip bitmap if too high.  */
+  if (p.h > row->height)
+    p.h = row->height;
+
+  p.face = FACE_FROM_ID (f, FRINGE_FACE_ID);
+  PREPARE_FACE_FOR_DISPLAY (f, p.face);
+
+  /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
+     the fringe.  */
+  p.bx = -1;
+  if (left_p)
+    {
+      if (p.wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
+       p.wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
+      p.x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
+            - p.wd
+            - (FRAME_X_LEFT_FRINGE_WIDTH (f) - p.wd) / 2);
+      if (p.wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > p.h)
+       {
+         /* If W has a vertical border to its left, don't draw over it.  */
+         int border = ((XFASTINT (w->left) > 0
+                        && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+                       ? 1 : 0);
+         p.bx = (window_box_left (w, -1)
+                 - FRAME_X_LEFT_FRINGE_WIDTH (f)
+                 + border);
+         p.nx = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
+       }
+    }
+  else
+    {
+      if (p.wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
+       p.wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+      p.x = (window_box_right (w, -1)
+            + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - p.wd) / 2);
+      /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
+        the fringe.  */
+      if (p.wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > p.h)
+       {
+         p.bx = window_box_right (w, -1);
+         p.nx = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+       }
+    }
+
+  if (p.bx >= 0)
+    {
+      int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+
+      p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
+      p.ny = row->visible_height;
+    }
+
+  /* Adjust y to the offset in the row to start drawing the bitmap.  */
+  p.y += (row->height - p.h) / 2;
+
+  rif->draw_fringe_bitmap (w, row, &p);
+}
+
+/* Draw fringe bitmaps for glyph row ROW on window W.  Call this
+   function with input blocked.  */
+
+void
+draw_row_fringe_bitmaps (w, row)
+     struct window *w;
+     struct glyph_row *row;
+{
+  struct frame *f = XFRAME (w->frame);
+  enum fringe_bitmap_type bitmap;
+
+  xassert (interrupt_input_blocked);
+
+  /* If row is completely invisible, because of vscrolling, we
+     don't have to draw anything.  */
+  if (row->visible_height <= 0)
+    return;
+
+  if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
+    {
+      /* Decide which bitmap to draw in the left fringe.  */
+      if (row->overlay_arrow_p)
+       bitmap = OVERLAY_ARROW_BITMAP;
+      else if (row->truncated_on_left_p)
+       bitmap = LEFT_TRUNCATION_BITMAP;
+      else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
+       bitmap = CONTINUATION_LINE_BITMAP;
+      else if (row->indicate_empty_line_p)
+       bitmap = ZV_LINE_BITMAP;
+      else
+       bitmap = NO_FRINGE_BITMAP;
+
+      draw_fringe_bitmap (w, row, bitmap, 1);
+    }
+
+  if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
+    {
+      /* Decide which bitmap to draw in the right fringe.  */
+      if (row->truncated_on_right_p)
+       bitmap = RIGHT_TRUNCATION_BITMAP;
+      else if (row->continued_p)
+       bitmap = CONTINUED_LINE_BITMAP;
+      else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
+       bitmap = ZV_LINE_BITMAP;
+      else
+       bitmap = NO_FRINGE_BITMAP;
+
+      draw_fringe_bitmap (w, row, bitmap, 0);
+    }
+}
+
+
+/* Compute actual fringe widths */
+
+void
+compute_fringe_widths (f, redraw)
+     struct frame *f;
+     int redraw;
+{
+  int o_left = FRAME_X_LEFT_FRINGE_WIDTH (f);
+  int o_right = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+  int o_cols = FRAME_X_FRINGE_COLS (f);
+
+  Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
+  Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
+  int left_fringe_width, right_fringe_width;
+
+  if (!NILP (left_fringe))
+    left_fringe = Fcdr (left_fringe);
+  if (!NILP (right_fringe))
+    right_fringe = Fcdr (right_fringe);
+
+  left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
+                      XINT (left_fringe));
+  right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
+                       XINT (right_fringe));
+
+  if (left_fringe_width || right_fringe_width)
+    {
+      int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
+      int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
+      int conf_wid = left_wid + right_wid;
+      int font_wid = FONT_WIDTH (FRAME_FONT (f));
+      int cols = (left_wid + right_wid + font_wid-1) / font_wid;
+      int real_wid = cols * font_wid;
+      if (left_wid && right_wid)
+       {
+         if (left_fringe_width < 0)
+           {
+             /* Left fringe width is fixed, adjust right fringe if necessary */
+             FRAME_X_LEFT_FRINGE_WIDTH (f) = left_wid;
+             FRAME_X_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
+           }
+         else if (right_fringe_width < 0)
+           {
+             /* Right fringe width is fixed, adjust left fringe if necessary */
+             FRAME_X_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
+             FRAME_X_RIGHT_FRINGE_WIDTH (f) = right_wid;
+           }
+         else
+           {
+             /* Adjust both fringes with an equal amount.
+                Note that we are doing integer arithmetic here, so don't
+                lose a pixel if the total width is an odd number.  */
+             int fill = real_wid - conf_wid;
+             FRAME_X_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
+             FRAME_X_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
+           }
+       }
+      else if (left_fringe_width)
+       {
+         FRAME_X_LEFT_FRINGE_WIDTH (f) = real_wid;
+         FRAME_X_RIGHT_FRINGE_WIDTH (f) = 0;
+       }
+      else
+       {
+         FRAME_X_LEFT_FRINGE_WIDTH (f) = 0;
+         FRAME_X_RIGHT_FRINGE_WIDTH (f) = real_wid;
+       }
+      FRAME_X_FRINGE_COLS (f) = cols;
+      FRAME_X_FRINGE_WIDTH (f) = real_wid;
+    }
+  else
+    {
+      FRAME_X_LEFT_FRINGE_WIDTH (f) = 0;
+      FRAME_X_RIGHT_FRINGE_WIDTH (f) = 0;
+      FRAME_X_FRINGE_COLS (f) = 0;
+      FRAME_X_FRINGE_WIDTH (f) = 0;
+    }
+
+  if (redraw && FRAME_VISIBLE_P (f))
+    if (o_left != FRAME_X_LEFT_FRINGE_WIDTH (f) ||
+       o_right != FRAME_X_RIGHT_FRINGE_WIDTH (f) ||
+       o_cols != FRAME_X_FRINGE_COLS (f))
+      redraw_frame (f);
+}
+
 #endif /* HAVE_WINDOW_SYSTEM */
 
 
@@ -8165,7 +8572,7 @@ hscroll_windows (window)
      Lisp_Object window;
 {
   int hscrolled_p;
-  
+
   if (automatic_hscrolling_p)
     {
       hscrolled_p = hscroll_window_tree (window);
@@ -8230,7 +8637,7 @@ debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
       method[len] = '|';
       --remaining, ++len;
     }
-  
+
   strncpy (method + len, buffer, remaining);
 
   if (trace_redisplay_p)
@@ -8238,7 +8645,7 @@ debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
             w,
             ((BUFFERP (w->buffer)
               && STRINGP (XBUFFER (w->buffer)->name))
-             ? (char *) XSTRING (XBUFFER (w->buffer)->name)->data
+             ? (char *) SDATA (XBUFFER (w->buffer)->name)
              : "no buffer"),
             buffer);
 }
@@ -8246,23 +8653,6 @@ debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
 #endif /* GLYPH_DEBUG */
 
 
-/* This counter is used to clear the face cache every once in a while
-   in redisplay_internal.  It is incremented for each redisplay.
-   Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is
-   cleared.  */
-
-#define CLEAR_FACE_CACHE_COUNT 500
-static int clear_face_cache_count;
-
-/* Record the previous terminal frame we displayed.  */
-
-static struct frame *previous_terminal_frame;
-
-/* Non-zero while redisplay_internal is in progress.  */
-
-int redisplaying_p;
-
-
 /* Value is non-zero if all changes in window W, which displays
    current_buffer, are in the text between START and END.  START is a
    buffer position, END is given as a distance from Z.  Used in
@@ -8274,7 +8664,7 @@ text_outside_line_unchanged_p (w, start, end)
      int start, end;
 {
   int unchanged_p = 1;
-  
+
   /* If text or overlays have changed, see where.  */
   if (XFASTINT (w->last_modified) < MODIFF
       || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
@@ -8288,7 +8678,7 @@ text_outside_line_unchanged_p (w, start, end)
          && (BEG_UNCHANGED < start - 1
              || END_UNCHANGED < end))
        unchanged_p = 0;
-      
+
       /* If selective display, can't optimize if changes start at the
         beginning of the line.  */
       if (unchanged_p
@@ -8354,7 +8744,7 @@ check_point_in_composition (prev_buf, prev_pt, buf, pt)
       if (prev_pt == pt)
        /* Point didn't move.  */
        return 0;
-    
+
       if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
          && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
          && COMPOSITION_VALID_P (start, end, prop)
@@ -8380,9 +8770,7 @@ reconsider_clip_changes (w, b)
      struct window *w;
      struct buffer *b;
 {
-  if (b->prevent_redisplay_optimizations_p)
-    b->clip_changed = 1;
-  else if (b->clip_changed
+  if (b->clip_changed
           && !NILP (w->window_end_valid)
           && w->current_matrix->buffer == b
           && w->current_matrix->zv == BUF_ZV (b)
@@ -8412,6 +8800,14 @@ reconsider_clip_changes (w, b)
        b->clip_changed = 1;
     }
 }
+\f
+#define STOP_POLLING                                   \
+do { if (! polling_stopped_here) stop_polling ();      \
+       polling_stopped_here = 1; } while (0)
+
+#define RESUME_POLLING                                 \
+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
@@ -8432,11 +8828,12 @@ redisplay_internal (preserve_echo_area)
   int number_of_visible_frames;
   int count;
   struct frame *sf = SELECTED_FRAME ();
+  int polling_stopped_here = 0;
 
   /* Non-zero means redisplay has to consider all windows on all
      frames.  Zero means, only selected_window is considered.  */
   int consider_all_windows_p;
-  
+
   TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
 
   /* No redisplay if running in batch mode or frame is not yet fully
@@ -8457,7 +8854,7 @@ redisplay_internal (preserve_echo_area)
        return;
     }
 
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   if (popup_activated ())
     return;
 #endif
@@ -8468,10 +8865,11 @@ redisplay_internal (preserve_echo_area)
 
   /* Record a function that resets redisplaying_p to its old value
      when we leave this function.  */
-  count = BINDING_STACK_SIZE ();
+  count = SPECPDL_INDEX ();
   record_unwind_protect (unwind_redisplay, make_number (redisplaying_p));
   ++redisplaying_p;
-  
+  specbind (Qinhibit_free_realized_faces, Qnil);
+
  retry:
   pause = 0;
   reconsider_clip_changes (w, current_buffer);
@@ -8515,7 +8913,7 @@ redisplay_internal (preserve_echo_area)
     FOR_EACH_FRAME (tail, frame)
       {
        struct frame *f = XFRAME (frame);
-       
+
        FRAME_SAMPLE_VISIBILITY (f);
        if (FRAME_VISIBLE_P (f))
          ++number_of_visible_frames;
@@ -8551,15 +8949,17 @@ redisplay_internal (preserve_echo_area)
       && !(PT == XFASTINT (w->last_point)
           && XFASTINT (w->last_modified) >= MODIFF
           && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
-      && XFASTINT (w->column_number_displayed) != current_column ())
-    w->update_mode_line = Qt; 
+      && (XFASTINT (w->column_number_displayed)
+          != (int) current_column ()))  /* iftc */
+    w->update_mode_line = Qt;
 
   FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
 
   /* The variable buffer_shared is set in redisplay_window and
      indicates that we redisplay a buffer in different windows.  See
      there.  */
-  consider_all_windows_p = update_mode_lines || buffer_shared > 1;
+  consider_all_windows_p = (update_mode_lines || buffer_shared > 1
+                           || cursor_type_changed);
 
   /* If specs for an arrow have changed, do thorough redisplay
      to ensure we remove any arrow that should no longer exist.  */
@@ -8589,7 +8989,7 @@ redisplay_internal (preserve_echo_area)
         the echo area.  */
       if (!display_last_displayed_message_p)
        message_cleared_p = 0;
-      
+
       if (fonts_changed_p)
        goto retry;
       else if (window_height_changed_p)
@@ -8597,7 +8997,7 @@ redisplay_internal (preserve_echo_area)
          consider_all_windows_p = 1;
          ++update_mode_lines;
          ++windows_or_buffers_changed;
-         
+
          /* If window configuration was changed, frames may have been
             marked garbaged.  Clear them or we will experience
             surprises wrt scrolling.  */
@@ -8617,14 +9017,14 @@ redisplay_internal (preserve_echo_area)
       consider_all_windows_p = 1;
       ++windows_or_buffers_changed;
       ++update_mode_lines;
-      
+
       /* If window configuration was changed, frames may have been
         marked garbaged.  Clear them or we will experience
         surprises wrt scrolling.  */
       if (frame_garbaged)
        clear_garbaged_frames ();
     }
-  
+
 
   /* If showing the region, and mark has changed, we must redisplay
      the whole window.  The assignment to this_line_start_pos prevents
@@ -8647,12 +9047,14 @@ redisplay_internal (preserve_echo_area)
       && CHARPOS (tlbufpos) > 0
       && NILP (w->update_mode_line)
       && !current_buffer->clip_changed
+      && !current_buffer->prevent_redisplay_optimizations_p
       && FRAME_VISIBLE_P (XFRAME (w->frame))
       && !FRAME_OBSCURED_P (XFRAME (w->frame))
       /* Make sure recorded data applies to current buffer, etc.  */
       && this_line_buffer == current_buffer
       && current_buffer == XBUFFER (w->buffer)
       && NILP (w->force_start)
+      && NILP (w->optional_new_start)
       /* Point must be on the line that we have info recorded about.  */
       && PT >= CHARPOS (tlbufpos)
       && PT <= Z - CHARPOS (tlendpos)
@@ -8706,7 +9108,7 @@ redisplay_internal (preserve_echo_area)
 
          /* If line contains point, is not continued,
              and ends at same distance from eob as before, we win */
-         if (w->cursor.vpos >= 0 
+         if (w->cursor.vpos >= 0
               /* Line is not continued, otherwise this_line_start_pos
                  would have been set to 0 in display_line.  */
              && CHARPOS (this_line_start_pos)
@@ -8723,7 +9125,7 @@ redisplay_internal (preserve_echo_area)
                  struct glyph_row *row
                    = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
                  int delta, delta_bytes;
-  
+
                  if (Z - CHARPOS (tlendpos) == ZV)
                    {
                      /* This line ends at end of (accessible part of)
@@ -8747,7 +9149,7 @@ redisplay_internal (preserve_echo_area)
                                     - BYTEPOS (tlendpos)
                                     - MATRIX_ROW_START_BYTEPOS (row));
                    }
-  
+
                  increment_matrix_positions (w->current_matrix,
                                              this_line_vpos + 1,
                                              w->current_matrix->nrows,
@@ -8766,7 +9168,7 @@ redisplay_internal (preserve_echo_area)
                       && this_line_vpos > 0)
                XSETINT (w->window_end_vpos, this_line_vpos - 1);
              w->window_end_valid = Qnil;
-             
+
              /* Update hint: No need to try to scroll in update_window.  */
              w->desired_matrix->no_scrolling_p = 1;
 
@@ -8790,7 +9192,7 @@ redisplay_internal (preserve_echo_area)
            {
              do_pending_window_change (1);
 
-             /* We used to always goto end_of_redisplay here, but this 
+             /* We used to always goto end_of_redisplay here, but this
                 isn't enough if we have a blinking cursor.  */
              if (w->cursor_off_p == w->last_cursor_off_p)
                goto end_of_redisplay;
@@ -8818,7 +9220,7 @@ redisplay_internal (preserve_echo_area)
          it.current_x = this_line_start_x;
          it.current_y = this_line_y;
          it.vpos = this_line_vpos;
-         
+
          /* The call to move_it_to stops in front of PT, but
             moves over before-strings.  */
          move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
@@ -8849,7 +9251,7 @@ redisplay_internal (preserve_echo_area)
   consider_all_windows_p |= buffer_shared > 1;
   ++clear_face_cache_count;
 
-  
+
   /* Build desired matrices, and update the display.  If
      consider_all_windows_p is non-zero, do it for all windows on all
      frames.  Otherwise do it for selected_window, only.  */
@@ -8875,7 +9277,7 @@ redisplay_internal (preserve_echo_area)
       FOR_EACH_FRAME (tail, frame)
        {
          struct frame *f = XFRAME (frame);
-         
+
          if (FRAME_WINDOW_P (f) || f == sf)
            {
 #ifdef HAVE_WINDOW_SYSTEM
@@ -8898,9 +9300,11 @@ redisplay_internal (preserve_echo_area)
                judge_scroll_bars_hook (f);
 
              /* If fonts changed, display again.  */
+             /* ??? rms: I suspect it is a mistake to jump all the way
+                back to retry here.  It should just retry this frame.  */
              if (fonts_changed_p)
                goto retry;
-             
+
              if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
                {
                  /* See if we have to hscroll.  */
@@ -8913,7 +9317,7 @@ redisplay_internal (preserve_echo_area)
                     error.  */
                  if (interrupt_input)
                    unrequest_sigio ();
-                 stop_polling ();
+                 STOP_POLLING;
 
                  /* Update the display.  */
                  set_window_update_flags (XWINDOW (f->root_window), 1);
@@ -8928,7 +9332,7 @@ redisplay_internal (preserve_echo_area)
                      bcopy (updated, p, nbytes);
                      size *= 2;
                    }
-                 
+
                  updated[n++] = f;
                }
            }
@@ -8951,12 +9355,15 @@ redisplay_internal (preserve_echo_area)
       struct frame *mini_frame;
 
       displayed_buffer = XBUFFER (XWINDOW (selected_window)->buffer);
-      internal_condition_case_1 (redisplay_window_1, selected_window, Qerror,
+      /* Use list_of_error, not Qerror, so that
+        we catch only errors and don't run the debugger.  */
+      internal_condition_case_1 (redisplay_window_1, selected_window,
+                                list_of_error,
                                 redisplay_window_error);
-  
+
       /* Compare desired and current matrices, perform output.  */
+
     update:
-  
       /* If fonts changed, display again.  */
       if (fonts_changed_p)
        goto retry;
@@ -8966,13 +9373,13 @@ redisplay_internal (preserve_echo_area)
         which can cause an apparent I/O error.  */
       if (interrupt_input)
        unrequest_sigio ();
-      stop_polling ();
+      STOP_POLLING;
 
       if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
        {
          if (hscroll_windows (selected_window))
            goto retry;
-         
+
          XWINDOW (selected_window)->must_be_updated_p = 1;
          pause = update_frame (sf, 0, 0);
        }
@@ -8984,7 +9391,7 @@ redisplay_internal (preserve_echo_area)
         it here.  */
       mini_window = FRAME_MINIBUF_WINDOW (sf);
       mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
-       
+
       if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
        {
          XWINDOW (mini_window)->must_be_updated_p = 1;
@@ -9009,7 +9416,7 @@ redisplay_internal (preserve_echo_area)
          last_arrow_position = Qt;
          last_arrow_string = Qt;
        }
-      
+
       /* If we pause after scrolling, some rows in the current
         matrices of some windows are not valid.  */
       if (!WINDOW_FULL_WIDTH_P (w)
@@ -9023,16 +9430,17 @@ redisplay_internal (preserve_echo_area)
          /* This has already been done above if
             consider_all_windows_p is set.  */
          mark_window_display_accurate_1 (w, 1);
-         
+
          last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
          last_arrow_string = Voverlay_arrow_string;
-         
+
          if (frame_up_to_date_hook != 0)
            frame_up_to_date_hook (sf);
        }
 
       update_mode_lines = 0;
       windows_or_buffers_changed = 0;
+      cursor_type_changed = 0;
     }
 
   /* Start SIGIO interrupts coming again.  Having them off during the
@@ -9041,7 +9449,7 @@ redisplay_internal (preserve_echo_area)
      But it is much hairier to try to do anything about that.  */
   if (interrupt_input)
     request_sigio ();
-  start_polling ();
+  RESUME_POLLING;
 
   /* If a frame has become visible which was not before, redisplay
      again, so that we display it.  Expose events for such a frame
@@ -9080,9 +9488,9 @@ redisplay_internal (preserve_echo_area)
   if (windows_or_buffers_changed && !pause)
     goto retry;
 
- end_of_redisplay:;
-
+ end_of_redisplay:
   unbind_to (count, Qnil);
+  RESUME_POLLING;
 }
 
 
@@ -9117,8 +9525,9 @@ redisplay_preserve_echo_area (from_where)
 
 
 /* Function registered with record_unwind_protect in
-   redisplay_internal.  Clears the flag indicating that a redisplay is
-   in progress.  */
+   redisplay_internal.  Reset redisplaying_p to the value it had
+   before redisplay_internal was called, and clear
+   prevent_freeing_realized_faces_p.  */
 
 static Lisp_Object
 unwind_redisplay (old_redisplaying_p)
@@ -9142,7 +9551,7 @@ mark_window_display_accurate_1 (w, accurate_p)
   if (BUFFERP (w->buffer))
     {
       struct buffer *b = XBUFFER (w->buffer);
-         
+
       w->last_modified
        = make_number (accurate_p ? BUF_MODIFF (b) : 0);
       w->last_overlay_modified
@@ -9159,14 +9568,14 @@ mark_window_display_accurate_1 (w, accurate_p)
          BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
          BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
          BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
-         
+
          w->current_matrix->buffer = b;
          w->current_matrix->begv = BUF_BEGV (b);
          w->current_matrix->zv = BUF_ZV (b);
-         
+
          w->last_cursor = w->cursor;
          w->last_cursor_off_p = w->cursor_off_p;
-         
+
          if (w == XWINDOW (selected_window))
            w->last_point = make_number (BUF_PT (b));
          else
@@ -9198,7 +9607,7 @@ mark_window_display_accurate (window, accurate_p)
      int accurate_p;
 {
   struct window *w;
-  
+
   for (; !NILP (window); window = w->next)
     {
       w = XWINDOW (window);
@@ -9241,13 +9650,13 @@ disp_char_vector (dp, c)
 
   if (SINGLE_BYTE_CHAR_P (c))
     return (dp->contents[c]);
-  
+
   SPLIT_CHAR (c, code[0], code[1], code[2]);
   if (code[1] < 32)
     code[1] = -1;
   else if (code[2] < 32)
     code[2] = -1;
-  
+
   /* Here, the possible range of code[0] (== charset ID) is
      128..max_charset.  Since the top level char table contains data
      for multibyte characters after 256th element, we must increment
@@ -9261,7 +9670,7 @@ disp_char_vector (dp, c)
       if (!SUB_CHAR_TABLE_P (val))
        return (NILP (val) ? dp->defalt : val);
     }
-  
+
   /* Here, val is a sub char table.  We return the default value of
      it.  */
   return (dp->defalt);
@@ -9282,7 +9691,7 @@ redisplay_windows (window)
   while (!NILP (window))
     {
       struct window *w = XWINDOW (window);
-      
+
       if (!NILP (w->hchild))
        redisplay_windows (w->hchild);
       else if (!NILP (w->vchild))
@@ -9290,7 +9699,10 @@ redisplay_windows (window)
       else
        {
          displayed_buffer = XBUFFER (w->buffer);
-         internal_condition_case_1 (redisplay_window_0, window, Qerror,
+         /* Use list_of_error, not Qerror, so that
+            we catch only errors and don't run the debugger.  */
+         internal_condition_case_1 (redisplay_window_0, window,
+                                    list_of_error,
                                     redisplay_window_error);
        }
 
@@ -9323,6 +9735,19 @@ redisplay_window_1 (window)
   return Qnil;
 }
 \f
+
+/* Increment GLYPH until it reaches END or CONDITION fails while
+   adding (GLYPH)->pixel_width to X. */
+
+#define SKIP_GLYPHS(glyph, end, x, condition)  \
+  do                                           \
+    {                                          \
+      (x) += (glyph)->pixel_width;             \
+      ++(glyph);                               \
+    }                                          \
+  while ((glyph) < (end) && (condition))
+
+
 /* Set cursor position of W.  PT is assumed to be displayed in ROW.
    DELTA is the number of bytes by which positions recorded in ROW
    differ from current buffer positions.  */
@@ -9336,6 +9761,14 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
 {
   struct glyph *glyph = row->glyphs[TEXT_AREA];
   struct glyph *end = glyph + row->used[TEXT_AREA];
+  /* The first glyph that starts a sequence of glyphs from string.  */
+  struct glyph *string_start;
+  /* The X coordinate of string_start.  */
+  int string_start_x;
+  /* The last known character position.  */
+  int last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
+  /* The last known character position before string_start.  */
+  int string_before_pos;
   int x = row->x;
   int pt_old = PT - delta;
 
@@ -9351,13 +9784,72 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
        ++glyph;
       }
 
+  string_start = NULL;
   while (glyph < end
         && !INTEGERP (glyph->object)
         && (!BUFFERP (glyph->object)
-            || glyph->charpos < pt_old))
+            || (last_pos = glyph->charpos) < pt_old))
     {
-      x += glyph->pixel_width;
-      ++glyph;
+      if (! STRINGP (glyph->object))
+       {
+         string_start = NULL;
+         x += glyph->pixel_width;
+         ++glyph;
+       }
+      else
+       {
+         string_before_pos = last_pos;
+         string_start = glyph;
+         string_start_x = x;
+         /* Skip all glyphs from string.  */
+         SKIP_GLYPHS (glyph, end, x, STRINGP (glyph->object));
+       }
+    }
+
+  if (string_start
+      && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old))
+    {
+      /* We may have skipped over point because the previous glyphs
+        are from string.  As there's no easy way to know the
+        character position of the current glyph, find the correct
+        glyph on point by scanning from string_start again.  */
+      Lisp_Object limit;
+      Lisp_Object string;
+      int pos;
+
+      limit = make_number (pt_old + 1);
+      end = glyph;
+      glyph = string_start;
+      x = string_start_x;
+      string = glyph->object;
+      pos = string_buffer_position (w, string, string_before_pos);
+      /* If STRING is from overlay, LAST_POS == 0.  We skip such glyphs
+        because we always put cursor after overlay strings.  */
+      while (pos == 0 && glyph < end)
+       {
+         string = glyph->object;
+         SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
+         if (glyph < end)
+           pos = string_buffer_position (w, glyph->object, string_before_pos);
+       }
+
+      while (glyph < end)
+       {
+         pos = XINT (Fnext_single_char_property_change
+                     (make_number (pos), Qdisplay, Qnil, limit));
+         if (pos > pt_old)
+           break;
+         /* Skip glyphs from the same string.  */
+         string = glyph->object;
+         SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
+         /* Skip glyphs from an overlay.  */
+         while (glyph < end
+                && ! string_buffer_position (w, glyph->object, pos))
+           {
+             string = glyph->object;
+             SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
+           }
+       }
     }
 
   w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
@@ -9372,17 +9864,17 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
          && row->x == 0)
        {
          this_line_buffer = XBUFFER (w->buffer);
-         
+
          CHARPOS (this_line_start_pos)
            = MATRIX_ROW_START_CHARPOS (row) + delta;
          BYTEPOS (this_line_start_pos)
            = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
-         
+
          CHARPOS (this_line_end_pos)
            = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
          BYTEPOS (this_line_end_pos)
            = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
-         
+
          this_line_y = w->cursor.y;
          this_line_pixel_height = row->height;
          this_line_vpos = w->cursor.vpos;
@@ -9412,7 +9904,7 @@ run_window_scroll_functions (window, startp)
 
   if (!NILP (Vwindow_scroll_functions))
     {
-      run_hook_with_args_2 (Qwindow_scroll_functions, window, 
+      run_hook_with_args_2 (Qwindow_scroll_functions, window,
                            make_number (CHARPOS (startp)));
       SET_TEXT_POS_FROM_MARKER (startp, w->start);
       /* In case the hook functions switch buffers.  */
@@ -9424,10 +9916,12 @@ run_window_scroll_functions (window, startp)
 }
 
 
-/* Modify the desired matrix of window W and W->vscroll so that the
-   line containing the cursor is fully visible.  If this requires
-   larger matrices than are allocated, set fonts_changed_p and return
-   0.  */
+/* Make sure the line containing the cursor is fully visible.
+   A value of 1 means there is nothing to be done.
+   (Either the line is fully visible, or it cannot be made so,
+   or we cannot tell.)
+   A value of 0 means the caller should do scrolling
+   as if point had gone off the screen.  */
 
 static int
 make_cursor_line_fully_visible (w)
@@ -9436,17 +9930,16 @@ make_cursor_line_fully_visible (w)
   struct glyph_matrix *matrix;
   struct glyph_row *row;
   int window_height;
-  
+
   /* It's not always possible to find the cursor, e.g, when a window
      is full of overlay strings.  Don't do anything in that case.  */
   if (w->cursor.vpos < 0)
     return 1;
-  
+
   matrix = w->desired_matrix;
   row = MATRIX_ROW (matrix, w->cursor.vpos);
 
-  /* If the cursor row is not partially visible, there's nothing
-     to do.  */
+  /* If the cursor row is not partially visible, there's nothing to do.  */
   if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
     return 1;
 
@@ -9456,6 +9949,13 @@ make_cursor_line_fully_visible (w)
   if (row->height >= window_height)
     return 1;
 
+  return 0;
+
+#if 0
+  /* This code used to try to scroll the window just enough to make
+     the line visible.  It returned 0 to say that the caller should
+     allocate larger glyph matrices.  */
+
   if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
     {
       int dy = row->height - row->visible_height;
@@ -9470,7 +9970,7 @@ make_cursor_line_fully_visible (w)
       w->cursor.y += dy;
       shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
     }
-  
+
   /* When we change the cursor y-position of the selected window,
      change this_line_y as well so that the display optimization for
      the cursor line of the selected window in redisplay_internal uses
@@ -9487,6 +9987,7 @@ make_cursor_line_fully_visible (w)
     }
 
   return 1;
+#endif /* 0 */
 }
 
 
@@ -9496,12 +9997,15 @@ make_cursor_line_fully_visible (w)
    in redisplay_window to bring a partially visible line into view in
    the case that only the cursor has moved.
 
+   LAST_LINE_MISFIT should be nonzero if we're scrolling because the
+   last screen line's vertical height extends past the end of the screen.
+
    Value is
 
    1   if scrolling succeeded
-    
+
    0   if scrolling didn't find point.
-   
+
    -1  if new fonts have been loaded so that we must interrupt
    redisplay, adjust glyph matrices, and try again.  */
 
@@ -9514,11 +10018,12 @@ enum
 
 static int
 try_scrolling (window, just_this_one_p, scroll_conservatively,
-              scroll_step, temp_scroll_step)
+              scroll_step, temp_scroll_step, last_line_misfit)
      Lisp_Object window;
      int just_this_one_p;
      EMACS_INT scroll_conservatively, scroll_step;
      int temp_scroll_step;
+     int last_line_misfit;
 {
   struct window *w = XWINDOW (window);
   struct frame *f = XFRAME (w->frame);
@@ -9534,13 +10039,14 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
   int amount_to_scroll = 0;
   Lisp_Object aggressive;
   int height;
+  int end_scroll_margin;
 
 #if GLYPH_DEBUG
   debug_method_add (w, "try_scrolling");
 #endif
 
   SET_TEXT_POS_FROM_MARKER (startp, w->start);
-  
+
   /* Compute scroll margin height in pixels.  We scroll when point is
      within this distance from the top or bottom of the window.  */
   if (scroll_margin > 0)
@@ -9570,19 +10076,24 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
      and move this_scroll_margin up to find the position of the scroll
      margin.  */
   window_end = Fwindow_end (window, Qt);
+
+ too_near_end:
+
   CHARPOS (scroll_margin_pos) = XINT (window_end);
   BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
-  if (this_scroll_margin)
+
+  end_scroll_margin = this_scroll_margin + !!last_line_misfit;
+  if (end_scroll_margin)
     {
       start_display (&it, w, scroll_margin_pos);
-      move_it_vertically (&it, - this_scroll_margin);
+      move_it_vertically (&it, - end_scroll_margin);
       scroll_margin_pos = it.current.pos;
     }
 
   if (PT >= CHARPOS (scroll_margin_pos))
     {
       int y0;
-      
+
       /* Point is in the scroll margin at the bottom of the window, or
         below.  Compute a new window start that makes point visible.  */
 
@@ -9597,19 +10108,21 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
         down so that the line the cursor is in is visible, which
         means we have to add in the height of the cursor line.  */
       dy = line_bottom_y (&it) - y0;
-      
+
       if (dy > scroll_max)
        return SCROLLING_FAILED;
-      
+
       /* Move the window start down.  If scrolling conservatively,
         move it just enough down to make point visible.  If
         scroll_step is set, move it down by scroll_step.  */
       start_display (&it, w, startp);
 
       if (scroll_conservatively)
+       /* Set AMOUNT_TO_SCROLL to at least one line,
+          and at most scroll_conservatively lines.  */
        amount_to_scroll
-         = max (max (dy, CANON_Y_UNIT (f)),
-                CANON_Y_UNIT (f) * max (scroll_step, temp_scroll_step));
+         = min (max (dy, CANON_Y_UNIT (f)),
+                CANON_Y_UNIT (f) * scroll_conservatively);
       else if (scroll_step || temp_scroll_step)
        amount_to_scroll = scroll_max;
       else
@@ -9624,7 +10137,12 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
       if (amount_to_scroll <= 0)
        return SCROLLING_FAILED;
 
+      /* If moving by amount_to_scroll leaves STARTP unchanged,
+        move it down one screen line.  */
+
       move_it_vertically (&it, amount_to_scroll);
+      if (CHARPOS (it.current.pos) == CHARPOS (startp))
+       move_it_by_lines (&it, 1, 1);
       startp = it.current.pos;
     }
   else
@@ -9644,7 +10162,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
          /* Point is in the scroll margin at the top of the window or
             above what is displayed in the window.  */
          int y0;
-         
+
          /* Compute the vertical distance from PT to the scroll
             margin position.  Give up if distance is greater than
             scroll_max.  */
@@ -9657,10 +10175,10 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
          dy = it.current_y - y0;
          if (dy > scroll_max)
            return SCROLLING_FAILED;
-         
+
          /* Compute new window start.  */
          start_display (&it, w, startp);
-         
+
          if (scroll_conservatively)
            amount_to_scroll =
              max (dy, CANON_Y_UNIT (f) * max (scroll_step, temp_scroll_step));
@@ -9677,7 +10195,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 
          if (amount_to_scroll <= 0)
            return SCROLLING_FAILED;
-         
+
          move_it_vertically (&it, - amount_to_scroll);
          startp = it.current.pos;
        }
@@ -9698,18 +10216,20 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
   else
     {
       /* Maybe forget recorded base line for line number display.  */
-      if (!just_this_one_p 
+      if (!just_this_one_p
          || current_buffer->clip_changed
          || BEG_UNCHANGED < CHARPOS (startp))
        w->base_line_number = Qnil;
-      
-      /* If cursor ends up on a partially visible line, shift display
-        lines up or down.  If that fails because we need larger
-        matrices, give up.  */
-      if (!make_cursor_line_fully_visible (w))
-       rc = SCROLLING_NEED_LARGER_MATRICES;
-      else
-       rc = SCROLLING_SUCCESS;
+
+      /* If cursor ends up on a partially visible line,
+        treat that as being off the bottom of the screen.  */
+      if (! make_cursor_line_fully_visible (w))
+       {
+         clear_glyph_matrix (w->desired_matrix);
+         last_line_misfit = 1;
+         goto too_near_end;
+       }
+      rc = SCROLLING_SUCCESS;
     }
 
   return rc;
@@ -9734,7 +10254,7 @@ compute_window_start_on_continuation_line (w)
   SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
 
   /* If window start is on a continuation line...  Window start may be
-     < BEGV in case there's invisible text at the start of the 
+     < BEGV in case there's invisible text at the start of the
      buffer (M-x rmail, for example).  */
   if (CHARPOS (start_pos) > BEGV
       && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
@@ -9747,7 +10267,7 @@ compute_window_start_on_continuation_line (w)
        SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
       else if (CHARPOS (start_pos) > ZV)
        SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
-      
+
       /* Find the start of the continued line.  This should be fast
         because scan_buffer is fast (newline cache).  */
       row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0);
@@ -9761,7 +10281,7 @@ compute_window_start_on_continuation_line (w)
          < XFASTINT (w->height) * XFASTINT (w->width))
        {
          int min_distance, distance;
-         
+
          /* Move forward by display lines to find the new window
             start.  If window width was enlarged, the new start can
             be expected to be > the old start.  If window width was
@@ -9777,22 +10297,22 @@ compute_window_start_on_continuation_line (w)
              pos = it.current.pos;
              move_it_by_lines (&it, 1, 0);
            }
-         
+
          /* Set the window start there.  */
          SET_MARKER_FROM_TEXT_POS (w->start, pos);
          window_start_changed_p = 1;
        }
     }
-  
+
   return window_start_changed_p;
 }
 
 
-/* Try cursor movement in case text has not changes in window WINDOW,
+/* Try cursor movement in case text has not changed in window WINDOW,
    with window start STARTP.  Value is
 
    CURSOR_MOVEMENT_SUCCESS if successful
-   
+
    CURSOR_MOVEMENT_CANNOT_BE_USED if this method cannot be used
 
    CURSOR_MOVEMENT_MUST_SCROLL if we know we have to scroll the
@@ -9803,7 +10323,7 @@ compute_window_start_on_continuation_line (w)
    which case we have to abort this redisplay, and adjust matrices
    first.  */
 
-enum 
+enum
 {
   CURSOR_MOVEMENT_SUCCESS,
   CURSOR_MOVEMENT_CANNOT_BE_USED,
@@ -9820,7 +10340,7 @@ try_cursor_movement (window, startp, scroll_step)
   struct window *w = XWINDOW (window);
   struct frame *f = XFRAME (w->frame);
   int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
-  
+
 #if GLYPH_DEBUG
   if (inhibit_try_cursor_movement)
     return rc;
@@ -9838,7 +10358,8 @@ try_cursor_movement (window, startp, scroll_step)
         cases.  */
       && !update_mode_lines
       && !windows_or_buffers_changed
-      /* Can't use this case if highlighting a region.  When a 
+      && !cursor_type_changed
+      /* Can't use this case if highlighting a region.  When a
          region exists, cursor movement has to do more than just
          set the cursor.  */
       && !(!NILP (Vtransient_mark_mode)
@@ -9896,7 +10417,7 @@ try_cursor_movement (window, startp, scroll_step)
        {
          int scroll_p = 0;
          int last_y = window_text_bottom_y (w) - this_scroll_margin;
-         
+
          if (PT > XFASTINT (w->last_point))
            {
              /* Point has moved forward.  */
@@ -9964,7 +10485,7 @@ try_cursor_movement (window, startp, scroll_step)
                     && MATRIX_ROW_END_CHARPOS (row) == PT
                     && !cursor_row_p (w, row))
                ++row;
-         
+
              /* If within the scroll margin, scroll.  */
              if (row->y < this_scroll_margin
                  && CHARPOS (startp) != BEGV)
@@ -9995,9 +10516,8 @@ try_cursor_movement (window, startp, scroll_step)
              else
                {
                  set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
-                 try_window (window, startp);
                  if (!make_cursor_line_fully_visible (w))
-                   rc = CURSOR_MOVEMENT_NEED_LARGER_MATRICES;
+                   rc = CURSOR_MOVEMENT_MUST_SCROLL;
                  else
                    rc = CURSOR_MOVEMENT_SUCCESS;
                }
@@ -10017,7 +10537,11 @@ try_cursor_movement (window, startp, scroll_step)
 
 
 /* Redisplay leaf window WINDOW.  JUST_THIS_ONE_P non-zero means only
-   selected_window is redisplayed.  */
+   selected_window is redisplayed.
+
+   We can return without actually redisplaying the window if
+   fonts_changed_p is nonzero.  In that case, redisplay_internal will
+   retry.  */
 
 static void
 redisplay_window (window, just_this_one_p)
@@ -10034,9 +10558,14 @@ redisplay_window (window, just_this_one_p)
   struct it it;
   /* Record it now because it's overwritten.  */
   int current_matrix_up_to_date_p = 0;
+  /* This is less strict than current_matrix_up_to_date_p.
+     It indictes that the buffer contents and narrowing are unchanged.  */
+  int buffer_unchanged_p = 0;
   int temp_scroll_step = 0;
-  int count = BINDING_STACK_SIZE ();
+  int count = SPECPDL_INDEX ();
   int rc;
+  int centering_position;
+  int last_line_misfit = 0;
 
   SET_TEXT_POS (lpoint, PT, PT_BYTE);
   opoint = lpoint;
@@ -10050,11 +10579,12 @@ redisplay_window (window, just_this_one_p)
   specbind (Qinhibit_point_motion_hooks, Qt);
 
   reconsider_clip_changes (w, buffer);
-    
-  /* Has the mode line to be updated?  */ 
+
+  /* Has the mode line to be updated?  */
   update_mode_line = (!NILP (w->update_mode_line)
                      || update_mode_lines
-                     || buffer->clip_changed);
+                     || buffer->clip_changed
+                     || buffer->prevent_redisplay_optimizations_p);
 
   if (MINI_WINDOW_P (w))
     {
@@ -10069,10 +10599,14 @@ redisplay_window (window, just_this_one_p)
            /* We've already displayed the echo area glyphs in this window.  */
            goto finish_scroll_bars;
        }
-      else if (w != XWINDOW (minibuf_window))
+      else if ((w != XWINDOW (minibuf_window)
+               || minibuf_level == 0)
+              /* Quail displays non-mini buffers in minibuffer window.
+                 In that case, redisplay the window normally.  */
+              && !NILP (Fmemq (w->buffer, Vminibuffer_list)))
        {
-         /* W is a mini-buffer window, but it's not the currently
-            active one, so clear it.  */
+         /* W is a mini-buffer window, but it's not active, so clear
+            it.  */
          int yb = window_text_bottom_y (w);
          struct glyph_row *row;
          int y;
@@ -10095,6 +10629,13 @@ redisplay_window (window, just_this_one_p)
   SET_TEXT_POS (opoint, PT, PT_BYTE);
 
   current_matrix_up_to_date_p
+    = (!NILP (w->window_end_valid)
+       && !current_buffer->clip_changed
+       && !current_buffer->prevent_redisplay_optimizations_p
+       && XFASTINT (w->last_modified) >= MODIFF
+       && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
+
+  buffer_unchanged_p
     = (!NILP (w->window_end_valid)
        && !current_buffer->clip_changed
        && XFASTINT (w->last_modified) >= MODIFF
@@ -10108,7 +10649,7 @@ redisplay_window (window, just_this_one_p)
         window start in case the window's width changed.  */
       if (XMARKER (w->start)->buffer == current_buffer)
        compute_window_start_on_continuation_line (w);
-      
+
       w->window_end_valid = Qnil;
     }
 
@@ -10126,8 +10667,9 @@ redisplay_window (window, just_this_one_p)
       && !(PT == XFASTINT (w->last_point)
           && XFASTINT (w->last_modified) >= MODIFF
           && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
-      && XFASTINT (w->column_number_displayed) != current_column ())
-    update_mode_line = 1; 
+      && (XFASTINT (w->column_number_displayed)
+          != (int) current_column ()))  /* iftc */
+    update_mode_line = 1;
 
   /* Count number of windows showing the selected buffer.  An indirect
      buffer counts as its base buffer.  */
@@ -10162,7 +10704,7 @@ redisplay_window (window, just_this_one_p)
          new_pt_byte = ZV_BYTE;
          set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
        }
-      
+
       /* We don't use SET_PT so that the point-motion hooks don't run.  */
       TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
     }
@@ -10211,13 +10753,15 @@ redisplay_window (window, just_this_one_p)
   if (!NILP (w->force_start)
       || w->frozen_window_start_p)
     {
+      /* We set this later on if we have to adjust point.  */
+      int new_vpos = -1;
+
       w->force_start = Qnil;
       w->vscroll = 0;
       w->window_end_valid = Qnil;
 
       /* Forget any recorded base line for line number display.  */
-      if (!current_matrix_up_to_date_p
-         || current_buffer->clip_changed)
+      if (!buffer_unchanged_p)
        w->base_line_number = Qnil;
 
       /* Redisplay the mode line.  Select the buffer properly for that.
@@ -10234,21 +10778,21 @@ redisplay_window (window, just_this_one_p)
          w->update_mode_line = Qt;
          startp = run_window_scroll_functions (window, startp);
        }
-      
+
       w->last_modified = make_number (0);
       w->last_overlay_modified = make_number (0);
       if (CHARPOS (startp) < BEGV)
        SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
       else if (CHARPOS (startp) > ZV)
        SET_TEXT_POS (startp, ZV, ZV_BYTE);
-      
-      /* Redisplay, then check if cursor has been set during the 
+
+      /* Redisplay, then check if cursor has been set during the
         redisplay.  Give up if new fonts were loaded.  */
       if (!try_window (window, startp))
        {
          w->force_start = Qt;
          clear_glyph_matrix (w->desired_matrix);
-         goto finish_scroll_bars;
+         goto need_larger_matrices;
        }
 
       if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
@@ -10256,12 +10800,24 @@ redisplay_window (window, just_this_one_p)
          /* If point does not appear, try to move point so it does
             appear. The desired matrix has been built above, so we
             can use it here.  */
-         int window_height;
+         new_vpos = window_box_height (w) / 2;
+       }
+
+      if (!make_cursor_line_fully_visible (w))
+       {
+         /* Point does appear, but on a line partly visible at end of window.
+            Move it back to a fully-visible line.  */
+         new_vpos = window_box_height (w);
+       }
+
+      /* If we need to move point for either of the above reasons,
+        now actually do it.  */
+      if (new_vpos >= 0)
+       {
          struct glyph_row *row;
 
-         window_height = window_box_height (w) / 2;
          row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
-         while (MATRIX_ROW_BOTTOM_Y (row) < window_height)
+         while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos)
            ++row;
 
          TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
@@ -10273,7 +10829,7 @@ redisplay_window (window, just_this_one_p)
            SET_TEXT_POS (lpoint, PT, PT_BYTE);
 
          set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
-         
+
          /* If we are highlighting the region, then we just changed
             the region, so redisplay to show it.  */
          if (!NILP (Vtransient_mark_mode)
@@ -10285,8 +10841,6 @@ redisplay_window (window, just_this_one_p)
            }
        }
 
-      if (!make_cursor_line_fully_visible (w))
-       goto need_larger_matrices;
 #if GLYPH_DEBUG
       debug_method_add (w, "forced window start");
 #endif
@@ -10294,7 +10848,8 @@ redisplay_window (window, just_this_one_p)
     }
 
   /* Handle case where text has not changed, only point, and it has
-     not moved off the frame.  */
+     not moved off the frame, and we are not retrying after hscroll.
+     (current_matrix_up_to_date_p is nonzero when retrying.)  */
   if (current_matrix_up_to_date_p
       && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
          rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
@@ -10303,13 +10858,15 @@ redisplay_window (window, just_this_one_p)
        {
        case CURSOR_MOVEMENT_SUCCESS:
          goto done;
-         
+
+#if 0  /* try_cursor_movement never returns this value.  */
        case CURSOR_MOVEMENT_NEED_LARGER_MATRICES:
          goto need_larger_matrices;
-         
+#endif
+
        case CURSOR_MOVEMENT_MUST_SCROLL:
          goto try_to_scroll;
-         
+
        default:
          abort ();
        }
@@ -10325,7 +10882,7 @@ redisplay_window (window, just_this_one_p)
 #endif
       goto recenter;
     }
-  
+
   /* Try scrolling with try_window_id.  Value is > 0 if update has
      been done, it is -1 if we know that the same window start will
      not work.  It is 0 if unsuccessful for some other reason.  */
@@ -10355,7 +10912,7 @@ redisplay_window (window, just_this_one_p)
 #if GLYPH_DEBUG
       debug_method_add (w, "same window start");
 #endif
-      
+
       /* Try to redisplay starting at same place as before.
          If point has not moved off frame, accept the results.  */
       if (!current_matrix_up_to_date_p
@@ -10372,18 +10929,23 @@ redisplay_window (window, just_this_one_p)
 
       if (fonts_changed_p)
        goto need_larger_matrices;
-      
+
       if (w->cursor.vpos >= 0)
        {
-         if (!just_this_one_p 
+         if (!just_this_one_p
              || current_buffer->clip_changed
              || BEG_UNCHANGED < CHARPOS (startp))
            /* Forget any recorded base line for line number display.  */
            w->base_line_number = Qnil;
-         
+
          if (!make_cursor_line_fully_visible (w))
-           goto need_larger_matrices;
-         goto done;
+           {
+             clear_glyph_matrix (w->desired_matrix);
+             last_line_misfit = 1;
+           }
+           /* Drop through and scroll.  */
+         else
+           goto done;
        }
       else
        clear_glyph_matrix (w->desired_matrix);
@@ -10408,7 +10970,7 @@ redisplay_window (window, just_this_one_p)
        || NUMBERP (current_buffer->scroll_up_aggressively)
        || NUMBERP (current_buffer->scroll_down_aggressively))
       && !current_buffer->clip_changed
-      && CHARPOS (startp) >= BEGV 
+      && CHARPOS (startp) >= BEGV
       && CHARPOS (startp) <= ZV)
     {
       /* The function returns -1 if new fonts were loaded, 1 if
@@ -10416,18 +10978,18 @@ redisplay_window (window, just_this_one_p)
       int rc = try_scrolling (window, just_this_one_p,
                              scroll_conservatively,
                              scroll_step,
-                             temp_scroll_step);
+                             temp_scroll_step, last_line_misfit);
       switch (rc)
        {
        case SCROLLING_SUCCESS:
          goto done;
-         
+
        case SCROLLING_NEED_LARGER_MATRICES:
          goto need_larger_matrices;
-         
+
        case SCROLLING_FAILED:
          break;
-         
+
        default:
          abort ();
        }
@@ -10436,6 +10998,10 @@ redisplay_window (window, just_this_one_p)
   /* Finally, just choose place to start which centers point */
 
  recenter:
+  centering_position = window_box_height (w) / 2;
+
+ point_at_top:
+  /* Jump here with centering_position already set to 0.  */
 
 #if GLYPH_DEBUG
   debug_method_add (w, "recenter");
@@ -10444,14 +11010,13 @@ redisplay_window (window, just_this_one_p)
   /* w->vscroll = 0; */
 
   /* Forget any previously recorded base line for line number display.  */
-  if (!current_matrix_up_to_date_p
-      || current_buffer->clip_changed)
+  if (!buffer_unchanged_p)
     w->base_line_number = Qnil;
 
   /* Move backward half the height of the window.  */
   init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
   it.current_y = it.last_visible_y;
-  move_it_vertically_backward (&it, 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
@@ -10468,7 +11033,7 @@ redisplay_window (window, 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_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
@@ -10479,6 +11044,7 @@ redisplay_window (window, just_this_one_p)
   /* Redisplay the window.  */
   if (!current_matrix_up_to_date_p
       || windows_or_buffers_changed
+      || cursor_type_changed
       /* Don't use try_window_reusing_current_matrix in this case
         because it can have changed the buffer.  */
       || !NILP (Vwindow_scroll_functions)
@@ -10530,9 +11096,23 @@ redisplay_window (window, just_this_one_p)
        ++row;
       set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
     }
-  
+
   if (!make_cursor_line_fully_visible (w))
-    goto need_larger_matrices;
+    {
+      /* If vscroll is enabled, disable it and try again.  */
+      if (w->vscroll)
+       {
+         w->vscroll = 0;
+         clear_glyph_matrix (w->desired_matrix);
+         goto recenter;
+       }
+
+      /* If centering point failed to make the whole line visible,
+        put point at the top instead.  That has to make the whole line
+        visible, if it can be done.  */
+      centering_position = 0;
+      goto point_at_top;
+    }
 
  done:
 
@@ -10544,17 +11124,18 @@ redisplay_window (window, just_this_one_p)
   /* Display the mode line, if we must.  */
   if ((update_mode_line
        /* If window not full width, must redo its mode line
-         if (a) the window to its side is being redone and 
+         if (a) the window to its side is being redone and
          (b) we do a frame-based redisplay.  This is a consequence
          of how inverted lines are drawn in frame-based redisplay.  */
-       || (!just_this_one_p 
+       || (!just_this_one_p
           && !FRAME_WINDOW_P (f)
           && !WINDOW_FULL_WIDTH_P (w))
        /* Line number to display.  */
        || INTEGERP (w->base_line_pos)
        /* Column number is displayed and different from the one displayed.  */
        || (!NILP (w->column_number_displayed)
-          && XFASTINT (w->column_number_displayed) != current_column ()))
+          && (XFASTINT (w->column_number_displayed)
+               != (int) current_column ()))) /* iftc */
        /* This means that the window has a mode line.  */
        && (WINDOW_WANTS_MODELINE_P (w)
           || WINDOW_WANTS_HEADER_LINE_P (w)))
@@ -10570,7 +11151,7 @@ redisplay_window (window, just_this_one_p)
          MATRIX_MODE_LINE_ROW (w->current_matrix)->height
            = DESIRED_MODE_LINE_HEIGHT (w);
        }
-      
+
       /* If top line height has changed, arrange for a thorough
         immediate redisplay using the correct mode line height.  */
       if (WINDOW_WANTS_HEADER_LINE_P (w)
@@ -10593,16 +11174,18 @@ redisplay_window (window, just_this_one_p)
     }
 
  finish_menu_bars:
-  
+
   /* When we reach a frame's selected window, redo the frame's menu bar.  */
   if (update_mode_line
       && EQ (FRAME_SELECTED_WINDOW (f), window))
     {
       int redisplay_menu_p = 0;
+      int redisplay_tool_bar_p = 0;
 
       if (FRAME_WINDOW_P (f))
        {
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+    || defined (USE_GTK)
          redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
 #else
          redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
@@ -10615,13 +11198,24 @@ redisplay_window (window, just_this_one_p)
         display_menu_bar (w);
 
 #ifdef HAVE_WINDOW_SYSTEM
-      if (WINDOWP (f->tool_bar_window)
-         && (FRAME_TOOL_BAR_LINES (f) > 0
-             || auto_resize_tool_bars_p))
-       redisplay_tool_bar (f);
+#ifdef USE_GTK
+      redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
+#else
+      redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
+        && (FRAME_TOOL_BAR_LINES (f) > 0
+            || auto_resize_tool_bars_p);
+
+#endif
+
+      if (redisplay_tool_bar_p)
+        redisplay_tool_bar (f);
 #endif
     }
 
+  /* We go to this label, with fonts_changed_p nonzero,
+     if it is necessary to try again using larger glyph matrices.
+     We have to redeem the scroll bar even in this case,
+     because the loop in redisplay_internal expects that.  */
  need_larger_matrices:
   ;
  finish_scroll_bars:
@@ -10647,9 +11241,9 @@ redisplay_window (window, just_this_one_p)
             moment, we'll pretend it is.  */
          end = (Z - XFASTINT (w->window_end_pos)) - BEGV;
 
-         if (end < start) 
+         if (end < start)
            end = start;
-         if (whole < (end - start)) 
+         if (whole < (end - start))
            whole = end - start;
        }
       else
@@ -10730,7 +11324,7 @@ try_window (window, pos)
       w->window_end_bytepos = 0;
       w->window_end_pos = w->window_end_vpos = make_number (0);
     }
-  
+
   /* But that is not valid info until redisplay finishes.  */
   w->window_end_valid = Qnil;
   return 1;
@@ -10771,7 +11365,8 @@ try_window_reusing_current_matrix (w)
       !FRAME_WINDOW_P (f)
       /* Don't try to reuse the display if windows have been split
         or such.  */
-      || windows_or_buffers_changed)
+      || windows_or_buffers_changed
+      || cursor_type_changed)
     return 0;
 
   /* Can't do this if region may have changed.  */
@@ -10800,11 +11395,11 @@ try_window_reusing_current_matrix (w)
 
   /* Clear the desired matrix for the display below.  */
   clear_glyph_matrix (w->desired_matrix);
-  
+
   if (CHARPOS (new_start) <= CHARPOS (start))
     {
       int first_row_y;
-      
+
       /* Don't use this method if the display starts with an ellipsis
         displayed for invisible text.  It's not easy to handle that case
         below, and it's certainly not worth the effort since this is
@@ -10813,7 +11408,7 @@ try_window_reusing_current_matrix (w)
        return 0;
 
       IF_DEBUG (debug_method_add (w, "twu1"));
-      
+
       /* Display up to a row that can be reused.  The variable
         last_text_row is set to the last row displayed that displays
         text.  Note that it.vpos == 0 if or if not there is a
@@ -10822,7 +11417,7 @@ try_window_reusing_current_matrix (w)
       first_row_y = it.current_y;
       w->cursor.vpos = -1;
       last_text_row = last_reused_text_row = NULL;
-      
+
       while (it.current_y < it.last_visible_y
             && IT_CHARPOS (it) < CHARPOS (start)
             && !fonts_changed_p)
@@ -10836,12 +11431,12 @@ try_window_reusing_current_matrix (w)
        {
          /* IT.vpos always starts from 0; it counts text lines.  */
          nrows_scrolled = it.vpos;
-         
+
          /* Find PT if not already found in the lines displayed.  */
          if (w->cursor.vpos < 0)
            {
              int dy = it.current_y - first_row_y;
-             
+
              row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
              row = row_containing_pos (w, PT, row, NULL, dy);
              if (row)
@@ -10880,7 +11475,7 @@ try_window_reusing_current_matrix (w)
                         start_vpos,
                         MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
                         nrows_scrolled);
-         
+
          /* Disable lines that must be updated.  */
          for (i = 0; i < it.vpos; ++i)
            (start_row + i)->enabled_p = 0;
@@ -10899,7 +11494,7 @@ try_window_reusing_current_matrix (w)
                row->visible_height -= min_y - row->y;
              if (row->y + row->height > max_y)
                row->visible_height -= row->y + row->height - max_y;
-             
+
              it.current_y += row->height;
 
              if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
@@ -10907,7 +11502,7 @@ try_window_reusing_current_matrix (w)
              if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
                break;
            }
-         
+
          /* Disable lines in the current matrix which are now
             below the window.  */
          for (++row; row < bottom_row; ++row)
@@ -10947,7 +11542,7 @@ try_window_reusing_current_matrix (w)
 
       /* Update hint: don't try scrolling again in update_window.  */
       w->desired_matrix->no_scrolling_p = 1;
-      
+
 #if GLYPH_DEBUG
       debug_method_add (w, "try_window_reusing_current_matrix 1");
 #endif
@@ -11034,7 +11629,7 @@ try_window_reusing_current_matrix (w)
       run.desired_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
       run.height = it.last_visible_y - run.current_y;
       dy = run.current_y - run.desired_y;
-      
+
       if (run.height)
        {
          struct frame *f = XFRAME (WINDOW_FRAME (w));
@@ -11088,7 +11683,7 @@ try_window_reusing_current_matrix (w)
          w->window_end_vpos
            = make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled);
        }
-      
+
       w->window_end_valid = Qnil;
       w->desired_matrix->no_scrolling_p = 1;
 
@@ -11097,7 +11692,7 @@ try_window_reusing_current_matrix (w)
 #endif
       return 1;
     }
-  
+
   return 0;
 }
 
@@ -11141,7 +11736,7 @@ find_last_row_displaying_text (matrix, it, start)
        break;
       ++row;
     }
-  
+
   return row_found;
 }
 
@@ -11186,7 +11781,7 @@ find_last_unchanged_at_beg_row (w)
       /* Stop if last visible row.  */
      if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
        break;
-      
+
       ++row;
     }
 
@@ -11195,17 +11790,17 @@ find_last_unchanged_at_beg_row (w)
 
 
 /* Find the first glyph row in the current matrix of W that is not
-   affected by changes at the end of current_buffer since the 
+   affected by changes at the end of current_buffer since the
    time W's current matrix was built.
 
    Return in *DELTA the number of chars by which buffer positions in
    unchanged text at the end of current_buffer must be adjusted.
-   
+
    Return in *DELTA_BYTES the corresponding number of bytes.
 
    Value is null if no such row exists, i.e. all rows are affected by
    changes.  */
-   
+
 static struct glyph_row *
 find_first_unchanged_at_end_row (w, delta, delta_bytes)
      struct window *w;
@@ -11220,7 +11815,7 @@ find_first_unchanged_at_end_row (w, delta, delta_bytes)
      is not up to date.  */
   if (NILP (w->window_end_valid))
     abort ();
-  
+
   /* A value of window_end_pos >= END_UNCHANGED means that the window
      end is in the range of changed text.  If so, there is no
      unchanged row at the end of W's current matrix.  */
@@ -11229,8 +11824,8 @@ find_first_unchanged_at_end_row (w, delta, delta_bytes)
 
   /* Set row to the last row in W's current matrix displaying text.  */
   row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
-  
-  /* If matrix is entirely empty, no unchanged row exists.  */ 
+
+  /* If matrix is entirely empty, no unchanged row exists.  */
   if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
     {
       /* The value of row is the last glyph row in the matrix having a
@@ -11255,14 +11850,14 @@ find_first_unchanged_at_end_row (w, delta, delta_bytes)
         position.  */
       last_unchanged_pos = Z - END_UNCHANGED + BEG;
       last_unchanged_pos_old = last_unchanged_pos - *delta;
-      
+
       /* Search backward from ROW for a row displaying a line that
         starts at a minimum position >= last_unchanged_pos_old.  */
       for (; row > first_text_row; --row)
        {
          if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
            abort ();
-         
+
          if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
            row_found = row;
        }
@@ -11270,7 +11865,7 @@ find_first_unchanged_at_end_row (w, delta, delta_bytes)
 
   if (row_found && !MATRIX_ROW_DISPLAYS_TEXT_P (row_found))
     abort ();
-  
+
   return row_found;
 }
 
@@ -11296,22 +11891,26 @@ sync_frame_with_window_matrix_rows (w)
 
   /* If W is a full-width window, glyph pointers in W's current matrix
      have, by definition, to be the same as glyph pointers in the
-     corresponding frame matrix.  */
+     corresponding frame matrix.  Note that frame matrices have no
+     marginal areas (see build_frame_matrix).  */
   window_row = w->current_matrix->rows;
   window_row_end = window_row + w->current_matrix->nrows;
   frame_row = f->current_matrix->rows + XFASTINT (w->top);
   while (window_row < window_row_end)
     {
-      int area;
-      
-      for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area)
-       frame_row->glyphs[area] = window_row->glyphs[area];
+      struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
+      struct glyph *end = window_row->glyphs[LAST_AREA];
+
+      frame_row->glyphs[LEFT_MARGIN_AREA] = start;
+      frame_row->glyphs[TEXT_AREA] = start;
+      frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
+      frame_row->glyphs[LAST_AREA] = end;
 
       /* Disable frame rows whose corresponding window rows have
         been disabled in try_window_id.  */
       if (!window_row->enabled_p)
        frame_row->enabled_p = 0;
-      
+
       ++window_row, ++frame_row;
     }
 }
@@ -11335,31 +11934,36 @@ row_containing_pos (w, charpos, start, end, dy)
   /* If we happen to start on a header-line, skip that.  */
   if (row->mode_line_p)
     ++row;
-  
+
   if ((end && row >= end) || !row->enabled_p)
     return NULL;
-  
+
   last_y = window_text_bottom_y (w) - dy;
-      
-  while ((end == NULL || row < end)
-        && MATRIX_ROW_BOTTOM_Y (row) < last_y
-        && (MATRIX_ROW_END_CHARPOS (row) < charpos
+
+  while (1)
+    {
+      /* Give up if we have gone too far.  */
+      if (end && row >= end)
+       return NULL;
+      /* This formerly returned if they were equal.
+        I think that both quantities are of a "last plus one" type;
+        if so, when they are equal, the row is within the screen. -- rms.  */
+      if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
+       return NULL;
+
+      /* If it is in this row, return this row.  */
+      if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
             || (MATRIX_ROW_END_CHARPOS (row) == charpos
                 /* The end position of a row equals the start
                    position of the next row.  If CHARPOS is there, we
                    would rather display it in the next line, except
                    when this line ends in ZV.  */
                 && !row->ends_at_zv_p
-                && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))))
-    ++row;
-      
-  /* Give up if CHARPOS not found.  */
-  if ((end && row >= end)
-      || charpos < MATRIX_ROW_START_CHARPOS (row)
-      || charpos > MATRIX_ROW_END_CHARPOS (row))
-    row = NULL;
-
-  return row;
+                && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
+         && charpos >= MATRIX_ROW_START_CHARPOS (row))
+       return row;
+      ++row;
+    }
 }
 
 
@@ -11434,22 +12038,24 @@ try_window_id (w)
 #else
 #define GIVE_UP(X) return 0
 #endif
-  
+
   SET_TEXT_POS_FROM_MARKER (start, w->start);
 
   /* Don't use this for mini-windows because these can show
      messages and mini-buffers, and we don't handle that here.  */
   if (MINI_WINDOW_P (w))
     GIVE_UP (1);
-  
+
   /* This flag is used to prevent redisplay optimizations.  */
-  if (windows_or_buffers_changed)
+  if (windows_or_buffers_changed || cursor_type_changed)
     GIVE_UP (2);
-  
-  /* Verify that narrowing has not changed.  This flag is also set to prevent
-     redisplay optimizations.  It would be nice to further
+
+  /* Verify that narrowing has not changed.
+     Also verify that we were not told to prevent redisplay optimizations.
+     It would be nice to further
      reduce the number of cases where this prevents try_window_id.  */
-  if (current_buffer->clip_changed)
+  if (current_buffer->clip_changed
+      || current_buffer->prevent_redisplay_optimizations_p)
     GIVE_UP (3);
 
   /* Window must either use window-based redisplay or be full width.  */
@@ -11465,15 +12071,15 @@ try_window_id (w)
   /* Another way to prevent redisplay optimizations.  */
   if (XFASTINT (w->last_modified) == 0)
     GIVE_UP (6);
-  
+
   /* Verify that window is not hscrolled.  */
   if (XFASTINT (w->hscroll) != 0)
     GIVE_UP (7);
-  
+
   /* Verify that display wasn't paused.  */
   if (NILP (w->window_end_valid))
     GIVE_UP (8);
-  
+
   /* Can't use this if highlighting a region because a cursor movement
      will do more than just set the cursor.  */
   if (!NILP (Vtransient_mark_mode)
@@ -11483,17 +12089,17 @@ try_window_id (w)
   /* Likewise if highlighting trailing whitespace.  */
   if (!NILP (Vshow_trailing_whitespace))
     GIVE_UP (11);
-  
+
   /* Likewise if showing a region.  */
   if (!NILP (w->region_showing))
     GIVE_UP (10);
-  
+
   /* Can use this if overlay arrow position and or string have changed.  */
   if (!EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
       || !EQ (last_arrow_string, Voverlay_arrow_string))
     GIVE_UP (12);
 
-  
+
   /* Make sure beg_unchanged and end_unchanged are up to date.  Do it
      only if buffer has really changed.  The reason is that the gap is
      initially at Z for freshly visited files.  The code below would
@@ -11533,7 +12139,7 @@ try_window_id (w)
       Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
       delta = Z - Z_old;
       delta_bytes = Z_BYTE - Z_BYTE_old;
-         
+
       /* Give up if PT is not in the window.  Note that it already has
         been checked at the start of try_window_id that PT is not in
         front of the window start.  */
@@ -11557,10 +12163,13 @@ try_window_id (w)
                                          MATRIX_ROW_VPOS (r1, current_matrix),
                                          delta, delta_bytes);
            }
-      
+
          /* Set the cursor.  */
          row = row_containing_pos (w, PT, r0, NULL, 0);
-         set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
+         if (row)
+           set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
+         else
+           abort ();
          return 1;
        }
     }
@@ -11598,13 +12207,16 @@ try_window_id (w)
 
          /* Set the cursor.  */
          row = row_containing_pos (w, PT, r0, NULL, 0);
-         set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
+         if (row)
+           set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
+         else
+           abort ();
          return 2;
        }
     }
 
   /* Give up if window start is in the changed area.
-     
+
      The condition used to read
 
      (BEG_UNCHANGED + END_UNCHANGED != Z - BEG && ...)
@@ -11613,7 +12225,7 @@ try_window_id (w)
   if (CHARPOS (start) >= first_changed_charpos
       && CHARPOS (start) <= last_changed_charpos)
     GIVE_UP (15);
-  
+
   /* Check that window start agrees with the start of the first glyph
      row in its current matrix.  Check this after we know the window
      start is not in changed text, otherwise positions would not be
@@ -11652,7 +12264,7 @@ try_window_id (w)
       if (init_to_row_end (&it, w, last_unchanged_at_beg_row) == 0)
        GIVE_UP (18);
       start_pos = it.current.pos;
-      
+
       /* Start displaying new lines in the desired matrix at the same
         vpos we would use in the current matrix, i.e. below
         last_unchanged_at_beg_row.  */
@@ -11681,7 +12293,7 @@ try_window_id (w)
     = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
   IF_DEBUG (debug_delta = delta);
   IF_DEBUG (debug_delta_bytes = delta_bytes);
-  
+
   /* Set stop_pos to the buffer position up to which we will have to
      display new lines.  If first_unchanged_at_end_row != NULL, this
      is the buffer position of the start of the line displayed in that
@@ -11692,7 +12304,7 @@ try_window_id (w)
     {
       xassert (last_unchanged_at_beg_row == NULL
               || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
-      
+
       /* If this is a continuation line, move forward to the next one
         that isn't.  Changes in lines above affect this line.
         Caution: this may move first_unchanged_at_end_row to a row
@@ -11721,22 +12333,22 @@ try_window_id (w)
 
 
 #if GLYPH_DEBUG
-  
+
   /* Either there is no unchanged row at the end, or the one we have
      now displays text.  This is a necessary condition for the window
      end pos calculation at the end of this function.  */
   xassert (first_unchanged_at_end_row == NULL
           || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
-  
+
   debug_last_unchanged_at_beg_vpos
     = (last_unchanged_at_beg_row
        ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
        : -1);
   debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
-  
+
 #endif /* GLYPH_DEBUG != 0 */
 
-  
+
   /* Display new lines.  Set last_text_row to the last new line
      displayed which has text on it, i.e. might end up as being the
      line where the window_end_vpos is.  */
@@ -11818,17 +12430,17 @@ try_window_id (w)
          return -1;
        }
     }
-  
+
   /* Don't let the cursor end in the scroll margins.  */
   {
     int this_scroll_margin, cursor_height;
-    
+
     this_scroll_margin = max (0, scroll_margin);
     this_scroll_margin = min (this_scroll_margin,
                              XFASTINT (w->height) / 4);
     this_scroll_margin *= CANON_Y_UNIT (it.f);
     cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
-    
+
     if ((w->cursor.y < this_scroll_margin
         && CHARPOS (start) > BEGV)
        /* Don't take scroll margin into account at the bottom because
@@ -11847,7 +12459,7 @@ try_window_id (w)
   if (dy && run.height)
     {
       update_begin (f);
-         
+
       if (FRAME_WINDOW_P (f))
        {
          rif->update_window_begin_hook (w);
@@ -11865,7 +12477,7 @@ try_window_id (w)
          int end = (XFASTINT (w->top)
                     + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0)
                     + window_internal_height (w));
-         
+
          /* Perform the operation on the screen.  */
          if (dvpos > 0)
            {
@@ -11899,10 +12511,10 @@ try_window_id (w)
              if (!scroll_region_ok)
                ins_del_lines (end + dvpos, -dvpos);
            }
-         
+
          set_terminal_window (0);
        }
-      
+
       update_end (f);
     }
 
@@ -11983,7 +12595,7 @@ try_window_id (w)
         get the right continuation_lines_width and current_x.  */
       it.continuation_lines_width = last_row->continuation_lines_width;
       it.hpos = it.current_x = 0;
-      
+
       /* Display the rest of the lines at the window end.  */
       it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
       while (it.current_y < it.last_visible_y
@@ -12012,7 +12624,7 @@ try_window_id (w)
       row = find_last_row_displaying_text (w->current_matrix, &it,
                                           first_unchanged_at_end_row);
       xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
-      
+
       w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
       w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
       w->window_end_vpos
@@ -12213,7 +12825,7 @@ dump_glyph_row (row, vpos, glyphs)
     {
       fprintf (stderr, "Row Start   End Used oEI><O\\CTZFesm     X    Y    W    H    V    A    P\n");
       fprintf (stderr, "=======================================================================\n");
-  
+
       fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d\
 %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d  %4d %4d %4d %4d %4d %4d %4d\n",
               vpos,
@@ -12249,7 +12861,7 @@ dump_glyph_row (row, vpos, glyphs)
       fprintf (stderr, "%9d %5d\n", row->start.dpvec_index,
               row->end.dpvec_index);
     }
-  
+
   if (glyphs > 1)
     {
       int area;
@@ -12258,14 +12870,14 @@ dump_glyph_row (row, vpos, glyphs)
        {
          struct glyph *glyph = row->glyphs[area];
          struct glyph *glyph_end = glyph + row->used[area];
-      
+
          /* Glyph for a line end in text.  */
          if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
            ++glyph_end;
-      
+
          if (glyph < glyph_end)
            fprintf (stderr, "  Glyph    Type Pos   O W    Code C Face LR\n");
-      
+
          for (; glyph < glyph_end; ++glyph)
            dump_glyph (row, glyph, area);
        }
@@ -12289,7 +12901,7 @@ dump_glyph_row (row, vpos, glyphs)
              else
                s[i] = '.';
            }
-      
+
          s[i] = '\0';
          fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
        }
@@ -12320,6 +12932,16 @@ glyphs in short form, otherwise show glyphs in long form.  */)
 }
 
 
+DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
+       Sdump_frame_glyph_matrix, 0, 0, "", doc: /* */)
+     ()
+{
+  struct frame *f = XFRAME (selected_frame);
+  dump_glyph_matrix (f->current_matrix, 1);
+  return Qnil;
+}
+
+
 DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "",
        doc: /* Dump glyph row ROW to stderr.
 GLYPH 0 means don't dump glyphs.
@@ -12330,7 +12952,7 @@ GLYPH > 1 or omitted means dump glyphs in long form.  */)
 {
   struct glyph_matrix *matrix;
   int vpos;
-  
+
   CHECK_NUMBER (row);
   matrix = XWINDOW (selected_window)->current_matrix;
   vpos = XINT (row);
@@ -12353,7 +12975,7 @@ GLYPH > 1 or omitted means dump glyphs in long form.  */)
   struct frame *sf = SELECTED_FRAME ();
   struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
   int vpos;
-  
+
   CHECK_NUMBER (row);
   vpos = XINT (row);
   if (vpos >= 0 && vpos < m->nrows)
@@ -12376,22 +12998,23 @@ With ARG, turn tracing on if and only if ARG is positive.  */)
       arg = Fprefix_numeric_value (arg);
       trace_redisplay_p = XINT (arg) > 0;
     }
-  
+
   return Qnil;
 }
 
 
 DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
-       doc: /* Like `format', but print result to stderr.  */)
+       doc: /* Like `format', but print result to stderr.
+usage: (trace-to-stderr STRING &rest OBJECTS)  */)
      (nargs, args)
      int nargs;
      Lisp_Object *args;
 {
   Lisp_Object s = Fformat (nargs, args);
-  fprintf (stderr, "%s", XSTRING (s)->data);
+  fprintf (stderr, "%s", SDATA (s));
   return Qnil;
 }
-       
+
 #endif /* GLYPH_DEBUG */
 
 
@@ -12410,10 +13033,10 @@ get_overlay_arrow_glyph_row (w)
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   struct buffer *buffer = XBUFFER (w->buffer);
   struct buffer *old = current_buffer;
-  unsigned char *arrow_string = XSTRING (Voverlay_arrow_string)->data;
-  int arrow_len = XSTRING (Voverlay_arrow_string)->size;
-  unsigned char *arrow_end = arrow_string + arrow_len;
-  unsigned char *p;
+  const unsigned char *arrow_string = SDATA (Voverlay_arrow_string);
+  int arrow_len = SCHARS (Voverlay_arrow_string);
+  const unsigned char *arrow_end = arrow_string + arrow_len;
+  const unsigned char *p;
   struct it it;
   int multibyte_p;
   int n_glyphs_before;
@@ -12428,14 +13051,14 @@ get_overlay_arrow_glyph_row (w)
   while (p < arrow_end)
     {
       Lisp_Object face, ilisp;
-      
+
       /* Get the next character.  */
       if (multibyte_p)
        it.c = string_char_and_length (p, arrow_len, &it.len);
       else
        it.c = *p, it.len = 1;
       p += it.len;
-      
+
       /* Get its face.  */
       ilisp = make_number (p - arrow_string);
       face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
@@ -12454,7 +13077,7 @@ get_overlay_arrow_glyph_row (w)
          break;
        }
     }
-  
+
   set_buffer_temp (old);
   return it.glyph_row;
 }
@@ -12484,7 +13107,7 @@ insert_left_trunc_glyphs (it)
   CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
   truncate_it.object = make_number (0);
   produce_special_glyphs (&truncate_it, IT_TRUNCATION);
-  
+
   /* Overwrite glyphs from IT with truncation glyphs.  */
   from = truncate_it.glyph_row->glyphs[TEXT_AREA];
   end = from + truncate_it.glyph_row->used[TEXT_AREA];
@@ -12547,7 +13170,7 @@ compute_line_metrics (it)
          row->phys_ascent = it->max_phys_ascent;
          row->phys_height = it->max_phys_ascent + it->max_phys_descent;
        }
-      
+
       /* Compute the width of this line.  */
       row->pixel_width = row->x;
       for (i = 0; i < row->used[TEXT_AREA]; ++i)
@@ -12571,7 +13194,7 @@ compute_line_metrics (it)
 
       /* Compute how much of the line is visible.  */
       row->visible_height = row->height;
-      
+
       min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (it->w);
       max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (it->w);
 
@@ -12645,7 +13268,7 @@ append_space (it, default_face_p)
 
          saved_object = it->object;
          saved_pos = it->position;
-         
+
          it->what = IT_CHARACTER;
          bzero (&it->position, sizeof it->position);
          it->object = make_number (0);
@@ -12660,7 +13283,7 @@ append_space (it, default_face_p)
          it->face_id = FACE_FOR_CHAR (it->f, face, 0);
 
          PRODUCE_GLYPHS (it);
-         
+
          it->current_x = saved_x;
          it->object = saved_object;
          it->position = saved_pos;
@@ -12680,7 +13303,7 @@ append_space (it, default_face_p)
    to the end of the display line.  Called from display_line.
    If the glyph row is empty, add a space glyph to it so that we
    know the face to draw.  Set the glyph row flag fill_line_p.  */
-   
+
 static void
 extend_face_to_end_of_line (it)
      struct it *it;
@@ -12691,7 +13314,7 @@ extend_face_to_end_of_line (it)
   /* If line is already filled, do nothing.  */
   if (it->current_x >= it->last_visible_x)
     return;
-  
+
   /* Face extension extends the background and box of IT->face_id
      to the end of the line.  If the background equals the background
      of the frame, we don't have to do anything.  */
@@ -12699,7 +13322,7 @@ extend_face_to_end_of_line (it)
     face = FACE_FROM_ID (it->f, it->saved_face_id);
   else
     face = FACE_FROM_ID (f, it->face_id);
-  
+
   if (FRAME_WINDOW_P (f)
       && face->box == FACE_NO_BOX
       && face->background == FRAME_BACKGROUND_PIXEL (f)
@@ -12741,19 +13364,19 @@ extend_face_to_end_of_line (it)
 
       saved_object = it->object;
       saved_pos = it->position;
-  
+
       it->what = IT_CHARACTER;
       bzero (&it->position, sizeof it->position);
       it->object = make_number (0);
       it->c = ' ';
       it->len = 1;
       it->face_id = face->id;
-      
+
       PRODUCE_GLYPHS (it);
-      
+
       while (it->current_x <= it->last_visible_x)
        PRODUCE_GLYPHS (it);
-      
+
       /* Don't count these blanks really.  It would let us insert a left
         truncation glyph below and make us set the cursor on them, maybe.  */
       it->current_x = saved_x;
@@ -12797,7 +13420,7 @@ highlight_trailing_whitespace (f, row)
      struct glyph_row *row;
 {
   int used = row->used[TEXT_AREA];
-  
+
   if (used)
     {
       struct glyph *start = row->glyphs[TEXT_AREA];
@@ -12823,7 +13446,7 @@ highlight_trailing_whitespace (f, row)
          && trailing_whitespace_p (glyph->charpos))
        {
          int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
-         
+
          while (glyph >= start
                 && BUFFERP (glyph->object)
                 && (glyph->type == STRETCH_GLYPH
@@ -12844,7 +13467,7 @@ cursor_row_p (w, row)
      struct glyph_row *row;
 {
   int cursor_row_p = 1;
-  
+
   if (PT == MATRIX_ROW_END_CHARPOS (row))
     {
       /* If the row ends with a newline from a string, we don't want
@@ -12871,7 +13494,7 @@ cursor_row_p (w, row)
    for an overview of struct it.  Value is non-zero if
    IT->glyph_row displays text, as opposed to a line displaying ZV
    only.  */
-   
+
 static int
 display_line (it)
      struct it *it;
@@ -12946,7 +13569,7 @@ display_line (it)
                      || (minibuf_level && EQ (it->window, minibuf_window))))
                row->indicate_empty_line_p = 1;
            }
-         
+
          it->continuation_lines_width = 0;
          row->ends_at_zv_p = 1;
          break;
@@ -12966,7 +13589,7 @@ display_line (it)
          phys_ascent = it->max_phys_ascent;
          phys_descent = it->max_phys_descent;
        }
-      
+
       PRODUCE_GLYPHS (it);
 
       /* If this display element was in marginal areas, continue with
@@ -13013,7 +13636,7 @@ display_line (it)
        {
          int new_x;
          struct glyph *glyph;
-         
+
          for (i = 0; i < nglyphs; ++i, x = new_x)
            {
              glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
@@ -13028,7 +13651,7 @@ display_line (it)
                          && FRAME_WINDOW_P (it->f))))
                {
                  /* End of a continued line.  */
-                 
+
                  if (it->hpos == 0
                      || (new_x == it->last_visible_x
                          && FRAME_WINDOW_P (it->f)))
@@ -13051,17 +13674,17 @@ display_line (it)
                         This means the whole character doesn't fit
                         on the line.  */
                      row->used[TEXT_AREA] = n_glyphs_before;
-                 
+
                      /* Fill the rest of the row with continuation
                         glyphs like in 20.x.  */
                      while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
                             < row->glyphs[1 + TEXT_AREA])
                        produce_special_glyphs (it, IT_CONTINUATION);
-                     
+
                      row->continued_p = 1;
                      it->current_x = x_before;
                      it->continuation_lines_width += x_before;
-                     
+
                      /* Restore the height to what it was before the
                         element not fitting on the line.  */
                      it->max_ascent = ascent;
@@ -13088,20 +13711,20 @@ display_line (it)
                         the right edge of the window.  Restore
                         positions to values before the element.  */
                      row->used[TEXT_AREA] = n_glyphs_before + i;
-                 
+
                      /* Display continuation glyphs.  */
                      if (!FRAME_WINDOW_P (it->f))
                        produce_special_glyphs (it, IT_CONTINUATION);
                      row->continued_p = 1;
 
                      it->continuation_lines_width += x;
-                     
+
                      if (nglyphs > 1 && i > 0)
                        {
                          row->ends_in_middle_of_char_p = 1;
                          it->starts_in_middle_of_char_p = 1;
                        }
-                     
+
                      /* Restore the height to what it was before the
                         element not fitting on the line.  */
                      it->max_ascent = ascent;
@@ -13116,7 +13739,7 @@ display_line (it)
                {
                  /* Increment number of glyphs actually displayed.  */
                  ++it->hpos;
-                 
+
                  if (x < it->first_visible_x)
                    /* Glyph is partially visible, i.e. row starts at
                       negative X position.  */
@@ -13126,18 +13749,19 @@ display_line (it)
                {
                  /* Glyph is completely off the left margin of the
                     window.  This should not happen because of the
-                    move_it_in_display_line at the start of
-                    this function.  */
-                 abort ();
+                    move_it_in_display_line at the start of this
+                    function, unless the text display area of the
+                    window is empty.  */
+                 xassert (it->first_visible_x <= it->last_visible_x);
                }
            }
-         
+
          row->ascent = max (row->ascent, it->max_ascent);
          row->height = max (row->height, it->max_ascent + it->max_descent);
          row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
          row->phys_height = max (row->phys_height,
                                  it->max_phys_ascent + it->max_phys_descent);
-         
+
          /* End of this display line if row is continued.  */
          if (row->continued_p)
            break;
@@ -13155,21 +13779,21 @@ display_line (it)
          /* Add a space at the end of the line that is used to
             display the cursor there.  */
          append_space (it, 0);
-         
+
          /* Extend the face to the end of the line.  */
          extend_face_to_end_of_line (it);
 
          /* Make sure we have the position.  */
          if (used_before == 0)
            row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
-         
+
          /* Consume the line end.  This skips over invisible lines.  */
          set_iterator_to_next (it, 1);
          it->continuation_lines_width = 0;
          break;
        }
 
-      /* Proceed with next display element.  Note that this skips 
+      /* Proceed with next display element.  Note that this skips
         over lines invisible because of selective display.  */
       set_iterator_to_next (it, 1);
 
@@ -13184,7 +13808,7 @@ display_line (it)
          if (!FRAME_WINDOW_P (it->f))
            {
              int i, n;
-             
+
              for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
                if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
                  break;
@@ -13195,7 +13819,7 @@ display_line (it)
                  produce_special_glyphs (it, IT_TRUNCATION);
                }
            }
-         
+
          row->truncated_on_right_p = 1;
          it->continuation_lines_width = 0;
          reseat_at_next_visible_line_start (it, 0);
@@ -13252,7 +13876,7 @@ display_line (it)
              row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
            }
        }
-      
+
       overlay_arrow_seen = 1;
       row->overlay_arrow_p = 1;
     }
@@ -13295,7 +13919,7 @@ display_line (it)
 
    The menu bar of X frames that don't have X toolkit support is
    displayed in a special window W->frame->menu_bar_window.
-   
+
    The menu bar of terminal frames is treated specially as far as
    glyph matrices are concerned.  Menu bar lines are not part of
    windows, so the update is done directly on the frame matrix rows
@@ -13315,11 +13939,11 @@ display_menu_bar (w)
   if (!NILP (Vwindow_system))
     return;
 #endif
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   if (FRAME_X_P (f))
     return;
 #endif
-#ifdef macintosh
+#ifdef MAC_OS
   if (FRAME_MAC_P (f))
     return;
 #endif
@@ -13383,7 +14007,7 @@ display_menu_bar (w)
       /* Display the item, pad with one space.  */
       if (it.current_x < it.last_visible_x)
        display_string (NULL, string, Qnil, 0, 0, &it,
-                       XSTRING (string)->size + 1, 0, 0, -1);
+                       SCHARS (string) + 1, 0, 0, -1);
     }
 
   /* Fill out the line with spaces.  */
@@ -13411,11 +14035,11 @@ redisplay_mode_lines (window, force)
      int force;
 {
   int nwindows = 0;
-  
+
   while (!NILP (window))
     {
       struct window *w = XWINDOW (window);
-      
+
       if (WINDOWP (w->hchild))
        nwindows += redisplay_mode_lines (w->hchild, force);
       else if (WINDOWP (w->vchild))
@@ -13430,13 +14054,13 @@ redisplay_mode_lines (window, force)
          /* Set the window's buffer for the mode line display.  */
          SET_TEXT_POS (lpoint, PT, PT_BYTE);
          set_buffer_internal_1 (XBUFFER (w->buffer));
-         
+
          /* Point refers normally to the selected window.  For any
             other window, set up appropriate value.  */
          if (!EQ (window, selected_window))
            {
              struct text_pos pt;
-             
+
              SET_TEXT_POS_FROM_MARKER (pt, w->pointm);
              if (CHARPOS (pt) < BEGV)
                TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
@@ -13480,7 +14104,7 @@ display_mode_lines (w)
   selected_frame = w->frame;
   old_selected_window = selected_window;
   XSETWINDOW (selected_window, w);
-  
+
   /* These will be set while the mode line specs are processed.  */
   line_number_displayed = 0;
   w->column_number_displayed = Qnil;
@@ -13494,7 +14118,7 @@ display_mode_lines (w)
                         current_buffer->mode_line_format);
       ++n;
     }
-  
+
   if (WINDOW_WANTS_HEADER_LINE_P (w))
     {
       display_mode_line (w, HEADER_LINE_FACE_ID,
@@ -13533,12 +14157,12 @@ display_mode_line (w, face_id, format)
      kboard-local variables in the mode_line_format will get the right
      values.  */
   push_frame_kboard (it.f);
-  display_mode_element (&it, 0, 0, 0, format, Qnil);
+  display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
   pop_frame_kboard ();
 
   /* Fill up with spaces.  */
   display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
-  
+
   compute_line_metrics (&it);
   it.glyph_row->full_width_p = 1;
   it.glyph_row->mode_line_p = 1;
@@ -13563,6 +14187,14 @@ display_mode_line (w, face_id, format)
    Each element is (PROPERTIZED-STRING . PROPERTY-LIST).  */
 Lisp_Object mode_line_proptrans_alist;
 
+/* List of strings making up the mode-line.  */
+Lisp_Object mode_line_string_list;
+
+/* Base face property when building propertized mode line string.  */
+static Lisp_Object mode_line_string_face;
+static Lisp_Object mode_line_string_face_prop;
+
+
 /* Contribute ELT to the mode line for window IT->w.  How it
    translates into text depends on its data type.
 
@@ -13576,14 +14208,23 @@ Lisp_Object mode_line_proptrans_alist;
    characters to display from ELT's representation.  See
    display_string for details.
 
-   Returns the hpos of the end of the text generated by ELT.  */
+   Returns the hpos of the end of the text generated by ELT.
+
+   PROPS is a property list to add to any string we encounter.
+
+   If RISKY is nonzero, remove (disregard) any properties in any string
+   we encounter, and ignore :eval and :propertize.
+
+   If the global variable `frame_title_ptr' is non-NULL, then the output
+   is passed to `store_frame_title' instead of `display_string'.  */
 
 static int
-display_mode_element (it, depth, field_width, precision, elt, props)
+display_mode_element (it, depth, field_width, precision, elt, props, risky)
      struct it *it;
      int depth;
      int field_width, precision;
      Lisp_Object elt, props;
+     int risky;
 {
   int n = 0, field, prec;
   int literal = 0;
@@ -13600,17 +14241,18 @@ display_mode_element (it, depth, field_width, precision, elt, props)
       {
        /* A string: output it and check for %-constructs within it.  */
        unsigned char c;
-       unsigned char *this, *lisp_string;
+       const unsigned char *this, *lisp_string;
 
-       if (!NILP (props))
+       if (!NILP (props) || risky)
          {
            Lisp_Object oprops, aelt;
            oprops = Ftext_properties_at (make_number (0), elt);
-           if (NILP (Fequal (props, oprops)))
+
+           if (NILP (Fequal (props, oprops)) || risky)
              {
                /* If the starting string has properties,
                   merge the specified ones onto the existing ones.  */
-               if (! NILP (oprops))
+               if (! NILP (oprops) && !risky)
                  {
                    Lisp_Object tem;
 
@@ -13627,26 +14269,42 @@ display_mode_element (it, depth, field_width, precision, elt, props)
 
                aelt = Fassoc (elt, mode_line_proptrans_alist);
                if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
-                 elt = XCAR (aelt);
+                 {
+                   mode_line_proptrans_alist
+                     = Fcons (aelt, Fdelq (aelt, mode_line_proptrans_alist));
+                   elt = XCAR (aelt);
+                 }
                else
                  {
+                   Lisp_Object tem;
+
                    elt = Fcopy_sequence (elt);
-                   Fset_text_properties (0, Flength (elt), props, elt);
+                   Fset_text_properties (make_number (0), Flength (elt),
+                                         props, elt);
+                   /* Add this item to mode_line_proptrans_alist.  */
                    mode_line_proptrans_alist
                      = Fcons (Fcons (elt, props),
                               mode_line_proptrans_alist);
+                   /* Truncate mode_line_proptrans_alist
+                      to at most 50 elements.  */
+                   tem = Fnthcdr (make_number (50),
+                                  mode_line_proptrans_alist);
+                   if (! NILP (tem))
+                     XSETCDR (tem, Qnil);
                  }
              }
          }
 
-       this = XSTRING (elt)->data;
+       this = SDATA (elt);
        lisp_string = this;
 
        if (literal)
          {
            prec = precision - n;
            if (frame_title_ptr)
-             n += store_frame_title (XSTRING (elt)->data, -1, prec);
+             n += store_frame_title (SDATA (elt), -1, prec);
+           else if (!NILP (mode_line_string_list))
+             n += store_mode_line_string (NULL, elt, 1, 0, prec, Qnil);
            else
              n += display_string (NULL, elt, Qnil, 0, 0, it,
                                   0, prec, 0, STRING_MULTIBYTE (elt));
@@ -13657,14 +14315,15 @@ display_mode_element (it, depth, field_width, precision, elt, props)
        while ((precision <= 0 || n < precision)
               && *this
               && (frame_title_ptr
+                  || !NILP (mode_line_string_list)
                   || it->current_x < it->last_visible_x))
          {
-           unsigned char *last = this;
+           const unsigned char *last = this;
 
            /* Advance to end of string or next format specifier.  */
            while ((c = *this++) != '\0' && c != '%')
              ;
-           
+
            if (this - 1 != last)
              {
                /* Output to end of string or up to '%'.  Field width
@@ -13675,9 +14334,18 @@ display_mode_element (it, depth, field_width, precision, elt, props)
                prec = chars_in_text (last, this - last);
                if (precision > 0 && prec > precision - n)
                  prec = precision - n;
-               
+
                if (frame_title_ptr)
                  n += store_frame_title (last, 0, prec);
+               else if (!NILP (mode_line_string_list))
+                 {
+                   int bytepos = last - lisp_string;
+                   int charpos = string_byte_to_char (elt, bytepos);
+                   n += store_mode_line_string (NULL,
+                                                Fsubstring (elt, make_number (charpos),
+                                                            make_number (charpos + prec)),
+                                                0, 0, 0, Qnil);
+                 }
                else
                  {
                    int bytepos = last - lisp_string;
@@ -13689,8 +14357,8 @@ display_mode_element (it, depth, field_width, precision, elt, props)
              }
            else /* c == '%' */
              {
-               unsigned char *percent_position = this;
-               
+               const unsigned char *percent_position = this;
+
                /* Get the specified minimum width.  Zero means
                   don't pad.  */
                field = 0;
@@ -13703,16 +14371,17 @@ display_mode_element (it, depth, field_width, precision, elt, props)
 
                /* Note that either PRECISION <= 0 or N < PRECISION.  */
                prec = precision - n;
-               
+
                if (c == 'M')
                  n += display_mode_element (it, depth, field, prec,
-                                            Vglobal_mode_string, props);
+                                            Vglobal_mode_string, props,
+                                            risky);
                else if (c != 0)
                  {
                    int multibyte;
                    int bytepos, charpos;
                    unsigned char *spec;
-                       
+
                    bytepos = percent_position - lisp_string;
                    charpos = (STRING_MULTIBYTE (elt)
                               ? string_byte_to_char (elt, bytepos)
@@ -13723,10 +14392,18 @@ display_mode_element (it, depth, field_width, precision, elt, props)
 
                    if (frame_title_ptr)
                      n += store_frame_title (spec, field, prec);
+                   else if (!NILP (mode_line_string_list))
+                     {
+                       int len = strlen (spec);
+                       Lisp_Object tem = make_string (spec, len);
+                       props = Ftext_properties_at (make_number (charpos), elt);
+                       /* Should only keep face property in props */
+                       n += store_mode_line_string (NULL, tem, 0, field, prec, props);
+                     }
                    else
                      {
                        int nglyphs_before, nwritten;
-                       
+
                        nglyphs_before = it->glyph_row->used[TEXT_AREA];
                        nwritten = display_string (spec, Qnil, elt,
                                                   charpos, 0, it,
@@ -13748,7 +14425,7 @@ display_mode_element (it, depth, field_width, precision, elt, props)
                                glyph[i].object = elt;
                                glyph[i].charpos = charpos;
                              }
-                           
+
                            n += nwritten;
                          }
                      }
@@ -13767,6 +14444,12 @@ display_mode_element (it, depth, field_width, precision, elt, props)
         literally.  */
       {
        register Lisp_Object tem;
+
+       /* If the variable is not marked as risky to set
+          then its contents are risky to use.  */
+       if (NILP (Fget (elt, Qrisky_local_variable)))
+         risky = 1;
+
        tem = Fboundp (elt);
        if (!NILP (tem))
          {
@@ -13805,24 +14488,30 @@ display_mode_element (it, depth, field_width, precision, elt, props)
            /* An element of the form (:eval FORM) means evaluate FORM
               and use the result as mode line elements.  */
 
+           if (risky)
+             break;
+
            if (CONSP (XCDR (elt)))
              {
                Lisp_Object spec;
                spec = safe_eval (XCAR (XCDR (elt)));
                n += display_mode_element (it, depth, field_width - n,
-                                          precision - n, spec, props);
+                                          precision - n, spec, props,
+                                          risky);
              }
          }
        else if (EQ (car, QCpropertize))
          {
+           /* An element of the form (:propertize ELT PROPS...)
+              means display ELT but applying properties PROPS.  */
+
+           if (risky)
+             break;
+
            if (CONSP (XCDR (elt)))
-             {
-               /* An element of the form (:propertize ELT PROPS...)
-                  means display ELT but applying properties PROPS.  */
-               n += display_mode_element (it, depth, field_width - n,
-                                          precision - n, XCAR (XCDR (elt)),
-                                          XCDR (XCDR (elt)));
-             }
+             n += display_mode_element (it, depth, field_width - n,
+                                        precision - n, XCAR (XCDR (elt)),
+                                        XCDR (XCDR (elt)), risky);
          }
        else if (SYMBOLP (car))
          {
@@ -13887,7 +14576,8 @@ display_mode_element (it, depth, field_width, precision, elt, props)
                   && (precision <= 0 || n < precision))
              {
                n += display_mode_element (it, depth, field_width - n,
-                                          precision - n, XCAR (elt), props);
+                                          precision - n, XCAR (elt),
+                                          props, risky);
                elt = XCDR (elt);
              }
          }
@@ -13898,6 +14588,8 @@ display_mode_element (it, depth, field_width, precision, elt, props)
     invalid:
       if (frame_title_ptr)
        n += store_frame_title ("*invalid*", 0, precision - n);
+      else if (!NILP (mode_line_string_list))
+       n += store_mode_line_string ("*invalid*", Qnil, 0, 0, precision - n, Qnil);
       else
        n += display_string ("*invalid*", Qnil, Qnil, 0, 0, it, 0,
                             precision - n, 0, 0);
@@ -13909,15 +14601,215 @@ display_mode_element (it, depth, field_width, precision, elt, props)
     {
       if (frame_title_ptr)
        n += store_frame_title ("", field_width - n, 0);
+      else if (!NILP (mode_line_string_list))
+       n += store_mode_line_string ("", Qnil, 0, field_width - n, 0, Qnil);
       else
        n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
                             0, 0, 0);
     }
-  
+
+  return n;
+}
+
+/* Store a mode-line string element in mode_line_string_list.
+
+   If STRING is non-null, display that C string.  Otherwise, the Lisp
+   string LISP_STRING is displayed.
+
+   FIELD_WIDTH is the minimum number of output glyphs to produce.
+   If STRING has fewer characters than FIELD_WIDTH, pad to the right
+   with spaces.  FIELD_WIDTH <= 0 means don't pad.
+
+   PRECISION is the maximum number of characters to output from
+   STRING.  PRECISION <= 0  means don't truncate the string.
+
+   If COPY_STRING is non-zero, make a copy of LISP_STRING before adding
+   properties to the string.
+
+   PROPS are the properties to add to the string.
+   The mode_line_string_face face property is always added to the string.
+ */
+
+static int store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props)
+     char *string;
+     Lisp_Object lisp_string;
+     int copy_string;
+     int field_width;
+     int precision;
+     Lisp_Object props;
+{
+  int len;
+  int n = 0;
+
+  if (string != NULL)
+    {
+      len = strlen (string);
+      if (precision > 0 && len > precision)
+       len = precision;
+      lisp_string = make_string (string, len);
+      if (NILP (props))
+       props = mode_line_string_face_prop;
+      else if (!NILP (mode_line_string_face))
+       {
+         Lisp_Object face = Fplist_get (props, Qface);
+         props = Fcopy_sequence (props);
+         if (NILP (face))
+           face = mode_line_string_face;
+         else
+           face = Fcons (face, Fcons (mode_line_string_face, Qnil));
+         props = Fplist_put (props, Qface, face);
+       }
+      Fadd_text_properties (make_number (0), make_number (len),
+                           props, lisp_string);
+    }
+  else
+    {
+      len = XFASTINT (Flength (lisp_string));
+      if (precision > 0 && len > precision)
+       {
+         len = precision;
+         lisp_string = Fsubstring (lisp_string, make_number (0), make_number (len));
+         precision = -1;
+       }
+      if (!NILP (mode_line_string_face))
+       {
+         Lisp_Object face;
+         if (NILP (props))
+           props = Ftext_properties_at (make_number (0), lisp_string);
+         face = Fplist_get (props, Qface);
+         if (NILP (face))
+           face = mode_line_string_face;
+         else
+           face = Fcons (face, Fcons (mode_line_string_face, Qnil));
+         props = Fcons (Qface, Fcons (face, Qnil));
+         if (copy_string)
+           lisp_string = Fcopy_sequence (lisp_string);
+       }
+      if (!NILP (props))
+       Fadd_text_properties (make_number (0), make_number (len),
+                             props, lisp_string);
+    }
+
+  if (len > 0)
+    {
+      mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
+      n += len;
+    }
+
+  if (field_width > len)
+    {
+      field_width -= len;
+      lisp_string = Fmake_string (make_number (field_width), make_number (' '));
+      if (!NILP (props))
+       Fadd_text_properties (make_number (0), make_number (field_width),
+                             props, lisp_string);
+      mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
+      n += field_width;
+    }
+
   return n;
 }
 
 
+DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
+       0, 3, 0,
+       doc: /* Return the mode-line of selected window as a string.
+First optional arg FORMAT specifies a different format string (see
+`mode-line-format' for details) to use.  If FORMAT is t, return
+the buffer's header-line.  Second optional arg WINDOW specifies a
+different window to use as the context for the formatting.
+If third optional arg NO-PROPS is non-nil, string is not propertized.  */)
+     (format, window, no_props)
+     Lisp_Object format, window, no_props;
+{
+  struct it it;
+  int len;
+  struct window *w;
+  struct buffer *old_buffer = NULL;
+  enum face_id face_id = DEFAULT_FACE_ID;
+
+  if (NILP (window))
+    window = selected_window;
+  CHECK_WINDOW (window);
+  w = XWINDOW (window);
+  CHECK_BUFFER (w->buffer);
+
+  if (XBUFFER (w->buffer) != current_buffer)
+    {
+      old_buffer = current_buffer;
+      set_buffer_internal_1 (XBUFFER (w->buffer));
+    }
+
+  if (NILP (format) || EQ (format, Qt))
+    {
+      face_id = NILP (format)
+       ? CURRENT_MODE_LINE_FACE_ID (w) :
+       HEADER_LINE_FACE_ID;
+      format = NILP (format)
+       ? current_buffer->mode_line_format
+       : current_buffer->header_line_format;
+    }
+
+  init_iterator (&it, w, -1, -1, NULL, face_id);
+
+  if (NILP (no_props))
+    {
+      mode_line_string_face =
+       (face_id == MODE_LINE_FACE_ID ? Qmode_line :
+        face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive :
+        face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil);
+
+      mode_line_string_face_prop =
+       NILP (mode_line_string_face) ? Qnil :
+       Fcons (Qface, Fcons (mode_line_string_face, Qnil));
+
+      /* We need a dummy last element in mode_line_string_list to
+        indicate we are building the propertized mode-line string.
+        Using mode_line_string_face_prop here GC protects it.  */
+      mode_line_string_list =
+       Fcons (mode_line_string_face_prop, Qnil);
+      frame_title_ptr = NULL;
+    }
+  else
+    {
+      mode_line_string_face_prop = Qnil;
+      mode_line_string_list = Qnil;
+      frame_title_ptr = frame_title_buf;
+    }
+
+  push_frame_kboard (it.f);
+  display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
+  pop_frame_kboard ();
+
+  if (old_buffer)
+    set_buffer_internal_1 (old_buffer);
+
+  if (NILP (no_props))
+    {
+      Lisp_Object str;
+      mode_line_string_list = Fnreverse (mode_line_string_list);
+      str = Fmapconcat (intern ("identity"), XCDR (mode_line_string_list),
+                       make_string ("", 0));
+      mode_line_string_face_prop = Qnil;
+      mode_line_string_list = Qnil;
+      return str;
+    }
+
+  len = frame_title_ptr - frame_title_buf;
+  if (len > 0 && frame_title_ptr[-1] == '-')
+    {
+      /* Mode lines typically ends with numerous dashes; reduce to two dashes.  */
+      while (frame_title_ptr > frame_title_buf && *--frame_title_ptr == '-')
+       ;
+      frame_title_ptr += 3;  /* restore last non-dash + two dashes */
+      if (len > frame_title_ptr - frame_title_buf)
+       len = frame_title_ptr - frame_title_buf;
+    }
+
+  frame_title_ptr = NULL;
+  return make_string (frame_title_buf, len);
+}
+
 /* Write a null-terminated, right justified decimal representation of
    the positive integer D to BUF using a minimal field width WIDTH.  */
 
@@ -13928,7 +14820,7 @@ pint2str (buf, width, d)
      register int d;
 {
   register char *p = buf;
-  
+
   if (d <= 0)
     *p++ = '0';
   else
@@ -13939,7 +14831,7 @@ pint2str (buf, width, d)
          d /= 10;
        }
     }
-  
+
   for (width -= (int) (p - buf); width > 0; --width)
     *p++ = ' ';
   *p-- = '\0';
@@ -13965,7 +14857,7 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
 {
   Lisp_Object val;
   int multibyte = !NILP (current_buffer->enable_multibyte_characters);
-  unsigned char *eol_str;
+  const unsigned char *eol_str;
   int eol_str_len;
   /* The EOL conversion we are using.  */
   Lisp_Object eoltype;
@@ -14005,20 +14897,21 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
                          ? eol_mnemonic_dos : eol_mnemonic_mac));
        }
     }
-  
+
   if (eol_flag)
     {
       /* Mention the EOL conversion if it is not the usual one.  */
       if (STRINGP (eoltype))
        {
-         eol_str = XSTRING (eoltype)->data;
-         eol_str_len = XSTRING (eoltype)->size;
+         eol_str = SDATA (eoltype);
+         eol_str_len = SBYTES (eoltype);
        }
       else if (INTEGERP (eoltype)
               && CHAR_VALID_P (XINT (eoltype), 0))
        {
-         eol_str = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
-         eol_str_len = CHAR_STRING (XINT (eoltype), eol_str);
+         unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
+         eol_str_len = CHAR_STRING (XINT (eoltype), tmp);
+         eol_str = tmp;
        }
       else
        {
@@ -14081,7 +14974,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
     case '%':
       return "%";
 
-    case '[': 
+    case '[':
       {
        int i;
        char *p;
@@ -14095,7 +14988,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
        return decode_mode_spec_buf;
       }
 
-    case ']': 
+    case ']':
       {
        int i;
        char *p;
@@ -14114,6 +15007,8 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
        register int i;
 
        /* Let lots_of_dashes be a string of infinite length.  */
+       if (!NILP (mode_line_string_list))
+         return "--";
        if (field_width <= 0
            || field_width > sizeof (lots_of_dashes))
          {
@@ -14126,13 +15021,13 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
          return lots_of_dashes;
       }
 
-    case 'b': 
+    case 'b':
       obj = b->name;
       break;
 
     case 'c':
       {
-       int col = current_column ();
+       int col = (int) current_column (); /* iftc */
        w->column_number_displayed = make_number (col);
        pint2str (decode_mode_spec_buf, field_width, col);
        return decode_mode_spec_buf;
@@ -14141,12 +15036,12 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
     case 'F':
       /* %F displays the frame name.  */
       if (!NILP (f->title))
-       return (char *) XSTRING (f->title)->data;
+       return (char *) SDATA (f->title);
       if (f->explicit_name || ! FRAME_WINDOW_P (f))
-       return (char *) XSTRING (f->name)->data;
+       return (char *) SDATA (f->name);
       return "Emacs";
 
-    case 'f': 
+    case 'f':
       obj = b->filename;
       break;
 
@@ -14158,7 +15053,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
        int nlines, junk;
        int height = XFASTINT (w->height);
 
-       /* If we decided that this buffer isn't suitable for line numbers, 
+       /* If we decided that this buffer isn't suitable for line numbers,
           don't forget that too fast.  */
        if (EQ (w->base_line_pos, w->buffer))
          goto no_value;
@@ -14224,7 +15119,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
                                          limit_byte,
                                          - (height * 2 + 30),
                                          &position);
-           /* If we couldn't find the lines we wanted within 
+           /* If we couldn't find the lines we wanted within
               line_number_display_limit_width chars per line,
               give up on line numbers for this window.  */
            if (position == limit_byte && limit == startpos - distance)
@@ -14262,7 +15157,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
       }
       break;
 
-    case 'm': 
+    case 'm':
       obj = b->mode_name;
       break;
 
@@ -14389,7 +15284,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
   if (STRINGP (obj))
     {
       *multibyte = STRING_MULTIBYTE (obj);
-      return (char *) XSTRING (obj)->data;
+      return (char *) SDATA (obj);
     }
   else
     return "";
@@ -14522,7 +15417,7 @@ display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
    If STRING has fewer characters than FIELD_WIDTH, pad to the right
    with spaces.  If STRING has more characters, more than FIELD_WIDTH
    glyphs will be produced.  FIELD_WIDTH <= 0 means don't pad.
-   
+
    PRECISION is the maximum number of characters to output from
    STRING.  PRECISION < 0  means don't truncate the string.
 
@@ -14568,7 +15463,7 @@ display_string (string, lisp_string, face_string, face_string_pos,
     {
       int endptr;
       struct face *face;
-      
+
       it->face_id
        = face_at_string_position (it->w, face_string, face_string_pos,
                                   0, it->region_beg_charpos,
@@ -14617,7 +15512,7 @@ display_string (string, lisp_string, face_string, face_string_pos,
       while (i < nglyphs)
        {
          struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
-         
+
          if (!it->truncate_lines_p
              && x + glyph->pixel_width > max_x)
            {
@@ -14712,7 +15607,7 @@ display_string (string, lisp_string, face_string, face_string_pos,
     }
 
   it->face_id = saved_face_id;
-  
+
   /* Value is number of columns displayed.  */
   return it->hpos - hpos_at_start;
 }
@@ -14733,7 +15628,7 @@ invisible_p (propval, list)
      Lisp_Object list;
 {
   register Lisp_Object tail, proptail;
-  
+
   for (tail = list; CONSP (tail); tail = XCDR (tail))
     {
       register Lisp_Object tem;
@@ -14743,7 +15638,7 @@ invisible_p (propval, list)
       if (CONSP (tem) && EQ (propval, XCAR (tem)))
        return NILP (XCDR (tem)) ? 1 : 2;
     }
-  
+
   if (CONSP (propval))
     {
       for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
@@ -14761,168 +15656,2434 @@ invisible_p (propval, list)
            }
        }
     }
-  
+
   return 0;
 }
 
 \f
 /***********************************************************************
-                           Initialization
+                            Glyph Display
  ***********************************************************************/
 
+#ifdef HAVE_WINDOW_SYSTEM
+
+#if GLYPH_DEBUG
+
 void
-syms_of_xdisp ()
+dump_glyph_string (s)
+     struct glyph_string *s;
 {
-  Vwith_echo_area_save_vector = Qnil;
-  staticpro (&Vwith_echo_area_save_vector);
+  fprintf (stderr, "glyph string\n");
+  fprintf (stderr, "  x, y, w, h = %d, %d, %d, %d\n",
+          s->x, s->y, s->width, s->height);
+  fprintf (stderr, "  ybase = %d\n", s->ybase);
+  fprintf (stderr, "  hl = %d\n", s->hl);
+  fprintf (stderr, "  left overhang = %d, right = %d\n",
+          s->left_overhang, s->right_overhang);
+  fprintf (stderr, "  nchars = %d\n", s->nchars);
+  fprintf (stderr, "  extends to end of line = %d\n",
+          s->extends_to_end_of_line_p);
+  fprintf (stderr, "  font height = %d\n", FONT_HEIGHT (s->font));
+  fprintf (stderr, "  bg width = %d\n", s->background_width);
+}
 
-  Vmessage_stack = Qnil;
-  staticpro (&Vmessage_stack);
-  
-  Qinhibit_redisplay = intern ("inhibit-redisplay");
-  staticpro (&Qinhibit_redisplay);
+#endif /* GLYPH_DEBUG */
 
-  message_dolog_marker1 = Fmake_marker ();
-  staticpro (&message_dolog_marker1);
-  message_dolog_marker2 = Fmake_marker ();
-  staticpro (&message_dolog_marker2);
-  message_dolog_marker3 = Fmake_marker ();
-  staticpro (&message_dolog_marker3);
+/* Initialize glyph string S.  CHAR2B is a suitably allocated vector
+   of XChar2b structures for S; it can't be allocated in
+   init_glyph_string because it must be allocated via `alloca'.  W
+   is the window on which S is drawn.  ROW and AREA are the glyph row
+   and area within the row from which S is constructed.  START is the
+   index of the first glyph structure covered by S.  HL is a
+   face-override for drawing S.  */
 
-#if GLYPH_DEBUG
-  defsubr (&Sdump_glyph_matrix);
-  defsubr (&Sdump_glyph_row);
-  defsubr (&Sdump_tool_bar_row);
-  defsubr (&Strace_redisplay);
-  defsubr (&Strace_to_stderr);
+#ifdef HAVE_NTGUI
+#define OPTIONAL_HDC(hdc)  hdc,
+#define DECLARE_HDC(hdc)   HDC hdc;
+#define ALLOCATE_HDC(hdc, f) hdc = get_frame_dc ((f))
+#define RELEASE_HDC(hdc, f)  release_frame_dc ((f), (hdc))
 #endif
-#ifdef HAVE_WINDOW_SYSTEM
-  defsubr (&Stool_bar_lines_needed);
+
+#ifndef OPTIONAL_HDC
+#define OPTIONAL_HDC(hdc)
+#define DECLARE_HDC(hdc)
+#define ALLOCATE_HDC(hdc, f)
+#define RELEASE_HDC(hdc, f)
 #endif
 
-  staticpro (&Qmenu_bar_update_hook);
-  Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
+static void
+init_glyph_string (s, OPTIONAL_HDC (hdc) char2b, w, row, area, start, hl)
+     struct glyph_string *s;
+     DECLARE_HDC (hdc)
+     XChar2b *char2b;
+     struct window *w;
+     struct glyph_row *row;
+     enum glyph_row_area area;
+     int start;
+     enum draw_glyphs_face hl;
+{
+  bzero (s, sizeof *s);
+  s->w = w;
+  s->f = XFRAME (w->frame);
+#ifdef HAVE_NTGUI
+  s->hdc = hdc;
+#endif
+  s->display = FRAME_X_DISPLAY (s->f);
+  s->window = FRAME_X_WINDOW (s->f);
+  s->char2b = char2b;
+  s->hl = hl;
+  s->row = row;
+  s->area = area;
+  s->first_glyph = row->glyphs[area] + start;
+  s->height = row->height;
+  s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+
+  /* Display the internal border below the tool-bar window.  */
+  if (s->w == XWINDOW (s->f->tool_bar_window))
+    s->y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
+
+  s->ybase = s->y + row->ascent;
+}
 
-  staticpro (&Qoverriding_terminal_local_map);
-  Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
 
-  staticpro (&Qoverriding_local_map);
-  Qoverriding_local_map = intern ("overriding-local-map");
+/* 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.  */
 
-  staticpro (&Qwindow_scroll_functions);
-  Qwindow_scroll_functions = intern ("window-scroll-functions");
+static INLINE void
+append_glyph_string_lists (head, tail, h, t)
+     struct glyph_string **head, **tail;
+     struct glyph_string *h, *t;
+{
+  if (h)
+    {
+      if (*head)
+       (*tail)->next = h;
+      else
+       *head = h;
+      h->prev = *tail;
+      *tail = t;
+    }
+}
 
-  staticpro (&Qredisplay_end_trigger_functions);
-  Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
-  
-  staticpro (&Qinhibit_point_motion_hooks);
-  Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
 
-  QCdata = intern (":data");
-  staticpro (&QCdata);
-  Qdisplay = intern ("display");
-  staticpro (&Qdisplay);
-  Qspace_width = intern ("space-width");
-  staticpro (&Qspace_width);
-  Qraise = intern ("raise");
-  staticpro (&Qraise);
-  Qspace = intern ("space");
-  staticpro (&Qspace);
-  Qmargin = intern ("margin");
-  staticpro (&Qmargin);
-  Qleft_margin = intern ("left-margin");
-  staticpro (&Qleft_margin);
-  Qright_margin = intern ("right-margin");
-  staticpro (&Qright_margin);
-  Qalign_to = intern ("align-to");
-  staticpro (&Qalign_to);
-  QCalign_to = intern (":align-to");
-  staticpro (&QCalign_to);
-  Qrelative_width = intern ("relative-width");
-  staticpro (&Qrelative_width);
-  QCrelative_width = intern (":relative-width");
-  staticpro (&QCrelative_width);
-  QCrelative_height = intern (":relative-height");
-  staticpro (&QCrelative_height);
-  QCeval = intern (":eval");
-  staticpro (&QCeval);
-  QCpropertize = intern (":propertize");
-  staticpro (&QCpropertize);
-  Qwhen = intern ("when");
-  staticpro (&Qwhen);
-  QCfile = intern (":file");
-  staticpro (&QCfile);
-  Qfontified = intern ("fontified");
-  staticpro (&Qfontified);
-  Qfontification_functions = intern ("fontification-functions");
-  staticpro (&Qfontification_functions);
-  Qtrailing_whitespace = intern ("trailing-whitespace");
-  staticpro (&Qtrailing_whitespace);
-  Qimage = intern ("image");
-  staticpro (&Qimage);
-  Qmessage_truncate_lines = intern ("message-truncate-lines");
-  staticpro (&Qmessage_truncate_lines);
-  Qcursor_in_non_selected_windows = intern ("cursor-in-non-selected-windows");
-  staticpro (&Qcursor_in_non_selected_windows);
-  Qgrow_only = intern ("grow-only");
-  staticpro (&Qgrow_only);
-  Qinhibit_menubar_update = intern ("inhibit-menubar-update");
-  staticpro (&Qinhibit_menubar_update);
-  Qinhibit_eval_during_redisplay = intern ("inhibit-eval-during-redisplay");
-  staticpro (&Qinhibit_eval_during_redisplay);
-  Qposition = intern ("position");
-  staticpro (&Qposition);
-  Qbuffer_position = intern ("buffer-position");
-  staticpro (&Qbuffer_position);
-  Qobject = intern ("object");
-  staticpro (&Qobject);
+/* Prepend 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.  */
 
-  last_arrow_position = Qnil;
-  last_arrow_string = Qnil;
-  staticpro (&last_arrow_position);
-  staticpro (&last_arrow_string);
-  
-  echo_buffer[0] = echo_buffer[1] = Qnil;
-  staticpro (&echo_buffer[0]);
-  staticpro (&echo_buffer[1]);
+static INLINE void
+prepend_glyph_string_lists (head, tail, h, t)
+     struct glyph_string **head, **tail;
+     struct glyph_string *h, *t;
+{
+  if (h)
+    {
+      if (*head)
+       (*head)->prev = t;
+      else
+       *tail = t;
+      t->next = *head;
+      *head = h;
+    }
+}
 
-  echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
-  staticpro (&echo_area_buffer[0]);
-  staticpro (&echo_area_buffer[1]);
 
-  Vmessages_buffer_name = build_string ("*Messages*");
-  staticpro (&Vmessages_buffer_name);
+/* Append glyph string S to the list with head *HEAD and tail *TAIL.
+   Set *HEAD and *TAIL to the resulting list.  */
 
-  mode_line_proptrans_alist = Qnil;
-  staticpro (&mode_line_proptrans_alist);
-  
-  DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
-    doc: /* Non-nil means highlight trailing whitespace.
-The face used for trailing whitespace is `trailing-whitespace'.  */);
-  Vshow_trailing_whitespace = Qnil;
+static INLINE void
+append_glyph_string (head, tail, s)
+     struct glyph_string **head, **tail;
+     struct glyph_string *s;
+{
+  s->next = s->prev = NULL;
+  append_glyph_string_lists (head, tail, s, s);
+}
 
-  DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
-    doc: /* Non-nil means don't actually do any redisplay.
-This is used for internal purposes.  */);
-  Vinhibit_redisplay = Qnil;
 
-  DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
-    doc: /* String (or mode line construct) included (normally) in `mode-line-format'.  */);
-  Vglobal_mode_string = Qnil;
+/* Get face and two-byte form of character glyph GLYPH on frame F.
+   The encoding of GLYPH->u.ch is returned in *CHAR2B.  Value is
+   a pointer to a realized face that is ready for display.  */
 
-  DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
-    doc: /* Marker for where to display an arrow on top of the buffer text.
-This must be the beginning of a line in order to work.
-See also `overlay-arrow-string'.  */);
-  Voverlay_arrow_position = Qnil;
+static INLINE struct face *
+get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
+     struct frame *f;
+     struct glyph *glyph;
+     XChar2b *char2b;
+     int *two_byte_p;
+{
+  struct face *face;
 
-  DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
-    doc: /* String to display as an arrow.  See also `overlay-arrow-position'.  */);
-  Voverlay_arrow_string = Qnil;
+  xassert (glyph->type == CHAR_GLYPH);
+  face = FACE_FROM_ID (f, glyph->face_id);
 
-  DEFVAR_INT ("scroll-step", &scroll_step,
-    doc: /* *The number of lines to try scrolling a window by when point moves out.
-If that fails to bring point back on frame, point is centered instead.
+  if (two_byte_p)
+    *two_byte_p = 0;
+
+  if (!glyph->multibyte_p)
+    {
+      /* Unibyte case.  We don't have to encode, but we have to make
+        sure to use a face suitable for unibyte.  */
+      STORE_XCHAR2B (char2b, 0, glyph->u.ch);
+    }
+  else if (glyph->u.ch < 128
+          && glyph->face_id < BASIC_FACE_ID_SENTINEL)
+    {
+      /* Case of ASCII in a face known to fit ASCII.  */
+      STORE_XCHAR2B (char2b, 0, glyph->u.ch);
+    }
+  else
+    {
+      int c1, c2, charset;
+
+      /* Split characters into bytes.  If c2 is -1 afterwards, C is
+        really a one-byte character so that byte1 is zero.  */
+      SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
+      if (c2 > 0)
+       STORE_XCHAR2B (char2b, c1, c2);
+      else
+       STORE_XCHAR2B (char2b, 0, c1);
+
+      /* Maybe encode the character in *CHAR2B.  */
+      if (charset != CHARSET_ASCII)
+       {
+         struct font_info *font_info
+           = FONT_INFO_FROM_ID (f, face->font_info_id);
+         if (font_info)
+           glyph->font_type
+             = rif->encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
+       }
+    }
+
+  /* Make sure X resources of the face are allocated.  */
+  xassert (face != NULL);
+  PREPARE_FACE_FOR_DISPLAY (f, face);
+  return face;
+}
+
+
+/* Fill glyph string S with composition components specified by S->cmp.
+
+   FACES is an array of faces for all components of this composition.
+   S->gidx is the index of the first component for S.
+   OVERLAPS_P non-zero means S should draw the foreground only, and
+   use its physical height for clipping.
+
+   Value is the index of a component not in S.  */
+
+static int
+fill_composite_glyph_string (s, faces, overlaps_p)
+     struct glyph_string *s;
+     struct face **faces;
+     int overlaps_p;
+{
+  int i;
+
+  xassert (s);
+
+  s->for_overlaps_p = overlaps_p;
+
+  s->face = faces[s->gidx];
+  s->font = s->face->font;
+  s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+
+  /* For all glyphs of this composition, starting at the offset
+     S->gidx, until we reach the end of the definition or encounter a
+     glyph that requires the different face, add it to S.  */
+  ++s->nchars;
+  for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
+    ++s->nchars;
+
+  /* All glyph strings for the same composition has the same width,
+     i.e. the width set for the first component of the composition.  */
+
+  s->width = s->first_glyph->pixel_width;
+
+  /* If the specified font could not be loaded, use the frame's
+     default font, but record the fact that we couldn't load it in
+     the glyph string so that we can draw rectangles for the
+     characters of the glyph string.  */
+  if (s->font == NULL)
+    {
+      s->font_not_found_p = 1;
+      s->font = FRAME_FONT (s->f);
+    }
+
+  /* Adjust base line for subscript/superscript text.  */
+  s->ybase += s->first_glyph->voffset;
+
+  xassert (s->face && s->face->gc);
+
+  /* This glyph string must always be drawn with 16-bit functions.  */
+  s->two_byte_p = 1;
+
+  return s->gidx + s->nchars;
+}
+
+
+/* Fill glyph string S from a sequence of character glyphs.
+
+   FACE_ID is the face id of the string.  START is the index of the
+   first glyph to consider, END is the index of the last + 1.
+   OVERLAPS_P non-zero means S should draw the foreground only, and
+   use its physical height for clipping.
+
+   Value is the index of the first glyph not in S.  */
+
+static int
+fill_glyph_string (s, face_id, start, end, overlaps_p)
+     struct glyph_string *s;
+     int face_id;
+     int start, end, overlaps_p;
+{
+  struct glyph *glyph, *last;
+  int voffset;
+  int glyph_not_available_p;
+
+  xassert (s->f == XFRAME (s->w->frame));
+  xassert (s->nchars == 0);
+  xassert (start >= 0 && end > start);
+
+  s->for_overlaps_p = overlaps_p,
+  glyph = s->row->glyphs[s->area] + start;
+  last = s->row->glyphs[s->area] + end;
+  voffset = glyph->voffset;
+
+  glyph_not_available_p = glyph->glyph_not_available_p;
+
+  while (glyph < last
+        && glyph->type == CHAR_GLYPH
+        && glyph->voffset == voffset
+        /* Same face id implies same font, nowadays.  */
+        && glyph->face_id == face_id
+        && glyph->glyph_not_available_p == glyph_not_available_p)
+    {
+      int two_byte_p;
+
+      s->face = get_glyph_face_and_encoding (s->f, glyph,
+                                              s->char2b + s->nchars,
+                                              &two_byte_p);
+      s->two_byte_p = two_byte_p;
+      ++s->nchars;
+      xassert (s->nchars <= end - start);
+      s->width += glyph->pixel_width;
+      ++glyph;
+    }
+
+  s->font = s->face->font;
+  s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+
+  /* If the specified font could not be loaded, use the frame's font,
+     but record the fact that we couldn't load it in
+     S->font_not_found_p so that we can draw rectangles for the
+     characters of the glyph string.  */
+  if (s->font == NULL || glyph_not_available_p)
+    {
+      s->font_not_found_p = 1;
+      s->font = FRAME_FONT (s->f);
+    }
+
+  /* Adjust base line for subscript/superscript text.  */
+  s->ybase += voffset;
+
+  xassert (s->face && s->face->gc);
+  return glyph - s->row->glyphs[s->area];
+}
+
+
+/* Fill glyph string S from image glyph S->first_glyph.  */
+
+static void
+fill_image_glyph_string (s)
+     struct glyph_string *s;
+{
+  xassert (s->first_glyph->type == IMAGE_GLYPH);
+  s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
+  xassert (s->img);
+  s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
+  s->font = s->face->font;
+  s->width = s->first_glyph->pixel_width;
+
+  /* Adjust base line for subscript/superscript text.  */
+  s->ybase += s->first_glyph->voffset;
+}
+
+
+/* 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.
+
+   Value is the index of the first glyph not in S.  */
+
+static int
+fill_stretch_glyph_string (s, row, area, start, end)
+     struct glyph_string *s;
+     struct glyph_row *row;
+     enum glyph_row_area area;
+     int start, end;
+{
+  struct glyph *glyph, *last;
+  int voffset, face_id;
+
+  xassert (s->first_glyph->type == STRETCH_GLYPH);
+
+  glyph = s->row->glyphs[s->area] + start;
+  last = s->row->glyphs[s->area] + end;
+  face_id = glyph->face_id;
+  s->face = FACE_FROM_ID (s->f, face_id);
+  s->font = s->face->font;
+  s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+  s->width = glyph->pixel_width;
+  voffset = glyph->voffset;
+
+  for (++glyph;
+       (glyph < last
+       && glyph->type == STRETCH_GLYPH
+       && glyph->voffset == voffset
+       && glyph->face_id == face_id);
+       ++glyph)
+    s->width += glyph->pixel_width;
+
+  /* Adjust base line for subscript/superscript text.  */
+  s->ybase += voffset;
+
+  /* The case that face->gc == 0 is handled when drawing the glyph
+     string by calling PREPARE_FACE_FOR_DISPLAY.  */
+  xassert (s->face);
+  return glyph - s->row->glyphs[s->area];
+}
+
+
+/* EXPORT for RIF:
+   Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
+   frame F.  Overhangs of glyphs other than type CHAR_GLYPH are
+   assumed to be zero.  */
+
+void
+x_get_glyph_overhangs (glyph, f, left, right)
+     struct glyph *glyph;
+     struct frame *f;
+     int *left, *right;
+{
+  *left = *right = 0;
+
+  if (glyph->type == CHAR_GLYPH)
+    {
+      XFontStruct *font;
+      struct face *face;
+      struct font_info *font_info;
+      XChar2b char2b;
+      XCharStruct *pcm;
+
+      face = get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
+      font = face->font;
+      font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
+      if (font  /* ++KFS: Should this be font_info ?  */
+         && (pcm = rif->per_char_metric (font, &char2b, glyph->font_type)))
+       {
+         if (pcm->rbearing > pcm->width)
+           *right = pcm->rbearing - pcm->width;
+         if (pcm->lbearing < 0)
+           *left = -pcm->lbearing;
+       }
+    }
+}
+
+
+/* Return the index of the first glyph preceding glyph string S that
+   is overwritten by S because of S's left overhang.  Value is -1
+   if no glyphs are overwritten.  */
+
+static int
+left_overwritten (s)
+     struct glyph_string *s;
+{
+  int k;
+
+  if (s->left_overhang)
+    {
+      int x = 0, i;
+      struct glyph *glyphs = s->row->glyphs[s->area];
+      int first = s->first_glyph - glyphs;
+
+      for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
+       x -= glyphs[i].pixel_width;
+
+      k = i + 1;
+    }
+  else
+    k = -1;
+
+  return k;
+}
+
+
+/* Return the index of the first glyph preceding glyph string S that
+   is overwriting S because of its right overhang.  Value is -1 if no
+   glyph in front of S overwrites S.  */
+
+static int
+left_overwriting (s)
+     struct glyph_string *s;
+{
+  int i, k, x;
+  struct glyph *glyphs = s->row->glyphs[s->area];
+  int first = s->first_glyph - glyphs;
+
+  k = -1;
+  x = 0;
+  for (i = first - 1; i >= 0; --i)
+    {
+      int left, right;
+      x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
+      if (x + right > 0)
+       k = i;
+      x -= glyphs[i].pixel_width;
+    }
+
+  return k;
+}
+
+
+/* Return the index of the last glyph following glyph string S that is
+   not overwritten by S because of S's right overhang.  Value is -1 if
+   no such glyph is found.  */
+
+static int
+right_overwritten (s)
+     struct glyph_string *s;
+{
+  int k = -1;
+
+  if (s->right_overhang)
+    {
+      int x = 0, i;
+      struct glyph *glyphs = s->row->glyphs[s->area];
+      int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+      int end = s->row->used[s->area];
+
+      for (i = first; i < end && s->right_overhang > x; ++i)
+       x += glyphs[i].pixel_width;
+
+      k = i;
+    }
+
+  return k;
+}
+
+
+/* Return the index of the last glyph following glyph string S that
+   overwrites S because of its left overhang.  Value is negative
+   if no such glyph is found.  */
+
+static int
+right_overwriting (s)
+     struct glyph_string *s;
+{
+  int i, k, x;
+  int end = s->row->used[s->area];
+  struct glyph *glyphs = s->row->glyphs[s->area];
+  int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+
+  k = -1;
+  x = 0;
+  for (i = first; i < end; ++i)
+    {
+      int left, right;
+      x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
+      if (x - left < 0)
+       k = i;
+      x += glyphs[i].pixel_width;
+    }
+
+  return k;
+}
+
+
+/* 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
+   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 *
+get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
+     struct frame *f;
+     int c, face_id;
+     XChar2b *char2b;
+     int multibyte_p, display_p;
+{
+  struct face *face = FACE_FROM_ID (f, face_id);
+
+  if (!multibyte_p)
+    {
+      /* Unibyte case.  We don't have to encode, but we have to make
+        sure to use a face suitable for unibyte.  */
+      STORE_XCHAR2B (char2b, 0, c);
+      face_id = FACE_FOR_CHAR (f, face, c);
+      face = FACE_FROM_ID (f, face_id);
+    }
+  else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
+    {
+      /* Case of ASCII in a face known to fit ASCII.  */
+      STORE_XCHAR2B (char2b, 0, c);
+    }
+  else
+    {
+      int c1, c2, charset;
+
+      /* Split characters into bytes.  If c2 is -1 afterwards, C is
+        really a one-byte character so that byte1 is zero.  */
+      SPLIT_CHAR (c, charset, c1, c2);
+      if (c2 > 0)
+       STORE_XCHAR2B (char2b, c1, c2);
+      else
+       STORE_XCHAR2B (char2b, 0, c1);
+
+      /* Maybe encode the character in *CHAR2B.  */
+      if (face->font != NULL)
+       {
+         struct font_info *font_info
+           = FONT_INFO_FROM_ID (f, face->font_info_id);
+         if (font_info)
+           rif->encode_char (c, char2b, font_info, 0);
+       }
+    }
+
+  /* Make sure X resources of the face are allocated.  */
+#ifdef HAVE_X_WINDOWS
+  if (display_p)
+#endif
+    {
+      xassert (face != NULL);
+      PREPARE_FACE_FOR_DISPLAY (f, face);
+    }
+
+  return face;
+}
+
+
+/* Set background width of glyph string S.  START is the index of the
+   first glyph following S.  LAST_X is the right-most x-position + 1
+   in the drawing area.  */
+
+static INLINE void
+set_glyph_string_background_width (s, start, last_x)
+     struct glyph_string *s;
+     int start;
+     int last_x;
+{
+  /* If the face of this glyph string has to be drawn to the end of
+     the drawing area, set S->extends_to_end_of_line_p.  */
+  struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
+
+  if (start == s->row->used[s->area]
+      && s->area == TEXT_AREA
+      && ((s->hl == DRAW_NORMAL_TEXT
+          && (s->row->fill_line_p
+              || s->face->background != default_face->background
+              || s->face->stipple != default_face->stipple
+              || s->row->mouse_face_p))
+         || s->hl == DRAW_MOUSE_FACE
+         || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
+             && s->row->fill_line_p)))
+      s->extends_to_end_of_line_p = 1;
+
+  /* If S extends its face to the end of the line, set its
+     background_width to the distance to the right edge of the drawing
+     area.  */
+  if (s->extends_to_end_of_line_p)
+    s->background_width = last_x - s->x + 1;
+  else
+    s->background_width = s->width;
+}
+
+
+/* Compute overhangs and x-positions for glyph string S and its
+   predecessors, or successors.  X is the starting x-position for S.
+   BACKWARD_P non-zero means process predecessors.  */
+
+static void
+compute_overhangs_and_x (s, x, backward_p)
+     struct glyph_string *s;
+     int x;
+     int backward_p;
+{
+  if (backward_p)
+    {
+      while (s)
+       {
+         if (rif->compute_glyph_string_overhangs)
+           rif->compute_glyph_string_overhangs (s);
+         x -= s->width;
+         s->x = x;
+         s = s->prev;
+       }
+    }
+  else
+    {
+      while (s)
+       {
+         if (rif->compute_glyph_string_overhangs)
+           rif->compute_glyph_string_overhangs (s);
+         s->x = x;
+         x += s->width;
+         s = s->next;
+       }
+    }
+}
+
+
+
+/* The following macros are only called from x_draw_glyphs below.
+   They reference the following parameters of that function directly:
+     `w', `row', `area', and `overlap_p'
+   as well as the following local variables:
+     `s', `f', and `hdc' (in W32)  */
+
+#ifdef HAVE_NTGUI
+/* On W32, silently add local `hdc' variable to argument list of
+   init_glyph_string.  */
+#define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
+  init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
+#else
+#define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
+  init_glyph_string (s, char2b, w, row, area, start, hl)
+#endif
+
+/* Add a glyph string for a stretch glyph to the list of strings
+   between HEAD and TAIL.  START is the index of the stretch glyph in
+   row area AREA of glyph row ROW.  END is the index of the last glyph
+   in that glyph row area.  X is the current output position assigned
+   to the new glyph string constructed.  HL overrides that face of the
+   glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn.  LAST_X
+   is the right-most x-position of the drawing area.  */
+
+/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
+   and below -- keep them on one line.  */
+#define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X)   \
+     do                                                                            \
+       {                                                                   \
+        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);      \
+        append_glyph_string (&HEAD, &TAIL, s);                             \
+         s->x = (X);                                                       \
+       }                                                                   \
+     while (0)
+
+
+/* Add a glyph string for an image glyph to the list of strings
+   between HEAD and TAIL.  START is the index of the image glyph in
+   row area AREA of glyph row ROW.  END is the index of the last glyph
+   in that glyph row area.  X is the current output position assigned
+   to the new glyph string constructed.  HL overrides that face of the
+   glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn.  LAST_X
+   is the right-most x-position of the drawing area.  */
+
+#define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
+     do                                                                        \
+       {                                                               \
+        s = (struct glyph_string *) alloca (sizeof *s);                \
+        INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL);          \
+        fill_image_glyph_string (s);                                   \
+        append_glyph_string (&HEAD, &TAIL, s);                         \
+        ++START;                                                       \
+         s->x = (X);                                                   \
+       }                                                               \
+     while (0)
+
+
+/* Add a glyph string for a sequence of character glyphs to the list
+   of strings between HEAD and TAIL.  START is the index of the first
+   glyph in row area AREA of glyph row ROW that is part of the new
+   glyph string.  END is the index of the last glyph in that glyph row
+   area.  X is the current output position assigned to the new glyph
+   string constructed.  HL overrides that face of the glyph; e.g. it
+   is DRAW_CURSOR if a cursor has to be drawn.  LAST_X is the
+   right-most x-position of the drawing area.  */
+
+#define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X)           \
+     do                                                                           \
+       {                                                                  \
+        int c, face_id;                                                   \
+        XChar2b *char2b;                                                  \
+                                                                          \
+        c = (row)->glyphs[area][START].u.ch;                              \
+        face_id = (row)->glyphs[area][START].face_id;                     \
+                                                                          \
+        s = (struct glyph_string *) alloca (sizeof *s);                   \
+        char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b);     \
+        INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);           \
+        append_glyph_string (&HEAD, &TAIL, s);                            \
+        s->x = (X);                                                       \
+        START = fill_glyph_string (s, face_id, START, END, overlaps_p);   \
+       }                                                                  \
+     while (0)
+
+
+/* Add a glyph string for a composite sequence to the list of strings
+   between HEAD and TAIL.  START is the index of the first glyph in
+   row area AREA of glyph row ROW that is part of the new glyph
+   string.  END is the index of the last glyph in that glyph row area.
+   X is the current output position assigned to the new glyph string
+   constructed.  HL overrides that face of the glyph; e.g. it is
+   DRAW_CURSOR if a cursor has to be drawn.  LAST_X is the right-most
+   x-position of the drawing area.  */
+
+#define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
+  do {                                                                   \
+    int cmp_id = (row)->glyphs[area][START].u.cmp_id;                    \
+    int face_id = (row)->glyphs[area][START].face_id;                    \
+    struct face *base_face = FACE_FROM_ID (f, face_id);                          \
+    struct composition *cmp = composition_table[cmp_id];                 \
+    int glyph_len = cmp->glyph_len;                                      \
+    XChar2b *char2b;                                                     \
+    struct face **faces;                                                 \
+    struct glyph_string *first_s = NULL;                                 \
+    int n;                                                               \
+                                                                         \
+    base_face = base_face->ascii_face;                                   \
+    char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len);                  \
+    faces = (struct face **) alloca ((sizeof *faces) * glyph_len);       \
+    /* At first, fill in `char2b' and `faces'.  */                       \
+    for (n = 0; n < glyph_len; n++)                                      \
+      {                                                                          \
+       int c = COMPOSITION_GLYPH (cmp, n);                               \
+       int this_face_id = FACE_FOR_CHAR (f, base_face, c);               \
+       faces[n] = FACE_FROM_ID (f, this_face_id);                        \
+       get_char_face_and_encoding (f, c, this_face_id,                   \
+                                   char2b + n, 1, 1);                    \
+      }                                                                          \
+                                                                         \
+    /* Make glyph_strings for each glyph sequence that is drawable by    \
+       the same face, and append them to HEAD/TAIL.  */                          \
+    for (n = 0; n < cmp->glyph_len;)                                     \
+      {                                                                          \
+       s = (struct glyph_string *) alloca (sizeof *s);                   \
+       INIT_GLYPH_STRING (s, char2b + n, w, row, area, START, HL);       \
+       append_glyph_string (&(HEAD), &(TAIL), s);                        \
+       s->cmp = cmp;                                                     \
+       s->gidx = n;                                                      \
+       s->x = (X);                                                       \
+                                                                         \
+       if (n == 0)                                                       \
+         first_s = s;                                                    \
+                                                                         \
+       n = fill_composite_glyph_string (s, faces, overlaps_p);           \
+      }                                                                          \
+                                                                         \
+    ++START;                                                             \
+    s = first_s;                                                         \
+  } while (0)
+
+
+/* Build a list of glyph strings between HEAD and TAIL for the glyphs
+   of AREA of glyph row ROW on window W between indices START and END.
+   HL overrides the face for drawing glyph strings, e.g. it is
+   DRAW_CURSOR to draw a cursor.  X and LAST_X are start and end
+   x-positions of the drawing area.
+
+   This is an ugly monster macro construct because we must use alloca
+   to allocate glyph strings (because x_draw_glyphs can be called
+   asynchronously).  */
+
+#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X)        \
+     do                                                                           \
+       {                                                                  \
+        HEAD = TAIL = NULL;                                               \
+        while (START < END)                                               \
+          {                                                               \
+             struct glyph *first_glyph = (row)->glyphs[area] + START;     \
+             switch (first_glyph->type)                                           \
+              {                                                           \
+              case CHAR_GLYPH:                                            \
+                 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL,        \
+                                          HL, X, LAST_X);                 \
+                break;                                                    \
+                                                                          \
+              case COMPOSITE_GLYPH:                                       \
+                 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL,    \
+                                              HL, X, LAST_X);             \
+                break;                                                    \
+                                                                          \
+              case STRETCH_GLYPH:                                         \
+                BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL,       \
+                                            HL, X, LAST_X);               \
+                break;                                                    \
+                                                                          \
+              case IMAGE_GLYPH:                                           \
+                BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL,         \
+                                          HL, X, LAST_X);                 \
+                break;                                                    \
+                                                                          \
+              default:                                                    \
+                abort ();                                                 \
+              }                                                           \
+                                                                          \
+             set_glyph_string_background_width (s, START, LAST_X);        \
+            (X) += s->width;                                              \
+            }                                                             \
+       }                                                                  \
+     while (0)
+
+
+/* Draw glyphs between START and END in AREA of ROW on window W,
+   starting at x-position X.  X is relative to AREA in W.  HL is a
+   face-override with the following meaning:
+
+   DRAW_NORMAL_TEXT    draw normally
+   DRAW_CURSOR         draw in cursor face
+   DRAW_MOUSE_FACE     draw in mouse face.
+   DRAW_INVERSE_VIDEO  draw in mode line face
+   DRAW_IMAGE_SUNKEN   draw an image with a sunken relief around it
+   DRAW_IMAGE_RAISED   draw an image with a raised relief around it
+
+   If OVERLAPS_P is non-zero, draw only the foreground of characters
+   and clip to the physical height of ROW.
+
+   Value is the x-position reached, relative to AREA of W.  */
+
+int
+x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
+     struct window *w;
+     int x;
+     struct glyph_row *row;
+     enum glyph_row_area area;
+     int start, end;
+     enum draw_glyphs_face hl;
+     int overlaps_p;
+{
+  struct glyph_string *head, *tail;
+  struct glyph_string *s;
+  int last_x, area_width;
+  int x_reached;
+  int i, j;
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  DECLARE_HDC (hdc);
+
+  ALLOCATE_HDC (hdc, f);
+
+  /* Let's rather be paranoid than getting a SEGV.  */
+  end = min (end, row->used[area]);
+  start = max (0, start);
+  start = min (end, start);
+
+  /* Translate X to frame coordinates.  Set last_x to the right
+     end of the drawing area.  */
+  if (row->full_width_p)
+    {
+      /* X is relative to the left edge of W, without scroll bars
+        or fringes.  */
+      int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
+
+      x += window_left_x;
+      area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
+      last_x = window_left_x + area_width;
+
+      if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+       {
+         int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
+         if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
+           last_x += width;
+         else
+           x -= width;
+       }
+
+      x += FRAME_INTERNAL_BORDER_WIDTH (f);
+      /* ++KFS: W32 and MAC versions had -= in next line (bug??)  */
+      last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
+    }
+  else
+    {
+      x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
+      area_width = window_box_width (w, area);
+      last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
+    }
+
+  /* Build a doubly-linked list of glyph_string structures between
+     head and tail from what we have to draw.  Note that the macro
+     BUILD_GLYPH_STRINGS will modify its start parameter.  That's
+     the reason we use a separate variable `i'.  */
+  i = start;
+  BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
+  if (tail)
+    x_reached = tail->x + tail->background_width;
+  else
+    x_reached = x;
+
+  /* If there are any glyphs with lbearing < 0 or rbearing > width in
+     the row, redraw some glyphs in front or following the glyph
+     strings built above.  */
+  if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
+    {
+      int dummy_x = 0;
+      struct glyph_string *h, *t;
+
+      /* Compute overhangs for all glyph strings.  */
+      if (rif->compute_glyph_string_overhangs)
+       for (s = head; s; s = s->next)
+         rif->compute_glyph_string_overhangs (s);
+
+      /* Prepend glyph strings for glyphs in front of the first glyph
+        string that are overwritten because of the first glyph
+        string's left overhang.  The background of all strings
+        prepended must be drawn because the first glyph string
+        draws over it.  */
+      i = left_overwritten (head);
+      if (i >= 0)
+       {
+         j = i;
+         BUILD_GLYPH_STRINGS (j, start, h, t,
+                              DRAW_NORMAL_TEXT, dummy_x, last_x);
+         start = i;
+         compute_overhangs_and_x (t, head->x, 1);
+         prepend_glyph_string_lists (&head, &tail, h, t);
+       }
+
+      /* Prepend glyph strings for glyphs in front of the first glyph
+        string that overwrite that glyph string because of their
+        right overhang.  For these strings, only the foreground must
+        be drawn, because it draws over the glyph string at `head'.
+        The background must not be drawn because this would overwrite
+        right overhangs of preceding glyphs for which no glyph
+        strings exist.  */
+      i = left_overwriting (head);
+      if (i >= 0)
+       {
+         BUILD_GLYPH_STRINGS (i, start, h, t,
+                              DRAW_NORMAL_TEXT, dummy_x, last_x);
+         for (s = h; s; s = s->next)
+           s->background_filled_p = 1;
+         compute_overhangs_and_x (t, head->x, 1);
+         prepend_glyph_string_lists (&head, &tail, h, t);
+       }
+
+      /* Append glyphs strings for glyphs following the last glyph
+        string tail that are overwritten by tail.  The background of
+        these strings has to be drawn because tail's foreground draws
+        over it.  */
+      i = right_overwritten (tail);
+      if (i >= 0)
+       {
+         BUILD_GLYPH_STRINGS (end, i, h, t,
+                              DRAW_NORMAL_TEXT, x, last_x);
+         compute_overhangs_and_x (h, tail->x + tail->width, 0);
+         append_glyph_string_lists (&head, &tail, h, t);
+       }
+
+      /* Append glyph strings for glyphs following the last glyph
+        string tail that overwrite tail.  The foreground of such
+        glyphs has to be drawn because it writes into the background
+        of tail.  The background must not be drawn because it could
+        paint over the foreground of following glyphs.  */
+      i = right_overwriting (tail);
+      if (i >= 0)
+       {
+         BUILD_GLYPH_STRINGS (end, i, h, t,
+                              DRAW_NORMAL_TEXT, x, last_x);
+         for (s = h; s; s = s->next)
+           s->background_filled_p = 1;
+         compute_overhangs_and_x (h, tail->x + tail->width, 0);
+         append_glyph_string_lists (&head, &tail, h, t);
+       }
+    }
+
+  /* Draw all strings.  */
+  for (s = head; s; s = s->next)
+    rif->draw_glyph_string (s);
+
+  if (area == TEXT_AREA
+      && !row->full_width_p
+      /* When drawing overlapping rows, only the glyph strings'
+        foreground is drawn, which doesn't erase a cursor
+        completely. */
+      && !overlaps_p)
+    {
+      int x0 = head ? head->x : x;
+      int x1 = tail ? tail->x + tail->background_width : x;
+
+      x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
+      x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
+
+      /* ++KFS: W32 and MAC versions had following test here:
+        if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
+      */
+
+      if (XFASTINT (w->left_margin_width) != 0)
+       {
+         int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
+         x0 -= left_area_width;
+         x1 -= left_area_width;
+       }
+
+      notice_overwritten_cursor (w, area, x0, x1,
+                                row->y, MATRIX_ROW_BOTTOM_Y (row));
+    }
+
+  /* Value is the x-position up to which drawn, relative to AREA of W.
+     This doesn't include parts drawn because of overhangs.  */
+  x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
+  if (!row->full_width_p)
+    {
+      /* ++KFS: W32 and MAC versions only had this test here:
+        if (area > LEFT_MARGIN_AREA)
+      */
+
+      if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
+       x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
+      if (area > TEXT_AREA)
+       x_reached -= window_box_width (w, TEXT_AREA);
+    }
+
+  RELEASE_HDC (hdc, f);
+
+  return x_reached;
+}
+
+
+/* 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
+append_glyph (it)
+     struct it *it;
+{
+  struct glyph *glyph;
+  enum glyph_row_area area = it->area;
+
+  xassert (it->glyph_row);
+  xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
+
+  glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
+  if (glyph < it->glyph_row->glyphs[area + 1])
+    {
+      glyph->charpos = CHARPOS (it->position);
+      glyph->object = it->object;
+      glyph->pixel_width = it->pixel_width;
+      glyph->voffset = it->voffset;
+      glyph->type = CHAR_GLYPH;
+      glyph->multibyte_p = it->multibyte_p;
+      glyph->left_box_line_p = it->start_of_box_run_p;
+      glyph->right_box_line_p = it->end_of_box_run_p;
+      glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
+                                     || it->phys_descent > it->descent);
+      glyph->padding_p = 0;
+      glyph->glyph_not_available_p = it->glyph_not_available_p;
+      glyph->face_id = it->face_id;
+      glyph->u.ch = it->char_to_display;
+      glyph->font_type = FONT_TYPE_UNKNOWN;
+      ++it->glyph_row->used[area];
+    }
+}
+
+/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
+   Called from x_produce_glyphs when IT->glyph_row is non-null.  */
+
+static INLINE void
+append_composite_glyph (it)
+     struct it *it;
+{
+  struct glyph *glyph;
+  enum glyph_row_area area = it->area;
+
+  xassert (it->glyph_row);
+
+  glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
+  if (glyph < it->glyph_row->glyphs[area + 1])
+    {
+      glyph->charpos = CHARPOS (it->position);
+      glyph->object = it->object;
+      glyph->pixel_width = it->pixel_width;
+      glyph->voffset = it->voffset;
+      glyph->type = COMPOSITE_GLYPH;
+      glyph->multibyte_p = it->multibyte_p;
+      glyph->left_box_line_p = it->start_of_box_run_p;
+      glyph->right_box_line_p = it->end_of_box_run_p;
+      glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
+                                     || it->phys_descent > it->descent);
+      glyph->padding_p = 0;
+      glyph->glyph_not_available_p = 0;
+      glyph->face_id = it->face_id;
+      glyph->u.cmp_id = it->cmp_id;
+      glyph->font_type = FONT_TYPE_UNKNOWN;
+      ++it->glyph_row->used[area];
+    }
+}
+
+
+/* Change IT->ascent and IT->height according to the setting of
+   IT->voffset.  */
+
+static INLINE void
+take_vertical_position_into_account (it)
+     struct it *it;
+{
+  if (it->voffset)
+    {
+      if (it->voffset < 0)
+       /* Increase the ascent so that we can display the text higher
+          in the line.  */
+       it->ascent += abs (it->voffset);
+      else
+       /* Increase the descent so that we can display the text lower
+          in the line.  */
+       it->descent += it->voffset;
+    }
+}
+
+
+/* Produce glyphs/get display metrics for the image IT is loaded with.
+   See the description of struct display_iterator in dispextern.h for
+   an overview of struct display_iterator.  */
+
+static void
+produce_image_glyph (it)
+     struct it *it;
+{
+  struct image *img;
+  struct face *face;
+
+  xassert (it->what == IT_IMAGE);
+
+  face = FACE_FROM_ID (it->f, it->face_id);
+  img = IMAGE_FROM_ID (it->f, it->image_id);
+  xassert (img);
+
+  /* Make sure X resources of the face and image are loaded.  */
+  PREPARE_FACE_FOR_DISPLAY (it->f, face);
+  prepare_image_for_display (it->f, img);
+
+  it->ascent = it->phys_ascent = image_ascent (img, face);
+  it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
+  it->pixel_width = img->width + 2 * img->hmargin;
+
+  it->nglyphs = 1;
+
+  if (face->box != FACE_NO_BOX)
+    {
+      if (face->box_line_width > 0)
+       {
+         it->ascent += face->box_line_width;
+         it->descent += face->box_line_width;
+       }
+
+      if (it->start_of_box_run_p)
+       it->pixel_width += abs (face->box_line_width);
+      if (it->end_of_box_run_p)
+       it->pixel_width += abs (face->box_line_width);
+    }
+
+  take_vertical_position_into_account (it);
+
+  if (it->glyph_row)
+    {
+      struct glyph *glyph;
+      enum glyph_row_area area = it->area;
+
+      glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
+      if (glyph < it->glyph_row->glyphs[area + 1])
+       {
+         glyph->charpos = CHARPOS (it->position);
+         glyph->object = it->object;
+         glyph->pixel_width = it->pixel_width;
+         glyph->voffset = it->voffset;
+         glyph->type = IMAGE_GLYPH;
+         glyph->multibyte_p = it->multibyte_p;
+         glyph->left_box_line_p = it->start_of_box_run_p;
+         glyph->right_box_line_p = it->end_of_box_run_p;
+         glyph->overlaps_vertically_p = 0;
+          glyph->padding_p = 0;
+         glyph->glyph_not_available_p = 0;
+         glyph->face_id = it->face_id;
+         glyph->u.img_id = img->id;
+         glyph->font_type = FONT_TYPE_UNKNOWN;
+         ++it->glyph_row->used[area];
+       }
+    }
+}
+
+
+/* Append a stretch glyph to IT->glyph_row.  OBJECT is the source
+   of the glyph, WIDTH and HEIGHT are the width and height of the
+   stretch.  ASCENT is the percentage/100 of HEIGHT to use for the
+   ascent of the glyph (0 <= ASCENT <= 1).  */
+
+static void
+append_stretch_glyph (it, object, width, height, ascent)
+     struct it *it;
+     Lisp_Object object;
+     int width, height;
+     double ascent;
+{
+  struct glyph *glyph;
+  enum glyph_row_area area = it->area;
+
+  xassert (ascent >= 0 && ascent <= 1);
+
+  glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
+  if (glyph < it->glyph_row->glyphs[area + 1])
+    {
+      glyph->charpos = CHARPOS (it->position);
+      glyph->object = object;
+      glyph->pixel_width = width;
+      glyph->voffset = it->voffset;
+      glyph->type = STRETCH_GLYPH;
+      glyph->multibyte_p = it->multibyte_p;
+      glyph->left_box_line_p = it->start_of_box_run_p;
+      glyph->right_box_line_p = it->end_of_box_run_p;
+      glyph->overlaps_vertically_p = 0;
+      glyph->padding_p = 0;
+      glyph->glyph_not_available_p = 0;
+      glyph->face_id = it->face_id;
+      glyph->u.stretch.ascent = height * ascent;
+      glyph->u.stretch.height = height;
+      glyph->font_type = FONT_TYPE_UNKNOWN;
+      ++it->glyph_row->used[area];
+    }
+}
+
+
+/* Produce a stretch glyph for iterator IT.  IT->object is the value
+   of the glyph property displayed.  The value must be a list
+   `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
+   being recognized:
+
+   1. `:width WIDTH' specifies that the space should be WIDTH *
+   canonical char width wide.  WIDTH may be an integer or floating
+   point number.
+
+   2. `:relative-width FACTOR' specifies that the width of the stretch
+   should be computed from the width of the first character having the
+   `glyph' property, and should be FACTOR times that width.
+
+   3. `:align-to HPOS' specifies that the space should be wide enough
+   to reach HPOS, a value in canonical character units.
+
+   Exactly one of the above pairs must be present.
+
+   4. `:height HEIGHT' specifies that the height of the stretch produced
+   should be HEIGHT, measured in canonical character units.
+
+   5. `:relative-height FACTOR' specifies that the height of the
+   stretch should be FACTOR times the height of the characters having
+   the glyph property.
+
+   Either none or exactly one of 4 or 5 must be present.
+
+   6. `:ascent ASCENT'  specifies that ASCENT percent of the height
+   of the stretch should be used for the ascent of the stretch.
+   ASCENT must be in the range 0 <= ASCENT <= 100.  */
+
+#define NUMVAL(X)                              \
+     ((INTEGERP (X) || FLOATP (X))             \
+      ? XFLOATINT (X)                          \
+      : - 1)
+
+
+static void
+produce_stretch_glyph (it)
+     struct it *it;
+{
+  /* (space :width WIDTH :height HEIGHT.  */
+  Lisp_Object prop, plist;
+  int width = 0, height = 0;
+  double ascent = 0;
+  struct face *face = FACE_FROM_ID (it->f, it->face_id);
+  XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
+
+  PREPARE_FACE_FOR_DISPLAY (it->f, face);
+
+  /* List should start with `space'.  */
+  xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
+  plist = XCDR (it->object);
+
+  /* Compute the width of the stretch.  */
+  if (prop = Fplist_get (plist, QCwidth),
+      NUMVAL (prop) > 0)
+    /* Absolute width `:width WIDTH' specified and valid.  */
+    width = NUMVAL (prop) * CANON_X_UNIT (it->f);
+  else if (prop = Fplist_get (plist, QCrelative_width),
+          NUMVAL (prop) > 0)
+    {
+      /* Relative width `:relative-width FACTOR' specified and valid.
+        Compute the width of the characters having the `glyph'
+        property.  */
+      struct it it2;
+      unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
+
+      it2 = *it;
+      if (it->multibyte_p)
+       {
+         int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
+                       - IT_BYTEPOS (*it));
+         it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
+       }
+      else
+       it2.c = *p, it2.len = 1;
+
+      it2.glyph_row = NULL;
+      it2.what = IT_CHARACTER;
+      x_produce_glyphs (&it2);
+      width = NUMVAL (prop) * it2.pixel_width;
+    }
+  else if (prop = Fplist_get (plist, QCalign_to),
+          NUMVAL (prop) > 0)
+    width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
+  else
+    /* Nothing specified -> width defaults to canonical char width.  */
+    width = CANON_X_UNIT (it->f);
+
+  /* Compute height.  */
+  if (prop = Fplist_get (plist, QCheight),
+      NUMVAL (prop) > 0)
+    height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
+  else if (prop = Fplist_get (plist, QCrelative_height),
+          NUMVAL (prop) > 0)
+    height = FONT_HEIGHT (font) * NUMVAL (prop);
+  else
+    height = FONT_HEIGHT (font);
+
+  /* Compute percentage of height used for ascent.  If
+     `:ascent ASCENT' is present and valid, use that.  Otherwise,
+     derive the ascent from the font in use.  */
+  if (prop = Fplist_get (plist, QCascent),
+      NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
+    ascent = NUMVAL (prop) / 100.0;
+  else
+    ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
+
+  if (width <= 0)
+    width = 1;
+  if (height <= 0)
+    height = 1;
+
+  if (it->glyph_row)
+    {
+      Lisp_Object object = it->stack[it->sp - 1].string;
+      if (!STRINGP (object))
+       object = it->w->buffer;
+      append_stretch_glyph (it, object, width, height, ascent);
+    }
+
+  it->pixel_width = width;
+  it->ascent = it->phys_ascent = height * ascent;
+  it->descent = it->phys_descent = height - it->ascent;
+  it->nglyphs = 1;
+
+  if (face->box != FACE_NO_BOX)
+    {
+      if (face->box_line_width > 0)
+       {
+         it->ascent += face->box_line_width;
+         it->descent += face->box_line_width;
+       }
+
+      if (it->start_of_box_run_p)
+       it->pixel_width += abs (face->box_line_width);
+      if (it->end_of_box_run_p)
+       it->pixel_width += abs (face->box_line_width);
+    }
+
+  take_vertical_position_into_account (it);
+}
+
+/* RIF:
+   Produce glyphs/get display metrics for the display element IT is
+   loaded with.  See the description of struct display_iterator in
+   dispextern.h for an overview of struct display_iterator.  */
+
+void
+x_produce_glyphs (it)
+     struct it *it;
+{
+  it->glyph_not_available_p = 0;
+
+  if (it->what == IT_CHARACTER)
+    {
+      XChar2b char2b;
+      XFontStruct *font;
+      struct face *face = FACE_FROM_ID (it->f, it->face_id);
+      XCharStruct *pcm;
+      int font_not_found_p;
+      struct font_info *font_info;
+      int boff;                        /* baseline offset */
+      /* We may change it->multibyte_p upon unibyte<->multibyte
+        conversion.  So, save the current value now and restore it
+        later.
+
+        Note: It seems that we don't have to record multibyte_p in
+        struct glyph because the character code itself tells if or
+        not the character is multibyte.  Thus, in the future, we must
+        consider eliminating the field `multibyte_p' in the struct
+        glyph.  */
+      int saved_multibyte_p = it->multibyte_p;
+
+      /* Maybe translate single-byte characters to multibyte, or the
+        other way.  */
+      it->char_to_display = it->c;
+      if (!ASCII_BYTE_P (it->c))
+       {
+         if (unibyte_display_via_language_environment
+             && SINGLE_BYTE_CHAR_P (it->c)
+             && (it->c >= 0240
+                 || !NILP (Vnonascii_translation_table)))
+           {
+             it->char_to_display = unibyte_char_to_multibyte (it->c);
+             it->multibyte_p = 1;
+             it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+             face = FACE_FROM_ID (it->f, it->face_id);
+           }
+         else if (!SINGLE_BYTE_CHAR_P (it->c)
+                  && !it->multibyte_p)
+           {
+             it->multibyte_p = 1;
+             it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+             face = FACE_FROM_ID (it->f, it->face_id);
+           }
+       }
+
+      /* Get font to use.  Encode IT->char_to_display.  */
+      get_char_face_and_encoding (it->f, it->char_to_display, it->face_id,
+                                 &char2b, it->multibyte_p, 0);
+      font = face->font;
+
+      /* When no suitable font found, use the default font.  */
+      font_not_found_p = font == NULL;
+      if (font_not_found_p)
+       {
+         font = FRAME_FONT (it->f);
+         boff = FRAME_BASELINE_OFFSET (it->f);
+         font_info = NULL;
+       }
+      else
+       {
+         font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+         boff = font_info->baseline_offset;
+         if (font_info->vertical_centering)
+           boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+       }
+
+      if (it->char_to_display >= ' '
+         && (!it->multibyte_p || it->char_to_display < 128))
+       {
+         /* Either unibyte or ASCII.  */
+         int stretched_p;
+
+         it->nglyphs = 1;
+
+         pcm = rif->per_char_metric (font, &char2b,
+                                     FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
+         it->ascent = FONT_BASE (font) + boff;
+         it->descent = FONT_DESCENT (font) - boff;
+
+         if (pcm)
+           {
+             it->phys_ascent = pcm->ascent + boff;
+             it->phys_descent = pcm->descent - boff;
+             it->pixel_width = pcm->width;
+           }
+         else
+           {
+             it->glyph_not_available_p = 1;
+              it->phys_ascent = FONT_BASE (font) + boff;
+              it->phys_descent = FONT_DESCENT (font) - boff;
+             it->pixel_width = FONT_WIDTH (font);
+           }
+
+         /* If this is a space inside a region of text with
+            `space-width' property, change its width.  */
+         stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
+         if (stretched_p)
+           it->pixel_width *= XFLOATINT (it->space_width);
+
+         /* If face has a box, add the box thickness to the character
+            height.  If character has a box line to the left and/or
+            right, add the box line width to the character's width.  */
+         if (face->box != FACE_NO_BOX)
+           {
+             int thick = face->box_line_width;
+
+             if (thick > 0)
+               {
+                 it->ascent += thick;
+                 it->descent += thick;
+               }
+             else
+               thick = -thick;
+
+             if (it->start_of_box_run_p)
+               it->pixel_width += thick;
+             if (it->end_of_box_run_p)
+               it->pixel_width += thick;
+           }
+
+         /* If face has an overline, add the height of the overline
+            (1 pixel) and a 1 pixel margin to the character height.  */
+         if (face->overline_p)
+           it->ascent += 2;
+
+         take_vertical_position_into_account (it);
+
+         /* If we have to actually produce glyphs, do it.  */
+         if (it->glyph_row)
+           {
+             if (stretched_p)
+               {
+                 /* Translate a space with a `space-width' property
+                    into a stretch glyph.  */
+                 double ascent = (double) FONT_BASE (font)
+                                / FONT_HEIGHT (font);
+                 append_stretch_glyph (it, it->object, it->pixel_width,
+                                       it->ascent + it->descent, ascent);
+               }
+             else
+               append_glyph (it);
+
+             /* If characters with lbearing or rbearing are displayed
+                in this line, record that fact in a flag of the
+                glyph row.  This is used to optimize X output code.  */
+             if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
+               it->glyph_row->contains_overlapping_glyphs_p = 1;
+           }
+       }
+      else if (it->char_to_display == '\n')
+       {
+         /* A newline has no width but we need the height of the line.  */
+         it->pixel_width = 0;
+         it->nglyphs = 0;
+         it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
+         it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
+
+         if (face->box != FACE_NO_BOX
+             && face->box_line_width > 0)
+           {
+             it->ascent += face->box_line_width;
+             it->descent += face->box_line_width;
+           }
+       }
+      else if (it->char_to_display == '\t')
+       {
+         int tab_width = it->tab_width * CANON_X_UNIT (it->f);
+         int x = it->current_x + it->continuation_lines_width;
+         int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
+
+         /* If the distance from the current position to the next tab
+            stop is less than a canonical character width, use the
+            tab stop after that.  */
+         if (next_tab_x - x < CANON_X_UNIT (it->f))
+           next_tab_x += tab_width;
+
+         it->pixel_width = next_tab_x - x;
+         it->nglyphs = 1;
+         it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
+         it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
+
+         if (it->glyph_row)
+           {
+             double ascent = (double) it->ascent / (it->ascent + it->descent);
+             append_stretch_glyph (it, it->object, it->pixel_width,
+                                   it->ascent + it->descent, ascent);
+           }
+       }
+      else
+       {
+         /* A multi-byte character.  Assume that the display width of the
+            character is the width of the character multiplied by the
+            width of the font.  */
+
+         /* If we found a font, this font should give us the right
+            metrics.  If we didn't find a font, use the frame's
+            default font and calculate the width of the character
+            from the charset width; this is what old redisplay code
+            did.  */
+
+         pcm = rif->per_char_metric (font, &char2b,
+                                     FONT_TYPE_FOR_MULTIBYTE (font, it->c));
+
+         if (font_not_found_p || !pcm)
+           {
+             int charset = CHAR_CHARSET (it->char_to_display);
+
+             it->glyph_not_available_p = 1;
+             it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
+                                * CHARSET_WIDTH (charset));
+             it->phys_ascent = FONT_BASE (font) + boff;
+             it->phys_descent = FONT_DESCENT (font) - boff;
+           }
+         else
+           {
+             it->pixel_width = pcm->width;
+             it->phys_ascent = pcm->ascent + boff;
+             it->phys_descent = pcm->descent - boff;
+             if (it->glyph_row
+                 && (pcm->lbearing < 0
+                     || pcm->rbearing > pcm->width))
+               it->glyph_row->contains_overlapping_glyphs_p = 1;
+           }
+         it->nglyphs = 1;
+          it->ascent = FONT_BASE (font) + boff;
+          it->descent = FONT_DESCENT (font) - boff;
+         if (face->box != FACE_NO_BOX)
+           {
+             int thick = face->box_line_width;
+
+             if (thick > 0)
+               {
+                 it->ascent += thick;
+                 it->descent += thick;
+               }
+             else
+               thick = - thick;
+
+             if (it->start_of_box_run_p)
+               it->pixel_width += thick;
+             if (it->end_of_box_run_p)
+               it->pixel_width += thick;
+           }
+
+         /* If face has an overline, add the height of the overline
+            (1 pixel) and a 1 pixel margin to the character height.  */
+         if (face->overline_p)
+           it->ascent += 2;
+
+         take_vertical_position_into_account (it);
+
+         if (it->glyph_row)
+           append_glyph (it);
+       }
+      it->multibyte_p = saved_multibyte_p;
+    }
+  else if (it->what == IT_COMPOSITION)
+    {
+      /* Note: A composition is represented as one glyph in the
+        glyph matrix.  There are no padding glyphs.  */
+      XChar2b char2b;
+      XFontStruct *font;
+      struct face *face = FACE_FROM_ID (it->f, it->face_id);
+      XCharStruct *pcm;
+      int font_not_found_p;
+      struct font_info *font_info;
+      int boff;                        /* baseline offset */
+      struct composition *cmp = composition_table[it->cmp_id];
+
+      /* Maybe translate single-byte characters to multibyte.  */
+      it->char_to_display = it->c;
+      if (unibyte_display_via_language_environment
+         && SINGLE_BYTE_CHAR_P (it->c)
+         && (it->c >= 0240
+             || (it->c >= 0200
+                 && !NILP (Vnonascii_translation_table))))
+       {
+         it->char_to_display = unibyte_char_to_multibyte (it->c);
+       }
+
+      /* Get face and font to use.  Encode IT->char_to_display.  */
+      it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+      face = FACE_FROM_ID (it->f, it->face_id);
+      get_char_face_and_encoding (it->f, it->char_to_display, it->face_id,
+                                 &char2b, it->multibyte_p, 0);
+      font = face->font;
+
+      /* When no suitable font found, use the default font.  */
+      font_not_found_p = font == NULL;
+      if (font_not_found_p)
+       {
+         font = FRAME_FONT (it->f);
+         boff = FRAME_BASELINE_OFFSET (it->f);
+         font_info = NULL;
+       }
+      else
+       {
+         font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+         boff = font_info->baseline_offset;
+         if (font_info->vertical_centering)
+           boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+       }
+
+      /* There are no padding glyphs, so there is only one glyph to
+        produce for the composition.  Important is that pixel_width,
+        ascent and descent are the values of what is drawn by
+        draw_glyphs (i.e. the values of the overall glyphs composed).  */
+      it->nglyphs = 1;
+
+      /* If we have not yet calculated pixel size data of glyphs of
+        the composition for the current face font, calculate them
+        now.  Theoretically, we have to check all fonts for the
+        glyphs, but that requires much time and memory space.  So,
+        here we check only the font of the first glyph.  This leads
+        to incorrect display very rarely, and C-l (recenter) can
+        correct the display anyway.  */
+      if (cmp->font != (void *) font)
+       {
+         /* Ascent and descent of the font of the first character of
+            this composition (adjusted by baseline offset).  Ascent
+            and descent of overall glyphs should not be less than
+            them respectively.  */
+         int font_ascent = FONT_BASE (font) + boff;
+         int font_descent = FONT_DESCENT (font) - boff;
+         /* Bounding box of the overall glyphs.  */
+         int leftmost, rightmost, lowest, highest;
+         int i, width, ascent, descent;
+
+         cmp->font = (void *) font;
+
+         /* Initialize the bounding box.  */
+         if (font_info
+             && (pcm = rif->per_char_metric (font, &char2b,
+                                             FONT_TYPE_FOR_MULTIBYTE (font, it->c))))
+           {
+             width = pcm->width;
+             ascent = pcm->ascent;
+             descent = pcm->descent;
+           }
+         else
+           {
+             width = FONT_WIDTH (font);
+             ascent = FONT_BASE (font);
+             descent = FONT_DESCENT (font);
+           }
+
+         rightmost = width;
+         lowest = - descent + boff;
+         highest = ascent + boff;
+         leftmost = 0;
+
+         if (font_info
+             && font_info->default_ascent
+             && CHAR_TABLE_P (Vuse_default_ascent)
+             && !NILP (Faref (Vuse_default_ascent,
+                              make_number (it->char_to_display))))
+           highest = font_info->default_ascent + boff;
+
+         /* Draw the first glyph at the normal position.  It may be
+            shifted to right later if some other glyphs are drawn at
+            the left.  */
+         cmp->offsets[0] = 0;
+         cmp->offsets[1] = boff;
+
+         /* Set cmp->offsets for the remaining glyphs.  */
+         for (i = 1; i < cmp->glyph_len; i++)
+           {
+             int left, right, btm, top;
+             int ch = COMPOSITION_GLYPH (cmp, i);
+             int face_id = FACE_FOR_CHAR (it->f, face, ch);
+
+             face = FACE_FROM_ID (it->f, face_id);
+             get_char_face_and_encoding (it->f, ch, face->id,
+                                         &char2b, it->multibyte_p, 0);
+             font = face->font;
+             if (font == NULL)
+               {
+                 font = FRAME_FONT (it->f);
+                 boff = FRAME_BASELINE_OFFSET (it->f);
+                 font_info = NULL;
+               }
+             else
+               {
+                 font_info
+                   = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+                 boff = font_info->baseline_offset;
+                 if (font_info->vertical_centering)
+                   boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+               }
+
+             if (font_info
+                 && (pcm = rif->per_char_metric (font, &char2b,
+                                                 FONT_TYPE_FOR_MULTIBYTE (font, ch))))
+               {
+                 width = pcm->width;
+                 ascent = pcm->ascent;
+                 descent = pcm->descent;
+               }
+             else
+               {
+                 width = FONT_WIDTH (font);
+                 ascent = 1;
+                 descent = 0;
+               }
+
+             if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
+               {
+                 /* Relative composition with or without
+                    alternate chars.  */
+                 left = (leftmost + rightmost - width) / 2;
+                 btm = - descent + boff;
+                 if (font_info && font_info->relative_compose
+                     && (! CHAR_TABLE_P (Vignore_relative_composition)
+                         || NILP (Faref (Vignore_relative_composition,
+                                         make_number (ch)))))
+                   {
+
+                     if (- descent >= font_info->relative_compose)
+                       /* One extra pixel between two glyphs.  */
+                       btm = highest + 1;
+                     else if (ascent <= 0)
+                       /* One extra pixel between two glyphs.  */
+                       btm = lowest - 1 - ascent - descent;
+                   }
+               }
+             else
+               {
+                 /* A composition rule is specified by an integer
+                    value that encodes global and new reference
+                    points (GREF and NREF).  GREF and NREF are
+                    specified by numbers as below:
+
+                       0---1---2 -- ascent
+                       |       |
+                       |       |
+                       |       |
+                       9--10--11 -- center
+                       |       |
+                    ---3---4---5--- baseline
+                       |       |
+                       6---7---8 -- descent
+                 */
+                 int rule = COMPOSITION_RULE (cmp, i);
+                 int gref, nref, grefx, grefy, nrefx, nrefy;
+
+                 COMPOSITION_DECODE_RULE (rule, gref, nref);
+                 grefx = gref % 3, nrefx = nref % 3;
+                 grefy = gref / 3, nrefy = nref / 3;
+
+                 left = (leftmost
+                         + grefx * (rightmost - leftmost) / 2
+                         - nrefx * width / 2);
+                 btm = ((grefy == 0 ? highest
+                         : grefy == 1 ? 0
+                         : grefy == 2 ? lowest
+                         : (highest + lowest) / 2)
+                        - (nrefy == 0 ? ascent + descent
+                           : nrefy == 1 ? descent - boff
+                           : nrefy == 2 ? 0
+                           : (ascent + descent) / 2));
+               }
+
+             cmp->offsets[i * 2] = left;
+             cmp->offsets[i * 2 + 1] = btm + descent;
+
+             /* Update the bounding box of the overall glyphs. */
+             right = left + width;
+             top = btm + descent + ascent;
+             if (left < leftmost)
+               leftmost = left;
+             if (right > rightmost)
+               rightmost = right;
+             if (top > highest)
+               highest = top;
+             if (btm < lowest)
+               lowest = btm;
+           }
+
+         /* If there are glyphs whose x-offsets are negative,
+            shift all glyphs to the right and make all x-offsets
+            non-negative.  */
+         if (leftmost < 0)
+           {
+             for (i = 0; i < cmp->glyph_len; i++)
+               cmp->offsets[i * 2] -= leftmost;
+             rightmost -= leftmost;
+           }
+
+         cmp->pixel_width = rightmost;
+         cmp->ascent = highest;
+         cmp->descent = - lowest;
+         if (cmp->ascent < font_ascent)
+           cmp->ascent = font_ascent;
+         if (cmp->descent < font_descent)
+           cmp->descent = font_descent;
+       }
+
+      it->pixel_width = cmp->pixel_width;
+      it->ascent = it->phys_ascent = cmp->ascent;
+      it->descent = it->phys_descent = cmp->descent;
+
+      if (face->box != FACE_NO_BOX)
+       {
+         int thick = face->box_line_width;
+
+         if (thick > 0)
+           {
+             it->ascent += thick;
+             it->descent += thick;
+           }
+         else
+           thick = - thick;
+
+         if (it->start_of_box_run_p)
+           it->pixel_width += thick;
+         if (it->end_of_box_run_p)
+           it->pixel_width += thick;
+       }
+
+      /* If face has an overline, add the height of the overline
+        (1 pixel) and a 1 pixel margin to the character height.  */
+      if (face->overline_p)
+       it->ascent += 2;
+
+      take_vertical_position_into_account (it);
+
+      if (it->glyph_row)
+       append_composite_glyph (it);
+    }
+  else if (it->what == IT_IMAGE)
+    produce_image_glyph (it);
+  else if (it->what == IT_STRETCH)
+    produce_stretch_glyph (it);
+
+  /* Accumulate dimensions.  Note: can't assume that it->descent > 0
+     because this isn't true for images with `:ascent 100'.  */
+  xassert (it->ascent >= 0 && it->descent >= 0);
+  if (it->area == TEXT_AREA)
+    it->current_x += it->pixel_width;
+
+  it->descent += it->extra_line_spacing;
+
+  it->max_ascent = max (it->max_ascent, it->ascent);
+  it->max_descent = max (it->max_descent, it->descent);
+  it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
+  it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
+}
+
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
+
+\f
+/***********************************************************************
+                            Cursor types
+ ***********************************************************************/
+
+/* Value is the internal representation of the specified cursor type
+   ARG.  If type is BAR_CURSOR, return in *WIDTH the specified width
+   of the bar cursor.  */
+
+enum text_cursor_kinds
+get_specified_cursor_type (arg, width)
+     Lisp_Object arg;
+     int *width;
+{
+  enum text_cursor_kinds type;
+
+  if (NILP (arg))
+    return NO_CURSOR;
+
+  if (EQ (arg, Qbox))
+    return FILLED_BOX_CURSOR;
+
+  if (EQ (arg, Qhollow))
+    return HOLLOW_BOX_CURSOR;
+
+  if (EQ (arg, Qbar))
+    {
+      *width = 2;
+      return BAR_CURSOR;
+    }
+
+  if (CONSP (arg)
+      && EQ (XCAR (arg), Qbar)
+      && INTEGERP (XCDR (arg))
+      && XINT (XCDR (arg)) >= 0)
+    {
+      *width = XINT (XCDR (arg));
+      return BAR_CURSOR;
+    }
+
+  if (EQ (arg, Qhbar))
+    {
+      *width = 2;
+      return HBAR_CURSOR;
+    }
+
+  if (CONSP (arg)
+      && EQ (XCAR (arg), Qhbar)
+      && INTEGERP (XCDR (arg))
+      && XINT (XCDR (arg)) >= 0)
+    {
+      *width = XINT (XCDR (arg));
+      return HBAR_CURSOR;
+    }
+
+  /* Treat anything unknown as "hollow box cursor".
+     It was bad to signal an error; people have trouble fixing
+     .Xdefaults with Emacs, when it has something bad in it.  */
+  type = HOLLOW_BOX_CURSOR;
+
+  return type;
+}
+
+/* Set the default cursor types for specified frame.  */
+void
+set_frame_cursor_types (f, arg)
+     struct frame *f;
+     Lisp_Object arg;
+{
+  int width;
+  Lisp_Object tem;
+
+  FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
+  FRAME_CURSOR_WIDTH (f) = width;
+
+  /* By default, set up the blink-off state depending on the on-state.  */
+
+  tem = Fassoc (arg, Vblink_cursor_alist);
+  if (!NILP (tem))
+    {
+      FRAME_BLINK_OFF_CURSOR (f)
+       = get_specified_cursor_type (XCDR (tem), &width);
+      FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
+    }
+  else
+    FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
+}
+
+
+/* Return the cursor we want to be displayed in window W.  Return
+   width of bar/hbar cursor through WIDTH arg.  Return with
+   ACTIVE_CURSOR arg set to 1 if cursor in window W is `active'
+   (i.e. if the `system caret' should track this cursor).
+
+   In a mini-buffer window, we want the cursor only to appear if we
+   are reading input from this window.  For the selected window, we
+   want the cursor type given by the frame parameter or buffer local
+   setting of cursor-type.  If explicitly marked off, draw no cursor.
+   In all other cases, we want a hollow box cursor.  */
+
+enum text_cursor_kinds
+get_window_cursor_type (w, width, active_cursor)
+     struct window *w;
+     int *width;
+     int *active_cursor;
+{
+  struct frame *f = XFRAME (w->frame);
+  struct buffer *b = XBUFFER (w->buffer);
+  int cursor_type = DEFAULT_CURSOR;
+  Lisp_Object alt_cursor;
+  int non_selected = 0;
+
+  *active_cursor = 1;
+
+  /* Echo area */
+  if (cursor_in_echo_area
+      && FRAME_HAS_MINIBUF_P (f)
+      && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
+    {
+      if (w == XWINDOW (echo_area_window))
+       {
+         *width = FRAME_CURSOR_WIDTH (f);
+         return FRAME_DESIRED_CURSOR (f);
+       }
+
+      *active_cursor = 0;
+      non_selected = 1;
+    }
+
+  /* Nonselected window or nonselected frame.  */
+  else if (w != XWINDOW (f->selected_window)
+#ifdef HAVE_WINDOW_SYSTEM
+          || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
+#endif
+          )
+    {
+      *active_cursor = 0;
+
+      if (MINI_WINDOW_P (w) && minibuf_level == 0)
+       return NO_CURSOR;
+
+      non_selected = 1;
+    }
+
+  /* Never display a cursor in a window in which cursor-type is nil.  */
+  if (NILP (b->cursor_type))
+    return NO_CURSOR;
+
+  /* Use cursor-in-non-selected-windows for non-selected window or frame.  */
+  if (non_selected)
+    {
+      alt_cursor = Fbuffer_local_value (Qcursor_in_non_selected_windows, w->buffer);
+      return get_specified_cursor_type (alt_cursor, width);
+    }
+
+  /* Get the normal cursor type for this window.  */
+  if (EQ (b->cursor_type, Qt))
+    {
+      cursor_type = FRAME_DESIRED_CURSOR (f);
+      *width = FRAME_CURSOR_WIDTH (f);
+    }
+  else
+    cursor_type = get_specified_cursor_type (b->cursor_type, width);
+
+  /* Use normal cursor if not blinked off.  */
+  if (!w->cursor_off_p)
+    return cursor_type;
+
+  /* Cursor is blinked off, so determine how to "toggle" it.  */
+
+  /* First look for an entry matching the buffer's cursor-type in blink-cursor-alist.  */
+  if ((alt_cursor = Fassoc (b->cursor_type, Vblink_cursor_alist), !NILP (alt_cursor)))
+    return get_specified_cursor_type (XCDR (alt_cursor), width);
+
+  /* Then see if frame has specified a specific blink off cursor type.  */
+  if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
+    {
+      *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
+      return FRAME_BLINK_OFF_CURSOR (f);
+    }
+
+  /* Finally perform built-in cursor blinking:
+       filled box      <->   hollow box
+       wide [h]bar     <->   narrow [h]bar
+       narrow [h]bar   <->   no cursor
+       other type      <->   no cursor  */
+
+  if (cursor_type == FILLED_BOX_CURSOR)
+    return HOLLOW_BOX_CURSOR;
+
+  if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
+    {
+      *width = 1;
+      return cursor_type;
+    }
+
+  return NO_CURSOR;
+}
+
+
+/* Notice when the text cursor of window W has been completely
+   overwritten by a drawing operation that outputs glyphs in AREA
+   starting at X0 and ending at X1 in the line starting at Y0 and
+   ending at Y1.  X coordinates are area-relative.  X1 < 0 means all
+   the rest of the line after X0 has been written.  Y coordinates
+   are window-relative.  */
+
+void
+notice_overwritten_cursor (w, area, x0, x1, y0, y1)
+     struct window *w;
+     enum glyph_row_area area;
+     int x0, y0, x1, y1;
+{
+#ifdef HAVE_CARBON
+  /* ++KFS:  Why is there a special version of this for the mac ? */
+  if (area == TEXT_AREA
+      && w->phys_cursor_on_p
+      && y0 <= w->phys_cursor.y
+      && y1 >= w->phys_cursor.y + w->phys_cursor_height
+      && x0 <= w->phys_cursor.x
+      && (x1 < 0 || x1 > w->phys_cursor.x))
+    w->phys_cursor_on_p = 0;
+#else
+  if (area == TEXT_AREA && w->phys_cursor_on_p)
+    {
+      int cx0 = w->phys_cursor.x;
+      int cx1 = cx0 + w->phys_cursor_width;
+      int cy0 = w->phys_cursor.y;
+      int cy1 = cy0 + w->phys_cursor_height;
+
+      if (x0 <= cx0 && (x1 < 0 || x1 >= cx1))
+       {
+         /* The cursor image will be completely removed from the
+            screen if the output area intersects the cursor area in
+            y-direction.  When we draw in [y0 y1[, and some part of
+            the cursor is at y < y0, that part must have been drawn
+            before.  When scrolling, the cursor is erased before
+            actually scrolling, so we don't come here.  When not
+            scrolling, the rows above the old cursor row must have
+            changed, and in this case these rows must have written
+            over the cursor image.
+
+            Likewise if part of the cursor is below y1, with the
+            exception of the cursor being in the first blank row at
+            the buffer and window end because update_text_area
+            doesn't draw that row.  (Except when it does, but
+            that's handled in update_text_area.)  */
+
+         if (((y0 >= cy0 && y0 < cy1) || (y1 > cy0 && y1 < cy1))
+             && w->current_matrix->rows[w->phys_cursor.vpos].displays_text_p)
+           w->phys_cursor_on_p = 0;
+       }
+    }
+#endif
+}
+
+\f
+/***********************************************************************
+                           Initialization
+ ***********************************************************************/
+
+void
+syms_of_xdisp ()
+{
+  Vwith_echo_area_save_vector = Qnil;
+  staticpro (&Vwith_echo_area_save_vector);
+
+  Vmessage_stack = Qnil;
+  staticpro (&Vmessage_stack);
+
+  Qinhibit_redisplay = intern ("inhibit-redisplay");
+  staticpro (&Qinhibit_redisplay);
+
+  message_dolog_marker1 = Fmake_marker ();
+  staticpro (&message_dolog_marker1);
+  message_dolog_marker2 = Fmake_marker ();
+  staticpro (&message_dolog_marker2);
+  message_dolog_marker3 = Fmake_marker ();
+  staticpro (&message_dolog_marker3);
+
+#if GLYPH_DEBUG
+  defsubr (&Sdump_frame_glyph_matrix);
+  defsubr (&Sdump_glyph_matrix);
+  defsubr (&Sdump_glyph_row);
+  defsubr (&Sdump_tool_bar_row);
+  defsubr (&Strace_redisplay);
+  defsubr (&Strace_to_stderr);
+#endif
+#ifdef HAVE_WINDOW_SYSTEM
+  defsubr (&Stool_bar_lines_needed);
+#endif
+  defsubr (&Sformat_mode_line);
+
+  staticpro (&Qmenu_bar_update_hook);
+  Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
+
+  staticpro (&Qoverriding_terminal_local_map);
+  Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
+
+  staticpro (&Qoverriding_local_map);
+  Qoverriding_local_map = intern ("overriding-local-map");
+
+  staticpro (&Qwindow_scroll_functions);
+  Qwindow_scroll_functions = intern ("window-scroll-functions");
+
+  staticpro (&Qredisplay_end_trigger_functions);
+  Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
+
+  staticpro (&Qinhibit_point_motion_hooks);
+  Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
+
+  QCdata = intern (":data");
+  staticpro (&QCdata);
+  Qdisplay = intern ("display");
+  staticpro (&Qdisplay);
+  Qspace_width = intern ("space-width");
+  staticpro (&Qspace_width);
+  Qraise = intern ("raise");
+  staticpro (&Qraise);
+  Qspace = intern ("space");
+  staticpro (&Qspace);
+  Qmargin = intern ("margin");
+  staticpro (&Qmargin);
+  Qleft_margin = intern ("left-margin");
+  staticpro (&Qleft_margin);
+  Qright_margin = intern ("right-margin");
+  staticpro (&Qright_margin);
+  Qalign_to = intern ("align-to");
+  staticpro (&Qalign_to);
+  QCalign_to = intern (":align-to");
+  staticpro (&QCalign_to);
+  Qrelative_width = intern ("relative-width");
+  staticpro (&Qrelative_width);
+  QCrelative_width = intern (":relative-width");
+  staticpro (&QCrelative_width);
+  QCrelative_height = intern (":relative-height");
+  staticpro (&QCrelative_height);
+  QCeval = intern (":eval");
+  staticpro (&QCeval);
+  QCpropertize = intern (":propertize");
+  staticpro (&QCpropertize);
+  QCfile = intern (":file");
+  staticpro (&QCfile);
+  Qfontified = intern ("fontified");
+  staticpro (&Qfontified);
+  Qfontification_functions = intern ("fontification-functions");
+  staticpro (&Qfontification_functions);
+  Qtrailing_whitespace = intern ("trailing-whitespace");
+  staticpro (&Qtrailing_whitespace);
+  Qimage = intern ("image");
+  staticpro (&Qimage);
+  Qmessage_truncate_lines = intern ("message-truncate-lines");
+  staticpro (&Qmessage_truncate_lines);
+  Qcursor_in_non_selected_windows = intern ("cursor-in-non-selected-windows");
+  staticpro (&Qcursor_in_non_selected_windows);
+  Qgrow_only = intern ("grow-only");
+  staticpro (&Qgrow_only);
+  Qinhibit_menubar_update = intern ("inhibit-menubar-update");
+  staticpro (&Qinhibit_menubar_update);
+  Qinhibit_eval_during_redisplay = intern ("inhibit-eval-during-redisplay");
+  staticpro (&Qinhibit_eval_during_redisplay);
+  Qposition = intern ("position");
+  staticpro (&Qposition);
+  Qbuffer_position = intern ("buffer-position");
+  staticpro (&Qbuffer_position);
+  Qobject = intern ("object");
+  staticpro (&Qobject);
+  Qbar = intern ("bar");
+  staticpro (&Qbar);
+  Qhbar = intern ("hbar");
+  staticpro (&Qhbar);
+  Qbox = intern ("box");
+  staticpro (&Qbox);
+  Qhollow = intern ("hollow");
+  staticpro (&Qhollow);
+  Qrisky_local_variable = intern ("risky-local-variable");
+  staticpro (&Qrisky_local_variable);
+  Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces");
+  staticpro (&Qinhibit_free_realized_faces);
+
+  list_of_error = Fcons (intern ("error"), Qnil);
+  staticpro (&list_of_error);
+
+  last_arrow_position = Qnil;
+  last_arrow_string = Qnil;
+  staticpro (&last_arrow_position);
+  staticpro (&last_arrow_string);
+
+  echo_buffer[0] = echo_buffer[1] = Qnil;
+  staticpro (&echo_buffer[0]);
+  staticpro (&echo_buffer[1]);
+
+  echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
+  staticpro (&echo_area_buffer[0]);
+  staticpro (&echo_area_buffer[1]);
+
+  Vmessages_buffer_name = build_string ("*Messages*");
+  staticpro (&Vmessages_buffer_name);
+
+  mode_line_proptrans_alist = Qnil;
+  staticpro (&mode_line_proptrans_alist);
+
+  mode_line_string_list = Qnil;
+  staticpro (&mode_line_string_list);
+
+  DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
+    doc: /* Non-nil means highlight trailing whitespace.
+The face used for trailing whitespace is `trailing-whitespace'.  */);
+  Vshow_trailing_whitespace = Qnil;
+
+  DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
+    doc: /* Non-nil means don't actually do any redisplay.
+This is used for internal purposes.  */);
+  Vinhibit_redisplay = Qnil;
+
+  DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
+    doc: /* String (or mode line construct) included (normally) in `mode-line-format'.  */);
+  Vglobal_mode_string = Qnil;
+
+  DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
+    doc: /* Marker for where to display an arrow on top of the buffer text.
+This must be the beginning of a line in order to work.
+See also `overlay-arrow-string'.  */);
+  Voverlay_arrow_position = Qnil;
+
+  DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
+    doc: /* String to display as an arrow.  See also `overlay-arrow-position'.  */);
+  Voverlay_arrow_string = Qnil;
+
+  DEFVAR_INT ("scroll-step", &scroll_step,
+    doc: /* *The number of lines to try scrolling a window by when point moves out.
+If that fails to bring point back on frame, point is centered instead.
 If this is zero, point is always centered after it moves off frame.
 If you want scrolling to always be a line at a time, you should set
 `scroll-conservatively' to a large value rather than set this to 1.  */);
@@ -14951,9 +18112,7 @@ of the top or bottom of the window.  */);
   DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
     doc: /* nil means display the mode-line/header-line/menu-bar in the default face.
 Any other value means to use the appropriate face, `mode-line',
-`header-line', or `menu' respectively.
-
-This variable is deprecated; please change the above faces instead.  */);
+`header-line', or `menu' respectively.  */);
   mode_line_inverse_video = 1;
 
   DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit,
@@ -15022,14 +18181,14 @@ Each function is called with two arguments, the window
 and its new display-start position.  Note that the value of `window-end'
 is not valid when these functions are called.  */);
   Vwindow_scroll_functions = Qnil;
-  
+
   DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
     doc: /* *Non-nil means automatically resize tool-bars.
 This increases a tool-bar's height if not all tool-bar items are visible.
 It decreases a tool-bar's height when it would display blank lines
 otherwise.  */);
   auto_resize_tool_bars_p = 1;
-  
+
   DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
     doc: /* *Non-nil means raise tool-bar buttons when the mouse moves over them.  */);
   auto_raise_tool_bar_buttons_p = 1;
@@ -15078,12 +18237,20 @@ only, until their display becomes empty, at which point the windows
 go back to their normal size.  */);
   Vresize_mini_windows = Qgrow_only;
 
-  DEFVAR_BOOL ("cursor-in-non-selected-windows",
-              &cursor_in_non_selected_windows,
-    doc: /* *Non-nil means display a hollow cursor in non-selected windows.
-nil means don't display a cursor there.  */);
-  cursor_in_non_selected_windows = 1;
-  
+  DEFVAR_LISP ("cursor-in-non-selected-windows",
+              &Vcursor_in_non_selected_windows,
+    doc: /* *Cursor type to display in non-selected windows.
+t means to use hollow box cursor.  See `cursor-type' for other values.  */);
+  Vcursor_in_non_selected_windows = Qt;
+
+  DEFVAR_LISP ("blink-cursor-alist", &Vblink_cursor_alist,
+    doc: /* Alist specifying how to blink the cursor off.
+Each element has the form (ON-STATE . OFF-STATE).  Whenever the
+`cursor-type' frame-parameter or variable equals ON-STATE,
+comparing using `equal', Emacs uses OFF-STATE to specify
+how to blink it off.  */);
+  Vblink_cursor_alist = Qnil;
+
   DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p,
     doc: /* *Non-nil means scroll the display automatically to make point visible.  */);
   automatic_hscrolling_p = 1;
@@ -15110,12 +18277,12 @@ scroll more than the value given by the scroll step.
 Note that the lower bound for automatic hscrolling specified by `scroll-left'
 and `scroll-right' overrides this variable's effect.  */);
   Vhscroll_step = make_number (0);
-  
+
   DEFVAR_LISP ("image-types", &Vimage_types,
     doc: /* List of supported image types.
 Each element of the list is a symbol for a supported image type.  */);
   Vimage_types = Qnil;
-  
+
   DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
     doc: /* If non-nil, messages are truncated instead of resizing the echo area.
 Bind this around calls to `message' to let it take effect.  */);
@@ -15125,7 +18292,7 @@ Bind this around calls to `message' to let it take effect.  */);
     doc: /* Normal hook run for clicks on menu bar, before displaying a submenu.
 Can be used to update submenus whose contents should vary.  */);
   Vmenu_bar_update_hook = Qnil;
-  
+
   DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update,
     doc: /* Non-nil means don't update menu bars.  Internal use only.  */);
   inhibit_menubar_update = 0;
@@ -15134,6 +18301,10 @@ Can be used to update submenus whose contents should vary.  */);
     doc: /* Non-nil means don't eval Lisp during redisplay.  */);
   inhibit_eval_during_redisplay = 0;
 
+  DEFVAR_BOOL ("inhibit-free-realized-faces", &inhibit_free_realized_faces,
+    doc: /* Non-nil means don't free realized faces.  Internal use only.  */);
+  inhibit_free_realized_faces = 0;
+
 #if GLYPH_DEBUG
   DEFVAR_BOOL ("inhibit-try-window-id", &inhibit_try_window_id,
               doc: /* Inhibit try_window_id display optimization.  */);
@@ -15184,21 +18355,20 @@ init_xdisp ()
       scratch_glyph_row.glyphs[TEXT_AREA + 1]
        = scratch_glyphs + MAX_SCRATCH_GLYPHS;
 
-      /* The default ellipsis glyphs `...'.  */ 
+      /* The default ellipsis glyphs `...'.  */
       for (i = 0; i < 3; ++i)
        default_invis_vector[i] = make_number ('.');
     }
 
-#ifdef HAVE_WINDOW_SYSTEM
   {
-    /* Allocate the buffer for frame titles.  */
+    /* Allocate the buffer for frame titles.
+       Also used for `format-mode-line'.  */
     int size = 100;
     frame_title_buf = (char *) xmalloc (size);
     frame_title_buf_end = frame_title_buf + size;
     frame_title_ptr = NULL;
   }
-#endif /* HAVE_WINDOW_SYSTEM */
-  
+
   help_echo_showing_p = 0;
 }