]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Merge from emacs--rel--22
[gnu-emacs] / src / xdisp.c
index f362f2c352f594026121ac58cc25ced38ae5ff4c..add712fc85b772784d4613e8b7acf2391536feff 100644 (file)
@@ -177,6 +177,7 @@ Boston, MA 02110-1301, USA.  */
 #include "termchar.h"
 #include "dispextern.h"
 #include "buffer.h"
+#include "character.h"
 #include "charset.h"
 #include "indent.h"
 #include "commands.h"
@@ -201,6 +202,12 @@ Boston, MA 02110-1301, USA.  */
 #include "macterm.h"
 #endif
 
+#ifdef HAVE_WINDOW_SYSTEM
+#ifdef USE_FONT_BACKEND
+#include "font.h"
+#endif /* USE_FONT_BACKEND */
+#endif /* HAVE_WINDOW_SYSTEM */
+
 #ifndef FRAME_X_OUTPUT
 #define FRAME_X_OUTPUT(f) ((f)->output_data.x)
 #endif
@@ -232,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;
@@ -580,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];
 
@@ -698,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.  */
@@ -753,6 +753,7 @@ 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.  */
 
@@ -764,6 +765,7 @@ 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}
 };
@@ -813,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;
@@ -923,7 +921,7 @@ static char *decode_mode_spec P_ ((struct window *, int, int, int, int *));
 static void display_menu_bar P_ ((struct window *));
 static int display_count_lines P_ ((int, int, int, int, int *));
 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));
@@ -965,7 +963,7 @@ 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, Lisp_Object,
                                           struct text_pos *, int));
@@ -1332,6 +1330,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);
@@ -1936,6 +1956,14 @@ get_glyph_string_clip_rects (s, rects, n)
        }
     }
 
+  if (s->row->clip)
+    {
+      XRectangle r_save = r;
+
+      if (! x_intersect_rectangles (&r_save, s->row->clip, &r))
+       r.width = 0;
+    }
+
   if ((s->for_overlaps & OVERLAPS_BOTH) == 0
       || ((s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1))
     {
@@ -2525,9 +2553,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);
@@ -3195,12 +3223,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;
 
@@ -3212,7 +3240,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);
@@ -3324,7 +3352,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))
     {
@@ -3492,7 +3521,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);
@@ -3546,7 +3575,7 @@ face_before_or_after_it_pos (it, before_p)
          struct face *face = FACE_FROM_ID (it->f, face_id);
 
          c = string_char_and_length (p, rest, &len);
-         face_id = FACE_FOR_CHAR (it->f, face, c);
+         face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), it->string);
        }
     }
   else
@@ -3585,7 +3614,7 @@ face_before_or_after_it_pos (it, before_p)
        {
          int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
          struct face *face = FACE_FROM_ID (it->f, face_id);
-         face_id = FACE_FOR_CHAR (it->f, face, c);
+         face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
        }
     }
 
@@ -3664,7 +3693,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?  */
@@ -4017,7 +4047,7 @@ handle_single_display_spec (it, spec, object, overlay, 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));
@@ -4083,7 +4113,7 @@ handle_single_display_spec (it, spec, object, overlay, position,
       && 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));
@@ -4099,7 +4129,7 @@ handle_single_display_spec (it, spec, object, overlay, 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))
@@ -4125,7 +4155,7 @@ handle_single_display_spec (it, spec, object, overlay, 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
@@ -4166,7 +4196,7 @@ handle_single_display_spec (it, spec, object, overlay, 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;
@@ -4183,7 +4213,7 @@ handle_single_display_spec (it, spec, object, overlay, position,
        {
          Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
          int face_id2 = lookup_derived_face (it->f, face_name,
-                                             'A', FRINGE_FACE_ID, 0);
+                                             FRINGE_FACE_ID, 0);
          if (face_id2 >= 0)
            face_id = face_id2;
        }
@@ -4216,7 +4246,7 @@ handle_single_display_spec (it, spec, object, overlay, 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;
        }
@@ -4261,9 +4291,9 @@ handle_single_display_spec (it, spec, object, overlay, 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)
     {
@@ -4335,7 +4365,7 @@ handle_single_display_spec (it, spec, object, overlay, 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
@@ -4537,6 +4567,100 @@ 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;
+
+#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)
+           {
+             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))
+               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];
+
+             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
+#endif /* USE_FONT_BACKEND */
+               args[3] = Qnil;
+             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.  */
 
@@ -4545,30 +4669,44 @@ handle_composition_prop (it)
      struct it *it;
 {
   Lisp_Object prop, string;
-  int pos, pos_byte, end;
+  EMACS_INT pos, pos_byte, start, end;
   enum prop_handled handled = HANDLED_NORMALLY;
 
   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
      composition (in the case that the composition is from the current
      buffer), draw a glyph composed from the composition components.  */
-  if (find_composition (pos, -1, &pos, &end, &prop, string)
-      && COMPOSITION_VALID_P (pos, end, prop)
-      && (STRINGP (it->string) || (PT <= pos || PT >= end)))
+  if (find_composition (pos, -1, &start, &end, &prop, string)
+      && COMPOSITION_VALID_P (start, end, prop)
+      && (STRINGP (it->string) || (PT <= start || PT >= end)))
     {
-      int id = get_composition_id (pos, pos_byte, end - pos, prop, string);
+      int id;
+
+      if (start != pos)
+       {
+         if (STRINGP (it->string))
+           pos_byte = string_char_to_byte (it->string, start);
+         else
+           pos_byte = CHAR_TO_BYTE (start);
+       }
+      id = get_composition_id (start, pos_byte, end - start, prop, string);
 
       if (id >= 0)
        {
@@ -4597,9 +4735,28 @@ handle_composition_prop (it)
          it->method = GET_FROM_COMPOSITION;
          it->cmp_id = id;
          it->cmp_len = COMPOSITION_LENGTH (prop);
-         /* For a terminal, draw only the first character of the
-             components.  */
-         it->c = COMPOSITION_GLYPH (composition_table[id], 0);
+         /* For a terminal, draw only the first (non-TAB) character
+            of the components.  */
+#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);
+           }
+         else
+#endif /* USE_FONT_BACKEND */
+           {
+             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;
@@ -4674,7 +4831,7 @@ next_overlay_string (it)
       /* If we're at the end of the buffer, record that we have
         processed the overlay strings there already, so that
         next_element_from_buffer doesn't try it again.  */
-      if (IT_CHARPOS (*it) >= it->end_charpos)
+      if (NILP (it->string) && IT_CHARPOS (*it) >= it->end_charpos)
        it->overlay_strings_at_end_processed_p = 1;
 
       /* If we have to display `...' for invisible text, set
@@ -5261,7 +5418,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 */
@@ -5553,6 +5710,7 @@ static int (* get_next_element[NUM_IT_METHODS]) P_ ((struct it *it)) =
   next_element_from_stretch
 };
 
+#define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
 
 /* Load IT's display element fields with information about the next
    display element from the current position of IT.  Value is zero if
@@ -5573,7 +5731,7 @@ get_next_display_element (it)
   int success_p;
 
  get_next:
-  success_p = (*get_next_element[it->method]) (it);
+  success_p = GET_NEXT_DISPLAY_ELEMENT (it);
 
   if (it->what == IT_CHARACTER)
     {
@@ -5623,60 +5781,55 @@ get_next_display_element (it)
             the translation.  This could easily be changed but I
             don't believe that it is worth doing.
 
-            If it->multibyte_p is nonzero, eight-bit characters and
-            non-printable multibyte characters are also translated to
-            octal form.
+            If it->multibyte_p is nonzero, non-printable non-ASCII
+            characters are also translated to octal form.
 
             If it->multibyte_p is zero, eight-bit characters that
             don't have corresponding multibyte char code are also
             translated to octal form.  */
          else if ((it->c < ' '
-                   && (it->area != TEXT_AREA
-                       /* In mode line, treat \n 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
-                      ? ((it->c >= 127
-                          && it->len == 1)
-                         || !CHAR_PRINTABLE_P (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 == 0x8a0 || it->c == 0x8ad
-                                 || it->c == 0x920 || it->c == 0x92d
-                                 || it->c == 0xe20 || it->c == 0xe2d
-                                 || it->c == 0xf20 || it->c == 0xf2d)))
+                             && (it->c == 0xA0 /* NO-BREAK SPACE */
+                                 || it->c == 0xAD /* SOFT HYPHEN */)))
                       : (it->c >= 127
-                         && (!unibyte_display_via_language_environment
-                             || it->c == unibyte_char_to_multibyte (it->c)))))
+                         && (! unibyte_display_via_language_environment
+                             || (UNIBYTE_CHAR_HAS_MULTIBYTE_P (it->c)))))))
            {
              /* IT->c is a control character which must be displayed
                 either as '\003' or as `^C' where the '\\' and '^'
                 can be defined in the display table.  Fill
                 IT->ctl_chars with glyphs for what we have to
                 display.  Then, set IT->dpvec to these glyphs.  */
-             GLYPH g;
+             Lisp_Object gc;
              int ctl_len;
              int face_id, lface_id = 0 ;
-             GLYPH escape_glyph;
+             int escape_glyph;
 
              /* Handle control characters with ^.  */
 
              if (it->c < 128 && it->ctl_arrow_p)
                {
+                 int g;
+
                  g = '^';           /* default glyph for Control */
                  /* Set IT->ctl_chars[0] to the glyph for `^'.  */
                  if (it->dp
-                     && INTEGERP (DISP_CTRL_GLYPH (it->dp))
-                     && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
+                     && (gc = DISP_CTRL_GLYPH (it->dp), GLYPH_CODE_P (gc))
+                     && GLYPH_CODE_CHAR_VALID_P (gc))
                    {
-                     g = XINT (DISP_CTRL_GLYPH (it->dp));
-                     lface_id = FAST_GLYPH_FACE (g);
+                     g = GLYPH_CODE_CHAR (gc);
+                     lface_id = GLYPH_CODE_FACE (gc);
                    }
                  if (lface_id)
                    {
-                      g = FAST_GLYPH_CHAR (g);
-                      face_id = merge_faces (it->f, Qt, lface_id,
-                                             it->face_id);
+                     face_id = merge_faces (it->f, Qt, lface_id, it->face_id);
                    }
                  else if (it->f == last_escape_glyph_frame
                           && it->face_id == last_escape_glyph_face_id)
@@ -5694,8 +5847,7 @@ get_next_display_element (it)
                    }
 
                  XSETINT (it->ctl_chars[0], g);
-                 g = it->c ^ 0100;
-                 XSETINT (it->ctl_chars[1], g);
+                 XSETINT (it->ctl_chars[1], it->c ^ 0100);
                  ctl_len = 2;
                  goto display_control;
                }
