In temp_output_buffer_show make sure window returned by display_buffer is live (Bug...
[bpt/emacs.git] / src / window.c
index 76432f8..560f31e 100644 (file)
@@ -66,14 +66,11 @@ static Lisp_Object Qsafe, Qabove, Qbelow, Qwindow_size, Qclone_of;
 static int displayed_window_lines (struct window *);
 static int count_windows (struct window *);
 static int get_leaf_windows (struct window *, struct window **, int);
-static void window_scroll (Lisp_Object, EMACS_INT, int, int);
-static void window_scroll_pixel_based (Lisp_Object, int, int, int);
-static void window_scroll_line_based (Lisp_Object, int, int, int);
-static int freeze_window_start (struct window *, void *);
+static void window_scroll (Lisp_Object, EMACS_INT, bool, int);
+static void window_scroll_pixel_based (Lisp_Object, int, bool, int);
+static void window_scroll_line_based (Lisp_Object, int, bool, int);
 static Lisp_Object window_list (void);
 static int add_window_to_list (struct window *, void *);
-static int candidate_window_p (Lisp_Object, Lisp_Object, Lisp_Object,
-                               Lisp_Object);
 static Lisp_Object next_window (Lisp_Object, Lisp_Object,
                                 Lisp_Object, int);
 static void decode_next_window_args (Lisp_Object *, Lisp_Object *,
@@ -90,6 +87,14 @@ static void window_resize_apply (struct window *, bool);
 static Lisp_Object select_window (Lisp_Object, Lisp_Object, int);
 static void select_window_1 (Lisp_Object, bool);
 
+static struct window *set_window_fringes (struct window *, Lisp_Object,
+                                         Lisp_Object, Lisp_Object);
+static struct window *set_window_margins (struct window *, Lisp_Object,
+                                         Lisp_Object);
+static struct window *set_window_scroll_bars (struct window *, Lisp_Object,
+                                             Lisp_Object, Lisp_Object);
+static void apply_window_adjustment (struct window *);
+
 /* This is the window in which the terminal's cursor should
    be left when nothing is being done with it.  This must
    always be a leaf window, and its buffer is selected by
@@ -154,16 +159,6 @@ wset_display_table (struct window *w, Lisp_Object val)
   w->display_table = val;
 }
 static void
-wset_left_fringe_width (struct window *w, Lisp_Object val)
-{
-  w->left_fringe_width = val;
-}
-static void
-wset_left_margin_cols (struct window *w, Lisp_Object val)
-{
-  w->left_margin_cols = val;
-}
-static void
 wset_new_normal (struct window *w, Lisp_Object val)
 {
   w->new_normal = val;
@@ -194,21 +189,6 @@ wset_pointm (struct window *w, Lisp_Object val)
   w->pointm = val;
 }
 static void
-wset_right_fringe_width (struct window *w, Lisp_Object val)
-{
-  w->right_fringe_width = val;
-}
-static void
-wset_right_margin_cols (struct window *w, Lisp_Object val)
-{
-  w->right_margin_cols = val;
-}
-static void
-wset_scroll_bar_width (struct window *w, Lisp_Object val)
-{
-  w->scroll_bar_width = val;
-}
-static void
 wset_start (struct window *w, Lisp_Object val)
 {
   w->start = val;
@@ -241,6 +221,17 @@ wset_combination (struct window *w, bool horflag, Lisp_Object val)
     w->horizontal = horflag;
 }
 
+/* Nonzero if leaf window W doesn't reflect the actual state
+   of displayed buffer due to its text or overlays change.  */
+
+bool
+window_outdated (struct window *w)
+{
+  struct buffer *b = XBUFFER (w->contents);
+  return (w->last_modified < BUF_MODIFF (b)
+         || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b));
+}
+
 struct window *
 decode_live_window (register Lisp_Object window)
 {
@@ -490,7 +481,6 @@ select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
   CHECK_LIVE_WINDOW (window);
 
   w = XWINDOW (window);
-  w->frozen_window_start_p = 0;
 
   /* Make the selected window's buffer current.  */
   Fset_buffer (w->contents);
@@ -559,15 +549,7 @@ select_window_1 (Lisp_Object window, bool inhibit_point_swap)
      than one window.  It also matters when
      redisplay_window has altered point after scrolling,
      because it makes the change only in the window.  */
-  {
-    register ptrdiff_t new_point = marker_position (XWINDOW (window)->pointm);
-    if (new_point < BEGV)
-      SET_PT (BEGV);
-    else if (new_point > ZV)
-      SET_PT (ZV);
-    else
-      SET_PT (new_point);
-  }
+  set_point_from_marker (XWINDOW (window)->pointm);
 }
 
 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
@@ -1355,7 +1337,7 @@ struct check_window_data
 static int
 check_window_containing (struct window *w, void *user_data)
 {
-  struct check_window_data *cw = (struct check_window_data *) user_data;
+  struct check_window_data *cw = user_data;
   enum window_part found;
   int continue_p = 1;
 
@@ -1508,8 +1490,7 @@ if it isn't already recorded.  */)
          || !w->window_end_valid
          || b->clip_changed
          || b->prevent_redisplay_optimizations_p
-         || w->last_modified < BUF_MODIFF (b)
-         || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b))
+         || window_outdated (w))
       && !noninteractive)
     {
       struct text_pos startp;
@@ -1550,7 +1531,7 @@ if it isn't already recorded.  */)
        set_buffer_internal (old_buffer);
     }
   else
