]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Merged in changes from CVS trunk.
[gnu-emacs] / src / xdisp.c
index 334ebb72fcb4190792b3af8f33774ac20f92aca8..b0a8f953c9c26f5db2343c679fbcb400b2cb7858 100644 (file)
@@ -215,6 +215,8 @@ extern int pending_menu_activation;
 extern int interrupt_input;
 extern int command_loop_level;
 
+extern Lisp_Object do_mouse_tracking;
+
 extern int minibuffer_auto_raise;
 extern Lisp_Object Vminibuffer_list;
 
@@ -262,6 +264,10 @@ int mouse_autoselect_window;
 
 int auto_raise_tool_bar_buttons_p;
 
+/* Non-zero means to reposition window if cursor line is only partially visible.  */
+
+int make_cursor_line_fully_visible_p;
+
 /* Margin around tool bar buttons in pixels.  */
 
 Lisp_Object Vtool_bar_button_margin;
@@ -306,6 +312,7 @@ Lisp_Object Qline_height, Qtotal;
 extern Lisp_Object Qheight;
 extern Lisp_Object QCwidth, QCheight, QCascent;
 extern Lisp_Object Qscroll_bar;
+extern Lisp_Object Qcursor;
 
 /* Non-nil means highlight trailing whitespace.  */
 
@@ -335,6 +342,11 @@ Lisp_Object Vvoid_text_area_pointer;
 
 Lisp_Object Qtrailing_whitespace;
 
+/* Name and number of the face used to highlight escape glyphs.  */
+
+Lisp_Object Qescape_glyph;
+int escape_glyph_face;
+
 /* The symbol `image' which is the car of the lists used to represent
    images in Lisp.  */
 
@@ -766,10 +778,6 @@ enum move_it_result
 #define CLEAR_FACE_CACHE_COUNT 500
 static int clear_face_cache_count;
 
-/* Record the previous terminal frame we displayed.  */
-
-static struct frame *previous_terminal_frame;
-
 /* Non-zero while redisplay_internal is in progress.  */
 
 int redisplaying_p;
@@ -800,7 +808,7 @@ static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
 \f
 /* Function prototypes.  */
 
-static void setup_for_ellipsis P_ ((struct it *));
+static void setup_for_ellipsis P_ ((struct it *, int));
 static void mark_window_display_accurate_1 P_ ((struct window *, int));
 static int single_display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
 static int display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
@@ -885,7 +893,7 @@ static void next_overlay_string P_ ((struct it *));
 static void reseat P_ ((struct it *, struct text_pos, int));
 static void reseat_1 P_ ((struct it *, struct text_pos, int));
 static void back_to_previous_visible_line_start P_ ((struct it *));
-static void reseat_at_previous_visible_line_start P_ ((struct it *));
+void reseat_at_previous_visible_line_start P_ ((struct it *));
 static void reseat_at_next_visible_line_start P_ ((struct it *, int));
 static int next_element_from_display_vector P_ ((struct it *));
 static int next_element_from_string P_ ((struct it *));
@@ -1782,7 +1790,8 @@ get_glyph_string_clip_rect (s, nr)
 
       /* If drawing a tool-bar window, draw it over the internal border
         at the top of the window.  */
-      if (s->w == XWINDOW (s->f->tool_bar_window))
+      if (WINDOWP (s->f->tool_bar_window)
+         && s->w == XWINDOW (s->f->tool_bar_window))
        r.y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
     }
 
@@ -2060,7 +2069,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
   XSETWINDOW (it->window, w);
   it->w = w;
   it->f = XFRAME (w->frame);
-
+  
   /* Extra space between lines (on window systems only).  */
   if (base_face_id == DEFAULT_FACE_ID
       && FRAME_WINDOW_P (it->f))
@@ -2072,13 +2081,14 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
                                  * FRAME_LINE_HEIGHT (it->f));
       else if (it->f->extra_line_spacing > 0)
        it->extra_line_spacing = it->f->extra_line_spacing;
+      it->max_extra_line_spacing = 0;
     }
 
   /* 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);
@@ -3218,7 +3228,7 @@ handle_invisible_prop (it)
              it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
            }
          else if (display_ellipsis_p)
-           setup_for_ellipsis (it);
+           setup_for_ellipsis (it, 0);
        }
     }
 
@@ -3226,14 +3236,17 @@ handle_invisible_prop (it)
 }
 
 
-/* Make iterator IT return `...' next.  */
+/* Make iterator IT return `...' next.
+   Replaces LEN characters from buffer.  */
 
 static void
-setup_for_ellipsis (it)
+setup_for_ellipsis (it, len)
      struct it *it;
+     int len;
 {
-  if (it->dp
-      && VECTORP (DISP_INVIS_VECTOR (it->dp)))
+  /* Use the display table definition for `...'.  Invalid glyphs
+     will be handled by the method returning elements from dpvec.  */
+  if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
     {
       struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
       it->dpvec = v->contents;
@@ -3246,12 +3259,12 @@ setup_for_ellipsis (it)
       it->dpend = default_invis_vector + 3;
     }
 
-  /* The ellipsis display does not replace the display of the
-     character at the new position.  Indicate this by setting
-     IT->dpvec_char_len to zero.  */
-  it->dpvec_char_len = 0;
-
+  it->dpvec_char_len = len;
   it->current.dpvec_index = 0;
+
+  /* Remember the current face id in case glyphs specify faces.
+     IT's face is restored in set_iterator_to_next.  */
+  it->saved_face_id = it->face_id;
   it->method = next_element_from_display_vector;
 }
 