@@ -5704,15 +5856,14 @@ get_next_display_element (it)
                 highlighting.  */
 
              if (EQ (Vnobreak_char_display, Qt)
-                 && (it->c == 0x8a0 || it->c == 0x920
-                     || it->c == 0xe20 || it->c == 0xf20))
+                 && it->c == 0xA0)
                {
                  /* Merge the no-break-space face into the current face.  */
                  face_id = merge_faces (it->f, Qnobreak_space, 0,
                                         it->face_id);
 
-                 g = it->c = ' ';
-                 XSETINT (it->ctl_chars[0], g);
+                 it->c = ' ';
+                 XSETINT (it->ctl_chars[0], ' ');
                  ctl_len = 1;
                  goto display_control;
                }
@@ -5723,17 +5874,16 @@ get_next_display_element (it)
              escape_glyph = '\\';
 
              if (it->dp
-                 && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
-                 && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
+                 && (gc = DISP_ESCAPE_GLYPH (it->dp), GLYPH_CODE_P (gc))
+                 && GLYPH_CODE_CHAR_VALID_P (gc))
                {
-                 escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
-                 lface_id = FAST_GLYPH_FACE (escape_glyph);
+                 escape_glyph = GLYPH_CODE_CHAR (gc);
+                 lface_id = GLYPH_CODE_FACE (gc);
                }
              if (lface_id)
                {
                  /* The display table specified a face.
                     Merge it into face_id and also into escape_glyph.  */
-                 escape_glyph = FAST_GLYPH_CHAR (escape_glyph);
                  face_id = merge_faces (it->f, Qt, lface_id,
                                         it->face_id);
                }
@@ -5756,11 +5906,10 @@ get_next_display_element (it)
                 highlighting.  */
 
              if (EQ (Vnobreak_char_display, Qt)
-                 && (it->c == 0x8ad || it->c == 0x92d
-                     || it->c == 0xe2d || it->c == 0xf2d))
+                 && it->c == 0xAD)
                {
-                 g = it->c = '-';
-                 XSETINT (it->ctl_chars[0], g);
+                 it->c = '-';
+                 XSETINT (it->ctl_chars[0], '-');
                  ctl_len = 1;
                  goto display_control;
                }
@@ -5768,14 +5917,11 @@ get_next_display_element (it)
              /* Handle non-break space and soft hyphen
                 with the escape glyph.  */
 
-             if (it->c == 0x8a0 || it->c == 0x8ad
-                 || it->c == 0x920 || it->c == 0x92d
-                 || it->c == 0xe20 || it->c == 0xe2d
-                 || it->c == 0xf20 || it->c == 0xf2d)
+             if (it->c == 0xA0 || it->c == 0xAD)
                {
                  XSETINT (it->ctl_chars[0], escape_glyph);
-                 g = it->c = ((it->c & 0xf) == 0 ? ' ' : '-');
-                 XSETINT (it->ctl_chars[1], g);
+                 it->c = (it->c == 0xA0 ? ' ' : '-');
+                 XSETINT (it->ctl_chars[1], it->c);
                  ctl_len = 2;
                  goto display_control;
                }
@@ -5786,27 +5932,32 @@ get_next_display_element (it)
                int i;
 
                /* Set IT->ctl_chars[0] to the glyph for `\\'.  */
-               if (SINGLE_BYTE_CHAR_P (it->c))
-                 str[0] = it->c, len = 1;
+               if (CHAR_BYTE8_P (it->c))
+                 {
+                   str[0] = CHAR_TO_BYTE8 (it->c);
+                   len = 1;
+                 }
+               else if (it->c < 256)
+                 {
+                   str[0] = it->c;
+                   len = 1;
+                 }
                else
                  {
-                   len = CHAR_STRING_NO_SIGNAL (it->c, str);
-                   if (len < 0)
-                     {
-                       /* It's an invalid character, which shouldn't
-                          happen actually, but due to bugs it may
-                          happen.  Let's print the char as is, there's
-                          not much meaningful we can do with it.  */
-                         str[0] = it->c;
-                         str[1] = it->c >> 8;
-                         str[2] = it->c >> 16;
-                         str[3] = it->c >> 24;
-                         len = 4;
-                       }
+                   /* It's an invalid character, which shouldn't
+                      happen actually, but due to bugs it may
+                      happen.  Let's print the char as is, there's
+                      not much meaningful we can do with it.  */
+                     str[0] = it->c;
+                     str[1] = it->c >> 8;
+                     str[2] = it->c >> 16;
+                     str[3] = it->c >> 24;
+                     len = 4;
                    }
 
                for (i = 0; i < len; i++)
                  {
+                   int g;
                    XSETINT (it->ctl_chars[i * 4], escape_glyph);
                    /* Insert three more glyphs into IT->ctl_chars for
                       the octal display of the character.  */
@@ -5833,16 +5984,21 @@ get_next_display_element (it)
              goto get_next;
            }
        }
+    }
 
-      /* Adjust face id for a multibyte character.  There are no
-         multibyte character in unibyte text.  */
-      if (it->multibyte_p
-         && success_p
-         && FRAME_WINDOW_P (it->f))
-       {
-         struct face *face = FACE_FROM_ID (it->f, it->face_id);
-         it->face_id = FACE_FOR_CHAR (it->f, face, it->c);
-       }
+  /* Adjust face id for a multibyte character.  There are no multibyte
+     character in unibyte text.  */
+  if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION)
+      && it->multibyte_p
+      && success_p
+      && 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);
     }
 
   /* Is this character the last one of a run of characters with
@@ -6041,18 +6197,20 @@ static int
 next_element_from_display_vector (it)
      struct it *it;
 {
+  Lisp_Object gc;
+
   /* Precondition.  */
   xassert (it->dpvec && it->current.dpvec_index >= 0);
 
   it->face_id = it->saved_face_id;
 
-  if (INTEGERP (*it->dpvec)
-      && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
-    {
-      GLYPH g;
+  /* KFS: This code used to check ip->dpvec[0] instead of the current element.
+          That seemed totally bogus - so I changed it...  */
 
-      g = XFASTINT (it->dpvec[it->current.dpvec_index]);
-      it->c = FAST_GLYPH_CHAR (g);
+  if ((gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc))
+      && GLYPH_CODE_CHAR_VALID_P (gc))
+    {
+      it->c = GLYPH_CODE_CHAR (gc);
       it->len = CHAR_BYTES (it->c);
 
       /* The entry may contain a face id to use.  Such a face id is
@@ -6062,7 +6220,7 @@ next_element_from_display_vector (it)
        it->face_id = it->dpvec_face_id;
       else
        {
-         int lface_id = FAST_GLYPH_FACE (g);
+         int lface_id = GLYPH_CODE_FACE (gc);
          if (lface_id > 0)
            it->face_id = merge_faces (it->f, Qt, lface_id,
                                       it->saved_face_id);
@@ -6103,7 +6261,7 @@ next_element_from_string (it)
 
       /* Since a handler may have changed IT->method, we must
         recurse here.  */
-      return get_next_display_element (it);
+      return GET_NEXT_DISPLAY_ELEMENT (it);
     }
 
   if (it->current.overlay_string_index >= 0)
@@ -6241,7 +6399,7 @@ next_element_from_ellipsis (it)
       it->face_before_selective_p = 1;
     }
 
-  return get_next_display_element (it);
+  return GET_NEXT_DISPLAY_ELEMENT (it);
 }
 
 
@@ -6305,7 +6463,7 @@ next_element_from_buffer (it)
            }
 
          if (overlay_strings_follow_p)
-           success_p = get_next_display_element (it);
+           success_p = GET_NEXT_DISPLAY_ELEMENT (it);
          else
            {
              it->what = IT_EOB;
@@ -6316,7 +6474,7 @@ next_element_from_buffer (it)
       else
        {
          handle_stop (it);
-         return get_next_display_element (it);
+         return GET_NEXT_DISPLAY_ELEMENT (it);
        }
     }
   else
