]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Merged in changes from CVS trunk.
[gnu-emacs] / src / xdisp.c
index b16331322144d7974a7f06e41684a836213241ea..90399c060312e6b48bf74c766038bb5a3e7e05ba 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
@@ -301,11 +299,14 @@ extern Lisp_Object Qface, Qinvisible, Qwidth;
 Lisp_Object Vdisplay_pixels_per_inch;
 Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
 Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
+Lisp_Object Qslice;
 Lisp_Object Qcenter;
 Lisp_Object Qmargin, Qpointer;
+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.  */
 
@@ -670,10 +671,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
@@ -770,10 +767,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;
@@ -797,6 +790,9 @@ int help_echo_pos;
 
 Lisp_Object previous_help_echo_string;
 
+/* Null glyph slice */
+
+static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
 
 \f
 /* Function prototypes.  */
@@ -849,7 +845,7 @@ static void insert_left_trunc_glyphs P_ ((struct it *));
 static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *,
                                                          Lisp_Object));
 static void extend_face_to_end_of_line P_ ((struct it *));
-static int append_space P_ ((struct it *, int));
+static int append_space_for_newline P_ ((struct it *, int));
 static int make_cursor_line_fully_visible P_ ((struct window *, int));
 static int try_scrolling P_ ((Lisp_Object, int, EMACS_INT, EMACS_INT, int, int));
 static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
@@ -1235,9 +1231,9 @@ line_bottom_y (it)
    and header-lines heights.  */
 
 int
-pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
+pos_visible_p (w, charpos, fully, x, y, exact_mode_line_heights_p)
      struct window *w;
-     int charpos, *fully, exact_mode_line_heights_p;
+     int charpos, *fully, *x, *y, exact_mode_line_heights_p;
 {
   struct it it;
   struct text_pos top;
@@ -1285,14 +1281,27 @@ pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
          visible_p = 1;
          *fully = bottom_y <= it.last_visible_y;
        }
+      if (visible_p && x)
+       {
+         *x = it.current_x;
+         *y = max (top_y + it.max_ascent - it.ascent, window_top_y);
+       }
     }
   else if (it.current_y + it.max_ascent + it.max_descent > it.last_visible_y)
     {
+      struct it it2;
+
+      it2 = it;
       move_it_by_lines (&it, 1, 0);
       if (charpos < IT_CHARPOS (it))
        {
          visible_p = 1;
-         *fully  = 0;
+         if (x)
+           {
+             move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
+             *x = it2.current_x;
+             *y = it2.current_y + it2.max_ascent - it2.ascent;
+           }
        }
     }
 
@@ -1300,6 +1309,7 @@ pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
     set_buffer_internal_1 (old_buffer);
 
   current_header_line_height = current_mode_line_height = -1;
+
   return visible_p;
 }
 
@@ -2047,29 +2057,34 @@ 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))
     {
       if (NATNUMP (current_buffer->extra_line_spacing))
        it->extra_line_spacing = XFASTINT (current_buffer->extra_line_spacing);
+      else if (FLOATP (current_buffer->extra_line_spacing))
+       it->extra_line_spacing = (XFLOAT_DATA (current_buffer->extra_line_spacing)
+                                 * FRAME_LINE_HEIGHT (it->f));
       else if (it->f->extra_line_spacing > 0)
        it->extra_line_spacing = it->f->extra_line_spacing;
     }
 
   /* 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);
 
-  /* Current value of the `space-width', and 'height' properties.  */
+  /* Current value of the `slice', `space-width', and 'height' properties.  */
+  it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
   it->space_width = Qnil;
   it->font_height = Qnil;
+  it->override_ascent = -1;
 
   /* Are control characters displayed as `^C'?  */
   it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
@@ -2710,19 +2725,10 @@ next_overlay_change (pos)
   int noverlays;
   int endpos;
   Lisp_Object *overlays;
-  int len;
   int i;
 
   /* Get all overlays at the given position.  */