@@ -3530,7 +3543,7 @@ handle_single_display_prop (it, prop, object, position,
           && CONSP (XCDR (prop)))
     {
       /* `(raise FACTOR)'.  */
-      if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+      if (!FRAME_WINDOW_P (it->f))
        return 0;
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -3566,28 +3579,28 @@ handle_single_display_prop (it, prop, object, position,
              || EQ (XCAR (prop), Qright_fringe))
          && CONSP (XCDR (prop)))
        {
-         unsigned face_id = DEFAULT_FACE_ID;
+         int face_id = DEFAULT_FACE_ID;
+         int fringe_bitmap;
 
          /* Save current settings of IT so that we can restore them
             when we are finished with the glyph property value.  */
 
          /* `(left-fringe BITMAP FACE)'.  */
-         if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+         if (!FRAME_WINDOW_P (it->f))
            return 0;
 
 #ifdef HAVE_WINDOW_SYSTEM
          value = XCAR (XCDR (prop));
-         if (!NUMBERP (value)
-             || !valid_fringe_bitmap_id_p (XINT (value)))
+         if (!SYMBOLP (value)
+             || !(fringe_bitmap = lookup_fringe_bitmap (value)))
            return 0;
 
          if (CONSP (XCDR (XCDR (prop))))
            {
              Lisp_Object face_name = XCAR (XCDR (XCDR (prop)));
-
-             face_id = lookup_named_face (it->f, face_name, 'A');
-             if (face_id < 0)
-               return 0;
+             int face_id2 = lookup_named_face (it->f, face_name, 'A', 0);
+             if (face_id2 >= 0)
+               face_id = face_id2;
            }
 
          push_it (it);
@@ -3607,12 +3620,12 @@ handle_single_display_prop (it, prop, object, position,
 
          if (EQ (XCAR (prop), Qleft_fringe))
            {
-             it->left_user_fringe_bitmap = XINT (value);
+             it->left_user_fringe_bitmap = fringe_bitmap;
              it->left_user_fringe_face_id = face_id;
            }
          else
            {
-             it->right_user_fringe_bitmap = XINT (value);
+             it->right_user_fringe_bitmap = fringe_bitmap;
              it->right_user_fringe_face_id = face_id;
            }
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -3646,7 +3659,7 @@ handle_single_display_prop (it, prop, object, position,
 
       valid_p = (STRINGP (value)
 #ifdef HAVE_WINDOW_SYSTEM
-                || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
+                || (FRAME_WINDOW_P (it->f) && valid_image_p (value))
 #endif /* not HAVE_WINDOW_SYSTEM */
                 || (CONSP (value) && EQ (XCAR (value), Qspace)));
 
@@ -3693,11 +3706,14 @@ handle_single_display_prop (it, prop, object, position,
 #ifdef HAVE_WINDOW_SYSTEM
          else
            {
-             it->what = IT_IMAGE;
-             it->image_id = lookup_image (it->f, value);
-             it->position = start_pos;
-             it->object = NILP (object) ? it->w->buffer : object;
-             it->method = next_element_from_image;
+              if (FRAME_WINDOW_P (it->f))
+                {
+                  it->what = IT_IMAGE;
+                  it->image_id = lookup_image (it->f, value);
+                  it->position = start_pos;
+                  it->object = NILP (object) ? it->w->buffer : object;
+                  it->method = next_element_from_image;
+                }
 
              /* Say that we haven't consumed the characters with
                 `display' property yet.  The call to pop_it in
@@ -4039,7 +4055,7 @@ next_overlay_string (it)
       /* If we have to display `...' for invisible text, set
         the iterator up for that.  */
       if (display_ellipsis_p)
-       setup_for_ellipsis (it);
+       setup_for_ellipsis (it, 0);
     }
   else
     {
@@ -4551,7 +4567,8 @@ back_to_previous_visible_line_start (it)
        {
          Lisp_Object prop;
 
-         prop = Fget_char_property (make_number (IT_CHARPOS (*it)),
+         /* Check the newline before point for invisibility.  */
+         prop = Fget_char_property (make_number (IT_CHARPOS (*it) - 1),
                                     Qinvisible, it->window);
          if (TEXT_PROP_MEANS_INVISIBLE (prop))
            visible_p = 0;
@@ -4582,7 +4599,7 @@ back_to_previous_visible_line_start (it)
    selective display.  At the end, update IT's overlay information,
    face information etc.  */
 
-static void
+void
 reseat_at_previous_visible_line_start (it)
      struct it *it;
 {
@@ -4830,7 +4847,10 @@ get_next_display_element (it)
      we hit the end of what we iterate over.  Performance note: the
      function pointer `method' used here turns out to be faster than
      using a sequence of if-statements.  */
-  int success_p = (*it->method) (it);
+  int success_p;
+
+ get_next:
+  success_p = (*it->method) (it);
 
   if (it->what == IT_CHARACTER)
     {
@@ -4862,14 +4882,14 @@ get_next_display_element (it)
                  it->dpvec = v->contents;
                  it->dpend = v->contents + v->size;
                  it->current.dpvec_index = 0;
+                 it->saved_face_id = it->face_id;
                  it->method = next_element_from_display_vector;
-                 success_p = get_next_display_element (it);
                }
              else
                {
                  set_iterator_to_next (it, 0);
-                 success_p = get_next_display_element (it);
                }
+             goto get_next;
            }
 
          /* Translate control characters into `\003' or `^C' form.
@@ -4887,13 +4907,19 @@ get_next_display_element (it)
             translated to octal form.  */
          else if ((it->c < ' '
                    && (it->area != TEXT_AREA
+                       /* In mode line, treat \n like other crl chars.  */
+                       || (it->c != '\n'
+                           && 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))
+                         || !CHAR_PRINTABLE_P (it->c)
+                         || it->c == 0x8ad
+                         || it->c == 0x8a0)
                       : (it->c >= 127
-                         && it->c == unibyte_char_to_multibyte (it->c))))
+                         && (!unibyte_display_via_language_environment
+                             || it->c == unibyte_char_to_multibyte (it->c)))))
            {
              /* IT->c is a control character which must be displayed
                 either as '\003' or as `^C' where the '\\' and '^'
@@ -4901,6 +4927,22 @@ get_next_display_element (it)
                 IT->ctl_chars with glyphs for what we have to
                 display.  Then, set IT->dpvec to these glyphs.  */
              GLYPH g;
+             int ctl_len;
+             int face_id = escape_glyph_face;
+
+             /* Find the face id if `escape-glyph' unless we recently did.  */
+             if (face_id < 0)
+               {
+                 Lisp_Object tem = Fget (Qescape_glyph, Qface);
+                 if (INTEGERP (tem))
+                   face_id = XINT (tem);
+                 else
+                   face_id = 0;
+                 /* If there's overflow, use 0 instead.  */
+                 if (FAST_GLYPH_FACE (FAST_MAKE_GLYPH (0, face_id)) != face_id)
+                   face_id = 0;
+                 escape_glyph_face = face_id;
+               }
 
              if (it->c < 128 && it->ctl_arrow_p)
                {
@@ -4910,19 +4952,27 @@ get_next_display_element (it)
                      && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
                    g = XINT (DISP_CTRL_GLYPH (it->dp));
                  else
-                   g = FAST_MAKE_GLYPH ('^', 0);
+                   g = FAST_MAKE_GLYPH ('^', face_id);
                  XSETINT (it->ctl_chars[0], g);
 
-                 g = FAST_MAKE_GLYPH (it->c ^ 0100, 0);
+                 g = FAST_MAKE_GLYPH (it->c ^ 0100, face_id);
                  XSETINT (it->ctl_chars[1], g);
+                 ctl_len = 2;
+               }
+             else if (it->c == 0x8a0 || it->c == 0x8ad)
+               {
+                 /* Set IT->ctl_chars[0] to the glyph for `\\'.  */
+                 if (it->dp
+                     && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
+                     && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (it->dp))))
+                   g = XINT (DISP_ESCAPE_GLYPH (it->dp));
+                 else
+                   g = FAST_MAKE_GLYPH ('\\', face_id);
+                 XSETINT (it->ctl_chars[0], g);
 
-                 /* Set up IT->dpvec and return first character from it.  */
-                 it->dpvec_char_len = it->len;
-                 it->dpvec = it->ctl_chars;
-                 it->dpend = it->dpvec + 2;
-                 it->current.dpvec_index = 0;
-                 it->method = next_element_from_display_vector;
-                 get_next_display_element (it);
+                 g = FAST_MAKE_GLYPH (it->c == 0x8ad ? '-' : ' ', face_id);
+                 XSETINT (it->ctl_chars[1], g);
+                 ctl_len = 2;
                }
              else
                {
@@ -4937,7 +4987,7 @@ get_next_display_element (it)
                      && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
                    escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
                  else
-                   escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
+                   escape_glyph = FAST_MAKE_GLYPH ('\\', face_id);
 
                  if (SINGLE_BYTE_CHAR_P (it->c))
                    str[0] = it->c, len = 1;
@@ -4964,23 +5014,27 @@ get_next_display_element (it)
                      XSETINT (it->ctl_chars[i * 4], escape_glyph);
                      /* Insert three more glyphs into IT->ctl_chars for
                         the octal display of the character.  */
-                     g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0);
+                     g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0',
+                                          face_id);
                      XSETINT (it->ctl_chars[i * 4 + 1], g);
-                     g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0);
+                     g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0',
+                                          face_id);
                      XSETINT (it->ctl_chars[i * 4 + 2], g);
-                     g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0);
+                     g = FAST_MAKE_GLYPH ((str[i] & 7) + '0',
+                                          face_id);
                      XSETINT (it->ctl_chars[i * 4 + 3], g);
                    }
-
-                 /* Set up IT->dpvec and return the first character
-                     from it.  */
-                 it->dpvec_char_len = it->len;
-                 it->dpvec = it->ctl_chars;
-                 it->dpend = it->dpvec + len * 4;
-                 it->current.dpvec_index = 0;
-                 it->method = next_element_from_display_vector;
-                 get_next_display_element (it);
+                 ctl_len = len * 4;
                }
+
+             /* Set up IT->dpvec and return first character from it.  */
+             it->dpvec_char_len = it->len;
+             it->dpvec = it->ctl_chars;
+             it->dpend = it->dpvec + ctl_len;
+             it->current.dpvec_index = 0;
+             it->saved_face_id = it->face_id;
+             it->method = next_element_from_display_vector;
+             goto get_next;
            }
        }
 
@@ -5102,6 +5156,9 @@ set_iterator_to_next (it, reseat_p)
          it->dpvec = NULL;
          it->current.dpvec_index = -1;
 
+         /* Recheck faces after display vector */
+         it->stop_charpos = 0;
+
          /* Skip over characters which were displayed via IT->dpvec.  */
          if (it->dpvec_char_len < 0)
            reseat_at_next_visible_line_start (it, 1);
@@ -5170,11 +5227,14 @@ set_iterator_to_next (it, reseat_p)
               && IT_STRING_CHARPOS (*it) >= 0));
 }
 
-
 /* Load IT's display element fields with information about the next
    display element which comes from a display table entry or from the
    result of translating a control character to one of the forms `^C'
-   or `\003'.  IT->dpvec holds the glyphs to return as characters.  */
+   or `\003'.
+
+   IT->dpvec holds the glyphs to return as characters.
+   IT->saved_face_id holds the face id before the display vector--
+   it is restored into IT->face_idin set_iterator_to_next.  */
 
 static int
 next_element_from_display_vector (it)
@@ -5183,10 +5243,6 @@ next_element_from_display_vector (it)
   /* Precondition.  */
   xassert (it->dpvec && it->current.dpvec_index >= 0);
 
-  /* Remember the current face id in case glyphs specify faces.
-     IT's face is restored in set_iterator_to_next.  */
-  it->saved_face_id = it->face_id;
-
   if (INTEGERP (*it->dpvec)
       && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
     {
@@ -5370,28 +5426,7 @@ next_element_from_ellipsis (it)
      struct it *it;
 {
   if (it->selective_display_ellipsis_p)
-    {
-      if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
-       {
-         /* Use the display table definition for `...'.  Invalid glyphs
-            will be handled by the method returning elements from dpvec.  */
-         struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
-         it->dpvec_char_len = it->len;
-         it->dpvec = v->contents;
-         it->dpend = v->contents + v->size;
-         it->current.dpvec_index = 0;
-         it->method = next_element_from_display_vector;
-       }
-      else
-       {
-         /* Use default `...' which is stored in default_invis_vector.  */
-         it->dpvec_char_len = it->len;
-         it->dpvec = default_invis_vector;
-         it->dpend = default_invis_vector + 3;
-         it->current.dpvec_index = 0;
-         it->method = next_element_from_display_vector;
-       }
-    }
+    setup_for_ellipsis (it, it->len);
   else
     {
       /* The face at the current position may be different from the
@@ -6059,10 +6094,13 @@ move_it_vertically_backward (it, dy)
 {
   int nlines, h;
   struct it it2, it3;
-  int start_pos = IT_CHARPOS (*it);
+  int start_pos;
 
+ move_further_back:
   xassert (dy >= 0);
 
+  start_pos = IT_CHARPOS (*it);
+
   /* Estimate how many newlines we must move back.  */
   nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f));
 
