Fix last commit.
[bpt/emacs.git] / src / xdisp.c
index 224dd48..c0c11bf 100644 (file)
@@ -1,7 +1,8 @@
 /* Display generation from window structure and buffer text.
    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
                  1997, 1998, 1999, 2000, 2001, 2002, 2003,
-                 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+                 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+                 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -168,6 +169,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <config.h>
 #include <stdio.h>
 #include <limits.h>
+#include <setjmp.h>
 
 #include "lisp.h"
 #include "keyboard.h"
@@ -227,7 +229,7 @@ extern Lisp_Object do_mouse_tracking;
 extern int minibuffer_auto_raise;
 extern Lisp_Object Vminibuffer_list;
 
-extern Lisp_Object Qface;
+extern Lisp_Object Qface, Qdefault;
 extern Lisp_Object Qmode_line, Qmode_line_inactive, Qheader_line;
 
 extern Lisp_Object Voverriding_local_map;
@@ -235,6 +237,7 @@ extern Lisp_Object Voverriding_local_map_menu_flag;
 extern Lisp_Object Qmenu_item;
 extern Lisp_Object Qwhen;
 extern Lisp_Object Qhelp_echo;
+extern Lisp_Object Qbefore_string, Qafter_string;
 
 Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
@@ -354,6 +357,8 @@ extern Lisp_Object Voverflow_newline_into_fringe;
    && it->current_x == it->last_visible_x      \
    && it->line_wrap != WORD_WRAP)
 
+#else /* !HAVE_WINDOW_SYSTEM */
+#define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) 0
 #endif /* HAVE_WINDOW_SYSTEM */
 
 /* Test if the display element loaded in IT is a space or tab
@@ -915,7 +920,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_ ((const unsigned char *, int, int *));
+static int string_char_and_length P_ ((const unsigned char *, 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 *));
@@ -949,7 +954,8 @@ 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, 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 char *decode_mode_spec P_ ((struct window *, int, int, int,
+                                  Lisp_Object *));
 static void display_menu_bar P_ ((struct window *));
 static int display_count_lines P_ ((int, int, int, int, int *));
 static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
@@ -1359,7 +1365,7 @@ pos_visible_p (w, charpos, x, y, rtop, rbot, rowh, vpos)
       int top_x = it.current_x;
       int top_y = it.current_y;
       enum it_method it_method = it.method;
-      /* Calling line_bottom_y may change it.method.  */
+      /* Calling line_bottom_y may change it.method, it.position, etc.  */
       int bottom_y = (last_height = 0, line_bottom_y (&it));
       int window_top_y = WINDOW_HEADER_LINE_HEIGHT (w);
 
@@ -1369,33 +1375,7 @@ pos_visible_p (w, charpos, x, y, rtop, rbot, rowh, vpos)
        visible_p = 1;
       if (visible_p)
        {
-         if (it_method == GET_FROM_BUFFER)
-           {
-             Lisp_Object window, prop;
-
-             XSETWINDOW (window, w);
-             prop = Fget_char_property (make_number (it.position.charpos),
-                                        Qinvisible, window);
-
-             /* If charpos coincides with invisible text covered with an
-                ellipsis, use the first glyph of the ellipsis to compute
-                the pixel positions.  */
-             if (TEXT_PROP_MEANS_INVISIBLE (prop) == 2)
-               {
-                 struct glyph_row *row = it.glyph_row;
-                 struct glyph *glyph = row->glyphs[TEXT_AREA];
-                 struct glyph *end = glyph + row->used[TEXT_AREA];
-                 int x = row->x;
-
-                 for (; glyph < end
-                        && (!BUFFERP (glyph->object)
-                            || glyph->charpos < charpos);
-                      glyph++)
-                   x += glyph->pixel_width;
-                 top_x = x;
-               }
-           }
-         else if (it_method == GET_FROM_DISPLAY_VECTOR)
+         if (it_method == GET_FROM_DISPLAY_VECTOR)
            {
              /* We stopped on the last glyph of a display vector.
                 Try and recompute.  Hack alert!  */
@@ -1474,20 +1454,19 @@ pos_visible_p (w, charpos, x, y, rtop, rbot, rowh, vpos)
 }
 
 
-/* Return the next character from STR which is MAXLEN bytes long.
-   Return in *LEN the length of the character.  This is like
-   STRING_CHAR_AND_LENGTH but never returns an invalid character.  If
-   we find one, we return a `?', but with the length of the invalid
-   character.  */
+/* Return the next character from STR.  Return in *LEN the length of
+   the character.  This is like STRING_CHAR_AND_LENGTH but never
+   returns an invalid character.  If we find one, we return a `?', but
+   with the length of the invalid character.  */
 
 static INLINE int
-string_char_and_length (str, maxlen, len)
+string_char_and_length (str, len)
      const unsigned char *str;
-     int maxlen, *len;
+     int *len;
 {
   int c;
 
-  c = STRING_CHAR_AND_LENGTH (str, maxlen, *len);
+  c = STRING_CHAR_AND_LENGTH (str, *len);
   if (!CHAR_VALID_P (c, 1))
     /* We may not change the length here because other places in Emacs
        don't use this function, i.e. they silently accept invalid
@@ -1512,15 +1491,13 @@ string_pos_nchars_ahead (pos, string, nchars)
 
   if (STRING_MULTIBYTE (string))
     {
-      int rest = SBYTES (string) - BYTEPOS (pos);
       const unsigned char *p = SDATA (string) + BYTEPOS (pos);
       int len;
 
       while (nchars--)
        {
-         string_char_and_length (p, rest, &len);
-         p += len, rest -= len;
-         xassert (rest >= 0);
+         string_char_and_length (p, &len);
+         p += len;
          CHARPOS (pos) += 1;
          BYTEPOS (pos) += len;
        }
@@ -1565,14 +1542,13 @@ c_string_pos (charpos, s, multibyte_p)
 
   if (multibyte_p)
     {
-      int rest = strlen (s), len;
+      int len;
 
       SET_TEXT_POS (pos, 0, 0);
       while (charpos--)
        {
-         string_char_and_length (s, rest, &len);
-         s += len, rest -= len;
-         xassert (rest >= 0);
+         string_char_and_length (s, &len);
+         s += len;
          CHARPOS (pos) += 1;
          BYTEPOS (pos) += len;
        }
@@ -1601,7 +1577,7 @@ number_of_chars (s, multibyte_p)
 
       for (nchars = 0; rest > 0; ++nchars)
        {
-         string_char_and_length (p, rest, &len);
+         string_char_and_length (p, &len);
          rest -= len, p += len;
        }
     }
@@ -1632,7 +1608,7 @@ compute_string_pos (newpos, pos, string)
 }
 
 /* EXPORT:
-   Return an estimation of the pixel height of mode or top lines on
+   Return an estimation of the pixel height of mode or header lines on
    frame F.  FACE_ID specifies what line's height to estimate.  */
 
 int
@@ -1977,12 +1953,6 @@ get_glyph_string_clip_rects (s, rects, n)
        r.y = WINDOW_HEADER_LINE_HEIGHT (s->w);
       else
        r.y = max (0, s->row->y);
-
-      /* If drawing a tool-bar window, draw it over the internal border
-        at the top of the window.  */
-      if (WINDOWP (s->f->tool_bar_window)
-         && s->w == XWINDOW (s->f->tool_bar_window))
-       r.y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
     }
 
   r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
@@ -2894,16 +2864,6 @@ start_display (it, w, pos)
          it->current_x = it->hpos = 0;
        }
     }
-
-#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
-          || FETCH_BYTE (IT_BYTEPOS (it) - 1) == '\n');
-#endif /* 0 */
 }
 
 
@@ -3377,6 +3337,8 @@ handle_fontified_prop (it)
       val = Vfontification_functions;
       specbind (Qfontification_functions, Qnil);
 
+      xassert (it->end_charpos == ZV);
+      
       if (!CONSP (val) || EQ (XCAR (val), Qlambda))
        safe_call1 (val, pos);
       else
@@ -3416,6 +3378,13 @@ handle_fontified_prop (it)
 
       unbind_to (count, Qnil);
 
+      /* The fontification code may have added/removed text.
+        It could do even a lot worse, but let's at least protect against
+        the most obvious case where only the text past `pos' gets changed',
+        as is/was done in grep.el where some escapes sequences are turned
+        into face properties (bug#7876).  */
+      it->end_charpos = ZV;
+      
       /* Return HANDLED_RECOMPUTE_PROPS only if function fontified
         something.  This avoids an endless loop if they failed to
         fontify the text for which reason ever.  */
@@ -3543,14 +3512,6 @@ handle_face_prop (it)
                                             &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.  */
-      if (it->glyph_row == MATRIX_MODE_LINE_ROW (it->w->desired_matrix)
-         && 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
@@ -3658,11 +3619,10 @@ face_before_or_after_it_pos (it, before_p)
       if (STRING_MULTIBYTE (it->string))
        {
          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);
+         c = string_char_and_length (p, &len);
          face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), it->string);
        }
     }
@@ -3905,7 +3865,7 @@ setup_for_ellipsis (it, len)
     {
       struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
       it->dpvec = v->contents;
-      it->dpend = v->contents + v->size;
+      it->dpend = v->contents + v->header.size;
     }
   else
     {
@@ -4590,10 +4550,9 @@ display_prop_string_p (prop, string)
 }
 
 
-/* Determine from which buffer position in W's buffer STRING comes
-   from.  AROUND_CHARPOS is an approximate position where it could
-   be from.  Value is the buffer position or 0 if it couldn't be
-   determined.
+/* Determine which buffer position in W's buffer STRING comes from.
+   AROUND_CHARPOS is an approximate position where it could come from.
+   Value is the buffer position or 0 if it couldn't be determined.
 
    W's buffer must be current.
 
@@ -4665,7 +4624,7 @@ handle_composition_prop (it)
       pos_byte = IT_STRING_BYTEPOS (*it);
       string = it->string;
       s = SDATA (string) + pos_byte;
-      it->c = STRING_CHAR (s, 0);
+      it->c = STRING_CHAR (s);
     }
   else
     {
@@ -4682,6 +4641,11 @@ handle_composition_prop (it)
       && COMPOSITION_VALID_P (start, end, prop)
       && (STRINGP (it->string) || (PT <= start || PT >= end)))
     {
+      if (start < pos)
+       /* As we can't handle this situation (perhaps, font-lock added
+          a new composition), we just return here hoping that next
+          redisplay will detect this composition much earlier.  */
+       return HANDLED_NORMALLY;
       if (start != pos)
        {
          if (STRINGP (it->string))
@@ -4762,6 +4726,7 @@ next_overlay_string (it)
                   && it->stop_charpos <= it->end_charpos));
       it->current.overlay_string_index = -1;
       it->n_overlay_strings = 0;