@@ -6844,6 +7002,16 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
             the line.  */
          if (skip == MOVE_X_REACHED)
            {
+             /* Wait!  We can conclude that TO_Y is in the line if
+                the already scanned glyphs make the line tall enough
+                because further scanning doesn't make it shorter.  */
+             line_height = it->max_ascent + it->max_descent;
+             if (to_y >= it->current_y
+                 && to_y < it->current_y + line_height)
+               {
+                 reached = 6;
+                 break;
+               }
              it_backup = *it;
              TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it)));
              skip2 = move_it_in_display_line_to (it, to_charpos, -1,
@@ -7380,7 +7548,7 @@ message_dolog (m, nbytes, nlflag, multibyte)
          for (i = 0; i < nbytes; i += char_bytes)
            {
              c = string_char_and_length (m + i, nbytes - i, &char_bytes);
-             work[0] = (SINGLE_BYTE_CHAR_P (c)
+             work[0] = (ASCII_CHAR_P (c)
                         ? c
                         : multibyte_char_to_unibyte (c, Qnil));
              insert_1_both (work, 1, 1, 1, 0, 0);
@@ -7396,7 +7564,8 @@ message_dolog (m, nbytes, nlflag, multibyte)
             for the *Message* buffer.  */
          for (i = 0; i < nbytes; i++)
            {
-             c = unibyte_char_to_multibyte (msg[i]);
+             c = msg[i];
+             c = unibyte_char_to_multibyte (c);
              char_bytes = CHAR_STRING (c, str);
              insert_1_both (str, 1, char_bytes, 1, 0, 0);
            }
@@ -7603,8 +7772,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);
     }
 }
 
@@ -7707,8 +7876,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);
     }
 }
 
@@ -7946,6 +8115,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
@@ -7970,6 +8143,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.  */
@@ -8035,7 +8219,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.  */
@@ -8045,22 +8229,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));
@@ -8607,7 +8791,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;
@@ -8637,7 +8821,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))
     {
@@ -8667,7 +8850,7 @@ set_message_1 (a1, a2, nbytes, multibyte_p)
          for (i = 0; i < nbytes; i += n)
            {
              c = string_char_and_length (s + i, nbytes - i, &n);
-             work[0] = (SINGLE_BYTE_CHAR_P (c)
+             work[0] = (ASCII_CHAR_P (c)
                         ? c
                         : multibyte_char_to_unibyte (c, Qnil));
              insert_1_both (work, 1, 1, 1, 0, 0);
@@ -8684,7 +8867,8 @@ set_message_1 (a1, a2, nbytes, multibyte_p)
          /* Convert a single-byte string to multibyte.  */
          for (i = 0; i < nbytes; i++)
            {
-             c = unibyte_char_to_multibyte (msg[i]);
+             c = msg[i];
+             c = unibyte_char_to_multibyte (c);
              n = CHAR_STRING (c, str);
              insert_1_both (str, 1, n, 1, 0, 0);
            }
@@ -8781,17 +8965,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)
@@ -8839,7 +9019,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);
@@ -8854,8 +9034,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
@@ -8913,7 +9095,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.  */
@@ -8923,17 +9105,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;
 }
@@ -8953,7 +9136,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;
@@ -9409,8 +9592,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;
     }
 }
@@ -9444,7 +9627,7 @@ update_tool_bar (f, save_match_data)
      struct frame *f;
      int save_match_data;
 {
-#ifdef USE_GTK
+#if defined (USE_GTK) || USE_MAC_TOOLBAR
   int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
 #else
   int do_update = WINDOWP (f->tool_bar_window)
@@ -9910,7 +10093,7 @@ redisplay_tool_bar (f)
   struct it it;
   struct glyph_row *row;
 
-#ifdef USE_GTK
+#if defined (USE_GTK) || USE_MAC_TOOLBAR
   if (FRAME_EXTERNAL_TOOL_BAR (f))
     update_frame_tool_bar (f);
   return 0;
@@ -10379,11 +10562,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;
@@ -10473,16 +10657,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;
 }
 
@@ -10781,7 +10958,7 @@ check_point_in_composition (prev_buf, prev_pt, buf, pt)
      struct buffer *prev_buf, *buf;
      int prev_pt, pt;
 {
-  int start, end;
+  EMACS_INT start, end;
   Lisp_Object prop;
   Lisp_Object buffer;
 
@@ -10862,31 +11039,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));
 }
 
 
@@ -10918,6 +11088,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.  */
@@ -10979,6 +11150,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;
@@ -10999,17 +11178,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
@@ -11031,6 +11209,7 @@ redisplay_internal (preserve_echo_area)
       }
   }
 
+
   /* Notice any pending interrupt request to change frame size.  */
   do_pending_window_change (1);
 
@@ -11392,7 +11571,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
@@ -11401,16 +11580,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
@@ -11457,12 +11636,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);
+                }
            }
        }
     }
@@ -11547,8 +11726,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;
@@ -11612,13 +11791,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 */
@@ -11658,8 +11831,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);
 }
 
 
@@ -11667,7 +11841,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)
@@ -11678,7 +11853,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;
 }
@@ -11789,35 +11965,24 @@ disp_char_vector (dp, c)
      struct Lisp_Char_Table *dp;
      int c;
 {
-  int code[4], i;
   Lisp_Object val;
 
-  if (SINGLE_BYTE_CHAR_P (c))
-    return (dp->contents[c]);
-
-  SPLIT_CHAR (c, code[0], code[1], code[2]);
-  if (code[1] < 32)
-    code[1] = -1;
-  else if (code[2] < 32)
-    code[2] = -1;
-
-  /* Here, the possible range of code[0] (== charset ID) is
-     128..max_charset.  Since the top level char table contains data
-     for multibyte characters after 256th element, we must increment
-     code[0] by 128 to get a correct index.  */
-  code[0] += 128;
-  code[3] = -1;                /* anchor */
-
-  for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
+  if (ASCII_CHAR_P (c))
     {
-      val = dp->contents[code[i]];
-      if (!SUB_CHAR_TABLE_P (val))
-       return (NILP (val) ? dp->defalt : val);
+      val = dp->ascii;
+      if (SUB_CHAR_TABLE_P (val))
+       val = XSUB_CHAR_TABLE (val)->contents[c];
     }
+  else
+    {
+      Lisp_Object table;
 
-  /* Here, val is a sub char table.  We return the default value of
-     it.  */
-  return (dp->defalt);
+      XSETCHAR_TABLE (table, dp);
+      val = char_table_ref (table, c);
+    }
+  if (NILP (val))
+    val = dp->defalt;
+  return val;
 }
 
 
@@ -12526,7 +12691,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;
@@ -12827,7 +12992,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);
 }
 
 
@@ -12862,7 +13029,7 @@ redisplay_window (window, just_this_one_p)
   int rc;
   int centering_position = -1;
   int last_line_misfit = 0;
-  int save_beg_unchanged, save_end_unchanged;
+  int beg_unchanged, end_unchanged;
 
   SET_TEXT_POS (lpoint, PT, PT_BYTE);
   opoint = lpoint;
@@ -12873,8 +13040,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?  */
@@ -12925,10 +13091,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);
-
-  save_beg_unchanged = BEG_UNCHANGED;
-  save_end_unchanged = END_UNCHANGED;
 
   current_matrix_up_to_date_p
     = (!NILP (w->window_end_valid)
@@ -12937,6 +13099,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
@@ -13234,16 +13413,16 @@ redisplay_window (window, just_this_one_p)
         than a simple mouse-click.  */
       if (NILP (w->start_at_line_beg)
          && NILP (do_mouse_tracking)
-         && CHARPOS (startp) > BEGV
-         && CHARPOS (startp) > BEG + save_beg_unchanged
-         && CHARPOS (startp) <= Z - save_end_unchanged)
+         && CHARPOS (startp) > BEGV
+         && CHARPOS (startp) > BEG + beg_unchanged
+         && CHARPOS (startp) <= Z - end_unchanged)
        {
          w->force_start = Qt;
          if (XMARKER (w->start)->buffer == current_buffer)
            compute_window_start_on_continuation_line (w);
          SET_TEXT_POS_FROM_MARKER (startp, w->start);
          goto force_start;
-       }
+       }
 
 #if GLYPH_DEBUG
       debug_method_add (w, "same window start");
@@ -13546,20 +13725,22 @@ redisplay_window (window, just_this_one_p)
         display_menu_bar (w);
 
 #ifdef HAVE_WINDOW_SYSTEM
-#ifdef USE_GTK
-      redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
+      if (FRAME_WINDOW_P (f))
+        {
+#if defined (USE_GTK) || USE_MAC_TOOLBAR
+          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
     }
 
@@ -13593,7 +13774,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.  */
@@ -13862,10 +14044,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);
            }
 
@@ -14034,10 +14216,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);
        }
 
@@ -14238,8 +14420,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
@@ -14290,8 +14471,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;
 }
@@ -14487,7 +14667,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);
 
@@ -14896,10 +15076,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
        {
@@ -14917,36 +15097,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);
@@ -15738,7 +15918,7 @@ append_space_for_newline (it, default_face_p)
          else if (it->face_before_selective_p)
            it->face_id = it->saved_face_id;
          face = FACE_FROM_ID (it->f, it->face_id);
-         it->face_id = FACE_FOR_CHAR (it->f, face, 0);
+         it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
 
          PRODUCE_GLYPHS (it);
 
@@ -15798,9 +15978,9 @@ extend_face_to_end_of_line (it)
          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 (!SINGLE_BYTE_CHAR_P (it->c))
+  if (!ASCII_CHAR_P (it->c))
     {
-      it->face_id = FACE_FOR_CHAR (f, face, 0);
+      it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
     }
 
   if (FRAME_WINDOW_P (f))
@@ -15906,7 +16086,7 @@ highlight_trailing_whitespace (f, row)
                  && glyph->u.ch == ' '))
          && trailing_whitespace_p (glyph->charpos))
        {
-         int face_id = lookup_named_face (f, Qtrailing_whitespace, 0, 0);
+         int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
          if (face_id < 0)
            return;
 
@@ -16520,7 +16700,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)
@@ -16586,7 +16766,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)
@@ -16751,10 +16931,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);
 