-  len = 10;
-  overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
-  noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
-  if (noverlays > len)
-    {
-      len = noverlays;
-      overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
-      noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
-    }
+  GET_OVERLAYS_AT (pos, overlays, noverlays, &endpos, 1);
 
   /* If any of these overlays ends before endpos,
      use its ending point instead.  */
@@ -3275,8 +3281,9 @@ handle_display_prop (it)
     }
 
   /* Reset those iterator values set from display property values.  */
-  it->font_height = Qnil;
+  it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
   it->space_width = Qnil;
+  it->font_height = Qnil;
   it->voffset = 0;
 
   /* We don't support recursive `display' properties, i.e. string
@@ -3295,6 +3302,7 @@ handle_display_prop (it)
       && !EQ (XCAR (prop), Qimage)
       && !EQ (XCAR (prop), Qspace)
       && !EQ (XCAR (prop), Qwhen)
+      && !EQ (XCAR (prop), Qslice)
       && !EQ (XCAR (prop), Qspace_width)
       && !EQ (XCAR (prop), Qheight)
       && !EQ (XCAR (prop), Qraise)
@@ -3490,6 +3498,30 @@ handle_single_display_prop (it, prop, object, position,
       if (NUMBERP (value) && XFLOATINT (value) > 0)
        it->space_width = value;
     }
+  else if (CONSP (prop)
+          && EQ (XCAR (prop), Qslice))
+    {
+      /* `(slice X Y WIDTH HEIGHT)'.  */
+      Lisp_Object tem;
+
+      if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+       return 0;
+
+      if (tem = XCDR (prop), CONSP (tem))
+       {
+         it->slice.x = XCAR (tem);
+         if (tem = XCDR (tem), CONSP (tem))
+           {
+             it->slice.y = XCAR (tem);
+             if (tem = XCDR (tem), CONSP (tem))
+               {
+                 it->slice.width = XCAR (tem);
+                 if (tem = XCDR (tem), CONSP (tem))
+                   it->slice.height = XCAR (tem);
+               }
+           }
+       }
+    }
   else if (CONSP (prop)
           && EQ (XCAR (prop), Qraise)
           && CONSP (XCDR (prop)))
@@ -4331,6 +4363,7 @@ push_it (it)
   p->string_nchars = it->string_nchars;
   p->area = it->area;
   p->multibyte_p = it->multibyte_p;
+  p->slice = it->slice;
   p->space_width = it->space_width;
   p->font_height = it->font_height;
   p->voffset = it->voffset;
@@ -4363,6 +4396,7 @@ pop_it (it)
   it->string_nchars = p->string_nchars;
   it->area = p->area;
   it->multibyte_p = p->multibyte_p;
+  it->slice = p->slice;
   it->space_width = p->space_width;
   it->font_height = p->font_height;
   it->voffset = p->voffset;
@@ -4520,6 +4554,14 @@ back_to_previous_visible_line_start (it)
            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);
@@ -5604,9 +5646,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;
@@ -5666,6 +5712,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;
@@ -5693,12 +5741,19 @@ 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;
@@ -5720,6 +5775,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
@@ -5736,6 +5793,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
@@ -6270,6 +6336,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
@@ -6286,10 +6353,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 (len);
+
   UNGCPRO;
 }
 
@@ -6591,8 +6660,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);
     }
 }
 
@@ -6677,8 +6746,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);
     }
 }
 
@@ -7701,11 +7770,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)
@@ -7719,7 +7788,7 @@ clear_garbaged_frames ()
              f->resized_p = 0;
            }
        }
-
+      
       frame_garbaged = 0;
       if (changed_count)
        ++windows_or_buffers_changed;
@@ -7752,11 +7821,11 @@ 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_TERMCAP_P (XFRAME (selected_frame))
+      && FRAME_TTY (XFRAME (selected_frame))->type == NULL)
     return 0;
 #endif /* HAVE_WINDOW_SYSTEM */
 #endif
@@ -7807,7 +7876,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);
@@ -8268,8 +8337,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;
     }
 }