+      it->overlay_strings_charpos = -1;
 
       /* If we're at the end of the buffer, record that we have
         processed the overlay strings there already, so that
@@ -4774,11 +4739,13 @@ next_overlay_string (it)
       /* There are more overlay strings to process.  If
         IT->current.overlay_string_index has advanced to a position
         where we must load IT->overlay_strings with more strings, do
-        it.  */
+        it.  We must load at the IT->overlay_strings_charpos where
+        IT->n_overlay_strings was originally computed; when invisible
+        text is present, this might not be IT_CHARPOS (Bug#7016).  */
       int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
 
       if (it->current.overlay_string_index && i == 0)
-       load_overlay_strings (it, 0);
+       load_overlay_strings (it, it->overlay_strings_charpos);
 
       /* Initialize IT to deliver display elements from the overlay
          string.  */
@@ -4868,7 +4835,7 @@ load_overlay_strings (it, charpos)
      struct it *it;
      int charpos;
 {
-  extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
+  extern Lisp_Object Qwindow, Qpriority;
   Lisp_Object overlay, window, str, invisible;
   struct Lisp_Overlay *ov;
   int start, end;
@@ -4994,8 +4961,9 @@ load_overlay_strings (it, charpos)
   if (n > 1)
     qsort (entries, n, sizeof *entries, compare_overlay_entries);
 
-  /* Record the total number of strings to process.  */
+  /* Record number of overlay strings, and where we computed it.  */
   it->n_overlay_strings = n;
+  it->overlay_strings_charpos = charpos;
 
   /* IT->current.overlay_string_index is the number of overlay strings
      that have already been consumed by IT.  Copy some of the
@@ -5182,6 +5150,16 @@ pop_it (it)
     case GET_FROM_STRING:
       it->object = it->string;
       break;
+    case GET_FROM_DISPLAY_VECTOR:
+      if (it->s)
+       it->method = GET_FROM_C_STRING;
+      else if (STRINGP (it->string))
+       it->method = GET_FROM_STRING;
+      else
+       {
+         it->method = GET_FROM_BUFFER;
+         it->object = it->w->buffer;
+       }
     }
   it->end_charpos = p->end_charpos;
   it->string_nchars = p->string_nchars;
@@ -5618,6 +5596,14 @@ reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
     it->dp = XCHAR_TABLE (Vstandard_display_table);
 
   it->stop_charpos = charpos;
+  if (s == NULL && it->multibyte_p)
+    {
+      EMACS_INT endpos = SCHARS (it->string);
+      if (endpos > it->end_charpos)
+       endpos = it->end_charpos;
+      composition_compute_stop_pos (&it->cmp_it, charpos, -1, endpos,
+                                   it->string);
+    }
   CHECK_IT (it);
 }
 
@@ -5645,11 +5631,11 @@ static int (* get_next_element[NUM_IT_METHODS]) P_ ((struct it *it)) =
 /* Return 1 iff a character at CHARPOS (and BYTEPOS) is composed
    (possibly with the following characters).  */
 
-#define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS)                            \
+#define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS,END_CHARPOS)                        \
   ((IT)->cmp_it.id >= 0                                                        \
    || ((IT)->cmp_it.stop_pos == (CHARPOS)                              \
        && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS,      \
-                                (IT)->end_charpos, (IT)->w,            \
+                                END_CHARPOS, (IT)->w,                  \
                                 FACE_FROM_ID ((IT)->f, (IT)->face_id), \
                                 (IT)->string)))
 
@@ -5689,9 +5675,26 @@ get_next_display_element (it)
       if (success_p && it->dpvec == NULL)
        {
          Lisp_Object dv;
+         struct charset *unibyte = CHARSET_FROM_ID (charset_unibyte);
+         enum { char_is_other = 0, char_is_nbsp, char_is_soft_hyphen }
+         nbsp_or_shy = char_is_other;
+         int c = it->c;        /* This is the character to display.  */
+
+         if (! it->multibyte_p && ! ASCII_CHAR_P (c))
+           {
+             xassert (SINGLE_BYTE_CHAR_P (c));
+             if (unibyte_display_via_language_environment)
+               {
+                 c = DECODE_CHAR (unibyte, c);
+                 if (c < 0)
+                   c = BYTE8_TO_CHAR (it->c);
+               }
+             else
+               c = BYTE8_TO_CHAR (it->c);
+           }
 
          if (it->dp
-             && (dv = DISP_CHAR_VECTOR (it->dp, it->c),
+             && (dv = DISP_CHAR_VECTOR (it->dp, c),
                  VECTORP (dv)))
            {
              struct Lisp_Vector *v = XVECTOR (dv);
@@ -5699,11 +5702,11 @@ get_next_display_element (it)
              /* Return the first character from the display table
                 entry, if not empty.  If empty, don't display the
                 current character.  */
-             if (v->size)
+             if (v->header.size)
                {
                  it->dpvec_char_len = it->len;
                  it->dpvec = v->contents;
-                 it->dpend = v->contents + v->size;
+                 it->dpend = v->contents + v->header.size;
                  it->current.dpvec_index = 0;
                  it->dpvec_face_id = -1;
                  it->saved_face_id = it->face_id;
@@ -5717,35 +5720,34 @@ get_next_display_element (it)
              goto get_next;
            }
 
+         if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
+           nbsp_or_shy = (c == 0xA0   ? char_is_nbsp
+                          : c == 0xAD ? char_is_soft_hyphen
+                          :             char_is_other);
+
          /* Translate control characters into `\003' or `^C' form.
             Control characters coming from a display table entry are
             currently not translated because we use IT->dpvec to hold
             the translation.  This could easily be changed but I
             don't believe that it is worth doing.
 
-            If it->multibyte_p is nonzero, non-printable non-ASCII
-            characters are also translated to octal form.
+            NBSP and SOFT-HYPEN are property translated too.
 
-            If it->multibyte_p is zero, eight-bit characters that
-            don't have corresponding multibyte char code are also
+            Non-printable characters and raw-byte characters are also
             translated to octal form.  */
-         else if ((it->c < ' '
-                   ? (it->area != TEXT_AREA
-                      /* In mode line, treat \n, \t like other crl chars.  */
-                      || (it->c != '\t'
-                          && it->glyph_row
-                          && (it->glyph_row->mode_line_p || it->avoid_cursor_p))
-                      || (it->c != '\n' && it->c != '\t'))
-                   : (it->multibyte_p
-                      ? (!CHAR_PRINTABLE_P (it->c)
-                         || (!NILP (Vnobreak_char_display)
-                             && (it->c == 0xA0 /* NO-BREAK SPACE */
-                                 || it->c == 0xAD /* SOFT HYPHEN */)))
-                      : (it->c >= 127
-                         && (! unibyte_display_via_language_environment
-                             || (UNIBYTE_CHAR_HAS_MULTIBYTE_P (it->c)))))))
+         if (((c < ' ' || c == 127) /* ASCII control chars */
+              ? (it->area != TEXT_AREA
+                 /* In mode line, treat \n, \t like other crl chars.  */
+                 || (c != '\t'
+                     && it->glyph_row
+                     && (it->glyph_row->mode_line_p || it->avoid_cursor_p))
+                 || (c != '\n' && c != '\t'))
+              : (nbsp_or_shy
+                 || CHAR_BYTE8_P (c)
+                 || ! CHAR_PRINTABLE_P (c))))
            {
-             /* IT->c is a control character which must be displayed
+             /* C is a control character, NBSP, SOFT-HYPEN, raw-byte,
+                or a non-printable character which must be displayed
                 either as '\003' or as `^C' where the '\\' and '^'
                 can be defined in the display table.  Fill
                 IT->ctl_chars with glyphs for what we have to
@@ -5757,7 +5759,7 @@ get_next_display_element (it)
 
              /* Handle control characters with ^.  */
 
-             if (it->c < 128 && it->ctl_arrow_p)
+             if (ASCII_CHAR_P (c) && it->ctl_arrow_p)
                {
                  int g;
 
@@ -5790,7 +5792,7 @@ get_next_display_element (it)
                    }
 
                  XSETINT (it->ctl_chars[0], g);
-                 XSETINT (it->ctl_chars[1], it->c ^ 0100);
+                 XSETINT (it->ctl_chars[1], c ^ 0100);
                  ctl_len = 2;
                  goto display_control;
                }
@@ -5799,13 +5801,13 @@ get_next_display_element (it)
                 highlighting.  */
 
              if (EQ (Vnobreak_char_display, Qt)
-                 && it->c == 0xA0)
+                 && nbsp_or_shy == char_is_nbsp)
                {
                  /* Merge the no-break-space face into the current face.  */
                  face_id = merge_faces (it->f, Qnobreak_space, 0,
                                         it->face_id);
 
-                 it->c = ' ';
+                 c = ' ';
                  XSETINT (it->ctl_chars[0], ' ');
                  ctl_len = 1;
                  goto display_control;
@@ -5849,9 +5851,8 @@ get_next_display_element (it)
                 highlighting.  */
 
              if (EQ (Vnobreak_char_display, Qt)
-                 && it->c == 0xAD)
+                 && nbsp_or_shy == char_is_soft_hyphen)
                {
-                 it->c = '-';
                  XSETINT (it->ctl_chars[0], '-');
                  ctl_len = 1;
                  goto display_control;
@@ -5860,58 +5861,28 @@ get_next_display_element (it)
              /* Handle non-break space and soft hyphen
                 with the escape glyph.  */
 
-             if (it->c == 0xA0 || it->c == 0xAD)
+             if (nbsp_or_shy)
                {
                  XSETINT (it->ctl_chars[0], escape_glyph);
-                 it->c = (it->c == 0xA0 ? ' ' : '-');
-                 XSETINT (it->ctl_chars[1], it->c);
+                 c = (nbsp_or_shy == char_is_nbsp ? ' ' : '-');
+                 XSETINT (it->ctl_chars[1], c);
                  ctl_len = 2;
                  goto display_control;
                }
 
              {
-               unsigned char str[MAX_MULTIBYTE_LENGTH];
-               int len;
-               int i;
+               char str[10];
+               int len, i;
 
-               /* Set IT->ctl_chars[0] to the glyph for `\\'.  */
-               if (CHAR_BYTE8_P (it->c))
-                 {
-                   str[0] = CHAR_TO_BYTE8 (it->c);
-                   len = 1;
-                 }
-               else if (it->c < 256)
-                 {
-                   str[0] = it->c;
-                   len = 1;
-                 }
-               else
-                 {
-                   /* It's an invalid character, which shouldn't
-                      happen actually, but due to bugs it may
-                      happen.  Let's print the char as is, there's
-                      not much meaningful we can do with it.  */
-                     str[0] = it->c;
-                     str[1] = it->c >> 8;
-                     str[2] = it->c >> 16;
-                     str[3] = it->c >> 24;
-                     len = 4;
-                   }
+               if (CHAR_BYTE8_P (c))
+                 /* Display \200 instead of \17777600.  */
+                 c = CHAR_TO_BYTE8 (c);
+               len = sprintf (str, "%03o", c);
 
+               XSETINT (it->ctl_chars[0], escape_glyph);
                for (i = 0; i < len; i++)
-                 {
-                   int g;
-                   XSETINT (it->ctl_chars[i * 4], escape_glyph);
-                   /* Insert three more glyphs into IT->ctl_chars for
-                      the octal display of the character.  */
-                   g = ((str[i] >> 6) & 7) + '0';
-                   XSETINT (it->ctl_chars[i * 4 + 1], g);
-                   g = ((str[i] >> 3) & 7) + '0';
-                   XSETINT (it->ctl_chars[i * 4 + 2], g);
-                   g = (str[i] & 7) + '0';
-                   XSETINT (it->ctl_chars[i * 4 + 3], g);
-                 }
-               ctl_len = len * 4;
+                 XSETINT (it->ctl_chars[i + 1], str[i]);
+               ctl_len = len + 1;
              }
 
            display_control:
@@ -5926,6 +5897,11 @@ get_next_display_element (it)
              it->ellipsis_p = 0;
              goto get_next;
            }
+         it->char_to_display = c;
+       }
+      else if (success_p)
+       {
+         it->char_to_display = it->c;
        }
     }
 
@@ -5951,8 +5927,21 @@ get_next_display_element (it)
          int pos = (it->s ? -1
                     : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
                     : IT_CHARPOS (*it));
+         int c;
 
-         it->face_id = FACE_FOR_CHAR (it->f, face, it->c, pos, it->string);
+         if (it->what == IT_CHARACTER)
+           c = it->char_to_display;
+         else
+           {
+             struct composition *cmp = composition_table[it->cmp_it.id];
+             int i;
+
+             c = ' ';
+             for (i = 0; i < cmp->glyph_len; i++)
+               if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
+                 break;
+           }
+         it->face_id = FACE_FOR_CHAR (it->f, face, c, pos, it->string);
        }
     }
 #endif