@@ -17046,7 +17226,6 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                    charpos = (STRING_MULTIBYTE (elt)
                               ? string_byte_to_char (elt, bytepos)
                               : bytepos);
-
                    spec
                      = decode_mode_spec (it->w, c, field, prec, &multibyte);
 
@@ -17426,7 +17605,7 @@ are the selected window and the window's buffer).  */)
   /* 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 build_string ("");
+    return empty_unibyte_string;
 
   if (no_props)
     face = Qnil;
@@ -17435,7 +17614,7 @@ are the selected window and the window's buffer).  */)
     {
       if (EQ (face, Qt))
        face = (EQ (window, selected_window) ? Qmode_line : Qmode_line_inactive);
-      face_id = lookup_named_face (XFRAME (WINDOW_FRAME (w)), face, 0, 0);
+      face_id = lookup_named_face (XFRAME (WINDOW_FRAME (w)), face, 0);
     }
 
   if (face_id < 0)
@@ -17471,9 +17650,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)
     {
@@ -17484,7 +17663,7 @@ are the selected window and the window's buffer).  */)
     {
       mode_line_string_list = Fnreverse (mode_line_string_list);
       str = Fmapconcat (intern ("identity"), mode_line_string_list,
-                       make_string ("", 0));
+                       empty_unibyte_string);
     }
 
   unbind_to (count, Qnil);
@@ -17658,7 +17837,7 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
   /* The EOL conversion we are using.  */
   Lisp_Object eoltype;
 
-  val = Fget (coding_system, Qcoding_system);
+  val = CODING_SYSTEM_SPEC (coding_system);
   eoltype = Qnil;
 
   if (!VECTORP (val))          /* Not yet decided.  */
@@ -17671,12 +17850,14 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
     }
   else
     {
+      Lisp_Object attrs;
       Lisp_Object eolvalue;
 
-      eolvalue = Fget (coding_system, Qeol_type);
+      attrs = AREF (val, 0);
+      eolvalue = AREF (val, 2);
 
       if (multibyte)
-       *buf++ = XFASTINT (AREF (val, 1));
+       *buf++ = XFASTINT (CODING_ATTR_MNEMONIC (attrs));
 
       if (eol_flag)
        {
@@ -17686,10 +17867,10 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
            eoltype = eol_mnemonic_undecided;
          else if (VECTORP (eolvalue)) /* Not yet decided.  */
            eoltype = eol_mnemonic_undecided;
-         else                  /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
-           eoltype = (XFASTINT (eolvalue) == 0
+         else                  /* eolvalue is Qunix, Qdos, or Qmac.  */
+           eoltype = (EQ (eolvalue, Qunix)
                       ? eol_mnemonic_unix
-                      : (XFASTINT (eolvalue) == 1
+                      : (EQ (eolvalue, Qdos) == 1
                          ? eol_mnemonic_dos : eol_mnemonic_mac));
        }
     }
@@ -17702,8 +17883,7 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
          eol_str = SDATA (eoltype);
          eol_str_len = SBYTES (eoltype);
        }
-      else if (INTEGERP (eoltype)
-              && CHAR_VALID_P (XINT (eoltype), 0))
+      else if (CHARACTERP (eoltype))
        {
          unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
          eol_str_len = CHAR_STRING (XINT (eoltype), tmp);
@@ -17909,8 +18089,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);
@@ -18078,6 +18258,16 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
 #endif
       break;
 
+    case '@':
+      {
+       Lisp_Object val;
+       val = call1 (intern ("file-remote-p"), current_buffer->directory);
+       if (NILP (val))
+         return "-";
+       else
+         return "@";
+      }
+
     case 't':                  /* indicate TEXT or BINARY */
 #ifdef MODE_LINE_BINARY_TEXT
       return MODE_LINE_BINARY_TEXT (b);
@@ -18097,8 +18287,12 @@ 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 (keyboard_coding.symbol, p, 0);
-           p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
+           p = decode_mode_spec_coding (CODING_ID_NAME
+                                        (FRAME_KEYBOARD_CODING (f)->id),
+                                        p, 0);
+           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,
                                     p, eol_flag);
@@ -18281,8 +18475,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;
@@ -18300,7 +18494,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
@@ -18370,7 +18564,7 @@ display_string (string, lisp_string, face_string, face_string_pos,
                }
              break;
            }
-         else if (x + glyph->pixel_width > it->first_visible_x)
+         else if (x + glyph->pixel_width >= it->first_visible_x)
            {
              /* Glyph is at least partially visible.  */
              ++it->hpos;
@@ -18502,6 +18696,27 @@ invisible_p (propval, list)
   return 0;
 }
 
+DEFUN ("invisible-p", Finvisible_p, Sinvisible_p, 1, 1, 0,
+       doc: /* Non-nil if the property makes the text invisible.
+POS-OR-PROP can be a marker or number, in which case it is taken to be
+a position in the current buffer and the value of the `invisible' property
+is checked; or it can be some other value, which is then presumed to be the
+value of the `invisible' property of the text of interest.
+The non-nil value returned can be t for truly invisible text or something
+else if the text is replaced by an ellipsis.  */)
+     (pos_or_prop)
+     Lisp_Object pos_or_prop;
+{
+  Lisp_Object prop
+    = (NATNUMP (pos_or_prop) || MARKERP (pos_or_prop)
+       ? Fget_char_property (pos_or_prop, Qinvisible, Qnil)
+       : pos_or_prop);
+  int invis = TEXT_PROP_MEANS_INVISIBLE (prop);
+  return (invis == 0 ? Qnil
+         : invis == 1 ? Qt
+         : make_number (invis));
+}
+
 /* Calculate a width or height in pixels from a specification using
    the following elements:
 
@@ -18590,6 +18805,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)
@@ -18706,7 +18923,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);
@@ -18898,6 +19116,80 @@ append_glyph_string (head, tail, s)
 }
 
 
+/* Get face and two-byte form of character C in face FACE_ID on frame
+   F.  The encoding of C is returned in *CHAR2B.  MULTIBYTE_P non-zero
+   means we want to display multibyte text.  DISPLAY_P non-zero means
+   make sure that X resources for the face returned are allocated.
+   Value is a pointer to a realized face that is ready for display if
+   DISPLAY_P is non-zero.  */
+
+static INLINE struct face *
+get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
+     struct frame *f;
+     int c, face_id;
+     XChar2b *char2b;
+     int multibyte_p, display_p;
+{
+  struct face *face = FACE_FROM_ID (f, face_id);
+
+#ifdef USE_FONT_BACKEND
+  if (enable_font_backend)
+    {
+      struct font *font = (struct font *) face->font_info;
+
+      if (font)
+       {
+         unsigned code = font->driver->encode_char (font, c);
+
+         if (code != FONT_INVALID_CODE)
+           STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
+         else
+           STORE_XCHAR2B (char2b, 0, 0);
+       }
+    }
+  else
+#endif /* USE_FONT_BACKEND */
+  if (!multibyte_p)
+    {
+      /* Unibyte case.  We don't have to encode, but we have to make
+        sure to use a face suitable for unibyte.  */
+      STORE_XCHAR2B (char2b, 0, c);
+      face_id = FACE_FOR_CHAR (f, face, c, -1, Qnil);
+      face = FACE_FROM_ID (f, face_id);
+    }
+  else if (c < 128)
+    {
+      /* Case of ASCII in a face known to fit ASCII.  */
+      STORE_XCHAR2B (char2b, 0, c);
+    }
+  else if (face->font != NULL)
+    {
+      struct font_info *font_info
+       = FONT_INFO_FROM_ID (f, face->font_info_id);
+      struct charset *charset = CHARSET_FROM_ID (font_info->charset);
+      unsigned code = ENCODE_CHAR (charset, c);
+
+      if (CHARSET_DIMENSION (charset) == 1)
+       STORE_XCHAR2B (char2b, 0, code);
+      else
+       STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
+       /* Maybe encode the character in *CHAR2B.  */
+      FRAME_RIF (f)->encode_char (c, char2b, font_info, charset, NULL);
+    }
+
+  /* Make sure X resources of the face are allocated.  */
+#ifdef HAVE_X_WINDOWS
+  if (display_p)
+#endif
+    {
+      xassert (face != NULL);
+      PREPARE_FACE_FOR_DISPLAY (f, face);
+    }
+
+  return face;
+}
+
+
 /* Get face and two-byte form of character glyph GLYPH on frame F.
    The encoding of GLYPH->u.ch is returned in *CHAR2B.  Value is
    a pointer to a realized face that is ready for display.  */
@@ -18917,6 +19209,23 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
   if (two_byte_p)
     *two_byte_p = 0;
 