@@ -6128,13 +6166,13 @@ move_it_vertically_backward (it, dy)
             a line height of 13 pixels each, recentering with point
             on the bottom line will try to move -39/2 = 19 pixels
             backward.  Try to avoid moving into the first line.  */
-         && it->current_y - target_y > line_height / 3 * 2
+         && it->current_y - target_y > line_height * 2 / 3
          && IT_CHARPOS (*it) > BEGV)
        {
          TRACE_MOVE ((stderr, "  not far enough -> move_vert %d\n",
                       target_y - it->current_y));
-         move_it_vertically (it, target_y - it->current_y);
-         xassert (IT_CHARPOS (*it) >= BEGV);
+         dy = it->current_y - target_y;
+         goto move_further_back;
        }
       else if (target_y >= it->current_y + line_height
               && IT_CHARPOS (*it) < ZV)
@@ -6175,7 +6213,7 @@ move_it_vertically (it, dy)
 {
   if (dy <= 0)
     move_it_vertically_backward (it, -dy);
-  else if (dy > 0)
+  else
     {
       TRACE_MOVE ((stderr, "move_it_v: from %d, %d\n", IT_CHARPOS (*it), dy));
       move_it_to (it, ZV, -1, it->current_y + dy, -1,
@@ -6272,6 +6310,8 @@ move_it_by_lines (it, dvpos, need_y_p)
       /* DVPOS == 0 means move to the start of the screen line.  */
       move_it_vertically_backward (it, 0);
       xassert (it->current_x == 0 && it->hpos == 0);
+      /* Let next call to line_bottom_y calculate real line height */
+      last_height = 0;
     }
   else if (dvpos > 0)
     move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
@@ -6360,7 +6400,7 @@ add_to_log (format, arg1, arg2)
   bcopy (SDATA (msg), buffer, len);
 
   message_dolog (buffer, len - 1, 1, 0);
-  SAFE_FREE (len);
+  SAFE_FREE ();
 
   UNGCPRO;
 }
@@ -6663,8 +6703,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_DISPLAY (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+       (*FRAME_DISPLAY (f)->frame_up_to_date_hook) (f);
     }
 }
 
@@ -6683,6 +6723,7 @@ message3 (m, nbytes, multibyte)
   struct gcpro gcpro1;
 
   GCPRO1 (m);
+  clear_message (1,1);
 
   /* First flush out any partial line written with print.  */
   message_log_maybe_newline ();
@@ -6749,8 +6790,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_DISPLAY (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+       (*FRAME_DISPLAY (f)->frame_up_to_date_hook) (f);
     }
 }
 
@@ -7415,7 +7456,7 @@ resize_mini_window (w, exact_p)
            height = it.current_y + last_height;
          else
            height = it.current_y + it.max_ascent + it.max_descent;
-         height -= it.extra_line_spacing;
+         height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
          height = (height + unit - 1) / unit;
        }
 
@@ -7773,11 +7814,11 @@ clear_garbaged_frames ()
     {
       Lisp_Object tail, frame;
       int changed_count = 0;
-
+      
       FOR_EACH_FRAME (tail, frame)
        {
          struct frame *f = XFRAME (frame);
-
+         
          if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
            {
              if (f->resized_p)
@@ -7791,7 +7832,7 @@ clear_garbaged_frames ()
              f->resized_p = 0;
            }
        }
-
+      
       frame_garbaged = 0;
       if (changed_count)
        ++windows_or_buffers_changed;
@@ -7824,11 +7865,10 @@ echo_area_display (update_frame_p)
 /* 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
@@ -7879,7 +7919,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);
@@ -7971,7 +8011,7 @@ store_frame_title (str, field_width, precision)
 
   /* Copy at most PRECISION chars from STR.  */
   nbytes = strlen (str);
-  n+= c_string_width (str, nbytes, precision, &dummy, &nbytes);
+  n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
   while (nbytes--)
     store_frame_title_char (*str++);
 
@@ -8340,8 +8380,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;
     }
 }
@@ -8409,7 +8449,8 @@ update_tool_bar (f, save_match_data)
        {
          struct buffer *prev = current_buffer;
          int count = SPECPDL_INDEX ();
-         Lisp_Object old_tool_bar;
+         Lisp_Object new_tool_bar;
+          int new_n_tool_bar;
          struct gcpro gcpro1;
 
          /* Set current_buffer to the buffer of the selected
@@ -8428,18 +8469,24 @@ update_tool_bar (f, save_match_data)
              specbind (Qoverriding_local_map, Qnil);
            }
 
-         old_tool_bar = f->tool_bar_items;
-         GCPRO1 (old_tool_bar);
+         GCPRO1 (new_tool_bar);
 
          /* Build desired tool-bar items from keymaps.  */
-          BLOCK_INPUT;
-         f->tool_bar_items
-           = tool_bar_items (f->tool_bar_items, &f->n_tool_bar_items);
-          UNBLOCK_INPUT;
+          new_tool_bar = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
+                                         &new_n_tool_bar);
 
          /* Redisplay the tool-bar if we changed it.  */
-         if (! NILP (Fequal (old_tool_bar, f->tool_bar_items)))
-           w->update_mode_line = Qt;
+         if (NILP (Fequal (new_tool_bar, f->tool_bar_items)))
+            {
+              /* Redisplay that happens asynchronously due to an expose event
+                 may access f->tool_bar_items.  Make sure we update both
+                 variables within BLOCK_INPUT so no such event interrupts.  */
+              BLOCK_INPUT;
+              f->tool_bar_items = new_tool_bar;
+              f->n_tool_bar_items = new_n_tool_bar;
+              w->update_mode_line = Qt;
+              UNBLOCK_INPUT;
+            }
 
          UNGCPRO;
 
@@ -8686,6 +8733,7 @@ display_tool_bar_line (it)
     {
       row->height = row->phys_height = it->last_visible_y - row->y;
       row->ascent = row->phys_ascent = 0;
+      row->extra_line_spacing = 0;
     }
 
   row->full_width_p = 1;
@@ -9518,11 +9566,13 @@ update_overlay_arrows (up_to_date)
 }
 
 
-/* Return overlay arrow string at row, or nil.  */
+/* Return overlay arrow string to display at row.
+   Return t if display as bitmap in left fringe.
+   Return nil if no overlay arrow.  */
 
 static Lisp_Object
-overlay_arrow_at_row (f, row, pbitmap)
-     struct frame *f;
+overlay_arrow_at_row (it, row, pbitmap)
+     struct it *it;
      struct glyph_row *row;
      int *pbitmap;
 {
@@ -9545,9 +9595,10 @@ overlay_arrow_at_row (f, row, pbitmap)
          && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
        {
          val = overlay_arrow_string_or_property (var, pbitmap);
-         if (FRAME_WINDOW_P (f))
+         if (FRAME_WINDOW_P (it->f)
+             && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
            return Qt;
-         else if (STRINGP (val))
+         if (STRINGP (val))
            return val;
          break;
        }
@@ -9762,17 +9813,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_terminal_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_terminal_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
@@ -9794,6 +9844,7 @@ redisplay_internal (preserve_echo_area)
       }
   }
 
+  
   /* Notice any pending interrupt request to change frame size.  */
   do_pending_window_change (1);
 
@@ -10153,7 +10204,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
@@ -10168,16 +10219,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_DISPLAY (f)->condemn_scroll_bars_hook)
+               FRAME_DISPLAY (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_DISPLAY (f)->judge_scroll_bars_hook)
+               FRAME_DISPLAY (f)->judge_scroll_bars_hook (f);
 
              /* If fonts changed, display again.  */
              /* ??? rms: I suspect it is a mistake to jump all the way
@@ -10229,8 +10280,8 @@ redisplay_internal (preserve_echo_area)
            {
              struct frame *f = updated[i];
              mark_window_display_accurate (f->root_window, 1);
-             if (frame_up_to_date_hook)
-               frame_up_to_date_hook (f);
+             if (FRAME_DISPLAY (f)->frame_up_to_date_hook)
+               FRAME_DISPLAY (f)->frame_up_to_date_hook (f);
            }
        }
     }
@@ -10315,8 +10366,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_DISPLAY (sf)->frame_up_to_date_hook != 0)
+           FRAME_DISPLAY (sf)->frame_up_to_date_hook (sf);
        }
 
       update_mode_lines = 0;
@@ -10402,6 +10453,10 @@ redisplay_preserve_echo_area (from_where)
     }
   else
     redisplay_internal (1);
+
+  if (FRAME_RIF (SELECTED_FRAME ()) != NULL
+      && FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
+    FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (NULL);
 }
 
 
@@ -10647,6 +10702,7 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
 {
   struct glyph *glyph = row->glyphs[TEXT_AREA];
   struct glyph *end = glyph + row->used[TEXT_AREA];
+  struct glyph *cursor = NULL;
   /* The first glyph that starts a sequence of glyphs from string.  */
   struct glyph *string_start;
   /* The X coordinate of string_start.  */