@@ -9428,7 +9497,7 @@ update_overlay_arrows (up_to_date)
       if (!SYMBOLP (var))
        continue;
 
-      if (up_to_date)
+      if (up_to_date > 0)
        {
          Lisp_Object val = find_symbol_value (var);
          Fput (var, Qlast_arrow_position,
@@ -9690,17 +9759,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
@@ -9722,6 +9790,7 @@ redisplay_internal (preserve_echo_area)
       }
   }
 
+  
   /* Notice any pending interrupt request to change frame size.  */
   do_pending_window_change (1);
 
@@ -10081,7 +10150,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
@@ -10096,16 +10165,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
@@ -10157,8 +10226,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);
            }
        }
     }
@@ -10243,8 +10312,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;
@@ -10309,7 +10378,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.  */
@@ -10575,6 +10644,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.  */
@@ -10584,6 +10654,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.
@@ -10609,6 +10681,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
        {
@@ -10616,12 +10694,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
@@ -10762,15 +10868,14 @@ make_cursor_line_fully_visible (w, force_p)
   if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
     return 1;
 
-  if (force_p)
-    return 0;
-
   /* If the row the cursor is in is taller than the window's height,
      it's not clear what to do, so do nothing.  */
   window_height = window_box_height (w);
   if (row->height >= window_height)
-    return 1;
-
+    {
+      if (!force_p || w->vscroll)
+       return 1;
+    }
   return 0;
 
 #if 0
@@ -10879,6 +10984,12 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
   else
     this_scroll_margin = 0;
 
+  /* Force scroll_conservatively to have a reasonable value so it doesn't
+     cause an overflow while computing how much to scroll.  */
+  if (scroll_conservatively)
+    scroll_conservatively = min (scroll_conservatively,
+                                 MOST_POSITIVE_FIXNUM / FRAME_LINE_HEIGHT (f));
+
   /* Compute how much we should try to scroll maximally to bring point
      into view.  */
   if (scroll_step || scroll_conservatively || temp_scroll_step)
@@ -10954,7 +11065,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)
@@ -11003,8 +11119,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
@@ -11012,7 +11128,12 @@ 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)
@@ -11207,7 +11328,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
@@ -11220,6 +11341,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
@@ -11274,13 +11399,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);
@@ -11308,7 +11432,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;
            }
@@ -11389,7 +11513,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);
 }
 
 
@@ -11787,8 +11913,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);
@@ -11917,8 +12043,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
@@ -12110,7 +12236,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.  */
@@ -12276,10 +12403,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 (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
@@ -12287,12 +12440,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);
@@ -12312,17 +12465,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);
            }
 
@@ -12478,9 +12631,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.  */
@@ -12492,10 +12644,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);
        }
 
@@ -12525,6 +12677,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.  */
@@ -12920,7 +13095,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);
 
