]> code.delx.au - gnu-emacs/blobdiff - src/window.c
; Revert "Ensure undo-boundary after insert-file-contents."
[gnu-emacs] / src / window.c
index efb4c9b4f8cd24ba3e39e6a61e147e476e4b8fe9..733cf75d1321b87ced5a51767c496f7fdbcedbce 100644 (file)
@@ -1,14 +1,14 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
-   Copyright (C) 1985-1987, 1993-1998, 2000-2015 Free Software
+   Copyright (C) 1985-1987, 1993-1998, 2000-2016 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -35,6 +35,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "dispextern.h"
 #include "blockinput.h"
 #include "termhooks.h"         /* For FRAME_TERMINAL.  */
+#include "xwidget.h"
 #ifdef HAVE_WINDOW_SYSTEM
 #include TERM_HEADER
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -669,7 +670,7 @@ DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_windo
 WINDOW must be a valid window used in horizontal or vertical combination.
 If LIMIT is nil, child windows of WINDOW can be recombined with WINDOW's
 siblings.  LIMIT t means that child windows of WINDOW are never
-(re-)combined with WINDOW's siblings.  Other values are reserved for
+\(re-)combined with WINDOW's siblings.  Other values are reserved for
 future use.  */)
   (Lisp_Object window, Lisp_Object limit)
 {
@@ -1323,7 +1324,7 @@ DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
 WINDOW must be a live window and defaults to the selected one.
 COORDINATES is a cons of the form (X . Y), X and Y being distances
 measured in characters from the upper-left corner of the frame.
-(0 . 0) denotes the character in the upper left corner of the
+\(0 . 0) denotes the character in the upper left corner of the
 frame.
 If COORDINATES are in the text portion of WINDOW,
    the coordinates relative to the window are returned.
@@ -1540,23 +1541,13 @@ WINDOW must be a live window and defaults to the selected one.  */)
   return Fmarker_position (decode_live_window (window)->old_pointm);
 }
 
-DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 2, 0,
+DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
        doc: /* Return position at which display currently starts in WINDOW.
 WINDOW must be a live window and defaults to the selected one.
-This is updated by redisplay or by calling `set-window-start'.
-
-If GROUP is non-nil, and WINDOW is part of a group of windows collectively
-displaying a buffer (such as with Follow Mode), return the start position of
-the group rather than of the individual WINDOW.  This condition holds when
-`window-start-group-function' is set to a function, in which case
-`window-start' calls the function with the argument WINDOW, then returns its
-result, instead of doing its normal processing.  */)
-  (Lisp_Object window, Lisp_Object group)
+This is updated by redisplay or by calling `set-window-start'.  */)
+  (Lisp_Object window)
 {
-  return (!NILP (group)
-          && FUNCTIONP (Vwindow_start_group_function))
-    ? call1 (Vwindow_start_group_function, window)
-    : Fmarker_position (decode_live_window (window)->start);
+  return Fmarker_position (decode_live_window (window)->start);
 }
 
 /* This is text temporarily removed from the doc string below.
@@ -1570,7 +1561,7 @@ have been if redisplay had finished, do this:
       (vertical-motion (1- (window-height window)) window)
       (point))")  */
 
-DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 3, 0,
+DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
        doc: /* Return position at which display currently ends in WINDOW.
 WINDOW must be a live window and defaults to the selected one.
 This is updated by redisplay, when it runs to completion.
@@ -1579,77 +1570,65 @@ does not update this value.
 Return nil if there is no recorded value.  (This can happen if the
 last redisplay of WINDOW was preempted, and did not finish.)
 If UPDATE is non-nil, compute the up-to-date position
-if it isn't already recorded.
-
-If GROUP is non-nil, and WINDOW is part of a group of windows collectively
-displaying a buffer (such as with Follow Mode), return the end position of
-the group rather than of the individual WINDOW.  This condition holds when
-`window-end-group-function' is set to a function, in which case `window-end'
-calls the function with the two arguments WINDOW and UPDATE, then returns its
-result, instead of doing its normal processing.  */)
-  (Lisp_Object window, Lisp_Object update, Lisp_Object group)
-{
-  if (!NILP (group)
-      && FUNCTIONP (Vwindow_end_group_function))
-    return call2 (Vwindow_end_group_function, window, update);
-  {
-    Lisp_Object value;
-    struct window *w = decode_live_window (window);
-    Lisp_Object buf;
-    struct buffer *b;
-
-    buf = w->contents;
-    CHECK_BUFFER (buf);
-    b = XBUFFER (buf);
-
-    if (! NILP (update)
-        && (windows_or_buffers_changed
-            || !w->window_end_valid
-            || b->clip_changed
-            || b->prevent_redisplay_optimizations_p
-            || window_outdated (w))
-        /* Don't call display routines if we didn't yet create any real
-           frames, because the glyph matrices are not yet allocated in
-           that case.  This could happen in some code that runs in the
-           daemon during initialization (e.g., see bug#20565).  */
-        && !(noninteractive || FRAME_INITIAL_P (WINDOW_XFRAME (w))))
-      {
-        struct text_pos startp;
-        struct it it;
-        struct buffer *old_buffer = NULL;
-        void *itdata = NULL;
-
-        /* Cannot use Fvertical_motion because that function doesn't
-           cope with variable-height lines.  */
-        if (b != current_buffer)
-          {
-            old_buffer = current_buffer;
-            set_buffer_internal (b);
-          }
-
-        /* In case W->start is out of the range, use something
-           reasonable.  This situation occurred when loading a file with
-           `-l' containing a call to `rmail' with subsequent other
-           commands.  At the end, W->start happened to be BEG, while
-           rmail had already narrowed the buffer.  */
-        CLIP_TEXT_POS_FROM_MARKER (startp, w->start);
-
-        itdata = bidi_shelve_cache ();
-        start_display (&it, w, startp);
-        move_it_vertically (&it, window_box_height (w));
-        if (it.current_y < it.last_visible_y)
-          move_it_past_eol (&it);
-        value = make_number (IT_CHARPOS (it));
-        bidi_unshelve_cache (itdata, false);
-
-        if (old_buffer)
-          set_buffer_internal (old_buffer);
-      }
-    else
-      XSETINT (value, BUF_Z (b) - w->window_end_pos);
+if it isn't already recorded.  */)
+  (Lisp_Object window, Lisp_Object update)
+{
+  Lisp_Object value;
+  struct window *w = decode_live_window (window);
+  Lisp_Object buf;
+  struct buffer *b;
+
+  buf = w->contents;
+  CHECK_BUFFER (buf);
+  b = XBUFFER (buf);
+
+  if (! NILP (update)
+      && (windows_or_buffers_changed
+         || !w->window_end_valid
+         || b->clip_changed
+         || b->prevent_redisplay_optimizations_p
+         || window_outdated (w))
+      /* Don't call display routines if we didn't yet create any real
+        frames, because the glyph matrices are not yet allocated in
+        that case.  This could happen in some code that runs in the
+        daemon during initialization (e.g., see bug#20565).  */
+      && !(noninteractive || FRAME_INITIAL_P (WINDOW_XFRAME (w))))
+    {
+      struct text_pos startp;
+      struct it it;
+      struct buffer *old_buffer = NULL;
+      void *itdata = NULL;
+
+      /* Cannot use Fvertical_motion because that function doesn't
+        cope with variable-height lines.  */
+      if (b != current_buffer)
+       {
+         old_buffer = current_buffer;
+         set_buffer_internal (b);
+       }
 
-    return value;
-  }
+      /* In case W->start is out of the range, use something
+         reasonable.  This situation occurred when loading a file with
+         `-l' containing a call to `rmail' with subsequent other
+         commands.  At the end, W->start happened to be BEG, while
+         rmail had already narrowed the buffer.  */
+      CLIP_TEXT_POS_FROM_MARKER (startp, w->start);
+
+      itdata = bidi_shelve_cache ();
+      start_display (&it, w, startp);
+      move_it_vertically (&it, window_box_height (w));
+      if (it.current_y < it.last_visible_y)
+       move_it_past_eol (&it);
+      value = make_number (IT_CHARPOS (it));
+      bidi_unshelve_cache (itdata, false);
+
+      if (old_buffer)
+       set_buffer_internal (old_buffer);
+    }
+  else
+    XSETINT (value, BUF_Z (b) - w->window_end_pos);
+
+  return value;
 }
 
 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
@@ -1688,43 +1667,30 @@ Return POS.  */)
   return pos;
 }
 
-DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 4, 0,
+DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
        doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
 WINDOW must be a live window and defaults to the selected one.  Return
 POS.  Optional third arg NOFORCE non-nil inhibits next redisplay from
-overriding motion of point in order to display at this exact start.
-
-If GROUP is non-nil, and WINDOW is part of a group of windows collectively
-displaying a buffer (such as with Follow Mode), set the start position of
-the group rather than of the individual WINDOW.  This condition holds when
-`set-window-start-group-function' is set to a function, in which case
-`set-window-start' calls the function with the three arguments WINDOW, POS,
-and NOFORCE, then returns its result, instead of doing its normal
-processing.  */)
-  (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce, Lisp_Object group)
-{
-  if (!NILP (group)
-      && FUNCTIONP (Vset_window_start_group_function))
-    return call3 (Vset_window_start_group_function, window, pos, noforce);
-  {
-    register struct window *w = decode_live_window (window);
+overriding motion of point in order to display at this exact start.  */)
+  (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
+{
+  register struct window *w = decode_live_window (window);
 
-    set_marker_restricted (w->start, pos, w->contents);
-    /* This is not right, but much easier than doing what is right.  */
-    w->start_at_line_beg = false;
-    if (NILP (noforce))
-      w->force_start = true;
-    wset_update_mode_line (w);
-    /* Bug#15957.  */
-    w->window_end_valid = false;
-    wset_redisplay (w);
+  set_marker_restricted (w->start, pos, w->contents);
+  /* This is not right, but much easier than doing what is right.  */
+  w->start_at_line_beg = false;
+  if (NILP (noforce))
+    w->force_start = true;
+  wset_update_mode_line (w);
+  /* Bug#15957.  */
+  w->window_end_valid = false;
+  wset_redisplay (w);
 
-    return pos;
-  }
+  return pos;
 }
 
 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
-       Spos_visible_in_window_p, 0, 4, 0,
+       Spos_visible_in_window_p, 0, 3, 0,
        doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
 WINDOW must be a live window and defaults to the selected one.
 
@@ -1744,21 +1710,9 @@ of the window.  The remaining elements are omitted if the character after
 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
 off-window at the top and bottom of the screen line ("row") containing
 POS, ROWH is the visible height of that row, and VPOS is the row number
-(zero-based).
-
-If GROUP is non-nil, and WINDOW is part of a group of windows collectively
-displaying a buffer (such as with Follow Mode), test whether POS is visible
-in the group of windows rather than in the individual WINDOW.  This
-condition holds when `pos-visible-in-window-p-function' is set to a
-function, in which case `pos-visible-in-window-p' calls the function with
-the three arguments POS, WINDOW, and PARTIALLY, then returns its result,
-instead of doing its normal processing.  */)
-  (Lisp_Object pos, Lisp_Object window, Lisp_Object partially, Lisp_Object group)
-{
-  if (!NILP (group)
-      && FUNCTIONP (Vpos_visible_in_window_p_group_function))
-    return call3 (Vpos_visible_in_window_p_group_function, pos, window, partially);
-  {
+\(zero-based).  */)
+  (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
+{
   struct window *w;
   EMACS_INT posint;
   struct buffer *buf;
@@ -1807,7 +1761,6 @@ instead of doing its normal processing.  */)
     }
 
   return in_window;
-  }
 }
 
 DEFUN ("window-line-height", Fwindow_line_height,
@@ -4018,9 +3971,11 @@ values.  */)
 }
 
 