@@ -6204,8 +6193,8 @@ set_iterator_to_next (it, reseat_p)
    or `\003'.
 
    IT->dpvec holds the glyphs to return as characters.
-   IT->saved_face_id holds the face id before the display vector--
-   it is restored into IT->face_idin set_iterator_to_next.  */
+   IT->saved_face_id holds the face id before the display vector--it
+   is restored into IT->face_id in set_iterator_to_next.  */
 
 static int
 next_element_from_display_vector (it)
@@ -6289,17 +6278,16 @@ next_element_from_string (it)
          return 0;
        }
       else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
-                               IT_STRING_BYTEPOS (*it))
+                               IT_STRING_BYTEPOS (*it), SCHARS (it->string))
               && next_element_from_composition (it))
        {
          return 1;
        }
       else if (STRING_MULTIBYTE (it->string))
        {
-         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);
+         it->c = string_char_and_length (s, &it->len);
        }
       else
        {
@@ -6325,17 +6313,16 @@ next_element_from_string (it)
          CHARPOS (position) = BYTEPOS (position) = -1;
        }
       else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
-                               IT_STRING_BYTEPOS (*it))
+                               IT_STRING_BYTEPOS (*it), it->string_nchars)
               && next_element_from_composition (it))
        {
          return 1;
        }
       else if (STRING_MULTIBYTE (it->string))
        {
-         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);
+         it->c = string_char_and_length (s, &it->len);
        }
       else
        {
@@ -6386,14 +6373,7 @@ next_element_from_c_string (it)
       BYTEPOS (it->position) = CHARPOS (it->position) = -1;
     }
   else if (it->multibyte_p)
-    {
-      /* Implementation note: The calls to strlen apparently aren't a
-        performance problem because there is no noticeable performance
-        difference between Emacs running in unibyte or multibyte mode.  */
-      int maxlen = strlen (it->s) - IT_BYTEPOS (*it);
-      it->c = string_char_and_length (it->s + IT_BYTEPOS (*it),
-                                     maxlen, &it->len);
-    }
+    it->c = string_char_and_length (it->s + IT_BYTEPOS (*it), &it->len);
   else
     it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
 
@@ -6403,7 +6383,7 @@ next_element_from_c_string (it)
 
 /* Set up IT to return characters from an ellipsis, if appropriate.
    The definition of the ellipsis glyphs may come from a display table
-   entry.  This function Fills IT with the first glyph from the
+   entry.  This function fills IT with the first glyph from the
    ellipsis if an ellipsis is to be displayed.  */
 
 static int
@@ -6439,6 +6419,7 @@ next_element_from_image (it)
      struct it *it;
 {
   it->what = IT_IMAGE;
+  it->ignore_overlay_strings_at_pos_p = 0;
   return 1;
 }
 
@@ -6513,7 +6494,8 @@ next_element_from_buffer (it)
          && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos)
        run_redisplay_end_trigger_hook (it);
 
-      if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it))
+      if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
+                          it->end_charpos)
          && next_element_from_composition (it))
        {
          return 1;
@@ -6522,7 +6504,7 @@ next_element_from_buffer (it)
       /* Get the next character, maybe multibyte.  */
       p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
       if (it->multibyte_p && !ASCII_BYTE_P (*p))
-       it->c = STRING_CHAR_AND_LENGTH (p, 0, it->len);
+       it->c = STRING_CHAR_AND_LENGTH (p, it->len);
       else
        it->c = *p, it->len = 1;
 
@@ -6816,9 +6798,9 @@ move_it_in_display_line_to (struct it *it,
       /* The number of glyphs we get back in IT->nglyphs will normally
         be 1 except when IT->c is (i) a TAB, or (ii) a multi-glyph
         character on a terminal frame, or (iii) a line end.  For the
-        second case, IT->nglyphs - 1 padding glyphs will be present
-        (on X frames, there is only one glyph produced for a
-        composite character.
+        second case, IT->nglyphs - 1 padding glyphs will be present.
+        (On X frames, there is only one glyph produced for a
+        composite character.)
 
         The behavior implemented below means, for continuation lines,
         that as many spaces of a TAB as fit on the current line are
@@ -6918,8 +6900,7 @@ move_it_in_display_line_to (struct it *it,
                            }
 
                          set_iterator_to_next (it, 1);
-#ifdef HAVE_WINDOW_SYSTEM
-                         /* One graphical terminals, newlines may
+                         /* On graphical terminals, newlines may
                             "overflow" into the fringe if
                             overflow-newline-into-fringe is non-nil.
                             On text-only terminals, newlines may
@@ -6947,7 +6928,6 @@ move_it_in_display_line_to (struct it *it,
                                  break;
                                }
                            }
-#endif /* HAVE_WINDOW_SYSTEM */
                        }
                    }
                  else
@@ -7022,7 +7002,6 @@ move_it_in_display_line_to (struct it *it,
       if (it->line_wrap == TRUNCATE
          && it->current_x >= it->last_visible_x)
        {
-#ifdef HAVE_WINDOW_SYSTEM
          if (!FRAME_WINDOW_P (it->f)
              || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
            {
@@ -7038,7 +7017,6 @@ move_it_in_display_line_to (struct it *it,
                  break;
                }
            }
-#endif /* HAVE_WINDOW_SYSTEM */
          result = MOVE_LINE_TRUNCATED;
          break;
        }
@@ -7108,8 +7086,7 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
      int op;
 {
   enum move_it_result skip, skip2 = MOVE_X_REACHED;
-  int line_height;
-  int reached = 0;
+  int line_height, line_start_x = 0, reached = 0;
 
   for (;;)
     {
@@ -7292,7 +7269,11 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
              if (it->current_x != it->last_visible_x
                  && (op & MOVE_TO_VPOS)
                  && !(op & (MOVE_TO_X | MOVE_TO_POS)))
-               set_iterator_to_next (it, 0);
+               {
+                 line_start_x = it->current_x + it->pixel_width
+                   - it->last_visible_x;
+                 set_iterator_to_next (it, 0);
+               }
            }
          else
            it->continuation_lines_width += it->current_x;
@@ -7304,7 +7285,9 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
 
       /* Reset/increment for the next run.  */
       recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
-      it->current_x = it->hpos = 0;
+      it->current_x = line_start_x;
+      line_start_x = 0;
+      it->hpos = 0;
       it->current_y += it->max_ascent + it->max_descent;
       ++it->vpos;
       last_height = it->max_ascent + it->max_descent;
@@ -7415,11 +7398,6 @@ move_it_vertically_backward (it, dy)
         value of nlines is > 0 if continuation lines were involved.  */
       if (nlines > 0)
        move_it_by_lines (it, nlines, 1);
-#if 0
-      /* I think this assert is bogus if buffer contains
-        invisible text or images.  KFS.  */
-      xassert (IT_CHARPOS (*it) <= start_pos);
-#endif
     }
   else
     {
@@ -7467,12 +7445,6 @@ move_it_vertically_backward (it, dy)
                }
              while (target_y >= line_bottom_y (it) && IT_CHARPOS (*it) < ZV);
            }
-
-#if 0
-         /* I think this assert is bogus if buffer contains
-            invisible text or images.  KFS.  */
-         xassert (IT_CHARPOS (*it) >= BEGV);
-#endif
        }
     }
 }
@@ -7753,7 +7725,7 @@ message_dolog (m, nbytes, nlflag, multibyte)
             for the *Message* buffer.  */
          for (i = 0; i < nbytes; i += char_bytes)
            {
-             c = string_char_and_length (m + i, nbytes - i, &char_bytes);
+             c = string_char_and_length (m + i, &char_bytes);
              work[0] = (ASCII_CHAR_P (c)
                         ? c
                         : multibyte_char_to_unibyte (c, Qnil));
@@ -7771,7 +7743,7 @@ message_dolog (m, nbytes, nlflag, multibyte)
          for (i = 0; i < nbytes; i++)
            {
              c = msg[i];
-             c = unibyte_char_to_multibyte (c);
+             MAKE_CHAR_MULTIBYTE (c);
              char_bytes = CHAR_STRING (c, str);
              insert_1_both (str, 1, char_bytes, 1, 0, 0);
            }
@@ -9058,7 +9030,7 @@ set_message_1 (a1, a2, nbytes, multibyte_p)
          /* Convert a multibyte string to single-byte.  */
          for (i = 0; i < nbytes; i += n)
            {
-             c = string_char_and_length (s + i, nbytes - i, &n);
+             c = string_char_and_length (s + i, &n);
              work[0] = (ASCII_CHAR_P (c)
                         ? c
                         : multibyte_char_to_unibyte (c, Qnil));
@@ -9077,7 +9049,7 @@ set_message_1 (a1, a2, nbytes, multibyte_p)
          for (i = 0; i < nbytes; i++)
            {
              c = msg[i];
-             c = unibyte_char_to_multibyte (c);
+             MAKE_CHAR_MULTIBYTE (c);
              n = CHAR_STRING (c, str);
              insert_1_both (str, 1, n, 1, 0, 0);
            }
@@ -9491,32 +9463,7 @@ x_consider_frame_title (frame)
       if (! STRINGP (f->name)
          || SBYTES (f->name) != len
          || bcmp (title, SDATA (f->name), len) != 0)
-        {
-#ifdef HAVE_NS
-          if (FRAME_NS_P (f))
-            {
-              if (!MINI_WINDOW_P(XWINDOW(f->selected_window)))
-                {
-                  if (EQ (fmt, Qt))
-                    ns_set_name_as_filename (f);
-                  else
-                    x_implicitly_set_name (f, make_string(title, len),
-                                           Qnil);
-                }
-            }
-          else
-#endif
-           x_implicitly_set_name (f, make_string (title, len), Qnil);
-        }
-#ifdef HAVE_NS
-      if (FRAME_NS_P (f))
-        {
-          /* do this also for frames with explicit names */
-          ns_implicitly_set_icon_type(f);
-          ns_set_doc_edited(f, Fbuffer_modified_p
-                            (XWINDOW (f->selected_window)->buffer), Qnil);
-        }
-#endif
+       x_implicitly_set_name (f, make_string (title, len), Qnil);
     }
 }
 
@@ -9612,6 +9559,12 @@ prepare_menu_bars ()
          menu_bar_hooks_run = update_menu_bar (f, 0, menu_bar_hooks_run);
 #ifdef HAVE_WINDOW_SYSTEM
          update_tool_bar (f, 0);
+#endif
+#ifdef HAVE_NS
+          if (windows_or_buffers_changed
+             && FRAME_NS_P (f))
+            ns_set_doc_edited (f, Fbuffer_modified_p
+                              (XWINDOW (f->selected_window)->buffer));
 #endif
          UNGCPRO;
        }
@@ -9863,7 +9816,7 @@ update_tool_bar (f, save_match_data)
      struct frame *f;
      int save_match_data;
 {
-#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR
+#if defined (USE_GTK) || defined (HAVE_NS)
   int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
 #else
   int do_update = WINDOWP (f->tool_bar_window)
@@ -10337,7 +10290,7 @@ redisplay_tool_bar (f)
   struct it it;
   struct glyph_row *row;
 
-#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR
+#if defined (USE_GTK) || defined (HAVE_NS)
   if (FRAME_EXTERNAL_TOOL_BAR (f))
     update_frame_tool_bar (f);
   return 0;
@@ -10824,7 +10777,7 @@ hscroll_window_tree (window)
              current_buffer = XBUFFER (w->buffer);
 
              if (w == XWINDOW (selected_window))
-               pt = BUF_PT (current_buffer);
+               pt = PT;
              else
                {
                  pt = marker_position (w->pointm);
@@ -11258,7 +11211,7 @@ reconsider_clip_changes (w, b)
       int pt;
 
       if (w == XWINDOW (selected_window))
-       pt = BUF_PT (current_buffer);
+       pt = PT;
       else
        pt = marker_position (w->pointm);
 
@@ -11325,6 +11278,7 @@ redisplay_internal (preserve_echo_area)
      int preserve_echo_area;
 {
   struct window *w = XWINDOW (selected_window);
+  struct window *sw;
   struct frame *f;
   int pause;
   int must_finish = 0;
@@ -11395,6 +11349,9 @@ redisplay_internal (preserve_echo_area)
   }
 
  retry:
+  /* Remember the currently selected window.  */
+  sw = w;
+
   if (!EQ (old_frame, selected_frame)
       && FRAME_LIVE_P (XFRAME (old_frame)))
     /* When running redisplay, we play a bit fast-and-loose and allow e.g.
@@ -11457,10 +11414,17 @@ redisplay_internal (preserve_echo_area)
       }
   }
 
-
   /* Notice any pending interrupt request to change frame size.  */
   do_pending_window_change (1);
 
+  /* do_pending_window_change could change the selected_window due to
+     frame resizing which makes the selected window too small.  */
+  if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
+    {
+      sw = w;
+      reconsider_clip_changes (w, current_buffer);
+    }
+
   /* Clear frames marked as garbaged.  */
   if (frame_garbaged)
     clear_garbaged_frames ();
@@ -11606,7 +11570,7 @@ redisplay_internal (preserve_echo_area)
       && PT >= CHARPOS (tlbufpos)
       && PT <= Z - CHARPOS (tlendpos)
       /* All text outside that line, including its final newline,
-        must be unchanged */
+        must be unchanged */
       && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
                                        CHARPOS (tlendpos)))
     {
@@ -11614,15 +11578,15 @@ redisplay_internal (preserve_echo_area)
          && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
          && (CHARPOS (tlbufpos) == ZV
              || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
-       /* Former continuation line has disappeared by becoming empty */
+       /* Former continuation line has disappeared by becoming empty */
        goto cancel;
       else if (XFASTINT (w->last_modified) < MODIFF
               || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
               || MINI_WINDOW_P (w))
        {
          /* We have to handle the case of continuation around a
-            wide-column character (See the comment in indent.c around
-            line 885).
+            wide-column character (see the comment in indent.c around
+            line 1340).
 
             For instance, in the following case:
 
@@ -11632,13 +11596,14 @@ redisplay_internal (preserve_echo_area)
             ^^                ^^
             --------          --------
 
-            As we have to redraw the line above, we should goto cancel.  */
+            As we have to redraw the line above, we cannot use this
+            optimization.  */
 
          struct it it;
          int line_height_before = this_line_pixel_height;
 
          /* Note that start_display will handle the case that the
-            line starting at tlbufpos is a continuation lines.  */
+            line starting at tlbufpos is a continuation line.  */
          start_display (&it, w, tlbufpos);
 
          /* Implementation note: It this still necessary?  */
@@ -11654,7 +11619,7 @@ redisplay_internal (preserve_echo_area)
          display_line (&it);
 
          /* If line contains point, is not continued,
-             and ends at same distance from eob as before, we win */
+             and ends at same distance from eob as before, we win */
          if (w->cursor.vpos >= 0
               /* Line is not continued, otherwise this_line_start_pos
                  would have been set to 0 in display_line.  */
@@ -11673,29 +11638,17 @@ redisplay_internal (preserve_echo_area)
                    = 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)
-                        buffer.  There is no newline to count.  */
-                     delta = (Z
-                              - CHARPOS (tlendpos)
-                              - MATRIX_ROW_START_CHARPOS (row));
-                     delta_bytes = (Z_BYTE
-                                    - BYTEPOS (tlendpos)
-                                    - MATRIX_ROW_START_BYTEPOS (row));
-                   }
-                 else
-                   {
-                     /* This line ends in a newline.  Must take
-                        account of the newline and the rest of the
-                        text that follows.  */
-                     delta = (Z
-                              - CHARPOS (tlendpos)
-                              - MATRIX_ROW_START_CHARPOS (row));
-                     delta_bytes = (Z_BYTE
-                                    - BYTEPOS (tlendpos)
-                                    - MATRIX_ROW_START_BYTEPOS (row));
-                   }
+                 /* We used to distinguish between two cases here,
+                    conditioned by Z - CHARPOS (tlendpos) == ZV, for
+                    when the line ends in a newline or the end of the
+                    buffer's accessible portion.  But both cases did
+                    the same, so they were collapsed.  */
+                 delta = (Z
+                          - CHARPOS (tlendpos)
+                          - MATRIX_ROW_START_CHARPOS (row));
+                 delta_bytes = (Z_BYTE
+                                - BYTEPOS (tlendpos)
+                                - MATRIX_ROW_START_BYTEPOS (row));
 
                  increment_matrix_positions (w->current_matrix,
                                              this_line_vpos + 1,
@@ -11741,6 +11694,10 @@ redisplay_internal (preserve_echo_area)
          if (!must_finish)
            {
              do_pending_window_change (1);
+             /* If selected_window changed, redisplay again.  */
+             if (WINDOWP (selected_window)
+                 && (w = XWINDOW (selected_window)) != sw)
+               goto retry;
 
              /* We used to always goto end_of_redisplay here, but this
                 isn't enough if we have a blinking cursor.  */
@@ -11838,6 +11795,10 @@ redisplay_internal (preserve_echo_area)
              if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
                redisplay_windows (FRAME_ROOT_WINDOW (f));
 
+             /* The X error handler may have deleted that frame.  */
+             if (!FRAME_LIVE_P (f))
+               continue;
+
              /* Any scroll bars which redisplay_windows should have
                 nuked should now go away.  */
              if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
@@ -12031,8 +11992,9 @@ redisplay_internal (preserve_echo_area)
   do_pending_window_change (1);
 
   /* If we just did a pending size change, or have additional
-     visible frames, redisplay again.  */
-  if (windows_or_buffers_changed && !pause)
+     visible frames, or selected_window changed, redisplay again.  */
+  if ((windows_or_buffers_changed && !pause)
+      || (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw))
     goto retry;
 
   /* Clear the face cache eventually.  */
@@ -12255,7 +12217,7 @@ redisplay_windows (window)
        redisplay_windows (w->hchild);
       else if (!NILP (w->vchild))
        redisplay_windows (w->vchild);
-      else
+      else if (!NILP (w->buffer))
        {
          displayed_buffer = XBUFFER (w->buffer);
          /* Use list_of_error, not Qerror, so that
@@ -12308,10 +12270,11 @@ redisplay_window_1 (window)
 
 
 /* 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.
+   DELTA and DELTA_BYTES are the numbers of characters and bytes by
+   which positions recorded in ROW differ from current buffer
+   positions.
 
-   Return 0 if cursor is not on this row 1 otherwise.  */
+   Return 0 if cursor is not on this row, 1 otherwise.  */
 
 int
 set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
@@ -12323,16 +12286,18 @@ 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];
   struct glyph *cursor = NULL;
-  /* The first glyph that starts a sequence of glyphs from string.  */
+  /* The first glyph that starts a sequence of glyphs from a string
+     that is a value of a display property.  */
   struct glyph *string_start;
   /* The X coordinate of string_start.  */
   int string_start_x;
-  /* The last known character position.  */
+  /* The last known character position in row.  */
   int last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
   /* The last known character position before string_start.  */
   int string_before_pos;
   int x = row->x;
   int cursor_x = x;
+  /* Last buffer position covered by an overlay.  */
   int cursor_from_overlay_pos = 0;
   int pt_old = PT - delta;
 
@@ -12360,11 +12325,15 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
          string_start = NULL;
          x += glyph->pixel_width;
          ++glyph;
+         /* If we are beyond the cursor position computed from the
+            last overlay seen, that overlay is not in effect for
+            current cursor position.  Reset the cursor information
+            computed from that overlay.  */
          if (cursor_from_overlay_pos
              && last_pos >= cursor_from_overlay_pos)
            {
              cursor_from_overlay_pos = 0;
-             cursor = 0;
+             cursor = NULL;
            }
        }
       else
@@ -12375,7 +12344,7 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
              string_start = glyph;
              string_start_x = x;
            }
-         /* Skip all glyphs from string.  */
+         /* Skip all glyphs from string.  */
          do
            {
              Lisp_Object cprop;
@@ -12386,14 +12355,14 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
                      !NILP (cprop))
                  && (pos = string_buffer_position (w, glyph->object,
                                                    string_before_pos),
-                     (pos == 0   /* From overlay */
+                     (pos == 0   /* from overlay */
                       || pos == pt_old)))
                {
-                 /* Estimate overlay buffer position from the buffer
-                    positions of the glyphs before and after the overlay.
-                    Add 1 to last_pos so that if point corresponds to the
-                    glyph right after the overlay, we still use a 'cursor'
-                    property found in that overlay.  */
+                 /* Compute the first buffer position after the overlay.
+                    If the `cursor' property tells us how  many positions
+                    are associated with the overlay, use that.  Otherwise,
+                    estimate from the buffer positions of the glyphs
+                    before and after the overlay.  */
                  cursor_from_overlay_pos = (pos ? 0 : last_pos
                                             + (INTEGERP (cprop) ? XINT (cprop) : 0));
                  cursor = glyph;