-    XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
+    XSETINT (value, BUF_Z (b) - w->window_end_pos);
 
   return value;
 }
@@ -1606,9 +1587,8 @@ overriding motion of point in order to display at this exact start.  */)
   if (NILP (noforce))
     w->force_start = 1;
   w->update_mode_line = 1;
-  w->last_modified = 0;
-  w->last_overlay_modified = 0;
-  if (!EQ (window, selected_window))
+  if (w != XWINDOW (selected_window))
+    /* Enforce full redisplay.  FIXME: make it more selective.  */
     windows_or_buffers_changed++;
 
   return pos;
@@ -1722,8 +1702,7 @@ Return nil if window display is not up-to-date.  In that case, use
       || windows_or_buffers_changed
       || b->clip_changed
       || b->prevent_redisplay_optimizations_p
-      || w->last_modified < BUF_MODIFF (b)
-      || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b))
+      || window_outdated (w))
     return Qnil;
 
   if (NILP (line))
@@ -2040,16 +2019,15 @@ replace_window (Lisp_Object old, Lisp_Object new, int setflag)
       n->desired_matrix = n->current_matrix = 0;
       n->vscroll = 0;
       memset (&n->cursor, 0, sizeof (n->cursor));
-      memset (&n->last_cursor, 0, sizeof (n->last_cursor));
       memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
+      n->last_cursor_vpos = 0;
       n->phys_cursor_type = -1;
       n->phys_cursor_width = -1;
       n->must_be_updated_p = 0;
       n->pseudo_window_p = 0;
-      wset_window_end_vpos (n, make_number (0));
-      wset_window_end_pos (n, make_number (0));
+      n->window_end_vpos = 0;
+      n->window_end_pos = 0;
       n->window_end_valid = 0;
-      n->frozen_window_start_p = 0;
     }
 
   tem = o->next;
@@ -2158,7 +2136,7 @@ delete_deletable_window (Lisp_Object window)
 static int
 add_window_to_list (struct window *w, void *user_data)
 {
-  Lisp_Object *list = (Lisp_Object *) user_data;
+  Lisp_Object *list = user_data;
   Lisp_Object window;
   XSETWINDOW (window, w);
   *list = Fcons (window, *list);
@@ -2213,12 +2191,13 @@ window_list (void)
                a window means search the frame that window belongs to,
                a frame means consider windows on that frame, only.  */
 
-static int
-candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf, Lisp_Object all_frames)
+static bool
+candidate_window_p (Lisp_Object window, Lisp_Object owindow,
+                   Lisp_Object minibuf, Lisp_Object all_frames)
 {
   struct window *w = XWINDOW (window);
   struct frame *f = XFRAME (w->frame);
-  int candidate_p = 1;
+  bool candidate_p = 1;
 
   if (!BUFFERP (w->contents))
     candidate_p = 0;
@@ -2855,7 +2834,7 @@ window-start value is reasonable when this function is called.  */)
   block_input ();
   if (!FRAME_INITIAL_P (f))
     {
-        Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
+      Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
 
       /* We are going to free the glyph matrices of WINDOW, and with
         that we might lose any information about glyph rows that have
@@ -2865,11 +2844,7 @@ window-start value is reasonable when this function is called.  */)
         frame's up-to-date hook that mouse highlight was overwritten,
         so that it will arrange for redisplaying the highlight.  */
       if (EQ (hlinfo->mouse_face_window, window))
-       {
-         hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
-         hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
-         hlinfo->mouse_face_window = Qnil;
-       }
+       reset_mouse_highlight (hlinfo);
     }
   free_window_matrices (r);
 
@@ -3020,7 +2995,7 @@ replace_buffer_in_windows_safely (Lisp_Object buffer)
    minimum allowable size.  */
 
 void
