Fix typos in comments.
[bpt/emacs.git] / src / xdisp.c
index d0b557c..07a2127 100644 (file)
@@ -1,7 +1,7 @@
 /* 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 Free Software Foundation, Inc.
+                 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -188,6 +188,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "coding.h"
 #include "process.h"
 #include "region-cache.h"
+#include "font.h"
 #include "fontset.h"
 #include "blockinput.h"
 
@@ -234,6 +235,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;
@@ -353,6 +355,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
@@ -767,7 +771,6 @@ static enum prop_handled handle_display_prop P_ ((struct it *));
 static enum prop_handled handle_composition_prop P_ ((struct it *));
 static enum prop_handled handle_overlay_change P_ ((struct it *));
 static enum prop_handled handle_fontified_prop P_ ((struct it *));
-static enum prop_handled handle_auto_composed_prop P_ ((struct it *));
 
 /* Properties handled by iterators.  */
 
@@ -779,7 +782,6 @@ static struct props it_props[] =
   {&Qface,             FACE_PROP_IDX,          handle_face_prop},
   {&Qdisplay,          DISPLAY_PROP_IDX,       handle_display_prop},
   {&Qinvisible,                INVISIBLE_PROP_IDX,     handle_invisible_prop},
-  {&Qauto_composed,    AUTO_COMPOSED_PROP_IDX, handle_auto_composed_prop},
   {&Qcomposition,      COMPOSITION_PROP_IDX,   handle_composition_prop},
   {NULL,               0,                      NULL}
 };
@@ -1324,7 +1326,7 @@ pos_visible_p (w, charpos, x, y, rtop, rbot, rowh, vpos)
   int visible_p = 0;
   struct buffer *old_buffer = NULL;
 
-  if (noninteractive)
+  if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
     return visible_p;
 
   if (XBUFFER (w->buffer) != current_buffer)
@@ -1350,21 +1352,27 @@ pos_visible_p (w, charpos, x, y, rtop, rbot, rowh, vpos)
   move_it_to (&it, charpos, -1, it.last_visible_y-1, -1,
              (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
 
-  /* Note that we may overshoot because of invisible text.  */
   if (charpos >= 0 && IT_CHARPOS (it) >= charpos)
     {
+      /* We have reached CHARPOS, or passed it.  How the call to
+        move_it_to can overshoot: (i) If CHARPOS is on invisible
+        text, move_it_to stops at the end of the invisible text,
+        after CHARPOS.  (ii) If CHARPOS is in a display vector,
+        move_it_to stops on its last glyph.  */
       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.  */
       int bottom_y = (last_height = 0, line_bottom_y (&it));
       int window_top_y = WINDOW_HEADER_LINE_HEIGHT (w);
 
       if (top_y < window_top_y)
        visible_p = bottom_y > window_top_y;
       else if (top_y < it.last_visible_y)
-         visible_p = 1;
+       visible_p = 1;
       if (visible_p)
        {
-         if (it.method == GET_FROM_BUFFER)
+         if (it_method == GET_FROM_BUFFER)
            {
              Lisp_Object window, prop;
 
@@ -1382,12 +1390,37 @@ pos_visible_p (w, charpos, x, y, rtop, rbot, rowh, vpos)
                  struct glyph *end = glyph + row->used[TEXT_AREA];
                  int x = row->x;
 
-                 for (; glyph < end && glyph->charpos < charpos; glyph++)
+                 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)
+           {
+             /* We stopped on the last glyph of a display vector.
+                Try and recompute.  Hack alert!  */
+             if (charpos < 2 || top.charpos >= charpos)
+               top_x = it.glyph_row->x;
+             else
+               {
+                 struct it it2;
+                 start_display (&it2, w, top);
+                 move_it_to (&it2, charpos - 1, -1, -1, -1, MOVE_TO_POS);
+                 get_next_display_element (&it2);
+                 PRODUCE_GLYPHS (&it2);
+                 if (ITERATOR_AT_END_OF_LINE_P (&it2)
+                     || it2.current_x > it2.last_visible_x)
+                   top_x = it.glyph_row->x;
+                 else
+                   {
+                     top_x = it2.current_x;
+                     top_y = it2.current_y;
+                   }
+               }
+           }
 
          *x = top_x;
          *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
@@ -1602,7 +1635,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
@@ -2574,6 +2607,8 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
   it->w = w;
   it->f = XFRAME (w->frame);
 
+  it->cmp_it.id = -1;
+
   /* Extra space between lines (on window systems only).  */
   if (base_face_id == DEFAULT_FACE_ID
       && FRAME_WINDOW_P (it->f))
@@ -2862,16 +2897,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 */
 }
 
 
@@ -2998,25 +3023,6 @@ init_from_display_pos (it, w, pos)
       it->method = GET_FROM_STRING;
     }
 
-#if 0 /* This is bogus because POS not having an overlay string
-        position does not mean it's after the string.  Example: A
-        line starting with a before-string and initialization of IT
-        to the previous row's end position.  */
-  else if (it->current.overlay_string_index >= 0)
-    {
-      /* If POS says we're already after an overlay string ending at
-        POS, make sure to pop the iterator because it will be in
-        front of that overlay string.  When POS is ZV, we've thereby
-        also ``processed'' overlay strings at ZV.  */
-      while (it->sp)
-       pop_it (it);
-      xassert (it->current.overlay_string_index == -1);
-      xassert (it->method == GET_FROM_BUFFER);
-      if (CHARPOS (pos->pos) == ZV)
-       it->overlay_strings_at_end_processed_p = 1;
-    }
-#endif /* 0 */
-
   if (CHARPOS (pos->string_pos) >= 0)
     {
       /* Recorded position is not in an overlay string, but in another
@@ -3132,11 +3138,23 @@ handle_stop (it)
                {
                  if (it->ellipsis_p)
                    setup_for_ellipsis (it, 0);
+                 /* When handling a display spec, we might load an
+                    empty string.  In that case, discard it here.  We
+                    used to discard it in handle_single_display_spec,
+                    but that causes get_overlay_strings_1, above, to
+                    ignore overlay strings that we must check.  */
+                 if (STRINGP (it->string) && !SCHARS (it->string))
+                   pop_it (it);
                  return;
                }
-             it->ignore_overlay_strings_at_pos_p = 1;
-             it->string_from_display_prop_p = 0;
-             handle_overlay_change_p = 0;
+             else if (STRINGP (it->string) && !SCHARS (it->string))
+               pop_it (it);
+             else
+               {
+                 it->ignore_overlay_strings_at_pos_p = 1;
+                 it->string_from_display_prop_p = 0;
+                 handle_overlay_change_p = 0;
+               }
              handled = HANDLED_RECOMPUTE_PROPS;
              break;
            }
@@ -3181,6 +3199,7 @@ compute_stop_pos (it)
 {
   register INTERVAL iv, next_iv;
   Lisp_Object object, limit, position;
+  EMACS_INT charpos, bytepos;
 
   /* If nowhere else, stop at the end.  */
   it->stop_charpos = it->end_charpos;
@@ -3191,19 +3210,22 @@ compute_stop_pos (it)
         properties.  */
       object = it->string;
       limit = Qnil;
-      position = make_number (IT_STRING_CHARPOS (*it));
+      charpos = IT_STRING_CHARPOS (*it);
+      bytepos = IT_STRING_BYTEPOS (*it);
     }
   else
     {
-      int charpos;
+      EMACS_INT pos;
 
       /* If next overlay change is in front of the current stop pos
         (which is IT->end_charpos), stop there.  Note: value of
         next_overlay_change is point-max if no overlay change
         follows.  */
-      charpos = next_overlay_change (IT_CHARPOS (*it));
-      if (charpos < it->stop_charpos)
-       it->stop_charpos = charpos;
+      charpos = IT_CHARPOS (*it);
+      bytepos = IT_BYTEPOS (*it);
+      pos = next_overlay_change (charpos);
+      if (pos < it->stop_charpos)
+       it->stop_charpos = pos;
 
       /* If showing the region, we have to stop at the region
         start or end because the face might change there.  */
@@ -3219,12 +3241,11 @@ compute_stop_pos (it)
          property changes.  */
       XSETBUFFER (object, current_buffer);
       limit = make_number (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT);
-      position = make_number (IT_CHARPOS (*it));
-
     }
 
   /* Get the interval containing IT's position.  Value is a null
      interval if there isn't such an interval.  */
+  position = make_number (charpos);
   iv = validate_interval_range (object, &position, &position, 0);
   if (!NULL_INTERVAL_P (iv))
     {
@@ -3268,6 +3289,9 @@ compute_stop_pos (it)
        }
     }
 
+  composition_compute_stop_pos (&it->cmp_it, charpos, bytepos,
+                               it->stop_charpos, it->string);
+
   xassert (STRINGP (it->string)
           || (it->stop_charpos >= BEGV
               && it->stop_charpos >= IT_CHARPOS (*it)));