@@ -12417,9 +12386,8 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
       while (glyph > row->glyphs[TEXT_AREA]
             && (glyph - 1)->charpos == last_pos)
        glyph--, x -= glyph->pixel_width;
-      /* That loop always goes one position too far,
-        including the glyph before the ellipsis.
-        So scan forward over that one.  */
+      /* That loop always goes one position too far, including the
+        glyph before the ellipsis.  So scan forward over that one.  */
       x += glyph->pixel_width;
       glyph++;
     }
@@ -12440,8 +12408,8 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
       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.  */
+      /* If POS == 0, STRING is from overlay.  We skip such glyphs
+        because we always put the cursor after overlay strings.  */
       while (pos == 0 && glyph < stop)
        {
          string = glyph->object;
@@ -12468,8 +12436,8 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
            }
        }
 
-      /* If we reached the end of the line, and end was from a string,
-        cursor is not on this line.  */
+      /* If we reached the end of the line, and END was from a string,
+        the cursor is not on this line.  */
       if (glyph == end && row->continued_p)
        return 0;
     }
@@ -12586,44 +12554,6 @@ cursor_row_fully_visible_p (w, force_p, current_matrix_p)
        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;
-      w->vscroll = 0;
-      w->cursor.y += dy;
-      shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
-    }
-  else /* MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row)) */
-    {
-      int dy = - (row->height - row->visible_height);
-      w->vscroll = dy;
-      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
-     the correct y-position.  */
-  if (w == XWINDOW (selected_window))
-    this_line_y = w->cursor.y;
-
-  /* If vscrolling requires a larger glyph matrix, arrange for a fresh
-     redisplay with larger matrices.  */
-  if (matrix->nrows < required_matrix_height (w))
-    {
-      fonts_changed_p = 1;
-      return 0;
-    }
-
-  return 1;
-#endif /* 0 */
 }
 
 
@@ -12863,7 +12793,11 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 
       /* If cursor ends up on a partially visible line,
         treat that as being off the bottom of the screen.  */
-      if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1, 0))
+      if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1, 0)
+         /* It's possible that the cursor is on the first line of the
+            buffer, which is partially obscured due to a vscroll
+            (Bug#7537).  In that case, avoid looping forever . */
+         && extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
        {
          clear_glyph_matrix (w->desired_matrix);
          ++extra_scroll_margin_lines;
@@ -13592,11 +13526,6 @@ redisplay_window (window, just_this_one_p)
          used_current_matrix_p = 1;
          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;
 
@@ -13686,7 +13615,7 @@ redisplay_window (window, just_this_one_p)
               = try_window_reusing_current_matrix (w)))
        {
          IF_DEBUG (debug_method_add (w, "1"));
-         if (try_window (window, startp, 1) < 0)
+         if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
            /* -1 means we need to scroll.
               0 means we need new matrices, but fonts_changed_p
               is set in that case, so we will detect it below.  */
@@ -13920,8 +13849,8 @@ redisplay_window (window, just_this_one_p)
            = DESIRED_MODE_LINE_HEIGHT (w);
        }
 
-      /* If top line height has changed, arrange for a thorough
-        immediate redisplay using the correct mode line height.  */
+      /* If header line height has changed, arrange for a thorough
+        immediate redisplay using the correct header line height.  */
       if (WINDOW_WANTS_HEADER_LINE_P (w)
          && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
        {
@@ -13968,7 +13897,7 @@ redisplay_window (window, just_this_one_p)
 #ifdef HAVE_WINDOW_SYSTEM
       if (FRAME_WINDOW_P (f))
         {
-#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR
+#if defined (USE_GTK) || defined (HAVE_NS)
           redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
 #else
           redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
@@ -14019,8 +13948,16 @@ redisplay_window (window, just_this_one_p)
         (*FRAME_TERMINAL (f)->redeem_scroll_bar_hook) (w);
     }
 
-  /* Restore current_buffer and value of point in it.  */
-  TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
+  /* Restore current_buffer and value of point in it.  The window
+     update may have changed the buffer, so first make sure `opoint'
+     is still valid (Bug#6177).  */
+  if (CHARPOS (opoint) < BEGV)
+    TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
+  else if (CHARPOS (opoint) > ZV)
+    TEMP_SET_PT_BOTH (Z, Z_BYTE);
+  else
+    TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
+
   set_buffer_internal_1 (old);
   /* Avoid an abort in TEMP_SET_PT_BOTH if the buffer has become
      shorter.  This can be caused by log truncation in *Messages*. */
@@ -14037,13 +13974,15 @@ redisplay_window (window, just_this_one_p)
    Value is 1 if successful.  It is zero if fonts were loaded during
    redisplay which makes re-adjusting glyph matrices necessary, and -1
    if point would appear in the scroll margins.
-   (We check that only if CHECK_MARGINS is nonzero.  */
+   (We check the former only if TRY_WINDOW_IGNORE_FONTS_CHANGE is
+   unset in FLAGS, and the latter only if TRY_WINDOW_CHECK_MARGINS is
+   set in FLAGS.)  */
 
 int
-try_window (window, pos, check_margins)
+try_window (window, pos, flags)
      Lisp_Object window;
      struct text_pos pos;
-     int check_margins;
+     int flags;
 {
   struct window *w = XWINDOW (window);
   struct it it;
@@ -14065,12 +14004,12 @@ try_window (window, pos, check_margins)
     {
       if (display_line (&it))
        last_text_row = it.glyph_row - 1;
-      if (fonts_changed_p)
+      if (fonts_changed_p && !(flags & TRY_WINDOW_IGNORE_FONTS_CHANGE))
        return 0;
     }
 
   /* Don't let the cursor end in the scroll margins.  */
-  if (check_margins
+  if ((flags & TRY_WINDOW_CHECK_MARGINS)
       && !MINI_WINDOW_P (w))
     {
       int this_scroll_margin;
@@ -14321,7 +14260,8 @@ 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;
-             row->redraw_fringe_bitmaps_p = 1;
+             if (row->fringe_bitmap_periodic_p)
+               row->redraw_fringe_bitmaps_p = 1;
 
              it.current_y += row->height;
 
@@ -14483,7 +14423,8 @@ 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;
-         row->redraw_fringe_bitmaps_p = 1;
+         if (row->fringe_bitmap_periodic_p)
+           row->redraw_fringe_bitmaps_p = 1;
        }
 
       /* Scroll the current matrix.  */
@@ -14922,7 +14863,7 @@ try_window_id (w)
          || !WINDOW_FULL_WIDTH_P (w)))
     GIVE_UP (4);
 
-  /* Give up if point is not known NOT to appear in W.  */
+  /* Give up if point is known NOT to appear in W.  */
   if (PT < CHARPOS (start))
     GIVE_UP (5);
 
@@ -14952,7 +14893,8 @@ try_window_id (w)
   if (!NILP (w->region_showing))
     GIVE_UP (10);
 
-  /* Can use this if overlay arrow position and or string have changed.  */
+  /* Can't use this if overlay arrow position and/or string have
+     changed.  */
   if (overlay_arrows_changed_p ())
     GIVE_UP (12);
 
@@ -15566,15 +15508,6 @@ try_window_id (w)
   else
     abort ();
 
-#if 0 /* This leads to problems, for instance when the cursor is
-        at ZV, and the cursor line displays no text.  */
-  /* Disable rows below what's displayed in the window.  This makes
-     debugging easier.  */
-  enable_glyph_matrix_rows (current_matrix,
-                           XFASTINT (w->window_end_vpos) + 1,
-                           bottom_vpos, 0);
-#endif
-
   IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
            debug_end_vpos = XFASTINT (w->window_end_vpos));
 
@@ -15953,15 +15886,19 @@ get_overlay_arrow_glyph_row (w, overlay_arrow_string)
 
       /* Get the next character.  */
       if (multibyte_p)
-       it.c = string_char_and_length (p, arrow_len, &it.len);
+       it.c = it.char_to_display = string_char_and_length (p, &it.len);
       else
-       it.c = *p, it.len = 1;
+       {
+         it.c = it.char_to_display = *p, it.len = 1;
+         if (! ASCII_CHAR_P (it.c))
+           it.char_to_display = BYTE8_TO_CHAR (it.c);
+       }
       p += it.len;
 
       /* Get its face.  */
       ilisp = make_number (p - arrow_string);
       face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
-      it.face_id = compute_char_face (f, it.c, face);
+      it.face_id = compute_char_face (f, it.char_to_display, face);
 
       /* Compute its width, get its glyphs.  */
       n_glyphs_before = it.glyph_row->used[TEXT_AREA];
@@ -16160,6 +16097,7 @@ append_space_for_newline (it, default_face_p)
             append_space_for_newline has been called.  */
          enum display_element_type saved_what = it->what;
          int saved_c = it->c, saved_len = it->len;
+         int saved_char_to_display = it->char_to_display;
          int saved_x = it->current_x;
          int saved_face_id = it->face_id;
          struct text_pos saved_pos;
@@ -16172,7 +16110,7 @@ append_space_for_newline (it, default_face_p)
          it->what = IT_CHARACTER;
          bzero (&it->position, sizeof it->position);
          it->object = make_number (0);
-         it->c = ' ';
+         it->c = it->char_to_display = ' ';
          it->len = 1;
 
          if (default_face_p)
@@ -16193,6 +16131,7 @@ append_space_for_newline (it, default_face_p)
          it->face_id = saved_face_id;
          it->len = saved_len;
          it->c = saved_c;
+         it->char_to_display = saved_char_to_display;
          return 1;
        }
     }
@@ -16237,9 +16176,10 @@ extend_face_to_end_of_line (it)
   it->glyph_row->fill_line_p = 1;
 
   /* If current character of IT is not ASCII, make sure we have the
-         ASCII face.  This will be automatically undone the next time
-         get_next_display_element returns a multibyte character.  Note
-         that the character will always be single byte in unibyte text.  */
+     ASCII face.  This will be automatically undone the next time
+     get_next_display_element returns a multibyte character.  Note
+     that the character will always be single byte in unibyte
+     text.  */
   if (!ASCII_CHAR_P (it->c))
     {
       it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
@@ -16271,7 +16211,7 @@ extend_face_to_end_of_line (it)
       it->what = IT_CHARACTER;
       bzero (&it->position, sizeof it->position);
       it->object = make_number (0);
-      it->c = ' ';
+      it->c = it->char_to_display = ' ';
       it->len = 1;
       it->face_id = face->id;
 
@@ -16434,22 +16374,20 @@ cursor_row_p (w, row)
 \f
 
 /* Push the display property PROP so that it will be rendered at the
-   current position in IT.  */
+   current position in IT.  Return 1 if PROP was successfully pushed,
+   0 otherwise.  */
 
-static void
+static int
 push_display_prop (struct it *it, Lisp_Object prop)
 {
   push_it (it);
 
-  /* Never display a cursor on the prefix.  */
-  it->avoid_cursor_p = 1;
-
   if (STRINGP (prop))
     {
       if (SCHARS (prop) == 0)
        {
          pop_it (it);
-         return;
+         return 0;
        }
 
       it->string = prop;
@@ -16476,8 +16414,10 @@ push_display_prop (struct it *it, Lisp_Object prop)
   else
     {
       pop_it (it);             /* bogus display property, give up */
-      return;
+      return 0;
     }
+
+  return 1;
 }
 
 /* Return the character-property PROP at the current position in IT.  */
@@ -16517,13 +16457,13 @@ handle_line_prefix (struct it *it)
       if (NILP (prefix))
        prefix = Vline_prefix;
     }
-  if (! NILP (prefix))
+  if (! NILP (prefix) && push_display_prop (it, prefix))
     {
-      push_display_prop (it, prefix);
       /* If the prefix is wider than the window, and we try to wrap
         it, it would acquire its own wrap prefix, and so on till the
         iterator stack overflows.  So, don't wrap the prefix.  */
       it->line_wrap = TRUNCATE;
+      it->avoid_cursor_p = 1;
     }
 }
 
@@ -16618,13 +16558,10 @@ display_line (it)
             display the cursor there under X.  Set the charpos of the
             first glyph of blank lines not corresponding to any text
             to -1.  */
-#ifdef HAVE_WINDOW_SYSTEM
          if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
            row->exact_window_width_line_p = 1;
-         else
-#endif /* HAVE_WINDOW_SYSTEM */
-         if ((append_space_for_newline (it, 1) && row->used[TEXT_AREA] == 1)
-             || row->used[TEXT_AREA] == 0)
+         else if ((append_space_for_newline (it, 1) && row->used[TEXT_AREA] == 1)
+                  || row->used[TEXT_AREA] == 0)
            {
              row->glyphs[TEXT_AREA]->charpos = -1;
              row->displays_text_p = 0;
@@ -16766,7 +16703,6 @@ display_line (it)
                            goto back_to_wrap;
 
                          set_iterator_to_next (it, 1);
-#ifdef HAVE_WINDOW_SYSTEM
                          if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
                            {
                              if (!get_next_display_element (it))
@@ -16782,7 +16718,6 @@ display_line (it)
                                  row->exact_window_width_line_p = 1;
                                }
                            }
-#endif /* HAVE_WINDOW_SYSTEM */
                        }
                    }
                  else if (CHAR_GLYPH_PADDING_P (*glyph)
@@ -16919,12 +16854,10 @@ display_line (it)
 
          row->ends_in_newline_from_string_p = STRINGP (it->object);
 
-#ifdef HAVE_WINDOW_SYSTEM
          /* Add a space at the end of the line that is used to
             display the cursor there.  */
          if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
            append_space_for_newline (it, 0);
-#endif /* HAVE_WINDOW_SYSTEM */
 
          /* Extend the face to the end of the line.  */
          extend_face_to_end_of_line (it);
@@ -16965,27 +16898,22 @@ display_line (it)
                  produce_special_glyphs (it, IT_TRUNCATION);
                }
            }
-#ifdef HAVE_WINDOW_SYSTEM
-         else
+         else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
            {
              /* Don't truncate if we can overflow newline into fringe.  */
-             if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+             if (!get_next_display_element (it))
                {
-                 if (!get_next_display_element (it))
-                   {
-                     it->continuation_lines_width = 0;
-                     row->ends_at_zv_p = 1;
-                     row->exact_window_width_line_p = 1;
-                     break;
-                   }
-                 if (ITERATOR_AT_END_OF_LINE_P (it))
-                   {
-                     row->exact_window_width_line_p = 1;
-                     goto at_end_of_line;
-                   }
+                 it->continuation_lines_width = 0;
+                 row->ends_at_zv_p = 1;
+                 row->exact_window_width_line_p = 1;
+                 break;
+               }
+             if (ITERATOR_AT_END_OF_LINE_P (it))
+               {
+                 row->exact_window_width_line_p = 1;
+                 goto at_end_of_line;
                }
            }
-#endif /* HAVE_WINDOW_SYSTEM */
 
          row->truncated_on_right_p = 1;
          it->continuation_lines_width = 0;