-check_frame_size (FRAME_PTR frame, int *rows, int *cols)
+check_frame_size (struct frame *frame, int *rows, int *cols)
 {
   /* For height, we have to see:
      how many windows the frame has at minimum (one or two),
@@ -3064,15 +3039,12 @@ adjust_window_margins (struct window *w)
   if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
     {
       if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
-       {
-         wset_left_margin_cols (w, make_number (margin_cols / 2));
-         wset_right_margin_cols (w, make_number (margin_cols / 2));
-       }
+       w->left_margin_cols = w->right_margin_cols = margin_cols / 2;
       else
-       wset_right_margin_cols (w, make_number (margin_cols));
+       w->right_margin_cols = margin_cols;
     }
   else
-    wset_left_margin_cols (w, make_number (margin_cols));
+    w->left_margin_cols = margin_cols;
   return 1;
 }
 \f
@@ -3086,18 +3058,18 @@ run_funs (Lisp_Object funs)
       call0 (XCAR (funs));
 }
 
-static Lisp_Object
+static void
 select_window_norecord (Lisp_Object window)
 {
-  return WINDOW_LIVE_P (window)
-    ? Fselect_window (window, Qt) : selected_window;
+  if (WINDOW_LIVE_P (window))
+    Fselect_window (window, Qt);
 }
 
-static Lisp_Object
+static void
 select_frame_norecord (Lisp_Object frame)
 {
-  return FRAME_LIVE_P (XFRAME (frame))
-    ? Fselect_frame (frame, Qt) : selected_frame;
+  if (FRAME_LIVE_P (XFRAME (frame)))
+    Fselect_frame (frame, Qt);
 }
 
 void
@@ -3120,7 +3092,7 @@ run_window_configuration_change_hook (struct frame *f)
 
   if (SELECTED_FRAME () != f)
     {
-      record_unwind_protect (select_frame_norecord, Fselected_frame ());
+      record_unwind_protect (select_frame_norecord, selected_frame);
       select_frame_norecord (frame);
     }
 
@@ -3135,7 +3107,7 @@ run_window_configuration_change_hook (struct frame *f)
                                      buffer)))
          {
            ptrdiff_t inner_count = SPECPDL_INDEX ();
-           record_unwind_protect (select_window_norecord, Fselected_window ());
+           record_unwind_protect (select_window_norecord, selected_window);
            select_window_norecord (window);
            run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
                                           buffer));
@@ -3186,9 +3158,9 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
     bset_display_count (b, make_number (XINT (BVAR (b, display_count)) + 1));
   bset_display_time (b, Fcurrent_time ());
 
-  wset_window_end_pos (w, make_number (0));
-  wset_window_end_vpos (w, make_number (0));
-  memset (&w->last_cursor, 0, sizeof w->last_cursor);
+  w->window_end_pos = 0;
+  w->window_end_vpos = 0;
+  w->last_cursor_vpos = 0;
 
   if (!(keep_margins_p && samebuf))
     { /* If we're not actually changing the buffer, don't reset hscroll and
@@ -3207,8 +3179,6 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
                             buffer);
       w->start_at_line_beg = 0;
       w->force_start = 0;
-      w->last_modified = 0;
-      w->last_overlay_modified = 0;
     }
   /* Maybe we could move this into the `if' but it's not obviously safe and
      I doubt it's worth the trouble.  */
@@ -3228,28 +3198,14 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
   if (!keep_margins_p)
     {
       /* Set left and right marginal area width etc. from buffer.  */
-
-      /* This may call adjust_window_margins three times, so
-        temporarily disable window margins.  */
-      Lisp_Object save_left = w->left_margin_cols;
-      Lisp_Object save_right = w->right_margin_cols;
-
-      wset_left_margin_cols (w, Qnil);
-      wset_right_margin_cols (w, Qnil);
-
-      Fset_window_fringes (window,
-                          BVAR (b, left_fringe_width), BVAR (b, right_fringe_width),
-                          BVAR (b, fringes_outside_margins));
-
-      Fset_window_scroll_bars (window,
-                              BVAR (b, scroll_bar_width),
-                              BVAR (b, vertical_scroll_bar_type), Qnil);
-
-      wset_left_margin_cols (w, save_left);
-      wset_right_margin_cols (w, save_right);
-
-      Fset_window_margins (window,
-                          BVAR (b, left_margin_cols), BVAR (b, right_margin_cols));
+      set_window_fringes (w, BVAR (b, left_fringe_width),
+                         BVAR (b, right_fringe_width),
+                         BVAR (b, fringes_outside_margins));
+      set_window_scroll_bars (w, BVAR (b, scroll_bar_width),
+                             BVAR (b, vertical_scroll_bar_type), Qnil);
+      set_window_margins (w, BVAR (b, left_margin_cols),
+                         BVAR (b, right_margin_cols));
+      apply_window_adjustment (w);
     }
 
   if (run_hooks_p)
@@ -3385,10 +3341,8 @@ temp_output_buffer_show (register Lisp_Object buf)
 
   if (!NILP (Vtemp_buffer_show_function))
     call1 (Vtemp_buffer_show_function, buf);
-  else
+  else if (WINDOW_LIVE_P (window = display_buffer (buf, Qnil, Qnil)))
     {
-      window = display_buffer (buf, Qnil, Qnil);
-
       if (!EQ (XWINDOW (window)->frame, selected_frame))
        Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
       Vminibuf_scroll_window = window;
@@ -3410,7 +3364,7 @@ temp_output_buffer_show (register Lisp_Object buf)
            Note: Both Fselect_window and select_window_norecord may
            set-buffer to the buffer displayed in the window,
            so we need to save the current buffer.  --stef  */
-        record_unwind_protect (Fset_buffer, prev_buffer);
+        record_unwind_protect (restore_buffer, prev_buffer);
         record_unwind_protect (select_window_norecord, prev_window);
         Fselect_window (window, Qt);
         Fset_buffer (w->contents);
@@ -3469,8 +3423,6 @@ make_window (void)
   wset_start (w, Fmake_marker ());
   wset_pointm (w, Fmake_marker ());
   wset_vertical_scroll_bar_type (w, Qt);
-  wset_window_end_pos (w, make_number (0));
-  wset_window_end_vpos (w, make_number (0));
   /* These Lisp fields are marked specially so they're not set to nil by
      allocate_window.  */
   wset_prev_buffers (w, Qnil);
@@ -3479,8 +3431,10 @@ make_window (void)
   /* Initialize non-Lisp data.  Note that allocate_window zeroes out all
      non-Lisp data, so do it only for slots which should not be zero.  */
   w->nrows_scale_factor = w->ncols_scale_factor = 1;
+  w->left_fringe_width = w->right_fringe_width = -1;
   w->phys_cursor_type = -1;
   w->phys_cursor_width = -1;
+  w->scroll_bar_width = -1;
   w->column_number_displayed = -1;
 
   /* Reset window_list.  */
@@ -3669,10 +3623,6 @@ window_resize_apply (struct window *w, bool horflag)
          c = NILP (c->next) ? 0 : XWINDOW (c->next);
        }
     }