@@ -3421,7 +3445,7 @@ handle_face_prop (it)
                                   &next_stop,
                                   (IT_CHARPOS (*it)
                                    + TEXT_PROP_DISTANCE_LIMIT),
-                                  0);
+                                  0, it->base_face_id);
 
       /* Is this a start of a run of characters with box face?
         Caveat: this can be called for a freshly initialized
@@ -3512,14 +3536,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
@@ -3600,7 +3616,8 @@ face_before_or_after_it_pos (it, before_p)
        /* For composition, we must check the character after the
            composition.  */
        pos = (it->what == IT_COMPOSITION
-              ? string_pos (IT_STRING_CHARPOS (*it) + it->cmp_len, it->string)
+              ? string_pos (IT_STRING_CHARPOS (*it)
+                            + it->cmp_it.nchars, it->string)
               : string_pos (IT_STRING_CHARPOS (*it) + 1, it->string));
 
       if (it->current.overlay_string_index >= 0)
@@ -3650,7 +3667,7 @@ face_before_or_after_it_pos (it, before_p)
          if (it->what == IT_COMPOSITION)
            /* For composition, we must check the position after the
               composition.  */
-           pos.charpos += it->cmp_len, pos.bytepos += it->len;
+           pos.charpos += it->cmp_it.nchars, pos.bytepos += it->len;
          else
            INC_TEXT_POS (pos, it->multibyte_p);
        }
@@ -3661,7 +3678,7 @@ face_before_or_after_it_pos (it, before_p)
                                         it->region_beg_charpos,
                                         it->region_end_charpos,
                                         &next_check_charpos,
-                                        limit, 0);
+                                        limit, 0, -1);
 
       /* Correct the face for charsets different from ASCII.  Do it
         for the multibyte case only.  The face returned above is
@@ -3994,11 +4011,8 @@ handle_display_prop (it)
     }
   else
     {
-      int ret = handle_single_display_spec (it, prop, object, overlay,
-                                           position, 0);
-      if (ret < 0)  /* Replaced by "", i.e. nothing. */
-       return HANDLED_RECOMPUTE_PROPS;
-      if (ret)
+      if (handle_single_display_spec (it, prop, object, overlay,
+                                     position, 0))
        display_replaced_p = 1;
     }
 
@@ -4045,8 +4059,7 @@ display_prop_end (it, object, start_pos)
    property ends.
 
    Value is non-zero if something was found which replaces the display