@@ -17178,7 +17106,7 @@ display_menu_bar (w)
 
   /* Display all items of the menu bar.  */
   items = FRAME_MENU_BAR_ITEMS (it.f);
-  for (i = 0; i < XVECTOR (items)->size; i += 4)
+  for (i = 0; i < XVECTOR_SIZE (items); i += 4)
     {
       Lisp_Object string;
 
@@ -17276,8 +17204,8 @@ redisplay_mode_lines (window, force)
 }
 
 
-/* Display the mode and/or top line of window W.  Value is the number
-   of mode lines displayed.  */
+/* Display the mode and/or header line of window W.  Value is the
+   sum number of mode lines and header lines displayed.  */
 
 static int
 display_mode_lines (w)
@@ -17318,10 +17246,11 @@ display_mode_lines (w)
 }
 
 
-/* Display mode or top line of window W.  FACE_ID specifies which line
-   to display; it is either MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID.
-   FORMAT is the mode line format to display.  Value is the pixel
-   height of the mode line displayed.  */
+/* Display mode or header line of window W.  FACE_ID specifies which
+   line to display; it is either MODE_LINE_FACE_ID or
+   HEADER_LINE_FACE_ID.  FORMAT is the mode/header line format to
+   display.  Value is the pixel height of the mode/header line
+   displayed.  */
 
 static int
 display_mode_line (w, face_id, format)
@@ -17643,13 +17572,14 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                    int multibyte;
                    int bytepos, charpos;
                    unsigned char *spec;
+                   Lisp_Object string;
 
                    bytepos = percent_position;
                    charpos = (STRING_MULTIBYTE (elt)
                               ? string_byte_to_char (elt, bytepos)
                               : bytepos);
-                   spec
-                     = decode_mode_spec (it->w, c, field, prec, &multibyte);
+                   spec = decode_mode_spec (it->w, c, field, prec, &string);
+                   multibyte = STRINGP (string) && STRING_MULTIBYTE (string);
 
                    switch (mode_line_target)
                      {
@@ -17671,7 +17601,7 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                          int nglyphs_before, nwritten;
 
                          nglyphs_before = it->glyph_row->used[TEXT_AREA];
-                         nwritten = display_string (spec, Qnil, elt,
+                         nwritten = display_string (spec, string, elt,
                                                     charpos, 0, it,
                                                     field, prec, 0,
                                                     multibyte);
@@ -17837,10 +17767,10 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
          }
        else if (STRINGP (car) || CONSP (car))
          {
-           register int limit = 50;
-           /* Limit is to protect against circular lists.  */
+           Lisp_Object halftail = elt;
+           int len = 0;
+
            while (CONSP (elt)
-                  && --limit > 0
                   && (precision <= 0 || n < precision))
              {
                n += display_mode_element (it, depth,
@@ -17852,6 +17782,12 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                                           precision - n, XCAR (elt),
                                           props, risky);
                elt = XCDR (elt);
+               len++;
+               if ((len & 1) == 0)
+                 halftail = XCDR (halftail);
+               /* Check for cycle.  */
+               if (EQ (halftail, elt))
+                 break;
              }
          }
       }
@@ -17992,16 +17928,19 @@ DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
 First arg FORMAT specifies the mode line format (see `mode-line-format'
 for details) to use.
 
-Optional second arg FACE specifies the face property to put
-on all characters for which no face is specified.
-The value t means whatever face the window's mode line currently uses
-\(either `mode-line' or `mode-line-inactive', depending).
-A value of nil means the default is no face property.
-If FACE is an integer, the value string has no text properties.
+By default, the format is evaluated for the currently selected window.
+
+Optional second arg FACE specifies the face property to put on all
+characters for which no face is specified.  The value nil means the
+default face.  The value t means whatever face the window's mode line
+currently uses (either `mode-line' or `mode-line-inactive',
+depending on whether the window is the selected window or not).
+An integer value means the value string has no text
+properties.
 
 Optional third and fourth args WINDOW and BUFFER specify the window
 and buffer to use as the context for the formatting (defaults
-are the selected window and the window's buffer).  */)
+are the selected window and the WINDOW's buffer).  */)
      (format, face, window, buffer)
      Lisp_Object format, face, window, buffer;
 {
@@ -18009,7 +17948,7 @@ are the selected window and the window's buffer).  */)
   int len;
   struct window *w;
   struct buffer *old_buffer = NULL;
-  int face_id = -1;
+  int face_id;
   int no_props = INTEGERP (face);
   int count = SPECPDL_INDEX ();
   Lisp_Object str;
@@ -18032,15 +17971,14 @@ are the selected window and the window's buffer).  */)
   if (no_props)
     face = Qnil;
 
-  if (!NILP (face))
-    {
-      if (EQ (face, Qt))
-       face = (EQ (window, selected_window) ? Qmode_line : Qmode_line_inactive);
-      face_id = lookup_named_face (XFRAME (WINDOW_FRAME (w)), face, 0);
-    }
-
-  if (face_id < 0)
-    face_id = DEFAULT_FACE_ID;
+  face_id = (NILP (face) || EQ (face, Qdefault)) ? DEFAULT_FACE_ID
+    : EQ (face, Qt) ? (EQ (window, selected_window)
+                      ? MODE_LINE_FACE_ID : MODE_LINE_INACTIVE_FACE_ID)
+    : EQ (face, Qmode_line) ? MODE_LINE_FACE_ID
+    : EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
+    : EQ (face, Qheader_line) ? HEADER_LINE_FACE_ID
+    : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
+    : DEFAULT_FACE_ID;
 
   if (XBUFFER (buffer) != current_buffer)
     old_buffer = current_buffer;
@@ -18328,8 +18266,8 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
 /* Return a string for the output of a mode line %-spec for window W,
    generated by character C.  PRECISION >= 0 means don't return a
    string longer than that value.  FIELD_WIDTH > 0 means pad the
-   string returned with spaces to that value.  Return 1 in *MULTIBYTE
-   if the result is multibyte text.
+   string returned with spaces to that value.  Return a Lisp string in
+   *STRING if the resulting string is taken from that Lisp string.
 
    Note we operate on the current buffer for most purposes,
    the exception being w->base_line_pos.  */
@@ -18337,11 +18275,11 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
 
 static char *
-decode_mode_spec (w, c, field_width, precision, multibyte)
+decode_mode_spec (w, c, field_width, precision, string)
      struct window *w;
      register int c;
      int field_width, precision;
-     int *multibyte;
+     Lisp_Object *string;
 {
   Lisp_Object obj;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
@@ -18349,7 +18287,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
   struct buffer *b = current_buffer;
 
   obj = Qnil;
-  *multibyte = 0;
+  *string = Qnil;
 
   switch (c)
     {
@@ -18684,8 +18622,11 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
 
     case '@':
       {
-       Lisp_Object val;
-       val = call1 (intern ("file-remote-p"), current_buffer->directory);
+       int count = inhibit_garbage_collection ();
+       Lisp_Object val = call1 (intern ("file-remote-p"),
+                                current_buffer->directory);
+       unbind_to (count, Qnil);
+
        if (NILP (val))
          return "-";
        else
@@ -18740,7 +18681,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
 
   if (STRINGP (obj))
     {
-      *multibyte = STRING_MULTIBYTE (obj);
+      *string = obj;
       return (char *) SDATA (obj);
     }
   else
@@ -18861,7 +18802,10 @@ display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
 /* Display a NUL-terminated string, starting with index START.
 
    If STRING is non-null, display that C string.  Otherwise, the Lisp
-   string LISP_STRING is displayed.
+   string LISP_STRING is displayed.  There's a case that STRING is
+   non-null and LISP_STRING is not nil.  It means STRING is a string
+   data of LISP_STRING.  In that case, we display LISP_STRING while
+   ignoring its text properties.
 
    If FACE_STRING is not nil, FACE_STRING_POS is a position in
    FACE_STRING.  Display STRING or LISP_STRING with the face at
@@ -18911,8 +18855,12 @@ display_string (string, lisp_string, face_string, face_string_pos,
 
   /* Initialize the iterator IT for iteration over STRING beginning
      with index START.  */
-  reseat_to_string (it, string, lisp_string, start,
+  reseat_to_string (it, NILP (lisp_string) ? string : NULL, lisp_string, start,
                    precision, field_width, multibyte);
+  if (string && STRINGP (lisp_string)) 
+    /* LISP_STRING is the one returned by decode_mode_spec.  We should
+       ignore its text properties.  */
+    it->stop_charpos = -1;
 
   /* If displaying STRING, set up the face of the iterator
      from LISP_STRING, if that's given.  */
@@ -19476,12 +19424,6 @@ init_glyph_string (s, OPTIONAL_HDC (hdc) char2b, w, row, area, start, hl)
   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 (WINDOWP (s->f->tool_bar_window)
-      && s->w == XWINDOW (s->f->tool_bar_window))
-    s->y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
-
   s->ybase = s->y + row->ascent;
 }
 
@@ -19600,7 +19542,12 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
 
   if (face->font)
     {
-      unsigned code = face->font->driver->encode_char (face->font, glyph->u.ch);
+      unsigned code;
+
+      if (CHAR_BYTE8_P (glyph->u.ch))
+       code = CHAR_TO_BYTE8 (glyph->u.ch);
+      else
+       code = face->font->driver->encode_char (face->font, glyph->u.ch);
 
       if (code != FONT_INVALID_CODE)
        STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
@@ -19615,6 +19562,26 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
 }
 
 
+/* Get glyph code of character C in FONT in the two-byte form CHAR2B.
+   Retunr 1 if FONT has a glyph for C, otherwise return 0.  */
+
+static INLINE int
+get_char_glyph_code (int c, struct font *font, XChar2b *char2b)
+{
+  unsigned code;
+
+  if (CHAR_BYTE8_P (c))
+    code = CHAR_TO_BYTE8 (c);
+  else
+    code = font->driver->encode_char (font, c);
+
+  if (code == FONT_INVALID_CODE)
+    return 0;
+  STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
+  return 1;
+}
+
+
 /* Fill glyph string S with composition components specified by S->cmp.
 
    BASE_FACE is the base face of the composition.
@@ -19913,10 +19880,10 @@ x_get_glyph_overhangs (glyph, f, left, right)
        {
          struct composition *cmp = composition_table[glyph->u.cmp.id];
 
-         if (cmp->rbearing - cmp->pixel_width)
+         if (cmp->rbearing > cmp->pixel_width)
            *right = cmp->rbearing - cmp->pixel_width;
-         if (cmp->lbearing < 0);
-         *left = - cmp->lbearing;
+         if (cmp->lbearing < 0)
+           *left = - cmp->lbearing;
        }
       else
        {
@@ -19926,7 +19893,7 @@ x_get_glyph_overhangs (glyph, f, left, right)
          composition_gstring_width (gstring, glyph->u.cmp.from,
                                     glyph->u.cmp.to + 1, &metrics);
          if (metrics.rbearing > metrics.width)
-           *right = metrics.rbearing;
+           *right = metrics.rbearing - metrics.width;
          if (metrics.lbearing < 0)
            *left = - metrics.lbearing;
        }
@@ -20451,6 +20418,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
          j = i;
          BUILD_GLYPH_STRINGS (j, start, h, t,
                               overlap_hl, dummy_x, last_x);
+         start = i;
          compute_overhangs_and_x (t, head->x, 1);
          prepend_glyph_string_lists (&head, &tail, h, t);
          clip_head = head;
@@ -20500,6 +20468,8 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
 
          BUILD_GLYPH_STRINGS (end, i, h, t,
                               overlap_hl, x, last_x);
+         /* Because BUILD_GLYPH_STRINGS updates the first argument,
+            we don't have `end = i;' here.  */
          compute_overhangs_and_x (h, tail->x + tail->width, 0);
          append_glyph_string_lists (&head, &tail, h, t);
          clip_tail = tail;
@@ -20804,13 +20774,6 @@ produce_image_glyph (it)
   if (it->descent < 0)
     it->descent = 0;
 
-#if 0  /* this breaks image tiling */
-  /* If this glyph is alone on the last line, adjust it.ascent to minimum row ascent.  */
-  int face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f);
-  if (face_ascent > it->ascent)
-    it->ascent = it->phys_ascent = face_ascent;
-#endif
-
   it->nglyphs = 1;
 
   if (face->box != FACE_NO_BOX)
@@ -20988,13 +20951,13 @@ produce_stretch_glyph (it)
 
       it2 = *it;
       if (it->multibyte_p)
+       it2.c = it2.char_to_display = STRING_CHAR_AND_LENGTH (p, it2.len);
+      else
        {
-         int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
-                       - IT_BYTEPOS (*it));
-         it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
+         it2.c = it2.char_to_display = *p, it2.len = 1;
+         if (! ASCII_CHAR_P (it2.c))
+           it2.char_to_display = BYTE8_TO_CHAR (it2.c);
        }
-      else
-       it2.c = *p, it2.len = 1;
 
       it2.glyph_row = NULL;
       it2.what = IT_CHARACTER;
@@ -21168,51 +21131,23 @@ x_produce_glyphs (it)
   if (it->what == IT_CHARACTER)
     {
       XChar2b char2b;
-      struct font *font;
       struct face *face = FACE_FROM_ID (it->f, it->face_id);
-      struct font_metrics *pcm;
-      int font_not_found_p;
+      struct font *font = face->font;
+      int font_not_found_p = font == NULL;
+      struct font_metrics *pcm = NULL;
       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)
-         && ! it->multibyte_p)
-       {
-         if (SINGLE_BYTE_CHAR_P (it->c)
-             && unibyte_display_via_language_environment)
-           it->char_to_display = unibyte_char_to_multibyte (it->c);
-         if (! SINGLE_BYTE_CHAR_P (it->char_to_display))
-           {
-             it->multibyte_p = 1;
-             it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display,
-                                          -1, Qnil);
-             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);
+         /* When no suitable font found, display an empty box based
+            on the metrics of the font of the default face (or what
+            remapped).  */
+         struct face *no_font_face
+           = FACE_FROM_ID (it->f,
+                           NILP (Vface_remapping_alist) ? DEFAULT_FACE_ID
+                           : lookup_basic_face (it->f, DEFAULT_FACE_ID));
+         font = no_font_face->font;
+         boff = font->baseline_offset;
        }
       else
        {
@@ -21221,16 +21156,12 @@ x_produce_glyphs (it)
            boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
        }
 
-      if (it->char_to_display >= ' '
-         && (!it->multibyte_p || it->char_to_display < 128))
+      if (it->char_to_display != '\n' && it->char_to_display != '\t')
        {
-         /* Either unibyte or ASCII.  */
          int stretched_p;
 
          it->nglyphs = 1;
 
-         pcm = get_per_char_metric (it->f, font, &char2b);
-
          if (it->override_ascent >= 0)
            {
              it->ascent = it->override_ascent;
@@ -21243,6 +21174,15 @@ x_produce_glyphs (it)
              it->descent = FONT_DESCENT (font) - boff;
            }
 
+         if (! font_not_found_p
+             && get_char_glyph_code (it->char_to_display, font, &char2b))
+           {
+             pcm = get_per_char_metric (it->f, font, &char2b);
+             if (pcm->width == 0
+                 && pcm->rbearing == 0 && pcm->lbearing == 0)
+               pcm = NULL;
+           }
+
          if (pcm)
            {
              it->phys_ascent = pcm->ascent + boff;
@@ -21254,7 +21194,7 @@ x_produce_glyphs (it)
              it->glyph_not_available_p = 1;
              it->phys_ascent = it->ascent;
              it->phys_descent = it->descent;
-             it->pixel_width = FONT_WIDTH (font);
+             it->pixel_width = font->space_width;
            }
 
          if (it->constrain_row_ascent_descent_p)
@@ -21344,9 +21284,9 @@ x_produce_glyphs (it)
        }
       else if (it->char_to_display == '\n')
        {
-         /* A newline has no width but we need the height of the line.
-            But if previous part of the line set a height, don't
-            increase that height */
+         /* A newline has no width, but we need the height of the
+            line.  But if previous part of the line sets a height,
+            don't increase that height */
 
          Lisp_Object height;
          Lisp_Object total_height = Qnil;
@@ -21428,7 +21368,7 @@ x_produce_glyphs (it)
                }
            }
        }
