]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
(erase_phys_cursor): Clear hollow cursor inside TEXT_AREA.
[gnu-emacs] / src / xdisp.c
index 45424db474c1ae9eec633762aecedc516e59abb6..3b7b9d39f81e6e648097bd2b84c8416f6f3fa606 100644 (file)
@@ -198,8 +198,6 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #ifdef MAC_OS
 #include "macterm.h"
-
-Cursor No_Cursor;
 #endif
 
 #ifndef FRAME_X_OUTPUT
@@ -217,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;
 
@@ -264,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;
@@ -308,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.  */
 
@@ -672,10 +677,6 @@ EMACS_INT hscroll_margin;
 /* How much to scroll horizontally when point is inside the above margin.  */
 Lisp_Object Vhscroll_step;
 
-/* A list of symbols, one for each supported image type.  */
-
-Lisp_Object Vimage_types;
-
 /* The variable `resize-mini-windows'.  If nil, don't resize
    mini-windows.  If t, always resize them to fit the text they
    display.  If `grow-only', let mini-windows grow only until they
@@ -891,7 +892,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 *));
@@ -1788,7 +1789,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);
     }
 
@@ -2078,6 +2080,7 @@ 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
@@ -3573,6 +3576,7 @@ handle_single_display_prop (it, prop, object, position,
          && CONSP (XCDR (prop)))
        {
          unsigned 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.  */
@@ -3583,8 +3587,8 @@ handle_single_display_prop (it, prop, object, position,
 
 #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))))
@@ -3613,12 +3617,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 */
@@ -4557,12 +4561,21 @@ 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;
        }
 
+      if (visible_p)
+       {
+         struct it it2 = *it;
+
+         if (handle_display_prop (&it2) == HANDLED_RETURN)
+           visible_p = 0;
+       }
+
       /* Back one more newline if the current one is invisible.  */
       if (!visible_p)
        back_to_previous_line_start (it);
@@ -4580,7 +4593,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;
 {
@@ -4885,13 +4898,17 @@ 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))
                       : (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 '^'
@@ -5647,9 +5664,13 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
     {
       int x, i, ascent = 0, descent = 0;
 
-      /* Stop when ZV or TO_CHARPOS reached.  */
+      /* Stop when ZV reached.
+         We used to stop here when TO_CHARPOS reached as well, but that is
+         too soon if this glyph does not fit on this line.  So we handle it
+         explicitly below.  */
       if (!get_next_display_element (it)
-         || BUFFER_POS_REACHED_P ())
+         || (it->truncate_lines_p
+             && BUFFER_POS_REACHED_P ()))
        {
          result = MOVE_POS_MATCH_OR_ZV;
          break;
@@ -5709,6 +5730,8 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
              /* We want to leave anything reaching TO_X to the caller.  */
              if ((op & MOVE_TO_X) && new_x > to_x)
                {
+                 if (BUFFER_POS_REACHED_P ())
+                   goto buffer_pos_reached;
                  it->current_x = x;
                  result = MOVE_X_REACHED;
                  break;
@@ -5736,17 +5759,26 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
 #ifdef HAVE_WINDOW_SYSTEM
                          if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
                            {
-                             if (!get_next_display_element (it)
-                                 || BUFFER_POS_REACHED_P ())
+                             if (!get_next_display_element (it))
                                {
                                  result = MOVE_POS_MATCH_OR_ZV;
                                  break;
                                }
+                             if (BUFFER_POS_REACHED_P ())
+                               {
+                                 if (ITERATOR_AT_END_OF_LINE_P (it))
+                                   result = MOVE_POS_MATCH_OR_ZV;
+                                 else
+                                   result = MOVE_LINE_CONTINUED;
+                                 break;
+                               }
                              if (ITERATOR_AT_END_OF_LINE_P (it))
                                {
                                  result = MOVE_NEWLINE_OR_CR;
                                  break;
                                }
+                             if (it->method == next_element_from_display_vector)
+                               it->face_id = it->saved_face_id;
                            }
 #endif /* HAVE_WINDOW_SYSTEM */
                        }
@@ -5763,6 +5795,8 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
                  result = MOVE_LINE_CONTINUED;
                  break;
                }
+             else if (BUFFER_POS_REACHED_P ())
+               goto buffer_pos_reached;
              else if (new_x > it->first_visible_x)
                {
                  /* Glyph is visible.  Increment number of glyphs that
@@ -5779,6 +5813,15 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
          if (result != MOVE_UNDEFINED)
            break;
        }
+      else if (BUFFER_POS_REACHED_P ())
+       {
+       buffer_pos_reached:
+         it->current_x = x;
+         it->max_ascent = ascent;
+         it->max_descent = descent;
+         result = MOVE_POS_MATCH_OR_ZV;
+         break;
+       }
       else if ((op & MOVE_TO_X) && it->current_x >= to_x)
        {
          /* Stop when TO_X specified and reached.  This check is
@@ -6033,10 +6076,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));
 
@@ -6102,13 +6148,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)
@@ -6149,7 +6195,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,
@@ -6246,6 +6292,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);
@@ -6313,6 +6361,7 @@ add_to_log (format, arg1, arg2)
   char *buffer;
   int len;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+  USE_SAFE_ALLOCA;
 
   /* Do nothing if called asynchronously.  Inserting text into
      a buffer may call after-change-functions and alike and
@@ -6329,10 +6378,12 @@ add_to_log (format, arg1, arg2)
   msg = Fformat (3, args);
 
   len = SBYTES (msg) + 1;
-  buffer = (char *) alloca (len);
+  SAFE_ALLOCA (buffer, char *, len);
   bcopy (SDATA (msg), buffer, len);
 
   message_dolog (buffer, len - 1, 1, 0);
+  SAFE_FREE ();
+
   UNGCPRO;
 }
 
@@ -6654,6 +6705,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 ();
@@ -7386,7 +7438,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;
        }
 
@@ -7942,7 +7994,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++);
 
@@ -8380,7 +8432,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
@@ -8399,18 +8452,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;
 
@@ -8657,6 +8716,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;
@@ -9489,11 +9549,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;
 {
@@ -9516,9 +9578,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;
        }
@@ -10352,7 +10415,7 @@ redisplay_internal (preserve_echo_area)
    This is useful in situations where you need to redisplay but no
    user action has occurred, making it inappropriate for the message
    area to be cleared.  See tracking_off and
-   wait_reading_process_input for examples of these situations.
+   wait_reading_process_output for examples of these situations.
 
    FROM_WHERE is an integer saying from where this function was
    called.  This is useful for debugging.  */
@@ -10373,6 +10436,9 @@ redisplay_preserve_echo_area (from_where)
     }
   else
     redisplay_internal (1);
+
+  if (rif != NULL && rif->flush_display_optional)
+    rif->flush_display_optional (NULL);
 }
 
 