@@ -13308,9 +13483,9 @@ 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 + cursor_height + this_scroll_margin > it.last_visible_y)
       {
        w->cursor.vpos = -1;
        clear_glyph_matrix (w->desired_matrix);
@@ -13327,10 +13502,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
        {
@@ -13348,36 +13523,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);
@@ -14096,8 +14271,7 @@ compute_line_metrics (it)
 
 
 /* Append one space to the glyph row of iterator IT if doing a
-   window-based redisplay.  DEFAULT_FACE_P non-zero means let the
-   space have the default face, otherwise let it have the same face as
+   window-based redisplay.  The space has the same face as
    IT->face_id.  Value is non-zero if a space was added.
 
    This function is called to make sure that there is always one glyph
@@ -14109,7 +14283,7 @@ compute_line_metrics (it)
    end of the line if the row ends in italic text.  */
 
 static int
-append_space (it, default_face_p)
+append_space_for_newline (it, default_face_p)
      struct it *it;
      int default_face_p;
 {
@@ -14123,7 +14297,7 @@ append_space (it, default_face_p)
          /* Save some values that must not be changed.
             Must save IT->c and IT->len because otherwise
             ITERATOR_AT_END_P wouldn't work anymore after
-            append_space has been called.  */
+            append_space_for_newline has been called.  */
          enum display_element_type saved_what = it->what;
          int saved_c = it->c, saved_len = it->len;
          int saved_x = it->current_x;
@@ -14150,6 +14324,8 @@ append_space (it, default_face_p)
 
          PRODUCE_GLYPHS (it);
 
+         it->override_ascent = -1;
+         it->constrain_row_ascent_descent_p = 0;
          it->current_x = saved_x;
          it->object = saved_object;
          it->position = saved_pos;
@@ -14372,9 +14548,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;
@@ -14431,7 +14611,7 @@ display_line (it)
            row->exact_window_width_line_p = 1;
          else
 #endif /* HAVE_WINDOW_SYSTEM */
-         if ((append_space (it, 1) && row->used[TEXT_AREA] == 1)
+         if ((append_space_for_newline (it, 1) && row->used[TEXT_AREA] == 1)
              || row->used[TEXT_AREA] == 0)
            {
              row->glyphs[TEXT_AREA]->charpos = -1;
@@ -14673,7 +14853,7 @@ display_line (it)
          /* Add a space at the end of the line that is used to
             display the cursor there.  */
          if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
-           append_space (it, 0);
+           append_space_for_newline (it, 0);
 #endif /* HAVE_WINDOW_SYSTEM */
 
          /* Extend the face to the end of the line.  */
@@ -15180,6 +15360,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,
@@ -15556,7 +15740,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;
@@ -15638,15 +15823,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;
@@ -15658,42 +15844,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
@@ -15966,7 +16156,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[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
 
@@ -15980,7 +16173,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;
@@ -16282,7 +16475,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
@@ -16309,8 +16502,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);
@@ -17147,7 +17340,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);
        }
     }
 
@@ -17296,6 +17489,7 @@ fill_image_glyph_string (s)
   xassert (s->first_glyph->type == IMAGE_GLYPH);
   s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
   xassert (s->img);
+  s->slice = s->first_glyph->slice;
   s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
   s->font = s->face->font;
   s->width = s->first_glyph->pixel_width;
@@ -17377,7 +17571,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;
@@ -17545,7 +17739,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);
        }
     }
 
@@ -17612,8 +17806,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;
@@ -17623,8 +17817,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;
@@ -17905,9 +18099,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
@@ -17975,7 +18169,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
@@ -18040,9 +18234,15 @@ append_glyph (it)
       glyph->glyph_not_available_p = it->glyph_not_available_p;
       glyph->face_id = it->face_id;
       glyph->u.ch = it->char_to_display;
+      glyph->slice = null_glyph_slice;
       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;
+    }
 }
 
 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
@@ -18076,9 +18276,15 @@ append_composite_glyph (it)
       glyph->glyph_not_available_p = 0;
       glyph->face_id = it->face_id;
       glyph->u.cmp_id = it->cmp_id;
+      glyph->slice = null_glyph_slice;
       glyph->font_type = FONT_TYPE_UNKNOWN;
       ++it->glyph_row->used[area];
     }
+  else if (!fonts_changed_p)
+    {
+      it->w->ncols_scale_factor++;
+      fonts_changed_p = 1;
+    }
 }
 
 
@@ -18094,7 +18300,7 @@ take_vertical_position_into_account (it)
       if (it->voffset < 0)
        /* Increase the ascent so that we can display the text higher
           in the line.  */
-       it->ascent += abs (it->voffset);
+       it->ascent -= it->voffset;
       else
        /* Increase the descent so that we can display the text lower
           in the line.  */
@@ -18114,6 +18320,7 @@ produce_image_glyph (it)
   struct image *img;
   struct face *face;
   int face_ascent, glyph_ascent;
+  struct glyph_slice slice;
 
   xassert (it->what == IT_IMAGE);
 
@@ -18137,19 +18344,68 @@ produce_image_glyph (it)
   /* Make sure X resources of the image is loaded.  */
   prepare_image_for_display (it->f, img);
 