@@ -10656,6 +10712,8 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
   /* The last known character position before string_start.  */
   int string_before_pos;
   int x = row->x;
+  int cursor_x = x;
+  int cursor_from_overlay_pos = 0;
   int pt_old = PT - delta;
 
   /* Skip over glyphs not having an object at the start of the row.
@@ -10681,6 +10739,12 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
          string_start = NULL;
          x += glyph->pixel_width;
          ++glyph;
+         if (cursor_from_overlay_pos
+             && last_pos > cursor_from_overlay_pos)
+           {
+             cursor_from_overlay_pos = 0;
+             cursor = 0;
+           }
        }
       else
        {
@@ -10688,12 +10752,40 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
          string_start = glyph;
          string_start_x = x;
          /* Skip all glyphs from string.  */
-         SKIP_GLYPHS (glyph, end, x, STRINGP (glyph->object));
+         do
+           {
+             int pos;
+             if ((cursor == NULL || glyph > cursor)
+                 && !NILP (Fget_char_property (make_number ((glyph)->charpos),
+                                               Qcursor, (glyph)->object))
+                 && (pos = string_buffer_position (w, glyph->object,
+                                                   string_before_pos),
+                     (pos == 0   /* From overlay */
+                      || pos == pt_old)))
+               {
+                 /* Estimate overlay buffer position from the buffer
+                    positions of the glyphs before and after the overlay.
+                    Add 1 to last_pos so that if point corresponds to the
+                    glyph right after the overlay, we still use a 'cursor'
+                    property found in that overlay.  */
+                 cursor_from_overlay_pos = pos == 0 ? last_pos+1 : 0;
+                 cursor = glyph;
+                 cursor_x = x;
+               }
+             x += glyph->pixel_width;
+             ++glyph;
+           }
+         while (glyph < end && STRINGP (glyph->object));
        }
     }
 
-  if (string_start
-      && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old))
+  if (cursor != NULL)
+    {
+      glyph = cursor;
+      x = cursor_x;
+    }
+  else if (string_start
+          && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old))
     {
       /* We may have skipped over point because the previous glyphs
         are from string.  As there's no easy way to know the
@@ -10822,6 +10914,9 @@ make_cursor_line_fully_visible (w, force_p)
   struct glyph_row *row;
   int window_height;
 
+  if (!make_cursor_line_fully_visible_p)
+    return 1;
+
   /* It's not always possible to find the cursor, e.g, when a window
      is full of overlay strings.  Don't do anything in that case.  */
   if (w->cursor.vpos < 0)
@@ -10831,7 +10926,7 @@ make_cursor_line_fully_visible (w, force_p)
   row = MATRIX_ROW (matrix, w->cursor.vpos);
 
   /* If the cursor row is not partially visible, there's nothing to do.  */
-  if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
+  if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row))
     return 1;
 
   /* If the row the cursor is in is taller than the window's height,
@@ -10985,7 +11080,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
     {
       start_display (&it, w, scroll_margin_pos);
       if (this_scroll_margin)
-       move_it_vertically (&it, - this_scroll_margin);
+       move_it_vertically_backward (&it, this_scroll_margin);
       if (extra_scroll_margin_lines)
        move_it_by_lines (&it, - extra_scroll_margin_lines, 0);
       scroll_margin_pos = it.current.pos;
@@ -11085,8 +11180,8 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
          start_display (&it, w, startp);
 
          if (scroll_conservatively)
-           amount_to_scroll =
-             max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step));
+           amount_to_scroll
+             max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step));
          else if (scroll_step || temp_scroll_step)
            amount_to_scroll = scroll_max;
          else
@@ -11105,7 +11200,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
          if (amount_to_scroll <= 0)
            return SCROLLING_FAILED;
 
-         move_it_vertically (&it, - amount_to_scroll);
+         move_it_vertically_backward (&it, amount_to_scroll);
          startp = it.current.pos;
        }
     }
@@ -11365,8 +11460,7 @@ try_cursor_movement (window, startp, scroll_step)
          else if (PT < XFASTINT (w->last_point))
            {
              /* Cursor has to be moved backward.  Note that PT >=
-                CHARPOS (startp) because of the outer
-                if-statement.  */
+                CHARPOS (startp) because of the outer if-statement.  */
              while (!row->mode_line_p
                     && (MATRIX_ROW_START_CHARPOS (row) > PT
                         || (MATRIX_ROW_START_CHARPOS (row) == PT
@@ -11410,7 +11504,8 @@ try_cursor_movement (window, startp, scroll_step)
              /* if PT is not in the glyph row, give up.  */
              rc = CURSOR_MOVEMENT_MUST_SCROLL;
            }
-         else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
+         else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
+                  && make_cursor_line_fully_visible_p)
            {
              if (PT == MATRIX_ROW_END_CHARPOS (row)
                  && !row->ends_at_zv_p
@@ -11480,7 +11575,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_DISPLAY (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
+    (*FRAME_DISPLAY (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
+      (w, end - start, whole, start);
 }
 
 
@@ -11525,6 +11622,9 @@ redisplay_window (window, just_this_one_p)
   *w->desired_matrix->method = 0;
 #endif
 
+  /* Force this to be looked up again for each redisp of each window.  */
+  escape_glyph_face = -1;
+
   specbind (Qinhibit_point_motion_hooks, Qt);
 
   reconsider_clip_changes (w, buffer);
@@ -11878,8 +11978,8 @@ redisplay_window (window, just_this_one_p)
             buffer.  */
          || !NILP (Vwindow_scroll_functions)
          || MINI_WINDOW_P (w)
-         || !(used_current_matrix_p =
-              try_window_reusing_current_matrix (w)))
+         || !(used_current_matrix_p
+              try_window_reusing_current_matrix (w)))
        {
          IF_DEBUG (debug_method_add (w, "1"));
          try_window (window, startp);
@@ -11985,7 +12085,7 @@ redisplay_window (window, just_this_one_p)
   if (it.current_y <= 0)
     {
       init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
-      move_it_vertically (&it, 0);
+      move_it_vertically_backward (&it, 0);
       xassert (IT_CHARPOS (it) <= PT);
       it.current_y = 0;
     }
@@ -12008,8 +12108,8 @@ redisplay_window (window, just_this_one_p)
       || !NILP (Vwindow_scroll_functions)
       || !just_this_one_p
       || MINI_WINDOW_P (w)
-      || !(used_current_matrix_p =
-          try_window_reusing_current_matrix (w)))
+      || !(used_current_matrix_p
+          try_window_reusing_current_matrix (w)))
     try_window (window, startp);
 
   /* If new fonts have been loaded (due to fontsets), give up.  We
@@ -12158,29 +12258,33 @@ redisplay_window (window, just_this_one_p)
         display_menu_bar (w);
 
 #ifdef HAVE_WINDOW_SYSTEM
+      if (FRAME_WINDOW_P (f))
+        {
 #ifdef USE_GTK
-      redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
+          redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
 #else
-      redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
-        && (FRAME_TOOL_BAR_LINES (f) > 0
-            || auto_resize_tool_bars_p);
-
+          redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
+            && (FRAME_TOOL_BAR_LINES (f) > 0
+                || auto_resize_tool_bars_p);
 #endif
 
-      if (redisplay_tool_bar_p)
-        redisplay_tool_bar (f);
+          if (redisplay_tool_bar_p)
+            redisplay_tool_bar (f);
+        }
 #endif
     }
 
 #ifdef HAVE_WINDOW_SYSTEM
-  if (update_window_fringes (w, 0)
+  if (FRAME_WINDOW_P (f)
+      && update_window_fringes (w, 0)
       && !just_this_one_p
       && (used_current_matrix_p || overlay_arrow_seen)
       && !w->pseudo_window_p)
     {
       update_begin (f);
       BLOCK_INPUT;
-      draw_window_fringes (w);
+      if (draw_window_fringes (w, 1))
+       x_draw_vertical_border (w);
       UNBLOCK_INPUT;
       update_end (f);
     }
@@ -12201,7 +12305,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_DISPLAY (f)->redeem_scroll_bar_hook)
+        (*FRAME_DISPLAY (f)->redeem_scroll_bar_hook) (w);
     }
 
   /* Restore current_buffer and value of point in it.  */
@@ -12332,7 +12437,7 @@ try_window_reusing_current_matrix (w)
   /* Give up if old or new display is scrolled vertically.  We could
      make this function handle this, but right now it doesn't.  */
   start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-  if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row))
