Convert (most) functions in src to standard C.
[bpt/emacs.git] / src / window.c
index 81fb70a..f3c6393 100644 (file)
@@ -1,7 +1,7 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
    Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
-                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -21,6 +21,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <stdio.h>
+#include <setjmp.h>
 
 #include "lisp.h"
 #include "buffer.h"
@@ -53,37 +54,37 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
 Lisp_Object Qdisplay_buffer;
-Lisp_Object Qscroll_up, Qscroll_down;
+Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
 Lisp_Object Qwindow_size_fixed;
 
 extern Lisp_Object Qleft_margin, Qright_margin;
 
-static int displayed_window_lines P_ ((struct window *));
-static struct window *decode_window P_ ((Lisp_Object));
-static int count_windows P_ ((struct window *));
-static int get_leaf_windows P_ ((struct window *, struct window **, int));
-static void window_scroll P_ ((Lisp_Object, int, int, int));
-static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
-static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
-static int window_min_size_1 P_ ((struct window *, int, int));
-static int window_min_size_2 P_ ((struct window *, int, int));
-static int window_min_size P_ ((struct window *, int, int, int, int *));
-static void size_window P_ ((Lisp_Object, int, int, int, int, int));
-static int freeze_window_start P_ ((struct window *, void *));
-static int window_fixed_size_p P_ ((struct window *, int, int));
-static void enlarge_window P_ ((Lisp_Object, int, int));
-static Lisp_Object window_list P_ ((void));
-static int add_window_to_list P_ ((struct window *, void *));
-static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
-                                  Lisp_Object));
-static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
-                                   Lisp_Object, int));
-static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
-                                        Lisp_Object *));
-static int foreach_window_1 P_ ((struct window *,
-                                int (* fn) (struct window *, void *),
-                                void *));
-static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
+static int displayed_window_lines (struct window *);
+static struct window *decode_window (Lisp_Object);
+static int count_windows (struct window *);
+static int get_leaf_windows (struct window *, struct window **, int);
+static void window_scroll (Lisp_Object, 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 window_min_size_1 (struct window *, int, int);
+static int window_min_size_2 (struct window *, int, int);
+static int window_min_size (struct window *, int, int, int, int *);
+static void size_window (Lisp_Object, int, int, int, int, int);
+static int freeze_window_start (struct window *, void *);
+static int window_fixed_size_p (struct window *, int, int);
+static void enlarge_window (Lisp_Object, int, 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 *,
+                                     Lisp_Object *);
+static int foreach_window_1 (struct window *,
+                             int (* fn) (struct window *, void *),
+                             void *);
+static Lisp_Object window_list_1 (Lisp_Object, Lisp_Object, Lisp_Object);
 
 /* This is the window in which the terminal's cursor should
    be left when nothing is being done with it.  This must
@@ -193,6 +194,14 @@ static int inhibit_frame_unsplittable;
 extern EMACS_INT scroll_margin;
 
 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
+
+/* If non-nil, then the `recenter' command with a nil argument
+   the entire frame to be redrawn; the special value `tty' causes the
+   frame to be redrawn only if it is a tty frame.  */
+
+static Lisp_Object Vrecenter_redisplay;
+extern Lisp_Object Qtty;
+
 \f
 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
        doc: /* Return t if OBJECT is a window.  */)
@@ -211,7 +220,7 @@ DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
 }
 
 Lisp_Object
-make_window ()
+make_window (void)
 {
   Lisp_Object val;
   register struct window *p;
@@ -474,8 +483,7 @@ Return nil if window display is not up-to-date.  In that case, use
 
 \f
 static struct window *
-decode_window (window)
-     register Lisp_Object window;
+decode_window (register Lisp_Object window)
 {
   if (NILP (window))
     return XWINDOW (selected_window);
@@ -485,8 +493,7 @@ decode_window (window)
 }
 
 static struct window *
-decode_any_window (window)
-     register Lisp_Object window;
+decode_any_window (register Lisp_Object window)
 {
   if (NILP (window))
     return XWINDOW (selected_window);
@@ -600,12 +607,15 @@ Afterwards the end-trigger value is reset to nil.  */)
 
 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
        doc: /* Return a list of the edge coordinates of WINDOW.
-\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
-RIGHT is one more than the rightmost column occupied by WINDOW,
-and BOTTOM is one more than the bottommost row occupied by WINDOW.
-The edges include the space used by the window's scroll bar,
-display margins, fringes, header line, and mode line, if it has them.
-To get the edges of the actual text area, use `window-inside-edges'.  */)
+The list has the form (LEFT TOP RIGHT BOTTOM).
+TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
+all relative to 0, 0 at top left corner of frame.
+
+RIGHT is one more than the rightmost column occupied by WINDOW.
+BOTTOM is one more than the bottommost row occupied by WINDOW.
+The edges include the space used by WINDOW's scroll bar, display
+margins, fringes, header line, and/or mode line.  For the edges of
+just the text area, use `window-inside-edges'.  */)
      (window)
      Lisp_Object window;
 {
@@ -620,12 +630,14 @@ To get the edges of the actual text area, use `window-inside-edges'.  */)
 
 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
        doc: /* Return a list of the edge pixel coordinates of WINDOW.
-\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
-RIGHT is one more than the rightmost x position occupied by WINDOW,
-and BOTTOM is one more than the bottommost y position occupied by WINDOW.
-The pixel edges include the space used by the window's scroll bar,
-display margins, fringes, header line, and mode line, if it has them.
-To get the edges of the actual text area, use `window-inside-pixel-edges'.  */)
+The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
+the top left corner of the frame.
+
+RIGHT is one more than the rightmost x position occupied by WINDOW.
+BOTTOM is one more than the bottommost y position occupied by WINDOW.
+The pixel edges include the space used by WINDOW's scroll bar, display
+margins, fringes, header line, and/or mode line.  For the pixel edges
+of just the text area, use `window-inside-pixel-edges'.  */)
      (window)
      Lisp_Object window;
 {
@@ -638,13 +650,58 @@ To get the edges of the actual text area, use `window-inside-pixel-edges'.  */)
                Qnil))));
 }
 