-  it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face);
-  it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
-  it->pixel_width = img->width + 2 * img->hmargin;
+  slice.x = slice.y = 0;
+  slice.width = img->width;
+  slice.height = img->height;
+
+  if (INTEGERP (it->slice.x))
+    slice.x = XINT (it->slice.x);
+  else if (FLOATP (it->slice.x))
+    slice.x = XFLOAT_DATA (it->slice.x) * img->width;
+
+  if (INTEGERP (it->slice.y))
+    slice.y = XINT (it->slice.y);
+  else if (FLOATP (it->slice.y))
+    slice.y = XFLOAT_DATA (it->slice.y) * img->height;
+
+  if (INTEGERP (it->slice.width))
+    slice.width = XINT (it->slice.width);
+  else if (FLOATP (it->slice.width))
+    slice.width = XFLOAT_DATA (it->slice.width) * img->width;
+
+  if (INTEGERP (it->slice.height))
+    slice.height = XINT (it->slice.height);
+  else if (FLOATP (it->slice.height))
+    slice.height = XFLOAT_DATA (it->slice.height) * img->height;
+
+  if (slice.x >= img->width)
+    slice.x = img->width;
+  if (slice.y >= img->height)
+    slice.y = img->height;
+  if (slice.x + slice.width >= img->width)
+    slice.width = img->width - slice.x;
+  if (slice.y + slice.height > img->height)
+    slice.height = img->height - slice.y;
+
+  if (slice.width == 0 || slice.height == 0)
+    return;
+
+  it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face, &slice);
+
+  it->descent = slice.height - glyph_ascent;
+  if (slice.y == 0)
+    it->descent += img->vmargin;
+  if (slice.y + slice.height == img->height)
+    it->descent += img->vmargin;
+  it->phys_descent = it->descent;
+
+  it->pixel_width = slice.width;
+  if (slice.x == 0)
+    it->pixel_width += img->hmargin;
+  if (slice.x + slice.width == img->width)
+    it->pixel_width += img->hmargin;
 
   /* It's quite possible for images to have an ascent greater than
      their height, so don't get confused in that case.  */
   if (it->descent < 0)
     it->descent = 0;
 
+#if 0  /* this breaks image tiling */
   /* If this glyph is alone on the last line, adjust it.ascent to minimum row ascent.  */
   face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f);
   if (face_ascent > it->ascent)
     it->ascent = it->phys_ascent = face_ascent;
+#endif
 
   it->nglyphs = 1;
 
@@ -18157,13 +18413,15 @@ produce_image_glyph (it)
     {
       if (face->box_line_width > 0)
        {
-         it->ascent += face->box_line_width;
-         it->descent += face->box_line_width;
+         if (slice.y == 0)
+           it->ascent += face->box_line_width;
+         if (slice.y + slice.height == img->height)
+           it->descent += face->box_line_width;
        }
 
-      if (it->start_of_box_run_p)
+      if (it->start_of_box_run_p && slice.x == 0)
        it->pixel_width += abs (face->box_line_width);
-      if (it->end_of_box_run_p)
+      if (it->end_of_box_run_p && slice.x + slice.width == img->width)
        it->pixel_width += abs (face->box_line_width);
     }
 
@@ -18192,9 +18450,15 @@ produce_image_glyph (it)
          glyph->glyph_not_available_p = 0;
          glyph->face_id = it->face_id;
          glyph->u.img_id = img->id;
+         glyph->slice = slice;
          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;
+       }
     }
 }
 
@@ -18234,9 +18498,15 @@ append_stretch_glyph (it, object, width, height, ascent)
       glyph->face_id = it->face_id;
       glyph->u.stretch.ascent = ascent;
       glyph->u.stretch.height = height;
+      glyph->slice = null_glyph_slice;
       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;
+    }
 }
 
 
@@ -18399,6 +18669,107 @@ produce_stretch_glyph (it)
   take_vertical_position_into_account (it);
 }
 