-
-  /* Clear out some redisplay caches.  */
-  w->last_modified = 0;
-  w->last_overlay_modified = 0;
 }
 
 
@@ -3947,15 +3897,15 @@ set correctly.  See the code of `split-window' for how this is done.  */)
     }
 
   n->window_end_valid = 0;
-  memset (&n->last_cursor, 0, sizeof n->last_cursor);
+  n->last_cursor_vpos = 0;
 
   /* Get special geometry settings from reference window.  */
-  wset_left_margin_cols (n, r->left_margin_cols);
-  wset_right_margin_cols (n, r->right_margin_cols);
-  wset_left_fringe_width (n, r->left_fringe_width);
-  wset_right_fringe_width (n, r->right_fringe_width);
+  n->left_margin_cols = r->left_margin_cols;
+  n->right_margin_cols = r->right_margin_cols;
+  n->left_fringe_width = r->left_fringe_width;
+  n->right_fringe_width = r->right_fringe_width;
   n->fringes_outside_margins = r->fringes_outside_margins;
-  wset_scroll_bar_width (n, r->scroll_bar_width);
+  n->scroll_bar_width = r->scroll_bar_width;
   wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
 
   /* Directly assign orthogonal coordinates and sizes.  */
@@ -4191,9 +4141,7 @@ grow_mini_window (struct window *w, int delta)
       /* Grow the mini-window.  */
       w->top_line = r->top_line + r->total_lines;
       w->total_lines -= XINT (value);
-      w->last_modified = 0;
-      w->last_overlay_modified = 0;
-
+      /* Enforce full redisplay.  FIXME: make it more selective.  */
       windows_or_buffers_changed++;
       adjust_glyphs (f);
       unblock_input ();
@@ -4227,10 +4175,7 @@ shrink_mini_window (struct window *w)
          /* Shrink the mini-window.  */
          w->top_line = r->top_line + r->total_lines;
          w->total_lines = 1;
-
-         w->last_modified = 0;
-         w->last_overlay_modified = 0;
-
+         /* Enforce full redisplay.  FIXME: make it more selective.  */
          windows_or_buffers_changed++;
          adjust_glyphs (f);
          unblock_input ();
@@ -4337,7 +4282,7 @@ window_internal_height (struct window *w)
    respectively.  */
 
 static void
-window_scroll (Lisp_Object window, EMACS_INT n, int whole, int noerror)
+window_scroll (Lisp_Object window, EMACS_INT n, bool whole, int noerror)
 {
   immediate_quit = 1;
   n = clip_to_bounds (INT_MIN, n, INT_MAX);
@@ -4358,7 +4303,7 @@ window_scroll (Lisp_Object window, EMACS_INT n, int whole, int noerror)
    descriptions.  */
 
 static void
-window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
+window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
 {
   struct it it;
   struct window *w = XWINDOW (window);
@@ -4368,6 +4313,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
   int vscrolled = 0;
   int x, y, rtop, rbot, rowh, vpos;
   void *itdata = NULL;
+  int window_total_lines;
+  int frame_line_height = default_line_pixel_height (w);
 
   SET_TEXT_POS_FROM_MARKER (start, w->start);
   /* Scrolling a minibuffer window via scroll bar when the echo area
@@ -4411,7 +4358,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
       if (rtop || rbot)                /* partially visible */
        {
          int px;
-         int dy = WINDOW_FRAME_LINE_HEIGHT (w);
+         int dy = frame_line_height;
          if (whole)
            dy = max ((window_box_height (w)
                       - next_screen_context_lines * dy),
@@ -4454,8 +4401,6 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
                                         w->contents);
                  w->start_at_line_beg = 1;
                  w->update_mode_line = 1;
-                 w->last_modified = 0;
-                 w->last_overlay_modified = 0;
                  /* Set force_start so that redisplay_window will run the
                     window-scroll-functions.  */
                  w->force_start = 1;
@@ -4497,7 +4442,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
   if (whole)
     {
       ptrdiff_t start_pos = IT_CHARPOS (it);
-      int dy = WINDOW_FRAME_LINE_HEIGHT (w);
+      int dy = frame_line_height;
       dy = max ((window_box_height (w)
                 - next_screen_context_lines * dy),
                dy) * n;
@@ -4600,8 +4545,6 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
       bytepos = marker_byte_position (w->start);
       w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
       w->update_mode_line = 1;
-      w->last_modified = 0;
-      w->last_overlay_modified = 0;
       /* Set force_start so that redisplay_window will run the
         window-scroll-functions.  */
       w->force_start = 1;
@@ -4614,10 +4557,12 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
   /* Move PT out of scroll margins.
      This code wants current_y to be zero at the window start position
      even if there is a header line.  */
+  window_total_lines
+    = w->total_lines * WINDOW_FRAME_LINE_HEIGHT (w) / frame_line_height;
   this_scroll_margin = max (0, scroll_margin);
   this_scroll_margin
-    = min (this_scroll_margin, w->total_lines / 4);
-  this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
+    = min (this_scroll_margin, window_total_lines / 4);
+  this_scroll_margin *= frame_line_height;
 
   if (n > 0)
     {
@@ -4722,7 +4667,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
    See the comment of window_scroll for parameter descriptions.  */
 
 static void
-window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
+window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
 {
   register struct window *w = XWINDOW (window);
   /* Fvertical_motion enters redisplay, which can trigger
@@ -4734,7 +4679,7 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
   register ptrdiff_t pos, pos_byte;
   register int ht = window_internal_height (w);
   register Lisp_Object tem;
-  int lose;
+  bool lose;
   Lisp_Object bolp;
   ptrdiff_t startpos = marker_position (w->start);
   ptrdiff_t startbyte = marker_byte_position (w->start);
@@ -4798,8 +4743,6 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
       set_marker_restricted_both (w->start, w->contents, pos, pos_byte);
       w->start_at_line_beg = !NILP (bolp);
       w->update_mode_line = 1;
-      w->last_modified = 0;
-      w->last_overlay_modified = 0;
       /* Set force_start so that redisplay_window will run
         the window-scroll-functions.  */
       w->force_start = 1;
@@ -5168,7 +5111,7 @@ and redisplay normally--don't erase and redraw the frame.  */)
   struct window *w = XWINDOW (selected_window);
   struct buffer *buf = XBUFFER (w->contents);
   struct buffer *obuf = current_buffer;
-  int center_p = 0;
+  bool center_p = 0;
   ptrdiff_t charpos, bytepos;
   EMACS_INT iarg IF_LINT (= 0);
   int this_scroll_margin;
@@ -5451,7 +5394,7 @@ struct save_window_data
     Lisp_Object saved_windows;
 
     /* All fields above are traced by the GC.
-       From `fame-cols' down, the fields are ignored by the GC.  */
+       From `frame-cols' down, the fields are ignored by the GC.  */
 
     int frame_cols, frame_lines, frame_menu_bar_lines;
     int frame_tool_bar_lines;
@@ -5513,7 +5456,7 @@ the return value is nil.  Otherwise the value is t.  */)
   struct Lisp_Vector *saved_windows;
   Lisp_Object new_current_buffer;
   Lisp_Object frame;
-  FRAME_PTR f;
+  struct frame *f;
   ptrdiff_t old_point = -1;
 
   CHECK_WINDOW_CONFIGURATION (configuration);
@@ -5700,12 +5643,12 @@ the return value is nil.  Otherwise the value is t.  */)
          w->hscroll = XFASTINT (p->hscroll);
          w->min_hscroll = XFASTINT (p->min_hscroll);
          wset_display_table (w, p->display_table);
-         wset_left_margin_cols (w, p->left_margin_cols);
-         wset_right_margin_cols (w, p->right_margin_cols);
-         wset_left_fringe_width (w, p->left_fringe_width);
-         wset_right_fringe_width (w, p->right_fringe_width);
+         w->left_margin_cols = XINT (p->left_margin_cols);
+         w->right_margin_cols = XINT (p->right_margin_cols);
+         w->left_fringe_width = XINT (p->left_fringe_width);
+         w->right_fringe_width = XINT (p->right_fringe_width);
          w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
-         wset_scroll_bar_width (w, p->scroll_bar_width);
+         w->scroll_bar_width = XINT (p->scroll_bar_width);
          wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
          wset_dedicated (w, p->dedicated);
          wset_combination_limit (w, p->combination_limit);
@@ -5731,9 +5674,6 @@ the return value is nil.  Otherwise the value is t.  */)
                }
            }
 
-         w->last_modified = 0;
-         w->last_overlay_modified = 0;
-
          if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
            /* If saved buffer is alive, install it.  */
            {
@@ -5869,6 +5809,12 @@ the return value is nil.  Otherwise the value is t.  */)
   return (FRAME_LIVE_P (f) ? Qt : Qnil);
 }
 
+void
+restore_window_configuration (Lisp_Object configuration)
+{
+  Fset_window_configuration (configuration);
+}
+
 
 /* If WINDOW is an internal window, recursively delete all child windows
    reachable via the next and contents slots of WINDOW.  Otherwise setup
@@ -5998,12 +5944,12 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
       XSETFASTINT (p->hscroll, w->hscroll);
       XSETFASTINT (p->min_hscroll, w->min_hscroll);
       p->display_table = w->display_table;
-      p->left_margin_cols = w->left_margin_cols;
-      p->right_margin_cols = w->right_margin_cols;
-      p->left_fringe_width = w->left_fringe_width;
-      p->right_fringe_width = w->right_fringe_width;
+      p->left_margin_cols = make_number (w->left_margin_cols);
+      p->right_margin_cols = make_number (w->right_margin_cols);
+      p->left_fringe_width = make_number (w->left_fringe_width);
+      p->right_fringe_width = make_number (w->right_fringe_width);
       p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
-      p->scroll_bar_width = w->scroll_bar_width;
+      p->scroll_bar_width = make_number (w->scroll_bar_width);
       p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
       p->dedicated = w->dedicated;
       p->combination_limit = w->combination_limit;
@@ -6144,11 +6090,46 @@ saved by this function.  */)
   XSETWINDOW_CONFIGURATION (tem, data);
   return (tem);
 }
+
+/* Called after W's margins, fringes or scroll bars was adjusted.  */
+
+static void
+apply_window_adjustment (struct window *w)
+{
+  eassert (w);
+  adjust_window_margins (w);
+  clear_glyph_matrix (w->current_matrix);
+  w->window_end_valid = 0;
+  windows_or_buffers_changed++;
+  adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
+}
+
 \f
 /***********************************************************************
                            Marginal Areas
  ***********************************************************************/
 
+static struct window *
+set_window_margins (struct window *w, Lisp_Object left_width,
+                   Lisp_Object right_width)
+{
+  int left, right;
+
+  /* FIXME: what about margins that are too wide?  */
+  left = (NILP (left_width) ? 0
+         : (CHECK_NATNUM (left_width), XINT (left_width)));
+  right = (NILP (right_width) ? 0
+          : (CHECK_NATNUM (right_width), XINT (right_width)));
+
+  if (w->left_margin_cols != left || w->right_margin_cols != right)
+    {
+      w->left_margin_cols = left;
+      w->right_margin_cols = right;
+      return w;
+    }
+  return NULL;
+}
+
 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
        2, 3, 0,
        doc: /* Set width of marginal areas of window WINDOW.
@@ -6157,41 +6138,14 @@ WINDOW must be a live window and defaults to the selected one.
 Second arg LEFT-WIDTH specifies the number of character cells to
 reserve for the left marginal area.  Optional third arg RIGHT-WIDTH
 does the same for the right marginal area.  A nil width parameter
-means no margin.  */)
+means no margin.
+
+Return t if any margin was actually changed and nil otherwise.  */)
   (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
 {
-  struct window *w = decode_live_window (window);
-
-  /* Translate negative or zero widths to nil.
-     Margins that are too wide have to be checked elsewhere.  */
-
-  if (!NILP (left_width))
-    {
-      CHECK_NUMBER (left_width);
-      if (XINT (left_width) <= 0)
-       left_width = Qnil;
-    }
-
-  if (!NILP (right_width))
-    {
-      CHECK_NUMBER (right_width);
-      if (XINT (right_width) <= 0)
-       right_width = Qnil;
-    }
-
-  if (!EQ (w->left_margin_cols, left_width)
-      || !EQ (w->right_margin_cols, right_width))
-    {
-      wset_left_margin_cols (w, left_width);
-      wset_right_margin_cols (w, right_width);
-
-      adjust_window_margins (w);
-
-      ++windows_or_buffers_changed;
-      adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
-    }
-
-  return Qnil;
+  struct window *w = set_window_margins (decode_live_window (window),
+                                        left_width, right_width);
+  return w ? (apply_window_adjustment (w), Qt) : Qnil;
 }
 
 
@@ -6206,7 +6160,8 @@ as nil.  */)
   (Lisp_Object window)
 {
   struct window *w = decode_live_window (window);
-  return Fcons (w->left_margin_cols, w->right_margin_cols);
+  return Fcons (w->left_margin_cols ? make_number (w->left_margin_cols) : Qnil,
+               w->right_margin_cols ? make_number (w->right_margin_cols) : Qnil);
 }
 
 
@@ -6215,6 +6170,31 @@ as nil.  */)
                            Fringes
  ***********************************************************************/
 
+static struct window *
+set_window_fringes (struct window *w, Lisp_Object left_width,
+                   Lisp_Object right_width, Lisp_Object outside_margins)
+{
+  int left, right, outside = !NILP (outside_margins);
+
+  left = (NILP (left_width) ? -1
+         : (CHECK_NATNUM (left_width), XINT (left_width)));
+  right = (NILP (right_width) ? -1
+          : (CHECK_NATNUM (right_width), XINT (right_width)));
+
+  /* Do nothing on a tty or if nothing to actually change.  */
+  if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
+      && (w->left_fringe_width != left
+         || w->right_fringe_width != right
+         || w->fringes_outside_margins != outside))
+    {
+      w->left_fringe_width = left;
+      w->right_fringe_width = right;
+      w->fringes_outside_margins = outside;
+      return w;
+    }
+  return NULL;
+}
+
 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
        2, 4, 0,
        doc: /* Set the fringe widths of window WINDOW.
@@ -6227,37 +6207,16 @@ frame's default fringe width.  Default fringe widths can be set with
 the command `set-fringe-style'.
 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
 outside of the display margins.  By default, fringes are drawn between
