* dispextern.h (face_at_buffer_position, face_for_overlay_string)
[bpt/emacs.git] / src / xdisp.c
index 3a85ef9..6876f16 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 Free Software Foundation, Inc.
+                 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -239,6 +239,7 @@ extern Lisp_Object Qhelp_echo;
 
 Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
+Lisp_Object Qwindow_text_change_functions, Vwindow_text_change_functions;
 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
 Lisp_Object Qinhibit_point_motion_hooks;
 Lisp_Object QCeval, QCfile, QCdata, QCpropertize;
@@ -587,21 +588,12 @@ Lisp_Object Vmessage_log_max;
 
 static Lisp_Object Vmessages_buffer_name;
 
-/* Index 0 is the buffer that holds the current (desired) echo area message,
-   or nil if none is desired right now.
-
-   Index 1 is the buffer that holds the previously displayed echo area message,
-   or nil to indicate no message.  This is normally what's on the screen now.
-
-   These two can point to the same buffer.  That happens when the last
-   message output by the user (or made by echoing) has been displayed.  */
+/* Current, index 0, and last displayed echo area message.  Either
+   buffers from echo_buffers, or nil to indicate no message.  */
 
 Lisp_Object echo_area_buffer[2];
 
-/* Permanent pointers to the two buffers that are used for echo area
-   purposes.  Once the two buffers are made, and their pointers are
-   placed here, these two slots remain unchanged unless those buffers
-   need to be created afresh.  */
+/* The buffers referenced from echo_area_buffer.  */
 
 static Lisp_Object echo_buffer[2];
 
@@ -705,6 +697,7 @@ int trace_move;
    point visible.  */
 
 int automatic_hscrolling_p;
+Lisp_Object Qauto_hscroll_mode;
 
 /* How close to the margin can point get before the window is scrolled
    horizontally.  */
@@ -822,10 +815,6 @@ static int clear_face_cache_count;
 static int clear_image_cache_count;
 #endif
 
-/* Record the previous terminal frame we displayed.  */
-
-static struct frame *previous_terminal_frame;
-
 /* Non-zero while redisplay_internal is in progress.  */
 
 int redisplaying_p;
@@ -928,11 +917,12 @@ static int display_mode_lines P_ ((struct window *));
 static int display_mode_line P_ ((struct window *, enum face_id, Lisp_Object));
 static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object, Lisp_Object, int));
 static int store_mode_line_string P_ ((char *, Lisp_Object, int, int, int, Lisp_Object));
-static char *decode_mode_spec P_ ((struct window *, int, int, int, int *));
+static char *decode_mode_spec P_ ((struct window *, int, int, int, int *,
+                                  Lisp_Object *));
 static void display_menu_bar P_ ((struct window *));
 static int display_count_lines P_ ((int, int, int, int, int *));
 static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
-                              int, int, struct it *, int, int, int, int));
+                              EMACS_INT, EMACS_INT, struct it *, int, int, int, int));
 static void compute_line_metrics P_ ((struct it *));
 static void run_redisplay_end_trigger_hook P_ ((struct it *));
 static int get_overlay_strings P_ ((struct it *, int));
@@ -974,10 +964,10 @@ static void compute_stop_pos P_ ((struct it *));
 static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
                                    Lisp_Object));
 static int face_before_or_after_it_pos P_ ((struct it *, int));
-static int next_overlay_change P_ ((int));
+static EMACS_INT next_overlay_change P_ ((EMACS_INT));
 static int handle_single_display_spec P_ ((struct it *, Lisp_Object,
-                                          Lisp_Object, struct text_pos *,
-                                          int));
+                                          Lisp_Object, Lisp_Object,
+                                          struct text_pos *, int));
 static int underlying_face_id P_ ((struct it *));
 static int in_ellipses_for_invisible_text_p P_ ((struct display_pos *,
                                                 struct window *));
@@ -1341,6 +1331,28 @@ pos_visible_p (w, charpos, x, y, rtop, rbot, rowh, vpos)
          visible_p = 1;
       if (visible_p)
        {
+         Lisp_Object window, prop;
+
+         XSETWINDOW (window, w);
+         prop = Fget_char_property (make_number (it.position.charpos),
+                                    Qinvisible, window);
+
+         /* If charpos coincides with invisible text covered with an
+            ellipsis, use the first glyph of the ellipsis to compute
+            the pixel positions.  */
+         if (TEXT_PROP_MEANS_INVISIBLE (prop) == 2)
+           {
+             struct glyph_row *row = it.glyph_row;
+             struct glyph *glyph = row->glyphs[TEXT_AREA];
+             struct glyph *end = glyph + row->used[TEXT_AREA];
+             int x = row->x;
+
+             for (; glyph < end && glyph->charpos < charpos; glyph++)
+               x += glyph->pixel_width;
+
+             top_x = x;
+           }
+
          *x = top_x;
          *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
          *rtop = max (0, window_top_y - top_y);
@@ -2542,9 +2554,9 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
 
   /* If realized faces have been removed, e.g. because of face
      attribute changes of named faces, recompute them.  When running
-     in batch mode, the face cache of Vterminal_frame is null.  If
+     in batch mode, the face cache of the initial frame is null.  If
      we happen to get called, make a dummy face cache.  */
-  if (noninteractive && FRAME_FACE_CACHE (it->f) == NULL)
+  if (FRAME_FACE_CACHE (it->f) == NULL)
     init_frame_faces (it->f);
   if (FRAME_FACE_CACHE (it->f)->used == 0)
     recompute_basic_faces (it->f);
@@ -3090,16 +3102,18 @@ handle_stop (it)
          if (it->method == GET_FROM_DISPLAY_VECTOR)
            handle_overlay_change_p = 0;
 
-         /* Handle overlay changes.  */
+         /* Handle overlay changes.
+            This sets HANDLED to HANDLED_RECOMPUTE_PROPS
+            if it finds overlays.  */
          if (handle_overlay_change_p)
            handled = handle_overlay_change (it);
-
-         /* Determine where to stop next.  */
-         if (handled == HANDLED_NORMALLY)
-           compute_stop_pos (it);
        }
     }
   while (handled == HANDLED_RECOMPUTE_PROPS);
+
+  /* Determine where to stop next.  */
+  if (handled == HANDLED_NORMALLY)
+    compute_stop_pos (it);
 }
 
 
@@ -3210,12 +3224,12 @@ compute_stop_pos (it)
    follows.  This is like `next-overlay-change' but doesn't use
    xmalloc.  */
 
-static int
+static EMACS_INT
 next_overlay_change (pos)
-     int pos;
+     EMACS_INT pos;
 {
   int noverlays;
-  int endpos;
+  EMACS_INT endpos;
   Lisp_Object *overlays;
   int i;
 
@@ -3227,7 +3241,7 @@ next_overlay_change (pos)
   for (i = 0; i < noverlays; ++i)
     {
       Lisp_Object oend;
-      int oendpos;
+      EMACS_INT oendpos;
 
       oend = OVERLAY_END (overlays[i]);
       oendpos = OVERLAY_POSITION (oend);
@@ -3339,7 +3353,8 @@ static enum prop_handled
 handle_face_prop (it)
      struct it *it;
 {
-  int new_face_id, next_stop;
+  int new_face_id;
+  EMACS_INT next_stop;
 
   if (!STRINGP (it->string))
     {
@@ -3380,18 +3395,58 @@ handle_face_prop (it)
   else
     {
       int base_face_id, bufpos;
+      int i;
+      Lisp_Object from_overlay
+       = (it->current.overlay_string_index >= 0
+          ? it->string_overlays[it->current.overlay_string_index]
+          : Qnil);
+
+      /* See if we got to this string directly or indirectly from
+        an overlay property.  That includes the before-string or
+        after-string of an overlay, strings in display properties
+        provided by an overlay, their text properties, etc.
+
+        FROM_OVERLAY is the overlay that brought us here, or nil if none.  */
+      if (! NILP (from_overlay))
+       for (i = it->sp - 1; i >= 0; i--)
+         {
+           if (it->stack[i].current.overlay_string_index >= 0)
+             from_overlay
+               = it->string_overlays[it->stack[i].current.overlay_string_index];
+           else if (! NILP (it->stack[i].from_overlay))
+             from_overlay = it->stack[i].from_overlay;
 
-      if (it->current.overlay_string_index >= 0)
-       bufpos = IT_CHARPOS (*it);
+           if (!NILP (from_overlay))
+             break;
+         }
+
+      if (! NILP (from_overlay))
+       {
+         bufpos = IT_CHARPOS (*it);
+         /* For a string from an overlay, the base face depends
+            only on text properties and ignores overlays.  */
+         base_face_id
+           = face_for_overlay_string (it->w,
+                                      IT_CHARPOS (*it),
+                                      it->region_beg_charpos,
+                                      it->region_end_charpos,
+                                      &next_stop,
+                                      (IT_CHARPOS (*it)
+                                       + TEXT_PROP_DISTANCE_LIMIT),
+                                      0,
+                                      from_overlay);
+       }
       else
-       bufpos = 0;
+       {
+         bufpos = 0;
 
-      /* For strings from a buffer, i.e. overlay strings or strings
-        from a `display' property, use the face at IT's current
-        buffer position as the base face to merge with, so that
-        overlay strings appear in the same face as surrounding
-        text, unless they specify their own faces.  */
-      base_face_id = underlying_face_id (it);
+         /* For strings from a `display' property, use the face at
+            IT's current buffer position as the base face to merge
+            with, so that overlay strings appear in the same face as
+            surrounding text, unless they specify their own
+            faces.  */
+         base_face_id = underlying_face_id (it);
+       }
 
       new_face_id = face_at_string_position (it->w,
                                             it->string,
@@ -3467,7 +3522,7 @@ face_before_or_after_it_pos (it, before_p)
      int before_p;
 {
   int face_id, limit;
-  int next_check_charpos;
+  EMACS_INT next_check_charpos;
   struct text_pos pos;
 
   xassert (it->s == NULL);
@@ -3639,7 +3694,8 @@ handle_invisible_prop (it)
     }
   else
     {
-      int invis_p, newpos, next_stop, start_charpos;
+      int invis_p;
+      EMACS_INT newpos, next_stop, start_charpos;
       Lisp_Object pos, prop, overlay;
 
       /* First of all, is there invisible text at this position?  */
@@ -3736,6 +3792,10 @@ handle_invisible_prop (it)
                  it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
                }
               setup_for_ellipsis (it, 0);
+             /* Let the ellipsis display before
+                considering any properties of the following char.
+                Fixes jasonr@gnu.org 01 Oct 07 bug.  */
+             handled = HANDLED_RETURN;
             }
        }
     }