@@ -10618,6 +10684,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.  */
@@ -10627,6 +10694,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.
@@ -10652,6 +10721,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
        {
@@ -10659,12 +10734,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
@@ -10793,6 +10896,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)
@@ -10802,7 +10908,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,
@@ -10956,7 +11062,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;
@@ -11002,7 +11108,12 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
          aggressive = current_buffer->scroll_up_aggressively;
          height = WINDOW_BOX_TEXT_HEIGHT (w);
          if (NUMBERP (aggressive))
-           amount_to_scroll = XFLOATINT (aggressive) * height;
+           {
+             double float_amount = XFLOATINT (aggressive) * height;
+             amount_to_scroll = float_amount;
+             if (amount_to_scroll == 0 && float_amount > 0)
+               amount_to_scroll = 1;
+           }
        }
 
       if (amount_to_scroll <= 0)
@@ -11051,8 +11162,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
@@ -11060,13 +11171,18 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
              aggressive = current_buffer->scroll_down_aggressively;
              height = WINDOW_BOX_TEXT_HEIGHT (w);
              if (NUMBERP (aggressive))
-               amount_to_scroll = XFLOATINT (aggressive) * height;
+               {
+                 double float_amount = XFLOATINT (aggressive) * height;
+                 amount_to_scroll = float_amount;
+                 if (amount_to_scroll == 0 && float_amount > 0)
+                   amount_to_scroll = 1;
+               }
            }
 
          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;
        }
     }
@@ -11255,7 +11371,7 @@ try_cursor_movement (window, startp, scroll_step)
       && (FRAME_WINDOW_P (f)
          || !overlay_arrow_in_current_buffer_p ()))
     {
-      int this_scroll_margin;
+      int this_scroll_margin, top_scroll_margin;
       struct glyph_row *row = NULL;
 
 #if GLYPH_DEBUG
@@ -11268,6 +11384,10 @@ try_cursor_movement (window, startp, scroll_step)
       this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
       this_scroll_margin *= FRAME_LINE_HEIGHT (f);
 
+      top_scroll_margin = this_scroll_margin;
+      if (WINDOW_WANTS_HEADER_LINE_P (w))
+       top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
+
       /* Start with the row the cursor was displayed during the last
         not paused redisplay.  Give up if that row is not valid.  */
       if (w->last_cursor.vpos < 0
@@ -11322,13 +11442,12 @@ 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
                             && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)))