-display marginal areas and the text area.  */)
-  (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width, Lisp_Object outside_margins)
-{
-  struct window *w = decode_live_window (window);
-  int outside = !NILP (outside_margins);
-
-  if (!NILP (left_width))
-    CHECK_NATNUM (left_width);
-  if (!NILP (right_width))
-    CHECK_NATNUM (right_width);
-
-  /* Do nothing on a tty.  */
-  if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
-      && (!EQ (w->left_fringe_width, left_width)
-         || !EQ (w->right_fringe_width, right_width)
-         || w->fringes_outside_margins != outside))
-    {
-      wset_left_fringe_width (w, left_width);
-      wset_right_fringe_width (w, right_width);
-      w->fringes_outside_margins = outside;
-
-      adjust_window_margins (w);
-
-      clear_glyph_matrix (w->current_matrix);
-      w->window_end_valid = 0;
+display marginal areas and the text area.
 
-      ++windows_or_buffers_changed;
-      adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
-    }
-
-  return Qnil;
+Return t if any fringe was actually changed and nil otherwise.  */)
+  (Lisp_Object window, Lisp_Object left_width,
+   Lisp_Object right_width, Lisp_Object outside_margins)
+{
+  struct window *w
+    = set_window_fringes (decode_live_window (window),
+                         left_width, right_width, outside_margins);
+  return w ? (apply_window_adjustment (w), Qt) : Qnil;
 }
 
 