+#ifdef USE_FONT_BACKEND
+  if (enable_font_backend)
+    {
+      struct font *font = (struct font *) face->font_info;
+
+      if (font)
+       {
+         unsigned code = font->driver->encode_char (font, glyph->u.ch);
+
+         if (code != FONT_INVALID_CODE)
+           STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
+         else
+           STORE_XCHAR2B (char2b, 0, code);
+       }
+    }
+  else
+#endif /* USE_FONT_BACKEND */
   if (!glyph->multibyte_p)
     {
       /* Unibyte case.  We don't have to encode, but we have to make
@@ -18930,24 +19239,25 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
     }
   else
     {
-      int c1, c2, charset;
+      struct font_info *font_info
+       = FONT_INFO_FROM_ID (f, face->font_info_id);
+      if (font_info)
+       {
+         struct charset *charset = CHARSET_FROM_ID (font_info->charset);
+         unsigned code = ENCODE_CHAR (charset, glyph->u.ch);
 
-      /* Split characters into bytes.  If c2 is -1 afterwards, C is
-        really a one-byte character so that byte1 is zero.  */
-      SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
-      if (c2 > 0)
-       STORE_XCHAR2B (char2b, c1, c2);
-      else
-       STORE_XCHAR2B (char2b, 0, c1);
+         if (CHARSET_DIMENSION (charset) == 1)
+           STORE_XCHAR2B (char2b, 0, code);
+         else
+           STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
 
-      /* Maybe encode the character in *CHAR2B.  */
-      if (charset != CHARSET_ASCII)
-       {
-         struct font_info *font_info
-           = FONT_INFO_FROM_ID (f, face->font_info_id);
-         if (font_info)
-           glyph->font_type
-             = rif->encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
+         /* Maybe encode the character in *CHAR2B.  */
+         if (CHARSET_ID (charset) != charset_ascii)
+           {
+             glyph->font_type
+               = FRAME_RIF (f)->encode_char (glyph->u.ch, char2b, font_info,
+                                             charset, two_byte_p);
+           }
        }
     }
 
@@ -18960,7 +19270,7 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
 
 /* Fill glyph string S with composition components specified by S->cmp.
 
-   FACES is an array of faces for all components of this composition.
+   BASE_FACE is the base face of the composition.
    S->gidx is the index of the first component for S.
 
    OVERLAPS non-zero means S should draw the foreground only, and use
@@ -18969,9 +19279,9 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
    Value is the index of a component not in S.  */
 
 static int
-fill_composite_glyph_string (s, faces, overlaps)
+fill_composite_glyph_string (s, base_face, overlaps)
      struct glyph_string *s;
-     struct face **faces;
+     struct face *base_face;
      int overlaps;
 {
   int i;
@@ -18980,21 +19290,70 @@ fill_composite_glyph_string (s, faces, overlaps)
 
   s->for_overlaps = overlaps;
 
-  s->face = faces[s->gidx];
-  s->font = s->face->font;
-  s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+#ifdef USE_FONT_BACKEND
+  if (enable_font_backend && 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_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 (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
+#endif /* USE_FONT_BACKEND */
+    {
+      /* 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;
 
-  /* For all glyphs of this composition, starting at the offset
-     S->gidx, until we reach the end of the definition or encounter a
-     glyph that requires the different face, add it to S.  */
-  ++s->nchars;
-  for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
-    ++s->nchars;
+      s->face = NULL;
+      s->font = NULL;
+      s->font_info = NULL;
+      for (i = s->gidx; i < s->cmp->glyph_len; i++)
+       {
+         int c = COMPOSITION_GLYPH (s->cmp, i);
 
-  /* All glyph strings for the same composition has the same width,
-     i.e. the width set for the first component of the composition.  */
+         if (c != '\t')
+           {
+             int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
+                                          -1, Qnil);
 
-  s->width = s->first_glyph->pixel_width;
+             face = get_char_face_and_encoding (s->f, c, face_id,
+                                                s->char2b + i, 1, 1);
+             if (face)
+               {
+                 if (! s->face)
+                   {
+                     s->face = face;
+                     s->font = s->face->font;
+                     s->font_info = FONT_INFO_FROM_FACE (s->f, s->face);
+                   }
+                 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;
+    }
 
   /* 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
@@ -19009,8 +19368,6 @@ fill_composite_glyph_string (s, faces, overlaps)
   /* Adjust base line for subscript/superscript text.  */
   s->ybase += s->first_glyph->voffset;
 
-  xassert (s->face && s->face->gc);
-
   /* This glyph string must always be drawn with 16-bit functions.  */
   s->two_byte_p = 1;
 
@@ -19045,7 +19402,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
@@ -19064,11 +19421,12 @@ 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;
-  s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+  s->font_info = FONT_INFO_FROM_FACE (s->f, s->face);
 
   /* If the specified font could not be loaded, use the frame's font,
      but record the fact that we couldn't load it in
@@ -19132,7 +19490,7 @@ fill_stretch_glyph_string (s, row, area, start, end)
   face_id = glyph->face_id;
   s->face = FACE_FROM_ID (s->f, face_id);
   s->font = s->face->font;
-  s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+  s->font_info = FONT_INFO_FROM_FACE (s->f, s->face);
   s->width = glyph->pixel_width;
   s->nchars = 1;
   voffset = glyph->voffset;
@@ -19154,6 +19512,36 @@ fill_stretch_glyph_string (s, row, area, start, end)
   return glyph - s->row->glyphs[s->area];
 }
 
+static XCharStruct *
+get_per_char_metric (f, font, font_info, char2b, font_type)
+     struct frame *f;
+     XFontStruct *font;
+     struct font_info *font_info;
+     XChar2b *char2b;
+     int font_type;
+{
+#ifdef USE_FONT_BACKEND
+  if (enable_font_backend)
+    {
+      static XCharStruct pcm_value;
+      unsigned code = (XCHAR2B_BYTE1 (char2b) << 8) | XCHAR2B_BYTE2 (char2b);
+      struct font *fontp;
+      struct font_metrics metrics;
+
+      if (! font_info || code == FONT_INVALID_CODE)
+       return NULL;
+      fontp = (struct font *) font_info;
+      fontp->driver->text_extents (fontp, &code, 1, &metrics);
+      pcm_value.lbearing = metrics.lbearing;
+      pcm_value.rbearing = metrics.rbearing;
+      pcm_value.ascent = metrics.ascent;
+      pcm_value.descent = metrics.descent;
+      pcm_value.width = metrics.width;
+      return &pcm_value;
+    }
+#endif /* USE_FONT_BACKEND */
+  return FRAME_RIF (f)->per_char_metric (font, char2b, font_type);
+}
 
 /* EXPORT for RIF:
    Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
@@ -19178,9 +19566,9 @@ x_get_glyph_overhangs (glyph, f, left, right)
 
       face = get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
       font = face->font;
-      font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
+      font_info = FONT_INFO_FROM_FACE (f, face);
       if (font  /* ++KFS: Should this be font_info ?  */
-         && (pcm = rif->per_char_metric (font, &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;
@@ -19188,6 +19576,13 @@ x_get_glyph_overhangs (glyph, f, left, right)
            *left = -pcm->lbearing;
        }
     }
+  else if (glyph->type == COMPOSITE_GLYPH)
+    {
+      struct composition *cmp = composition_table[glyph->u.cmp_id];
+
+      *right = cmp->rbearing - cmp->pixel_width;
+      *left = - cmp->lbearing;
+    }
 }
 
 
@@ -19301,70 +19696,6 @@ right_overwriting (s)
 }
 
 
-/* Get face and two-byte form of character C in face FACE_ID on frame
-   F.  The encoding of C is returned in *CHAR2B.  MULTIBYTE_P non-zero
-   means we want to display multibyte text.  DISPLAY_P non-zero means
-   make sure that X resources for the face returned are allocated.
-   Value is a pointer to a realized face that is ready for display if
-   DISPLAY_P is non-zero.  */
-
-static INLINE struct face *
-get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
-     struct frame *f;
-     int c, face_id;
-     XChar2b *char2b;
-     int multibyte_p, display_p;
-{
-  struct face *face = FACE_FROM_ID (f, face_id);
-
-  if (!multibyte_p)
-    {
-      /* Unibyte case.  We don't have to encode, but we have to make
-        sure to use a face suitable for unibyte.  */
-      STORE_XCHAR2B (char2b, 0, c);
-      face_id = FACE_FOR_CHAR (f, face, c);
-      face = FACE_FROM_ID (f, face_id);
-    }
-  else if (c < 128)
-    {
-      /* Case of ASCII in a face known to fit ASCII.  */
-      STORE_XCHAR2B (char2b, 0, c);
-    }
-  else
-    {
-      int c1, c2, charset;
-
-      /* Split characters into bytes.  If c2 is -1 afterwards, C is
-        really a one-byte character so that byte1 is zero.  */
-      SPLIT_CHAR (c, charset, c1, c2);
-      if (c2 > 0)
-       STORE_XCHAR2B (char2b, c1, c2);
-      else
-       STORE_XCHAR2B (char2b, 0, c1);
-
-      /* Maybe encode the character in *CHAR2B.  */
-      if (face->font != NULL)
-       {
-         struct font_info *font_info
-           = FONT_INFO_FROM_ID (f, face->font_info_id);
-         if (font_info)
-           rif->encode_char (c, char2b, font_info, 0);
-       }
-    }
-
-  /* Make sure X resources of the face are allocated.  */
-#ifdef HAVE_X_WINDOWS
-  if (display_p)
-#endif
-    {
-      xassert (face != NULL);
-      PREPARE_FACE_FOR_DISPLAY (f, face);
-    }
-
-  return face;
-}
-
-
 /* Set background width of glyph string S.  START is the index of the
    first glyph following S.  LAST_X is the right-most x-position + 1
    in the drawing area.  */
@@ -19411,8 +19742,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;
@@ -19422,8 +19753,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;
@@ -19504,10 +19835,9 @@ compute_overhangs_and_x (s, x, backward_p)
 #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X)           \
      do                                                                           \
        {                                                                  \
-        int c, face_id;                                                   \
+        int face_id;                                                      \
         XChar2b *char2b;                                                  \
                                                                           \
-        c = (row)->glyphs[area][START].u.ch;                              \
         face_id = (row)->glyphs[area][START].face_id;                     \
                                                                           \
         s = (struct glyph_string *) alloca (sizeof *s);                   \
@@ -19530,49 +19860,34 @@ compute_overhangs_and_x (s, x, backward_p)
    x-position of the drawing area.  */
 
 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
-  do {                                                                   \
-    int cmp_id = (row)->glyphs[area][START].u.cmp_id;                    \
-    int face_id = (row)->glyphs[area][START].face_id;                    \
-    struct face *base_face = FACE_FROM_ID (f, face_id);                          \
-    struct composition *cmp = composition_table[cmp_id];                 \
-    int glyph_len = cmp->glyph_len;                                      \
-    XChar2b *char2b;                                                     \
-    struct face **faces;                                                 \
-    struct glyph_string *first_s = NULL;                                 \
-    int n;                                                               \
-                                                                         \
-    base_face = base_face->ascii_face;                                   \
-    char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len);                  \
-    faces = (struct face **) alloca ((sizeof *faces) * glyph_len);       \
-    /* At first, fill in `char2b' and `faces'.  */                       \
-    for (n = 0; n < glyph_len; n++)                                      \
-      {                                                                          \
-       int c = COMPOSITION_GLYPH (cmp, n);                               \
-       int this_face_id = FACE_FOR_CHAR (f, base_face, c);               \
-       faces[n] = FACE_FROM_ID (f, this_face_id);                        \
-       get_char_face_and_encoding (f, c, this_face_id,                   \
-                                   char2b + n, 1, 1);                    \
-      }                                                                          \
-                                                                         \
-    /* Make glyph_strings for each glyph sequence that is drawable by    \
-       the same face, and append them to HEAD/TAIL.  */                          \
-    for (n = 0; n < cmp->glyph_len;)                                     \
-      {                                                                          \
-       s = (struct glyph_string *) alloca (sizeof *s);                   \
-       INIT_GLYPH_STRING (s, char2b + n, w, row, area, START, HL);       \
-       append_glyph_string (&(HEAD), &(TAIL), s);                        \
-       s->cmp = cmp;                                                     \
-       s->gidx = n;                                                      \
-       s->x = (X);                                                       \
-                                                                         \
-       if (n == 0)                                                       \
-         first_s = s;                                                    \
-                                                                         \
-       n = fill_composite_glyph_string (s, faces, overlaps);             \
-      }                                                                          \
-                                                                         \
-    ++START;                                                             \
-    s = first_s;                                                         \
+  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;                      \
+    struct composition *cmp = composition_table[cmp_id];                   \
+    XChar2b *char2b;                                                       \
+    struct glyph_string *first_s;                                          \
+    int n;                                                                 \
+                                                                           \
+    char2b = (XChar2b *) alloca ((sizeof *char2b) * cmp->glyph_len);       \
+                                                                           \
+    /* Make glyph_strings for each glyph sequence that is drawable by      \
+       the same face, and append them to HEAD/TAIL.  */                            \
+    for (n = 0; n < cmp->glyph_len;)                                       \
+      {                                                                            \
+       s = (struct glyph_string *) alloca (sizeof *s);                     \
+       INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);             \
+       append_glyph_string (&(HEAD), &(TAIL), s);                          \
+       s->cmp = cmp;                                                       \
+       s->gidx = n;                                                        \
+       s->x = (X);                                                         \
+       if (n == 0)                                                         \
+         first_s = s;                                                      \
+       n = fill_composite_glyph_string (s, base_face, overlaps);           \
+      }                                                                            \
+                                                                           \
+    ++START;                                                               \
+    s = first_s;                                                           \
   } while (0)
 
 
@@ -19619,8 +19934,11 @@ compute_overhangs_and_x (s, x, backward_p)
                 abort ();                                                 \
               }                                                           \
                                                                           \