-      else if (it->char_to_display == '\t')
+      else                   /* i.e. (it->char_to_display == '\t') */
        {
          if (font->space_width > 0)
            {
@@ -21459,94 +21399,15 @@ x_produce_glyphs (it)
              it->nglyphs = 1;
            }
        }
-      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 by
-            multiplying the width of font by the width of the
-            character.  */
-
-         pcm = get_per_char_metric (it->f, font, &char2b);
-
-         if (font_not_found_p || !pcm)
-           {
-             int char_width = CHAR_WIDTH (it->char_to_display);
-
-             if (char_width == 0)
-               /* This is a non spacing character.  But, as we are
-                  going to display an empty box, the box must occupy
-                  at least one column.  */
-               char_width = 1;
-             it->glyph_not_available_p = 1;
-             it->pixel_width = FRAME_COLUMN_WIDTH (it->f) * char_width;
-             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 += overline_margin;
-
-         take_vertical_position_into_account (it);
-
-         if (it->ascent < 0)
-           it->ascent = 0;
-         if (it->descent < 0)
-           it->descent = 0;
-
-         if (it->glyph_row)
-           append_glyph (it);
-         if (it->pixel_width == 0)
-           /* We assure that all visible glyphs have at least 1-pixel
-              width.  */
-           it->pixel_width = 1;
-       }
-      it->multibyte_p = saved_multibyte_p;
     }
   else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
     {
-      /* A static compositoin.
+      /* A static composition.
 
         Note: A composition is represented as one glyph in the
         glyph matrix.  There are no padding glyphs.
 
-        Important is that pixel_width, ascent, and descent are the
+        Important note: pixel_width, ascent, and descent are the
         values of what is drawn by draw_glyphs (i.e. the values of
         the overall glyphs composed).  */
       struct face *face = FACE_FROM_ID (it->f, it->face_id);
@@ -21561,15 +21422,15 @@ x_produce_glyphs (it)
         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, but it's very rare, and C-l (recenter)
-        can correct the display anyway.  */
+        here we check only the font of the first glyph.  This may
+        lead to incorrect display, but it's very rare, and C-l
+        (recenter-top-bottom) can correct the display anyway.  */
       if (! cmp->font || cmp->font != 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.  */
+            than these, respectively.  */
          int font_ascent, font_descent, font_height;
          /* Bounding box of the overall glyphs.  */
          int leftmost, rightmost, lowest, highest;
@@ -21598,7 +21459,7 @@ x_produce_glyphs (it)
 
          pos = (STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
                 : IT_CHARPOS (*it));
-         /* When no suitable font found, use the default font.  */
+         /* If no suitable font is found, use the default font.  */
          font_not_found_p = font == NULL;
          if (font_not_found_p)
            {
@@ -21633,7 +21494,7 @@ x_produce_glyphs (it)
            }
          else
            {
-             width = FONT_WIDTH (font);
+             width = font->space_width;
              ascent = FONT_BASE (font);
              descent = FONT_DESCENT (font);
              lbearing = 0;
@@ -22719,9 +22580,6 @@ display_and_set_cursor (w, on, hpos, vpos, x, y)
 /* Switch the display of W's cursor on or off, according to the value
    of ON.  */
 
-#ifndef HAVE_NS
-static
-#endif
 void
 update_window_cursor (w, on)
      struct window *w;
@@ -22777,7 +22635,7 @@ x_update_cursor (f, on_p)
 /* EXPORT:
    Clear the cursor of window W to background color, and mark the
    cursor as not shown.  This is used when the text where the cursor
-   is is about to be rewritten.  */
+   is about to be rewritten.  */
 
 void
 x_clear_cursor (w)
@@ -22928,206 +22786,187 @@ cursor_in_mouse_face_p (w)
 
 
 \f
-/* Find the glyph matrix position of buffer position CHARPOS in window
-   *W.  HPOS, *VPOS, *X, and *Y are set to the positions found.  W's
-   current glyphs must be up to date.  If CHARPOS is above window
-   start return (0, 0, 0, 0).  If CHARPOS is after end of W, return end
-   of last line in W.  In the row containing CHARPOS, stop before glyphs
-   having STOP as object.  */
-
-#if 1 /* This is a version of fast_find_position that's more correct
-        in the presence of hscrolling, for example.  I didn't install
-        it right away because the problem fixed is minor, it failed
-        in 20.x as well, and I think it's too risky to install
-        so near the release of 21.1.  2001-09-25 gerd.  */
+/* This function sets the mouse_face_* elements of DPYINFO, assuming
+   the mouse cursor is on a glyph with buffer charpos MOUSE_CHARPOS in
+   window WINDOW.  START_CHARPOS and END_CHARPOS are buffer positions
+   for the overlay or run of text properties specifying the mouse
+   face.  BEFORE_STRING and AFTER_STRING, if non-nil, are a
+   before-string and after-string that must also be highlighted.
+   DISPLAY_STRING, if non-nil, is a display string that may cover some
+   or all of the highlighted text.  */
 
-static
-int
-fast_find_position (w, charpos, hpos, vpos, x, y, stop)
-     struct window *w;
-     EMACS_INT charpos;
-     int *hpos, *vpos, *x, *y;
-     Lisp_Object stop;
+static void
+mouse_face_from_buffer_pos (Lisp_Object window,
+                           Display_Info *dpyinfo,
+                           EMACS_INT mouse_charpos,
+                           EMACS_INT start_charpos,
+                           EMACS_INT end_charpos,
+                           Lisp_Object before_string,
+                           Lisp_Object after_string,
+                           Lisp_Object display_string)
 {
-  struct glyph_row *row, *first;
+  struct window *w = XWINDOW (window);
+  struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  struct glyph_row *row;
   struct glyph *glyph, *end;
-  int past_end = 0;
+  EMACS_INT ignore;
+  int x;
+
+  xassert (NILP (display_string) || STRINGP (display_string));
+  xassert (NILP (before_string) || STRINGP (before_string));
+  xassert (NILP (after_string) || STRINGP (after_string));
 
-  first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-  if (charpos < MATRIX_ROW_START_CHARPOS (first))
+  /* Find the first highlighted glyph.  */
+  if (start_charpos < MATRIX_ROW_START_CHARPOS (first))
     {
-      *x = first->x;
-      *y = first->y;
-      *hpos = 0;
-      *vpos = MATRIX_ROW_VPOS (first, w->current_matrix);
-      return 1;
+      dpyinfo->mouse_face_beg_col = 0;
+      dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (first, w->current_matrix);
+      dpyinfo->mouse_face_beg_x = first->x;
+      dpyinfo->mouse_face_beg_y = first->y;
+    }
+  else
+    {
+      row = row_containing_pos (w, start_charpos, first, NULL, 0);
+      if (row == NULL)
+       row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+
+      /* If the before-string or display-string contains newlines,
+        row_containing_pos skips to its last row.  Move back.  */
+      if (!NILP (before_string) || !NILP (display_string))
+       {
+         struct glyph_row *prev;
+         while ((prev = row - 1, prev >= first)
+                && MATRIX_ROW_END_CHARPOS (prev) == start_charpos
+                && prev->used[TEXT_AREA] > 0)
+           {
+             struct glyph *beg = prev->glyphs[TEXT_AREA];
+             glyph = beg + prev->used[TEXT_AREA];
+             while (--glyph >= beg && INTEGERP (glyph->object));
+             if (glyph < beg
+                 || !(EQ (glyph->object, before_string)
+                      || EQ (glyph->object, display_string)))
+               break;
+             row = prev;
+           }
+       }
+
+      glyph = row->glyphs[TEXT_AREA];
+      end = glyph + row->used[TEXT_AREA];
+      x = row->x;
+      dpyinfo->mouse_face_beg_y = row->y;
+      dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (row, w->current_matrix);
+
+      /* Skip truncation glyphs at the start of the glyph row.  */
+      if (row->displays_text_p)
+       for (; glyph < end
+              && INTEGERP (glyph->object)
+              && glyph->charpos < 0;
+            ++glyph)
+         x += glyph->pixel_width;
+
+      /* Scan the glyph row, stopping before BEFORE_STRING or
+        DISPLAY_STRING or START_CHARPOS.  */
+      for (; glyph < end
+            && !INTEGERP (glyph->object)
+            && !EQ (glyph->object, before_string)
+            && !EQ (glyph->object, display_string)
+            && !(BUFFERP (glyph->object)
+                 && glyph->charpos >= start_charpos);
+          ++glyph)
+       x += glyph->pixel_width;
+
+      dpyinfo->mouse_face_beg_x = x;
+      dpyinfo->mouse_face_beg_col = glyph - row->glyphs[TEXT_AREA];
     }
 
-  row = row_containing_pos (w, charpos, first, NULL, 0);
+  /* Find the last highlighted glyph.  */
+  row = row_containing_pos (w, end_charpos, first, NULL, 0);
   if (row == NULL)
     {
       row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
-      past_end = 1;
+      dpyinfo->mouse_face_past_end = 1;
     }
-
-  /* If whole rows or last part of a row came from a display overlay,
-     row_containing_pos will skip over such rows because their end pos
-     equals the start pos of the overlay or interval.
-
-     Move back if we have a STOP object and previous row's
-     end glyph came from STOP.  */
-  if (!NILP (stop))
+  else if (!NILP (after_string))
     {
-      struct glyph_row *prev;
-      while ((prev = row - 1, prev >= first)
-            && MATRIX_ROW_END_CHARPOS (prev) == charpos
-            && prev->used[TEXT_AREA] > 0)
-       {
-         struct glyph *beg = prev->glyphs[TEXT_AREA];
-         glyph = beg + prev->used[TEXT_AREA];
-         while (--glyph >= beg
-                && INTEGERP (glyph->object));
-         if (glyph < beg
-             || !EQ (stop, glyph->object))
-           break;
-         row = prev;
-       }
-    }
+      /* If the after-string has newlines, advance to its last row.  */
+      struct glyph_row *next;
+      struct glyph_row *last
+       = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
 
-  *x = row->x;
-  *y = row->y;
-  *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
+      for (next = row + 1;
+          next <= last
+            && next->used[TEXT_AREA] > 0
+            && EQ (next->glyphs[TEXT_AREA]->object, after_string);
+          ++next)
+       row = next;
+    }
 
   glyph = row->glyphs[TEXT_AREA];
   end = glyph + row->used[TEXT_AREA];
+  x = row->x;
+  dpyinfo->mouse_face_end_y = row->y;
+  dpyinfo->mouse_face_end_row = MATRIX_ROW_VPOS (row, w->current_matrix);
 
-  /* Skip over glyphs not having an object at the start of the row.
-     These are special glyphs like truncation marks on terminal
-     frames.  */
+  /* Skip truncation glyphs at the start of the row.  */
   if (row->displays_text_p)
-    while (glyph < end
+    for (; glyph < end
           && INTEGERP (glyph->object)
-          && !EQ (stop, glyph->object)
-          && glyph->charpos < 0)
-      {
-       *x += glyph->pixel_width;
-       ++glyph;
-      }
+          && glyph->charpos < 0;
+        ++glyph)
+      x += glyph->pixel_width;
 
-  while (glyph < end
+  /* Scan the glyph row, stopping at END_CHARPOS or when we encounter
+     AFTER_STRING.  */
+  for (; glyph < end
         && !INTEGERP (glyph->object)
-        && !EQ (stop, glyph->object)
-        && (!BUFFERP (glyph->object)
-            || glyph->charpos < charpos))
-    {
-      *x += glyph->pixel_width;
-      ++glyph;
-    }
-
-  *hpos = glyph - row->glyphs[TEXT_AREA];
-  return !past_end;
-}
-
-#else /* not 1 */
-
-static int
-fast_find_position (w, pos, hpos, vpos, x, y, stop)
-     struct window *w;
-     EMACS_INT pos;
-     int *hpos, *vpos, *x, *y;
-     Lisp_Object stop;
-{
-  int i;
-  int lastcol;
-  int maybe_next_line_p = 0;
-  int line_start_position;
-  int yb = window_text_bottom_y (w);
-  struct glyph_row *row, *best_row;
-  int row_vpos, best_row_vpos;
-  int current_x;
-
-  row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-  row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
+        && !EQ (glyph->object, after_string)
+        && !(BUFFERP (glyph->object) && glyph->charpos >= end_charpos);
+       ++glyph)
+    x += glyph->pixel_width;
 
-  while (row->y < yb)
+  /* If we found AFTER_STRING, consume it and stop.  */
+  if (EQ (glyph->object, after_string))
     {
-      if (row->used[TEXT_AREA])
-       line_start_position = row->glyphs[TEXT_AREA]->charpos;
-      else
-       line_start_position = 0;
-
-      if (line_start_position > pos)
-       break;
-      /* If the position sought is the end of the buffer,
-        don't include the blank lines at the bottom of the window.  */
-      else if (line_start_position == pos
-              && pos == BUF_ZV (XBUFFER (w->buffer)))
-       {
-         maybe_next_line_p = 1;
-         break;
-       }
-      else if (line_start_position > 0)
-       {
-         best_row = row;
-         best_row_vpos = row_vpos;
-       }
-
-      if (row->y + row->height >= yb)
-       break;
-
-      ++row;
-      ++row_vpos;
+      for (; EQ (glyph->object, after_string) && glyph < end; ++glyph)
+       x += glyph->pixel_width;
     }
-
-  /* Find the right column within BEST_ROW.  */
-  lastcol = 0;
-  current_x = best_row->x;
-  for (i = 0; i < best_row->used[TEXT_AREA]; i++)
+  else
     {
-      struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
-      int charpos = glyph->charpos;
+      /* If there's no after-string, we must check if we overshot,
+        which might be the case if we stopped after a string glyph.
+        That glyph may belong to a before-string or display-string
+        associated with the end position, which must not be
+        highlighted.  */
+      Lisp_Object prev_object;
+      int pos;
 
-      if (BUFFERP (glyph->object))
+      while (glyph > row->glyphs[TEXT_AREA])
        {
-         if (charpos == pos)
-           {
-             *hpos = i;
-             *vpos = best_row_vpos;
-             *x = current_x;
-             *y = best_row->y;
-             return 1;
-           }
-         else if (charpos > pos)
+         prev_object = (glyph - 1)->object;
+         if (!STRINGP (prev_object) || EQ (prev_object, display_string))
            break;
-       }
-      else if (EQ (glyph->object, stop))
-       break;
 
-      if (charpos > 0)
-       lastcol = i;
-      current_x += glyph->pixel_width;
-    }
+         pos = string_buffer_position (w, prev_object, end_charpos);
+         if (pos && pos < end_charpos)
+           break;
 
-  /* If we're looking for the end of the buffer,
-     and we didn't find it in the line we scanned,
-     use the start of the following line.  */
-  if (maybe_next_line_p)
-    {
-      ++best_row;
-      ++best_row_vpos;
-      lastcol = 0;
-      current_x = best_row->x;
+         for (; glyph > row->glyphs[TEXT_AREA]
+                && EQ ((glyph - 1)->object, prev_object);
+              --glyph)
+           x -= (glyph - 1)->pixel_width;
+       }
     }
 
-  *vpos = best_row_vpos;
-  *hpos = lastcol + 1;
-  *x = current_x;
-  *y = best_row->y;
-  return 0;
+  dpyinfo->mouse_face_end_x = x;
+  dpyinfo->mouse_face_end_col = glyph - row->glyphs[TEXT_AREA];
+  dpyinfo->mouse_face_window = window;
+  dpyinfo->mouse_face_face_id
+    = face_at_buffer_position (w, mouse_charpos, 0, 0, &ignore,
+                              mouse_charpos + 1,
+                              !dpyinfo->mouse_face_hidden, -1);
+  show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
 }
 
-#endif /* not 1 */
-
 
 /* Find the position of the glyph for position POS in OBJECT in
    window W's current matrix, and return in *X, *Y the pixel
@@ -23266,7 +23105,7 @@ on_hot_spot_p (hot_spot, x, y)
        {
          struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
          Lisp_Object *poly = v->contents;
-         int n = v->size;
+         int n = v->header.size;
          int i;
          int inside = 0;
          Lisp_Object lx, ly;
@@ -23645,7 +23484,7 @@ note_mouse_highlight (f, x, y)
      int x, y;
 {
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  enum window_part part;
+  enum window_part part = ON_NOTHING;
   Lisp_Object window;
   struct window *w;
   Cursor cursor = No_Cursor;
@@ -23659,7 +23498,8 @@ note_mouse_highlight (f, x, y)
 #endif
 
   if (NILP (Vmouse_highlight)
-      || !f->glyphs_initialized_p)
+      || !f->glyphs_initialized_p
+      || f->pointer_invisible)
     return;
 
   dpyinfo->mouse_face_mouse_x = x;
@@ -23678,11 +23518,14 @@ note_mouse_highlight (f, x, y)
   /* Which window is that in?  */
   window = window_from_coordinates (f, x, y, &part, 0, 0, 1);
 
-  /* If we were displaying active text in another window, clear that.
-     Also clear if we move out of text area in same window.  */
+  /* If displaying active text in another window, clear that.  */
   if (! EQ (window, dpyinfo->mouse_face_window)
-      || (part != ON_TEXT && part != ON_MODE_LINE && part != ON_HEADER_LINE
-         && !NILP (dpyinfo->mouse_face_window)))
+      /* Also clear if we move out of text area in same window.  */
+      || (!NILP (dpyinfo->mouse_face_window)
+         && !NILP (window)
+         && part != ON_TEXT
+         && part != ON_MODE_LINE
+         && part != ON_HEADER_LINE))
     clear_mouse_face (dpyinfo);
 
   /* Not on a window -> return.  */