+  if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
     return 0;
 
   /* The variable new_start now holds the new window start.  The old
@@ -12367,10 +12472,36 @@ try_window_reusing_current_matrix (w)
       last_text_row = last_reused_text_row = NULL;
 
       while (it.current_y < it.last_visible_y
-            && IT_CHARPOS (it) < CHARPOS (start)
             && !fonts_changed_p)
-       if (display_line (&it))
-         last_text_row = it.glyph_row - 1;
+       {
+         /* If we have reached into the characters in the START row,
+            that means the line boundaries have changed.  So we
+            can't start copying with the row START.  Maybe it will
+            work to start copying with the following row.  */
+         while (IT_CHARPOS (it) > CHARPOS (start))
+           {
+             /* Advance to the next row as the "start".  */
+             start_row++;
+             start = start_row->start.pos;
+             /* If there are no more rows to try, or just one, give up.  */
+             if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
+                 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
+                 || CHARPOS (start) == ZV)
+               {
+                 clear_glyph_matrix (w->desired_matrix);
+                 return 0;
+               }
+
+             start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
+           }
+         /* If we have reached alignment,
+            we can copy the rest of the rows.  */
+         if (IT_CHARPOS (it) == CHARPOS (start))
+           break;
+
+         if (display_line (&it))
+           last_text_row = it.glyph_row - 1;
+       }
 
       /* A value of current_y < last_visible_y means that we stopped
         at the previous window start, which in turn means that we
@@ -12378,12 +12509,12 @@ try_window_reusing_current_matrix (w)
       if (it.current_y < it.last_visible_y)
        {
          /* IT.vpos always starts from 0; it counts text lines.  */
-         nrows_scrolled = it.vpos;
+         nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
 
          /* Find PT if not already found in the lines displayed.  */
          if (w->cursor.vpos < 0)
            {
-             int dy = it.current_y - first_row_y;
+             int dy = it.current_y - start_row->y;
 
              row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
              row = row_containing_pos (w, PT, row, NULL, dy);
@@ -12403,17 +12534,17 @@ try_window_reusing_current_matrix (w)
             scroll_run_hook will clear the cursor, and use the
             current matrix to get the height of the row the cursor is
             in.  */
-         run.current_y = first_row_y;
+         run.current_y = start_row->y;
          run.desired_y = it.current_y;
          run.height = it.last_visible_y - it.current_y;
 
          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);
            }
 
@@ -12582,10 +12713,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);
        }
 
@@ -13033,7 +13164,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);
 
@@ -13423,7 +13554,9 @@ try_window_id (w)
         && CHARPOS (start) > BEGV)
        /* Old redisplay didn't take scroll margin into account at the bottom,
           but then global-hl-line-mode doesn't scroll.  KFS 2004-06-14 */
-       || w->cursor.y + cursor_height + this_scroll_margin > it.last_visible_y)
+       || (w->cursor.y + (make_cursor_line_fully_visible_p
+                          ? cursor_height + this_scroll_margin
+                          : 1)) > it.last_visible_y)
       {
        w->cursor.vpos = -1;
        clear_glyph_matrix (w->desired_matrix);
@@ -13440,10 +13573,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
        {
@@ -13461,36 +13594,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);
@@ -14001,8 +14134,8 @@ usage: (trace-to-stderr STRING &rest OBJECTS)  */)
                     Building Desired Matrix Rows
  ***********************************************************************/
 
-/* Return a temporary glyph row holding the glyphs of an overlay
-   arrow.  Only used for non-window-redisplay windows.  */
+/* Return a temporary glyph row holding the glyphs of an overlay arrow.
+   Used for non-window-redisplay windows, and for windows w/o left fringe.  */
 
 static struct glyph_row *
 get_overlay_arrow_glyph_row (w, overlay_arrow_string)
@@ -14148,6 +14281,7 @@ compute_line_metrics (it)
          row->height = it->max_ascent + it->max_descent;
          row->phys_ascent = it->max_phys_ascent;
          row->phys_height = it->max_phys_ascent + it->max_phys_descent;
+         row->extra_line_spacing = it->max_extra_line_spacing;
        }
 
       /* Compute the width of this line.  */
@@ -14191,6 +14325,7 @@ compute_line_metrics (it)
        row->pixel_width -= it->truncation_pixel_width;
       row->ascent = row->phys_ascent = 0;
       row->height = row->phys_height = row->visible_height = 1;
+      row->extra_line_spacing = 0;
     }
 
   /* Compute a hash code for this row.  */
@@ -14425,7 +14560,9 @@ highlight_trailing_whitespace (f, row)
                  && glyph->u.ch == ' '))
          && trailing_whitespace_p (glyph->charpos))
        {
-         int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
+         int face_id = lookup_named_face (f, Qtrailing_whitespace, 0, 0);
+         if (face_id < 0)
+           return;
 
          while (glyph >= start
                 && BUFFERP (glyph->object)
@@ -14518,8 +14655,10 @@ display_line (it)
      hscrolled.  This may stop at an x-position < IT->first_visible_x
      if the first glyph is partially visible or if we hit a line end.  */
   if (it->current_x < it->first_visible_x)
-    move_it_in_display_line_to (it, ZV, it->first_visible_x,
-                               MOVE_TO_POS | MOVE_TO_X);
+    {
+      move_it_in_display_line_to (it, ZV, it->first_visible_x,
+                                 MOVE_TO_POS | MOVE_TO_X);
+    }
 
   /* Get the initial row height.  This is either the height of the
      text hscrolled, if there is any, or zero.  */
@@ -14527,6 +14666,7 @@ display_line (it)
   row->height = it->max_ascent + it->max_descent;
   row->phys_ascent = it->max_phys_ascent;
   row->phys_height = it->max_phys_ascent + it->max_phys_descent;
+  row->extra_line_spacing = it->max_extra_line_spacing;
 
   /* Loop generating characters.  The loop is left with IT on the next
      character to display.  */
@@ -14592,6 +14732,8 @@ display_line (it)
          row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
          row->phys_height = max (row->phys_height,
                                  it->max_phys_ascent + it->max_phys_descent);
+         row->extra_line_spacing = max (row->extra_line_spacing,
+                                        it->max_extra_line_spacing);
          set_iterator_to_next (it, 1);
          continue;
        }
@@ -14620,6 +14762,8 @@ display_line (it)
          row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
          row->phys_height = max (row->phys_height,
                                  it->max_phys_ascent + it->max_phys_descent);
+         row->extra_line_spacing = max (row->extra_line_spacing,
+                                        it->max_extra_line_spacing);
          if (it->current_x - it->pixel_width < it->first_visible_x)
            row->x = x - it->first_visible_x;
        }
@@ -14771,6 +14915,8 @@ display_line (it)
          row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
          row->phys_height = max (row->phys_height,
                                  it->max_phys_ascent + it->max_phys_descent);
+         row->extra_line_spacing = max (row->extra_line_spacing,
+                                        it->max_extra_line_spacing);
 
          /* End of this display line if row is continued.  */
          if (row->continued_p || row->ends_at_zv_p)
@@ -14841,12 +14987,10 @@ display_line (it)
                {
                  if (!get_next_display_element (it))
                    {
-#ifdef HAVE_WINDOW_SYSTEM
                      it->continuation_lines_width = 0;
                      row->ends_at_zv_p = 1;
                      row->exact_window_width_line_p = 1;
                      break;
-#endif /* HAVE_WINDOW_SYSTEM */
                    }
                  if (ITERATOR_AT_END_OF_LINE_P (it))
                    {
@@ -14883,11 +15027,11 @@ display_line (it)
      better to let it be displayed like cursors under X.  */
   if (! overlay_arrow_seen
       && (overlay_arrow_string
-           = overlay_arrow_at_row (it->f, row, &overlay_arrow_bitmap),
+           = overlay_arrow_at_row (it, row, &overlay_arrow_bitmap),
          !NILP (overlay_arrow_string)))
     {
       /* Overlay arrow in window redisplay is a fringe bitmap.  */
-      if (!FRAME_WINDOW_P (it->f))
+      if (STRINGP (overlay_arrow_string))
        {
          struct glyph_row *arrow_row
            = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
@@ -14912,10 +15056,12 @@ display_line (it)
              row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
            }
        }
-
+      else
+       {
+         it->w->overlay_arrow_bitmap = overlay_arrow_bitmap;
+         row->overlay_arrow_p = 1;
+       }
       overlay_arrow_seen = 1;
-      it->w->overlay_arrow_bitmap = overlay_arrow_bitmap;
-      row->overlay_arrow_p = 1;
     }
 
   /* Compute pixel dimensions of this line.  */
@@ -15298,6 +15444,10 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
            Lisp_Object oprops, aelt;
            oprops = Ftext_properties_at (make_number (0), elt);
 
+           /* If the starting string's properties are not what
+              we want, translate the string.  Also, if the string
+              is risky, do that anyway.  */
+
            if (NILP (Fequal (props, oprops)) || risky)
              {
                /* If the starting string has properties,
@@ -15376,14 +15526,15 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
 
            if (this - 1 != last)
              {
+               int nchars, nbytes;
+
                /* Output to end of string or up to '%'.  Field width
                   is length of string.  Don't output more than
                   PRECISION allows us.  */
                --this;
 
-               prec = chars_in_text (last, this - last);
-               if (precision > 0 && prec > precision - n)
-                 prec = precision - n;
+               prec = c_string_width (last, this - last, precision - n,
+                                      &nchars, &nbytes);
 
                if (frame_title_ptr)
                  n += store_frame_title (last, 0, prec);
@@ -15391,9 +15542,14 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                  {
                    int bytepos = last - lisp_string;
                    int charpos = string_byte_to_char (elt, bytepos);
+                   int endpos = (precision <= 0
+                                 ? string_byte_to_char (elt,
+                                                        this - lisp_string)
+                                 : charpos + nchars);
+
                    n += store_mode_line_string (NULL,
                                                 Fsubstring (elt, make_number (charpos),
-                                                            make_number (charpos + prec)),
+                                                            make_number (endpos)),
                                                 0, 0, 0, Qnil);
                  }
                else
@@ -15674,7 +15830,8 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
    The mode_line_string_face face property is always added to the string.
  */
 
-static int store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props)
+static int
+store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props)
      char *string;
      Lisp_Object lisp_string;
      int copy_string;