-             set_glyph_string_background_width (s, START, LAST_X);        \
-            (X) += s->width;                                              \
+            if (s)                                                        \
+              {                                                           \
+                set_glyph_string_background_width (s, START, LAST_X);     \
+                (X) += s->width;                                          \
+              }                                                           \
             }                                                             \
        }                                                                  \
      while (0)
@@ -19654,7 +19972,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
      int x;
      struct glyph_row *row;
      enum glyph_row_area area;
-     int start, end;
+     EMACS_INT start, end;
      enum draw_glyphs_face hl;
      int overlaps;
 {
@@ -19711,9 +20029,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
@@ -19774,6 +20092,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
       if (i >= 0)
        {
          clip_tail = tail;
+         i++;                  /* We must include the Ith glyph.  */
          BUILD_GLYPH_STRINGS (end, i, h, t,
                               DRAW_NORMAL_TEXT, x, last_x);
          for (s = h; s; s = s->next)
@@ -19791,7 +20110,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
@@ -19856,7 +20175,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;
@@ -19866,7 +20196,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;
@@ -20050,9 +20379,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);
@@ -20363,7 +20692,7 @@ calc_line_height_property (it, val, font, boff, override)
       struct face *face;
       struct font_info *font_info;
 
-      face_id = lookup_named_face (it->f, face_name, ' ', 0);
+      face_id = lookup_named_face (it->f, face_name, 0);
       if (face_id < 0)
        return make_number (-1);
 
@@ -20372,7 +20701,7 @@ calc_line_height_property (it, val, font, boff, override)
       if (font == NULL)
        return make_number (-1);
 
-      font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+      font_info = FONT_INFO_FROM_FACE (it->f, face);
       boff = font_info->baseline_offset;
       if (font_info->vertical_centering)
        boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
@@ -20436,23 +20765,17 @@ x_produce_glyphs (it)
       /* Maybe translate single-byte characters to multibyte, or the
         other way.  */
       it->char_to_display = it->c;
-      if (!ASCII_BYTE_P (it->c))
+      if (!ASCII_BYTE_P (it->c)
+         && ! it->multibyte_p)
        {
-         if (unibyte_display_via_language_environment
-             && SINGLE_BYTE_CHAR_P (it->c)
-             && (it->c >= 0240
-                 || !NILP (Vnonascii_translation_table)))
-           {
-             it->char_to_display = unibyte_char_to_multibyte (it->c);
-             it->multibyte_p = 1;
-             it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
-             face = FACE_FROM_ID (it->f, it->face_id);
-           }
-         else if (!SINGLE_BYTE_CHAR_P (it->c)
-                  && !it->multibyte_p)
+         if (SINGLE_BYTE_CHAR_P (it->c)
+             && unibyte_display_via_language_environment)
+           it->char_to_display = unibyte_char_to_multibyte (it->c);
+         if (! SINGLE_BYTE_CHAR_P (it->char_to_display))
            {
              it->multibyte_p = 1;
-             it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+             it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display,
+                                          -1, Qnil);
              face = FACE_FROM_ID (it->f, it->face_id);
            }
        }