@@ -23854,8 +23697,7 @@ note_mouse_highlight (f, x, y)
          || (OVERLAYP (dpyinfo->mouse_face_overlay)
              && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
        {
-         /* Find the highest priority overlay that has a mouse-face
-            property.  */
+         /* Find the highest priority overlay with a mouse-face.  */
          overlay = Qnil;
          for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
            {
@@ -23864,12 +23706,10 @@ note_mouse_highlight (f, x, y)
                overlay = overlay_vec[i];
            }
 
-         /* If we're actually highlighting the same overlay as
-            before, there's no need to do that again.  */
-         if (!NILP (overlay)
-             && EQ (overlay, dpyinfo->mouse_face_overlay))
+         /* If we're highlighting the same overlay as before, there's
+            no need to do that again.  */
+         if (!NILP (overlay) && EQ (overlay, dpyinfo->mouse_face_overlay))
            goto check_help_echo;
-
          dpyinfo->mouse_face_overlay = overlay;
 
          /* Clear the display of the old active region, if any.  */
@@ -23880,95 +23720,19 @@ note_mouse_highlight (f, x, y)
          if (NILP (overlay))
            mouse_face = Fget_text_property (position, Qmouse_face, object);
 
-         /* Handle the overlay case.  */
-         if (!NILP (overlay))
-           {
-             /* Find the range of text around this char that
-                should be active.  */
-             Lisp_Object before, after;
-             EMACS_INT ignore;
-
-             before = Foverlay_start (overlay);
-             after = Foverlay_end (overlay);
-             /* Record this as the current active region.  */
-             fast_find_position (w, XFASTINT (before),
-                                 &dpyinfo->mouse_face_beg_col,
-                                 &dpyinfo->mouse_face_beg_row,
-                                 &dpyinfo->mouse_face_beg_x,
-                                 &dpyinfo->mouse_face_beg_y, Qnil);
-
-             dpyinfo->mouse_face_past_end
-               = !fast_find_position (w, XFASTINT (after),
-                                      &dpyinfo->mouse_face_end_col,
-                                      &dpyinfo->mouse_face_end_row,
-                                      &dpyinfo->mouse_face_end_x,
-                                      &dpyinfo->mouse_face_end_y, Qnil);
-             dpyinfo->mouse_face_window = window;
-
-             dpyinfo->mouse_face_face_id
-               = face_at_buffer_position (w, pos, 0, 0,
-                                          &ignore, pos + 1,
-                                          !dpyinfo->mouse_face_hidden,
-                                          -1);
-
-             /* Display it as active.  */
-             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
-             cursor = No_Cursor;
-           }
-         /* Handle the text property case.  */
-         else if (!NILP (mouse_face) && BUFFERP (object))
-           {
-             /* Find the range of text around this char that
-                should be active.  */
-             Lisp_Object before, after, beginning, end;
-             EMACS_INT ignore;
-
-             beginning = Fmarker_position (w->start);
-             end = make_number (BUF_Z (XBUFFER (object))
-                                - XFASTINT (w->window_end_pos));
-             before
-               = Fprevious_single_property_change (make_number (pos + 1),
-                                                   Qmouse_face,
-                                                   object, beginning);
-             after
-               = Fnext_single_property_change (position, Qmouse_face,
-                                               object, end);
-
-             /* Record this as the current active region.  */
-             fast_find_position (w, XFASTINT (before),
-                                 &dpyinfo->mouse_face_beg_col,
-                                 &dpyinfo->mouse_face_beg_row,
-                                 &dpyinfo->mouse_face_beg_x,
-                                 &dpyinfo->mouse_face_beg_y, Qnil);
-             dpyinfo->mouse_face_past_end
-               = !fast_find_position (w, XFASTINT (after),
-                                      &dpyinfo->mouse_face_end_col,
-                                      &dpyinfo->mouse_face_end_row,
-                                      &dpyinfo->mouse_face_end_x,
-                                      &dpyinfo->mouse_face_end_y, Qnil);
-             dpyinfo->mouse_face_window = window;
-
-             if (BUFFERP (object))
-               dpyinfo->mouse_face_face_id
-                 = face_at_buffer_position (w, pos, 0, 0,
-                                            &ignore, pos + 1,
-                                            !dpyinfo->mouse_face_hidden,
-                                            -1);
-
-             /* Display it as active.  */
-             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
-             cursor = No_Cursor;
-           }
-         else if (!NILP (mouse_face) && STRINGP (object))
+         /* Next, compute the bounds of the mouse highlighting and
+            display it.  */
+         if (!NILP (mouse_face) && STRINGP (object))
            {
+             /* The mouse-highlighting comes from a display string
+                with a mouse-face.  */
              Lisp_Object b, e;
              EMACS_INT ignore;
 
-             b = Fprevious_single_property_change (make_number (pos + 1),
-                                                   Qmouse_face,
-                                                   object, Qnil);
-             e = Fnext_single_property_change (position, Qmouse_face,
-                                               object, Qnil);
+             b = Fprevious_single_property_change
+               (make_number (pos + 1), Qmouse_face, object, Qnil);
+             e = Fnext_single_property_change
+               (position, Qmouse_face, object, Qnil);
              if (NILP (b))
                b = make_number (0);
              if (NILP (e))
@@ -23992,53 +23756,67 @@ note_mouse_highlight (f, x, y)
              show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
              cursor = No_Cursor;
            }
-         else if (STRINGP (object) && NILP (mouse_face))
+         else
            {
-             /* A string which doesn't have mouse-face, but
-                the text ``under'' it might have.  */
-             struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
-             int start = MATRIX_ROW_START_CHARPOS (r);
-
-             pos = string_buffer_position (w, object, start);
-             if (pos > 0)
-               mouse_face = get_char_property_and_overlay (make_number (pos),
-                                                           Qmouse_face,
-                                                           w->buffer,
-                                                           &overlay);
-             if (!NILP (mouse_face) && !NILP (overlay))
+             /* The mouse-highlighting, if any, comes from an overlay
+                or text property in the buffer.  */
+             Lisp_Object buffer, display_string;
+
+             if (STRINGP (object))
                {
-                 Lisp_Object before = Foverlay_start (overlay);
-                 Lisp_Object after = Foverlay_end (overlay);
-                 EMACS_INT ignore;
+                 /* If we are on a display string with no mouse-face,
+                    check if the text under it has one.  */
+                 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
+                 int start = MATRIX_ROW_START_CHARPOS (r);
+                 pos = string_buffer_position (w, object, start);
+                 if (pos > 0)
+                   {
+                     mouse_face = get_char_property_and_overlay
+                       (make_number (pos), Qmouse_face, w->buffer, &overlay);
+                     buffer = w->buffer;
+                     display_string = object;
+                   }
+               }
+             else
+               {
+                 buffer = object;
+                 display_string = Qnil;
+               }
 
-                 /* Note that we might not be able to find position
-                    BEFORE in the glyph matrix if the overlay is
-                    entirely covered by a `display' property.  In
-                    this case, we overshoot.  So let's stop in
-                    the glyph matrix before glyphs for OBJECT.  */
-                 fast_find_position (w, XFASTINT (before),
-                                     &dpyinfo->mouse_face_beg_col,
-                                     &dpyinfo->mouse_face_beg_row,
-                                     &dpyinfo->mouse_face_beg_x,
-                                     &dpyinfo->mouse_face_beg_y,
-                                     object);
-
-                 dpyinfo->mouse_face_past_end
-                   = !fast_find_position (w, XFASTINT (after),
-                                          &dpyinfo->mouse_face_end_col,
-                                          &dpyinfo->mouse_face_end_row,
-                                          &dpyinfo->mouse_face_end_x,
-                                          &dpyinfo->mouse_face_end_y,
-                                          Qnil);
-                 dpyinfo->mouse_face_window = window;
-                 dpyinfo->mouse_face_face_id
-                   = face_at_buffer_position (w, pos, 0, 0,
-                                              &ignore, pos + 1,
-                                              !dpyinfo->mouse_face_hidden,
-                                              -1);
-
-                 /* Display it as active.  */
-                 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+             if (!NILP (mouse_face))
+               {
+                 Lisp_Object before, after;
+                 Lisp_Object before_string, after_string;
+
+                 if (NILP (overlay))
+                   {
+                     /* Handle the text property case.  */
+                     before = Fprevious_single_property_change
+                       (make_number (pos + 1), Qmouse_face, buffer,
+                        Fmarker_position (w->start));
+                     after = Fnext_single_property_change
+                       (make_number (pos), Qmouse_face, buffer,
+                        make_number (BUF_Z (XBUFFER (buffer))
+                                     - XFASTINT (w->window_end_pos)));
+                     before_string = after_string = Qnil;
+                   }
+                 else
+                   {
+                     /* Handle the overlay case.  */
+                     before = Foverlay_start (overlay);
+                     after = Foverlay_end (overlay);
+                     before_string = Foverlay_get (overlay, Qbefore_string);
+                     after_string = Foverlay_get (overlay, Qafter_string);
+
+                     if (!STRINGP (before_string)) before_string = Qnil;
+                     if (!STRINGP (after_string))  after_string = Qnil;
+                   }
+
+                 mouse_face_from_buffer_pos (window, dpyinfo, pos,
+                                             XFASTINT (before),
+                                             XFASTINT (after),
+                                             before_string, after_string,
+                                             display_string);
                  cursor = No_Cursor;
                }
            }
@@ -24474,7 +24252,7 @@ expose_window (w, fr)
     {
       int yb = window_text_bottom_y (w);
       struct glyph_row *row;
-      int cursor_cleared_p;
+      int cursor_cleared_p, phys_cursor_on_p;
       struct glyph_row *first_overlapping_row, *last_overlapping_row;
 
       TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
@@ -24494,6 +24272,13 @@ expose_window (w, fr)
       else
        cursor_cleared_p = 0;
 
+      /* If the row containing the cursor extends face to end of line,
+        then expose_area might overwrite the cursor outside the
+        rectangle and thus notice_overwritten_cursor might clear
+        w->phys_cursor_on_p.  We remember the original value and
+        check later if it is changed.  */
+      phys_cursor_on_p = w->phys_cursor_on_p;
+
       /* Update lines intersecting rectangle R.  */
       first_overlapping_row = last_overlapping_row = NULL;
       for (row = w->current_matrix->rows;
@@ -24560,7 +24345,8 @@ expose_window (w, fr)
          x_draw_vertical_border (w);
 
          /* Turn the cursor on again.  */
-         if (cursor_cleared_p)
+         if (cursor_cleared_p
+             || (phys_cursor_on_p && !w->phys_cursor_on_p))
            update_window_cursor (w, 1);
        }
     }
@@ -24761,7 +24547,7 @@ syms_of_xdisp ()
   Vmessage_stack = Qnil;
   staticpro (&Vmessage_stack);
 
-  Qinhibit_redisplay = intern ("inhibit-redisplay");
+  Qinhibit_redisplay = intern_c_string ("inhibit-redisplay");
   staticpro (&Qinhibit_redisplay);
 
   message_dolog_marker1 = Fmake_marker ();
@@ -24787,133 +24573,133 @@ syms_of_xdisp ()
   defsubr (&Sinvisible_p);
 
   staticpro (&Qmenu_bar_update_hook);
-  Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
+  Qmenu_bar_update_hook = intern_c_string ("menu-bar-update-hook");
 
   staticpro (&Qoverriding_terminal_local_map);
-  Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
+  Qoverriding_terminal_local_map = intern_c_string ("overriding-terminal-local-map");
 
   staticpro (&Qoverriding_local_map);
-  Qoverriding_local_map = intern ("overriding-local-map");
+  Qoverriding_local_map = intern_c_string ("overriding-local-map");
 
   staticpro (&Qwindow_scroll_functions);
-  Qwindow_scroll_functions = intern ("window-scroll-functions");
+  Qwindow_scroll_functions = intern_c_string ("window-scroll-functions");
 
   staticpro (&Qwindow_text_change_functions);
-  Qwindow_text_change_functions = intern ("window-text-change-functions");
+  Qwindow_text_change_functions = intern_c_string ("window-text-change-functions");
 
   staticpro (&Qredisplay_end_trigger_functions);
-  Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
+  Qredisplay_end_trigger_functions = intern_c_string ("redisplay-end-trigger-functions");
 
   staticpro (&Qinhibit_point_motion_hooks);
-  Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
+  Qinhibit_point_motion_hooks = intern_c_string ("inhibit-point-motion-hooks");
 
-  Qeval = intern ("eval");
+  Qeval = intern_c_string ("eval");
   staticpro (&Qeval);
 
-  QCdata = intern (":data");
+  QCdata = intern_c_string (":data");
   staticpro (&QCdata);
-  Qdisplay = intern ("display");
+  Qdisplay = intern_c_string ("display");
   staticpro (&Qdisplay);
-  Qspace_width = intern ("space-width");
+  Qspace_width = intern_c_string ("space-width");
   staticpro (&Qspace_width);
-  Qraise = intern ("raise");
+  Qraise = intern_c_string ("raise");
   staticpro (&Qraise);
-  Qslice = intern ("slice");
+  Qslice = intern_c_string ("slice");
   staticpro (&Qslice);
-  Qspace = intern ("space");
+  Qspace = intern_c_string ("space");
   staticpro (&Qspace);
-  Qmargin = intern ("margin");
+  Qmargin = intern_c_string ("margin");
   staticpro (&Qmargin);
-  Qpointer = intern ("pointer");
+  Qpointer = intern_c_string ("pointer");
   staticpro (&Qpointer);
-  Qleft_margin = intern ("left-margin");
+  Qleft_margin = intern_c_string ("left-margin");
   staticpro (&Qleft_margin);
-  Qright_margin = intern ("right-margin");
+  Qright_margin = intern_c_string ("right-margin");
   staticpro (&Qright_margin);
-  Qcenter = intern ("center");
+  Qcenter = intern_c_string ("center");
   staticpro (&Qcenter);
-  Qline_height = intern ("line-height");
+  Qline_height = intern_c_string ("line-height");
   staticpro (&Qline_height);
-  QCalign_to = intern (":align-to");
+  QCalign_to = intern_c_string (":align-to");
   staticpro (&QCalign_to);
-  QCrelative_width = intern (":relative-width");
+  QCrelative_width = intern_c_string (":relative-width");
   staticpro (&QCrelative_width);
-  QCrelative_height = intern (":relative-height");
+  QCrelative_height = intern_c_string (":relative-height");
   staticpro (&QCrelative_height);
-  QCeval = intern (":eval");
+  QCeval = intern_c_string (":eval");
   staticpro (&QCeval);
-  QCpropertize = intern (":propertize");
+  QCpropertize = intern_c_string (":propertize");
   staticpro (&QCpropertize);
-  QCfile = intern (":file");
+  QCfile = intern_c_string (":file");
   staticpro (&QCfile);
-  Qfontified = intern ("fontified");
+  Qfontified = intern_c_string ("fontified");
   staticpro (&Qfontified);
-  Qfontification_functions = intern ("fontification-functions");
+  Qfontification_functions = intern_c_string ("fontification-functions");
   staticpro (&Qfontification_functions);
-  Qtrailing_whitespace = intern ("trailing-whitespace");
+  Qtrailing_whitespace = intern_c_string ("trailing-whitespace");
   staticpro (&Qtrailing_whitespace);
-  Qescape_glyph = intern ("escape-glyph");
+  Qescape_glyph = intern_c_string ("escape-glyph");
   staticpro (&Qescape_glyph);
-  Qnobreak_space = intern ("nobreak-space");
+  Qnobreak_space = intern_c_string ("nobreak-space");
   staticpro (&Qnobreak_space);
-  Qimage = intern ("image");
+  Qimage = intern_c_string ("image");
   staticpro (&Qimage);
-  QCmap = intern (":map");
+  QCmap = intern_c_string (":map");
   staticpro (&QCmap);
-  QCpointer = intern (":pointer");
+  QCpointer = intern_c_string (":pointer");
   staticpro (&QCpointer);
-  Qrect = intern ("rect");
+  Qrect = intern_c_string ("rect");
   staticpro (&Qrect);
-  Qcircle = intern ("circle");
+  Qcircle = intern_c_string ("circle");
   staticpro (&Qcircle);
-  Qpoly = intern ("poly");
+  Qpoly = intern_c_string ("poly");
   staticpro (&Qpoly);
-  Qmessage_truncate_lines = intern ("message-truncate-lines");
+  Qmessage_truncate_lines = intern_c_string ("message-truncate-lines");
   staticpro (&Qmessage_truncate_lines);
-  Qgrow_only = intern ("grow-only");
+  Qgrow_only = intern_c_string ("grow-only");
   staticpro (&Qgrow_only);
-  Qinhibit_menubar_update = intern ("inhibit-menubar-update");
+  Qinhibit_menubar_update = intern_c_string ("inhibit-menubar-update");
   staticpro (&Qinhibit_menubar_update);
-  Qinhibit_eval_during_redisplay = intern ("inhibit-eval-during-redisplay");
+  Qinhibit_eval_during_redisplay = intern_c_string ("inhibit-eval-during-redisplay");
   staticpro (&Qinhibit_eval_during_redisplay);
-  Qposition = intern ("position");
+  Qposition = intern_c_string ("position");
   staticpro (&Qposition);
-  Qbuffer_position = intern ("buffer-position");
+  Qbuffer_position = intern_c_string ("buffer-position");
   staticpro (&Qbuffer_position);
-  Qobject = intern ("object");
+  Qobject = intern_c_string ("object");
   staticpro (&Qobject);
-  Qbar = intern ("bar");
+  Qbar = intern_c_string ("bar");
   staticpro (&Qbar);
-  Qhbar = intern ("hbar");
+  Qhbar = intern_c_string ("hbar");
   staticpro (&Qhbar);
-  Qbox = intern ("box");
+  Qbox = intern_c_string ("box");
   staticpro (&Qbox);
-  Qhollow = intern ("hollow");
+  Qhollow = intern_c_string ("hollow");
   staticpro (&Qhollow);
-  Qhand = intern ("hand");
+  Qhand = intern_c_string ("hand");
   staticpro (&Qhand);
-  Qarrow = intern ("arrow");
+  Qarrow = intern_c_string ("arrow");
   staticpro (&Qarrow);
-  Qtext = intern ("text");
+  Qtext = intern_c_string ("text");
   staticpro (&Qtext);
-  Qrisky_local_variable = intern ("risky-local-variable");
+  Qrisky_local_variable = intern_c_string ("risky-local-variable");
   staticpro (&Qrisky_local_variable);
-  Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces");
+  Qinhibit_free_realized_faces = intern_c_string ("inhibit-free-realized-faces");
   staticpro (&Qinhibit_free_realized_faces);
 
-  list_of_error = Fcons (Fcons (intern ("error"),
-                               Fcons (intern ("void-variable"), Qnil)),
+  list_of_error = Fcons (Fcons (intern_c_string ("error"),
+                               Fcons (intern_c_string ("void-variable"), Qnil)),
                         Qnil);
   staticpro (&list_of_error);
 
-  Qlast_arrow_position = intern ("last-arrow-position");
+  Qlast_arrow_position = intern_c_string ("last-arrow-position");
   staticpro (&Qlast_arrow_position);
-  Qlast_arrow_string = intern ("last-arrow-string");
+  Qlast_arrow_string = intern_c_string ("last-arrow-string");
   staticpro (&Qlast_arrow_string);
 
-  Qoverlay_arrow_string = intern ("overlay-arrow-string");
+  Qoverlay_arrow_string = intern_c_string ("overlay-arrow-string");
   staticpro (&Qoverlay_arrow_string);
-  Qoverlay_arrow_bitmap = intern ("overlay-arrow-bitmap");
+  Qoverlay_arrow_bitmap = intern_c_string ("overlay-arrow-bitmap");
   staticpro (&Qoverlay_arrow_bitmap);
 
   echo_buffer[0] = echo_buffer[1] = Qnil;
@@ -24924,7 +24710,7 @@ syms_of_xdisp ()
   staticpro (&echo_area_buffer[0]);
   staticpro (&echo_area_buffer[1]);
 
-  Vmessages_buffer_name = build_string ("*Messages*");
+  Vmessages_buffer_name = make_pure_c_string ("*Messages*");
   staticpro (&Vmessages_buffer_name);
 
   mode_line_proptrans_alist = Qnil;
@@ -24994,14 +24780,14 @@ See also `overlay-arrow-string'.  */);
   DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
     doc: /* String to display as an arrow in non-window frames.
 See also `overlay-arrow-position'.  */);
-  Voverlay_arrow_string = build_string ("=>");
+  Voverlay_arrow_string = make_pure_c_string ("=>");
 
   DEFVAR_LISP ("overlay-arrow-variable-list", &Voverlay_arrow_variable_list,
     doc: /* List of variables (symbols) which hold markers for overlay arrows.
 The symbols on this list are examined during redisplay to determine
 where to display overlay arrows.  */);
   Voverlay_arrow_variable_list
-    = Fcons (intern ("overlay-arrow-position"), Qnil);
+    = Fcons (intern_c_string ("overlay-arrow-position"), Qnil);
 
   DEFVAR_INT ("scroll-step", &scroll_step,
     doc: /* *The number of lines to try scrolling a window by when point moves out.
@@ -25037,13 +24823,13 @@ Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI).  */);
 
   DEFVAR_LISP ("truncate-partial-width-windows",
               &Vtruncate_partial_width_windows,
-    doc: /* Non-nil means truncate lines in windows with less than the frame width.
-For an integer value, truncate lines in each window with less than the
+    doc: /* Non-nil means truncate lines in windows narrower than the frame.
+For an integer value, truncate lines in each window narrower than the
 full frame width, provided the window width is less than that integer;
 otherwise, respect the value of `truncate-lines'.
 
-For any other non-nil value, truncate lines in all windows with
-less than the full frame width.
+For any other non-nil value, truncate lines in all windows that do
+not span the full frame width.
 
 A value of nil means to respect the value of `truncate-lines'.
 
@@ -25095,14 +24881,14 @@ and is used only on frames for which no explicit name has been set
 \(see `modify-frame-parameters').  */);
   Vicon_title_format
     = Vframe_title_format
-    = Fcons (intern ("multiple-frames"),
-            Fcons (build_string ("%b"),
-                   Fcons (Fcons (empty_unibyte_string,
-                                 Fcons (intern ("invocation-name"),
-                                        Fcons (build_string ("@"),
-                                               Fcons (intern ("system-name"),
-                                                              Qnil)))),
-                          Qnil)));
+    = pure_cons (intern_c_string ("multiple-frames"),
+                pure_cons (make_pure_c_string ("%b"),
+                           pure_cons (pure_cons (empty_unibyte_string,
+                                                 pure_cons (intern_c_string ("invocation-name"),
+                                                            pure_cons (make_pure_c_string ("@"),
+                                                                       pure_cons (intern_c_string ("system-name"),
+                                                                                  Qnil)))),
+                                      Qnil)));
 
   DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
     doc: /* Maximum number of lines to keep in the message log buffer.
@@ -25204,10 +24990,13 @@ fontified regions the property `fontified'.  */);
   DEFVAR_BOOL ("unibyte-display-via-language-environment",
                &unibyte_display_via_language_environment,
     doc: /* *Non-nil means display unibyte text according to language environment.
-Specifically this means that unibyte non-ASCII characters
+Specifically, this means that raw bytes in the range 160-255 decimal
 are displayed by converting them to the equivalent multibyte characters
 according to the current language environment.  As a result, they are
-displayed according to the current fontset.  */);
+displayed according to the current fontset.
+
+Note that this variable affects only how these bytes are displayed,
+but does not change the fact they are interpreted as raw bytes.  */);
   unibyte_display_via_language_environment = 0;
 
   DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height,
@@ -25240,7 +25029,7 @@ the frame's other specifications determine how to blink the cursor off.  */);
   DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p,
     doc: /* *Non-nil means scroll the display automatically to make point visible.  */);
   automatic_hscrolling_p = 1;