@@ -15695,7 +15852,7 @@ static int store_mode_line_string (string, lisp_string, copy_string, field_width
        props = mode_line_string_face_prop;
       else if (!NILP (mode_line_string_face))
        {
-         Lisp_Object face = Fplist_get (props, Qface);
+         Lisp_Object face = Fsafe_plist_get (props, Qface);
          props = Fcopy_sequence (props);
          if (NILP (face))
            face = mode_line_string_face;
@@ -15720,7 +15877,7 @@ static int store_mode_line_string (string, lisp_string, copy_string, field_width
          Lisp_Object face;
          if (NILP (props))
            props = Ftext_properties_at (make_number (0), lisp_string);
-         face = Fplist_get (props, Qface);
+         face = Fsafe_plist_get (props, Qface);
          if (NILP (face))
            face = mode_line_string_face;
          else
@@ -15756,15 +15913,16 @@ static int store_mode_line_string (string, lisp_string, copy_string, field_width
 
 
 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
-       0, 3, 0,
+       0, 4, 0,
        doc: /* Return the mode-line of selected window as a string.
 First optional arg FORMAT specifies a different format string (see
 `mode-line-format' for details) to use.  If FORMAT is t, return
 the buffer's header-line.  Second optional arg WINDOW specifies a
 different window to use as the context for the formatting.
-If third optional arg NO-PROPS is non-nil, string is not propertized.  */)
-     (format, window, no_props)
-     Lisp_Object format, window, no_props;
+If third optional arg NO-PROPS is non-nil, string is not propertized.
+Fourth optional arg BUFFER specifies which buffer to use.  */)
+  (format, window, no_props, buffer)
+     Lisp_Object format, window, no_props, buffer;
 {
   struct it it;
   int len;
@@ -15776,42 +15934,46 @@ If third optional arg NO-PROPS is non-nil, string is not propertized.  */)
     window = selected_window;
   CHECK_WINDOW (window);
   w = XWINDOW (window);
-  CHECK_BUFFER (w->buffer);
 
-  if (XBUFFER (w->buffer) != current_buffer)
+  if (NILP (buffer))
+    buffer = w->buffer;
+
+  CHECK_BUFFER (buffer);
+
+  if (XBUFFER (buffer) != current_buffer)
     {
       old_buffer = current_buffer;
-      set_buffer_internal_1 (XBUFFER (w->buffer));
+      set_buffer_internal_1 (XBUFFER (buffer));
     }
 
   if (NILP (format) || EQ (format, Qt))
     {
-      face_id = NILP (format)
-       ? CURRENT_MODE_LINE_FACE_ID (w) :
-       HEADER_LINE_FACE_ID;
-      format = NILP (format)
-       ? current_buffer->mode_line_format
-       : current_buffer->header_line_format;
+      face_id = (NILP (format)
+                ? CURRENT_MODE_LINE_FACE_ID (w)
+                : HEADER_LINE_FACE_ID);
+      format = (NILP (format)
+               ? current_buffer->mode_line_format
+               : current_buffer->header_line_format);
     }
 
   init_iterator (&it, w, -1, -1, NULL, face_id);
 
   if (NILP (no_props))
     {
-      mode_line_string_face =
-       (face_id == MODE_LINE_FACE_ID ? Qmode_line :
-        face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive :
-        face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil);
+      mode_line_string_face
+       = (face_id == MODE_LINE_FACE_ID ? Qmode_line
+          : face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive
+          : face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil);
 
-      mode_line_string_face_prop =
-       NILP (mode_line_string_face) ? Qnil :
-       Fcons (Qface, Fcons (mode_line_string_face, Qnil));
+      mode_line_string_face_prop
+       = (NILP (mode_line_string_face) ? Qnil
+          : Fcons (Qface, Fcons (mode_line_string_face, Qnil)));
 
       /* We need a dummy last element in mode_line_string_list to
         indicate we are building the propertized mode-line string.
         Using mode_line_string_face_prop here GC protects it.  */
-      mode_line_string_list =
-       Fcons (mode_line_string_face_prop, Qnil);
+      mode_line_string_list
+       Fcons (mode_line_string_face_prop, Qnil);
       frame_title_ptr = NULL;
     }
   else
@@ -15940,27 +16102,31 @@ pint2hrstr (buf, width, d)
        {
          tenths = remainder / 100;
          if (50 <= remainder % 100)
-           if (tenths < 9)
-             tenths++;
-           else
-             {
-               quotient++;
-               if (quotient == 10)
-                 tenths = -1;
-               else
-                 tenths = 0;
-             }
+           {
+             if (tenths < 9)
+               tenths++;
+             else
+               {
+                 quotient++;
+                 if (quotient == 10)
+                   tenths = -1;
+                 else
+                   tenths = 0;
+               }
+           }
        }
       else
        if (500 <= remainder)
-         if (quotient < 999)
-           quotient++;
-         else
-           {
-             quotient = 1;
-             exponent++;
-             tenths = 0;
-           }
+         {
+           if (quotient < 999)
+             quotient++;
+           else
+             {
+               quotient = 1;
+               exponent++;
+               tenths = 0;
+             }
+         }
     }
 
   /* Calculate the LENGTH of QUOTIENT.TENTHS as a string. */
@@ -16084,7 +16250,10 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
    generated by character C.  PRECISION >= 0 means don't return a
    string longer than that value.  FIELD_WIDTH > 0 means pad the
    string returned with spaces to that value.  Return 1 in *MULTIBYTE
-   if the result is multibyte text.  */
+   if the result is multibyte text.
+
+   Note we operate on the current buffer for most purposes,
+   the exception being w->base_line_pos.  */
 
 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
 
@@ -16098,7 +16267,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
   Lisp_Object obj;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
-  struct buffer *b = XBUFFER (w->buffer);
+  struct buffer *b = current_buffer;
 
   obj = Qnil;
   *multibyte = 0;
@@ -16400,7 +16569,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
 
     case 's':
       /* status of process */
-      obj = Fget_buffer_process (w->buffer);
+      obj = Fget_buffer_process (Fcurrent_buffer ());
       if (NILP (obj))
        return "no process";
 #ifdef subprocesses
@@ -16427,8 +16596,8 @@ 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 (FRAME_KEYBOARD_CODING (f)->symbol, p, 0);
+           p = decode_mode_spec_coding (FRAME_TERMINAL_CODING (f)->symbol, p, 0);
          }
        p = decode_mode_spec_coding (b->buffer_file_coding_system,
                                     p, eol_flag);
@@ -16659,6 +16828,7 @@ display_string (string, lisp_string, face_string, face_string_pos,
   row->height = it->max_ascent + it->max_descent;
   row->phys_ascent = it->max_phys_ascent;
   row->phys_height = it->max_phys_ascent + it->max_phys_descent;
+  row->extra_line_spacing = it->max_extra_line_spacing;
 
   /* This condition is for the case that we are called with current_x
      past last_visible_x.  */
@@ -16718,6 +16888,8 @@ display_string (string, lisp_string, face_string, face_string_pos,
          row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
          row->phys_height = max (row->phys_height,
                                  it->max_phys_ascent + it->max_phys_descent);
+         row->extra_line_spacing = max (row->extra_line_spacing,
+                                        it->max_extra_line_spacing);
          x += glyph->pixel_width;
          ++i;
        }
@@ -17154,7 +17326,8 @@ init_glyph_string (s, OPTIONAL_HDC (hdc) char2b, w, row, area, start, hl)
   s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
 
   /* Display the internal border below the tool-bar window.  */
-  if (s->w == XWINDOW (s->f->tool_bar_window))
+  if (WINDOWP (s->f->tool_bar_window)
+      && s->w == XWINDOW (s->f->tool_bar_window))
     s->y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
 
   s->ybase = s->y + row->ascent;
@@ -17265,7 +17438,7 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
            = 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);
+             = FRAME_RIF (f)->encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
        }
     }
 
@@ -17496,7 +17669,7 @@ x_get_glyph_overhangs (glyph, f, left, right)
       font = face->font;
       font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
       if (font  /* ++KFS: Should this be font_info ?  */
-         && (pcm = rif->per_char_metric (font, &char2b, glyph->font_type)))
+         && (pcm = FRAME_RIF (f)->per_char_metric (font, &char2b, glyph->font_type)))
        {
          if (pcm->rbearing > pcm->width)
            *right = pcm->rbearing - pcm->width;
@@ -17664,7 +17837,7 @@ get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
          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);
+           FRAME_RIF (f)->encode_char (c, char2b, font_info, 0);
        }
     }
 
@@ -17731,8 +17904,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;
@@ -17742,8 +17915,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;
@@ -18024,9 +18197,9 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
       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