@@ -6282,29 +6241,14 @@ Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS).  */)
                            Scroll bars
  ***********************************************************************/
 
-DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
-       Sset_window_scroll_bars, 2, 4, 0,
-       doc: /* Set width and type of scroll bars of window WINDOW.
-WINDOW must be a live window and defaults to the selected one.
-
-Second parameter WIDTH specifies the pixel width for the scroll bar;
-this is automatically adjusted to a multiple of the frame column width.
-Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
-bar: left, right, or nil.
-If WIDTH is nil, use the frame's scroll-bar width.
-If VERTICAL-TYPE is t, use the frame's scroll-bar type.
-Fourth parameter HORIZONTAL-TYPE is currently unused.  */)
-  (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type, Lisp_Object horizontal_type)
+static struct window *
+set_window_scroll_bars (struct window *w, Lisp_Object width,
+                       Lisp_Object vertical_type, Lisp_Object horizontal_type)
 {
-  struct window *w = decode_live_window (window);
-
-  if (!NILP (width))
-    {
-      CHECK_RANGED_INTEGER (width, 0, INT_MAX);
+  int iwidth = (NILP (width) ? -1 : (CHECK_NATNUM (width), XINT (width)));
 
-      if (XINT (width) == 0)
-       vertical_type = Qnil;
-    }
+  if (iwidth == 0)
+    vertical_type = Qnil;
 
   if (!(NILP (vertical_type)
        || EQ (vertical_type, Qleft)
@@ -6312,22 +6256,37 @@ Fourth parameter HORIZONTAL-TYPE is currently unused.  */)
        || EQ (vertical_type, Qt)))
     error ("Invalid type of vertical scroll bar");
 