+static void
+calc_absolute_offset(struct window *w, int *add_x, int *add_y)
+{
+  struct frame *f = XFRAME (w->frame);
+  *add_y = f->top_pos;
+#ifdef FRAME_MENUBAR_HEIGHT
+  *add_y += FRAME_MENUBAR_HEIGHT (f);
+#endif
+#ifdef FRAME_TOOLBAR_HEIGHT
+  *add_y += FRAME_TOOLBAR_HEIGHT (f);
+#endif
+#ifdef FRAME_NS_TITLEBAR_HEIGHT
+  *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
+#endif
+  *add_x = f->left_pos;
+}
+
+DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
+       Swindow_absolute_pixel_edges, 0, 1, 0,
+       doc: /* Return a list of the edge pixel coordinates of WINDOW.
+The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
+the top left corner of the display.
+
+RIGHT is one more than the rightmost x position occupied by WINDOW.
+BOTTOM is one more than the bottommost y position occupied by WINDOW.
+The pixel edges include the space used by WINDOW's scroll bar, display
+margins, fringes, header line, and/or mode line.  For the pixel edges
+of just the text area, use `window-inside-absolute-pixel-edges'.  */)
+     (window)
+     Lisp_Object window;
+{
+  register struct window *w = decode_any_window (window);
+  int add_x, add_y;
+  calc_absolute_offset(w, &add_x, &add_y);
+
+  return Fcons (make_number (WINDOW_LEFT_EDGE_X (w) + add_x),
+         Fcons (make_number (WINDOW_TOP_EDGE_Y (w) + add_y),
+        Fcons (make_number (WINDOW_RIGHT_EDGE_X (w) + add_x),
+        Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w) + add_y),
+               Qnil))));
+}
+
 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
        doc: /* Return a list of the edge coordinates of WINDOW.
-\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
-RIGHT is one more than the rightmost column used by text in WINDOW,
-and BOTTOM is one more than the bottommost row used by text in WINDOW.
-The inside edges do not include the space used by the window's scroll bar,
-display margins, fringes, header line, and/or mode line.  */)
+The list has the form (LEFT TOP RIGHT BOTTOM).
+TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
+all relative to 0, 0 at top left corner of frame.
+
+RIGHT is one more than the rightmost column of WINDOW's text area.
+BOTTOM is one more than the bottommost row of WINDOW's text area.
+The inside edges do not include the space used by the WINDOW's scroll
+bar, display margins, fringes, header line, and/or mode line.  */)
      (window)
      Lisp_Object window;
 {
@@ -664,10 +721,12 @@ display margins, fringes, header line, and/or mode line.  */)
 
 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
        doc: /* Return a list of the edge pixel coordinates of WINDOW.
-\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
-RIGHT is one more than the rightmost x position used by text in WINDOW,
-and BOTTOM is one more than the bottommost y position used by text in WINDOW.
-The inside edges do not include the space used by the window's scroll bar,
+The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
+the top left corner of the frame.
+
+RIGHT is one more than the rightmost x position of WINDOW's text area.
+BOTTOM is one more than the bottommost y position of WINDOW's text area.
+The inside edges do not include the space used by WINDOW's scroll bar,
 display margins, fringes, header line, and/or mode line.  */)
      (window)
      Lisp_Object window;
@@ -686,6 +745,36 @@ display margins, fringes, header line, and/or mode line.  */)
                             - WINDOW_MODE_LINE_HEIGHT (w)));
 }
 
+DEFUN ("window-inside-absolute-pixel-edges",
+       Fwindow_inside_absolute_pixel_edges,
+       Swindow_inside_absolute_pixel_edges, 0, 1, 0,
+       doc: /* Return a list of the edge pixel coordinates of WINDOW.
+The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
+the top left corner of the display.
+
+RIGHT is one more than the rightmost x position of WINDOW's text area.
+BOTTOM is one more than the bottommost y position of WINDOW's text area.
+The inside edges do not include the space used by WINDOW's scroll bar,
+display margins, fringes, header line, and/or mode line.  */)
+     (window)
+     Lisp_Object window;
+{
+  register struct window *w = decode_any_window (window);
+  int add_x, add_y;
+  calc_absolute_offset(w, &add_x, &add_y);
+
+  return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
+                            + WINDOW_LEFT_MARGIN_WIDTH (w)
+                            + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
+               make_number (WINDOW_TOP_EDGE_Y (w)
+                            + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
+               make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
+                            - WINDOW_RIGHT_MARGIN_WIDTH (w)
+                            - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
+               make_number (WINDOW_BOTTOM_EDGE_Y (w)
+                            - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
+}
+
 /* Test if the character at column *X, row *Y is within window W.
    If it is not, return ON_NOTHING;
    if it is in the window's text area,
@@ -708,9 +797,7 @@ display margins, fringes, header line, and/or mode line.  */)
    X and Y are frame relative pixel coordinates.  */
 
 static enum window_part
-coordinates_in_window (w, x, y)
-     register struct window *w;
-     register int *x, *y;
+coordinates_in_window (register struct window *w, register int *x, register int *y)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   int left_x, right_x, top_y, bottom_y;
@@ -993,9 +1080,7 @@ struct check_window_data
 };
 
 static int