@@ -18094,7 +18267,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
 
   /* 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
@@ -18126,6 +18299,19 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
   return x_reached;
 }
 
+/* Expand row matrix if too narrow.  Don't expand if area
+   is not present.  */
+
+#define IT_EXPAND_MATRIX_WIDTH(it, area)               \
+  {                                                    \
+    if (!fonts_changed_p                               \
+       && (it->glyph_row->glyphs[area]                 \
+           < it->glyph_row->glyphs[area + 1]))         \
+      {                                                        \
+       it->w->ncols_scale_factor++;                    \
+       fonts_changed_p = 1;                            \
+      }                                                        \
+  }
 
 /* Store one glyph for IT->char_to_display in IT->glyph_row.
    Called from x_produce_glyphs when IT->glyph_row is non-null.  */
@@ -18163,11 +18349,8 @@ append_glyph (it)
       glyph->font_type = FONT_TYPE_UNKNOWN;
       ++it->glyph_row->used[area];
     }
-  else if (!fonts_changed_p)
-    {
-      it->w->ncols_scale_factor++;
-      fonts_changed_p = 1;
-    }
+  else
+    IT_EXPAND_MATRIX_WIDTH (it, area);
 }
 
 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
@@ -18205,11 +18388,8 @@ append_composite_glyph (it)
       glyph->font_type = FONT_TYPE_UNKNOWN;
       ++it->glyph_row->used[area];
     }
-  else if (!fonts_changed_p)
-    {
-      it->w->ncols_scale_factor++;
-      fonts_changed_p = 1;
-    }
+  else
+    IT_EXPAND_MATRIX_WIDTH (it, area);
 }
 
 
@@ -18244,7 +18424,7 @@ produce_image_glyph (it)
 {
   struct image *img;
   struct face *face;
-  int face_ascent, glyph_ascent;
+  int glyph_ascent;
   struct glyph_slice slice;
 
   xassert (it->what == IT_IMAGE);
@@ -18327,7 +18507,7 @@ produce_image_glyph (it)
 
 #if 0  /* this breaks image tiling */
   /* If this glyph is alone on the last line, adjust it.ascent to minimum row ascent.  */
-  face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f);
+  int face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f);
   if (face_ascent > it->ascent)
     it->ascent = it->phys_ascent = face_ascent;
 #endif
@@ -18379,11 +18559,8 @@ produce_image_glyph (it)
          glyph->font_type = FONT_TYPE_UNKNOWN;
          ++it->glyph_row->used[area];
        }
-      else if (!fonts_changed_p)
-       {
-         it->w->ncols_scale_factor++;
-         fonts_changed_p = 1;
-       }
+      else
+       IT_EXPAND_MATRIX_WIDTH (it, area);
     }
 }
 
@@ -18427,11 +18604,8 @@ append_stretch_glyph (it, object, width, height, ascent)
       glyph->font_type = FONT_TYPE_UNKNOWN;
       ++it->glyph_row->used[area];
     }
-  else if (!fonts_changed_p)
-    {
-      it->w->ncols_scale_factor++;
-      fonts_changed_p = 1;
-    }
+  else
+    IT_EXPAND_MATRIX_WIDTH (it, area);
 }
 
 
@@ -18486,14 +18660,14 @@ produce_stretch_glyph (it)
   plist = XCDR (it->object);
 
   /* Compute the width of the stretch.  */
-  if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
+  if ((prop = Fsafe_plist_get (plist, QCwidth), !NILP (prop))
       && calc_pixel_width_or_height (&tem, it, prop, font, 1, 0))
     {
       /* Absolute width `:width WIDTH' specified and valid.  */
       zero_width_ok_p = 1;
       width = (int)tem;
     }