-/* Resize frame F's windows when number of lines of F is set to SIZE.
-   HORFLAG means resize windows when number of columns of F is set to
-   SIZE.  PIXELWISE means to interpret SIZE as pixels.  */
+/* Resize frame F's windows when F's width or height is set to SIZE.
+   If HORFLAG is zero, F's width was set to SIZE, otherwise its height
+   was set.  SIZE is interpreted in F's canonical character units
+   (a.k.a. "columns" or "lines"), unless PIXELWISE is non-zero, which
+   means to interpret SIZE in pixel units.  */
 void
 resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
 {
@@ -4112,37 +4067,6 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
            {
              window_resize_apply (r, horflag);
              window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
-#if false /* Let's try without safe sizes and/or killing other windows.  */
-           }
-         else
-           {
-             /* Finally, try with "safe" minimum sizes.  */
-             resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe,
-                                 pixelwise ? Qt : Qnil);
-             if (window_resize_check (r, horflag)
-                 && new_pixel_size == XINT (r->new_pixel))
-               {
-                 window_resize_apply (r, horflag);
-                 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
-               }
-             else
-               {
-                 /* We lost.  Delete all windows but the frame's
-                    selected one.  */
-                 root = f->selected_window;
-                 Fdelete_other_windows_internal (root, Qnil);
-                 if (horflag)
-                   {
-                     XWINDOW (root)->total_cols = new_size;
-                     XWINDOW (root)->pixel_width = new_pixel_size;
-                   }
-                 else
-                   {
-                     XWINDOW (root)->total_lines = new_size;
-                     XWINDOW (root)->pixel_height = new_pixel_size;
-                   }
-               }
-#endif /* false */
            }
        }
     }
@@ -4152,7 +4076,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
       m = XWINDOW (mini);
       if (horflag)
        {
-         m->total_cols = size;
+         m->total_cols = new_size;
          m->pixel_width = new_pixel_size;
        }
       else
@@ -4165,6 +4089,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
        }
     }
 
+  FRAME_WINDOW_SIZES_CHANGED (f) = true;
   fset_redisplay (f);
 }
 
@@ -4446,6 +4371,7 @@ Signal an error when WINDOW is the only window on its frame.  */)
 
       /* Block input.  */
       block_input ();
+      xwidget_view_delete_all_in_window (w);
       window_resize_apply (p, horflag);
       /* If this window is referred to by the dpyinfo's mouse
         highlight, invalidate that slot to be safe (Bug#9904).  */
@@ -4603,6 +4529,7 @@ grow_mini_window (struct window *w, int delta, bool pixelwise)
          /* Enforce full redisplay of the frame.  */
          /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
          fset_redisplay (f);
+         FRAME_WINDOW_SIZES_CHANGED (f) = true;
          adjust_frame_glyphs (f);
          unblock_input ();
        }
@@ -4642,6 +4569,7 @@ shrink_mini_window (struct window *w, bool pixelwise)
          /* Enforce full redisplay of the frame.  */
          /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
          fset_redisplay (f);
+         FRAME_WINDOW_SIZES_CHANGED (f) = true;
          adjust_frame_glyphs (f);
          unblock_input ();
        }
@@ -5055,27 +4983,34 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
 
   if (n > 0)
     {
+      int last_y = it.last_visible_y - this_scroll_margin - 1;
+
       /* We moved the window start towards ZV, so PT may be now
         in the scroll margin at the top.  */
       move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
-      if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
+      if (IT_CHARPOS (it) == PT
+         && it.current_y >= this_scroll_margin
+         && it.current_y <= last_y - WINDOW_HEADER_LINE_HEIGHT (w)
           && (NILP (Vscroll_preserve_screen_position)
              || EQ (Vscroll_preserve_screen_position, Qt)))
        /* We found PT at a legitimate height.  Leave it alone.  */
        ;
-      else if (window_scroll_pixel_based_preserve_y >= 0)
-       {
-         /* If we have a header line, take account of it.
-            This is necessary because we set it.current_y to 0, above.  */
-         move_it_to (&it, -1,
-                     window_scroll_pixel_based_preserve_x,
-                     (window_scroll_pixel_based_preserve_y
-                      - WINDOW_WANTS_HEADER_LINE_P (w)),
-                     -1, MOVE_TO_Y | MOVE_TO_X);
-         SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
-       }
       else
        {
+         if (window_scroll_pixel_based_preserve_y >= 0)
+           {
+             /* Don't enter the scroll margin at the end of the window.  */
+             int goal_y = min (last_y, window_scroll_pixel_based_preserve_y);
+
+             /* If we have a header line, take account of it.  This
+                is necessary because we set it.current_y to 0, above.  */
+             move_it_to (&it, -1,
+                         window_scroll_pixel_based_preserve_x,
+                         goal_y - WINDOW_HEADER_LINE_HEIGHT (w),
+                         -1, MOVE_TO_Y | MOVE_TO_X);
+           }
+
+         /* Get out of the scroll margin at the top of the window.  */
          while (it.current_y < this_scroll_margin)
            {
              int prev = it.current_y;
@@ -5099,7 +5034,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
       /* We moved the window start towards BEGV, so PT may be now
         in the scroll margin at the bottom.  */
       move_it_to (&it, PT, -1,
-                 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
+                 (it.last_visible_y - WINDOW_HEADER_LINE_HEIGHT (w)
                   - this_scroll_margin - 1),
                  -1,
                  MOVE_TO_POS | MOVE_TO_Y);
@@ -5150,14 +5085,20 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
        ;
       else if (window_scroll_pixel_based_preserve_y >= 0)
        {
+         int goal_y = min (it.last_visible_y - this_scroll_margin - 1,
+                           window_scroll_pixel_based_preserve_y);
+
+         /* Don't let the preserved screen Y coordinate put us inside
+            any of the two margins.  */
+         if (goal_y < this_scroll_margin)
+           goal_y = this_scroll_margin;
          SET_TEXT_POS_FROM_MARKER (start, w->start);
          start_display (&it, w, start);
          /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
             here because we called start_display again and did not
             alter it.current_y this time.  */
          move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
-                     window_scroll_pixel_based_preserve_y, -1,
-                     MOVE_TO_Y | MOVE_TO_X);
+                     goal_y, -1, MOVE_TO_Y | MOVE_TO_X);
          SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
        }
       else
@@ -5233,7 +5174,7 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
     }
 
   XSETFASTINT (tem, PT);