-                    && (row->y > this_scroll_margin
+                    && (row->y > top_scroll_margin
                         || CHARPOS (startp) == BEGV))
                {
                  xassert (row->enabled_p);
@@ -11356,7 +11475,7 @@ try_cursor_movement (window, startp, scroll_step)
                ++row;
 
              /* If within the scroll margin, scroll.  */
-             if (row->y < this_scroll_margin
+             if (row->y < top_scroll_margin
                  && CHARPOS (startp) != BEGV)
                scroll_p = 1;
            }
@@ -11367,7 +11486,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
@@ -11835,8 +11955,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);
@@ -11942,7 +12062,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;
     }
@@ -11965,8 +12085,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
@@ -12130,14 +12250,16 @@ redisplay_window (window, just_this_one_p)
     }
 
 #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);
     }
@@ -12289,7 +12411,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
@@ -12324,10 +12446,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
@@ -12335,12 +12483,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);
@@ -12360,7 +12508,7 @@ 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;
 
@@ -12526,9 +12674,8 @@ try_window_reusing_current_matrix (w)
         position.  */
       if (pt_row)
        {
-         w->cursor.vpos -= MATRIX_ROW_VPOS (first_reusable_row,
-                                            w->current_matrix);
-         w->cursor.y -= first_reusable_row->y;
+         w->cursor.vpos -= nrows_scrolled;
+         w->cursor.y -= first_reusable_row->y - start_row->y;
        }
 
       /* Scroll the display.  */
@@ -12573,6 +12720,29 @@ try_window_reusing_current_matrix (w)
       for (row -= nrows_scrolled; row < bottom_row; ++row)
        row->enabled_p = 0;
 
+      /* Point may have moved to a different line, so we cannot assume that
+        the previous cursor position is valid; locate the correct row.  */
+      if (pt_row)
+       {
+         for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
+              row < bottom_row && PT >= MATRIX_ROW_END_CHARPOS (row);
+              row++)
+           {
+             w->cursor.vpos++;
+             w->cursor.y = row->y;
+           }
+         if (row < bottom_row)
+           {
+             struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
+             while (glyph->charpos < PT)
+               {
+                 w->cursor.hpos++;
+                 w->cursor.x += glyph->pixel_width;
+                 glyph++;
+               }
+           }
+       }
+
       /* Adjust window end.  A null value of last_text_row means that
         the window end is in reused rows which in turn means that
         only its vpos can have changed.  */
@@ -13356,9 +13526,11 @@ try_window_id (w)
 
     if ((w->cursor.y < this_scroll_margin
         && CHARPOS (start) > BEGV)
-       /* Don't take scroll margin into account at the bottom because
-          old redisplay didn't do it either.  */
-       || w->cursor.y + cursor_height > it.last_visible_y)
+       /* 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 + (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);
@@ -13936,8 +14108,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)
@@ -14083,6 +14255,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.  */
@@ -14126,6 +14299,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.  */
@@ -14421,9 +14595,13 @@ display_line (it)
   /* We always start displaying at hpos zero even if hscrolled.  */
   xassert (it->hpos == 0 && it->current_x == 0);
 
-  /* We must not display in a row that's not a text row.  */
-  xassert (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
-          < it->w->desired_matrix->nrows);
+  if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
+      >= it->w->desired_matrix->nrows)
+    {
+      it->w->nrows_scale_factor++;
+      fonts_changed_p = 1;
+      return 0;
+    }
 
   /* Is IT->w showing the region?  */
   it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
@@ -14458,6 +14636,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.  */
@@ -14523,6 +14702,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;
        }
@@ -14551,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);
          if (it->current_x - it->pixel_width < it->first_visible_x)
            row->x = x - it->first_visible_x;
        }
@@ -14604,6 +14787,8 @@ display_line (it)
                                  row->continued_p = 0;
                                  row->exact_window_width_line_p = 1;
                                }
+                             else if (it->method == next_element_from_display_vector)
+                               it->face_id = it->saved_face_id;
                            }
 #endif /* HAVE_WINDOW_SYSTEM */
                        }