-  else if (prop = Fplist_get (plist, QCrelative_width),
+  else if (prop = Fsafe_plist_get (plist, QCrelative_width),
           NUMVAL (prop) > 0)
     {
       /* Relative width `:relative-width FACTOR' specified and valid.
@@ -18517,7 +18691,7 @@ produce_stretch_glyph (it)
       x_produce_glyphs (&it2);
       width = NUMVAL (prop) * it2.pixel_width;
     }
-  else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
+  else if ((prop = Fsafe_plist_get (plist, QCalign_to), !NILP (prop))
           && calc_pixel_width_or_height (&tem, it, prop, font, 1, &align_to))
     {
       if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
@@ -18537,13 +18711,13 @@ produce_stretch_glyph (it)
     width = 1;
 
   /* Compute height.  */
-  if ((prop = Fplist_get (plist, QCheight), !NILP (prop))
+  if ((prop = Fsafe_plist_get (plist, QCheight), !NILP (prop))
       && calc_pixel_width_or_height (&tem, it, prop, font, 0, 0))
     {
       height = (int)tem;
       zero_height_ok_p = 1;
     }
-  else if (prop = Fplist_get (plist, QCrelative_height),
+  else if (prop = Fsafe_plist_get (plist, QCrelative_height),
           NUMVAL (prop) > 0)
     height = FONT_HEIGHT (font) * NUMVAL (prop);
   else
@@ -18555,7 +18729,7 @@ produce_stretch_glyph (it)
   /* Compute percentage of height used for ascent.  If
      `:ascent ASCENT' is present and valid, use that.  Otherwise,
      derive the ascent from the font in use.  */
-  if (prop = Fplist_get (plist, QCascent),
+  if (prop = Fsafe_plist_get (plist, QCascent),
       NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
     ascent = height * NUMVAL (prop) / 100.0;
   else if (!NILP (prop)
@@ -18615,8 +18789,10 @@ calc_line_height_property (it, prop, font, boff, total)
 
   if (STRINGP (it->object))
     position = make_number (IT_STRING_CHARPOS (*it));
-  else
+  else if (BUFFERP (it->object))
     position = make_number (IT_CHARPOS (*it));
+  else
+    return Qnil;
 
   val = Fget_char_property (position, prop, it->object);
 
@@ -18660,7 +18836,7 @@ calc_line_height_property (it, prop, font, boff, total)
       struct face *face;
       struct font_info *font_info;
 
-      face_id = lookup_named_face (it->f, face_name, ' ');
+      face_id = lookup_named_face (it->f, face_name, ' ', 0);
       if (face_id < 0)
        return make_number (-1);
 
@@ -18781,20 +18957,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 = FRAME_RIF (it->f)->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;
+           }
 
          if (pcm)
            {
@@ -18997,8 +19173,8 @@ x_produce_glyphs (it)
             from the charset width; this is what old redisplay code
             did.  */
 
-         pcm = rif->per_char_metric (font, &char2b,
-                                     FONT_TYPE_FOR_MULTIBYTE (font, it->c));
+         pcm = FRAME_RIF (it->f)->per_char_metric (font, &char2b,
+                                                    FONT_TYPE_FOR_MULTIBYTE (font, it->c));
 
          if (font_not_found_p || !pcm)
            {
@@ -19129,8 +19305,8 @@ x_produce_glyphs (it)
 
          /* Initialize the bounding box.  */
          if (font_info
-             && (pcm = rif->per_char_metric (font, &char2b,
-                                             FONT_TYPE_FOR_MULTIBYTE (font, it->c))))
+             && (pcm = FRAME_RIF (it->f)->per_char_metric (font, &char2b,
+                                                            FONT_TYPE_FOR_MULTIBYTE (font, it->c))))
            {
              width = pcm->width;
              ascent = pcm->ascent;
@@ -19188,8 +19364,8 @@ x_produce_glyphs (it)
                }
 
              if (font_info
-                 && (pcm = rif->per_char_metric (font, &char2b,
-                                                 FONT_TYPE_FOR_MULTIBYTE (font, ch))))
+                 && (pcm = FRAME_RIF (it->f)->per_char_metric (font, &char2b,
+                                                                FONT_TYPE_FOR_MULTIBYTE (font, ch))))
                {
                  width = pcm->width;
                  ascent = pcm->ascent;
@@ -19338,7 +19514,11 @@ x_produce_glyphs (it)
     it->current_x += it->pixel_width;
 
   if (extra_line_spacing > 0)
-    it->descent += extra_line_spacing;
+    {
+      it->descent += extra_line_spacing;
+      if (extra_line_spacing > it->max_extra_line_spacing)
+       it->max_extra_line_spacing = extra_line_spacing;
+    }
 
   it->max_ascent = max (it->max_ascent, it->ascent);
   it->max_descent = max (it->max_descent, it->descent);
@@ -19425,8 +19605,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];
@@ -19508,8 +19688,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;
     }
 }
@@ -19920,6 +20100,11 @@ erase_phys_cursor (w)
   if (!cursor_row->enabled_p)
     goto mark_cursor_off;
 
+  /* If line spacing is > 0, old cursor may only be partially visible in
+     window after split-window.  So adjust visible height.  */
+  cursor_row->visible_height = min (cursor_row->visible_height,
+                                   window_text_bottom_y (w) - cursor_row->y);
+
   /* If row is completely invisible, don't attempt to delete a cursor which
      isn't there.  This can happen if cursor is at top of a window, and
      we switch to a buffer with a header line in that window.  */
@@ -19963,6 +20148,7 @@ erase_phys_cursor (w)
     {
       int x, y;
       int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+      int width;
 
       cursor_glyph = get_phys_cursor_glyph (w);
       if (cursor_glyph == NULL)
@@ -19970,9 +20156,10 @@ erase_phys_cursor (w)
 
       x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
       y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y));
+      width = min (cursor_glyph->pixel_width,
+                   window_box_width (w, TEXT_AREA) - w->phys_cursor.x);
 
-      rif->clear_frame_area (f, x, y,
-                            cursor_glyph->pixel_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.  */
@@ -20069,9 +20256,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);
 }
 
 
@@ -20216,11 +20403,11 @@ show_mouse_face (dpyinfo, draw)
 
   /* Change the mouse cursor.  */
   if (draw == DRAW_NORMAL_TEXT)
-    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:
@@ -20305,19 +20492,20 @@ fast_find_position (w, charpos, hpos, vpos, x, y, stop)
   int past_end = 0;
 
   first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  if (charpos < MATRIX_ROW_START_CHARPOS (first))
+    {
+      *x = first->x;
+      *y = first->y;
+      *hpos = 0;
+      *vpos = MATRIX_ROW_VPOS (first, w->current_matrix);
+      return 1;
+    }
+
   row = row_containing_pos (w, charpos, first, NULL, 0);
   if (row == NULL)
     {
-      if (charpos < MATRIX_ROW_START_CHARPOS (first))
-       {
-         *x = *y = *hpos = *vpos = 0;
-         return 1;
-       }
-      else
-       {
-         row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
-         past_end = 1;
-       }
+      row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+      past_end = 1;
     }
 
   *x = row->x;
@@ -20634,7 +20822,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;
 }
 
@@ -20687,6 +20874,10 @@ define_frame_cursor1 (f, cursor, pointer)
      Cursor cursor;
      Lisp_Object pointer;
 {
+  /* Do not change cursor shape while dragging mouse.  */
+  if (!NILP (do_mouse_tracking))
+    return;
+
   if (!NILP (pointer))
     {
       if (EQ (pointer, Qarrow))
@@ -20710,7 +20901,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
@@ -20748,7 +20939,7 @@ note_mode_line_or_margin_highlight (w, x, y, area)
   if (IMAGEP (object))
     {
       Lisp_Object image_map, hotspot;
-      if ((image_map = Fplist_get (XCDR (object), QCmap),
+      if ((image_map = Fsafe_plist_get (XCDR (object), QCmap),
           !NILP (image_map))
          && (hotspot = find_hot_spot (image_map, dx, dy),
              CONSP (hotspot))
@@ -20760,12 +20951,14 @@ note_mode_line_or_margin_highlight (w, x, y, area)
          /* Could check AREA_ID to see if we enter/leave this hot-spot.
             If so, we could look for mouse-enter, mouse-leave
             properties in PLIST (and do something...).  */
-         if ((plist = XCDR (hotspot), CONSP (plist)))
+         hotspot = XCDR (hotspot);
+         if (CONSP (hotspot)
+             && (plist = XCAR (hotspot), CONSP (plist)))
            {
-             pointer = Fplist_get (plist, Qpointer);
+             pointer = Fsafe_plist_get (plist, Qpointer);
              if (NILP (pointer))
                pointer = Qhand;
-             help = Fplist_get (plist, Qhelp_echo);
+             help = Fsafe_plist_get (plist, Qhelp_echo);
              if (!NILP (help))
                {
                  help_echo_string = help;
@@ -20776,7 +20969,7 @@ note_mode_line_or_margin_highlight (w, x, y, area)
                }
            }
          if (NILP (pointer))
-           pointer = Fplist_get (XCDR (object), QCpointer);
+           pointer = Fsafe_plist_get (XCDR (object), QCpointer);
        }
     }
 
@@ -20786,13 +20979,16 @@ note_mode_line_or_margin_highlight (w, x, y, area)
       /* If we're on a string with `help-echo' text property, arrange
         for the help to be displayed.  This is done by setting the
         global variable help_echo_string to the help string.  */
-      help = Fget_text_property (pos, Qhelp_echo, string);
-      if (!NILP (help))
+      if (NILP (help))
        {
-         help_echo_string = help;
-         XSETWINDOW (help_echo_window, w);
-         help_echo_object = string;
-         help_echo_pos = charpos;
+         help = Fget_text_property (pos, Qhelp_echo, string);
+         if (!NILP (help))
+           {
+             help_echo_string = help;
+             XSETWINDOW (help_echo_window, w);
+             help_echo_object = string;
+             help_echo_pos = charpos;
+           }
        }
 
       if (NILP (pointer))
@@ -20859,8 +21055,10 @@ note_mouse_highlight (f, x, y)
   /* Which window is that in?  */
   window = window_from_coordinates (f, x, y, &part, 0, 0, 1);
 
-  /* If we were displaying active text in another window, clear that.  */
-  if (! EQ (window, dpyinfo->mouse_face_window))
+  /* If we were displaying active text in another window, clear that.
+     Also clear if we move out of text area in same window.  */
+  if (! EQ (window, dpyinfo->mouse_face_window)
+      || (part != ON_TEXT && !NILP (dpyinfo->mouse_face_window)))
     clear_mouse_face (dpyinfo);
 
   /* Not on a window -> return.  */
@@ -20892,7 +21090,8 @@ note_mouse_highlight (f, x, y)
 
   if (part == ON_VERTICAL_BORDER)
     cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
-  else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE)
+  else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
+          || part == ON_SCROLL_BAR)
     cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
   else
     cursor = FRAME_X_OUTPUT (f)->text_cursor;
@@ -20924,7 +21123,7 @@ note_mouse_highlight (f, x, y)
          if (img != NULL && IMAGEP (img->spec))
            {
              Lisp_Object image_map, hotspot;
-             if ((image_map = Fplist_get (XCDR (img->spec), QCmap),
+             if ((image_map = Fsafe_plist_get (XCDR (img->spec), QCmap),
                   !NILP (image_map))
                  && (hotspot = find_hot_spot (image_map,
                                               glyph->slice.x + dx,
@@ -20938,12 +21137,14 @@ note_mouse_highlight (f, x, y)
                  /* Could check AREA_ID to see if we enter/leave this hot-spot.
                     If so, we could look for mouse-enter, mouse-leave
                     properties in PLIST (and do something...).  */
-                 if ((plist = XCDR (hotspot), CONSP (plist)))
+                 hotspot = XCDR (hotspot);
+                 if (CONSP (hotspot)
+                     && (plist = XCAR (hotspot), CONSP (plist)))
                    {
-                     pointer = Fplist_get (plist, Qpointer);
+                     pointer = Fsafe_plist_get (plist, Qpointer);
                      if (NILP (pointer))
                        pointer = Qhand;
-                     help_echo_string = Fplist_get (plist, Qhelp_echo);
+                     help_echo_string = Fsafe_plist_get (plist, Qhelp_echo);
                      if (!NILP (help_echo_string))
                        {
                          help_echo_window = window;
@@ -20953,7 +21154,7 @@ note_mouse_highlight (f, x, y)
                    }
                }
              if (NILP (pointer))
-               pointer = Fplist_get (XCDR (img->spec), QCpointer);
+               pointer = Fsafe_plist_get (XCDR (img->spec), QCpointer);
            }
        }
 
@@ -21526,8 +21727,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;
 }
 
 
@@ -21539,6 +21740,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 */
@@ -21547,6 +21750,9 @@ x_draw_vertical_border (w)
      do it for frames with vertical scroll bars because either the
      right scroll bar of a window, or the left scroll bar of its
      neighbor will suffice as a border.  */
+  if (FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (w->frame)))
+    return;
+
   if (!WINDOW_RIGHTMOST_P (w)
       && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
     {
@@ -21555,7 +21761,7 @@ x_draw_vertical_border (w)
       window_box_edges (w, -1, &x0, &y0, &x1, &y1);
       y1 -= 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))
@@ -21565,7 +21771,7 @@ x_draw_vertical_border (w)
       window_box_edges (w, -1, &x0, &y0, &x1, &y1);
       y1 -= 1;
 
-      rif->draw_vertical_window_border (w, x0, y0, y1);
+      FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
     }
 }
 
@@ -21990,6 +22196,8 @@ syms_of_xdisp ()
   staticpro (&Qfontification_functions);
   Qtrailing_whitespace = intern ("trailing-whitespace");
   staticpro (&Qtrailing_whitespace);
+  Qescape_glyph = intern ("escape-glyph");
+  staticpro (&Qescape_glyph);
   Qimage = intern ("image");
   staticpro (&Qimage);
   QCmap = intern (":map");
@@ -22247,6 +22455,10 @@ otherwise.  */);
     doc: /* *Non-nil means raise tool-bar buttons when the mouse moves over them.  */);
   auto_raise_tool_bar_buttons_p = 1;
 
+  DEFVAR_BOOL ("make-cursor-line-fully-visible", &make_cursor_line_fully_visible_p,
+    doc: /* *Non-nil means to scroll (recenter) cursor line if it is not fully visible.  */);
+  make_cursor_line_fully_visible_p = 1;
+
   DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin,
     doc: /* *Margin around tool-bar buttons in pixels.
 If an integer, use that for both horizontal and vertical margins.