-  tem = Fpos_visible_in_window_p (tem, window, Qnil, Qnil);
+  tem = Fpos_visible_in_window_p (tem, window, Qnil);
 
   if (NILP (tem))
     {
@@ -5273,6 +5214,7 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
       w->force_start = true;
 
       if (!NILP (Vscroll_preserve_screen_position)
+         && this_scroll_margin == 0
          && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
        {
          SET_PT_BOTH (pos, pos_byte);
@@ -5298,8 +5240,16 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
                         marker_byte_position (opoint_marker));
          else if (!NILP (Vscroll_preserve_screen_position))
            {
+             int nlines = window_scroll_preserve_vpos;
+
              SET_PT_BOTH (pos, pos_byte);
-             Fvertical_motion (original_pos, window, Qnil);
+             if (window_scroll_preserve_vpos < this_scroll_margin)
+               nlines = this_scroll_margin;
+             else if (window_scroll_preserve_vpos
+                      >= w->total_lines - this_scroll_margin)
+               nlines = w->total_lines - this_scroll_margin - 1;
+             Fvertical_motion (Fcons (make_number (window_scroll_preserve_hpos),
+                                      make_number (nlines)), window, Qnil);
            }
          else
            SET_PT (top_margin);
@@ -5325,8 +5275,16 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
            {
              if (!NILP (Vscroll_preserve_screen_position))
                {
+                 int nlines = window_scroll_preserve_vpos;
+
                  SET_PT_BOTH (pos, pos_byte);
-                 Fvertical_motion (original_pos, window, Qnil);
+                 if (window_scroll_preserve_vpos < this_scroll_margin)
+                   nlines = this_scroll_margin;
+                 else if (window_scroll_preserve_vpos
+                          >= ht - this_scroll_margin)
+                   nlines = ht - this_scroll_margin - 1;
+                 Fvertical_motion (Fcons (make_number (window_scroll_preserve_hpos),
+                                          make_number (nlines)), window, Qnil);
                }
              else
                Fvertical_motion (make_number (-1), window, Qnil);
@@ -5622,7 +5580,7 @@ displayed_window_lines (struct window *w)
 }
 
 
-DEFUN ("recenter", Frecenter, Srecenter, 0, 2, "P\ni",
+DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
        doc: /* Center point in selected window and maybe redisplay frame.
 With a numeric prefix argument ARG, recenter putting point on screen line ARG
 relative to the selected window.  If ARG is negative, it counts up from the
@@ -5636,221 +5594,208 @@ height needed); if `recenter-redisplay' has the special value `tty',
 then only tty frames are redrawn.
 
 Just C-u as prefix means put point in the center of the window
-and redisplay normally--don't erase and redraw the frame.
-
-When `recenter' is called from a program, GROUP is non-nil, and WINDOW is
-part of a group of windows collectively displaying a buffer (such as with
-Follow Mode), perform `recenter''s actions on the group rather than on the
-individual WINDOW.  This condition holds when `recenter-group-function' is
-set to a function, in which case `recenter' calls the function with the
-argument ARG, then returns its value, instead of doing its normal
-processing.  */)
-  (register Lisp_Object arg, Lisp_Object group)
-{
-  if (!NILP (group)
-      && FUNCTIONP (Vrecenter_group_function))
-    return call1 (Vrecenter_group_function, arg);
-  {
-    struct window *w = XWINDOW (selected_window);
-    struct buffer *buf = XBUFFER (w->contents);
-    bool center_p = false;
-    ptrdiff_t charpos, bytepos;
-    EMACS_INT iarg IF_LINT (= 0);
-    int this_scroll_margin;
+and redisplay normally--don't erase and redraw the frame.  */)
+  (register Lisp_Object arg)
+{
+  struct window *w = XWINDOW (selected_window);
+  struct buffer *buf = XBUFFER (w->contents);
+  bool center_p = false;
+  ptrdiff_t charpos, bytepos;
+  EMACS_INT iarg IF_LINT (= 0);
+  int this_scroll_margin;
 
-    if (buf != current_buffer)
-      error ("`recenter'ing a window that does not display current-buffer.");
+  if (buf != current_buffer)
+    error ("`recenter'ing a window that does not display current-buffer.");
 
-    /* If redisplay is suppressed due to an error, try again.  */
-    buf->display_error_modiff = 0;
+  /* If redisplay is suppressed due to an error, try again.  */
+  buf->display_error_modiff = 0;
 
-    if (NILP (arg))
-      {
-        if (!NILP (Vrecenter_redisplay)
-            && (!EQ (Vrecenter_redisplay, Qtty)
-                || !NILP (Ftty_type (selected_frame))))
-          {
-            ptrdiff_t i;
-
-            /* Invalidate pixel data calculated for all compositions.  */
-            for (i = 0; i < n_compositions; i++)
-              composition_table[i]->font = NULL;
+  if (NILP (arg))
+    {
+      if (!NILP (Vrecenter_redisplay)
+         && (!EQ (Vrecenter_redisplay, Qtty)
+             || !NILP (Ftty_type (selected_frame))))
+       {
+         ptrdiff_t i;
+
+         /* Invalidate pixel data calculated for all compositions.  */
+         for (i = 0; i < n_compositions; i++)
+           composition_table[i]->font = NULL;
 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
-            WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
+         WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
 #endif
-            Fredraw_frame (WINDOW_FRAME (w));
-            SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
-          }
+         Fredraw_frame (WINDOW_FRAME (w));
+         SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
+       }
 
-        center_p = true;
-      }
-    else if (CONSP (arg)) /* Just C-u.  */
       center_p = true;
-    else
-      {
-        arg = Fprefix_numeric_value (arg);
-        CHECK_NUMBER (arg);
-        iarg = XINT (arg);
-      }
+    }
+  else if (CONSP (arg)) /* Just C-u.  */
+    center_p = true;
+  else
+    {
+      arg = Fprefix_numeric_value (arg);
+      CHECK_NUMBER (arg);
+      iarg = XINT (arg);
+    }
 
-    /* Do this after making BUF current
-       in case scroll_margin is buffer-local.  */
-    this_scroll_margin
-      = max (0, min (scroll_margin, w->total_lines / 4));
+  /* Do this after making BUF current
+     in case scroll_margin is buffer-local.  */
+  this_scroll_margin
+    = max (0, min (scroll_margin, w->total_lines / 4));
 
-    /* Don't use redisplay code for initial frames, as the necessary
-       data structures might not be set up yet then.  */
-    if (!FRAME_INITIAL_P (XFRAME (w->frame)))
-      {
-        if (center_p)
-          {
-            struct it it;
-            struct text_pos pt;
-            void *itdata = bidi_shelve_cache ();
-
-            SET_TEXT_POS (pt, PT, PT_BYTE);
-            start_display (&it, w, pt);
-            move_it_vertically_backward (&it, window_box_height (w) / 2);
-            charpos = IT_CHARPOS (it);
-            bytepos = IT_BYTEPOS (it);
-            bidi_unshelve_cache (itdata, false);
-          }
-        else if (iarg < 0)
-          {
-            struct it it;
-            struct text_pos pt;
-            ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
-            int extra_line_spacing;
-            int h = window_box_height (w);
-            int ht = window_internal_height (w);
-            void *itdata = bidi_shelve_cache ();
-
-            nlines = clip_to_bounds (this_scroll_margin + 1, nlines,
-                                     ht - this_scroll_margin);
-
-            SET_TEXT_POS (pt, PT, PT_BYTE);
-            start_display (&it, w, pt);
-
-            /* Be sure we have the exact height of the full line containing PT.  */
-            move_it_by_lines (&it, 0);
-
-            /* The amount of pixels we have to move back is the window
-               height minus what's displayed in the line containing PT,
-               and the lines below.  */
-            it.current_y = 0;
-            it.vpos = 0;
-            move_it_by_lines (&it, nlines);
-
-            if (it.vpos == nlines)
-              h -= it.current_y;
-            else
-              {
-                /* Last line has no newline.  */
-                h -= line_bottom_y (&it);
-                it.vpos++;
-              }
-
-            /* Don't reserve space for extra line spacing of last line.  */
-            extra_line_spacing = it.max_extra_line_spacing;
-
-            /* If we can't move down NLINES lines because we hit
-               the end of the buffer, count in some empty lines.  */
-            if (it.vpos < nlines)
-              {
-                nlines -= it.vpos;
-                extra_line_spacing = it.extra_line_spacing;
-                h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
-              }
-            if (h <= 0)
-              {
-                bidi_unshelve_cache (itdata, false);
-                return Qnil;
-              }
-
-            /* Now find the new top line (starting position) of the window.  */
-            start_display (&it, w, pt);
-            it.current_y = 0;
-            move_it_vertically_backward (&it, h);
-
-            /* If extra line spacing is present, we may move too far
-               back.  This causes the last line to be only partially
-               visible (which triggers redisplay to recenter that line
-               in the middle), so move forward.
-               But ignore extra line spacing on last line, as it is not
-               considered to be part of the visible height of the line.
-            */
-            h += extra_line_spacing;
-            while (-it.current_y > h)
-              move_it_by_lines (&it, 1);
-
-            charpos = IT_CHARPOS (it);
-            bytepos = IT_BYTEPOS (it);
-
-            bidi_unshelve_cache (itdata, false);
-          }
-        else
-          {
-            struct it it;
-            struct text_pos pt;
-            ptrdiff_t nlines = min (PTRDIFF_MAX, iarg);
-            int ht = window_internal_height (w);
-            void *itdata = bidi_shelve_cache ();
-
-            nlines = clip_to_bounds (this_scroll_margin, nlines,
-                                     ht - this_scroll_margin - 1);
-
-            SET_TEXT_POS (pt, PT, PT_BYTE);
-            start_display (&it, w, pt);
-
-            /* Move to the beginning of screen line containing PT.  */
-            move_it_by_lines (&it, 0);
-
-            /* Move back to find the point which is ARG screen lines above PT.  */
-            if (nlines > 0)
-              {
-                it.current_y = 0;
-                it.vpos = 0;
-                move_it_by_lines (&it, -nlines);
-              }
-
-            charpos = IT_CHARPOS (it);
-            bytepos = IT_BYTEPOS (it);
-
-            bidi_unshelve_cache (itdata, false);
-          }
-      }
-    else
-      {
-        struct position pos;
-        int ht = window_internal_height (w);
+  /* Don't use redisplay code for initial frames, as the necessary
+     data structures might not be set up yet then.  */
+  if (!FRAME_INITIAL_P (XFRAME (w->frame)))
+    {
+      if (center_p)
+       {
+         struct it it;
+         struct text_pos pt;
+         void *itdata = bidi_shelve_cache ();
+
+         SET_TEXT_POS (pt, PT, PT_BYTE);
+         start_display (&it, w, pt);
+         move_it_vertically_backward (&it, window_box_height (w) / 2);
+         charpos = IT_CHARPOS (it);
+         bytepos = IT_BYTEPOS (it);
+         bidi_unshelve_cache (itdata, false);
+       }
+      else if (iarg < 0)
+       {
+         struct it it;
+         struct text_pos pt;
+         ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
+         int extra_line_spacing;
+         int h = window_box_height (w);
+         int ht = window_internal_height (w);
+         void *itdata = bidi_shelve_cache ();
+
+         nlines = clip_to_bounds (this_scroll_margin + 1, nlines,
+                                  ht - this_scroll_margin);
+
+         SET_TEXT_POS (pt, PT, PT_BYTE);
+         start_display (&it, w, pt);
+
+         /* Be sure we have the exact height of the full line containing PT.  */
+         move_it_by_lines (&it, 0);
+
+         /* The amount of pixels we have to move back is the window
+            height minus what's displayed in the line containing PT,
+            and the lines below.  */
+         it.current_y = 0;
+         it.vpos = 0;
+         move_it_by_lines (&it, nlines);
 
-        if (center_p)
-          iarg = ht / 2;
-        else if (iarg < 0)
-          iarg += ht;
+         if (it.vpos == nlines)
+           h -= it.current_y;
+         else
+           {
+             /* Last line has no newline.  */
+             h -= line_bottom_y (&it);
+             it.vpos++;
+           }
 
-        /* Don't let it get into the margin at either top or bottom.  */
-        iarg = clip_to_bounds (this_scroll_margin, iarg,
-                               ht - this_scroll_margin - 1);
+         /* Don't reserve space for extra line spacing of last line.  */
+         extra_line_spacing = it.max_extra_line_spacing;
 
-        pos = *vmotion (PT, PT_BYTE, - iarg, w);
-        charpos = pos.bufpos;
-        bytepos = pos.bytepos;
-      }
+         /* If we can't move down NLINES lines because we hit
+            the end of the buffer, count in some empty lines.  */
+         if (it.vpos < nlines)
+           {
+             nlines -= it.vpos;
+             extra_line_spacing = it.extra_line_spacing;
+             h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
+           }
+         if (h <= 0)
+           {
+             bidi_unshelve_cache (itdata, false);
+             return Qnil;
+           }
 
-    /* Set the new window start.  */
-    set_marker_both (w->start, w->contents, charpos, bytepos);
-    w->window_end_valid = false;
+         /* Now find the new top line (starting position) of the window.  */
+         start_display (&it, w, pt);
+         it.current_y = 0;
+         move_it_vertically_backward (&it, h);
+
+         /* If extra line spacing is present, we may move too far
+            back.  This causes the last line to be only partially
+            visible (which triggers redisplay to recenter that line
+            in the middle), so move forward.
+            But ignore extra line spacing on last line, as it is not
+            considered to be part of the visible height of the line.
+         */
+         h += extra_line_spacing;
+         while (-it.current_y > h)
+           move_it_by_lines (&it, 1);
 
-    w->optional_new_start = true;
+         charpos = IT_CHARPOS (it);
+         bytepos = IT_BYTEPOS (it);
 
-    w->start_at_line_beg = (bytepos == BEGV_BYTE
-                            || FETCH_BYTE (bytepos - 1) == '\n');
+         bidi_unshelve_cache (itdata, false);
+       }
+      else
+       {
+         struct it it;
+         struct text_pos pt;
+         ptrdiff_t nlines = min (PTRDIFF_MAX, iarg);
+         int ht = window_internal_height (w);
+         void *itdata = bidi_shelve_cache ();
 
-    wset_redisplay (w);
+         nlines = clip_to_bounds (this_scroll_margin, nlines,
+                                  ht - this_scroll_margin - 1);
 
-    return Qnil;
-  }
+         SET_TEXT_POS (pt, PT, PT_BYTE);
+         start_display (&it, w, pt);
+
+         /* Move to the beginning of screen line containing PT.  */
+         move_it_by_lines (&it, 0);
+
+         /* Move back to find the point which is ARG screen lines above PT.  */
+         if (nlines > 0)
+           {
+             it.current_y = 0;
+             it.vpos = 0;
+             move_it_by_lines (&it, -nlines);
+           }
+
+         charpos = IT_CHARPOS (it);
+         bytepos = IT_BYTEPOS (it);
+
+         bidi_unshelve_cache (itdata, false);
+       }
+    }
+  else
+    {
+      struct position pos;
+      int ht = window_internal_height (w);
+
+      if (center_p)
+       iarg = ht / 2;
+      else if (iarg < 0)
+       iarg += ht;
+
+      /* Don't let it get into the margin at either top or bottom.  */
+      iarg = clip_to_bounds (this_scroll_margin, iarg,
+                            ht - this_scroll_margin - 1);
+
+      pos = *vmotion (PT, PT_BYTE, - iarg, w);
+      charpos = pos.bufpos;
+      bytepos = pos.bytepos;
+    }
+
+  /* Set the new window start.  */
+  set_marker_both (w->start, w->contents, charpos, bytepos);
+  w->window_end_valid = false;
+
+  w->optional_new_start = true;
+
+  w->start_at_line_beg = (bytepos == BEGV_BYTE
+                         || FETCH_BYTE (bytepos - 1) == '\n');
+
+  wset_redisplay (w);
+
+  return Qnil;
 }
 
 DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width,
@@ -5897,68 +5842,52 @@ pixels.  */)
 }
 \f
 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
-       1, 2, "P\ni",
+       1, 1, "P",
        doc: /* Position point relative to window.
 ARG nil means position point at center of window.
 Else, ARG specifies vertical position within the window;
-zero means top of window, negative means relative to bottom of window.
-
-When GROUP is non-nil, and `move-to-window-line-group-function' is set to a
-function, then instead of the above, that function is called with the
-single argument ARG, and its result returned.
-
-If GROUP is non-nil, and WINDOW is part of a group of windows collectively
-displaying a buffer (such as with Follow Mode), position point relative to
-the group of windows as a whole rather than the individual WINDOW.  This
-condition holds when `move-to-window-line-group-function' is set to a
-function, in which case `move-to-window-line' calls the function with the
-argument ARG, then returns its result, instead of doing its normal
-processing.  */)
-  (Lisp_Object arg, Lisp_Object group)
-{
-  if (!NILP (group)
-      && FUNCTIONP (Vmove_to_window_line_group_function))
-    return call1 (Vmove_to_window_line_group_function, arg);
-  {
-    struct window *w = XWINDOW (selected_window);
-    int lines, start;
-    Lisp_Object window;
+zero means top of window, negative means relative to bottom of window.  */)
+  (Lisp_Object arg)
+{
+  struct window *w = XWINDOW (selected_window);
+  int lines, start;
+  Lisp_Object window;
 #if false
-    int this_scroll_margin;
+  int this_scroll_margin;
 #endif
 
-    if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer))
-      /* This test is needed to make sure PT/PT_BYTE make sense in w->contents
-         when passed below to set_marker_both.  */
-      error ("move-to-window-line called from unrelated buffer");
+  if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer))
+    /* This test is needed to make sure PT/PT_BYTE make sense in w->contents
+       when passed below to set_marker_both.  */
+    error ("move-to-window-line called from unrelated buffer");
 