-  if (!EQ (w->scroll_bar_width, width)
+  if (w->scroll_bar_width != iwidth
       || !EQ (w->vertical_scroll_bar_type, vertical_type))
     {
-      wset_scroll_bar_width (w, width);
+      w->scroll_bar_width = iwidth;
       wset_vertical_scroll_bar_type (w, vertical_type);
+      return w;
+    }
+  return NULL;
+}
 
-      adjust_window_margins (w);
-
-      clear_glyph_matrix (w->current_matrix);
-      w->window_end_valid = 0;
+DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
+       Sset_window_scroll_bars, 2, 4, 0,
+       doc: /* Set width and type of scroll bars of window WINDOW.
+WINDOW must be a live window and defaults to the selected one.
 
-      ++windows_or_buffers_changed;
-      adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
-    }
+Second parameter WIDTH specifies the pixel width for the scroll bar;
+this is automatically adjusted to a multiple of the frame column width.
+Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
+bar: left, right, or nil.
+If WIDTH is nil, use the frame's scroll-bar width.
+If VERTICAL-TYPE is t, use the frame's scroll-bar type.
+Fourth parameter HORIZONTAL-TYPE is currently unused.
 
-  return Qnil;
+Return t if scroll bars was actually changed and nil otherwise.  */)
+  (Lisp_Object window, Lisp_Object width,
+   Lisp_Object vertical_type, Lisp_Object horizontal_type)
+{
+  struct window *w
+    = set_window_scroll_bars (decode_live_window (window),
+                             width, vertical_type, horizontal_type);
+  return w ? (apply_window_adjustment (w), Qt) : Qnil;
 }
 
 
@@ -6456,38 +6415,6 @@ foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *u
   return cont;
 }
 
-
-/* Freeze or unfreeze the window start of W unless it is a
-   mini-window or the selected window.  FREEZE_P non-null means freeze
-   the window start.  */
-
-static int
-freeze_window_start (struct window *w, void *freeze_p)
-{
-  if (MINI_WINDOW_P (w)
-      || (WINDOWP (selected_window) /* Can be nil in corner cases.  */
-         && (w == XWINDOW (selected_window)
-             || (MINI_WINDOW_P (XWINDOW (selected_window))
-                 && ! NILP (Vminibuf_scroll_window)
-                 && w == XWINDOW (Vminibuf_scroll_window)))))
-    freeze_p = NULL;
-
-  w->frozen_window_start_p = freeze_p != NULL;
-  return 1;
-}
-
-
-/* Freeze or unfreeze the window starts of all leaf windows on frame
-   F, except the selected window and a mini-window.  FREEZE_P non-zero
-   means freeze the window start.  */
-
-void
-freeze_window_starts (struct frame *f, bool freeze_p)
-{
-  foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
-}
-
-\f
 /***********************************************************************
                            Initialization
  ***********************************************************************/