-  Qauto_hscroll_mode = intern ("auto-hscroll-mode");
+  Qauto_hscroll_mode = intern_c_string ("auto-hscroll-mode");
   staticpro (&Qauto_hscroll_mode);
 
   DEFVAR_INT ("hscroll-margin", &hscroll_margin,
@@ -25298,7 +25087,7 @@ property.
 To add a prefix to non-continuation lines, use `line-prefix'.  */);
   Vwrap_prefix = Qnil;
   staticpro (&Qwrap_prefix);
-  Qwrap_prefix = intern ("wrap-prefix");
+  Qwrap_prefix = intern_c_string ("wrap-prefix");
   Fmake_variable_buffer_local (Qwrap_prefix);
 
   DEFVAR_LISP ("line-prefix", &Vline_prefix,
@@ -25312,7 +25101,7 @@ property.
 To add a prefix to continuation lines, use `wrap-prefix'.  */);
   Vline_prefix = Qnil;
   staticpro (&Qline_prefix);
-  Qline_prefix = intern ("line-prefix");
+  Qline_prefix = intern_c_string ("line-prefix");
   Fmake_variable_buffer_local (Qline_prefix);
 
   DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay,
@@ -25380,6 +25169,7 @@ init_xdisp ()
 
   mini_w = XWINDOW (minibuf_window);
   root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
+  echo_area_window = minibuf_window;
 
   if (!noninteractive)
     {