diff lisp/packages/scroll-in-place.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children b82b59fe008d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/packages/scroll-in-place.el	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,1561 @@
+
+;;;; -*-Emacs-Lisp-*- Improved Vertical Scrolling Commands
+;;;; Written by Eric Eide, last modified on 1994/11/18 21:23:01.
+;;;; (C) Copyright 1993, 1994, Eric Eide and the University of Utah
+;;;;
+;;;; COPYRIGHT NOTICE
+;;;;
+;;;; This program 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 2 of the License, or (at your option)
+;;;; any later version.
+;;;;
+;;;; This program is distributed in the hope that it will be useful, but
+;;;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;;;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+;;;; for more details.
+;;;;
+;;;; You should have received a copy of the GNU General Public License along
+;;;; with GNU Emacs.  If you did not, write to the Free Software Foundation,
+;;;; Inc., 675 Mass Ave., Cambridge, MA 02139, USA.
+
+;;; Synched up with: Not in FSF.
+
+;;;; AUTHORS
+;;;;
+;;;; This package was written by Eric Eide (eeide@cs.utah.edu) and was based on
+;;;; a very similar package ("scroll-fix") by Joe Wells.  Almost all of the
+;;;; code in this file is original, but I owe a great debt to Mr. Wells for his
+;;;; ideas and his original implementation.
+;;;;
+;;;;   Eric Eide (eeide@cs.utah.edu)
+;;;;   University of Utah
+;;;;   3190 Merrill Engineering Building
+;;;;   Salt Lake City, Utah  84112
+;;;;
+;;;;   Joe Wells (jbw@cs.bu.edu)
+;;;;
+;;;; Joe Wells' "scroll-fix" package is Copyright (C) 1988, 1989, and 1991 by
+;;;; the Free Software Foundation.  It is distributed under the terms of the
+;;;; GNU General Public License.
+
+;;;; LISP CODE DIRECTORY INFORMATION
+;;;;
+;;;; LCD Archive Entry:
+;;;; scroll-in-place|Eric Eide|eeide@cs.utah.edu|
+;;;; Improved vertical scrolling commands|
+;;;; 1994/11/18 21:23:01|1.3|~/misc/scroll-in-place.el.Z|
+
+;;;; SUMMARY
+;;;;
+;;;; This package provides improved vertical scrolling commands for GNU Emacs.
+;;;; These new commands offer the following features:
+;;;;
+;;;; + When a scrolling command is executed, GNU Emacs tries to keep point as
+;;;;   close as possible to its original window position (window line and
+;;;;   column).  This is what "scroll in place" means: point stays "in place"
+;;;;   within the window.  (There are times when point must be moved from its
+;;;;   original window position in order to execute the scroll; see below.)
+;;;;
+;;;;   The variable `scroll-in-place', which is true by default, determines
+;;;;   whether or not the standard GNU Emacs scrolling commands (`scroll-down',
+;;;;   `scroll-up', `scroll-other-window-down', and `scroll-other-window') use
+;;;;   the "in place" features listed here.  When `scroll-in-place' is `nil'
+;;;;   the standard GNU Emacs scrolling commands essentially just call the
+;;;;   original versions of themselves.  (Note that even when `scroll-in-place'
+;;;;   is `nil' the new versions of `scroll-down' and `scroll-up' have slightly
+;;;;   different behavior when a minibuffer window is the selected window.  See
+;;;;   below.)
+;;;;
+;;;;   It is possible to turn off (or turn on) "in place" scrolling for certain
+;;;;   buffers by making buffer-local bindings of the variable `scroll-in-
+;;;;   place' for those buffers.  The variable `scroll-in-place' is not usually
+;;;;   buffer-local, but you can make it so if you desire.
+;;;;
+;;;; + Because the improved scrolling commands keep point at its original
+;;;;   window position, these scrolling commands are "reversible."  The
+;;;;   `scroll-up' command undoes the effect of the immediately previous
+;;;;   `scroll-down' command (if any) and vice versa.  In other words, if you
+;;;;   scroll up and then immediately scroll back down, the window config-
+;;;;   uration is restored to its exact original state.  This allows you to
+;;;;   browse through a buffer more easily, as you can always get back to the
+;;;;   original configuration.
+;;;;
+;;;;   Note, however, that the improved scrolling commands are guaranteed to be
+;;;;   reversible only if there are no intervening non-scrolling commands.
+;;;;   Also, if you give a prefix argument to a scrolling command (in order to
+;;;;   specify the number of lines to scroll by), previous scrolling commands
+;;;;   may no longer be reversible.  More specifically, if the new prefix
+;;;;   argument has a different magnitude than the previous scrolling distance,
+;;;;   then any previous scrolling commands are not reversible.  The new prefix
+;;;;   argument takes precedence.
+;;;;
+;;;;   You might find it useful to think of the scrolling commands as forming
+;;;;   "chains."  A scrolling command either starts or continues a chain.  By
+;;;;   issuing a non-scrolling command or by changing the number of lines to be
+;;;;   scrolled, you break the chain.  (Note that simply changing the scrolling
+;;;;   direction won't break the chain; changing the absolute number of lines
+;;;;   to be scrolled is what breaks the chain.)  Scrolling commands are
+;;;;   guaranteed to be reversible only within the current chain.  Hopefully
+;;;;   that's clear enough.
+;;;;
+;;;; + When a scrolling command is given a prefix argument (which specifies the
+;;;;   number of lines to scroll by), then that argument becomes the default
+;;;;   scrolling distance for all immediately subsequent scrolling commands.
+;;;;   This means that you can easily set the scrolling distance for a chain
+;;;;   of scrolling commands.  Note that a new prefix argument or any non-
+;;;;   scrolling command breaks the chain (as described above), and any further
+;;;;   scrolling commands will use the usual defaults (or the prefix argument
+;;;;   you specify at that time, of course).
+;;;;
+;;;;   However, there are cases in which one doesn't want the current scrolling
+;;;;   command to use the default scrolling distance that was set by the
+;;;;   previous scrolling command.  For example, suppose that you had special
+;;;;   commands that scrolled one line up and one line down.  When you invoke
+;;;;   one of these commands, the "in place" scrolling routines set the default
+;;;;   scrolling distance to be just one line.  Now suppose that you use one of
+;;;;   your special commands and then immediately invoke `scroll-up' (`C-v'),
+;;;;   expecting it to scroll by a near windowful of text.  You would be
+;;;;   disappointed --- because the previous command set the default scrolling
+;;;;   distance to be just one line, `scroll-up' just scrolls by one line.
+;;;;
+;;;;   To solve this problem, "scroll-in-place" allows you to divide scrolling
+;;;;   commands into separate "groups."  Commands in a group can only form
+;;;;   chains with (and therefore, inherit defaults from) commands in the same
+;;;;   group.  (Note that no command can be in more than one group.)  If you
+;;;;   invoke a scrolling command that is not in the same group as that of the
+;;;;   immediately previous scrolling command, then the previous chain is
+;;;;   broken and you start a new chain --- with a new set of defaults.
+;;;;
+;;;;   So to solve the problem described above, you could put your one-line
+;;;;   scrolling commands in their own group.  Once that is done, the standard
+;;;;   scrolling commands will not form chains with your one-line scrolling
+;;;;   commands, and therefore will not use the default scrolling distance set
+;;;;   by those commands.  Problem solved!
+;;;;
+;;;;   By default, all "in place" scrolling commands are in a single group.  If
+;;;;   you want to partition some commands into separate groups, you must do
+;;;;   that yourself *before* any "in place" commands are invoked.  For more
+;;;;   information about grouping commands, see the documentation for the
+;;;;   variables `scroll-command-groups' and `scroll-default-command-group'.
+;;;;
+;;;; + The improved scrolling commands will avoid displaying empty lines past
+;;;;   the end of the buffer when possible.  In other words, just as you can't
+;;;;   see "dead space" before the beginning of the buffer text, the new
+;;;;   scrolling commands try to avoid displaying "dead space" past the end of
+;;;;   the buffer text.  This behavior is somewhat configurable; see the
+;;;;   documentation for the variable `scroll-allow-blank-lines-past-eob'.
+;;;;
+;;;;   Dead space will be displayed if it is necessary in order to make a
+;;;;   previous scrolling action reversible, however.
+;;;;
+;;;; + If the scrolling commands cannot keep point at its initial window
+;;;;   position (because a buffer boundary is on screen and the window can't be
+;;;;   scrolled as far as necessary to keep point at the right place), point is
+;;;;   allowed to temporarily stray from its initial window position.  That is,
+;;;;   point moves the correct number of window lines, even if it means that it
+;;;;   has to stray from its desired window position.  This straying is undone
+;;;;   when (and if) the scrolling action is reversed.
+;;;;
+;;;; + If a scrolling command tries to move point past a buffer boundary, point
+;;;;   is instead moved to the boundary (the beginning or the end of the buffer
+;;;;   as appropriate) and an appropriate message is displayed.  This motion is
+;;;;   reversible, of course.
+;;;;
+;;;;   However, if point was already at the buffer boundary when the scrolling
+;;;;   command was invoked, the command signals an appropriate error instead.
+;;;;
+;;;; + When a minibuffer window is the selected window, the new versions of
+;;;;   `scroll-up' and `scroll-down' either scroll the window in the variable
+;;;;   `minibuffer-scroll-window' (which is usually the window of completions)
+;;;;   or the `next-window' if there is no `minibuffer-scroll-window'.  This is
+;;;;   usually much more useful than scrolling the minibuffer itself.  (Note
+;;;;   that this feature is available even when the variable `scroll-in-place'
+;;;;   is `nil'.)
+;;;;
+;;;; + When a scrolling command is scrolling a window other than the selected
+;;;;   window, it will signal an appropriate buffer boundary error if the
+;;;;   window cannot be scrolled (because the appropriate buffer boundary is
+;;;;   already visible).  This means that an error is signalled even in cases
+;;;;   that would be allowed (by "straying" point or by moving it to the buffer
+;;;;   boundary) if the window were selected.
+;;;;
+;;;;   (If an error were not signalled in these cases, then there would be many
+;;;;   cases in which the last scroll in a particular direction would appear to
+;;;;   do nothing because only the point position would change --- the
+;;;;   displayed text would stay the same!  To avoid these cases the scrolling
+;;;;   commands signal boundary errors "prematurely" when the window to be
+;;;;   scrolled is not selected.)
+;;;;
+;;;; So how is this package different than Joe Wells' "scroll-fix" package?
+;;;;
+;;;; + This package provides "in place" behavior for the standard GNU Emacs
+;;;;   commands by default; "scroll-fix" does not.
+;;;;
+;;;; + "scroll-fix" behaves differently when the window is near a buffer
+;;;;   boundary.  Instead of allowing point to stray, "scroll-fix" first does
+;;;;   an incomplete scroll (i.e., moves point less than the full distance in
+;;;;   order to keep point at the desired window position) and then pops point
+;;;;   to the buffer boundary.  I think that the behavior of this package is
+;;;;   somewhat move intuitive, especially for small scrolling distances.
+;;;;
+;;;; + The scrolling commands in this package will appropriately signal buffer
+;;;;   boundary errors; the commands in "scroll-fix" never signal boundary
+;;;;   errors.  This makes it difficult to allow "scroll-fix" to replace the
+;;;;   standard `scroll-down' and `scroll-up' commands because some other
+;;;;   packages (e.g., VM and GNUS) expect the scrolling commands to signal
+;;;;   these errors as necessary.
+;;;;
+;;;; + This package handles long lines correctly.  (But see PROBLEMS, below.)
+;;;;
+;;;; + "scroll-fix" handles prefix arguments differently.  In "scroll-fix", a
+;;;;   number-containing prefix argument always breaks any running chain of
+;;;;   scrolling commands.  The prefix argument `-' (the symbol minus,
+;;;;   generated by `C-u -') causes a temporary change in direction --- a
+;;;;   change for only the current command.  In this package, however, a
+;;;;   number-containing prefix argument only breaks a running chain if it has
+;;;;   a different magnitude than the default scrolling distance, and the
+;;;;   prefix argument `-' causes a permanent change in the sign of the default
+;;;;   scrolling distance --- a change visible to immediately subsequent
+;;;;   scrolling commands.
+;;;;
+;;;; + This package keeps track of the set of "in place" scrolling commands
+;;;;   dynamically, in order to detect "chains" of scrolling commands.
+;;;;   "scroll-fix" has a fixed list of scrolling commands, so "scroll-fix"
+;;;;   cannot keep track of some chains.  (Again, "scroll-fix" interacts badly
+;;;;   with VM and GNUS.)  And because "scroll-fix" keeps a static list of
+;;;;   scrolling commands, it is a bad idea to call its "in place" commands
+;;;;   from a program.  This package, because it maintains the information
+;;;;   dynamically, has no such problems.
+;;;;
+;;;; + This package allows one to divide the "in place" scrolling commands into
+;;;;   groups; a command in a group only forms chains with the members of its
+;;;;   group.  "scroll-fix" has no notion of command groups.
+;;;;
+;;;; + This package provides "in place" versions of the standard GNU Emacs
+;;;;   commands `scroll-other-window-down' and `scroll-other-window'.
+;;;;
+;;;; + This package will refuse to scroll non-selected windows (by signalling
+;;;;   an error) when the displayed text would not change, as described in the
+;;;;   feature list above.
+;;;;
+;;;; + When a minibuffer window is selected, this package always scrolls a
+;;;;   window other than the minibuffer.  "scroll-fix" will scroll another
+;;;;   window only if the entire minibuffer contents are visible.
+;;;;
+;;;; + "scroll-fix" provides a command to toggle the "in place" behavior of the
+;;;;   standard GNU Emacs commands.  This package doesn't; you'll have to set
+;;;;   the option manually with the command `set-variable'.
+;;;;
+;;;; + This package has gratuitous variable renaming (insert smile here!):
+;;;;
+;;;;   "scroll-fix" user variable            Equivalent in this package
+;;;;   -----------------------------------------------------------------------
+;;;;   scroll-in-place                       (none)
+;;;;   scroll-in-place-replace-original      scroll-in-place
+;;;;   scroll-in-place-eob-blank-allowed     scroll-allow-blank-lines-past-eob
+;;;;
+;;;; + This package allows programmers to specify the default scrolling
+;;;;   distance (i.e., the default distance used when starting a new chain of
+;;;;   scrolling commands) for custom scrolling commands.
+
+;;;; COMMANDS AND FUNCTIONS
+;;;;
+;;;; This package provides the following "in place" versions of GNU Emacs'
+;;;; standard vertical scrolling commands:
+;;;;
+;;;;   scroll-down-in-place
+;;;;   scroll-up-in-place
+;;;;   scroll-other-window-down-in-place
+;;;;   scroll-other-window-in-place
+;;;;
+;;;; The variable `scroll-in-place', which is true by default, determines
+;;;; whether or not the new versions of the standard GNU Emacs scrolling
+;;;; commands (`scroll-down', `scroll-up', `scroll-other-window-down', and
+;;;; `scroll-other-window') use the "in place" features listed above.  When
+;;;; `scroll-in-place' is `nil' the standard GNU Emacs scrolling commands
+;;;; essentially just call the original versions of themselves.  (Note that
+;;;; even when `scroll-in-place' is `nil' the new versions of `scroll-down' and
+;;;; `scroll-up' have slightly different behavior when a minibuffer window is
+;;;; the selected window.  See the feature list above.)
+;;;;
+;;;; NOTE that this package redefines the standard GNU Emacs commands `scroll-
+;;;; down', `scroll-up', `scroll-other-window-down', and `scroll-other-window'
+;;;; (in order to check the variable `scroll-in-place', as described above).
+;;;; The command `scroll-other-window-down' first appeared as a standard
+;;;; command in the FSF's GNU Emacs 19.26.
+;;;;
+;;;; This package also provides the following functions and variables which are
+;;;; of use to programmers:
+;;;;
+;;;;   scroll-window
+;;;;   scroll-window-in-place
+;;;;   scroll-window-in-place-continue-sequence
+;;;;   scroll-default-lines (variable)
+;;;;   scroll-command-groups (variable)
+;;;;
+;;;; The `scroll-window-in-place' function is the heart of the "in place"
+;;;; scrolling commands.  `scroll-window' is a function that checks the
+;;;; variable `scroll-in-place' and calls the appropriate scrolling function
+;;;; (either `scroll-window-in-place' or one of the original versions of
+;;;; `scroll-down' and `scroll-up').  The function `scroll-window-in-place-
+;;;; continue-sequence' is provided in order to preserve running "chains" of
+;;;; scrolling commands as described above.
+;;;;
+;;;; The variable `scroll-default-lines' determines the default scrolling
+;;;; distance when a new chain of "in place" scrolling commands begins.  If
+;;;; this variable is not a number, then the default distance is the height of
+;;;; the window to be scrolled minus `next-screen-context-lines'.  The variable
+;;;; `scroll-command-groups' contains the explicit groups of "in place"
+;;;; scrolling commands; for more information read the variable documentation.
+
+;;;; YOUR .EMACS FILE
+;;;;
+;;;; To use this package, you simply need to load it from within your ".emacs"
+;;;; file:
+;;;;
+;;;;   (require 'scroll-in-place)
+;;;;
+;;;; By default, this package provides for the standard GNU Emacs vertical
+;;;; scrolling commands (`scroll-down', `scroll-up', `scroll-other-window-
+;;;; down', and `scroll-other-window') to use the "in place" features.  If you
+;;;; would rather not have this, set the variable `scroll-in-place' to `nil':
+;;;;
+;;;;   (setq scroll-in-place nil)
+;;;;
+;;;; When `scroll-in-place' is `nil' you will have to bind keys in order to
+;;;; call the "in place" scrolling commands.  For example, you might want to do
+;;;; the following:
+;;;;
+;;;;   (global-set-key "\M-v" 'scroll-down-in-place)
+;;;;   (global-set-key "\C-v" 'scroll-up-in-place)
+;;;;
+;;;; Sun users should also read the PROBLEMS section, below.
+;;;;
+;;;; ADVANCED CUSTOMIZATION
+;;;;
+;;;; If you want to partition certain "in place" scrolling commands into
+;;;; separate groups, you should do something like the following:
+;;;;
+;;;;   ;; Make one group containing the commands `scroll-down-one-line' and
+;;;;   ;; `scroll-up-one-line'.  (These are not standard GNU Emacs commands.)
+;;;;   (setq scroll-command-groups
+;;;;         (list '(scroll-down-one-line scroll-up-one-line)))
+;;;;
+;;;; You could write the `scroll-down-one-line' command like this:
+;;;;
+;;;;   (defun scroll-down-one-line (arg)
+;;;;     "Scroll down one line, or number of lines specified by prefix arg."
+;;;;     (interactive "P")
+;;;;     (let ((scroll-default-lines 1))
+;;;;       (scroll-down-in-place arg)))
+;;;;
+;;;; If you want to disable "in place" scrolling for windows that display a
+;;;; particular buffer (while leaving it available in other windows), you can
+;;;; make `scroll-in-place' a buffer-local variable for that buffer and then
+;;;; bind that local copy of `scroll-in-place' to `nil'.  This is the kind of
+;;;; thing that one generally does in a major mode hook.  For example, you can
+;;;; disable "in place" scrolling of GNUS article windows with the following
+;;;; code:
+;;;;
+;;;;   (setq gnus-article-mode-hook
+;;;;         (function (lambda ()
+;;;;                     (make-local-variable 'scroll-in-place)
+;;;;                     (setq scroll-in-place nil))))
+;;;;   ;; Set the variable `gnus-Article-mode-hook' instead if you are using
+;;;;   ;; an old version of GNUS, say version 3.13 or 3.14.
+;;;;
+;;;; The variable `scroll-allow-blank-lines-past-eob' can also be made local to
+;;;; particular buffers, if you desire.  (But why would you want to do that?)
+
+;;;; PROBLEMS
+;;;;
+;;;; + It is sometimes difficult for one's eyes to follow an incomplete scroll
+;;;;   (i.e., a scroll in which the text doesn't move as far as one expected),
+;;;;   especially when the scrolled window is not selected (and therefore that
+;;;;   window's point is not highlighted).  One can lose one's place in the
+;;;;   text.
+;;;;
+;;;; + The names `scroll-down-in-place' and `scroll-up-in-place' conflict with
+;;;;   two commands in the GNU Emacs terminal-specific file "term/sun.el".
+;;;;   This means that in order to load this package correctly, Sunterm users
+;;;;   will have to use the hook `term-setup-hook'.  For example, you might put
+;;;;   the following form in your ".emacs" file:
+;;;;
+;;;;   (setq term-setup-hook (function (lambda () (require 'scroll-in-place))))
+;;;;
+;;;;   If this is confusing, get help from your local GNU Emacs guru.
+;;;;
+;;;; + `scroll-determine-goal-column' tries to honor the variable `track-eol'
+;;;;   if it is set.  But when lines are being wrapped we can't move point past
+;;;;   the wrap --- or else it is possible that scrolling won't work correctly.
+;;;;   In short, this package honors `track-eol' as best it can.
+;;;;
+;;;; + `scroll-window-in-place' can become confused when something changes the
+;;;;   window "out from under it."  By "confused" I mean that it is possible
+;;;;   for `scroll-window-in-place' to think that it should continue the
+;;;;   running sequence of "in place" scrolls when it should really probably
+;;;;   start a new sequence.  For example, if a process filter inserts text
+;;;;   into the buffer and moves point, `scroll-window-in-place' loses track of
+;;;;   where point should be and where the window should start.  Commands that
+;;;;   call a "scroll in place" function and then subsequently move point can
+;;;;   also confuse `scroll-window-in-place'.
+;;;;
+;;;;   To correct some of this confusion, `scroll-window-in-place' could keep
+;;;;   track of the final positions of `window-start' and `window-point',
+;;;;   possibly with both markers and character positions.  In my experience
+;;;;   the "in place" scrolling commands are almost never confused (except by
+;;;;   fancy packages that do their own fancy kinds of scrolling, as described
+;;;;   below), so the extra sanity checking isn't worth the effort.  If your
+;;;;   mileage varies let me know.
+;;;;
+;;;; + The "in place" scrolling commands can interact poorly with packages that
+;;;;   provide their own special scrolling commands.  For example, there are
+;;;;   varying degrees of conflict with Rmail, VM, and GNUS.
+;;;;
+;;;;   RMAIL
+;;;;
+;;;;   In the version of Rmail that is part of the FSF's GNU Emacs 19 (19.25
+;;;;   through 19.28 at least), the command `rmail-summary-scroll-msg-down' in
+;;;;   the file "rmailsum.el" fails to work properly when "in place" scrolling
+;;;;   is enabled for the Rmail message buffer.  (The source of the conflict:
+;;;;   the "in place" scrolling commands and Emacs' standard scrolling commands
+;;;;   interpret the argument '- in different ways.)  Fortunately it is easy to
+;;;;   patch Rmail.  Send me mail if you would like to receive a copy of these
+;;;;   patches.
+;;;;
+;;;;   I know of no conflicts between the "in place" scrolling commands and
+;;;;   older versions of Rmail (i.e., versions that came with GNU Emacs 18).
+;;;;
+;;;;   VM
+;;;;
+;;;;   `scroll-window-in-place' is *very* confused by VM 5's message scrolling
+;;;;   commands, especially because VM 5 rebuilds Emacs' window configuration
+;;;;   from scratch so often.  I have written an experimental set of patches
+;;;;   for VM 5.70 that allows VM 5 to use the "scroll-in-place" features; send
+;;;;   me mail if you would like to receive a copy of these patches.  I hope
+;;;;   that someday my patches will be incorporated into VM.
+;;;;
+;;;;   `scroll-window-in-place' is not confused by VM 4.41's message scrolling
+;;;;   commands, however.
+;;;;
+;;;;   GNUS
+;;;;
+;;;;   `scroll-window-in-place' can be *slightly* confused by GNUS' article
+;;;;   scrolling commands because they move point to the last line of the
+;;;;   article window and then scroll the text.  (This is the case for at least
+;;;;   GNUS versions 3.13 through 4.1, inclusive.)  The potential conflict is
+;;;;   so minor, however, that you'll probably never notice it.  I never do.
+;;;;
+;;;;   A severe conflict, however, exists between the "in place" scrolling
+;;;;   commands and the add-on "gnus-hide" package.  "gnus-hide" can elide
+;;;;   signatures at the ends of articles but it does so in a way that causes
+;;;;   `scroll-window-in-place', as invoked by the GNUS scrolling commands, not
+;;;;   to signal end-of-buffer conditions at the right times.  Someday I may
+;;;;   write new article scrolling commands for GNUS.
+;;;;
+;;;; + Process filters that call scrolling functions can cause confusion.  They
+;;;;   may break running chains of "in place" scrolling commands and they may
+;;;;   set up inappropriate defaults for future scrolling commands.  Maybe this
+;;;;   is a moot problem, as I am currently unaware of any process filters that
+;;;;   invoke scrolling commands (although many filters move point around,
+;;;;   which will also confuse `scroll-window-in-place').
+
+;; (provide 'scroll-in-place) at the end of this file.
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;
+;;;; Here are the variable declarations, both user options and internal
+;;;; variables.
+;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar scroll-in-place t
+  "*When this variable is true (i.e., non-`nil'), the standard GNU Emacs
+vertical scrolling commands `scroll-down', `scroll-up', `scroll-other-window-
+down', and `scroll-other-window' will attempt to keep point at its current
+position in the window (window line and column).  In other words, point stays
+\"in place\" within the window.
+
+When this variable is `nil' the standard GNU Emacs vertical scrolling commands
+behave as usual.  The \"in place\" equivalents, however, are still available as
+separate commands.
+
+This variable may be made buffer-local in order to disable (or enable) \"in
+place\" scrolling in particular buffers."
+  ;; I have thought about dividing `scroll-in-place' into three variables: a
+  ;; list of commands that always scroll in place, a list of commands that
+  ;; never scroll in place, and a flag that determines the default behavior of
+  ;; other scrolling commands.  This could make it easier to make "in place"
+  ;; scrolling the default because one could single out certain ill-behaved
+  ;; commands.  But as of now I'm sure that the added complexity would really
+  ;; be worth it.
+  )
+
+(defvar scroll-allow-blank-lines-past-eob nil
+  "*When this variable is `nil' the \"in place\" scrolling commands will avoid
+displaying empty lines past the end of the buffer text.  In other words, just
+as you can't see \"dead space\" before the beginning of the buffer text, the
+\"in place\" scrolling commands try to avoid displaying \"dead space\" past the
+end of the buffer text.  This helps make the most of window real estate.
+
+Note that sometimes it is necessary to display \"dead space\" in order to make
+a previous scrolling action reversible.
+
+When this variable is non-`nil' the \"in place\" scrolling commands will always
+allow blank lines to be shown past the end of the buffer.")
+
+;;;;
+;;;; The following variables are not user options, but are intended to be set
+;;;; by code outside this package.
+;;;;
+
+(defvar scroll-default-lines nil
+  "The default number of lines to be scrolled by when a new sequence of \"in
+place\" scrolling commands begins.  Of course, when an explicit number of lines
+is specified, that explicit number takes precedence.  See the documentation for
+the function `scroll-window-in-place' for more information.
+
+If this variable is not bound to a number, then the default number of lines is
+the height of the window to be scrolled minus `next-screen-context-lines'.
+
+This variable should not be set globally!  Commands that want to specify a
+default scrolling distance should just bind the variable `scroll-default-lines'
+temporarily.")
+
+(defvar scroll-command-groups nil
+  "The explicitly specified \"groups\" of \"in place\" scrolling commands.
+This variable should be set before or immediately after the \"in place\"
+scrolling package is loaded, and then not changed after that.
+
+Usually, \"in place\" scrolling commands share state (e.g., the number of lines
+to scroll by) with any and all immediately previous \"in place\" scrolling
+commands.  Sometimes, however, this is undesirable.  In these cases the \"in
+place\" scrolling commands can be divided into groups.  A command in a group
+only shares state with members of its group.
+
+Each element of `scroll-command-groups' is a list that contains all of the
+members of a unique command group.  For example, if there were only one
+explicit group and that group contained the commands `scroll-down-one-line' and
+`scroll-up-one-line', then `scroll-command-groups' would be set to:
+
+  ((scroll-down-one-line scroll-up-one-line))
+
+Commands that are not in any explicitly specified group are added to a default
+group.  That group is stored in the variable `scroll-default-command-group'.
+
+The \"in place\" scrolling functions assume that all of the scrolling command
+groups are nonintersecting (i.e., no command is in more than one group) and
+only contain \"in place\" scrolling commands.")
+
+;;;;
+;;;; The variables below this point are internal to this package.
+;;;;
+
+(defvar scroll-default-command-group nil
+  "The set of \"in place\" scrolling commands that are not members of any
+explicitly defined group of commands.  This set of commands is an implicitly
+defined group, constructed as \"in place\" commands are invoked, and members of
+this group share state among themselves.  See the documentation for the
+variable `scroll-command-groups' for more information.")
+
+(defvar scroll-initially-displayed-lines 0
+  "The number of window lines that contained buffer text when the current
+sequence of \"in place\" scrolling commands started.  Unless the variable
+`scroll-in-place-allow-blank-lines-past-eob' is true, the \"in place\"
+scrolling commands ensure that at least this many text lines are visible at all
+times.")
+
+(defvar scroll-previous-window nil
+  "The window that was most recently scrolled by an \"in place\" scrolling
+command.")
+
+(defvar scroll-previous-lines 0
+  "The number of window lines that the previous \"in place\" scrolling command
+attempted to scroll.")
+
+(defvar scroll-goal-column 0
+  "The desired horizontal window position for point, used by the \"in place\"
+scrolling commands.")
+
+(defvar scroll-boundary-previous-point nil
+  "The value of point before point was moved to a buffer boundary.")
+
+(defvar scroll-boundary-previous-lines 0
+  "The number of lines that point moved when it moved to a buffer boundary.")
+
+(defvar scroll-boundary-error-command nil
+  "The value of `this-command' when an \"in place\" scrolling command signalled
+a buffer boundary error.  This is used to decide how subsequent scrolling
+commands should recover from the error.")
+
+(defvar scroll-boundary-error-point nil
+  "The value of point when an \"in place\" scrolling command signalled a buffer
+boundary error.  This is used to decide how subsequent scrolling commands
+should recover from the error."
+  ;; This variable is used as a flag, indicating whether or not the previous
+  ;; "in place" scrolling command signalled an error.
+  )
+
+(defvar scroll-window-debt 0
+  "The difference between the number of lines an \"in place\" scrolling command
+tried to scroll a window and the number of lines that the window actually
+scrolled.  This difference is the \"debt\" in the window's starting position.
+Subsequent \"in place\" scrolling commands try to make up this debt.")
+
+(defconst scroll-pos-visible-bug-p
+  ;; On September 14, 1993, David Hughes <djh@Harston.CV.COM> told me that
+  ;; Lucid GNU Emacs 19.8 had inherited the bug from Epoch... sigh.
+  (let ((old-match-data (match-data)))
+    (unwind-protect
+	(or (and (boundp 'epoch::version)
+		 (if (string-match "\\`4\\." emacs-version) t nil)
+		 )
+	    (and (string-match "Lucid" emacs-version)
+		 (if (string-match "\\`19\\.8\\." emacs-version) t nil)
+		 )
+	    )
+      (store-match-data old-match-data)))
+  "A flag, set when this version of GNU Emacs has a buggy version of the
+function `pos-visible-in-window-p' that returns `nil' when given `(point-max)'
+and `(point-max)' is on the last line of the window.  Currently, this flag is
+set for all versions of Epoch 4 and for Lucid GNU Emacs 19.8.")
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;
+;;;; Here are the window-choosing auxiliary functions used by the new scrolling
+;;;; commands.
+;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun scroll-choose-window ()
+  "Choose the window to be scrolled by the commands `scroll-down', `scroll-up',
+`scroll-down-in-place', and `scroll-up-in-place'.
+
+The rules are simple.  If the selected window is not a minibuffer window, then
+just choose the selected window.
+
+However, when a minibuffer window is selected, look first for the `minibuffer-
+scroll-window'.  The `minibuffer-scroll-window' is usually the window that
+displays completions.  If it exists, choose it; otherwise choose the next
+window after the selected window in the canonical ordering of windows.  The
+next window is generally the one below the selected window, or the one at the
+top of the screen if the selected window is at the bottom of the screen."
+  (let ((selected-window (selected-window)))
+    (if (window-minibuffer-p selected-window)
+	;; A minibuffer window is selected --- scroll some other window.
+	(if (window-live-p minibuffer-scroll-window)
+	    minibuffer-scroll-window
+	  ;; We know that the (selected) minibuffer is active, so `next-window'
+	  ;; will examine all of the frames that share this minibuffer.
+	  ;; Should we consider `other-window-scroll-buffer' here?  I don't
+	  ;; believe so.
+	  (next-window selected-window))
+      selected-window)))
+
+;;;
+;;;
+;;;
+
+(defun scroll-choose-other-window ()
+  "Choose the window to be scrolled by the commands `scroll-other-window-down',
+`scroll-other-window', `scroll-other-window-down-in-place', and `scroll-other-
+window-in-place'.
+
+The rules are these.  If the selected window is not a minibuffer window, then
+choose either:
+
+  + a window that displays the `other-window-scroll-buffer', if that buffer
+    exists.  Note, this function will display that buffer if necessary.
+
+  + the next window after the selected window in the canonical ordering of
+    windows.  The next window is generally the one below the selected window,
+    or the one at the top of the screen if the selected window is at the bottom
+    of the screen.
+
+However, when a minibuffer window is selected, look first for the `minibuffer-
+scroll-window'.  The `minibuffer-scroll-window' is usually the window that
+displays completions.  If it exists, choose it; otherwise choose the window to
+be scrolled as described above (`other-window-scroll-buffer' or next window).
+
+This function is essentially a Lisp version of the function `other-window-for-
+scrolling' which first appeared in the FSF's GNU Emacs 19.26."
+  (let* ((no-error nil)
+	 (selected-window (selected-window))
+	 (other-window nil))
+    (setq other-window
+	  (cond ((and (window-minibuffer-p selected-window)
+		      (window-live-p minibuffer-scroll-window))
+		 ;; Don't signal an error when `minibuffer-scroll-window' is
+		 ;; the minibuffer itself --- which would be really weird, but
+		 ;; isn't necessarily erroneous.
+		 (setq no-error t)
+		 minibuffer-scroll-window)
+		
+		((and ;; `other-window-scroll-buffer' is an Emacs 19 invention.
+		      (boundp 'other-window-scroll-buffer)
+		      (bufferp other-window-scroll-buffer)
+		      ;; `buffer-name' is `nil' if the buffer has been killed.
+		      (buffer-name other-window-scroll-buffer))
+		 ;; This is what FSF GNU Emacs 19.26 does, but it occurred to
+		 ;; me: what if one of these forms returns the selected window?
+		 ;; Signalling an error would be bad news, so I added a flag.
+		 (setq no-error t)
+		 (or (get-buffer-window other-window-scroll-buffer)
+		     (display-buffer other-window-scroll-buffer t)))
+		
+		((let ((next-window (next-window selected-window)))
+		   (if (eq next-window selected-window)
+		       nil
+		     next-window)))
+		
+		(t
+		 ;; In Emacs 19 (FSF, Lucid, and XEmacs), look for a window on
+		 ;; another visible frame.  This could be written for
+		 ;; Epoch, too, I suppose...
+		 (condition-case nil
+		     (let ((this-window (next-window selected-window nil t)))
+		       (while (not (or (eq this-window selected-window)
+				       (scroll-choose-window-frame-visible-p
+					this-window)))
+			 (setq this-window (next-window this-window nil t)))
+		       this-window)
+		   ;; In older versions of Emacs, `next-window' didn't accept
+		   ;; three arguments.  Catch this error and then return the
+		   ;; selected window --- which will cause another error to be
+		   ;; signalled later on.
+		   (wrong-number-of-arguments selected-window))
+		 )
+		))
+    
+    (if (and (not no-error)
+	     (eq selected-window other-window))
+	(error "There is no other window."))
+    other-window))
+
+;;;
+;;;
+;;;
+
+(defun scroll-choose-window-frame-visible-p (window)
+  "Return a true value if the frame of the given WINDOW is visible."
+  (cond ((fboundp 'window-frame)
+	 (eq t (frame-visible-p (window-frame window))))
+	(t t)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;
+;;;; Here are the "in place" scrolling commands (interactive functions) and the
+;;;; replacements for the standard GNU Emacs vertical scrolling commands.
+;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;;
+;;;; Here are the new scroll "in place" commands.
+;;;;
+
+(defun scroll-down-in-place (&optional lines)
+  "Scroll the text of the current window downward by LINES lines, leaving point
+as close as possible to its current window position (window line and column).
+In other words, point is left \"in place\" within the window.  As a special
+case, when the current window is a minibuffer window, this command scrolls the
+`minibuffer-scroll-window' (which is usually the list of completions) if it
+exists, or otherwise the next window in the canonical ordering of windows.
+
+If the optional argument LINES is `nil', scroll the window by the same amount
+it was moved by the immediately previous \"in place\" scrolling command, or by
+the value of the variable `scroll-default-lines' (usually almost a windowful)
+if the previous command was not an \"in place\" scrolling command (or when that
+previous command scrolled some other window, or when other circumstances
+prevent the previous scrolling distance from being used).  If LINES is the
+symbol `-', then the scrolling distance is determined as if LINES had been
+`nil' and then that distance is multiplied by -1.
+
+If the window cannot be scrolled by the full distance, point is allowed to
+stray from its initial position so that it can move the full number of lines.
+If point cannot move the full number of lines, point is moved to the buffer
+boundary.  Any immediately subsequent \"in place\" scrolling commands will try
+to restore point to its initial window position."
+  (interactive "P")
+  (scroll-window-in-place (scroll-choose-window) lines -1))
+
+;;;
+;;;
+;;;
+
+(defun scroll-up-in-place (&optional lines)
+  "Scroll the text of the current window upward by LINES lines, leaving point
+as close as possible to its current window position (window line and column).
+In other words, point is left \"in place\" within the window.  As a special
+case, when the current window is a minibuffer window, this command scrolls the
+`minibuffer-scroll-window' (which is usually the list of completions) if it
+exists, or otherwise the next window in the canonical ordering of windows.
+
+If the optional argument LINES is `nil', scroll the window by the same amount
+it was moved by the immediately previous \"in place\" scrolling command, or by
+the value of the variable `scroll-default-lines' (usually almost a windowful)
+if the previous command was not an \"in place\" scrolling command (or when that
+previous command scrolled some other window, or when other circumstances
+prevent the previous scrolling distance from being used).  If LINES is the
+symbol `-', then the scrolling distance is determined as if LINES had been
+`nil' and then that distance is multiplied by -1.
+
+If the window cannot be scrolled by the full distance, point is allowed to
+stray from its initial position so that it can move the full number of lines.
+If point cannot move the full number of lines, point is moved to the buffer
+boundary.  Any immediately subsequent \"in place\" scrolling commands will try
+to restore point to its initial window position."
+  (interactive "P")
+  (scroll-window-in-place (scroll-choose-window) lines 1))
+
+;;;
+;;; The command `scroll-other-window-down' first appeared in FSF GNU Emacs
+;;; 19.26.
+;;;
+
+(defun scroll-other-window-down-in-place (&optional lines)
+  "Scroll the text of the next window downward by LINES lines, leaving point in
+that window as close as possible to its current window position (window line
+and column).  In other words, point is left \"in place\" within the window.
+The next window is generally the one below the current one, or the one at the
+top of the screen if the current window is at the bottom of the screen.  In
+special circumstances this command will scroll a window other than the next
+window.  Read the documentation for the function `scroll-choose-other-window'
+for details.
+
+If the optional argument LINES is `nil', scroll the window by the same amount
+it was moved by the immediately previous \"in place\" scrolling command, or by
+the value of the variable `scroll-default-lines' (usually almost a windowful)
+if the previous command was not an \"in place\" scrolling command (or when that
+previous command scrolled some other window, or when other circumstances
+prevent the previous scrolling distance from being used).  If LINES is the
+symbol `-', then the scrolling distance is determined as if LINES had been
+`nil' and then that distance is multiplied by -1.
+
+If the window cannot be scrolled by the full distance, point is allowed to
+stray from its initial position so that it can move the full number of lines.
+If point cannot move the full number of lines, point is moved to the buffer
+boundary.  Any immediately subsequent \"in place\" scrolling commands will try
+to restore point to its initial window position.
+
+If it is impossible to scroll the text of the window at all (because a buffer
+boundary is already visible), this command signals a buffer boundary error.
+The error is signalled even if point could otherwise move the full number of
+lines."
+  (interactive "P")
+  (scroll-window-in-place (scroll-choose-other-window) lines -1))
+
+;;;
+;;;
+;;;
+
+(defun scroll-other-window-in-place (&optional lines)
+  "Scroll the text of the next window upward by LINES lines, leaving point in
+that window as close as possible to its current window position (window line
+and column).  In other words, point is left \"in place\" within the window.
+The next window is generally the one below the current one, or the one at the
+top of the screen if the current window is at the bottom of the screen.  In
+special circumstances this command will scroll a window other than the next
+window.  Read the documentation for the function `scroll-choose-other-window'
+for details.
+
+If the optional argument LINES is `nil', scroll the window by the same amount
+it was moved by the immediately previous \"in place\" scrolling command, or by
+the value of the variable `scroll-default-lines' (usually almost a windowful)
+if the previous command was not an \"in place\" scrolling command (or when that
+previous command scrolled some other window, or when other circumstances
+prevent the previous scrolling distance from being used).  If LINES is the
+symbol `-', then the scrolling distance is determined as if LINES had been
+`nil' and then that distance is multiplied by -1.
+
+If the window cannot be scrolled by the full distance, point is allowed to
+stray from its initial position so that it can move the full number of lines.
+If point cannot move the full number of lines, point is moved to the buffer
+boundary.  Any immediately subsequent \"in place\" scrolling commands will try
+to restore point to its initial window position.
+
+If it is impossible to scroll the text of the window at all (because a buffer
+boundary is already visible), this command signals a buffer boundary error.
+The error is signalled even if point could otherwise move the full number of
+lines."
+  (interactive "P")
+  (scroll-window-in-place (scroll-choose-other-window) lines 1))
+
+;;;;
+;;;; Here are the replacements for GNU Emacs' standard vertical scrolling
+;;;; commands.
+;;;;
+
+(or (fboundp 'original-scroll-down)
+    (fset 'original-scroll-down (symbol-function 'scroll-down)))
+(or (fboundp 'original-scroll-up)
+    (fset 'original-scroll-up (symbol-function 'scroll-up)))
+(or (fboundp 'original-scroll-other-window-down)
+    ;; `scroll-other-window-down' first appeared in FSF GNU Emacs 19.26.
+    (if (fboundp 'scroll-other-window-down)
+	(fset 'original-scroll-other-window-down
+	      (symbol-function 'scroll-other-window-down))
+      ))
+(or (fboundp 'original-scroll-other-window)
+    (fset 'original-scroll-other-window (symbol-function 'scroll-other-window))
+    )
+
+;;;
+;;;
+;;;
+
+(defun scroll-down (&optional lines)
+  "Scroll the text of the current window downward by LINES lines.  As a special
+case, when the current window is a minibuffer window, this command scrolls the
+`minibuffer-scroll-window' (which is usually the list of completions) if it
+exists, or otherwise the next window in the canonical ordering of windows.
+
+The argument LINES is optional.  Its meaning depends on the current value of
+the variable `scroll-in-place'.
+
+When the variable `scroll-in-place' is true, this command works just like the
+command `scroll-down-in-place', scrolling the current window and leaving point
+\"in place\" within the window.  See the documentation for the command
+`scroll-down-in-place' for more information.
+
+When the variable `scroll-in-place' is `nil' this command invokes the standard
+GNU Emacs version of `scroll-down'.  In that case, when LINES is `nil' the
+current window is scrolled by nearly a complete windowful of text.
+
+Note that this command correctly handles cases in which `scroll-in-place' has a
+buffer-local value in the window to be scrolled.  That value is honored."
+  (interactive "P")
+  (scroll-window (scroll-choose-window) lines -1))
+
+;;;
+;;;
+;;;
+
+(defun scroll-up (&optional lines)
+  "Scroll the text of the current window upward by LINES lines.  As a special
+case, when the current window is a minibuffer window, this command scrolls the
+`minibuffer-scroll-window' (which is usually the list of completions) if it
+exists, or otherwise the next window in the canonical ordering of windows.
+
+The argument LINES is optional.  Its meaning depends on the current value of
+the variable `scroll-in-place'.
+
+When the variable `scroll-in-place' is true, this command works just like the
+command `scroll-up-in-place', scrolling the current window and leaving point
+\"in place\" within the window.  See the documentation for the command
+`scroll-up-in-place' for more information.
+
+When the variable `scroll-in-place' is `nil' this command invokes the standard
+GNU Emacs version of `scroll-up'.  In that case, when LINES is `nil' the
+current window is scrolled by nearly a complete windowful of text.
+
+Note that this command correctly handles cases in which `scroll-in-place' has a
+buffer-local value in the window to be scrolled.  That value is honored."
+  (interactive "P")
+  (scroll-window (scroll-choose-window) lines 1))
+
+;;;
+;;; NOTE that in the FSF GNU Emacs 19.26 version of `scroll-other-window-down',
+;;; the `lines' argument is required.  I've left it optional in order to be
+;;; like `scroll-other-window'.
+;;;
+
+(defun scroll-other-window-down (&optional lines)
+  "Scroll the text of the next window downward by LINES lines.  The next window
+is generally the one below the current one, or the one at the top of the screen
+if the current window is at the bottom of the screen.  In special circumstances
+this command will scroll a window other than the next window.  Read the
+documentation for the function `scroll-choose-other-window' for details.
+
+The argument LINES is optional.  Its meaning depends on the current value of
+the variable `scroll-in-place'.
+
+When the variable `scroll-in-place' is true, this command works just like the
+command `scroll-other-window-down-in-place', scrolling the next window and
+leaving point \"in place\" within that window.  See the documentation for the
+command `scroll-other-window-down-in-place' for more information.
+
+When the variable `scroll-in-place' is `nil' this command invokes the standard
+GNU Emacs version of `scroll-other-window-down'.  In that case, when LINES is
+`nil' the next window is scrolled by nearly a complete windowful of text.
+\(Note that `scroll-other-window-down' first appeared as a standard command in
+the FSF's GNU Emacs 19.26.  If the builtin version of that command is not
+available in the current Emacs system, an equivalent action is invoked
+instead.)
+
+Note that this command correctly handles cases in which `scroll-in-place' has a
+buffer-local value in the window to be scrolled.  That value is honored."
+  (interactive "P")
+  ;; This code is similar to the body of `scroll-window', below.
+  (let* ((other-window (scroll-choose-other-window))
+	 (other-window-buffer (window-buffer other-window)))
+    (if ;; Allow `scroll-in-place' to be a buffer-local variable.
+	(save-excursion (set-buffer other-window-buffer) scroll-in-place)
+	(scroll-window-in-place other-window lines -1)
+      
+      ;; Paranoid, we forcibly break any running sequence of "in place"
+      ;; scrolling commands.
+      (setq scroll-previous-window nil)
+      ;; For XEmacs and Lucid GNU Emacs, preserve the region's state.
+      (if (boundp 'zmacs-region-stays)
+	  (setq zmacs-region-stays t))
+      (if (fboundp 'original-scroll-other-window-down)
+	  (original-scroll-other-window-down lines)
+	;; `scroll-other-window-down' first appeared as a builtin in FSF GNU
+	;; Emacs 19.26, so it may not be available in the current Emacs system.
+	;; Do the equivalent thing.
+	(original-scroll-other-window (cond
+				       ((null lines) '-)
+				       ((eq lines '-) nil)
+				       (t (- (prefix-numeric-value lines)))
+				       ))
+	))
+    ))
+
+;;;
+;;;
+;;;
+
+(defun scroll-other-window (&optional lines)
+  "Scroll the text of the next window upward by LINES lines.  The next window
+is generally the one below the current one, or the one at the top of the screen
+if the current window is at the bottom of the screen.  In special circumstances
+this command will scroll a window other than the next window.  Read the
+documentation for the function `scroll-choose-other-window' for details.
+
+The argument LINES is optional.  Its meaning depends on the current value of
+the variable `scroll-in-place'.
+
+When the variable `scroll-in-place' is true, this command works just like the
+command `scroll-other-window-in-place', scrolling the next window and leaving
+point \"in place\" within that window.  See the documentation for the command
+`scroll-other-window-in-place' for more information.
+
+When the variable `scroll-in-place' is `nil' this command invokes the standard
+GNU Emacs version of `scroll-other-window'.  In that case, when LINES is `nil'
+the next window is scrolled by nearly a complete windowful of text.
+
+Note that this command correctly handles cases in which `scroll-in-place' has a
+buffer-local value in the window to be scrolled.  That value is honored."
+  (interactive "P")
+  ;; This code is similar to the body of `scroll-window', below.
+  (let* ((other-window (scroll-choose-other-window))
+	 (other-window-buffer (window-buffer other-window)))
+    (if ;; Allow `scroll-in-place' to be a buffer-local variable.
+	(save-excursion (set-buffer other-window-buffer) scroll-in-place)
+	(scroll-window-in-place other-window lines 1)
+      
+      ;; Paranoid, we forcibly break any running sequence of "in place"
+      ;; scrolling commands.
+      (setq scroll-previous-window nil)
+      ;; For XEmacs and Lucid GNU Emacs, preserve the region's state.
+      (if (boundp 'zmacs-region-stays)
+	  (setq zmacs-region-stays t))
+      (original-scroll-other-window lines))
+    ))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;
+;;;; Here are the new functions `scroll-window-in-place', `scroll-window', and
+;;;; `scroll-window-in-place-continue-sequence'.  These functions are intended
+;;;; to be available to programs outside this package.
+;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun scroll-window-in-place (window lines direction)
+  "Scroll WINDOW vertically by the given number of window LINES in the given
+DIRECTION, leaving the window's point as close as possible to its original
+window position (window line and column).  In other words, the window's point
+is left \"in place\" within the window.
+
+Note that the window to be scrolled does not have to be the selected window,
+and that this function does not change which window is selected.
+
+LINES specifies the number of window lines to scroll and is interpreted as if
+it were a raw prefix argument.  If LINES is `nil', the window is scrolled by
+the amount it was moved by the immediately previous \"in place\" scrolling
+command, or by the value of the variable `scroll-default-lines' (by default,
+almost a windowful) if the previous command was not an \"in place\" scrolling
+command (or when WINDOW is not the previously scrolled window, or when the
+value of `this-command' is not in the same group as the previous scrolling
+command (see the documentation for the variable `scroll-command-groups'), or
+when other circumstances prevent the previous scrolling distance from being
+used).  If LINES is the symbol `-', then the scrolling distance is determined
+as if LINES had been `nil' and then that distance is multiplied by -1.
+
+DIRECTION determines the direction of the scrolling motion.  The values -1 and
+`down' indicate downward motion; the values 1 and `up' indicate upward motion.
+Any other value causes an error.
+
+If the window cannot be scrolled by the full distance (because the window hits
+the boundary of its buffer), the window's point is allowed to stray from its
+initial position so that it can move the full number of lines.  If point cannot
+move the full number of lines, point is moved to the buffer boundary (unless it
+was already there, in which case a buffer boundary error is signalled instead).
+Any immediately subsequent \"in place\" scrolling commands will try to restore
+point to its initial window position.
+
+Unless the variable `scroll-allow-blank-lines-past-eob' is true, this function
+avoids displaying blank lines past the end of the buffer except as necessary to
+make a previous \"in place\" scrolling action reversible.  Effectively, this
+means that this function will not display any more past-end-of-buffer blank
+lines than were visible when the current sequence of \"in place\" scrolling
+commands started.  When the variable `scroll-allow-blank-lines-past-eob' is
+true, this function will display as many blank lines as is necessary to keep
+point \"in place\" in the window.
+
+Note that if WINDOW is not the selected window and it is impossible to scroll
+the text of WINDOW at all (because a buffer boundary is already visible), then
+this function signals a buffer boundary error.  The error is signalled even if
+point could otherwise move the full number of lines."
+  (let* (;; Make sure that the user doesn't quit in the middle and leave us
+	 ;; with our variables out of sync.
+	 (inhibit-quit t)
+	 (original-window (selected-window))
+	 (original-buffer (current-buffer))
+	 (window-height (- (window-height window)
+			   (if (window-minibuffer-p window)
+			       0 1)))
+	 (this-command-group (scroll-get-command-group this-command))
+	 (continue-scroll-p
+	  (and ;; We're scrolling the previously scrolled window...
+	       (windowp scroll-previous-window)
+	       (eq window scroll-previous-window)
+	       ;; ...and the last command was an "in place" scrolling command
+	       ;; that can be continued by this command.
+	       (if (eq last-command t)
+		   ;; If the previous command signalled an error, the value of
+		   ;; `last-command' is `t'.  Try to see if we signalled the
+		   ;; error and if point is where we left it.  (NOTE that FSF
+		   ;; GNU Emacs 19.23+ no longer sets `last-command' to `t'
+		   ;; when a command signals an error.  This is OK because the
+		   ;; else part of this `if' does the appropriate thing.)
+		   (and	scroll-boundary-error-point
+			(eq (window-point window) scroll-boundary-error-point)
+			(memq scroll-boundary-error-command this-command-group)
+			)
+		 ;; Otherwise...
+		 (memq last-command this-command-group))
+	       ))
+	 (lines-value (prefix-numeric-value lines))
+	 )
+    
+    ;; For XEmacs and Lucid GNU Emacs, preserve the region's state.  Note that
+    ;; these Emacsen will forcibly deactivate the region if we signal an error
+    ;; later on.  Is this bad?
+    (if (boundp 'zmacs-region-stays)
+	(setq zmacs-region-stays t))
+    ;; Parse the direction into a unit distance (1 or -1).
+    (setq direction (scroll-parse-direction direction))
+    
+    (setq scroll-previous-window window
+	  ;; `(setq scroll-boundary-error-command nil)' is not necessary.
+	  scroll-boundary-error-point nil)
+    (unwind-protect
+	(progn
+	  ;; `select-window' does an implicit `set-buffer'.
+	  (select-window window)
+	  
+	  (if (or ;; The current command is not a continuation of a running
+		  ;; sequence of "in place" scrolling commands...
+		  (not continue-scroll-p)
+		  ;; ...or we were given an explicit number of lines to scroll,
+		  ;; and that number has a different magnitude than the last
+		  ;; number of lines we scrolled...
+	          (and (or (numberp lines) (consp lines))
+		       (/= scroll-previous-lines lines-value)
+		       (/= scroll-previous-lines (- lines-value)))
+		  ;; ...or the last successful scrolling command moved to a
+		  ;; buffer boundary, but the buffer is no longer in the state
+		  ;; we left it.  (This can occur if, for example, we signal an
+		  ;; end-of-buffer error and something catches it and moves
+		  ;; point or renarrows.  VM, for example, does this.)
+		  (and scroll-boundary-previous-point
+		       (or (not (or (bobp) (eobp)))
+			   (< scroll-boundary-previous-point (point-min))
+			   (> scroll-boundary-previous-point (point-max))
+			   (eq scroll-boundary-previous-point (point)))))
+	      
+	      ;; We're starting a new sequence of scrolling commands.
+	      (setq lines (if (or (numberp lines) (consp lines))
+			      lines-value
+			    ;; The default number of lines...
+			    (* (if (eq lines '-) -1 1)
+			       (if (numberp scroll-default-lines)
+				   scroll-default-lines
+				 (max (- window-height
+					 next-screen-context-lines)
+				      1))))
+		    scroll-previous-lines lines
+		    scroll-goal-column (scroll-determine-goal-column window)
+		    scroll-boundary-previous-point nil
+		    ;; `(setq scroll-boundary-previous-lines 0)' is not
+		    ;; necessary.
+		    scroll-window-debt 0
+		    scroll-initially-displayed-lines
+		    (if scroll-allow-blank-lines-past-eob
+			0
+		      (save-excursion
+			(goto-char (window-start window))
+			(vertical-motion (1- window-height)))))
+	    
+	    ;; Otherwise we want to scroll by the same number of lines (but
+	    ;; possibly in a different direction) that we scrolled in previous
+	    ;; invocations of this function.
+	    (cond ((null lines)
+		   (setq lines scroll-previous-lines))
+		  ((eq lines '-)
+		   (setq lines (- scroll-previous-lines)
+			 scroll-previous-lines lines))
+		  (t
+		   (setq lines lines-value
+			 scroll-previous-lines lines)))
+	    )
+	  
+	  (setq lines (* direction lines))
+	  
+	  ;; If point is not in the window, center window around point.  We try
+	  ;; to account for a bug in `pos-visible-in-window-p' in some versions
+	  ;; of Emacs (see `scroll-pos-visible-bug-p', above).
+	  (save-excursion
+	    (if (pos-visible-in-window-p (let ((point (point)))
+					   (if (and scroll-pos-visible-bug-p
+						    (= point (point-max)))
+					       (max (1- point) (point-min))
+					     point))
+					 window)
+		nil
+	      (vertical-motion (/ (- window-height) 2))
+	      (set-window-start window (point))))
+	  
+	  (cond ((and scroll-boundary-previous-point
+		      ;; `lines' is the same sign as the direction from point
+		      ;; to the `scroll-boundary-previous-point'.
+		      (cond ((> lines 0)
+			     (> (- scroll-boundary-previous-point (point)) 0))
+			    ((< lines 0)
+			     (< (- scroll-boundary-previous-point (point)) 0))
+			    (t nil)))
+		 ;; We're moving away from the buffer boundary.
+		 (goto-char scroll-boundary-previous-point)
+		 ;; Always move here (i.e., don't reject cases in which the
+		 ;; window doesn't move).
+		 (scroll-set-window-start window
+					  (- scroll-boundary-previous-lines))
+		 ;; (message "Back, window debt is %s." scroll-window-debt)
+		 (setq scroll-boundary-previous-point nil))
+
+		((= lines 0)
+		 ;; We're going nowhere, so save ourselves some work.
+		 ;; (message "Scrolled zero lines.")
+		 )
+		
+		(t
+		 ;; Perform the scrolling motion.
+		 (let ((initial-point (point))
+		       (moved nil))
+		   ;; First move point and see how far it goes.
+		   (setq moved (vertical-motion lines))
+		   (if (= moved lines)
+		       (progn
+			 ;; Point moved the full distance.  Move to the desired
+			 ;; column and then try to move the window the full
+			 ;; distance, too.
+			 (move-to-column (+ (current-column)
+					    scroll-goal-column))
+			 (or (scroll-set-window-start window moved
+						      original-window)
+			     (scroll-signal-boundary-error initial-point
+							   lines))
+			 ;; (message "Normal, window debt is %s."
+			 ;;          scroll-window-debt)
+			 )
+		     ;; Point couldn't move all the way.  Move to the buffer
+		     ;; boundary if we're not already there, or signal a buffer
+		     ;; boundary error otherwise.
+		     (let ((boundary-point (if (< lines 0)
+					       (point-min)
+					     (point-max)))
+			   (boundary-symbol (if (< lines 0)
+						'beginning-of-buffer
+					      'end-of-buffer)))
+		       (if (= initial-point boundary-point)
+			   (scroll-signal-boundary-error initial-point lines)
+			 ;; Scroll the window by as many lines as point could
+			 ;; move.
+			 (or (scroll-set-window-start window moved
+						      original-window)
+			     (scroll-signal-boundary-error initial-point
+							   lines))
+			 (message "%s" (get boundary-symbol 'error-message))
+			 ;; (message "Boundary, window debt is %s."
+			 ;;          scroll-window-debt)
+			 (setq scroll-boundary-previous-lines moved)
+			 (setq scroll-boundary-previous-point initial-point)
+			 (goto-char boundary-point))
+		       )))
+		 )))
+      
+      ;; The unwind forms of the `unwind-protect', above.  Restore the
+      ;; originally selected window and current buffer.
+      (select-window original-window)
+      (set-buffer original-buffer)))
+  
+  ;; The standard GNU Emacs scrolling commands return `nil' so we do, too.
+  nil)
+
+;;;
+;;;
+;;;
+
+(defun scroll-window (window lines direction)
+  "Scroll WINDOW vertically by the given number of window LINES in the given
+DIRECTION.  Note that the window to be scrolled does not have to be the
+selected window, and that this function does not change which window is
+selected.
+
+When the variable `scroll-in-place' is true, this function simply invokes the
+function `scroll-window-in-place' to scroll the window and leave point \"in
+place\" within that window.  See the documentation for `scroll-window-in-place'
+for more information.
+
+When the variable `scroll-in-place' is `nil' this function invokes the original
+version of the standard GNU Emacs command `scroll-down' or `scroll-up', as
+determined by DIRECTION, to scroll the window.  If DIRECTION is -1 or `down',
+the original `scroll-down' is called; if DIRECTION is 1 or `up', the original
+`scroll-up' is called.  Any other DIRECTION is an error.  LINES is interpreted
+as if it were a raw prefix argument.  If LINES is `nil', the window is scrolled
+by almost a complete windowful.  If LINES is the symbol `-', the window is
+scrolled by almost a complete windowful in the opposite direction.
+
+Note that this function correctly handles cases in which `scroll-in-place' has
+a buffer-local value in the WINDOW's buffer.  That value is honored."
+  (let ((current-buffer (current-buffer))
+	(selected-window (selected-window))
+	(window-buffer (window-buffer window)))
+    (if ;; Allow `scroll-in-place' to be a buffer-local variable.
+	(if (eq current-buffer window-buffer)
+	    scroll-in-place
+	  (save-excursion (set-buffer window-buffer) scroll-in-place))
+	(scroll-window-in-place window lines direction)
+      
+      (unwind-protect
+	  (progn
+	    ;; Paranoid, we forcibly break any running sequence of "in place"
+	    ;; scrolling commands.
+	    (setq scroll-previous-window nil)
+	    ;; For XEmacs and Lucid GNU Emacs, preserve the region's state.
+	    (if (boundp 'zmacs-region-stays)
+		(setq zmacs-region-stays t))
+	    (select-window window)
+	    (if (= (scroll-parse-direction direction) 1)
+		(original-scroll-up lines)
+	      (original-scroll-down lines)))
+	(select-window selected-window)
+	(set-buffer current-buffer))
+      )))
+
+;;;
+;;; The following function is sometimes useful.  For example, I call it from
+;;; functions that are invoked by certain mouse button down events in order to
+;;; preserve any running chain of "in place" scrolling commands.  This lets me
+;;; continue the sequence from my mouse button up functions.
+;;;
+;;; I haven't yet needed a function to purposely break a running sequence of
+;;; "in place" scrolling commands.  Such a function would be easy to write,
+;;; however; just set the variable `scroll-previous-window' to `nil'.
+;;;
+
+(defun scroll-window-in-place-continue-sequence ()
+  "If the previous command was a \"scroll in place\" command, set the variable
+`this-command' to the name of that previous command.  This ensures that any
+running sequence of \"in place\" scrolling commands will not be broken by the
+current command.  See the documentation for the commands `scroll-down-in-place'
+and `scroll-up-in-place' for more information about \"in place\" scrolling.
+
+NOTE that you don't need to call this function if the current command scrolls
+in place!  You only need to call this function when the current command is not
+a \"scroll in place\" command but you still want to preserve any running
+sequence of \"in place\" commands.  Such situations are rare.
+
+NOTE that this function sets `this-command' in order to trick the \"in place\"
+scrolling commands.  If something else subsequently sets `this-command', any
+running sequence of scrolling commands will probably be broken anyway."
+  (if (if (eq last-command t)
+	  ;; If `last-command' is `t', then the previous command signalled an
+	  ;; error.  See if the last invocation of `scroll-window-in-place'
+	  ;; signalled an error.  (NOTE that FSF GNU Emacs 19.23+ no longer
+	  ;; sets `last-command' to `t' when a command signals an error.  This
+	  ;; is OK because the else part of this `if' does the appropriate
+	  ;; thing.)
+	  scroll-boundary-error-point
+	;; Otherwise, the value of `last-command' must belong to some group of
+	;; "in place" scrolling commands.
+	(or (memq last-command scroll-default-command-group)
+	    (let ((groups scroll-command-groups)
+		  (found nil))
+	      (while (and groups (not found))
+		(if (memq last-command (car groups))
+		    (setq found t)
+		  (setq groups (cdr groups)))
+		)
+	      found)))
+      (setq this-command last-command)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;
+;;;; Here are the various auxiliary functions called by the function `scroll-
+;;;; window-in-place'.  None of the functions are intended to be called from
+;;;; outside this package.
+;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun scroll-get-command-group (command)
+  "Return the group of \"in place\" scrolling commands that contains the given
+COMMAND.  This is the list of commands with which the given command may share
+state and form \"chains.\"
+
+This function is an auxiliary for the function `scroll-window-in-place'.  Don't
+call this function from other code."
+  ;; This function assumes that the given command is an "in place" scrolling
+  ;; command.
+  (let ((groups scroll-command-groups)
+	(found nil))
+    (while (and groups (not found))
+      (if (memq command (car groups))
+	  (setq found t)
+	(setq groups (cdr groups)))
+      )
+    (if groups
+	(car groups)
+      ;; Otherwise return the default command group.  If necessary, add the
+      ;; given command to the default command group.
+      (or (memq command scroll-default-command-group)
+	  (setq scroll-default-command-group
+		(cons command scroll-default-command-group)))
+      scroll-default-command-group)
+    ))
+
+;;;
+;;;
+;;;
+
+(defun scroll-parse-direction (direction)
+  "Return the signed unit distance for the given DIRECTION.  If DIRECTION is
+unacceptable, signal an error."
+  (cond ((or (eq direction 1) (eq direction -1)) direction)
+	((eq direction 'up) 1)
+	((eq direction 'down) -1)
+	(t (signal 'args-out-of-range (list 'direction direction)))
+	))
+
+;;;
+;;;
+;;;
+
+(defun scroll-determine-goal-column (window)
+  "Return the goal column for the \"in place\" vertical scrolling commands.
+This is the horizontal window position at which these commands try to keep
+point.
+
+This function is an auxiliary for the function `scroll-window-in-place'.  Don't
+call this function from other code."
+  ;; NOTE that `window' must be the selected window!  `scroll-window-in-place'
+  ;; ensures that this is so.
+  (cond ((or truncate-lines
+	     (and truncate-partial-width-windows
+		  (< (window-width window) (screen-width)))
+	     (> (window-hscroll window) 0))
+	 ;; Lines in this window are being truncated.
+	 (if (and track-eol (eolp))
+	     9999
+	   (current-column)))
+	((and track-eol (eolp))
+	 ;; In some ways this isn't quite right, as point doesn't track the
+	 ;; ends of wrapped lines.  But if it did so, point would be on the
+	 ;; wrong window line.  This is the best we can do.
+	 (1- (window-width window)))
+	(t (% (current-column) (1- (window-width window))))
+	))
+
+;;;
+;;;
+;;;
+
+(defun scroll-set-window-start (window lines &optional original-window)
+  "Move the `window-start' of the given window, which must be the selected
+window.  If the window was successfully scrolled, update the variable
+`scroll-window-debt' and return `t'.  Otherwise return `nil'.
+
+This function is an auxiliary for the function `scroll-window-in-place'.  Don't
+call this function from other code."
+  (save-excursion
+    (goto-char (window-start window))
+    ;; Try to move the window start by the specified number of lines.  In
+    ;; addition, try to make up any existing debt in the window start's
+    ;; position and make sure that we don't move too close to the end of the
+    ;; buffer.
+    (let ((moved (+ (vertical-motion (+ lines
+					scroll-window-debt
+					scroll-initially-displayed-lines))
+		    (vertical-motion (- scroll-initially-displayed-lines)))))
+      ;; If we're not scrolling the `original-window' (i.e., the originally
+      ;; selected window), punt if we didn't move the window start at all.
+      (if (and original-window
+	       (not (eq window original-window))
+	       (= moved 0))
+	  nil
+	;; Otherwise update the window start and keep track of the debt in our
+	;; position.  Return `t' to indicate success.
+	(set-window-start window (point))
+	(setq scroll-window-debt (- (+ lines scroll-window-debt) moved))
+	t))
+    ))
+
+;;;
+;;;
+;;;
+
+(defun scroll-signal-boundary-error (initial-point lines)
+  "Move point to its initial location and signal an appropriate buffer boundary
+error.
+
+This function is an auxiliary for the function `scroll-window-in-place'.  Don't
+call this function from other code."
+  (goto-char initial-point)
+  ;; Remember what we were doing and where point was when we signalled the
+  ;; error so that subsequent "in place" scrolling commands can decide how to
+  ;; recover.
+  (setq scroll-boundary-error-command this-command
+	scroll-boundary-error-point initial-point)
+  (signal (if (< lines 0) 'beginning-of-buffer 'end-of-buffer)
+	  nil))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;
+;;;; Finally, here is the `provide' statement.
+;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(provide 'scroll-in-place)
+
+;; End of file.
+