+/* Calculate line-height and line-spacing properties.
+   An integer value specifies explicit pixel value.
+   A float value specifies relative value to current face height.
+   A cons (float . face-name) specifies relative value to
+   height of specified face font.
+
+   Returns height in pixels, or nil.  */
+
+static Lisp_Object
+calc_line_height_property (it, prop, font, boff, total)
+     struct it *it;
+     Lisp_Object prop;
+     XFontStruct *font;
+     int boff, *total;
+{
+  Lisp_Object position, val;
+  Lisp_Object face_name = Qnil;
+  int ascent, descent, height, override;
+
+  if (STRINGP (it->object))
+    position = make_number (IT_STRING_CHARPOS (*it));
+  else
+    position = make_number (IT_CHARPOS (*it));
+
+  val = Fget_char_property (position, prop, it->object);
+
+  if (NILP (val))
+    return val;
+
+  if (total && CONSP (val) && EQ (XCAR (val), Qtotal))
+    {
+      *total = 1;
+      val = XCDR (val);
+    }
+
+  if (INTEGERP (val))
+    return val;
+
+  if (CONSP (val))
+    {
+      face_name = XCDR (val);
+      val = XCAR (val);
+    }
+  else if (SYMBOLP (val))
+    {
+      face_name = val;
+      val = Qnil;
+    }
+
+  override = EQ (prop, Qline_height);
+
+  if (NILP (face_name))
+    {
+      font = FRAME_FONT (it->f);
+      boff = FRAME_BASELINE_OFFSET (it->f);
+    }
+  else if (EQ (face_name, Qt))
+    {
+      override = 0;
+    }
+  else
+    {
+      int face_id;
+      struct face *face;
+      struct font_info *font_info;
+
+      face_id = lookup_named_face (it->f, face_name, ' ');
+      if (face_id < 0)
+       return make_number (-1);
+
+      face = FACE_FROM_ID (it->f, face_id);
+      font = face->font;
+      if (font == NULL)
+       return make_number (-1);
+
+      font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+      boff = font_info->baseline_offset;
+      if (font_info->vertical_centering)
+       boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+    }
+
+  ascent = FONT_BASE (font) + boff;
+  descent = FONT_DESCENT (font) - boff;
+
+  if (override)
+    {
+      it->override_ascent = ascent;
+      it->override_descent = descent;
+      it->override_boff = boff;
+    }
+
+  height = ascent + descent;
+  if (FLOATP (val))
+    height = (int)(XFLOAT_DATA (val) * height);
+  else if (INTEGERP (val))
+    height *= XINT (val);
+
+  return make_number (height);
+}
+
+
 /* RIF:
    Produce glyphs/get display metrics for the display element IT is
    loaded with.  See the description of struct display_iterator in
@@ -18408,6 +18779,8 @@ void
 x_produce_glyphs (it)
      struct it *it;
 {
+  int extra_line_spacing = it->extra_line_spacing;
+
   it->glyph_not_available_p = 0;
 
   if (it->what == IT_CHARACTER)
@@ -18483,10 +18856,20 @@ x_produce_glyphs (it)
 
          it->nglyphs = 1;
 
-         pcm = rif->per_char_metric (font, &char2b,
-                                     FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
-         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)
            {
@@ -18497,11 +18880,28 @@ x_produce_glyphs (it)
          else
            {
              it->glyph_not_available_p = 1;
-              it->phys_ascent = FONT_BASE (font) + boff;
-              it->phys_descent = FONT_DESCENT (font) - boff;
+             it->phys_ascent = it->ascent;
+             it->phys_descent = it->descent;
              it->pixel_width = FONT_WIDTH (font);
            }
 
+         if (it->constrain_row_ascent_descent_p)
+           {
+             if (it->descent > it->max_descent)
+               {
+                 it->ascent += it->descent - it->max_descent;
+                 it->descent = it->max_descent;
+               }
+             if (it->ascent > it->max_ascent)
+               {
+                 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
+                 it->ascent = it->max_ascent;
+               }
+             it->phys_ascent = min (it->phys_ascent, it->ascent);
+             it->phys_descent = min (it->phys_descent, it->descent);
+             extra_line_spacing = 0;
+           }
+
          /* If this is a space inside a region of text with
             `space-width' property, change its width.  */
          stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