@@ -20472,7 +20795,7 @@ x_produce_glyphs (it)
        }
       else
        {
-         font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+         font_info = FONT_INFO_FROM_FACE (it->f, face);
          boff = font_info->baseline_offset;
          if (font_info->vertical_centering)
            boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
@@ -20486,20 +20809,20 @@ x_produce_glyphs (it)
 
          it->nglyphs = 1;
 
-         pcm = rif->per_char_metric (font, &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)
            {
@@ -20595,6 +20918,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')
        {
@@ -20713,20 +21040,24 @@ x_produce_glyphs (it)
 
          /* If we found a font, this font should give us the right
             metrics.  If we didn't find a font, use the frame's
-            default font and calculate the width of the character
-            from the charset width; this is what old redisplay code
-            did.  */
+            default font and calculate the width of the character by
+            multiplying the width of font by the width of the
+            character.  */
 
-         pcm = rif->per_char_metric (font, &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)
            {
-             int charset = CHAR_CHARSET (it->char_to_display);
+             int char_width = CHAR_WIDTH (it->char_to_display);
 
+             if (char_width == 0)
+               /* This is a non spacing character.  But, as we are
+                  going to display an empty box, the box must occupy
+                  at least one column.  */
+               char_width = 1;
              it->glyph_not_available_p = 1;
-             it->pixel_width = (FRAME_COLUMN_WIDTH (it->f)
-                                * CHARSET_WIDTH (charset));
+             it->pixel_width = FRAME_COLUMN_WIDTH (it->f) * char_width;
              it->phys_ascent = FONT_BASE (font) + boff;
              it->phys_descent = FONT_DESCENT (font) - boff;
            }
@@ -20768,107 +21099,137 @@ 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;
     }
   else if (it->what == IT_COMPOSITION)
     {
       /* Note: A composition is represented as one glyph in the
-        glyph matrix.  There are no padding glyphs.  */
-      XChar2b char2b;
-      XFontStruct *font;
+        glyph matrix.  There are no padding glyphs.
+
+        Important is that pixel_width, ascent, and descent are the
+        values of what is drawn by draw_glyphs (i.e. the values of
+        the overall glyphs composed).  */
       struct face *face = FACE_FROM_ID (it->f, it->face_id);
-      XCharStruct *pcm;
-      int font_not_found_p;
-      struct font_info *font_info;
       int boff;                        /* baseline offset */
       struct composition *cmp = composition_table[it->cmp_id];
+      int glyph_len = cmp->glyph_len;
+      XFontStruct *font = face->font;
 
-      /* Maybe translate single-byte characters to multibyte.  */
-      it->char_to_display = it->c;
-      if (unibyte_display_via_language_environment
-         && SINGLE_BYTE_CHAR_P (it->c)
-         && (it->c >= 0240
-             || (it->c >= 0200
-                 && !NILP (Vnonascii_translation_table))))
-       {
-         it->char_to_display = unibyte_char_to_multibyte (it->c);
-       }
-
-      /* Get face and font to use.  Encode IT->char_to_display.  */
-      it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
-      face = FACE_FROM_ID (it->f, it->face_id);
-      get_char_face_and_encoding (it->f, it->char_to_display, it->face_id,
-                                 &char2b, it->multibyte_p, 0);
-      font = face->font;
+      it->nglyphs = 1;
 
-      /* When no suitable font found, use the default font.  */
-      font_not_found_p = font == NULL;
-      if (font_not_found_p)
+#ifdef USE_FONT_BACKEND
+      if (cmp->method == COMPOSITION_WITH_GLYPH_STRING)
        {
-         font = FRAME_FONT (it->f);
-         boff = FRAME_BASELINE_OFFSET (it->f);
-         font_info = NULL;
+         PREPARE_FACE_FOR_DISPLAY (it->f, face);
+         font_prepare_composition (cmp, it->f);
        }
       else
-       {
-         font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
-         boff = font_info->baseline_offset;
-         if (font_info->vertical_centering)
-           boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
-       }
-
-      /* There are no padding glyphs, so there is only one glyph to
-        produce for the composition.  Important is that pixel_width,
-        ascent and descent are the values of what is drawn by
-        draw_glyphs (i.e. the values of the overall glyphs composed).  */
-      it->nglyphs = 1;
-
+#endif /* USE_FONT_BACKEND */
       /* If we have not yet calculated pixel size data of glyphs of
         the composition for the current face font, calculate them
         now.  Theoretically, we have to check all fonts for the
         glyphs, but that requires much time and memory space.  So,
         here we check only the font of the first glyph.  This leads
-        to incorrect display very rarely, and C-l (recenter) can
-        correct the display anyway.  */
-      if (cmp->font != (void *) font)
-       {
-         /* Ascent and descent of the font of the first character of
-            this composition (adjusted by baseline offset).  Ascent
-            and descent of overall glyphs should not be less than
-            them respectively.  */
-         int font_ascent = FONT_BASE (font) + boff;
-         int font_descent = FONT_DESCENT (font) - boff;
+        to incorrect display, but it's very rare, and C-l (recenter)
+        can correct the display anyway.  */
+      if (! cmp->font || cmp->font != font)
+       {
+         /* Ascent and descent of the font of the first character
+            of this composition (adjusted by baseline offset).
+            Ascent and descent of overall glyphs should not be less
+            than them respectively.  */
+         int font_ascent, font_descent, font_height;
          /* Bounding box of the overall glyphs.  */
          int leftmost, rightmost, lowest, highest;
+         int lbearing, rbearing;
          int i, width, ascent, descent;
+         int left_padded = 0, right_padded = 0;
+         int face_id;
+         int c;
+         XChar2b char2b;
+         XCharStruct *pcm;
+         int font_not_found_p;
+         struct font_info *font_info;
+         int pos;
+
+         for (glyph_len = cmp->glyph_len; glyph_len > 0; glyph_len--)
+           if ((c = COMPOSITION_GLYPH (cmp, glyph_len - 1)) != '\t')
+             break;
+         if (glyph_len < cmp->glyph_len)
+           right_padded = 1;
+         for (i = 0; i < glyph_len; i++)
+           {
+             if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
+               break;
+             cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
+           }
+         if (i > 0)
+           left_padded = 1;
+
+         pos = (STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
+                : IT_CHARPOS (*it));
+         /* When no suitable font found, use the default font.  */
+         font_not_found_p = font == NULL;
+         if (font_not_found_p)
+           {
+             face = face->ascii_face;
+             font = face->font;
+           }
+         font_info = FONT_INFO_FROM_FACE (it->f, face);
+         boff = font_info->baseline_offset;
+         if (font_info->vertical_centering)
+           boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+         font_ascent = FONT_BASE (font) + boff;
+         font_descent = FONT_DESCENT (font) - boff;
+         font_height = FONT_HEIGHT (font);
 
          cmp->font = (void *) font;
 
+         pcm = NULL;
+         if (! font_not_found_p)
+           {
+             get_char_face_and_encoding (it->f, c, it->face_id,
+                                         &char2b, it->multibyte_p, 0);
+             pcm = get_per_char_metric (it->f, font, font_info, &char2b,
+                                        FONT_TYPE_FOR_MULTIBYTE (font, c));
+           }
+
          /* Initialize the bounding box.  */
-         if (font_info
-             && (pcm = rif->per_char_metric (font, &char2b,
-                                             FONT_TYPE_FOR_MULTIBYTE (font, it->c))))
+         if (pcm)
            {
              width = pcm->width;
              ascent = pcm->ascent;
              descent = pcm->descent;
+             lbearing = pcm->lbearing;
+             rbearing = pcm->rbearing;
            }
          else
            {
              width = FONT_WIDTH (font);
              ascent = FONT_BASE (font);
              descent = FONT_DESCENT (font);
+             lbearing = 0;
+             rbearing = width;
            }
 
          rightmost = width;
+         leftmost = 0;
          lowest = - descent + boff;
          highest = ascent + boff;
-         leftmost = 0;
 
-         if (font_info
+         if (! font_not_found_p
              && font_info->default_ascent
              && CHAR_TABLE_P (Vuse_default_ascent)
              && !NILP (Faref (Vuse_default_ascent,
@@ -20876,123 +21237,138 @@ x_produce_glyphs (it)
            highest = font_info->default_ascent + boff;
 
          /* Draw the first glyph at the normal position.  It may be
-            shifted to right later if some other glyphs are drawn at
-            the left.  */
-         cmp->offsets[0] = 0;
-         cmp->offsets[1] = boff;
+            shifted to right later if some other glyphs are drawn
+            at the left.  */
+         cmp->offsets[i * 2] = 0;
+         cmp->offsets[i * 2 + 1] = boff;
+         cmp->lbearing = lbearing;
+         cmp->rbearing = rbearing;
 
          /* Set cmp->offsets for the remaining glyphs.  */
-         for (i = 1; i < cmp->glyph_len; i++)
+         for (i++; i < glyph_len; i++)
            {
              int left, right, btm, top;
              int ch = COMPOSITION_GLYPH (cmp, i);
-             int face_id = FACE_FOR_CHAR (it->f, face, ch);
+             int face_id;
+             struct face *this_face;
+             int this_boff;
+
+             if (ch == '\t')
+               ch = ' ';
+             face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
+             this_face = FACE_FROM_ID (it->f, face_id);
+             font = this_face->font;
 
-             face = FACE_FROM_ID (it->f, face_id);
-             get_char_face_and_encoding (it->f, ch, face->id,
-                                         &char2b, it->multibyte_p, 0);
-             font = face->font;
              if (font == NULL)
-               {
-                 font = FRAME_FONT (it->f);
-                 boff = FRAME_BASELINE_OFFSET (it->f);
-                 font_info = NULL;
-               }
+               pcm = NULL;
              else
                {
-                 font_info
-                   = FONT_INFO_FROM_ID (it->f, face->font_info_id);
-                 boff = font_info->baseline_offset;
+                 font_info = FONT_INFO_FROM_FACE (it->f, this_face);
+                 this_boff = font_info->baseline_offset;
                  if (font_info->vertical_centering)
-                   boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+                   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 (it->f, font, font_info, &char2b,
+                                            FONT_TYPE_FOR_MULTIBYTE (font,
+                                                                     ch));
                }
-
-             if (font_info
-                 && (pcm = rif->per_char_metric (font, &char2b,
-                                                 FONT_TYPE_FOR_MULTIBYTE (font, ch))))
+             if (! pcm)
+               cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
+             else
                {
                  width = pcm->width;
                  ascent = pcm->ascent;
                  descent = pcm->descent;
-               }
-             else
-               {
-                 width = FONT_WIDTH (font);
-                 ascent = 1;
-                 descent = 0;
-               }
+                 lbearing = pcm->lbearing;
+                 rbearing = pcm->rbearing;
+                 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
+                   {
+                     /* Relative composition with or without
+                        alternate chars.  */
+                     left = (leftmost + rightmost - width) / 2;
+                     btm = - descent + boff;
+                     if (font_info->relative_compose
+                         && (! CHAR_TABLE_P (Vignore_relative_composition)
+                             || NILP (Faref (Vignore_relative_composition,
+                                             make_number (ch)))))
+                       {
 
-             if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
-               {
-                 /* Relative composition with or without
-                    alternate chars.  */
-                 left = (leftmost + rightmost - width) / 2;
-                 btm = - descent + boff;
-                 if (font_info && font_info->relative_compose
-                     && (! CHAR_TABLE_P (Vignore_relative_composition)
-                         || NILP (Faref (Vignore_relative_composition,
-                                         make_number (ch)))))
+                         if (- descent >= font_info->relative_compose)
+                           /* One extra pixel between two glyphs.  */
+                           btm = highest + 1;
+                         else if (ascent <= 0)
+                           /* One extra pixel between two glyphs.  */
+                           btm = lowest - 1 - ascent - descent;
+                       }
+                   }
+                 else
                    {
+                     /* A composition rule is specified by an integer
+                        value that encodes global and new reference
+                        points (GREF and NREF).  GREF and NREF are
+                        specified by numbers as below:
+
+                        0---1---2 -- ascent
+                        |       |
+                        |       |
+                        |       |
+                        9--10--11 -- center
+                        |       |
+                        ---3---4---5--- baseline
+                        |       |
+                        6---7---8 -- descent
+                     */
+                     int rule = COMPOSITION_RULE (cmp, i);
+                     int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
+
+                     COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
+                     grefx = gref % 3, nrefx = nref % 3;
+                     grefy = gref / 3, nrefy = nref / 3;
+                     if (xoff)
+                       xoff = font_height * (xoff - 128) / 256;
+                     if (yoff)
+                       yoff = font_height * (yoff - 128) / 256;
+
+                     left = (leftmost
+                             + grefx * (rightmost - leftmost) / 2
+                             - nrefx * width / 2
+                             + xoff);
+
+                     btm = ((grefy == 0 ? highest
+                             : grefy == 1 ? 0
+                             : grefy == 2 ? lowest
+                             : (highest + lowest) / 2)
+                            - (nrefy == 0 ? ascent + descent
+                               : nrefy == 1 ? descent - boff
+                               : nrefy == 2 ? 0
+                               : (ascent + descent) / 2)
+                            + yoff);
+                   }
 
-                     if (- descent >= font_info->relative_compose)
-                       /* One extra pixel between two glyphs.  */
-                       btm = highest + 1;
-                     else if (ascent <= 0)
-                       /* One extra pixel between two glyphs.  */
-                       btm = lowest - 1 - ascent - descent;
+                 cmp->offsets[i * 2] = left;
+                 cmp->offsets[i * 2 + 1] = btm + descent;
+
+                 /* Update the bounding box of the overall glyphs. */
+                 if (width > 0)
+                   {
+                     right = left + width;
+                     if (left < leftmost)
+                       leftmost = left;
+                     if (right > rightmost)
+                       rightmost = right;
                    }
+                 top = btm + descent + ascent;
+                 if (top > highest)
+                   highest = top;
+                 if (btm < lowest)
+                   lowest = btm;
+
+                 if (cmp->lbearing > left + lbearing)
+                   cmp->lbearing = left + lbearing;
+                 if (cmp->rbearing < left + rbearing)
+                   cmp->rbearing = left + rbearing;
                }
-             else
-               {
-                 /* A composition rule is specified by an integer
-                    value that encodes global and new reference
-                    points (GREF and NREF).  GREF and NREF are
-                    specified by numbers as below:
-
-                       0---1---2 -- ascent
-                       |       |
-                       |       |
-                       |       |
-                       9--10--11 -- center
-                       |       |
-                    ---3---4---5--- baseline
-                       |       |
-                       6---7---8 -- descent
-                 */
-                 int rule = COMPOSITION_RULE (cmp, i);
-                 int gref, nref, grefx, grefy, nrefx, nrefy;
-
-                 COMPOSITION_DECODE_RULE (rule, gref, nref);
-                 grefx = gref % 3, nrefx = nref % 3;
-                 grefy = gref / 3, nrefy = nref / 3;
-
-                 left = (leftmost
-                         + grefx * (rightmost - leftmost) / 2
-                         - nrefx * width / 2);
-                 btm = ((grefy == 0 ? highest
-                         : grefy == 1 ? 0
-                         : grefy == 2 ? lowest
-                         : (highest + lowest) / 2)
-                        - (nrefy == 0 ? ascent + descent
-                           : nrefy == 1 ? descent - boff
-                           : nrefy == 2 ? 0
-                           : (ascent + descent) / 2));
-               }
-
-             cmp->offsets[i * 2] = left;
-             cmp->offsets[i * 2 + 1] = btm + descent;
-
-             /* Update the bounding box of the overall glyphs. */
-             right = left + width;
-             top = btm + descent + ascent;
-             if (left < leftmost)
-               leftmost = left;
-             if (right > rightmost)
-               rightmost = right;
-             if (top > highest)
-               highest = top;
-             if (btm < lowest)
-               lowest = btm;
            }
 
          /* If there are glyphs whose x-offsets are negative,
@@ -21003,6 +21379,21 @@ x_produce_glyphs (it)
              for (i = 0; i < cmp->glyph_len; i++)
                cmp->offsets[i * 2] -= leftmost;
              rightmost -= leftmost;
+             cmp->lbearing -= leftmost;
+             cmp->rbearing -= leftmost;
+           }
+
+         if (left_padded && cmp->lbearing < 0)
+           {
+             for (i = 0; i < cmp->glyph_len; i++)
+               cmp->offsets[i * 2] -= cmp->lbearing;
+             rightmost -= cmp->lbearing;
+             cmp->rbearing -= cmp->lbearing;
+             cmp->lbearing = 0;
+           }
+         if (right_padded && rightmost < cmp->rbearing)
+           {
+             rightmost = cmp->rbearing;
            }
 
          cmp->pixel_width = rightmost;
@@ -21014,10 +21405,14 @@ x_produce_glyphs (it)
            cmp->descent = font_descent;
        }
 
+      if (it->glyph_row
+         && (cmp->lbearing < 0
+             || cmp->rbearing > cmp->pixel_width))
+       it->glyph_row->contains_overlapping_glyphs_p = 1;
+
       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;
@@ -21042,6 +21437,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);
@@ -21124,7 +21523,8 @@ x_insert_glyphs (start, len)
   int line_height, shift_by_width, shifted_region_width;
   struct glyph_row *row;
   struct glyph *glyph;
-  int frame_x, frame_y, hpos;
+  int frame_x, frame_y;
+  EMACS_INT hpos;
 
   xassert (updated_window && updated_row);
   BLOCK_INPUT;
@@ -21149,8 +21549,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];
@@ -21232,8 +21632,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;
     }
 }
@@ -21754,7 +22154,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.  */
@@ -21851,9 +22251,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);
 }
 
 
@@ -22002,11 +22402,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:
@@ -22082,7 +22482,7 @@ cursor_in_mouse_face_p (w)
 static int
 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
      struct window *w;
-     int charpos;
+     EMACS_INT charpos;
      int *hpos, *vpos, *x, *y;
      Lisp_Object stop;
 {
@@ -22170,7 +22570,7 @@ fast_find_position (w, charpos, hpos, vpos, x, y, stop)
 static int
 fast_find_position (w, pos, hpos, vpos, x, y, stop)
      struct window *w;
-     int pos;
+     EMACS_INT pos;
      int *hpos, *vpos, *x, *y;
      Lisp_Object stop;
 {
@@ -22284,7 +22684,7 @@ fast_find_position (w, pos, hpos, vpos, x, y, stop)
 static int
 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
      struct window *w;
-     int pos;
+     EMACS_INT pos;
      Lisp_Object object;
      int *hpos, *vpos, *x, *y;
      int right_p;
@@ -22314,8 +22714,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)))
@@ -22445,7 +22845,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;
 }
 
@@ -22525,7 +22924,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
@@ -22672,7 +23071,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;
 
@@ -23024,7 +23423,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);
@@ -23058,7 +23457,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))
@@ -23098,7 +23497,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,
@@ -23145,7 +23544,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
@@ -23446,10 +23845,11 @@ expose_line (w, row, r)
    LAST_OVERLAPPING_ROW is the last such row.  */
 
 static void
-expose_overlaps (w, first_overlapping_row, last_overlapping_row)
+expose_overlaps (w, first_overlapping_row, last_overlapping_row, r)
      struct window *w;
      struct glyph_row *first_overlapping_row;
      struct glyph_row *last_overlapping_row;
+     XRectangle *r;
 {
   struct glyph_row *row;
 
@@ -23458,6 +23858,7 @@ expose_overlaps (w, first_overlapping_row, last_overlapping_row)
       {
        xassert (row->enabled_p && !row->mode_line_p);
 
+       row->clip = r;
        if (row->used[LEFT_MARGIN_AREA])
          x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
 
@@ -23466,6 +23867,7 @@ expose_overlaps (w, first_overlapping_row, last_overlapping_row)
 
        if (row->used[RIGHT_MARGIN_AREA])
          x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
+       row->clip = NULL;
       }
 }
 
@@ -23511,8 +23913,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;
 }
 
 
@@ -23524,6 +23926,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 */
@@ -23544,9 +23948,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))
@@ -23557,9 +23961,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);
     }
 }
 