-check_window_containing (w, user_data)
-     struct window *w;
-     void *user_data;
+check_window_containing (struct window *w, void *user_data)
 {
   struct check_window_data *cw = (struct check_window_data *) user_data;
   enum window_part found;
@@ -1033,12 +1118,7 @@ check_window_containing (w, user_data)
    case.  */
 
 Lisp_Object
-window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
-     struct frame *f;
-     int x, y;
-     enum window_part *part;
-     int *wx, *wy;
-     int tool_bar_p;
+window_from_coordinates (struct frame *f, int x, int y, enum window_part *part, int *wx, int *wy, int tool_bar_p)
 {
   Lisp_Object window;
   struct check_window_data cw;
@@ -1378,8 +1458,7 @@ WINDOW defaults to the selected window.  */)
    return 0.  */
 
 struct Lisp_Char_Table *
-window_display_table (w)
-     struct window *w;
+window_display_table (struct window *w)
 {
   struct Lisp_Char_Table *dp = NULL;
 
@@ -1413,8 +1492,7 @@ DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_displa
 /* Record info on buffer window w is displaying
    when it is about to cease to display that buffer.  */
 static void
-unshow_buffer (w)
-     register struct window *w;
+unshow_buffer (register struct window *w)
 {
   Lisp_Object buf;
   struct buffer *b;
@@ -1462,8 +1540,7 @@ unshow_buffer (w)
 
 /* Put replacement into the window structure in place of old. */
 static void
-replace_window (old, replacement)
-     Lisp_Object old, replacement;
+replace_window (Lisp_Object old, Lisp_Object replacement)
 {
   register Lisp_Object tem;
   register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
@@ -1525,6 +1602,9 @@ Signal an error when WINDOW is the only window on its frame.  */)
   struct frame *f;
   if (NILP (window))
     window = selected_window;
+  else
+    CHECK_LIVE_WINDOW (window);
+
   f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
   delete_window (window);
 
@@ -1534,8 +1614,7 @@ Signal an error when WINDOW is the only window on its frame.  */)
 }
 
 void
-delete_window (window)
-     register Lisp_Object window;
+delete_window (register Lisp_Object window)
 {
   register Lisp_Object tem, parent, sib;
   register struct window *p;
@@ -1749,9 +1828,7 @@ delete_window (window)
    function window_list.  */
 
 static int
-add_window_to_list (w, user_data)
-     struct window *w;
-     void *user_data;
+add_window_to_list (struct window *w, void *user_data)
 {
   Lisp_Object *list = (Lisp_Object *) user_data;
   Lisp_Object window;
@@ -1766,7 +1843,7 @@ add_window_to_list (w, user_data)
    list, cache it in Vwindow_list, and return that.  */
 
 static Lisp_Object
-window_list ()
+window_list (void)
 {
   if (!CONSP (Vwindow_list))
     {
@@ -1807,8 +1884,7 @@ window_list ()
                a frame means consider windows on that frame, only.  */
 
 static int
-candidate_window_p (window, owindow, minibuf, all_frames)
-     Lisp_Object window, owindow, minibuf, all_frames;
+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);
@@ -1873,8 +1949,7 @@ candidate_window_p (window, owindow, minibuf, all_frames)
    ALL_FRAMES.  */
 
 static void
-decode_next_window_args (window, minibuf, all_frames)
-     Lisp_Object *window, *minibuf, *all_frames;
+decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
 {
   if (NILP (*window))
     *window = selected_window;
@@ -1920,9 +1995,7 @@ decode_next_window_args (window, minibuf, all_frames)
    ALL_FRAMES.  */
 
 static Lisp_Object
-next_window (window, minibuf, all_frames, next_p)
-     Lisp_Object window, minibuf, all_frames;
-     int next_p;
+next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, int next_p)
 {
   decode_next_window_args (&window, &minibuf, &all_frames);
 
@@ -2106,8 +2179,7 @@ MINIBUF neither nil nor t means never include the minibuffer window.  */)
    for `next-window'.  */
 
 static Lisp_Object
-window_list_1 (window, minibuf, all_frames)
-     Lisp_Object window, minibuf, all_frames;
+window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
 {
   Lisp_Object tail, list, rest;
 
@@ -2155,10 +2227,7 @@ enum window_loop
 };
 
 static Lisp_Object
-window_loop (type, obj, mini, frames)
-     enum window_loop type;
-     Lisp_Object obj, frames;
-     int mini;
+window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frames)
 {
   Lisp_Object window, windows, best_window, frame_arg;
   struct frame *f;
@@ -2385,7 +2454,7 @@ window_loop (type, obj, mini, frames)
 /* Used for debugging.  Abort if any window has a dead buffer.  */
 
 void
-check_all_windows ()
+check_all_windows (void)
 {
   window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
 }
@@ -2596,8 +2665,7 @@ frames left, some other buffer is displayed in that window.  */)
    of all frames, even those on other keyboards.  */
 
 void
-replace_buffer_in_all_windows (buffer)
-     Lisp_Object buffer;
+replace_buffer_in_all_windows (Lisp_Object buffer)
 {
   Lisp_Object tail, frame;
 
@@ -2626,9 +2694,7 @@ replace_buffer_in_all_windows (buffer)
    minimum allowable size.  */
 
 void
-check_frame_size (frame, rows, cols)
-     FRAME_PTR frame;
-     int *rows, *cols;
+check_frame_size (FRAME_PTR frame, int *rows, int *cols)
 {
   /* For height, we have to see:
      how many windows the frame has at minimum (one or two),
@@ -2654,9 +2720,7 @@ check_frame_size (frame, rows, cols)
    either.  */
 
 static int
-window_fixed_size_p (w, width_p, check_siblings_p)
-     struct window *w;
-     int width_p, check_siblings_p;
+window_fixed_size_p (struct window *w, int width_p, int check_siblings_p)
 {
   int fixed_p;
   struct window *c;
@@ -2756,9 +2820,7 @@ window_fixed_size_p (w, width_p, check_siblings_p)
    minibuffer window, always return 1.  */
 
 static int
-window_min_size_2 (w, width_p, safe_p)
-     struct window *w;
-     int width_p, safe_p;
+window_min_size_2 (struct window *w, int width_p, int safe_p)
 {
   /* We should consider buffer-local values of window_min_height and
      window_min_width here.  */
@@ -2792,9 +2854,7 @@ window_min_size_2 (w, width_p, safe_p)
    sizes of W's children.  */
 
 static int
-window_min_size_1 (w, width_p, safe_p)
-     struct window *w;
-     int width_p, safe_p;
+window_min_size_1 (struct window *w, int width_p, int safe_p)
 {
   struct window *c;
   int size;
@@ -2869,9 +2929,7 @@ window_min_size_1 (w, width_p, safe_p)
    to 1 if W is fixed-size unless FIXED is null.  */
 
 static int
-window_min_size (w, width_p, safe_p, ignore_fixed_p, fixed)
-     struct window *w;
-     int width_p, safe_p, ignore_fixed_p, *fixed;
+window_min_size (struct window *w, int width_p, int safe_p, int ignore_fixed_p, int *fixed)
 {
   int size, fixed_p;
 
@@ -2897,8 +2955,7 @@ window_min_size (w, width_p, safe_p, ignore_fixed_p, fixed)
    is still too narrow.  */
 
 static int
-adjust_window_margins (w)
-     struct window *w;
+adjust_window_margins (struct window *w)
 {
   int box_cols = (WINDOW_TOTAL_COLS (w)
                  - WINDOW_FRINGE_COLS (w)
@@ -3096,10 +3153,7 @@ shrink_windows (total, size, nchildren, shrinkable, resize_fixed_p,
    This should give better behavior when resizing frames.  */
 
 static void
-size_window (window, size, width_p, nodelete_p, first_only, last_only)
-     Lisp_Object window;
-     int size, width_p, nodelete_p;
-     int first_only, last_only;
+size_window (Lisp_Object window, int size, int width_p, int nodelete_p, int first_only, int last_only)
 {
   struct window *w = XWINDOW (window);
   struct window *c;
@@ -3290,10 +3344,7 @@ size_window (window, size, width_p, nodelete_p, first_only, last_only)
    displayed correctly.  */
 
 void
-set_window_height (window, height, nodelete)
-     Lisp_Object window;
-     int height;
-     int nodelete;
+set_window_height (Lisp_Object window, int height, int nodelete)
 {
   size_window (window, height, 0, nodelete, 0, 0);
 }
@@ -3307,10 +3358,7 @@ set_window_height (window, height, nodelete)
    displayed correctly.  */
 
 void
-set_window_width (window, width, nodelete)
-     Lisp_Object window;
-     int width;
-     int nodelete;
+set_window_width (Lisp_Object window, int width, int nodelete)
 {
   size_window (window, width, 1, nodelete, 0, 0);
 }
@@ -3318,9 +3366,7 @@ set_window_width (window, width, nodelete)
 /* Change window heights in windows rooted in WINDOW by N lines.  */
 
 void
-change_window_heights (window, n)
-     Lisp_Object window;
-     int n;
+change_window_heights (Lisp_Object window, int n)
 {
   struct window *w = XWINDOW (window);
 
@@ -3416,9 +3462,7 @@ run_window_configuration_change_hook (struct frame *f)
    reset from the buffer's local settings.  */
 
 void
-set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
-     Lisp_Object window, buffer;
-     int run_hooks_p, keep_margins_p;
+set_window_buffer (Lisp_Object window, Lisp_Object buffer, int run_hooks_p, int keep_margins_p)
 {
   struct window *w = XWINDOW (window);
   struct buffer *b = XBUFFER (buffer);
@@ -3589,6 +3633,7 @@ selected window before each command.  */)
     {
       ++window_select_count;
       XSETFASTINT (w->use_time, window_select_count);
+      record_buffer (w->buffer);
     }
 
   if (EQ (window, selected_window))
@@ -3624,8 +3669,6 @@ selected window before each command.  */)
 
   selected_window = window;
 
-  if (NILP (norecord))
-    record_buffer (w->buffer);
   Fset_buffer (w->buffer);
 
   XBUFFER (w->buffer)->last_selected_window = window;
@@ -3650,24 +3693,21 @@ selected window before each command.  */)
 }
 
 static Lisp_Object
-select_window_norecord (window)
-     Lisp_Object window;
+select_window_norecord (Lisp_Object window)
 {
   return WINDOW_LIVE_P (window)
     ? Fselect_window (window, Qt) : selected_window;
 }
 
 static Lisp_Object
-select_frame_norecord (frame)
-     Lisp_Object frame;
+select_frame_norecord (Lisp_Object frame)
 {
   return FRAME_LIVE_P (XFRAME (frame))
     ? Fselect_frame (frame, Qt) : selected_frame;
 }
 \f
 Lisp_Object
-display_buffer (buffer, not_this_window_p, override_frame)
-     Lisp_Object buffer, not_this_window_p, override_frame;
+display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
 {
   return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
 }
@@ -3718,8 +3758,7 @@ displaying that buffer.  */)
 
 
 void
-temp_output_buffer_show (buf)
-     register Lisp_Object buf;
+temp_output_buffer_show (register Lisp_Object buf)
 {
   register struct buffer *old = current_buffer;
   register Lisp_Object window;
@@ -3779,8 +3818,7 @@ temp_output_buffer_show (buf)
 }
 \f
 static void
-make_dummy_parent (window)
-     Lisp_Object window;
+make_dummy_parent (Lisp_Object window)
 {
   Lisp_Object new;
   register struct window *o, *p;
@@ -3994,16 +4032,14 @@ fixed size windows is not altered by this function. */)
 }
 
 int
-window_height (window)
-     Lisp_Object window;
+window_height (Lisp_Object window)
 {
   register struct window *p = XWINDOW (window);
   return WINDOW_TOTAL_LINES (p);
 }
 
 int
-window_width (window)
-     Lisp_Object window;
+window_width (Lisp_Object window)
 {
   register struct window *p = XWINDOW (window);
   return WINDOW_TOTAL_COLS (p);
@@ -4025,17 +4061,15 @@ window_width (window)
    deleted.  */
 
 static void
-enlarge_window (window, delta, horiz_flag)
-     Lisp_Object window;
-     int delta, horiz_flag;
+enlarge_window (Lisp_Object window, int delta, int horiz_flag)
 {
   Lisp_Object parent, next, prev;
   struct window *p;
   Lisp_Object *sizep;
   int maximum;
-  int (*sizefun) P_ ((Lisp_Object))
+  int (*sizefun) (Lisp_Object)
     = horiz_flag ? window_width : window_height;
-  void (*setsizefun) P_ ((Lisp_Object, int, int))
+  void (*setsizefun) (Lisp_Object, int, int)
     = (horiz_flag ? set_window_width : set_window_height);
 
   /* Give up if this window cannot be resized.  */
@@ -4303,9 +4337,7 @@ enlarge_window (window, delta, horiz_flag)
    are not deleted; instead, we signal an error.  */
 
 static void
-adjust_window_trailing_edge (window, delta, horiz_flag)
-     Lisp_Object window;
-     int delta, horiz_flag;
+adjust_window_trailing_edge (Lisp_Object window, int delta, int horiz_flag)
 {
   Lisp_Object parent, child;
   struct window *p;
@@ -4461,7 +4493,7 @@ are not deleted; instead, we signal an error.  */)
                        Resizing Mini-Windows
  ***********************************************************************/
 
-static void shrink_window_lowest_first P_ ((struct window *, int));
+static void shrink_window_lowest_first (struct window *, int);
 
 enum save_restore_action
 {
@@ -4470,16 +4502,14 @@ enum save_restore_action
     RESTORE_ORIG_SIZES
 };
 
-static int save_restore_orig_size P_ ((struct window *,
-                                       enum save_restore_action));
+static int save_restore_orig_size (struct window *,
+                                   enum save_restore_action);
 
 /* Shrink windows rooted in window W to HEIGHT.  Take the space needed
    from lowest windows first.  */
 
 static void
-shrink_window_lowest_first (w, height)
-     struct window *w;
-     int height;
+shrink_window_lowest_first (struct window *w, int height)
 {
   struct window *c;
   Lisp_Object child;
@@ -4561,9 +4591,7 @@ shrink_window_lowest_first (w, height)
    stored in orig_top_line and orig_total_lines for all windows.  */
 
 static int
-save_restore_orig_size (w, action)
-     struct window *w;
-     enum save_restore_action action;
+save_restore_orig_size (struct window *w, enum save_restore_action action)
 {
   int success_p = 1;
 
@@ -4618,20 +4646,21 @@ save_restore_orig_size (w, action)
    without deleting other windows.  */
 
 void
-grow_mini_window (w, delta)
-     struct window *w;
-     int delta;
+grow_mini_window (struct window *w, int delta)
 {
   struct frame *f = XFRAME (w->frame);
   struct window *root;
 
   xassert (MINI_WINDOW_P (w));
-  xassert (delta >= 0);
+  /* Commenting out the following assertion goes against the stated interface
+     of the function, but it currently does not seem to do anything useful.
+     See discussion of this issue in the thread for bug#4534.
+     xassert (delta >= 0); */
 
   /* Compute how much we can enlarge the mini-window without deleting
      other windows.  */
   root = XWINDOW (FRAME_ROOT_WINDOW (f));
-  if (delta)
+  if (delta > 0)
     {
       int min_height = window_min_size (root, 0, 0, 0, 0);
       if (XFASTINT (root->total_lines) - delta < min_height)
@@ -4666,8 +4695,7 @@ grow_mini_window (w, delta)
    line.  */
 
 void
-shrink_mini_window (w)
-     struct window *w;
+shrink_mini_window (struct window *w)
 {
   struct frame *f = XFRAME (w->frame);
   struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
@@ -4697,8 +4725,7 @@ shrink_mini_window (w)
    the frame are cleared.  */
 
 void
-mark_window_cursors_off (w)
-     struct window *w;
+mark_window_cursors_off (struct window *w)
 {
   while (w)
     {
@@ -4717,8 +4744,7 @@ mark_window_cursors_off (w)
 /* Return number of lines of text (not counting mode lines) in W.  */
 
 int
-window_internal_height (w)
-     struct window *w;
+window_internal_height (struct window *w)
 {
   int ht = XFASTINT (w->total_lines);
 
@@ -4745,8 +4771,7 @@ window_internal_height (w)
    separating W from the sibling to its right.  */
 
 int
-window_box_text_cols (w)
-     struct window *w;
+window_box_text_cols (struct window *w)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   int width = XINT (w->total_cols);
@@ -4783,11 +4808,7 @@ window_box_text_cols (w)
    respectively.  */
 
 static void
-window_scroll (window, n, whole, noerror)
-     Lisp_Object window;
-     int n;
-     int whole;
-     int noerror;
+window_scroll (Lisp_Object window, int n, int whole, int noerror)
 {
   immediate_quit = 1;
 
@@ -4807,11 +4828,7 @@ window_scroll (window, n, whole, noerror)
    descriptions.  */
 
 static void
-window_scroll_pixel_based (window, n, whole, noerror)
-     Lisp_Object window;
-     int n;
-     int whole;
-     int noerror;
+window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
 {
   struct it it;
   struct window *w = XWINDOW (window);
@@ -4917,12 +4934,13 @@ window_scroll_pixel_based (window, n, whole, noerror)
   if (!NILP (Vscroll_preserve_screen_position))
     {
       /* We preserve the goal pixel coordinate across consecutive
-        calls to scroll-up or scroll-down.  This avoids the
+        calls to scroll-up, scroll-down and other commands that
+        have the `scroll-command' property.  This avoids the
         possibility of point becoming "stuck" on a tall line when
         scrolling by one line.  */
       if (window_scroll_pixel_based_preserve_y < 0
-         || (!EQ (current_kboard->Vlast_command, Qscroll_up)
-             && !EQ (current_kboard->Vlast_command, Qscroll_down)))
+         || !SYMBOLP (current_kboard->Vlast_command)
+         || NILP (Fget (current_kboard->Vlast_command, Qscroll_command)))
        {
          start_display (&it, w, start);
          move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
@@ -5156,11 +5174,7 @@ window_scroll_pixel_based (window, n, whole, noerror)
    See the comment of window_scroll for parameter descriptions.  */
 
 static void
-window_scroll_line_based (window, n, whole, noerror)
-     Lisp_Object window;
-     int n;
-     int whole;
-     int noerror;
+window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
 {
   register struct window *w = XWINDOW (window);
   register int opoint = PT, opoint_byte = PT_BYTE;
@@ -5182,8 +5196,8 @@ window_scroll_line_based (window, n, whole, noerror)
   if (!NILP (Vscroll_preserve_screen_position))
     {
       if (window_scroll_preserve_vpos <= 0
-         || (!EQ (current_kboard->Vlast_command, Qscroll_up)
-             && !EQ (current_kboard->Vlast_command, Qscroll_down)))
+         || !SYMBOLP (current_kboard->Vlast_command)
+         || NILP (Fget (current_kboard->Vlast_command, Qscroll_command)))
        {
          struct position posit
            = *compute_motion (startpos, 0, 0, 0,
@@ -5318,9 +5332,7 @@ window_scroll_line_based (window, n, whole, noerror)
    up.  This is the guts of Fscroll_up and Fscroll_down.  */
 
 static void
-scroll_command (n, direction)
-     Lisp_Object n;
-     int direction;
+scroll_command (Lisp_Object n, int direction)
 {
   int count = SPECPDL_INDEX ();
 
@@ -5547,8 +5559,7 @@ Returns nil, if selected window is not a minibuffer window.  */)
    as opposed to its height.  */
 
 static int
-displayed_window_lines (w)
-     struct window *w;
+displayed_window_lines (struct window *w)
 {
   struct it it;
   struct text_pos start;
@@ -5602,14 +5613,17 @@ displayed_window_lines (w)
 
 
 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
-       doc: /* Center point in selected window and redisplay frame.
+       doc: /* Center point in selected window and maybe redisplay frame.
 With prefix argument ARG, recenter putting point on screen line ARG
 relative to the selected window.  If ARG is negative, it counts up from the
 bottom of the window.  (ARG should be less than the height of the window.)
 
-If ARG is omitted or nil, erase the entire frame and then redraw with point
-in the center of the selected window.  If `auto-resize-tool-bars' is set to
-`grow-only', this resets the tool-bar's height to the minimum height needed.
+If ARG is omitted or nil, then recenter with point on the middle line of
+the selected window; if the variable `recenter-redisplay' is non-nil,
+also erase the entire frame and redraw it (when `auto-resize-tool-bars'
+is set to `grow-only', this resets the tool-bar's height to the minimum
+height needed); if `recenter-redisplay' has the special value `tty',
+then only tty frame 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.  */)
@@ -5629,16 +5643,22 @@ and redisplay normally--don't erase and redraw the frame.  */)
 
   if (NILP (arg))
     {
-      int i;
+      if (!NILP (Vrecenter_redisplay)
+         && (!EQ (Vrecenter_redisplay, Qtty)
+             || !NILP (Ftty_type (selected_frame))))
+       {
+         int i;
 
-      /* Invalidate pixel data calculated for all compositions.  */
-      for (i = 0; i < n_compositions; i++)
-       composition_table[i]->font = NULL;
+         /* Invalidate pixel data calculated for all compositions.  */
+         for (i = 0; i < n_compositions; i++)
+           composition_table[i]->font = NULL;
 
-      WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
+         WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
+
+         Fredraw_frame (WINDOW_FRAME (w));
+         SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
+       }
 
-      Fredraw_frame (WINDOW_FRAME (w));
-      SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
       center_p = 1;
     }
   else if (CONSP (arg)) /* Just C-u. */
@@ -5790,8 +5810,8 @@ DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
        doc: /* Return the height in lines of the text display area of WINDOW.
 WINDOW defaults to the selected window.
 
-The return value does neither include the mode line or header line, if
-any, nor any partial-height lines in the text display area.  */)
+The return value does not include the mode line, any header line, nor
+any partial-height lines in the text display area.  */)
      (window)
      Lisp_Object window;
 {
@@ -6284,8 +6304,7 @@ the return value is nil.  Otherwise the value is t.  */)
    by setting their buffers to nil.  */
 
 void
-delete_all_subwindows (w)
-     register struct window *w;
+delete_all_subwindows (register struct window *w)
 {
   if (!NILP (w->next))
     delete_all_subwindows (XWINDOW (w->next));
@@ -6311,8 +6330,7 @@ delete_all_subwindows (w)
 }
 \f
 static int
-count_windows (window)
-     register struct window *window;
+count_windows (register struct window *window)
 {
   register int count = 1;
   if (!NILP (window->next))
@@ -6329,10 +6347,7 @@ count_windows (window)
    Value is last index + 1.  */
 
 static int
-get_leaf_windows (w, flat, i)
-     struct window *w;
-     struct window **flat;
-     int i;
+get_leaf_windows (struct window *w, struct window **flat, int i)
 {
   while (w)
     {
@@ -6355,8 +6370,7 @@ get_leaf_windows (w, flat, i)
    can be returned.  */
 
 struct glyph *
-get_phys_cursor_glyph (w)
-     struct window *w;
+get_phys_cursor_glyph (struct window *w)
 {
   struct glyph_row *row;
   struct glyph *glyph;
@@ -6375,10 +6389,7 @@ get_phys_cursor_glyph (w)
 
 
 static int
-save_window_save (window, vector, i)
-     Lisp_Object window;
-     struct Lisp_Vector *vector;
-     int i;
+save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
 {
   register struct saved_window *p;
   register struct window *w;
@@ -6536,8 +6547,7 @@ usage: (save-window-excursion BODY...)  */)
  ***********************************************************************/
 
 static Lisp_Object
-window_tree (w)
-     struct window *w;
+window_tree (struct window *w)
 {
   Lisp_Object tail = Qnil;
   Lisp_Object result = Qnil;
@@ -6904,10 +6914,7 @@ If PIXELS-P is non-nil, the return value is VSCROLL.  */)
    additional argument USER_DATA.  Stops when FN returns 0.  */
 
 void
-foreach_window (f, fn, user_data)
-     struct frame *f;
-     int (* fn) P_ ((struct window *, void *));
-     void *user_data;
+foreach_window (struct frame *f, int (*fn) (struct window *, void *), void *user_data)
 {
   /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil.  */
   if (WINDOWP (FRAME_ROOT_WINDOW (f)))
@@ -6921,10 +6928,7 @@ foreach_window (f, fn, user_data)
    Stop when FN returns 0.  Value is 0 if stopped by FN.  */
 
 static int
-foreach_window_1 (w, fn, user_data)
-     struct window *w;
-     int (* fn) P_ ((struct window *, void *));
-     void *user_data;
+foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *user_data)
 {
   int cont;
 
@@ -6949,9 +6953,7 @@ foreach_window_1 (w, fn, user_data)
    the window start.  */
 
 static int
-freeze_window_start (w, freeze_p)
-     struct window *w;
-     void *freeze_p;
+freeze_window_start (struct window *w, void *freeze_p)
 {
   if (MINI_WINDOW_P (w)
       || (WINDOWP (selected_window) /* Can be nil in corner cases.  */
@@ -6971,9 +6973,7 @@ freeze_window_start (w, freeze_p)
    means freeze the window start.  */
 
 void
-freeze_window_starts (f, freeze_p)
-     struct frame *f;
-     int freeze_p;
+freeze_window_starts (struct frame *f, int freeze_p)
 {
   foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
 }
@@ -6987,9 +6987,7 @@ freeze_window_starts (f, freeze_p)
    describe the same state of affairs.  This is used by Fequal.  */
 
 int
-compare_window_configurations (c1, c2, ignore_positions)
-     Lisp_Object c1, c2;
-     int ignore_positions;
+compare_window_configurations (Lisp_Object c1, Lisp_Object c2, int ignore_positions)
 {
   register struct save_window_data *d1, *d2;
   struct Lisp_Vector *sw1, *sw2;
@@ -7115,7 +7113,7 @@ and scrolling positions.  */)
 }
 \f
 void
-init_window_once ()
+init_window_once (void)
 {
   struct frame *f = make_initial_frame ();
   XSETFRAME (selected_frame, f);
@@ -7128,41 +7126,47 @@ init_window_once ()
 }
 
 void
-init_window ()
+init_window (void)
 {
   Vwindow_list = Qnil;
 }
 
 void
-syms_of_window ()
+syms_of_window (void)
 {
-  Qscroll_up = intern ("scroll-up");
+  Qscroll_up = intern_c_string ("scroll-up");
   staticpro (&Qscroll_up);
 
-  Qscroll_down = intern ("scroll-down");
+  Qscroll_down = intern_c_string ("scroll-down");
   staticpro (&Qscroll_down);
 
-  Qwindow_size_fixed = intern ("window-size-fixed");
+  Qscroll_command = intern_c_string ("scroll-command");
+  staticpro (&Qscroll_command);
+
+  Fput (Qscroll_up, Qscroll_command, Qt);
+  Fput (Qscroll_down, Qscroll_command, Qt);
+
+  Qwindow_size_fixed = intern_c_string ("window-size-fixed");
   staticpro (&Qwindow_size_fixed);
   Fset (Qwindow_size_fixed, Qnil);
 
   staticpro (&Qwindow_configuration_change_hook);
   Qwindow_configuration_change_hook
-    = intern ("window-configuration-change-hook");
+    = intern_c_string ("window-configuration-change-hook");
 
-  Qwindowp = intern ("windowp");
+  Qwindowp = intern_c_string ("windowp");
   staticpro (&Qwindowp);
 
-  Qwindow_configuration_p = intern ("window-configuration-p");
+  Qwindow_configuration_p = intern_c_string ("window-configuration-p");
   staticpro (&Qwindow_configuration_p);
 
-  Qwindow_live_p = intern ("window-live-p");
+  Qwindow_live_p = intern_c_string ("window-live-p");
   staticpro (&Qwindow_live_p);
 
-  Qdisplay_buffer = intern ("display-buffer");
+  Qdisplay_buffer = intern_c_string ("display-buffer");
   staticpro (&Qdisplay_buffer);
 
-  Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
+  Qtemp_buffer_show_hook = intern_c_string ("temp-buffer-show-hook");
   staticpro (&Qtemp_buffer_show_hook);
 
   staticpro (&Vwindow_list);
@@ -7231,7 +7235,9 @@ at the scroll margin or window boundary respectively.
 A value of t means point keeps its screen position if the scroll
 command moved it vertically out of the window, e.g. when scrolling
 by full screens.
-Any other value means point always keeps its screen position.  */);
+Any other value means point always keeps its screen position.
+Scroll commands should have the `scroll-command' property
+on their symbols to be controlled by this variable.  */);
   Vscroll_preserve_screen_position = Qnil;
 
   DEFVAR_LISP ("window-point-insertion-type", &Vwindow_point_insertion_type,
@@ -7246,6 +7252,13 @@ selected; while the global part is run only once for the modified frame,
 with the relevant frame selected.  */);
   Vwindow_configuration_change_hook = Qnil;
 
+  DEFVAR_LISP ("recenter-redisplay", &Vrecenter_redisplay,
+              doc: /* If non-nil, then the `recenter' command with a nil argument
+will redraw the entire frame; the special value `tty' causes the
+frame to be redrawn only if it is a tty frame.  */);
+  Vrecenter_redisplay = Qtty;
+
+
   defsubr (&Sselected_window);
   defsubr (&Sminibuffer_window);
   defsubr (&Swindow_minibuffer_p);
@@ -7263,8 +7276,10 @@ with the relevant frame selected.  */);
   defsubr (&Sset_window_redisplay_end_trigger);
   defsubr (&Swindow_edges);
   defsubr (&Swindow_pixel_edges);
+  defsubr (&Swindow_absolute_pixel_edges);
   defsubr (&Swindow_inside_edges);
   defsubr (&Swindow_inside_pixel_edges);
+  defsubr (&Swindow_inside_absolute_pixel_edges);
   defsubr (&Scoordinates_in_window_p);
   defsubr (&Swindow_at);
   defsubr (&Swindow_point);
@@ -7326,7 +7341,7 @@ with the relevant frame selected.  */);
 }
 
 void
-keys_of_window ()
+keys_of_window (void)
 {
   initial_define_key (control_x_map, '1', "delete-other-windows");
   initial_define_key (control_x_map, '2', "split-window");
@@ -7336,12 +7351,9 @@ keys_of_window ()
   initial_define_key (control_x_map, '<', "scroll-left");
   initial_define_key (control_x_map, '>', "scroll-right");
 
-  initial_define_key (global_map, Ctl ('V'), "scroll-up");
+  initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
   initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
-  initial_define_key (meta_map, 'v', "scroll-down");
-
-  initial_define_key (global_map, Ctl('L'), "recenter");
-  initial_define_key (meta_map, 'r', "move-to-window-line");
+  initial_define_key (meta_map, 'v', "scroll-down-command");
 }
 
 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f