-   of buffer or string text.  Specifically, the value is -1 if that
-   "something" is "nothing". */
+   of buffer or string text.  */
 
 static int
 handle_single_display_spec (it, spec, object, overlay, position,
@@ -4371,11 +4384,6 @@ handle_single_display_spec (it, spec, object, overlay, position,
 
       if (STRINGP (value))
        {
-         if (SCHARS (value) == 0)
-           {
-             pop_it (it);
-             return -1;  /* Replaced by "", i.e. nothing.  */
-           }
          it->string = value;
          it->multibyte_p = STRING_MULTIBYTE (it->string);
          it->current.overlay_string_index = -1;
@@ -4567,10 +4575,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.
 
@@ -4624,97 +4631,6 @@ string_buffer_position (w, string, around_charpos)
                        `composition' property
  ***********************************************************************/
 
-static enum prop_handled
-handle_auto_composed_prop (it)
-     struct it *it;
-{
-  enum prop_handled handled = HANDLED_NORMALLY;
-
-  if (FUNCTIONP (Vauto_composition_function))
-    {
-      Lisp_Object val = Qnil;
-      EMACS_INT pos, limit = -1;
-
-      if (STRINGP (it->string))
-       pos = IT_STRING_CHARPOS (*it);
-      else
-       pos = IT_CHARPOS (*it);
-
-      val = Fget_text_property (make_number (pos), Qauto_composed, it->string);
-      if (! NILP (val))
-       {
-         Lisp_Object cmp_prop;
-         EMACS_INT cmp_start, cmp_end;
-
-         if (get_property_and_range (pos, Qcomposition, &cmp_prop,
-                                     &cmp_start, &cmp_end, it->string)
-             && cmp_start == pos
-             && COMPOSITION_METHOD (cmp_prop) == COMPOSITION_WITH_GLYPH_STRING)
-           {
-             Lisp_Object gstring = COMPOSITION_COMPONENTS (cmp_prop);
-             Lisp_Object font_object = LGSTRING_FONT (gstring);
-
-             if (! EQ (font_object,
-                       font_at (-1, pos, FACE_FROM_ID (it->f, it->face_id),
-                                it->w, it->string)))
-               /* We must re-compute the composition for the
-                  different font.  */
-               val = Qnil;
-           }
-
-         if (! NILP (val))
-           {
-             Lisp_Object end;
-
-             /* As Fnext_single_char_property_change is very slow, we
-                limit the search to the current line.  */
-             if (STRINGP (it->string))
-               limit = SCHARS (it->string);
-             else
-               limit = find_next_newline_no_quit (pos, 1);
-             end = Fnext_single_char_property_change (make_number (pos),
-                                                      Qauto_composed,
-                                                      it->string,
-                                                      make_number (limit));
-
-             if (XINT (end) < limit)
-               /* The current point is auto-composed, but there exist
-                  characters not yet composed beyond the
-                  auto-composed region.  There's a possiblity that
-                  the last characters in the region may be newly
-                  composed.  */
-               val = Qnil;
-           }
-       }
-      if (NILP (val) && ! STRINGP (it->string))
-       {
-         if (limit < 0)
-           limit = (STRINGP (it->string) ? SCHARS (it->string)
-                    : find_next_newline_no_quit (pos, 1));
-         if (pos < limit)
-           {
-             int count = SPECPDL_INDEX ();
-             Lisp_Object args[5];
-
-             if (FRAME_WINDOW_P (it->f))
-               limit = font_range (pos, limit,
-                                   FACE_FROM_ID (it->f, it->face_id),
-                                   it->f, it->string);
-             args[0] = Vauto_composition_function;
-             specbind (Qauto_composition_function, Qnil);
-             args[1] = make_number (pos);
-             args[2] = make_number (limit);
-             args[3] = it->window;
-             args[4] = it->string;
-             safe_call (5, args);
-             unbind_to (count, Qnil);
-           }
-       }
-    }
-
-  return handled;
-}
-
 /* Set up iterator IT from `composition' property at its current
    position.  Called from handle_stop.  */
 
@@ -4724,7 +4640,6 @@ handle_composition_prop (it)
 {
   Lisp_Object prop, string;
   EMACS_INT pos, pos_byte, start, end;
-  enum prop_handled handled = HANDLED_NORMALLY;
 
   if (STRINGP (it->string))
     {
@@ -4751,8 +4666,6 @@ handle_composition_prop (it)
       && COMPOSITION_VALID_P (start, end, prop)
       && (STRINGP (it->string) || (PT <= start || PT >= end)))
     {
-      int id;
-
       if (start != pos)
        {
          if (STRINGP (it->string))
@@ -4760,63 +4673,18 @@ handle_composition_prop (it)
          else
            pos_byte = CHAR_TO_BYTE (start);
        }
-      id = get_composition_id (start, pos_byte, end - start, prop, string);
+      it->cmp_it.id = get_composition_id (start, pos_byte, end - start,
+                                              prop, string);
 
-      if (id >= 0)
+      if (it->cmp_it.id >= 0)
        {
-         struct composition *cmp = composition_table[id];
-
-         if (cmp->glyph_len == 0)
-           {
-             /* No glyph.  */
-             if (STRINGP (it->string))
-               {
-                 IT_STRING_CHARPOS (*it) = end;
-                 IT_STRING_BYTEPOS (*it) = string_char_to_byte (it->string,
-                                                                end);
-               }
-             else
-               {
-                 IT_CHARPOS (*it) = end;
-                 IT_BYTEPOS (*it) = CHAR_TO_BYTE (end);
-               }
-             return HANDLED_RECOMPUTE_PROPS;
-           }
-
-         it->stop_charpos = end;
-         push_it (it);
-
-         it->method = GET_FROM_COMPOSITION;
-         it->cmp_id = id;
-         it->cmp_len = COMPOSITION_LENGTH (prop);
-         /* For a terminal, draw only the first (non-TAB) character
-            of the components.  */
-         if (composition_table[id]->method == COMPOSITION_WITH_GLYPH_STRING)
-           {
-             /* FIXME: This doesn't do anything!?! */
-             Lisp_Object lgstring = AREF (XHASH_TABLE (composition_hash_table)
-                                          ->key_and_value,
-                                          cmp->hash_index * 2);
-           }
-         else
-           {
-             int i;
-
-             for (i = 0; i < cmp->glyph_len; i++)
-               if ((it->c = COMPOSITION_GLYPH (composition_table[id], i))
-                   != '\t')
-                 break;
-           }
-         if (it->c == '\t')
-           it->c = ' ';
-         it->len = (STRINGP (it->string)
-                    ? string_char_to_byte (it->string, end)
-                    : CHAR_TO_BYTE (end)) - pos_byte;
-         handled = HANDLED_RETURN;
+         it->cmp_it.ch = -1;
+         it->cmp_it.nchars = COMPOSITION_LENGTH (prop);
+         it->cmp_it.nglyphs = -1;
        }
     }
 
-  return handled;
+  return HANDLED_NORMALLY;
 }
 
 
@@ -4872,7 +4740,6 @@ next_overlay_string (it)
       it->ellipsis_p = (it->stack[it->sp - 1].display_ellipsis_p != 0);
       pop_it (it);
       xassert (it->sp > 0
-              || it->method == GET_FROM_COMPOSITION
               || (NILP (it->string)
                   && it->method == GET_FROM_BUFFER
                   && it->stop_charpos >= BEGV
@@ -4904,6 +4771,8 @@ next_overlay_string (it)
       SET_TEXT_POS (it->current.string_pos, 0, 0);
       it->method = GET_FROM_STRING;
       it->stop_charpos = 0;
+      if (it->cmp_it.stop_pos >= 0)
+       it->cmp_it.stop_pos = 0;
     }
 
   CHECK_IT (it);
@@ -4983,7 +4852,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;
@@ -5162,7 +5031,11 @@ get_overlay_strings_1 (it, charpos, compute_stop_p)
       /* Save IT's settings.  They are restored after all overlay
         strings have been processed.  */
       xassert (!compute_stop_p || it->sp == 0);
-      push_it (it);
+
+      /* When called from handle_stop, there might be an empty display
+         string loaded.  In that case, don't bother saving it.  */
+      if (!STRINGP (it->string) || SCHARS (it->string))
+       push_it (it);
 
       /* Set up IT to deliver display elements from the first overlay
         string.  */
@@ -5218,6 +5091,7 @@ push_it (it)
   p = it->stack + it->sp;
 
   p->stop_charpos = it->stop_charpos;
+  p->cmp_it = it->cmp_it;
   xassert (it->face_id >= 0);
   p->face_id = it->face_id;
   p->string = it->string;
@@ -5230,13 +5104,6 @@ push_it (it)
       p->u.image.image_id = it->image_id;
       p->u.image.slice = it->slice;
       break;
-    case GET_FROM_COMPOSITION:
-      p->u.comp.object = it->object;
-      p->u.comp.c = it->c;
-      p->u.comp.len = it->len;
-      p->u.comp.cmp_id = it->cmp_id;
-      p->u.comp.cmp_len = it->cmp_len;
-      break;
     case GET_FROM_STRETCH:
       p->u.stretch.object = it->object;
       break;
@@ -5253,6 +5120,7 @@ push_it (it)
   p->voffset = it->voffset;
   p->string_from_display_prop_p = it->string_from_display_prop_p;
   p->display_ellipsis_p = 0;
+  p->line_wrap = it->line_wrap;
   ++it->sp;
 }
 
@@ -5273,6 +5141,7 @@ pop_it (it)
   --it->sp;
   p = it->stack + it->sp;
   it->stop_charpos = p->stop_charpos;
+  it->cmp_it = p->cmp_it;
   it->face_id = p->face_id;
   it->current = p->current;
   it->position = p->position;
@@ -5288,13 +5157,6 @@ pop_it (it)
       it->object = p->u.image.object;
       it->slice = p->u.image.slice;
       break;
-    case GET_FROM_COMPOSITION:
-      it->object = p->u.comp.object;
-      it->c = p->u.comp.c;
-      it->len = p->u.comp.len;
-      it->cmp_id = p->u.comp.cmp_id;
-      it->cmp_len = p->u.comp.cmp_len;
-      break;
     case GET_FROM_STRETCH:
       it->object = p->u.comp.object;
       break;
@@ -5304,6 +5166,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;
@@ -5314,6 +5186,7 @@ pop_it (it)
   it->font_height = p->font_height;
   it->voffset = p->voffset;
   it->string_from_display_prop_p = p->string_from_display_prop_p;
+  it->line_wrap = p->line_wrap;
 }
 
 
@@ -5754,7 +5627,6 @@ static int (* get_next_element[NUM_IT_METHODS]) P_ ((struct it *it)) =
 {
   next_element_from_buffer,
   next_element_from_display_vector,
-  next_element_from_composition,
   next_element_from_string,
   next_element_from_c_string,
   next_element_from_image,
@@ -5763,6 +5635,19 @@ static int (* get_next_element[NUM_IT_METHODS]) P_ ((struct it *it)) =
 
 #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
 
+
+/* Return 1 iff a character at CHARPOS (and BYTEPOS) is composed
+   (possibly with the following characters).  */
+
+#define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS)                            \
+  ((IT)->cmp_it.id >= 0                                                        \
+   || ((IT)->cmp_it.stop_pos == (CHARPOS)                              \
+       && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS,      \
+                                (IT)->end_charpos, (IT)->w,            \
+                                FACE_FROM_ID ((IT)->f, (IT)->face_id), \
+                                (IT)->string)))
+
+
 /* Load IT's display element fields with information about the next
    display element from the current position of IT.  Value is zero if
    end of buffer (or C string) is reached.  */
@@ -5798,6 +5683,10 @@ 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 decoded = it->c;
 
          if (it->dp
              && (dv = DISP_CHAR_VECTOR (it->dp, it->c),
@@ -5826,6 +5715,22 @@ get_next_display_element (it)
              goto get_next;
            }
 
+         if (unibyte_display_via_language_environment
+             && it->c >= 0x80)
+           decoded = DECODE_CHAR (unibyte, it->c);
+
+         if (it->c >= 0x80 && ! NILP (Vnobreak_char_display))
+           {
+             if (it->multibyte_p)
+               nbsp_or_shy = (it->c == 0xA0   ? char_is_nbsp
+                              : it->c == 0xAD ? char_is_soft_hyphen
+                              :                 char_is_other);
+             else if (unibyte_display_via_language_environment)
+               nbsp_or_shy = (decoded == 0xA0   ? char_is_nbsp
+                              : decoded == 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
@@ -5838,20 +5743,19 @@ get_next_display_element (it)
             If it->multibyte_p is zero, eight-bit characters that
             don't have corresponding multibyte char code are also
             translated to octal form.  */
-         else if ((it->c < ' '
-                   ? (it->area != TEXT_AREA
-                      /* In mode line, treat \n, \t like other crl chars.  */
-                      || (it->c != '\t'
-                          && it->glyph_row && it->glyph_row->mode_line_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 ((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'))
+              : (nbsp_or_shy
+                 || (it->multibyte_p
+                     ? ! CHAR_PRINTABLE_P (it->c)
+                     : (! unibyte_display_via_language_environment
+                        ? it->c >= 0x80
+                        : (decoded >= 0x80 && decoded < 0xA0))))))
            {
              /* IT->c is a control character which must be displayed
                 either as '\003' or as `^C' where the '\\' and '^'
@@ -5907,7 +5811,7 @@ 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,
@@ -5957,7 +5861,7 @@ 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], '-');
@@ -5968,10 +5872,10 @@ 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 ? ' ' : '-');
+                 it->c = (nbsp_or_shy == char_is_nbsp ? ' ' : '-');
                  XSETINT (it->ctl_chars[1], it->c);
                  ctl_len = 2;
                  goto display_control;
@@ -6037,6 +5941,7 @@ get_next_display_element (it)
        }
     }
 
+#ifdef HAVE_WINDOW_SYSTEM
   /* Adjust face id for a multibyte character.  There are no multibyte
      character in unibyte text.  */
   if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION)
@@ -6045,26 +5950,76 @@ get_next_display_element (it)
       && FRAME_WINDOW_P (it->f))
     {
       struct face *face = FACE_FROM_ID (it->f, it->face_id);
-      int pos = (it->s ? -1
-                : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
-                : IT_CHARPOS (*it));
 
-      it->face_id = FACE_FOR_CHAR (it->f, face, it->c, pos, it->string);
+      if (it->what == IT_COMPOSITION && it->cmp_it.ch >= 0)
+       {
+         /* Automatic composition with glyph-string.   */
+         Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
+
+         it->face_id = face_for_font (it->f, LGSTRING_FONT (gstring), face);
+       }
+      else
+       {
+         int pos = (it->s ? -1
+                    : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
+                    : IT_CHARPOS (*it));
+
+         it->face_id = FACE_FOR_CHAR (it->f, face, it->c, pos, it->string);
+       }
     }
+#endif
 
   /* Is this character the last one of a run of characters with
      box?  If yes, set IT->end_of_box_run_p to 1.  */
   if (it->face_box_p
       && it->s == NULL)
     {
-      int face_id;
-      struct face *face;
+      if (it->method == GET_FROM_STRING && it->sp)
+       {
+         int face_id = underlying_face_id (it);
+         struct face *face = FACE_FROM_ID (it->f, face_id);
 
-      it->end_of_box_run_p
-       = ((face_id = face_after_it_pos (it),
-           face_id != it->face_id)
-          && (face = FACE_FROM_ID (it->f, face_id),
-              face->box == FACE_NO_BOX));
+         if (face)
+           {
+             if (face->box == FACE_NO_BOX)
+               {
+                 /* If the box comes from face properties in a
+                    display string, check faces in that string.  */
+                 int string_face_id = face_after_it_pos (it);
+                 it->end_of_box_run_p
+                   = (FACE_FROM_ID (it->f, string_face_id)->box
+                      == FACE_NO_BOX);
+               }
+             /* Otherwise, the box comes from the underlying face.
+                If this is the last string character displayed, check
+                the next buffer location.  */
+             else if ((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
+                      && (it->current.overlay_string_index
+                          == it->n_overlay_strings - 1))
+               {
+                 EMACS_INT ignore;
+                 int next_face_id;
+                 struct text_pos pos = it->current.pos;
+                 INC_TEXT_POS (pos, it->multibyte_p);
+
+                 next_face_id = face_at_buffer_position
+                   (it->w, CHARPOS (pos), it->region_beg_charpos,
+                    it->region_end_charpos, &ignore,
+                    (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT), 0,
+                    -1);
+                 it->end_of_box_run_p
+                   = (FACE_FROM_ID (it->f, next_face_id)->box
+                      == FACE_NO_BOX);
+               }
+           }
+       }
+      else
+       {
+         int face_id = face_after_it_pos (it);
+         it->end_of_box_run_p
+           = (face_id != it->face_id
+              && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX);
+       }
     }
 
   /* Value is 0 if end of buffer or string reached.  */
@@ -6105,6 +6060,20 @@ set_iterator_to_next (it, reseat_p)
         invisible lines that are so because of selective display.  */
       if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
        reseat_at_next_visible_line_start (it, 0);
+      else if (it->cmp_it.id >= 0)
+       {
+         IT_CHARPOS (*it) += it->cmp_it.nchars;
+         IT_BYTEPOS (*it) += it->cmp_it.nbytes;
+         if (it->cmp_it.to < it->cmp_it.nglyphs)
+           it->cmp_it.from = it->cmp_it.to;
+         else
+           {
+             it->cmp_it.id = -1;
+             composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
+                                           IT_BYTEPOS (*it), it->stop_charpos,
+                                           Qnil);
+           }
+       }
       else
        {
          xassert (it->len != 0);
@@ -6114,23 +6083,6 @@ set_iterator_to_next (it, reseat_p)
        }
       break;
 
-    case GET_FROM_COMPOSITION:
-      xassert (it->cmp_id >= 0 && it->cmp_id < n_compositions);
-      xassert (it->sp > 0);
-      pop_it (it);
-      if (it->method == GET_FROM_STRING)
-       {
-         IT_STRING_BYTEPOS (*it) += it->len;
-         IT_STRING_CHARPOS (*it) += it->cmp_len;
-         goto consider_string_end;
-       }
-      else if (it->method == GET_FROM_BUFFER)
-       {
-         IT_BYTEPOS (*it) += it->len;
-         IT_CHARPOS (*it) += it->cmp_len;
-       }
-      break;
-
     case GET_FROM_C_STRING:
       /* Current display element of IT is from a C string.  */
       IT_BYTEPOS (*it) += it->len;
@@ -6186,8 +6138,26 @@ set_iterator_to_next (it, reseat_p)
     case GET_FROM_STRING:
       /* Current display element is a character from a Lisp string.  */
       xassert (it->s == NULL && STRINGP (it->string));
-      IT_STRING_BYTEPOS (*it) += it->len;
-      IT_STRING_CHARPOS (*it) += 1;
+      if (it->cmp_it.id >= 0)
+       {
+         IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
+         IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
+         if (it->cmp_it.to < it->cmp_it.nglyphs)
+           it->cmp_it.from = it->cmp_it.to;
+         else
+           {
+             it->cmp_it.id = -1;
+             composition_compute_stop_pos (&it->cmp_it,
+                                           IT_STRING_CHARPOS (*it),
+                                           IT_STRING_BYTEPOS (*it),
+                                           it->stop_charpos, it->string);
+           }
+       }
+      else
+       {
+         IT_STRING_BYTEPOS (*it) += it->len;
+         IT_STRING_CHARPOS (*it) += 1;
+       }
 
     consider_string_end:
 
@@ -6330,6 +6300,12 @@ next_element_from_string (it)
          it->what = IT_EOB;
          return 0;
        }
+      else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
+                               IT_STRING_BYTEPOS (*it))
+              && next_element_from_composition (it))
+       {
+         return 1;
+       }
       else if (STRING_MULTIBYTE (it->string))
        {
          int remaining = SBYTES (it->string) - IT_STRING_BYTEPOS (*it);
@@ -6360,6 +6336,12 @@ next_element_from_string (it)
          it->c = ' ', it->len = 1;
          CHARPOS (position) = BYTEPOS (position) = -1;
        }
+      else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
+                               IT_STRING_BYTEPOS (*it))
+              && next_element_from_composition (it))
+       {
+         return 1;
+       }
       else if (STRING_MULTIBYTE (it->string))
        {
          int maxlen = SBYTES (it->string) - IT_STRING_BYTEPOS (*it);
@@ -6497,10 +6479,7 @@ next_element_from_buffer (it)
 {
   int success_p = 1;
 
-  /* Check this assumption, otherwise, we would never enter the
-     if-statement, below.  */
-  xassert (IT_CHARPOS (*it) >= BEGV
-          && IT_CHARPOS (*it) <= it->stop_charpos);
+  xassert (IT_CHARPOS (*it) >= BEGV);
 
   if (IT_CHARPOS (*it) >= it->stop_charpos)
     {
@@ -6546,14 +6525,16 @@ 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))
+         && next_element_from_composition (it))
+       {
+         return 1;
+       }
+
       /* Get the next character, maybe multibyte.  */
       p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
       if (it->multibyte_p && !ASCII_BYTE_P (*p))
-       {
-         int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
-                       - IT_BYTEPOS (*it));
-         it->c = string_char_and_length (p, maxlen, &it->len);
-       }
+       it->c = STRING_CHAR_AND_LENGTH (p, 0, it->len);
       else
        it->c = *p, it->len = 1;
 
@@ -6625,22 +6606,43 @@ run_redisplay_end_trigger_hook (it)
 }
 
 
-/* Deliver a composition display element.  The iterator IT is already
-   filled with composition information (done in
-   handle_composition_prop).  Value is always 1.  */
+/* Deliver a composition display element.  Unlike the other
+   next_element_from_XXX, this function is not registered in the array
+   get_next_element[].  It is called from next_element_from_buffer and
+   next_element_from_string when necessary.  */
 
 static int
 next_element_from_composition (it)
      struct it *it;
 {
   it->what = IT_COMPOSITION;
-  it->position = (STRINGP (it->string)
-                 ? it->current.string_pos
-                 : it->current.pos);
+  it->len = it->cmp_it.nbytes;
   if (STRINGP (it->string))
-    it->object = it->string;
+    {
+      if (it->c < 0)
+       {
+         IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
+         IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
+         return 0;
+       }
+      it->position = it->current.string_pos;
+      it->object = it->string;
+      it->c = composition_update_it (&it->cmp_it, IT_STRING_CHARPOS (*it),
+                                    IT_STRING_BYTEPOS (*it), it->string);
+    }
   else
-    it->object = it->w->buffer;
+    {
+      if (it->c < 0)
+       {
+         IT_CHARPOS (*it) += it->cmp_it.nchars;
+         IT_BYTEPOS (*it) += it->cmp_it.nbytes;
+         return 0;
+       }
+      it->position = it->current.pos;
+      it->object = it->w->buffer;
+      it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
+                                    IT_BYTEPOS (*it), Qnil);
+    }
   return 1;
 }
 