@@ -23647,8 +24051,22 @@ expose_window (w, fr)
                  last_overlapping_row = row;
                }
 
+             row->clip = fr;
              if (expose_line (w, row, &r))
                mouse_face_overwritten_p = 1;
+             row->clip = NULL;
+           }
+         else if (row->overlapping_p)
+           {
+             /* We must redraw a row overlapping the exposed area.  */
+             if (y0 < r.y
+                 ? y0 + row->phys_height > r.y
+                 : y0 + row->ascent - row->phys_ascent < r.y +r.height)
+               {
+                 if (first_overlapping_row == NULL)
+                   first_overlapping_row = row;
+                 last_overlapping_row = row;
+               }
            }
 
          if (y1 >= yb)
@@ -23669,7 +24087,8 @@ expose_window (w, fr)
        {
          /* Fix the display of overlapping rows.  */
          if (first_overlapping_row)
-           expose_overlaps (w, first_overlapping_row, last_overlapping_row);
+           expose_overlaps (w, first_overlapping_row, last_overlapping_row,
+                            fr);
 
          /* Draw border between windows.  */
          x_draw_vertical_border (w);
@@ -23899,6 +24318,7 @@ syms_of_xdisp ()
   defsubr (&Slookup_image_map);
 #endif
   defsubr (&Sformat_mode_line);
+  defsubr (&Sinvisible_p);
 
   staticpro (&Qmenu_bar_update_hook);
   Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
@@ -23912,6 +24332,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");
 
@@ -24195,7 +24618,7 @@ and is used only on frames for which no explicit name has been set
     = Vframe_title_format
     = Fcons (intern ("multiple-frames"),
             Fcons (build_string ("%b"),
-                   Fcons (Fcons (empty_string,
+                   Fcons (Fcons (empty_unibyte_string,
                                  Fcons (intern ("invocation-name"),
                                         Fcons (build_string ("@"),
                                                Fcons (intern ("system-name"),
@@ -24223,6 +24646,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.
@@ -24332,6 +24760,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