@@ -3797,7 +3857,7 @@ static enum prop_handled
 handle_display_prop (it)
      struct it *it;
 {
-  Lisp_Object prop, object;
+  Lisp_Object prop, object, overlay;
   struct text_pos *position;
   /* Nonzero if some property replaces the display of the text itself.  */
   int display_replaced_p = 0;
@@ -3825,10 +3885,12 @@ handle_display_prop (it)
   if (!it->string_from_display_prop_p)
     it->area = TEXT_AREA;
 
-  prop = Fget_char_property (make_number (position->charpos),
-                            Qdisplay, object);
+  prop = get_char_property_and_overlay (make_number (position->charpos),
+                                       Qdisplay, object, &overlay);
   if (NILP (prop))
     return HANDLED_NORMALLY;
+  /* Now OVERLAY is the overlay that gave us this property, or nil
+     if it was a text property.  */
 
   if (!STRINGP (it->string))
     object = it->w->buffer;
@@ -3850,22 +3912,35 @@ handle_display_prop (it)
     {
       for (; CONSP (prop); prop = XCDR (prop))
        {
-         if (handle_single_display_spec (it, XCAR (prop), object,
+         if (handle_single_display_spec (it, XCAR (prop), object, overlay,
                                          position, display_replaced_p))
-           display_replaced_p = 1;
+           {
+             display_replaced_p = 1;
+             /* If some text in a string is replaced, `position' no
+                longer points to the position of `object'.  */
+             if (STRINGP (object))
+               break;
+           }
        }
     }
   else if (VECTORP (prop))
     {
       int i;
       for (i = 0; i < ASIZE (prop); ++i)
-       if (handle_single_display_spec (it, AREF (prop, i), object,
+       if (handle_single_display_spec (it, AREF (prop, i), object, overlay,
                                        position, display_replaced_p))
-         display_replaced_p = 1;
+         {
+           display_replaced_p = 1;
+           /* If some text in a string is replaced, `position' no
+              longer points to the position of `object'.  */
+           if (STRINGP (object))
+             break;
+         }
     }
   else
     {
-      int ret = handle_single_display_spec (it, prop, object, position, 0);
+      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)
@@ -3907,6 +3982,9 @@ display_prop_end (it, object, start_pos)
    replaced text display with something else, for example an image;
    we ignore such properties after the first one has been processed.
 
+   OVERLAY is the overlay this `display' property came from,
+   or nil if it was a text property.
+
    If PROP is a `space' or `image' specification, and in some other
    cases too, set *POSITION to the position where the `display'
    property ends.
@@ -3916,11 +3994,12 @@ display_prop_end (it, object, start_pos)
    "something" is "nothing". */
 
 static int
-handle_single_display_spec (it, spec, object, position,
+handle_single_display_spec (it, spec, object, overlay, position,
                            display_replaced_before_p)
      struct it *it;
      Lisp_Object spec;
      Lisp_Object object;
+     Lisp_Object overlay;
      struct text_pos *position;
      int display_replaced_before_p;
 {
@@ -3969,7 +4048,7 @@ handle_single_display_spec (it, spec, object, position,
       && EQ (XCAR (spec), Qheight)
       && CONSP (XCDR (spec)))
     {
-      if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+      if (!FRAME_WINDOW_P (it->f))
        return 0;
 
       it->font_height = XCAR (XCDR (spec));
@@ -4030,12 +4109,12 @@ handle_single_display_spec (it, spec, object, position,
       return 0;
     }
 
-  /* Handle `(space_width WIDTH)'.  */
+  /* Handle `(space-width WIDTH)'.  */
   if (CONSP (spec)
       && EQ (XCAR (spec), Qspace_width)
       && CONSP (XCDR (spec)))
     {
-      if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+      if (!FRAME_WINDOW_P (it->f))
        return 0;
 
       value = XCAR (XCDR (spec));
@@ -4051,7 +4130,7 @@ handle_single_display_spec (it, spec, object, position,
     {
       Lisp_Object tem;
 
-      if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+      if (!FRAME_WINDOW_P (it->f))
        return 0;
 
       if (tem = XCDR (spec), CONSP (tem))
@@ -4077,7 +4156,7 @@ handle_single_display_spec (it, spec, object, position,
       && EQ (XCAR (spec), Qraise)
       && CONSP (XCDR (spec)))
     {
-      if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+      if (!FRAME_WINDOW_P (it->f))
        return 0;
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -4118,7 +4197,7 @@ handle_single_display_spec (it, spec, object, position,
       int face_id = DEFAULT_FACE_ID;
       int fringe_bitmap;
 
-      if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+      if (!FRAME_WINDOW_P (it->f))
        /* If we return here, POSITION has been advanced
           across the text with this property.  */
        return 0;
@@ -4154,6 +4233,7 @@ handle_single_display_spec (it, spec, object, position,
       it->position = start_pos;
       it->object = NILP (object) ? it->w->buffer : object;
       it->method = GET_FROM_IMAGE;
+      it->from_overlay = Qnil;
       it->face_id = face_id;
 
       /* Say that we haven't consumed the characters with
@@ -4167,7 +4247,7 @@ handle_single_display_spec (it, spec, object, position,
          it->left_user_fringe_face_id = face_id;
        }
       else
-       {
+        {
          it->right_user_fringe_bitmap = fringe_bitmap;
          it->right_user_fringe_face_id = face_id;
        }
@@ -4212,9 +4292,9 @@ handle_single_display_spec (it, spec, object, position,
 
   valid_p = (STRINGP (value)
 #ifdef HAVE_WINDOW_SYSTEM
-            || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
+             || (FRAME_WINDOW_P (it->f) && valid_image_p (value))
 #endif /* not HAVE_WINDOW_SYSTEM */
-            || (CONSP (value) && EQ (XCAR (value), Qspace)));
+             || (CONSP (value) && EQ (XCAR (value), Qspace)));
 
   if (valid_p && !display_replaced_before_p)
     {
@@ -4224,6 +4304,7 @@ handle_single_display_spec (it, spec, object, position,
       it->position = *position;
       push_it (it);
       it->position = save_pos;
+      it->from_overlay = overlay;
 
       if (NILP (location))
        it->area = TEXT_AREA;
@@ -4250,13 +4331,16 @@ handle_single_display_spec (it, spec, object, position,
          /* Say that we haven't consumed the characters with
             `display' property yet.  The call to pop_it in
             set_iterator_to_next will clean this up.  */
-         *position = start_pos;
+         if (BUFFERP (object))
+           it->current.pos = start_pos;
        }
       else if (CONSP (value) && EQ (XCAR (value), Qspace))
        {
          it->method = GET_FROM_STRETCH;
          it->object = value;
-         *position = it->position = start_pos;
+         it->position = start_pos;
+         if (BUFFERP (object))
+           it->current.pos = start_pos;
        }
 #ifdef HAVE_WINDOW_SYSTEM
       else
@@ -4270,7 +4354,8 @@ handle_single_display_spec (it, spec, object, position,
          /* Say that we haven't consumed the characters with
             `display' property yet.  The call to pop_it in
             set_iterator_to_next will clean this up.  */
-         *position = start_pos;
+         if (BUFFERP (object))
+           it->current.pos = start_pos;
        }
 #endif /* HAVE_WINDOW_SYSTEM */
 
@@ -4284,7 +4369,7 @@ handle_single_display_spec (it, spec, object, position,
 }
 
 
-/* Check if SPEC is a display specification value whose text should be
+/* Check if SPEC is a display sub-property value whose text should be
    treated as intangible.  */
 
 static int
@@ -4494,103 +4579,86 @@ handle_auto_composed_prop (it)
 
   if (FUNCTIONP (Vauto_composition_function))
     {
-      Lisp_Object val;
-      EMACS_INT pos, this_pos;
+      Lisp_Object val = Qnil;
+      EMACS_INT pos, limit = -1;
 
       if (STRINGP (it->string))
        pos = IT_STRING_CHARPOS (*it);
       else
        pos = IT_CHARPOS (*it);
-      this_pos = pos;
 
-      val =Fget_char_property (make_number (pos), Qauto_composed, it->string);
+      val = Fget_text_property (make_number (pos), Qauto_composed, it->string);
       if (! NILP (val))
        {
-         Lisp_Object limit = Qnil, next;
-         
-         /* As Fnext_single_char_property_change is very slow, we
-            limit the search to the current line.  */
-         if (STRINGP (it->string))
-           limit = make_number (SCHARS (it->string));
-         else
-           limit = make_number (find_next_newline_no_quit (pos, 1));
+         Lisp_Object cmp_prop;
+         EMACS_INT cmp_start, cmp_end;
 
-         next = (Fnext_single_property_change
-                 (make_number (pos), Qauto_composed, it->string, limit));
-         if (XINT (next) < XINT (limit))
+#ifdef USE_FONT_BACKEND
+         if (enable_font_backend
+             && 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)
            {
-             /* 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.  */
-             int charpos = XINT (next) - 1, bytepos, c;
+             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;
+           }
+#endif
+         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))
-               {
-                 bytepos = string_char_to_byte (it->string, charpos);
-                 c = SDATA (it->string)[bytepos];
-               }
+               limit = SCHARS (it->string);
              else
-               {
-                 bytepos = CHAR_TO_BYTE (charpos);
-                 c = FETCH_BYTE (bytepos);
-               }
-             if (c != '\n')
-               /* If the last character is not newline, it may be
-                  composed with the following characters.  */
-               val = Qnil, pos = charpos + 1;
+               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))
        {
-         int count = SPECPDL_INDEX ();
-         Lisp_Object args[4];
-
-         args[0] = Vauto_composition_function;
-         specbind (Qauto_composition_function, Qnil);
-         args[1] = make_number (pos);
-         args[2] = it->string;
-#ifdef USE_FONT_BACKEND
-         if (enable_font_backend)
+         if (limit < 0)
+           limit = (STRINGP (it->string) ? SCHARS (it->string)
+                    : find_next_newline_no_quit (pos, 1));
+         if (pos < limit)
            {
-             struct face *face = FACE_FROM_ID (it->f, it->face_id);
-             int c;
-
-             if (STRINGP (it->string))
-               {
-                 EMACS_INT pos_byte = IT_STRING_BYTEPOS (*it);
-                 const unsigned char *s = SDATA (it->string) + pos_byte;
+             int count = SPECPDL_INDEX ();
+             Lisp_Object args[5];
 
-                 if (STRING_MULTIBYTE (it->string))
-                   it->c = STRING_CHAR (s, 0);
-                 else
-                   it->c = *s;
-               }
+             args[0] = Vauto_composition_function;
+             specbind (Qauto_composition_function, Qnil);
+             args[1] = make_number (pos);
+             args[2] = make_number (limit);
+#ifdef USE_FONT_BACKEND
+             if (enable_font_backend)
+               args[3] = it->window;
              else
-               {
-                 EMACS_INT pos_byte = IT_BYTEPOS (*it);
-
-                 it->c = FETCH_CHAR (pos_byte);
-               }
-             args[3] = font_at (it->c, this_pos, face, it->w, it->string);
-           }
-         else
 #endif /* USE_FONT_BACKEND */
-           args[3] = Qnil;
-         safe_call (4, args);
-         unbind_to (count, Qnil);
-
-         if (this_pos == pos)
-           {
-             val = Fget_char_property (args[1], Qauto_composed, it->string);
-             /* Return HANDLED_RECOMPUTE_PROPS only if function composed
-                something.  This avoids an endless loop if they failed to
-                fontify the text for which reason ever.  */
-             if (! NILP (val))
-               handled = HANDLED_RECOMPUTE_PROPS;
+               args[3] = Qnil;
+             args[4] = it->string;
+             safe_call (5, args);
+             unbind_to (count, Qnil);
            }
-         else
-           handled = HANDLED_RECOMPUTE_PROPS;
        }
     }
 
@@ -4610,15 +4678,20 @@ handle_composition_prop (it)
 
   if (STRINGP (it->string))
     {
+      unsigned char *s;
+
       pos = IT_STRING_CHARPOS (*it);
       pos_byte = IT_STRING_BYTEPOS (*it);
       string = it->string;
+      s = SDATA (string) + pos_byte;
+      it->c = STRING_CHAR (s, 0);
     }
   else
     {
       pos = IT_CHARPOS (*it);
       pos_byte = IT_BYTEPOS (*it);
       string = Qnil;
+      it->c = FETCH_CHAR (pos_byte);
     }
 
   /* If there's a valid composition and point is not inside of the
@@ -4671,11 +4744,10 @@ handle_composition_prop (it)
 #ifdef USE_FONT_BACKEND
          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);
-
-             it->c = XINT (LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, 0)));
            }
          else
 #endif /* USE_FONT_BACKEND */
@@ -5003,7 +5075,10 @@ load_overlay_strings (it, charpos)
   i = 0;
   j = it->current.overlay_string_index;
   while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
-    it->overlay_strings[i++] = entries[j++].string;
+    {
+      it->overlay_strings[i] = entries[j].string;
+      it->string_overlays[i++] = entries[j++].overlay;
+    }
 
   CHECK_IT (it);
 }
@@ -5049,6 +5124,7 @@ get_overlay_strings_1 (it, charpos, compute_stop_p)
         string.  */
       IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
       it->string = it->overlay_strings[0];
+      it->from_overlay = Qnil;
       it->stop_charpos = 0;
       xassert (STRINGP (it->string));
       it->end_charpos = SCHARS (it->string);
@@ -5102,6 +5178,7 @@ push_it (it)
   p->face_id = it->face_id;
   p->string = it->string;
   p->method = it->method;
+  p->from_overlay = it->from_overlay;
   switch (p->method)
     {
     case GET_FROM_IMAGE:
@@ -5155,6 +5232,7 @@ pop_it (it)
   it->current = p->current;
   it->position = p->position;
   it->string = p->string;
+  it->from_overlay = p->from_overlay;
   if (NILP (it->string))
     SET_TEXT_POS (it->current.string_pos, -1, -1);
   it->method = p->method;
@@ -5343,7 +5421,7 @@ back_to_previous_visible_line_start (it)
       {
        struct it it2;
        int pos;
-       int beg, end;
+       EMACS_INT beg, end;
        Lisp_Object val, overlay;
 
        /* If newline is part of a composition, continue from start of composition */
@@ -5922,7 +6000,7 @@ get_next_display_element (it)
       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);
     }
 
@@ -7695,8 +7773,8 @@ message2_nolog (m, nbytes, multibyte)
       do_pending_window_change (0);
       echo_area_display (1);
       do_pending_window_change (0);
-      if (frame_up_to_date_hook != 0 && ! gc_in_progress)
-       (*frame_up_to_date_hook) (f);
+      if (FRAME_TERMINAL (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+       (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
     }
 }
 
@@ -7799,8 +7877,8 @@ message3_nolog (m, nbytes, multibyte)
       do_pending_window_change (0);
       echo_area_display (1);
       do_pending_window_change (0);
-      if (frame_up_to_date_hook != 0 && ! gc_in_progress)
-       (*frame_up_to_date_hook) (f);
+      if (FRAME_TERMINAL (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+       (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
     }
 }
 
@@ -8038,6 +8116,10 @@ ensure_echo_area_buffers ()
    WHICH > 0 means use echo_area_buffer[1].  If that is nil, choose a
    suitable buffer from echo_buffer[] and clear it.
 
+   If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
+   that the current message becomes the last displayed one, make
+   choose a suitable buffer for echo_area_buffer[0], and clear it.
+
    Value is what FN returns.  */
 
 static int
@@ -8062,6 +8144,17 @@ with_echo_area_buffer (w, which, fn, a1, a2, a3, a4)
     this_one = 0, the_other = 1;
   else if (which > 0)
     this_one = 1, the_other = 0;
+  else
+    {
+      this_one = 0, the_other = 1;
+      clear_buffer_p = 1;
+
+      /* We need a fresh one in case the current echo buffer equals
+        the one containing the last displayed echo area message.  */
+      if (!NILP (echo_area_buffer[this_one])
+         && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
+       echo_area_buffer[this_one] = Qnil;
+    }
 
   /* Choose a suitable buffer from echo_buffer[] is we don't
      have one.  */
@@ -8127,7 +8220,7 @@ with_echo_area_buffer_unwind_data (w)
      struct window *w;
 {
   int i = 0;
-  Lisp_Object vector;
+  Lisp_Object vector, tmp;
 
   /* Reduce consing by keeping one vector in
      Vwith_echo_area_save_vector.  */
@@ -8137,22 +8230,22 @@ with_echo_area_buffer_unwind_data (w)
   if (NILP (vector))
     vector = Fmake_vector (make_number (7), Qnil);
 
-  XSETBUFFER (AREF (vector, i), current_buffer); ++i;
-  AREF (vector, i) = Vdeactivate_mark, ++i;
-  AREF (vector, i) = make_number (windows_or_buffers_changed), ++i;
+  XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
+  ASET (vector, i, Vdeactivate_mark); ++i;
+  ASET (vector, i, make_number (windows_or_buffers_changed)); ++i;
 
   if (w)
     {
-      XSETWINDOW (AREF (vector, i), w); ++i;
-      AREF (vector, i) = w->buffer; ++i;
-      AREF (vector, i) = make_number (XMARKER (w->pointm)->charpos); ++i;
-      AREF (vector, i) = make_number (XMARKER (w->pointm)->bytepos); ++i;
+      XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
+      ASET (vector, i, w->buffer); ++i;
+      ASET (vector, i, make_number (XMARKER (w->pointm)->charpos)); ++i;
+      ASET (vector, i, make_number (XMARKER (w->pointm)->bytepos)); ++i;
     }
   else
     {
       int end = i + 4;
       for (; i < end; ++i)
-       AREF (vector, i) = Qnil;
+       ASET (vector, i, Qnil);
     }
 
   xassert (i == ASIZE (vector));
@@ -8383,7 +8476,7 @@ resize_mini_window_1 (a1, exactly, a3, a4)
 }
 
 
-/* Resize mini-window W to fit the size of its contents.  EXACT:P
+/* Resize mini-window W to fit the size of its contents.  EXACT_P
    means size the window exactly to the size needed.  Otherwise, it's
    only enlarged until W's buffer is empty.
 
@@ -8699,7 +8792,7 @@ set_message (s, string, nbytes, multibyte_p)
     = ((s && multibyte_p)
        || (STRINGP (string) && STRING_MULTIBYTE (string)));
 
-  with_echo_area_buffer (0, 0, set_message_1,
+  with_echo_area_buffer (0, -1, set_message_1,
                         (EMACS_INT) s, string, nbytes, multibyte_p);
   message_buf_print = 0;
   help_echo_showing_p = 0;
@@ -8729,7 +8822,6 @@ set_message_1 (a1, a2, nbytes, multibyte_p)
 
   /* Insert new message at BEG.  */
   TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
-  Ferase_buffer ();
 
   if (STRINGP (string))
     {
@@ -8874,17 +8966,13 @@ echo_area_display (update_frame_p)
   if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
     return 0;
 
-/* The terminal frame is used as the first Emacs frame on the Mac OS.  */
-#ifndef MAC_OS8
 #ifdef HAVE_WINDOW_SYSTEM
-  /* When Emacs starts, selected_frame may be a visible terminal
-     frame, even if we run under a window system.  If we let this
-     through, a message would be displayed on the terminal.  */
-  if (EQ (selected_frame, Vterminal_frame)
-      && !NILP (Vwindow_system))
+  /* When Emacs starts, selected_frame may be the initial terminal
+     frame.  If we let this through, a message would be displayed on
+     the terminal.  */
+  if (FRAME_INITIAL_P (XFRAME (selected_frame)))
     return 0;
 #endif /* HAVE_WINDOW_SYSTEM */
-#endif
 
   /* Redraw garbaged frames.  */
   if (frame_garbaged)
@@ -8932,7 +9020,7 @@ echo_area_display (update_frame_p)
                 Can do with a display update of the echo area,
                 unless we displayed some mode lines.  */
              update_single_window (w, 1);
-             rif->flush_display (f);
+             FRAME_RIF (f)->flush_display (f);
            }
          else
            update_frame (f, 1, 1);
@@ -8947,8 +9035,10 @@ echo_area_display (update_frame_p)
   else if (!EQ (mini_window, selected_window))
     windows_or_buffers_changed++;
 
-  /* The current message is now also the last one displayed.  */
+  /* Last displayed message is now the current message.  */
   echo_area_buffer[1] = echo_area_buffer[0];
+  /* Inform read_char that we're not echoing.  */
+  echo_message_buffer = Qnil;
 
   /* Prevent redisplay optimization in redisplay_internal by resetting
      this_line_start_pos.  This is done because the mini-buffer now
@@ -9006,7 +9096,7 @@ static Lisp_Object
 format_mode_line_unwind_data (obuf, save_proptrans)
      struct buffer *obuf;
 {
-  Lisp_Object vector;
+  Lisp_Object vector, tmp;
 
   /* Reduce consing by keeping one vector in
      Vwith_echo_area_save_vector.  */
@@ -9016,17 +9106,18 @@ format_mode_line_unwind_data (obuf, save_proptrans)
   if (NILP (vector))
     vector = Fmake_vector (make_number (7), Qnil);
 
-  AREF (vector, 0) = make_number (mode_line_target);
-  AREF (vector, 1) = make_number (MODE_LINE_NOPROP_LEN (0));
-  AREF (vector, 2) = mode_line_string_list;
-  AREF (vector, 3) = (save_proptrans ? mode_line_proptrans_alist : Qt);
-  AREF (vector, 4) = mode_line_string_face;
-  AREF (vector, 5) = mode_line_string_face_prop;
+  ASET (vector, 0, make_number (mode_line_target));
+  ASET (vector, 1, make_number (MODE_LINE_NOPROP_LEN (0)));
+  ASET (vector, 2, mode_line_string_list);
+  ASET (vector, 3, save_proptrans ? mode_line_proptrans_alist : Qt);
+  ASET (vector, 4, mode_line_string_face);
+  ASET (vector, 5, mode_line_string_face_prop);
 
   if (obuf)
-    XSETBUFFER (AREF (vector, 6), obuf);
+    XSETBUFFER (tmp, obuf);
   else
-    AREF (vector, 6) = Qnil;
+    tmp = Qnil;
+  ASET (vector, 6, tmp);
 
   return vector;
 }
@@ -9046,7 +9137,7 @@ unwind_format_mode_line (vector)
   if (!NILP (AREF (vector, 6)))
     {
       set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
-      AREF (vector, 6) = Qnil;
+      ASET (vector, 6, Qnil);
     }
 
   Vmode_line_unwind_vector = vector;
@@ -9502,8 +9593,8 @@ x_cursor_to (vpos, hpos, y, x)
     {
       BLOCK_INPUT;
       display_and_set_cursor (w, 1, hpos, vpos, x, y);
-      if (rif->flush_display_optional)
-       rif->flush_display_optional (SELECTED_FRAME ());
+      if (FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
+       FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (SELECTED_FRAME ());
       UNBLOCK_INPUT;
     }
 }
@@ -10472,11 +10563,12 @@ hscroll_window_tree (window)
          /* Scroll when cursor is inside this scroll margin.  */
          h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
 
-         if ((XFASTINT (w->hscroll)
-              && w->cursor.x <= h_margin)
-             || (cursor_row->enabled_p
-                 && cursor_row->truncated_on_right_p
-                 && (w->cursor.x >= text_area_width - h_margin)))
+         if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->buffer))
+             && ((XFASTINT (w->hscroll)
+                  && w->cursor.x <= h_margin)
+                 || (cursor_row->enabled_p
+                     && cursor_row->truncated_on_right_p
+                     && (w->cursor.x >= text_area_width - h_margin))))
            {
              struct it it;
              int hscroll;
@@ -10566,16 +10658,9 @@ static int
 hscroll_windows (window)
      Lisp_Object window;
 {
-  int hscrolled_p;
-
-  if (automatic_hscrolling_p)
-    {
-      hscrolled_p = hscroll_window_tree (window);
-      if (hscrolled_p)
-       clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
-    }
-  else
-    hscrolled_p = 0;
+  int hscrolled_p = hscroll_window_tree (window);
+  if (hscrolled_p)
+    clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
   return hscrolled_p;
 }
 
@@ -10955,31 +11040,24 @@ select_frame_for_redisplay (frame)
   Lisp_Object tail, sym, val;
   Lisp_Object old = selected_frame;
 
+  xassert (FRAMEP (frame) && FRAME_LIVE_P (XFRAME (frame)));
+
   selected_frame = frame;
 
-  for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
-    if (CONSP (XCAR (tail))
-       && (sym = XCAR (XCAR (tail)),
-           SYMBOLP (sym))
-       && (sym = indirect_variable (sym),
-           val = SYMBOL_VALUE (sym),
-           (BUFFER_LOCAL_VALUEP (val)
-            || SOME_BUFFER_LOCAL_VALUEP (val)))
-       && XBUFFER_LOCAL_VALUE (val)->check_frame)
-      /* Use find_symbol_value rather than Fsymbol_value
-        to avoid an error if it is void.  */
-      find_symbol_value (sym);
-
-  for (tail = XFRAME (old)->param_alist; CONSP (tail); tail = XCDR (tail))
-    if (CONSP (XCAR (tail))
-       && (sym = XCAR (XCAR (tail)),
-           SYMBOLP (sym))
-       && (sym = indirect_variable (sym),
-           val = SYMBOL_VALUE (sym),
-           (BUFFER_LOCAL_VALUEP (val)
-            || SOME_BUFFER_LOCAL_VALUEP (val)))
-       && XBUFFER_LOCAL_VALUE (val)->check_frame)
-      find_symbol_value (sym);
+  do
+    {
+      for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
+       if (CONSP (XCAR (tail))
+           && (sym = XCAR (XCAR (tail)),
+               SYMBOLP (sym))
+           && (sym = indirect_variable (sym),
+               val = SYMBOL_VALUE (sym),
+               (BUFFER_LOCAL_VALUEP (val)))
+           && XBUFFER_LOCAL_VALUE (val)->check_frame)
+         /* Use find_symbol_value rather than Fsymbol_value
+            to avoid an error if it is void.  */
+         find_symbol_value (sym);
+    } while (!EQ (frame, old) && (frame = old, 1));
 }
 
 
@@ -11011,6 +11089,7 @@ redisplay_internal (preserve_echo_area)
   int count, count1;
   struct frame *sf;
   int polling_stopped_here = 0;
+  Lisp_Object old_frame = selected_frame;
 
   /* Non-zero means redisplay has to consider all windows on all
      frames.  Zero means, only selected_window is considered.  */
@@ -11072,6 +11151,14 @@ redisplay_internal (preserve_echo_area)
   }
 
  retry:
+  if (!EQ (old_frame, selected_frame)
+      && FRAME_LIVE_P (XFRAME (old_frame)))
+    /* When running redisplay, we play a bit fast-and-loose and allow e.g.
+       selected_frame and selected_window to be temporarily out-of-sync so
+       when we come back here via `goto retry', we need to resync because we
+       may need to run Elisp code (via prepare_menu_bars).  */
+    select_frame_for_redisplay (old_frame);
+
   pause = 0;
   reconsider_clip_changes (w, current_buffer);
   last_escape_glyph_frame = NULL;
@@ -11092,17 +11179,16 @@ redisplay_internal (preserve_echo_area)
   if (face_change_count)
     ++windows_or_buffers_changed;
 
-  if (! FRAME_WINDOW_P (sf)
-      && previous_terminal_frame != sf)
+  if (FRAME_TERMCAP_P (sf)
+      && FRAME_TTY (sf)->previous_frame != sf)
     {
-      /* Since frames on an ASCII terminal share the same display
-        area, displaying a different frame means redisplay the whole
-        thing.  */
+      /* Since frames on a single ASCII terminal share the same
+        display area, displaying a different frame means redisplay
+        the whole thing.  */
       windows_or_buffers_changed++;
       SET_FRAME_GARBAGED (sf);
-      XSETFRAME (Vterminal_frame, sf);
+      FRAME_TTY (sf)->previous_frame = sf;
     }
-  previous_terminal_frame = sf;
 
   /* Set the visible flags for all frames.  Do this before checking
      for resized or garbaged frames; they want to know if their frames
@@ -11124,6 +11210,7 @@ redisplay_internal (preserve_echo_area)
       }
   }
 
+
   /* Notice any pending interrupt request to change frame size.  */
   do_pending_window_change (1);
 
@@ -11485,7 +11572,7 @@ redisplay_internal (preserve_echo_area)
        {
          struct frame *f = XFRAME (frame);
 
-         if (FRAME_WINDOW_P (f) || f == sf)
+         if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
            {
              if (! EQ (frame, selected_frame))
                /* Select the frame, for the sake of frame-local
@@ -11494,16 +11581,16 @@ redisplay_internal (preserve_echo_area)
 
              /* Mark all the scroll bars to be removed; we'll redeem
                 the ones we want when we redisplay their windows.  */
-             if (condemn_scroll_bars_hook)
-               condemn_scroll_bars_hook (f);
+             if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
+               FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
 
              if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
                redisplay_windows (FRAME_ROOT_WINDOW (f));
 
              /* Any scroll bars which redisplay_windows should have
                 nuked should now go away.  */
-             if (judge_scroll_bars_hook)
-               judge_scroll_bars_hook (f);
+             if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
+               FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
 
              /* If fonts changed, display again.  */
              /* ??? rms: I suspect it is a mistake to jump all the way
@@ -11550,12 +11637,12 @@ redisplay_internal (preserve_echo_area)
          FOR_EACH_FRAME (tail, frame)
            {
              struct frame *f = XFRAME (frame);
-             if (f->updated_p)
-               {
-                 mark_window_display_accurate (f->root_window, 1);
-                 if (frame_up_to_date_hook)
-                   frame_up_to_date_hook (f);
-               }
+              if (f->updated_p)
+                {
+                  mark_window_display_accurate (f->root_window, 1);
+                  if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
+                    FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
+                }
            }
        }
     }
@@ -11640,8 +11727,8 @@ redisplay_internal (preserve_echo_area)
          /* Say overlay arrows are up to date.  */
          update_overlay_arrows (1);
 
-         if (frame_up_to_date_hook != 0)
-           frame_up_to_date_hook (sf);
+         if (FRAME_TERMINAL (sf)->frame_up_to_date_hook != 0)
+           FRAME_TERMINAL (sf)->frame_up_to_date_hook (sf);
        }
 
       update_mode_lines = 0;
@@ -11705,13 +11792,7 @@ redisplay_internal (preserve_echo_area)
 #ifdef HAVE_WINDOW_SYSTEM
       if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
        {
-         Lisp_Object tail, frame;
-         FOR_EACH_FRAME (tail, frame)
-           {
-             struct frame *f = XFRAME (frame);
-             if (FRAME_WINDOW_P (f))
-               clear_image_cache (f, 0);
-           }
+         clear_image_caches (Qnil);
          clear_image_cache_count = 0;
        }
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -11751,8 +11832,9 @@ redisplay_preserve_echo_area (from_where)
   else
     redisplay_internal (1);
 
-  if (rif != NULL && rif->flush_display_optional)
-    rif->flush_display_optional (NULL);
+  if (FRAME_RIF (SELECTED_FRAME ()) != NULL
+      && FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
+    FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (NULL);
 }
 
 
@@ -11760,7 +11842,8 @@ redisplay_preserve_echo_area (from_where)
    redisplay_internal.  Reset redisplaying_p to the value it had
    before redisplay_internal was called, and clear
    prevent_freeing_realized_faces_p.  It also selects the previously
-   selected frame.  */
+   selected frame, unless it has been deleted (by an X connection
+   failure during redisplay, for example).  */
 
 static Lisp_Object
 unwind_redisplay (val)
@@ -11771,7 +11854,8 @@ unwind_redisplay (val)
   old_redisplaying_p = XCAR (val);
   redisplaying_p = XFASTINT (old_redisplaying_p);
   old_frame = XCDR (val);
-  if (! EQ (old_frame, selected_frame))
+  if (! EQ (old_frame, selected_frame)
+      && FRAME_LIVE_P (XFRAME (old_frame)))
     select_frame_for_redisplay (old_frame);
   return Qnil;
 }
@@ -12608,7 +12692,7 @@ compute_window_start_on_continuation_line (w)
             minimum distance from the old window start.  */
          pos = it.current.pos;
          min_distance = INFINITY;
-         while ((distance = abs (CHARPOS (start_pos) - IT_CHARPOS (it))),
+         while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
                 distance < min_distance)
            {
              min_distance = distance;
@@ -12909,7 +12993,9 @@ set_vertical_scroll_bar (w)
     start = end = whole = 0;
 
   /* Indicate what this scroll bar ought to be displaying now.  */
-  set_vertical_scroll_bar_hook (w, end - start, whole, start);
+  if (FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
+    (*FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
+      (w, end - start, whole, start);
 }
 
 
@@ -12955,8 +13041,7 @@ redisplay_window (window, just_this_one_p)
   *w->desired_matrix->method = 0;
 #endif
 
-  specbind (Qinhibit_point_motion_hooks, Qt);
-
+ restart:
   reconsider_clip_changes (w, buffer);
 
   /* Has the mode line to be updated?  */
@@ -13007,10 +13092,6 @@ redisplay_window (window, just_this_one_p)
   /* Really select the buffer, for the sake of buffer-local
      variables.  */
   set_buffer_internal_1 (XBUFFER (w->buffer));
-  SET_TEXT_POS (opoint, PT, PT_BYTE);
-
-  beg_unchanged = BEG_UNCHANGED;
-  end_unchanged = END_UNCHANGED;
 
   current_matrix_up_to_date_p
     = (!NILP (w->window_end_valid)
@@ -13019,6 +13100,23 @@ redisplay_window (window, just_this_one_p)
        && XFASTINT (w->last_modified) >= MODIFF
        && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
 
+  /* Run the window-bottom-change-functions
+     if it is possible that the text on the screen has changed
+     (either due to modification of the text, or any other reason).  */
+  if (!current_matrix_up_to_date_p
+      && !NILP (Vwindow_text_change_functions))
+    {
+      safe_run_hooks (Qwindow_text_change_functions);
+      goto restart;
+    }
+
+  beg_unchanged = BEG_UNCHANGED;
+  end_unchanged = END_UNCHANGED;
+
+  SET_TEXT_POS (opoint, PT, PT_BYTE);
+
+  specbind (Qinhibit_point_motion_hooks, Qt);
+
   buffer_unchanged_p
     = (!NILP (w->window_end_valid)
        && !current_buffer->clip_changed
@@ -13628,20 +13726,22 @@ redisplay_window (window, just_this_one_p)
         display_menu_bar (w);
 
 #ifdef HAVE_WINDOW_SYSTEM
+      if (FRAME_WINDOW_P (f))
+        {
 #if defined (USE_GTK) || USE_MAC_TOOLBAR
-      redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
+          redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
 #else
-      redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
-        && (FRAME_TOOL_BAR_LINES (f) > 0
-            || !NILP (Vauto_resize_tool_bars));
-
+          redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
+            && (FRAME_TOOL_BAR_LINES (f) > 0
+                || !NILP (Vauto_resize_tool_bars));
 #endif
 
-      if (redisplay_tool_bar_p && redisplay_tool_bar (f))
-       {
-         extern int ignore_mouse_drag_p;
-         ignore_mouse_drag_p = 1;
-       }
+          if (redisplay_tool_bar_p && redisplay_tool_bar (f))
+           {
+             extern int ignore_mouse_drag_p;
+             ignore_mouse_drag_p = 1;
+           }
+        }
 #endif
     }
 
@@ -13675,7 +13775,8 @@ redisplay_window (window, just_this_one_p)
 
       /* Note that we actually used the scroll bar attached to this
         window, so it shouldn't be deleted at the end of redisplay.  */
-      redeem_scroll_bar_hook (w);
+      if (FRAME_TERMINAL (f)->redeem_scroll_bar_hook)
+        (*FRAME_TERMINAL (f)->redeem_scroll_bar_hook) (w);
     }
 
   /* Restore current_buffer and value of point in it.  */
@@ -13944,10 +14045,10 @@ try_window_reusing_current_matrix (w)
          if (run.height > 0 && run.current_y != run.desired_y)
            {
              update_begin (f);
-             rif->update_window_begin_hook (w);
-             rif->clear_window_mouse_face (w);
-             rif->scroll_run_hook (w, &run);
-             rif->update_window_end_hook (w, 0, 0);
+             FRAME_RIF (f)->update_window_begin_hook (w);
+             FRAME_RIF (f)->clear_window_mouse_face (w);
+             FRAME_RIF (f)->scroll_run_hook (w, &run);
+             FRAME_RIF (f)->update_window_end_hook (w, 0, 0);
              update_end (f);
            }
 
@@ -14116,10 +14217,10 @@ try_window_reusing_current_matrix (w)
       if (run.height)
        {
          update_begin (f);
-         rif->update_window_begin_hook (w);
-         rif->clear_window_mouse_face (w);
-         rif->scroll_run_hook (w, &run);
-         rif->update_window_end_hook (w, 0, 0);
+         FRAME_RIF (f)->update_window_begin_hook (w);
+         FRAME_RIF (f)->clear_window_mouse_face (w);
+         FRAME_RIF (f)->scroll_run_hook (w, &run);
+         FRAME_RIF (f)->update_window_end_hook (w, 0, 0);
          update_end (f);
        }
 
@@ -14320,8 +14421,7 @@ find_first_unchanged_at_end_row (w, delta, delta_bytes)
 
   /* Display must not have been paused, otherwise the current matrix
      is not up to date.  */
-  if (NILP (w->window_end_valid))
-    abort ();
+  eassert (!NILP (w->window_end_valid));
 
   /* A value of window_end_pos >= END_UNCHANGED means that the window
      end is in the range of changed text.  If so, there is no
@@ -14372,8 +14472,7 @@ find_first_unchanged_at_end_row (w, delta, delta_bytes)
        }
     }
 
-  if (row_found && !MATRIX_ROW_DISPLAYS_TEXT_P (row_found))
-    abort ();
+  eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
 
   return row_found;
 }
@@ -14569,7 +14668,7 @@ try_window_id (w)
 
   /* Window must either use window-based redisplay or be full width.  */
   if (!FRAME_WINDOW_P (f)
-      && (!line_ins_del_ok
+      && (!FRAME_LINE_INS_DEL_OK (f)
          || !WINDOW_FULL_WIDTH_P (w)))
     GIVE_UP (4);
 
@@ -14978,10 +15077,10 @@ try_window_id (w)
 
       if (FRAME_WINDOW_P (f))
        {
-         rif->update_window_begin_hook (w);
-         rif->clear_window_mouse_face (w);
-         rif->scroll_run_hook (w, &run);
-         rif->update_window_end_hook (w, 0, 0);
+         FRAME_RIF (f)->update_window_begin_hook (w);
+         FRAME_RIF (f)->clear_window_mouse_face (w);
+         FRAME_RIF (f)->scroll_run_hook (w, &run);
+         FRAME_RIF (f)->update_window_end_hook (w, 0, 0);
        }
       else
        {
@@ -14999,36 +15098,36 @@ try_window_id (w)
            {
              /* Scroll last_unchanged_at_beg_row to the end of the
                 window down dvpos lines.  */
-             set_terminal_window (end);
+             set_terminal_window (f, end);
 
              /* On dumb terminals delete dvpos lines at the end
                 before inserting dvpos empty lines.  */
-             if (!scroll_region_ok)
-               ins_del_lines (end - dvpos, -dvpos);
+             if (!FRAME_SCROLL_REGION_OK (f))
+               ins_del_lines (f, end - dvpos, -dvpos);
 
              /* Insert dvpos empty lines in front of
                  last_unchanged_at_beg_row.  */
-             ins_del_lines (from, dvpos);
+             ins_del_lines (f, from, dvpos);
            }
          else if (dvpos < 0)
            {
              /* Scroll up last_unchanged_at_beg_vpos to the end of
                 the window to last_unchanged_at_beg_vpos - |dvpos|.  */
-             set_terminal_window (end);
+             set_terminal_window (f, end);
 
              /* Delete dvpos lines in front of
                 last_unchanged_at_beg_vpos.  ins_del_lines will set
                 the cursor to the given vpos and emit |dvpos| delete
                 line sequences.  */
-             ins_del_lines (from + dvpos, dvpos);
+             ins_del_lines (f, from + dvpos, dvpos);
 
              /* On a dumb terminal insert dvpos empty lines at the
                  end.  */
-             if (!scroll_region_ok)
-               ins_del_lines (end + dvpos, -dvpos);
+             if (!FRAME_SCROLL_REGION_OK (f))
+               ins_del_lines (f, end + dvpos, -dvpos);
            }
 
-         set_terminal_window (0);
+         set_terminal_window (f, 0);
        }
 
       update_end (f);
@@ -16602,7 +16701,7 @@ display_menu_bar (w)
 
   /* Don't do all this for graphical frames.  */
 #ifdef HAVE_NTGUI
-  if (!NILP (Vwindow_system))
+  if (FRAME_W32_P (f))
     return;
 #endif
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
@@ -16668,7 +16767,7 @@ display_menu_bar (w)
        break;
 
       /* Remember where item was displayed.  */
-      AREF (items, i + 3) = make_number (it.hpos);
+      ASET (items, i + 3, make_number (it.hpos));
 
       /* Display the item, pad with one space.  */
       if (it.current_x < it.last_visible_x)
@@ -16833,10 +16932,10 @@ display_mode_line (w, face_id, format)
   /* Temporarily make frame's keyboard the current kboard so that
      kboard-local variables in the mode_line_format will get the right
      values.  */
-  push_frame_kboard (it.f);
+  push_kboard (FRAME_KBOARD (it.f));
   record_unwind_save_match_data ();
   display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
-  pop_frame_kboard ();
+  pop_kboard ();
 
   unbind_to (count, Qnil);
 
@@ -17123,14 +17222,14 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                    int multibyte;
                    int bytepos, charpos;
                    unsigned char *spec;
+                   Lisp_Object string;
 
                    bytepos = percent_position;
                    charpos = (STRING_MULTIBYTE (elt)
                               ? string_byte_to_char (elt, bytepos)
                               : bytepos);
-
-                   spec
-                     = decode_mode_spec (it->w, c, field, prec, &multibyte);
+                   spec = decode_mode_spec (it->w, c, field, prec, &multibyte,
+                                            &string);
 
                    switch (mode_line_target)
                      {
@@ -17140,19 +17239,24 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                        break;
                      case MODE_LINE_STRING:
                        {
-                         int len = strlen (spec);
-                         Lisp_Object tem = make_string (spec, len);
+                         if (NILP (string))
+                           {
+                             int len = strlen (spec);
+                             string = make_string (spec, len);
+                           }
                          props = Ftext_properties_at (make_number (charpos), elt);
                          /* Should only keep face property in props */
-                         n += store_mode_line_string (NULL, tem, 0, field, prec, props);
+                         n += store_mode_line_string (NULL, string, 0, field, prec, props);
                        }
                        break;
                      case MODE_LINE_DISPLAY:
                        {
                          int nglyphs_before, nwritten;
 
+                         if (STRINGP (string))
+                           spec = NULL;
                          nglyphs_before = it->glyph_row->used[TEXT_AREA];
-                         nwritten = display_string (spec, Qnil, elt,
+                         nwritten = display_string (spec, string, elt,
                                                     charpos, 0, it,
                                                     field, prec, 0,
                                                     multibyte);
@@ -17505,7 +17609,9 @@ are the selected window and the window's buffer).  */)
     buffer = w->buffer;
   CHECK_BUFFER (buffer);
 
-  if (NILP (format))
+  /* Make formatting the modeline a non-op when noninteractive, otherwise
+     there will be problems later caused by a partially initialized frame.  */
+  if (NILP (format) || noninteractive)
     return empty_unibyte_string;
 
   if (no_props)
@@ -17551,9 +17657,9 @@ are the selected window and the window's buffer).  */)
        = (NILP (face) ? Qnil : Fcons (Qface, Fcons (face, Qnil)));
     }
 
-  push_frame_kboard (it.f);
+  push_kboard (FRAME_KBOARD (it.f));
   display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
-  pop_frame_kboard ();
+  pop_kboard ();
 
   if (no_props)
     {
@@ -17814,18 +17920,19 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
 
 static char *
-decode_mode_spec (w, c, field_width, precision, multibyte)
+decode_mode_spec (w, c, field_width, precision, multibyte, string)
      struct window *w;
      register int c;
      int field_width, precision;
      int *multibyte;
+     Lisp_Object *string;
 {
   Lisp_Object obj;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
   struct buffer *b = current_buffer;
 
-  obj = Qnil;
+  *string = obj = Qnil;
   *multibyte = 0;
 
   switch (c)
@@ -17990,8 +18097,8 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
            goto no_value;
          }
 
-       if (!NILP (w->base_line_number)
-           && !NILP (w->base_line_pos)
+       if (INTEGERP (w->base_line_number)
+           && INTEGERP (w->base_line_pos)
            && XFASTINT (w->base_line_pos) <= startpos)
          {
            line = XFASTINT (w->base_line_number);
@@ -18188,9 +18295,11 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
          {
            /* No need to mention EOL here--the terminal never needs
               to do EOL conversion.  */
-           p = decode_mode_spec_coding (CODING_ID_NAME (keyboard_coding.id),
+           p = decode_mode_spec_coding (CODING_ID_NAME
+                                        (FRAME_KEYBOARD_CODING (f)->id),
                                         p, 0);
-           p = decode_mode_spec_coding (CODING_ID_NAME (terminal_coding.id),
+           p = decode_mode_spec_coding (CODING_ID_NAME
+                                        (FRAME_TERMINAL_CODING (f)->id),
                                         p, 0);
          }
        p = decode_mode_spec_coding (b->buffer_file_coding_system,
@@ -18216,6 +18325,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
   if (STRINGP (obj))
     {
       *multibyte = STRING_MULTIBYTE (obj);
+      *string = obj;
       return (char *) SDATA (obj);
     }
   else
@@ -18374,8 +18484,8 @@ display_string (string, lisp_string, face_string, face_string_pos,
      unsigned char *string;
      Lisp_Object lisp_string;
      Lisp_Object face_string;
-     int face_string_pos;
-     int start;
+     EMACS_INT face_string_pos;
+     EMACS_INT start;
      struct it *it;
      int field_width, precision, max_x;
      int multibyte;
@@ -18393,7 +18503,7 @@ display_string (string, lisp_string, face_string, face_string_pos,
      from LISP_STRING, if that's given.  */
   if (STRINGP (face_string))
     {
-      int endptr;
+      EMACS_INT endptr;
       struct face *face;
 
       it->face_id
@@ -18704,6 +18814,8 @@ calc_pixel_width_or_height (res, it, prop, font, width_p, align_to)
   if (NILP (prop))
     return OK_PIXELS (0);
 
+  xassert (FRAME_LIVE_P (it->f));
+
   if (SYMBOLP (prop))
     {
       if (SCHARS (SYMBOL_NAME (prop)) == 2)
@@ -18820,7 +18932,8 @@ calc_pixel_width_or_height (res, it, prop, font, width_p, align_to)
       if (SYMBOLP (car))
        {
 #ifdef HAVE_WINDOW_SYSTEM
-         if (valid_image_p (prop))
+         if (FRAME_WINDOW_P (it->f)
+             && valid_image_p (prop))
            {
              int id = lookup_image (it->f, prop);
              struct image *img = IMAGE_FROM_ID (it->f, id);
@@ -19070,7 +19183,7 @@ get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
       else
        STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
        /* Maybe encode the character in *CHAR2B.  */
-      rif->encode_char (c, char2b, font_info, charset, NULL);
+      FRAME_RIF (f)->encode_char (c, char2b, font_info, charset, NULL);
     }
 
   /* Make sure X resources of the face are allocated.  */
@@ -19151,8 +19264,8 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
          if (CHARSET_ID (charset) != charset_ascii)
            {
              glyph->font_type
-               = rif->encode_char (glyph->u.ch, char2b, font_info, charset,
-                                   two_byte_p);
+               = FRAME_RIF (f)->encode_char (glyph->u.ch, char2b, font_info,
+                                             charset, two_byte_p);
            }
        }
     }
@@ -19194,16 +19307,16 @@ fill_composite_glyph_string (s, base_face, overlaps)
                s->cmp->hash_index * 2);
 
       s->face = base_face;
-      s->font_info = s->cmp->font;
+      s->font_info = base_face->font_info;
       s->font = s->font_info->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 (LGLYPH_FROM (g)))
+         if (NILP (g))
            break;
-         code = XUINT (LGLYPH_CODE (g));
+         code = LGLYPH_CODE (g);
           store_pos = s->char2b + i;
          STORE_XCHAR2B (store_pos, code >> 8, code & 0xFF);
        }
@@ -19226,7 +19339,8 @@ fill_composite_glyph_string (s, base_face, overlaps)
 
          if (c != '\t')
            {
-             int face_id = FACE_FOR_CHAR (s->f, base_face, c, -1, Qnil);
+             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);
@@ -19297,7 +19411,7 @@ fill_glyph_string (s, face_id, start, end, overlaps)
   glyph = s->row->glyphs[s->area] + start;
   last = s->row->glyphs[s->area] + end;
   voffset = glyph->voffset;
-
+  s->padding_p = glyph->padding_p;
   glyph_not_available_p = glyph->glyph_not_available_p;
 
   while (glyph < last
@@ -19316,7 +19430,8 @@ fill_glyph_string (s, face_id, start, end, overlaps)
       ++s->nchars;
       xassert (s->nchars <= end - start);
       s->width += glyph->pixel_width;
-      ++glyph;
+      if (glyph++->padding_p != s->padding_p)
+       break;
     }
 
   s->font = s->face->font;
@@ -19407,7 +19522,8 @@ fill_stretch_glyph_string (s, row, area, start, end)
 }
 
 static XCharStruct *
-get_per_char_metric (font, font_info, char2b, font_type)
+get_per_char_metric (f, font, font_info, char2b, font_type)
+     struct frame *f;
      XFontStruct *font;
      struct font_info *font_info;
      XChar2b *char2b;
@@ -19433,7 +19549,7 @@ get_per_char_metric (font, font_info, char2b, font_type)
       return &pcm_value;
     }
 #endif /* USE_FONT_BACKEND */
-  return rif->per_char_metric (font, char2b, font_type);
+  return FRAME_RIF (f)->per_char_metric (font, char2b, font_type);
 }
 
 /* EXPORT for RIF:
@@ -19461,7 +19577,7 @@ x_get_glyph_overhangs (glyph, f, left, right)
       font = face->font;
       font_info = FONT_INFO_FROM_FACE (f, face);
       if (font  /* ++KFS: Should this be font_info ?  */
-         && (pcm = get_per_char_metric (font, font_info, &char2b, glyph->font_type)))
+         && (pcm = get_per_char_metric (f, font, font_info, &char2b, glyph->font_type)))
        {
          if (pcm->rbearing > pcm->width)
            *right = pcm->rbearing - pcm->width;
@@ -19635,8 +19751,8 @@ compute_overhangs_and_x (s, x, backward_p)
     {
       while (s)
        {
-         if (rif->compute_glyph_string_overhangs)
-           rif->compute_glyph_string_overhangs (s);
+         if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
+           FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
          x -= s->width;
          s->x = x;
          s = s->prev;
@@ -19646,8 +19762,8 @@ compute_overhangs_and_x (s, x, backward_p)
     {
       while (s)
        {
-         if (rif->compute_glyph_string_overhangs)
-           rif->compute_glyph_string_overhangs (s);
+         if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
+           FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
          s->x = x;
          x += s->width;
          s = s->next;
@@ -19763,7 +19879,6 @@ compute_overhangs_and_x (s, x, backward_p)
     int n;                                                                 \
                                                                            \
     char2b = (XChar2b *) alloca ((sizeof *char2b) * cmp->glyph_len);       \
-    base_face = base_face->ascii_face;                                     \
                                                                            \
     /* Make glyph_strings for each glyph sequence that is drawable by      \
        the same face, and append them to HEAD/TAIL.  */                            \
@@ -19923,9 +20038,9 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
       struct glyph_string *h, *t;
 
       /* Compute overhangs for all glyph strings.  */
-      if (rif->compute_glyph_string_overhangs)
+      if (FRAME_RIF (f)->compute_glyph_string_overhangs)
        for (s = head; s; s = s->next)
-         rif->compute_glyph_string_overhangs (s);
+         FRAME_RIF (f)->compute_glyph_string_overhangs (s);
 
       /* Prepend glyph strings for glyphs in front of the first glyph
         string that are overwritten because of the first glyph
@@ -20004,7 +20119,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
 
   /* Draw all strings.  */
   for (s = head; s; s = s->next)
-    rif->draw_glyph_string (s);
+    FRAME_RIF (f)->draw_glyph_string (s);
 
   if (area == TEXT_AREA
       && !row->full_width_p
@@ -20069,7 +20184,18 @@ append_glyph (it)
     {
       glyph->charpos = CHARPOS (it->position);
       glyph->object = it->object;
-      glyph->pixel_width = it->pixel_width;
+      if (it->pixel_width > 0)
+       {
+         glyph->pixel_width = it->pixel_width;
+         glyph->padding_p = 0;
+       }
+      else
+       {
+         /* Assure at least 1-pixel width.  Otherwise, cursor can't
+            be displayed correctly.  */
+         glyph->pixel_width = 1;
+         glyph->padding_p = 1;
+       }
       glyph->ascent = it->ascent;
       glyph->descent = it->descent;
       glyph->voffset = it->voffset;
@@ -20079,7 +20205,6 @@ append_glyph (it)
       glyph->right_box_line_p = it->end_of_box_run_p;
       glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
                                      || it->phys_descent > it->descent);
-      glyph->padding_p = 0;
       glyph->glyph_not_available_p = it->glyph_not_available_p;
       glyph->face_id = it->face_id;
       glyph->u.ch = it->char_to_display;
@@ -20263,9 +20388,9 @@ produce_image_glyph (it)
        }
 
       if (it->start_of_box_run_p && slice.x == 0)
-       it->pixel_width += abs (face->box_line_width);
+       it->pixel_width += eabs (face->box_line_width);
       if (it->end_of_box_run_p && slice.x + slice.width == img->width)
-       it->pixel_width += abs (face->box_line_width);
+       it->pixel_width += eabs (face->box_line_width);
     }
 
   take_vertical_position_into_account (it);
@@ -20693,20 +20818,20 @@ x_produce_glyphs (it)
 
          it->nglyphs = 1;
 
-         pcm = get_per_char_metric (font, font_info, &char2b,
-                                     FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
-
-         if (it->override_ascent >= 0)
-           {
-             it->ascent = it->override_ascent;
-             it->descent = it->override_descent;
-             boff = it->override_boff;
-           }
-         else
-           {
-             it->ascent = FONT_BASE (font) + boff;
-             it->descent = FONT_DESCENT (font) - boff;
-           }
+         pcm = get_per_char_metric (it->f, font, font_info, &char2b,
+                                    FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
+
+         if (it->override_ascent >= 0)
+           {
+             it->ascent = it->override_ascent;
+             it->descent = it->override_descent;
+             boff = it->override_boff;
+           }
+         else
+           {
+             it->ascent = FONT_BASE (font) + boff;
+             it->descent = FONT_DESCENT (font) - boff;
+           }
 
          if (pcm)
            {
@@ -20802,6 +20927,10 @@ x_produce_glyphs (it)
              if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
                it->glyph_row->contains_overlapping_glyphs_p = 1;
            }
+         if (! stretched_p && it->pixel_width == 0)
+           /* We assure that all visible glyphs have at least 1-pixel
+              width.  */
+           it->pixel_width = 1;
        }
       else if (it->char_to_display == '\n')
        {
@@ -20924,8 +21053,8 @@ x_produce_glyphs (it)
             multiplying the width of font by the width of the
             character.  */
 
-         pcm = get_per_char_metric (font, font_info, &char2b,
-                                     FONT_TYPE_FOR_MULTIBYTE (font, it->c));
+           pcm = get_per_char_metric (it->f, font, font_info, &char2b,
+                                      FONT_TYPE_FOR_MULTIBYTE (font, it->c));
 
          if (font_not_found_p || !pcm)
            {
@@ -20979,8 +21108,17 @@ x_produce_glyphs (it)
 
          take_vertical_position_into_account (it);
 
+         if (it->ascent < 0)
+           it->ascent = 0;
+         if (it->descent < 0)
+           it->descent = 0;
+
          if (it->glyph_row)
            append_glyph (it);
+         if (it->pixel_width == 0)
+           /* We assure that all visible glyphs have at least 1-pixel
+              width.  */
+           it->pixel_width = 1;
        }
       it->multibyte_p = saved_multibyte_p;
     }
@@ -21003,8 +21141,8 @@ x_produce_glyphs (it)
 #ifdef USE_FONT_BACKEND
       if (cmp->method == COMPOSITION_WITH_GLYPH_STRING)
        {
-         if (! cmp->font || cmp->font != font)
-           font_prepare_composition (cmp);
+         PREPARE_FACE_FOR_DISPLAY (it->f, face);
+         font_prepare_composition (cmp, it->f);
        }
       else
 #endif /* USE_FONT_BACKEND */
@@ -21073,7 +21211,7 @@ x_produce_glyphs (it)
            {
              get_char_face_and_encoding (it->f, c, it->face_id,
                                          &char2b, it->multibyte_p, 0);
-             pcm = get_per_char_metric (font, font_info, &char2b,
+             pcm = get_per_char_metric (it->f, font, font_info, &char2b,
                                         FONT_TYPE_FOR_MULTIBYTE (font, c));
            }
 
@@ -21140,7 +21278,7 @@ x_produce_glyphs (it)
                    this_boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
                  get_char_face_and_encoding (it->f, ch, face_id,
                                              &char2b, it->multibyte_p, 0);
-                 pcm = get_per_char_metric (font, font_info, &char2b,
+                 pcm = get_per_char_metric (it->f, font, font_info, &char2b,
                                             FONT_TYPE_FOR_MULTIBYTE (font,
                                                                      ch));
                }
@@ -21205,7 +21343,7 @@ x_produce_glyphs (it)
                              + grefx * (rightmost - leftmost) / 2
                              - nrefx * width / 2
                              + xoff);
-                 
+
                      btm = ((grefy == 0 ? highest
                              : grefy == 1 ? 0
                              : grefy == 2 ? lowest
@@ -21284,7 +21422,6 @@ x_produce_glyphs (it)
       it->pixel_width = cmp->pixel_width;
       it->ascent = it->phys_ascent = cmp->ascent;
       it->descent = it->phys_descent = cmp->descent;
-
       if (face->box != FACE_NO_BOX)
        {
          int thick = face->box_line_width;
@@ -21309,6 +21446,10 @@ x_produce_glyphs (it)
        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);
@@ -21417,8 +21558,8 @@ x_insert_glyphs (start, len)
   frame_x = window_box_left (w, updated_area) + output_cursor.x;
   frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
 
-  rif->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
-                               line_height, shift_by_width);
+  FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
+                                          line_height, shift_by_width);
 
   /* Write the glyphs.  */
   hpos = start - row->glyphs[updated_area];
@@ -21500,8 +21641,8 @@ x_clear_end_of_line (to_x)
   if (to_x > from_x && to_y > from_y)
     {
       BLOCK_INPUT;
-      rif->clear_frame_area (f, from_x, from_y,
-                            to_x - from_x, to_y - from_y);
+      FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
+                                       to_x - from_x, to_y - from_y);
       UNBLOCK_INPUT;
     }
 }
@@ -21644,7 +21785,7 @@ get_window_cursor_type (w, glyph, width, active_cursor)
       non_selected = 1;
     }
 
-  /* Nonselected window or nonselected frame.  */
+  /* Detect a nonselected window or nonselected frame.  */
   else if (w != XWINDOW (f->selected_window)
 #ifdef HAVE_WINDOW_SYSTEM
           || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
@@ -21663,13 +21804,6 @@ get_window_cursor_type (w, glyph, width, active_cursor)
   if (NILP (b->cursor_type))
     return NO_CURSOR;
 
-  /* Use cursor-in-non-selected-windows for non-selected window or frame.  */
-  if (non_selected)
-    {
-      alt_cursor = b->cursor_in_non_selected_windows;
-      return get_specified_cursor_type (alt_cursor, width);
-    }
-
   /* Get the normal cursor type for this window.  */
   if (EQ (b->cursor_type, Qt))
     {
@@ -21679,6 +21813,21 @@ get_window_cursor_type (w, glyph, width, active_cursor)
   else
     cursor_type = get_specified_cursor_type (b->cursor_type, width);
 
+  /* Use cursor-in-non-selected-windows instead
+     for non-selected window or frame.  */
+  if (non_selected)
+    {
+      alt_cursor = b->cursor_in_non_selected_windows;
+      if (!EQ (Qt, alt_cursor))
+       return get_specified_cursor_type (alt_cursor, width);
+      /* t means modify the normal cursor type.  */
+      if (cursor_type == FILLED_BOX_CURSOR)
+       cursor_type = HOLLOW_BOX_CURSOR;
+      else if (cursor_type == BAR_CURSOR && *width > 1)
+       --*width;
+      return cursor_type;
+    }
+
   /* Use normal cursor if not blinked off.  */
   if (!w->cursor_off_p)
     {
@@ -22014,7 +22163,7 @@ erase_phys_cursor (w)
       x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, max (x, left_x));
 
       if (width > 0)
-      rif->clear_frame_area (f, x, y, width, cursor_row->visible_height);
+       FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
     }
 
   /* Erase the cursor by redrawing the character underneath it.  */
@@ -22111,9 +22260,9 @@ display_and_set_cursor (w, on, hpos, vpos, x, y)
       w->phys_cursor.vpos = vpos;
     }
 
-  rif->draw_window_cursor (w, glyph_row, x, y,
-                          new_cursor_type, new_cursor_width,
-                          on, active_cursor);
+  FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
+                                     new_cursor_type, new_cursor_width,
+                                     on, active_cursor);
 }
 
 
@@ -22262,11 +22411,11 @@ show_mouse_face (dpyinfo, draw)
 
   /* Change the mouse cursor.  */
   if (draw == DRAW_NORMAL_TEXT && !EQ (dpyinfo->mouse_face_window, f->tool_bar_window))
-    rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
+    FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
   else if (draw == DRAW_MOUSE_FACE)
-    rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
+    FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
   else
-    rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
+    FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
 }
 
 /* EXPORT:
@@ -22574,8 +22723,8 @@ fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
                goto found;
              }
            else if (best_glyph == NULL
-                    || ((abs (g->charpos - pos)
-                        < abs (best_glyph->charpos - pos))
+                    || ((eabs (g->charpos - pos)
+                        < eabs (best_glyph->charpos - pos))
                         && (right_p
                             ? g->charpos < pos
                             : g->charpos > pos)))
@@ -22705,7 +22854,6 @@ on_hot_spot_p (hot_spot, x, y)
          return inside;
        }
     }
-  /* If we don't understand the format, pretend we're not in the hot-spot.  */
   return 0;
 }
 
@@ -22785,7 +22933,7 @@ define_frame_cursor1 (f, cursor, pointer)
     }
 
   if (cursor != No_Cursor)
-    rif->define_frame_cursor (f, cursor);
+    FRAME_RIF (f)->define_frame_cursor (f, cursor);
 }
 
 /* Take proper action when mouse has moved to the mode or header line
@@ -22932,7 +23080,7 @@ note_mode_line_or_margin_highlight (window, x, y, area)
          int gpos;
          int gseq_length;
          int total_pixel_width;
-         int ignore;
+         EMACS_INT ignore;
 
          int vpos, hpos;
 
@@ -23284,7 +23432,7 @@ note_mouse_highlight (f, x, y)
              /* Find the range of text around this char that
                 should be active.  */
              Lisp_Object before, after;
-             int ignore;
+             EMACS_INT ignore;
 
              before = Foverlay_start (overlay);
              after = Foverlay_end (overlay);
@@ -23318,7 +23466,7 @@ note_mouse_highlight (f, x, y)
              /* Find the range of text around this char that
                 should be active.  */
              Lisp_Object before, after, beginning, end;
-             int ignore;
+             EMACS_INT ignore;
 
              beginning = Fmarker_position (w->start);
              end = make_number (BUF_Z (XBUFFER (object))
@@ -23358,7 +23506,7 @@ note_mouse_highlight (f, x, y)
          else if (!NILP (mouse_face) && STRINGP (object))
            {
              Lisp_Object b, e;
-             int ignore;
+             EMACS_INT ignore;
 
              b = Fprevious_single_property_change (make_number (pos + 1),
                                                    Qmouse_face,
@@ -23405,7 +23553,7 @@ note_mouse_highlight (f, x, y)
                {
                  Lisp_Object before = Foverlay_start (overlay);
                  Lisp_Object after = Foverlay_end (overlay);
-                 int ignore;
+                 EMACS_INT ignore;
 
                  /* Note that we might not be able to find position
                     BEFORE in the glyph matrix if the overlay is
@@ -23742,6 +23890,24 @@ phys_cursor_in_rect_p (w, r)
 {
   XRectangle cr, result;
   struct glyph *cursor_glyph;
+  struct glyph_row *row;
+
+  if (w->phys_cursor.vpos >= 0
+      && w->phys_cursor.vpos < w->current_matrix->nrows
+      && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
+         row->enabled_p)
+      && row->cursor_in_fringe_p)
+    {
+      /* Cursor is in the fringe.  */
+      cr.x = window_box_right_offset (w,
+                                     (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                                      ? RIGHT_MARGIN_AREA
+                                      : TEXT_AREA));
+      cr.y = row->y;
+      cr.width = WINDOW_RIGHT_FRINGE_WIDTH (w);
+      cr.height = row->height;
+      return x_intersect_rectangles (&cr, r, &result);
+    }
 
   cursor_glyph = get_phys_cursor_glyph (w);
   if (cursor_glyph)
@@ -23756,8 +23922,8 @@ phys_cursor_in_rect_p (w, r)
         I assume the effect is the same -- and this is portable.  */
       return x_intersect_rectangles (&cr, r, &result);
     }
-  else
-    return 0;
+  /* If we don't understand the format, pretend we're not in the hot-spot.  */
+  return 0;
 }
 
 
@@ -23769,6 +23935,8 @@ void
 x_draw_vertical_border (w)
      struct window *w;
 {
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+
   /* We could do better, if we knew what type of scroll-bar the adjacent
      windows (on either side) have...  But we don't :-(
      However, I think this works ok.  ++KFS 2003-04-25 */
@@ -23789,9 +23957,9 @@ x_draw_vertical_border (w)
       y1 -= 1;
 
       if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
-       x1 -= 1;
+        x1 -= 1;
 
-      rif->draw_vertical_window_border (w, x1, y0, y1);
+      FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
     }
   else if (!WINDOW_LEFTMOST_P (w)
           && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
@@ -23802,9 +23970,9 @@ x_draw_vertical_border (w)
       y1 -= 1;
 
       if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
-       x0 -= 1;
+        x0 -= 1;
 
-      rif->draw_vertical_window_border (w, x0, y0, y1);
+      FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
     }
 }
 
@@ -24173,6 +24341,9 @@ syms_of_xdisp ()
   staticpro (&Qwindow_scroll_functions);
   Qwindow_scroll_functions = intern ("window-scroll-functions");
 
+  staticpro (&Qwindow_text_change_functions);
+  Qwindow_text_change_functions = intern ("window-text-change-functions");
+
   staticpro (&Qredisplay_end_trigger_functions);
   Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
 
@@ -24381,8 +24552,12 @@ If you want scrolling to always be a line at a time, you should set
 
   DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
     doc: /* *Scroll up to this many lines, to bring point back on screen.
-A value of zero means to scroll the text to center point vertically
-in the window.  */);
+If point moves off-screen, redisplay will scroll by up to
+`scroll-conservatively' lines in order to bring point just barely
+onto the screen again.   If that cannot be done, then redisplay
+recenters point as usual.
+
+A value of zero means always recenter point if it moves off screen.  */);
   scroll_conservatively = 0;
 
   DEFVAR_INT ("scroll-margin", &scroll_margin,
@@ -24480,6 +24655,11 @@ and its new display-start position.  Note that the value of `window-end'
 is not valid when these functions are called.  */);
   Vwindow_scroll_functions = Qnil;
 
+  DEFVAR_LISP ("window-text-change-functions",
+              &Vwindow_text_change_functions,
+    doc: /* Functions to call in redisplay when text in the window might change.  */);
+  Vwindow_text_change_functions = Qnil;
+
   DEFVAR_LISP ("redisplay-end-trigger-functions", &Vredisplay_end_trigger_functions,
     doc: /* Functions called when redisplay of a window reaches the end trigger.
 Each function is called with two arguments, the window and the end trigger value.
@@ -24500,7 +24680,10 @@ Any other value means to autoselect window instantaneously when the
 mouse pointer enters it.
 
 Autoselection selects the minibuffer only if it is active, and never
-unselects the minibuffer if it is active.  */);
+unselects the minibuffer if it is active.
+
+When customizing this variable make sure that the actual value of
+`focus-follows-mouse' matches the behavior of your window manager.  */);
   Vmouse_autoselect_window = Qnil;
 
   DEFVAR_LISP ("auto-resize-tool-bars", &Vauto_resize_tool_bars,
@@ -24586,6 +24769,8 @@ the frame's other specifications determine how to blink the cursor off.  */);
   DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p,
     doc: /* *Non-nil means scroll the display automatically to make point visible.  */);
   automatic_hscrolling_p = 1;
+  Qauto_hscroll_mode = intern ("auto-hscroll-mode");
+  staticpro (&Qauto_hscroll_mode);
 
   DEFVAR_INT ("hscroll-margin", &hscroll_margin,
     doc: /* *How many columns away from the window edge point is allowed to get