@@ -6826,9 +6828,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
@@ -6928,8 +6930,14 @@ move_it_in_display_line_to (struct it *it,
                            }
 
                          set_iterator_to_next (it, 1);
-#ifdef HAVE_WINDOW_SYSTEM
-                         if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+                         /* On graphical terminals, newlines may
+                            "overflow" into the fringe if
+                            overflow-newline-into-fringe is non-nil.
+                            On text-only terminals, newlines may
+                            overflow into the last glyph on the
+                            display line.*/
+                         if (!FRAME_WINDOW_P (it->f)
+                             || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
                            {
                              if (!get_next_display_element (it))
                                {
@@ -6950,7 +6958,6 @@ move_it_in_display_line_to (struct it *it,
                                  break;
                                }
                            }
-#endif /* HAVE_WINDOW_SYSTEM */
                        }
                    }
                  else
@@ -7025,8 +7032,8 @@ 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 (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+         if (!FRAME_WINDOW_P (it->f)
+             || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
            {
              if (!get_next_display_element (it)
                  || BUFFER_POS_REACHED_P ())
@@ -7040,7 +7047,6 @@ move_it_in_display_line_to (struct it *it,
                  break;
                }
            }
-#endif /* HAVE_WINDOW_SYSTEM */
          result = MOVE_LINE_TRUNCATED;
          break;
        }
@@ -7110,8 +7116,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 (;;)
     {
@@ -7251,7 +7256,8 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
            break;
        }
       else if (BUFFERP (it->object)
-              && it->method == GET_FROM_BUFFER
+              && (it->method == GET_FROM_BUFFER
+                  || it->method == GET_FROM_STRETCH)
               && IT_CHARPOS (*it) >= to_charpos)
        skip = MOVE_POS_MATCH_OR_ZV;
       else
@@ -7284,8 +7290,23 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
             associated with the tab are displayed on the current
             line.  Since it->current_x does not include these glyphs,
             we use it->last_visible_x instead.  */
-         it->continuation_lines_width +=
-           (it->c == '\t') ? it->last_visible_x : it->current_x;
+         if (it->c == '\t')
+           {
+             it->continuation_lines_width += it->last_visible_x;
+             /* When moving by vpos, ensure that the iterator really
+                advances to the next line (bug#847, bug#969).  Fixme:
+                do we need to do this in other circumstances?  */
+             if (it->current_x != it->last_visible_x
+                 && (op & MOVE_TO_VPOS)
+                 && !(op & (MOVE_TO_X | MOVE_TO_POS)))
+               {
+                 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;
          break;
 
        default:
@@ -7294,7 +7315,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;
@@ -7405,11 +7428,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
     {
@@ -7457,12 +7475,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
        }
     }
 }
@@ -7925,7 +7937,7 @@ message2_nolog (m, nbytes, multibyte)
   struct frame *sf = SELECTED_FRAME ();
   message_enable_multibyte = multibyte;
 
-  if (noninteractive)
+  if (FRAME_INITIAL_P (sf))
     {
       if (noninteractive_need_newline)
        putc ('\n', stderr);
@@ -8024,7 +8036,7 @@ message3_nolog (m, nbytes, multibyte)
   struct frame *sf = SELECTED_FRAME ();
   message_enable_multibyte = multibyte;
 
-  if (noninteractive)
+  if (FRAME_INITIAL_P (sf))
     {
       if (noninteractive_need_newline)
        putc ('\n', stderr);
@@ -8122,7 +8134,7 @@ message_with_string (m, string, log)
            putc ('\n', stderr);
          noninteractive_need_newline = 0;
          fprintf (stderr, m, SDATA (string));
-         if (cursor_in_echo_area == 0)
+         if (!cursor_in_echo_area)
            fprintf (stderr, "\n");
          fflush (stderr);
        }
@@ -8293,7 +8305,7 @@ ensure_echo_area_buffers ()
        sprintf (name, " *Echo Area %d*", i);
        echo_buffer[i] = Fget_buffer_create (build_string (name));
        XBUFFER (echo_buffer[i])->truncate_lines = Qnil;
-       /* to force word wrap in echo area - 
+       /* to force word wrap in echo area -
           it was decided to postpone this*/
        /* XBUFFER (echo_buffer[i])->word_wrap = Qt; */
 
@@ -9591,7 +9603,8 @@ prepare_menu_bars ()
 
              while (CONSP (functions))
                {
-                 call1 (XCAR (functions), frame);
+                 if (!EQ (XCAR (functions), Qt))
+                   call1 (XCAR (functions), frame);
                  functions = XCDR (functions);
                }
              UNGCPRO;
@@ -9852,7 +9865,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)
@@ -10326,7 +10339,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;
@@ -11333,7 +11346,7 @@ redisplay_internal (preserve_echo_area)
   /* No redisplay if running in batch mode or frame is not yet fully
      initialized, or redisplay is explicitly turned off by setting
      Vinhibit_redisplay.  */
-  if (noninteractive
+  if (FRAME_INITIAL_P (SELECTED_FRAME ())
       || !NILP (Vinhibit_redisplay))
     return;
 
@@ -11412,7 +11425,7 @@ redisplay_internal (preserve_echo_area)
   if (face_change_count)
     ++windows_or_buffers_changed;
 
-  if (FRAME_TERMCAP_P (sf)
+  if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
       && FRAME_TTY (sf)->previous_frame != sf)
     {
       /* Since frames on a single ASCII terminal share the same
@@ -11446,7 +11459,6 @@ redisplay_internal (preserve_echo_area)
       }
   }
 
-
   /* Notice any pending interrupt request to change frame size.  */
   do_pending_window_change (1);
 
@@ -11662,29 +11674,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,
@@ -11827,6 +11827,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)
@@ -12244,7 +12248,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
@@ -12575,44 +12579,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 */
 }
 
 
@@ -12669,17 +12635,15 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
   /* Compute scroll margin height in pixels.  We scroll when point is
      within this distance from the top or bottom of the window.  */
   if (scroll_margin > 0)
-    {
-      this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
-      this_scroll_margin *= FRAME_LINE_HEIGHT (f);
-    }
+    this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
+      * FRAME_LINE_HEIGHT (f);
   else
     this_scroll_margin = 0;
 
   /* Force scroll_conservatively to have a reasonable value, to avoid
-     overflow while computing how much to scroll.  Note that it's
-     fairly common for users to supply scroll-conservatively equal to
-     `most-positive-fixnum', which can be larger than INT_MAX.  */
+     overflow while computing how much to scroll.  Note that the user
+     can supply scroll-conservatively equal to `most-positive-fixnum',
+     which can be larger than INT_MAX.  */
   if (scroll_conservatively > scroll_limit)
     {
       scroll_conservatively = scroll_limit;
@@ -12701,7 +12665,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 
  too_near_end:
 
-  /* Decide whether we have to scroll down.  */
+  /* Decide whether to scroll down.  */
   if (PT > CHARPOS (startp))
     {
       int scroll_margin_y;
@@ -12716,17 +12680,17 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 
       if (PT > CHARPOS (it.current.pos))
        {
-         /* Point is in the scroll margin at the bottom of the
-            window, or below.  Compute the distance from the scroll
-            margin to PT, and give up if the distance is greater than
-            scroll_max.  */
-         move_it_to (&it, PT, -1, it.last_visible_y - 1, -1,
-                     MOVE_TO_POS | MOVE_TO_Y);
+         int y0 = line_bottom_y (&it);
 
-         /* To make point visible, we must move the window start down
-            so that the cursor line is visible, which means we have
-            to add in the height of the cursor line.  */
-         dy = line_bottom_y (&it) - scroll_margin_y;
+         /* Compute the distance from the scroll margin to PT
+            (including the height of the cursor line).  Moving the
+            iterator unconditionally to PT can be slow if PT is far
+            away, so stop 10 lines past the window bottom (is there a
+            way to do the right thing quickly?).  */
+         move_it_to (&it, PT, -1,
+                     it.last_visible_y + 10 * FRAME_LINE_HEIGHT (f),
+                     -1, MOVE_TO_POS | MOVE_TO_Y);
+         dy = line_bottom_y (&it) - y0;
 
          if (dy > scroll_max)
            return SCROLLING_FAILED;
@@ -12737,14 +12701,11 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 
   if (scroll_down_p)
     {
-      /* Move the window start down.  If scrolling conservatively,
-        move it just enough down to make point visible.  If
-        scroll_step is set, move it down by scroll_step.  */
-      start_display (&it, w, startp);
-
+      /* Point is in or below the bottom scroll margin, so move the
+        window start down.  If scrolling conservatively, move it just
+        enough down to make point visible.  If scroll_step is set,
+        move it down by scroll_step.  */
       if (scroll_conservatively)
-       /* Set AMOUNT_TO_SCROLL to at least one line,
-          and at most scroll_conservatively lines.  */
        amount_to_scroll
          = min (max (dy, FRAME_LINE_HEIGHT (f)),
                 FRAME_LINE_HEIGHT (f) * scroll_conservatively);
@@ -12766,10 +12727,10 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
       if (amount_to_scroll <= 0)
        return SCROLLING_FAILED;
 
-      /* If moving by amount_to_scroll leaves STARTP unchanged,
-        move it down one screen line.  */
-
+      start_display (&it, w, startp);
       move_it_vertically (&it, amount_to_scroll);
+
+      /* If STARTP is unchanged, move it down another screen line.  */
       if (CHARPOS (it.current.pos) == CHARPOS (startp))
        move_it_by_lines (&it, 1, 1);
       startp = it.current.pos;
@@ -13586,11 +13547,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;
 
@@ -13914,8 +13870,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))
        {
@@ -13962,7 +13918,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)
@@ -14431,13 +14387,6 @@ try_window_reusing_current_matrix (w)
        if (display_line (&it))
          last_text_row = it.glyph_row - 1;
 
-      /* Give up If point isn't in a row displayed or reused.  */
-      if (w->cursor.vpos < 0)
-       {
-         clear_glyph_matrix (w->desired_matrix);
-         return 0;
-       }
-
       /* If point is in a reused row, adjust y and vpos of the cursor
         position.  */
       if (pt_row)
@@ -14446,6 +14395,16 @@ try_window_reusing_current_matrix (w)
          w->cursor.y -= first_reusable_row->y - start_row->y;
        }
 
+      /* Give up if point isn't in a row displayed or reused.  (This
+        also handles the case where w->cursor.vpos < nrows_scrolled
+        after the calls to display_line, which can happen with scroll
+        margins.  See bug#1295.)  */
+      if (w->cursor.vpos < 0)
+       {
+         clear_glyph_matrix (w->desired_matrix);
+         return 0;
+       }
+
       /* Scroll the display.  */
       run.current_y = first_reusable_row->y;
       run.desired_y = WINDOW_HEADER_LINE_HEIGHT (w);
@@ -14502,11 +14461,15 @@ try_window_reusing_current_matrix (w)
          if (row < bottom_row)
            {
              struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
-             while (glyph->charpos < PT)
+             struct glyph *end = glyph + row->used[TEXT_AREA];
+
+             for (; glyph < end
+                    && (!BUFFERP (glyph->object)
+                        || glyph->charpos < PT);
+                  glyph++)
                {
                  w->cursor.hpos++;
                  w->cursor.x += glyph->pixel_width;
-                 glyph++;
                }
            }
        }
@@ -14939,7 +14902,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);
 
@@ -15553,15 +15517,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));
 
@@ -15674,7 +15629,7 @@ dump_glyph (row, glyph, area)
   else if (glyph->type == COMPOSITE_GLYPH)
     {
       fprintf (stderr,
-              "  %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
+              "  %5d %4c %6d %c %3d 0x%05x",
               glyph - row->glyphs[TEXT_AREA],
               '+',
               glyph->charpos,
@@ -15684,8 +15639,12 @@ dump_glyph (row, glyph, area)
                   ? 'S'
                   : '-')),
               glyph->pixel_width,
-              glyph->u.cmp_id,
-              '.',
+              glyph->u.cmp.id);
+      if (glyph->u.cmp.automatic)
+       fprintf (stderr,
+                "[%d-%d]",
+                glyph->u.cmp.from, glyph->u.cmp.to);
+      fprintf (stderr, " . %4d %1.1d%1.1d\n",
               glyph->face_id,
               glyph->left_box_line_p,
               glyph->right_box_line_p);
@@ -16220,9 +16179,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);
@@ -16501,7 +16461,13 @@ handle_line_prefix (struct it *it)
        prefix = Vline_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;
+    }
 }
 
 \f
@@ -16595,13 +16561,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;
@@ -16743,7 +16706,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))
@@ -16759,7 +16721,6 @@ display_line (it)
                                  row->exact_window_width_line_p = 1;
                                }
                            }
-#endif /* HAVE_WINDOW_SYSTEM */
                        }
                    }
                  else if (CHAR_GLYPH_PADDING_P (*glyph)
@@ -16896,12 +16857,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);
@@ -16942,27 +16901,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;
@@ -17253,8 +17207,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)
@@ -17295,10 +17249,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)
@@ -17814,10 +17769,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,
@@ -17829,6 +17784,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;
              }
          }
       }
@@ -19595,7 +19556,7 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
 /* Fill glyph string S with composition components specified by S->cmp.
 
    BASE_FACE is the base face of the composition.
-   S->gidx is the index of the first component for S.
+   S->cmp_from is the index of the first component for S.
 
    OVERLAPS non-zero means S should draw the foreground only, and use
    its physical height for clipping.  See also draw_glyphs.
@@ -19609,70 +19570,45 @@ fill_composite_glyph_string (s, base_face, overlaps)
      int overlaps;
 {
   int i;
+  /* For all glyphs of this composition, starting at the offset
+     S->cmp_from, until we reach the end of the definition or encounter a
+     glyph that requires the different face, add it to S.  */
+  struct face *face;
 
   xassert (s);
 
   s->for_overlaps = overlaps;
-
-  if (s->cmp->method == COMPOSITION_WITH_GLYPH_STRING)
-    {
-      Lisp_Object gstring
-       = AREF (XHASH_TABLE (composition_hash_table)->key_and_value,
-               s->cmp->hash_index * 2);
-
-      s->face = base_face;
-      s->font = base_face->font;
-      for (i = 0, s->nchars = 0; i < s->cmp->glyph_len; i++, s->nchars++)
-       {
-         Lisp_Object g = LGSTRING_GLYPH (gstring, i);
-         unsigned code;
-          XChar2b * store_pos;
-         if (NILP (g))
-           break;
-         code = LGLYPH_CODE (g);
-          store_pos = s->char2b + i;
-         STORE_XCHAR2B (store_pos, code >> 8, code & 0xFF);
-       }
-      s->width = s->cmp->pixel_width;
-    }
-  else
+  s->face = NULL;
+  s->font = NULL;
+  for (i = s->cmp_from; i < s->cmp->glyph_len; i++)
     {
-      /* For all glyphs of this composition, starting at the offset
-        S->gidx, until we reach the end of the definition or encounter a
-        glyph that requires the different face, add it to S.  */
-      struct face *face;
+      int c = COMPOSITION_GLYPH (s->cmp, i);
 
-      s->face = NULL;
-      s->font = NULL;
-      for (i = s->gidx; i < s->cmp->glyph_len; i++)
+      if (c != '\t')
        {
-         int c = COMPOSITION_GLYPH (s->cmp, i);
+         int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
+                                      -1, Qnil);
 
-         if (c != '\t')
+         face = get_char_face_and_encoding (s->f, c, face_id,
+                                            s->char2b + i, 1, 1);
+         if (face)
            {
-             int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
-                                          -1, Qnil);
-
-             face = get_char_face_and_encoding (s->f, c, face_id,
-                                                s->char2b + i, 1, 1);
-             if (face)
+             if (! s->face)
                {
-                 if (! s->face)
-                   {
-                     s->face = face;
-                     s->font = s->face->font;
-                   }
-                 else if (s->face != face)
-                   break;
+                 s->face = face;
+                 s->font = s->face->font;
                }
+             else if (s->face != face)
+               break;
            }
-         ++s->nchars;
        }
-
-      /* All glyph strings for the same composition has the same width,
-        i.e. the width set for the first component of the composition.  */
-      s->width = s->first_glyph->pixel_width;
+      ++s->nchars;
     }
+  s->cmp_to = i;
+
+  /* All glyph strings for the same composition has the same width,
+     i.e. the width set for the first component of the composition.  */
+  s->width = s->first_glyph->pixel_width;
 
   /* If the specified font could not be loaded, use the frame's
      default font, but record the fact that we couldn't load it in
@@ -19690,7 +19626,44 @@ fill_composite_glyph_string (s, base_face, overlaps)
   /* This glyph string must always be drawn with 16-bit functions.  */
   s->two_byte_p = 1;
 
-  return s->gidx + s->nchars;
+  return s->cmp_to;
+}
+
+static int
+fill_gstring_glyph_string (s, face_id, start, end, overlaps)
+     struct glyph_string *s;
+     int face_id;
+     int start, end, overlaps;
+{
+  struct glyph *glyph, *last;
+  Lisp_Object lgstring;
+  int i;
+
+  s->for_overlaps = overlaps;
+  glyph = s->row->glyphs[s->area] + start;
+  last = s->row->glyphs[s->area] + end;
+  s->cmp_id = glyph->u.cmp.id;
+  s->cmp_from = glyph->u.cmp.from;
+  s->cmp_to = glyph->u.cmp.to + 1;
+  s->face = FACE_FROM_ID (s->f, face_id);
+  lgstring = composition_gstring_from_id (s->cmp_id);
+  s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
+  glyph++;
+  while (glyph < last
+        && glyph->u.cmp.automatic
+        && glyph->u.cmp.id == s->cmp_id
+        && s->cmp_to == glyph->u.cmp.from)
+    s->cmp_to = (glyph++)->u.cmp.to + 1;
+
+  for (i = s->cmp_from; i < s->cmp_to; i++)
+    {
+      Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
+      unsigned code = LGLYPH_CODE (lglyph);
+
+      STORE_XCHAR2B ((s->char2b + i), code >> 8, code & 0xFF);
+    }
+  s->width = composition_gstring_width (lgstring, s->cmp_from, s->cmp_to, NULL);
+  return glyph - s->row->glyphs[s->area];
 }
 
 
@@ -19717,7 +19690,7 @@ fill_glyph_string (s, face_id, start, end, overlaps)
   xassert (s->nchars == 0);
   xassert (start >= 0 && end > start);
 
-  s->for_overlaps = overlaps,
+  s->for_overlaps = overlaps;
   glyph = s->row->glyphs[s->area] + start;
   last = s->row->glyphs[s->area] + end;
   voffset = glyph->voffset;
@@ -19837,7 +19810,6 @@ get_per_char_metric (f, font, char2b)
 {
   static struct font_metrics metrics;
   unsigned code = (XCHAR2B_BYTE1 (char2b) << 8) | XCHAR2B_BYTE2 (char2b);
-  struct font *fontp;
 
   if (! font || code == FONT_INVALID_CODE)
     return NULL;
@@ -19875,10 +19847,27 @@ x_get_glyph_overhangs (glyph, f, left, right)
     }
   else if (glyph->type == COMPOSITE_GLYPH)
     {
-      struct composition *cmp = composition_table[glyph->u.cmp_id];
+      if (! glyph->u.cmp.automatic)
+       {
+         struct composition *cmp = composition_table[glyph->u.cmp.id];
+
+         if (cmp->rbearing > cmp->pixel_width)
+           *right = cmp->rbearing - cmp->pixel_width;
+         if (cmp->lbearing < 0)
+           *left = - cmp->lbearing;
+       }
+      else
+       {
+         Lisp_Object gstring = composition_gstring_from_id (glyph->u.cmp.id);
+         struct font_metrics metrics;
 
-      *right = cmp->rbearing - cmp->pixel_width;
-      *left = - cmp->lbearing;
+         composition_gstring_width (gstring, glyph->u.cmp.from,
+                                    glyph->u.cmp.to + 1, &metrics);
+         if (metrics.rbearing > metrics.width)
+           *right = metrics.rbearing - metrics.width;
+         if (metrics.lbearing < 0)
+           *left = - metrics.lbearing;
+       }
     }
 }
 
@@ -20142,7 +20131,7 @@ compute_overhangs_and_x (s, x, backward_p)
         INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);           \
         append_glyph_string (&HEAD, &TAIL, s);                            \
         s->x = (X);                                                       \
-        START = fill_glyph_string (s, face_id, START, END, overlaps);   \
+        START = fill_glyph_string (s, face_id, START, END, overlaps);     \
        }                                                                  \
      while (0)
 
@@ -20160,7 +20149,7 @@ compute_overhangs_and_x (s, x, backward_p)
   do {                                                                     \
     int face_id = (row)->glyphs[area][START].face_id;                      \
     struct face *base_face = FACE_FROM_ID (f, face_id);                            \
-    int cmp_id = (row)->glyphs[area][START].u.cmp_id;                      \
+    int cmp_id = (row)->glyphs[area][START].u.cmp.id;                      \
     struct composition *cmp = composition_table[cmp_id];                   \
     XChar2b *char2b;                                                       \
     struct glyph_string *first_s;                                          \
@@ -20176,7 +20165,7 @@ compute_overhangs_and_x (s, x, backward_p)
        INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);             \
        append_glyph_string (&(HEAD), &(TAIL), s);                          \
        s->cmp = cmp;                                                       \
-       s->gidx = n;                                                        \
+       s->cmp_from = n;                                                    \
        s->x = (X);                                                         \
        if (n == 0)                                                         \
          first_s = s;                                                      \
@@ -20188,6 +20177,28 @@ compute_overhangs_and_x (s, x, backward_p)
   } while (0)
 
 
+/* Add a glyph string for a glyph-string sequence to the list of strings
+   between HEAD and TAIL.  */
+
+#define BUILD_GSTRING_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
+  do {                                                                   \
+    int face_id;                                                         \
+    XChar2b *char2b;                                                     \
+    Lisp_Object gstring;                                                 \
+                                                                         \
+    face_id = (row)->glyphs[area][START].face_id;                        \
+    gstring = (composition_gstring_from_id                               \
+              ((row)->glyphs[area][START].u.cmp.id));                    \
+    s = (struct glyph_string *) alloca (sizeof *s);                      \
+    char2b = (XChar2b *) alloca ((sizeof *char2b)                        \
+                                * LGSTRING_GLYPH_LEN (gstring));         \
+    INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);              \
+    append_glyph_string (&(HEAD), &(TAIL), s);                           \
+    s->x = (X);                                                                  \
+    START = fill_gstring_glyph_string (s, face_id, START, END, overlaps); \
+  } while (0)
+
+
 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
    of AREA of glyph row ROW on window W between indices START and END.
    HL overrides the face for drawing glyph strings, e.g. it is
@@ -20198,47 +20209,50 @@ compute_overhangs_and_x (s, x, backward_p)
    to allocate glyph strings (because draw_glyphs can be called
    asynchronously).  */
 
-#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X)        \
-     do                                                                           \
-       {                                                                  \
-        HEAD = TAIL = NULL;                                               \
-        while (START < END)                                               \
-          {                                                               \
-             struct glyph *first_glyph = (row)->glyphs[area] + START;     \
-             switch (first_glyph->type)                                           \
-              {                                                           \
-              case CHAR_GLYPH:                                            \
-                 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL,        \
-                                          HL, X, LAST_X);                 \
-                break;                                                    \
-                                                                          \
-              case COMPOSITE_GLYPH:                                       \
-                 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL,    \
-                                              HL, X, LAST_X);             \
-                break;                                                    \
-                                                                          \
-              case STRETCH_GLYPH:                                         \
-                BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL,       \
-                                            HL, X, LAST_X);               \
-                break;                                                    \
-                                                                          \
-              case IMAGE_GLYPH:                                           \
-                BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL,         \
-                                          HL, X, LAST_X);                 \
-                break;                                                    \
-                                                                          \
-              default:                                                    \
-                abort ();                                                 \
-              }                                                           \
-                                                                          \
-            if (s)                                                        \
-              {                                                           \
-                set_glyph_string_background_width (s, START, LAST_X);     \
-                (X) += s->width;                                          \
-              }                                                           \
-            }                                                             \
-       }                                                                  \
-     while (0)
+#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X)     \
+  do                                                                   \
+    {                                                                  \
+      HEAD = TAIL = NULL;                                              \
+      while (START < END)                                              \
+       {                                                               \
+         struct glyph *first_glyph = (row)->glyphs[area] + START;      \
+         switch (first_glyph->type)                                    \
+           {                                                           \
+           case CHAR_GLYPH:                                            \
+             BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL,         \
+                                       HL, X, LAST_X);                 \
+             break;                                                    \
+                                                                       \
+           case COMPOSITE_GLYPH:                                       \
+             if (first_glyph->u.cmp.automatic)                         \
+               BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL,     \
+                                           HL, X, LAST_X);             \
+             else                                                      \
+               BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL,   \
+                                             HL, X, LAST_X);           \
+             break;                                                    \
+                                                                       \
+           case STRETCH_GLYPH:                                         \
+             BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL,       \
+                                         HL, X, LAST_X);               \
+             break;                                                    \
+                                                                       \
+           case IMAGE_GLYPH:                                           \
+             BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL,         \
+                                       HL, X, LAST_X);                 \
+             break;                                                    \
+                                                                       \
+           default:                                                    \
+             abort ();                                                 \
+           }                                                           \
+                                                                       \
+         if (s)                                                        \
+           {                                                           \
+             set_glyph_string_background_width (s, START, LAST_X);     \
+             (X) += s->width;                                          \
+           }                                                           \
+       }                                                               \
+    } while (0)
 
 
 /* Draw glyphs between START and END in AREA of ROW on window W,
@@ -20465,6 +20479,9 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
   for (s = head; s; s = s->next)
     FRAME_RIF (f)->draw_glyph_string (s);
 
+#ifndef HAVE_NS
+  /* When focus a sole frame and move horizontally, this sets on_p to 0
+     causing a failure to erase prev cursor position. */
   if (area == TEXT_AREA
       && !row->full_width_p
       /* When drawing overlapping rows, only the glyph strings'
@@ -20481,6 +20498,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
       notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
                                 row->y, MATRIX_ROW_BOTTOM_Y (row));
     }
+#endif
 
   /* Value is the x-position up to which drawn, relative to AREA of W.
      This doesn't include parts drawn because of overhangs.  */
@@ -20559,8 +20577,9 @@ append_glyph (it)
     IT_EXPAND_MATRIX_WIDTH (it, area);
 }
 
-/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
-   Called from x_produce_glyphs when IT->glyph_row is non-null.  */
+/* Store one glyph for the composition IT->cmp_it.id in
+   IT->glyph_row.  Called from x_produce_glyphs when IT->glyph_row is
+   non-null.  */
 
 static INLINE void
 append_composite_glyph (it)
@@ -20581,6 +20600,18 @@ append_composite_glyph (it)
       glyph->descent = it->descent;
       glyph->voffset = it->voffset;
       glyph->type = COMPOSITE_GLYPH;
+      if (it->cmp_it.ch < 0)
+       {
+         glyph->u.cmp.automatic = 0;
+         glyph->u.cmp.id = it->cmp_it.id;
+       }
+      else
+       {
+         glyph->u.cmp.automatic = 1;
+         glyph->u.cmp.id = it->cmp_it.id;
+         glyph->u.cmp.from = it->cmp_it.from;
+         glyph->u.cmp.to = it->cmp_it.to - 1;
+       }
       glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
       glyph->left_box_line_p = it->start_of_box_run_p;
@@ -20590,7 +20621,6 @@ append_composite_glyph (it)
       glyph->padding_p = 0;
       glyph->glyph_not_available_p = 0;
       glyph->face_id = it->face_id;
-      glyph->u.cmp_id = it->cmp_id;
       glyph->slice = null_glyph_slice;
       glyph->font_type = FONT_TYPE_UNKNOWN;
       ++it->glyph_row->used[area];
@@ -20712,13 +20742,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)
@@ -21100,9 +21123,12 @@ x_produce_glyphs (it)
        {
          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))
            {
+             struct charset *unibyte = CHARSET_FROM_ID (charset_unibyte);
+
+             /* get_next_display_element assures that this decoding
+                never fails.  */
+             it->char_to_display = DECODE_CHAR (unibyte, it->c);
              it->multibyte_p = 1;
              it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display,
                                           -1, Qnil);
@@ -21447,9 +21473,11 @@ x_produce_glyphs (it)
        }
       it->multibyte_p = saved_multibyte_p;
     }
-  else if (it->what == IT_COMPOSITION)
+  else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
     {
-      /* Note: A composition is represented as one glyph in the
+      /* A static compositoin.
+
+        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
@@ -21457,18 +21485,12 @@ x_produce_glyphs (it)
         the overall glyphs composed).  */
       struct face *face = FACE_FROM_ID (it->f, it->face_id);
       int boff;                        /* baseline offset */
-      struct composition *cmp = composition_table[it->cmp_id];
+      struct composition *cmp = composition_table[it->cmp_it.id];
       int glyph_len = cmp->glyph_len;
       struct font *font = face->font;
 
       it->nglyphs = 1;
 
-      if (cmp->method == COMPOSITION_WITH_GLYPH_STRING)
-       {
-         PREPARE_FACE_FOR_DISPLAY (it->f, face);
-         font_prepare_composition (cmp, it->f);
-       }
-      else
       /* If we have not yet calculated pixel size data of glyphs of
         the composition for the current face font, calculate them
         now.  Theoretically, we have to check all fonts for the
@@ -21488,7 +21510,6 @@ x_produce_glyphs (it)
          int lbearing, rbearing;
          int i, width, ascent, descent;
          int left_padded = 0, right_padded = 0;
-         int face_id;
          int c;
          XChar2b char2b;
          struct font_metrics *pcm;
@@ -21768,6 +21789,52 @@ x_produce_glyphs (it)
       if (it->descent < 0)
        it->descent = 0;
 
+      if (it->glyph_row)
+       append_composite_glyph (it);
+    }
+  else if (it->what == IT_COMPOSITION)
+    {
+      /* A dynamic (automatic) composition.  */
+      struct face *face = FACE_FROM_ID (it->f, it->face_id);
+      Lisp_Object gstring;
+      struct font_metrics metrics;
+
+      gstring = composition_gstring_from_id (it->cmp_it.id);
+      it->pixel_width
+       = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to,
+                                    &metrics);
+      if (it->glyph_row
+         && (metrics.lbearing < 0 || metrics.rbearing > metrics.width))
+       it->glyph_row->contains_overlapping_glyphs_p = 1;
+      it->ascent = it->phys_ascent = metrics.ascent;
+      it->descent = it->phys_descent = metrics.descent;
+      if (face->box != FACE_NO_BOX)
+       {
+         int thick = face->box_line_width;
+
+         if (thick > 0)
+           {
+             it->ascent += thick;
+             it->descent += thick;
+           }
+         else
+           thick = - thick;
+
+         if (it->start_of_box_run_p)
+           it->pixel_width += thick;
+         if (it->end_of_box_run_p)
+           it->pixel_width += thick;
+       }
+      /* If face has an overline, add the height of the overline
+        (1 pixel) and a 1 pixel margin to the character height.  */
+      if (face->overline_p)
+       it->ascent += 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_composite_glyph (it);
     }
@@ -22644,7 +22711,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)
@@ -22795,206 +22862,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;
 
-  first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-  if (charpos < MATRIX_ROW_START_CHARPOS (first))
+  xassert (NILP (display_string) || STRINGP (display_string));
+  xassert (NILP (before_string) || STRINGP (before_string));
+  xassert (NILP (after_string) || STRINGP (after_string));
+
+  /* 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));
 
-  row = row_containing_pos (w, charpos, first, NULL, 0);
+      /* 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];
+    }
+
+  /* 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
@@ -23721,8 +23769,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)
            {
@@ -23731,12 +23778,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.  */
@@ -23747,93 +23792,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);
-
-             /* 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);
-
-             /* 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))
@@ -23857,52 +23828,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;
+               }
+
+             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;
+                   }
 
-                 /* 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);
-
-                 /* Display it as active.  */
-                 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+                 mouse_face_from_buffer_pos (window, dpyinfo, pos,
+                                             XFASTINT (before),
+                                             XFASTINT (after),
+                                             before_string, after_string,
+                                             display_string);
                  cursor = No_Cursor;
                }
            }
@@ -24901,13 +24887,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'.
 
@@ -24984,9 +24970,10 @@ all the functions in the list are called, with the frame as argument.  */);
 
   DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
     doc: /* List of functions to call before redisplaying a window with scrolling.
-Each function is called with two arguments, the window
-and its new display-start position.  Note that the value of `window-end'
-is not valid when these functions are called.  */);
+Each function is called with two arguments, the window and its new
+display-start position.  Note that these functions are also called by
+`set-window-buffer'.  Also note that the value of `window-end' is not
+valid when these functions are called.  */);
   Vwindow_scroll_functions = Qnil;
 
   DEFVAR_LISP ("window-text-change-functions",
@@ -25151,26 +25138,28 @@ The enable predicate for a menu binding should check this variable.  */);
   inhibit_menubar_update = 0;
 
   DEFVAR_LISP ("wrap-prefix", &Vwrap_prefix,
-    doc: /* Prefix added to the beginning of all continuation lines at display-time.
-May be a string, an image, or a stretch-glyph such as used by the
-`display' text-property.
+    doc: /* Prefix prepended to all continuation lines at display time.
+The value may be a string, an image, or a stretch-glyph; it is
+interpreted in the same way as the value of a `display' text property.
 
-This variable is overridden by any `wrap-prefix' text-property.
+This variable is overridden by any `wrap-prefix' text or overlay
+property.
 
-To add a prefix to non-continuation lines, use the `line-prefix' variable.  */);
+To add a prefix to non-continuation lines, use `line-prefix'.  */);
   Vwrap_prefix = Qnil;
   staticpro (&Qwrap_prefix);
   Qwrap_prefix = intern ("wrap-prefix");
   Fmake_variable_buffer_local (Qwrap_prefix);
 
   DEFVAR_LISP ("line-prefix", &Vline_prefix,
-    doc: /* Prefix added to the beginning of all non-continuation lines at display-time.
-May be a string, an image, or a stretch-glyph such as used by the
-`display' text-property.
+    doc: /* Prefix prepended to all non-continuation lines at display time.
+The value may be a string, an image, or a stretch-glyph; it is
+interpreted in the same way as the value of a `display' text property.
 
-This variable is overridden by any `line-prefix' text-property.
+This variable is overridden by any `line-prefix' text or overlay
+property.
 
-To add a prefix to continuation lines, use the `wrap-prefix' variable.  */);
+To add a prefix to continuation lines, use `wrap-prefix'.  */);
   Vline_prefix = Qnil;
   staticpro (&Qline_prefix);
   Qline_prefix = intern ("line-prefix");