-    window = selected_window;
-    start = marker_position (w->start);
-    if (start < BEGV || start > ZV)
-      {
-        int height = window_internal_height (w);
-        Fvertical_motion (make_number (- (height / 2)), window, Qnil);
-        set_marker_both (w->start, w->contents, PT, PT_BYTE);
-        w->start_at_line_beg = !NILP (Fbolp ());
-        w->force_start = true;
-      }
-    else
-      Fgoto_char (w->start);
+  window = selected_window;
+  start = marker_position (w->start);
+  if (start < BEGV || start > ZV)
+    {
+      int height = window_internal_height (w);
+      Fvertical_motion (make_number (- (height / 2)), window, Qnil);
+      set_marker_both (w->start, w->contents, PT, PT_BYTE);
+      w->start_at_line_beg = !NILP (Fbolp ());
+      w->force_start = true;
+    }
+  else
+    Fgoto_char (w->start);
 
-    lines = displayed_window_lines (w);
+  lines = displayed_window_lines (w);
 
 #if false
-    this_scroll_margin = max (0, min (scroll_margin, lines / 4));
+  this_scroll_margin = max (0, min (scroll_margin, lines / 4));
 #endif
 
-    if (NILP (arg))
-      XSETFASTINT (arg, lines / 2);
-    else
-      {
-        EMACS_INT iarg = XINT (Fprefix_numeric_value (arg));
+  if (NILP (arg))
+    XSETFASTINT (arg, lines / 2);
+  else
+    {
+      EMACS_INT iarg = XINT (Fprefix_numeric_value (arg));
 
-        if (iarg < 0)
-          iarg = iarg + lines;
+      if (iarg < 0)
+       iarg = iarg + lines;
 
 #if false /* This code would prevent move-to-window-line from moving point
             to a place inside the scroll margins (which would cause the
@@ -5966,20 +5895,19 @@ processing.  */)
             it is probably better not to install it.  However, it is here
             inside #if false so as not to lose it.  -- rms.  */
 
-        /* Don't let it get into the margin at either top or bottom.  */
-        iarg = max (iarg, this_scroll_margin);
-        iarg = min (iarg, lines - this_scroll_margin - 1);
+      /* Don't let it get into the margin at either top or bottom.  */
+      iarg = max (iarg, this_scroll_margin);
+      iarg = min (iarg, lines - this_scroll_margin - 1);
 #endif
 
-        arg = make_number (iarg);
-      }
+      arg = make_number (iarg);
+    }
 