@@ -18534,6 +18934,14 @@ x_produce_glyphs (it)
          if (face->overline_p)
            it->ascent += 2;
 
+         if (it->constrain_row_ascent_descent_p)
+           {
+             if (it->ascent > it->max_ascent)
+               it->ascent = it->max_ascent;
+             if (it->descent > it->max_descent)
+               it->descent = it->max_descent;
+           }
+
          take_vertical_position_into_account (it);
 
          /* If we have to actually produce glyphs, do it.  */
@@ -18560,17 +18968,73 @@ x_produce_glyphs (it)
        }
       else if (it->char_to_display == '\n')
        {
-         /* A newline has no width but we need the height of the line.  */
+         /* A newline has no width but we need the height of the line.
+            But if previous part of the line set a height, don't
+            increase that height */
+
+         Lisp_Object height;
+
+         it->override_ascent = -1;
          it->pixel_width = 0;
          it->nglyphs = 0;
-         it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
-         it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
 
-         if (face->box != FACE_NO_BOX
-             && face->box_line_width > 0)
+         height = calc_line_height_property(it, Qline_height, font, boff, 0);
+
+         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 (EQ (height, make_number(0)))
            {
-             it->ascent += face->box_line_width;
-             it->descent += face->box_line_width;
+             if (it->descent > it->max_descent)
+               {
+                 it->ascent += it->descent - it->max_descent;
+                 it->descent = it->max_descent;
+               }
+             if (it->ascent > it->max_ascent)
+               {
+                 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
+                 it->ascent = it->max_ascent;
+               }
+             it->phys_ascent = min (it->phys_ascent, it->ascent);
+             it->phys_descent = min (it->phys_descent, it->descent);
+             it->constrain_row_ascent_descent_p = 1;
+             extra_line_spacing = 0;
+           }
+         else
+           {
+             Lisp_Object spacing;
+             int total = 0;
+
+             it->phys_ascent = it->ascent;
+             it->phys_descent = it->descent;
+
+             if ((it->max_ascent > 0 || it->max_descent > 0)
+                 && face->box != FACE_NO_BOX
+                 && face->box_line_width > 0)
+               {
+                 it->ascent += face->box_line_width;
+                 it->descent += face->box_line_width;
+               }
+             if (!NILP (height)
+                 && XINT (height) > it->ascent + it->descent)
+               it->ascent = XINT (height) - it->descent;
+
+             spacing = calc_line_height_property(it, Qline_spacing, font, boff, &total);
+             if (INTEGERP (spacing))
+               {
+                 extra_line_spacing = XINT (spacing);
+                 if (total)
+                   extra_line_spacing -= (it->phys_ascent + it->phys_descent);
+               }
            }
        }
       else if (it->char_to_display == '\t')
@@ -18608,8 +19072,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)
            {
@@ -18740,8 +19204,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;
@@ -18799,8 +19263,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;
@@ -18948,7 +19412,8 @@ x_produce_glyphs (it)
   if (it->area == TEXT_AREA)
     it->current_x += it->pixel_width;
 
-  it->descent += it->extra_line_spacing;
+  if (extra_line_spacing > 0)
+    it->descent += extra_line_spacing;
 
   it->max_ascent = max (it->max_ascent, it->ascent);
   it->max_descent = max (it->max_descent, it->descent);
@@ -19035,8 +19500,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];
@@ -19118,8 +19583,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;
     }
 }
@@ -19581,8 +20046,8 @@ 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));
 
-      rif->clear_frame_area (f, x, y,
-                            cursor_glyph->pixel_width, cursor_row->visible_height);
+      FRAME_RIF (f)->clear_frame_area (f, x, y,
+                                       cursor_glyph->pixel_width, cursor_row->visible_height);
     }
 
   /* Erase the cursor by redrawing the character underneath it.  */