@@ -14702,6 +14887,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)
@@ -14772,12 +14959,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))
                    {
@@ -14814,11 +14999,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);
@@ -14843,10 +15028,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.  */
@@ -15229,6 +15416,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,
@@ -15307,14 +15498,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);
@@ -15322,9 +15514,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
@@ -15605,7 +15802,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;
@@ -15626,7 +15824,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;
@@ -15651,7 +15849,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
@@ -15687,15 +15885,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;
@@ -15707,42 +15906,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
@@ -15871,27 +16074,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. */
@@ -16015,7 +16222,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[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
 
@@ -16029,7 +16239,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;
@@ -16331,7 +16541,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
@@ -16590,6 +16800,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.  */
@@ -16649,6 +16860,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;
        }
@@ -17085,7 +17298,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;
@@ -18057,6 +18271,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.  */
@@ -18094,6 +18321,8 @@ append_glyph (it)
       glyph->font_type = FONT_TYPE_UNKNOWN;
       ++it->glyph_row->used[area];
     }
+  else
+    IT_EXPAND_MATRIX_WIDTH (it, area);
 }
 
 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
@@ -18131,6 +18360,8 @@ append_composite_glyph (it)
       glyph->font_type = FONT_TYPE_UNKNOWN;
       ++it->glyph_row->used[area];
     }
+  else
+    IT_EXPAND_MATRIX_WIDTH (it, area);
 }
 
 
@@ -18165,7 +18396,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);
@@ -18248,7 +18479,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
@@ -18300,6 +18531,8 @@ produce_image_glyph (it)
          glyph->font_type = FONT_TYPE_UNKNOWN;
          ++it->glyph_row->used[area];
        }
+      else
+       IT_EXPAND_MATRIX_WIDTH (it, area);
     }
 }
 
@@ -18343,6 +18576,8 @@ append_stretch_glyph (it, object, width, height, ascent)
       glyph->font_type = FONT_TYPE_UNKNOWN;
       ++it->glyph_row->used[area];
     }
+  else
+    IT_EXPAND_MATRIX_WIDTH (it, area);
 }
 
 
@@ -18397,14 +18632,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.
@@ -18428,7 +18663,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)
@@ -18448,13 +18683,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
@@ -18466,7 +18701,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)
@@ -18526,8 +18761,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);
 
@@ -19249,7 +19486,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);
@@ -19831,6 +20072,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.  */
@@ -19874,6 +20120,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)
@@ -19881,9 +20128,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);
+      rif->clear_frame_area (f, x, y, width, cursor_row->visible_height);
     }
 
   /* Erase the cursor by redrawing the character underneath it.  */
@@ -20216,19 +20464,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;
@@ -20598,6 +20847,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))
@@ -20620,11 +20873,7 @@ define_frame_cursor1 (f, cursor, pointer)
        cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
     }
 
-#ifndef HAVE_CARBON
   if (cursor != No_Cursor)
-#else
-  if (bcmp (&cursor, &No_Cursor, sizeof (Cursor)))
-#endif
     rif->define_frame_cursor (f, cursor);
 }
 
@@ -20663,7 +20912,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))
@@ -20675,12 +20924,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;
@@ -20691,7 +20942,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);
        }
     }
 
@@ -20701,13 +20952,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))
@@ -20774,8 +21028,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.  */
@@ -20807,7 +21063,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;
@@ -20839,7 +21096,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,
@@ -20853,12 +21110,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;
@@ -20868,7 +21127,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);
            }
        }
 
@@ -21462,6 +21721,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))
     {
@@ -22141,7 +22403,7 @@ all the functions in the list are called, with the frame as argument.  */);
   Vwindow_size_change_functions = Qnil;
 
   DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
-    doc: /* List of Functions to call before redisplaying a window with scrolling.
+    doc: /* List of functions to call before redisplaying a window with scrolling.
 Each function is called with two arguments, the window
 and its new display-start position.  Note that the value of `window-end'
 is not valid when these functions are called.  */);
@@ -22162,6 +22424,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.
@@ -22247,11 +22513,6 @@ Note that the lower bound for automatic hscrolling specified by `scroll-left'
 and `scroll-right' overrides this variable's effect.  */);
   Vhscroll_step = make_number (0);
 
-  DEFVAR_LISP ("image-types", &Vimage_types,
-    doc: /* List of supported image types.
-Each element of the list is a symbol for a supported image type.  */);
-  Vimage_types = Qnil;
-
   DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
     doc: /* If non-nil, messages are truncated instead of resizing the echo area.
 Bind this around calls to `message' to let it take effect.  */);