-    /* Skip past a partially visible first line.  */
-    if (w->vscroll)
-      XSETINT (arg, XINT (arg) + 1);
+  /* Skip past a partially visible first line.  */
+  if (w->vscroll)
+    XSETINT (arg, XINT (arg) + 1);
 
-    return Fvertical_motion (arg, window, Qnil);
-  }
+  return Fvertical_motion (arg, window, Qnil);
 }
 
 
@@ -7253,12 +7181,6 @@ syms_of_window (void)
   DEFSYM (Qclone_of, "clone-of");
   DEFSYM (Qfloor, "floor");
   DEFSYM (Qceiling, "ceiling");
-  DEFSYM (Qwindow_start_group_function, "window-start-group-function");
-  DEFSYM (Qwindow_end_group_function, "window-end-group-function");
-  DEFSYM (Qset_window_start_group_function, "set-window-start-group-function");
-  DEFSYM (Qrecenter_group_function, "recenter-group-function");
-  DEFSYM (Qpos_visible_in_window_p_group_function, "pos-visible-in-window-p-group-function");
-  DEFSYM (Qmove_to_window_line_group_function, "move-to-window-line-group-function");
 
   staticpro (&Vwindow_list);
 
@@ -7341,7 +7263,7 @@ resizing a window preferably resizes one adjacent window only.
 
 If this variable is t, splitting a window tries to get the space
 proportionally from all windows in the same combination.  This also