@@ -19679,9 +20144,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);
 }
 
 
@@ -19826,11 +20291,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:
@@ -20244,8 +20709,7 @@ on_hot_spot_p (hot_spot, x, y)
          return inside;
        }
     }
-  else
-    return 0;
+  return 0;
 }
 
 Lisp_Object
@@ -20280,7 +20744,6 @@ Returns the alist element for the first matching AREA in MAP.  */)
      Lisp_Object map;
      Lisp_Object x, y;
 {
-  int ix, iy;
   if (NILP (map))
     return Qnil;
 
@@ -20320,12 +20783,8 @@ 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);
+    FRAME_RIF (f)->define_frame_cursor (f, cursor);
 }
 
 /* Take proper action when mouse has moved to the mode or header line
@@ -20346,7 +20805,7 @@ note_mode_line_or_margin_highlight (w, x, y, area)
   Lisp_Object pointer = Qnil;
   int charpos, dx, dy, width, height;
   Lisp_Object string, object = Qnil;
-  Lisp_Object pos, help, image;
+  Lisp_Object pos, help;
 
   if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
     string = mode_line_string (w, area, &x, &y, &charpos,
@@ -20507,7 +20966,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;
@@ -20525,7 +20985,7 @@ note_mouse_highlight (f, x, y)
       Lisp_Object object;
       Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
       Lisp_Object *overlay_vec = NULL;
-      int len, noverlays;
+      int noverlays;
       struct buffer *obuf;
       int obegv, ozv, same_region;
 
@@ -20541,7 +21001,9 @@ note_mouse_highlight (f, x, y)
              Lisp_Object image_map, hotspot;
              if ((image_map = Fplist_get (XCDR (img->spec), QCmap),
                   !NILP (image_map))
-                 && (hotspot = find_hot_spot (image_map, dx, dy),
+                 && (hotspot = find_hot_spot (image_map,
+                                              glyph->slice.x + dx,
+                                              glyph->slice.y + dy),
                      CONSP (hotspot))
                  && (hotspot = XCDR (hotspot), CONSP (hotspot)))
                {
@@ -20610,19 +21072,8 @@ note_mouse_highlight (f, x, y)
 
       if (BUFFERP (object))
        {
-         /* Put all the overlays we want in a vector in overlay_vec.
-            Store the length in len.  If there are more than 10, make
-            enough space for all, and try again.  */
-         len = 10;
-         overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-         noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
-         if (noverlays > len)
-           {
-             len = noverlays;
-             overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-             noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
-           }
-
+         /* Put all the overlays we want in a vector in overlay_vec.  */
+         GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
          /* Sort overlays into increasing priority order.  */
          noverlays = sort_overlays (overlay_vec, noverlays, w);
        }
@@ -21150,8 +21601,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;
 }
 
 
@@ -21163,6 +21614,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 */
@@ -21179,7 +21632,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))
@@ -21189,7 +21642,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);
     }
 }
 
@@ -21578,6 +22031,8 @@ syms_of_xdisp ()
   staticpro (&Qspace_width);
   Qraise = intern ("raise");
   staticpro (&Qraise);
+  Qslice = intern ("slice");
+  staticpro (&Qslice);
   Qspace = intern ("space");
   staticpro (&Qspace);
   Qmargin = intern ("margin");
@@ -21590,6 +22045,10 @@ syms_of_xdisp ()
   staticpro (&Qright_margin);
   Qcenter = intern ("center");
   staticpro (&Qcenter);
+  Qline_height = intern ("line-height");
+  staticpro (&Qline_height);
+  Qtotal = intern ("total");
+  staticpro (&Qtotal);
   QCalign_to = intern (":align-to");
   staticpro (&QCalign_to);
   QCrelative_width = intern (":relative-width");
@@ -21844,7 +22303,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.  */);
@@ -21950,11 +22409,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.  */);