-allows to split a window that is otherwise too small or of fixed size.
+allows splitting a window that is otherwise too small or of fixed size.
 Resizing and deleting a window proportionally resize all windows in the
 same combination.
 
@@ -7430,72 +7352,6 @@ Note that this optimization can cause the portion of the buffer
 displayed after a scrolling operation to be somewhat inaccurate.  */);
   Vfast_but_imprecise_scrolling = false;
 
-  DEFVAR_LISP ("window-start-group-function", Vwindow_start_group_function,
-               doc: /* Function to call for `window-start' when its GROUP parameter is non-nil.
-When this variable contains a function, and `window-start' is called with a
-non-nil GROUP parameter, the function is called instead of `window-start''s
-normal action.  `window-start' passes the function its argument WINDOW, which
-might be nil.  The function may recursively call `window-start'.  */);
-  Vwindow_start_group_function = Qnil;
-  Fmake_variable_buffer_local (Qwindow_start_group_function);
-  Fput (Qwindow_start_group_function, Qpermanent_local, Qt);
-
-  DEFVAR_LISP ("window-end-group-function", Vwindow_end_group_function,
-               doc: /* Function to call for `window-end' if its GROUP parameter is non-nil.
-When this variable contains a function, and `window-end' is called with a
-non-nil GROUP parameter, the function is called instead of `window-end''s
-normal action.  `window-end' passes the function its two parameters WINDOW,
-and UPDATE.  The function may call `window-end' recursively.  */);
-  Vwindow_end_group_function = Qnil;
-  Fmake_variable_buffer_local (Qwindow_end_group_function);
-  Fput (Qwindow_end_group_function, Qpermanent_local, Qt);
-
-  DEFVAR_LISP ("set-window-start-group-function",
-               Vset_window_start_group_function,
-               doc: /* The function to call for `set-window-start' when its GROUP parameter is non-nil.
-When this variable contains a function, and `set-window-start' is called
-with a non-nil GROUP parameter, the function is called instead of
-`set-window-start''s normal action.  `set-window-start' passes the function
-its three parameters WINDOW, POS, and NOFORCE.  The function may call
-`set-window-start' recursively.  */);
-  Vset_window_start_group_function = Qnil;
-  Fmake_variable_buffer_local (Qset_window_start_group_function);
-  Fput (Qset_window_start_group_function, Qpermanent_local, Qt);
-
-  DEFVAR_LISP ("recenter-group-function", Vrecenter_group_function,
-               doc: /* Function to call for `recenter' when its GROUP parameter is non-nil.
-When this variable contains a function, and `recenter' is called with a
-non-nil GROUP parameter, the function is called instead of `recenter''s
-normal action.  `recenter' passes the function its parameter ARG.  The
-function may call `recenter' recursively.  */);
-  Vrecenter_group_function = Qnil;
-  Fmake_variable_buffer_local (Qrecenter_group_function);
-  Fput (Qrecenter_group_function, Qpermanent_local, Qt);
-
-  DEFVAR_LISP ("pos-visible-in-window-p-group-function",
-               Vpos_visible_in_window_p_group_function,
-               doc: /*  Function for `pos-visible-in-window-p' when its GROUP parameter is non-nil.
-When this variable contains a function, and `pos-visible-in-window-p' is
-called with a non-nil GROUP parameter, the function is called instead of
-`pos-visible-in-window-p''s normal action.  `pos-visible-in-window-p'
-passes the function its three parameters POS, WINDOW, and PARTIALLY.  The
-function may call `pos-visible-in-window-p' recursively.  */);
-  Vpos_visible_in_window_p_group_function = Qnil;
-  Fmake_variable_buffer_local (Qpos_visible_in_window_p_group_function);
-  Fput (Qpos_visible_in_window_p_group_function, Qpermanent_local, Qt);
-
-  DEFVAR_LISP ("move-to-window-line-group-function",
-               Vmove_to_window_line_group_function,
-               doc: /* Function for `move-to-window-line' when its GROUP parameter is non-nil.
-When this variable contains a function, and `move-to-window-line' is
-called with a non-nil GROUP parameter, the function is called instead of
-`move-to-window-line''s normal action.  `move-to-window-line' passes the
-function its parameter ARG.  The function may call `move-to-window-line'
-recursively.  */);
-  Vmove_to_window_line_group_function = Qnil;
-  Fmake_variable_buffer_local (Qmove_to_window_line_group_function);
-  Fput (Qmove_to_window_line_group_function, Qpermanent_local, Qt);
-
   defsubr (&Sselected_window);
   defsubr (&Sminibuffer_window);
   defsubr (&Swindow_minibuffer_p);