0
|
1
|
|
2 ;;;; -*-Emacs-Lisp-*- Improved Vertical Scrolling Commands
|
|
3 ;;;; Written by Eric Eide, last modified on 1994/11/18 21:23:01.
|
|
4 ;;;; (C) Copyright 1993, 1994, Eric Eide and the University of Utah
|
|
5 ;;;;
|
|
6 ;;;; COPYRIGHT NOTICE
|
|
7 ;;;;
|
|
8 ;;;; This program is free software; you can redistribute it and/or modify it
|
|
9 ;;;; under the terms of the GNU General Public License as published by the Free
|
|
10 ;;;; Software Foundation; either version 2 of the License, or (at your option)
|
|
11 ;;;; any later version.
|
|
12 ;;;;
|
|
13 ;;;; This program is distributed in the hope that it will be useful, but
|
|
14 ;;;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
15 ;;;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
16 ;;;; for more details.
|
|
17 ;;;;
|
|
18 ;;;; You should have received a copy of the GNU General Public License along
|
|
19 ;;;; with GNU Emacs. If you did not, write to the Free Software Foundation,
|
76
|
20 ;;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
0
|
21
|
|
22 ;;; Synched up with: Not in FSF.
|
|
23
|
|
24 ;;;; AUTHORS
|
|
25 ;;;;
|
|
26 ;;;; This package was written by Eric Eide (eeide@cs.utah.edu) and was based on
|
|
27 ;;;; a very similar package ("scroll-fix") by Joe Wells. Almost all of the
|
|
28 ;;;; code in this file is original, but I owe a great debt to Mr. Wells for his
|
|
29 ;;;; ideas and his original implementation.
|
|
30 ;;;;
|
|
31 ;;;; Eric Eide (eeide@cs.utah.edu)
|
|
32 ;;;; University of Utah
|
|
33 ;;;; 3190 Merrill Engineering Building
|
|
34 ;;;; Salt Lake City, Utah 84112
|
|
35 ;;;;
|
|
36 ;;;; Joe Wells (jbw@cs.bu.edu)
|
|
37 ;;;;
|
|
38 ;;;; Joe Wells' "scroll-fix" package is Copyright (C) 1988, 1989, and 1991 by
|
|
39 ;;;; the Free Software Foundation. It is distributed under the terms of the
|
|
40 ;;;; GNU General Public License.
|
|
41
|
|
42 ;;;; LISP CODE DIRECTORY INFORMATION
|
|
43 ;;;;
|
|
44 ;;;; LCD Archive Entry:
|
|
45 ;;;; scroll-in-place|Eric Eide|eeide@cs.utah.edu|
|
|
46 ;;;; Improved vertical scrolling commands|
|
|
47 ;;;; 1994/11/18 21:23:01|1.3|~/misc/scroll-in-place.el.Z|
|
|
48
|
|
49 ;;;; SUMMARY
|
|
50 ;;;;
|
|
51 ;;;; This package provides improved vertical scrolling commands for GNU Emacs.
|
|
52 ;;;; These new commands offer the following features:
|
|
53 ;;;;
|
|
54 ;;;; + When a scrolling command is executed, GNU Emacs tries to keep point as
|
|
55 ;;;; close as possible to its original window position (window line and
|
|
56 ;;;; column). This is what "scroll in place" means: point stays "in place"
|
|
57 ;;;; within the window. (There are times when point must be moved from its
|
|
58 ;;;; original window position in order to execute the scroll; see below.)
|
|
59 ;;;;
|
|
60 ;;;; The variable `scroll-in-place', which is true by default, determines
|
|
61 ;;;; whether or not the standard GNU Emacs scrolling commands (`scroll-down',
|
|
62 ;;;; `scroll-up', `scroll-other-window-down', and `scroll-other-window') use
|
|
63 ;;;; the "in place" features listed here. When `scroll-in-place' is `nil'
|
|
64 ;;;; the standard GNU Emacs scrolling commands essentially just call the
|
|
65 ;;;; original versions of themselves. (Note that even when `scroll-in-place'
|
|
66 ;;;; is `nil' the new versions of `scroll-down' and `scroll-up' have slightly
|
|
67 ;;;; different behavior when a minibuffer window is the selected window. See
|
|
68 ;;;; below.)
|
|
69 ;;;;
|
|
70 ;;;; It is possible to turn off (or turn on) "in place" scrolling for certain
|
|
71 ;;;; buffers by making buffer-local bindings of the variable `scroll-in-
|
|
72 ;;;; place' for those buffers. The variable `scroll-in-place' is not usually
|
|
73 ;;;; buffer-local, but you can make it so if you desire.
|
|
74 ;;;;
|
|
75 ;;;; + Because the improved scrolling commands keep point at its original
|
|
76 ;;;; window position, these scrolling commands are "reversible." The
|
|
77 ;;;; `scroll-up' command undoes the effect of the immediately previous
|
|
78 ;;;; `scroll-down' command (if any) and vice versa. In other words, if you
|
|
79 ;;;; scroll up and then immediately scroll back down, the window config-
|
|
80 ;;;; uration is restored to its exact original state. This allows you to
|
|
81 ;;;; browse through a buffer more easily, as you can always get back to the
|
|
82 ;;;; original configuration.
|
|
83 ;;;;
|
|
84 ;;;; Note, however, that the improved scrolling commands are guaranteed to be
|
|
85 ;;;; reversible only if there are no intervening non-scrolling commands.
|
|
86 ;;;; Also, if you give a prefix argument to a scrolling command (in order to
|
|
87 ;;;; specify the number of lines to scroll by), previous scrolling commands
|
|
88 ;;;; may no longer be reversible. More specifically, if the new prefix
|
|
89 ;;;; argument has a different magnitude than the previous scrolling distance,
|
|
90 ;;;; then any previous scrolling commands are not reversible. The new prefix
|
|
91 ;;;; argument takes precedence.
|
|
92 ;;;;
|
|
93 ;;;; You might find it useful to think of the scrolling commands as forming
|
|
94 ;;;; "chains." A scrolling command either starts or continues a chain. By
|
|
95 ;;;; issuing a non-scrolling command or by changing the number of lines to be
|
|
96 ;;;; scrolled, you break the chain. (Note that simply changing the scrolling
|
|
97 ;;;; direction won't break the chain; changing the absolute number of lines
|
|
98 ;;;; to be scrolled is what breaks the chain.) Scrolling commands are
|
|
99 ;;;; guaranteed to be reversible only within the current chain. Hopefully
|
|
100 ;;;; that's clear enough.
|
|
101 ;;;;
|
|
102 ;;;; + When a scrolling command is given a prefix argument (which specifies the
|
|
103 ;;;; number of lines to scroll by), then that argument becomes the default
|
|
104 ;;;; scrolling distance for all immediately subsequent scrolling commands.
|
|
105 ;;;; This means that you can easily set the scrolling distance for a chain
|
|
106 ;;;; of scrolling commands. Note that a new prefix argument or any non-
|
|
107 ;;;; scrolling command breaks the chain (as described above), and any further
|
|
108 ;;;; scrolling commands will use the usual defaults (or the prefix argument
|
|
109 ;;;; you specify at that time, of course).
|
|
110 ;;;;
|
|
111 ;;;; However, there are cases in which one doesn't want the current scrolling
|
|
112 ;;;; command to use the default scrolling distance that was set by the
|
|
113 ;;;; previous scrolling command. For example, suppose that you had special
|
|
114 ;;;; commands that scrolled one line up and one line down. When you invoke
|
|
115 ;;;; one of these commands, the "in place" scrolling routines set the default
|
|
116 ;;;; scrolling distance to be just one line. Now suppose that you use one of
|
|
117 ;;;; your special commands and then immediately invoke `scroll-up' (`C-v'),
|
|
118 ;;;; expecting it to scroll by a near windowful of text. You would be
|
|
119 ;;;; disappointed --- because the previous command set the default scrolling
|
|
120 ;;;; distance to be just one line, `scroll-up' just scrolls by one line.
|
|
121 ;;;;
|
|
122 ;;;; To solve this problem, "scroll-in-place" allows you to divide scrolling
|
|
123 ;;;; commands into separate "groups." Commands in a group can only form
|
|
124 ;;;; chains with (and therefore, inherit defaults from) commands in the same
|
|
125 ;;;; group. (Note that no command can be in more than one group.) If you
|
|
126 ;;;; invoke a scrolling command that is not in the same group as that of the
|
|
127 ;;;; immediately previous scrolling command, then the previous chain is
|
|
128 ;;;; broken and you start a new chain --- with a new set of defaults.
|
|
129 ;;;;
|
|
130 ;;;; So to solve the problem described above, you could put your one-line
|
|
131 ;;;; scrolling commands in their own group. Once that is done, the standard
|
|
132 ;;;; scrolling commands will not form chains with your one-line scrolling
|
|
133 ;;;; commands, and therefore will not use the default scrolling distance set
|
|
134 ;;;; by those commands. Problem solved!
|
|
135 ;;;;
|
|
136 ;;;; By default, all "in place" scrolling commands are in a single group. If
|
|
137 ;;;; you want to partition some commands into separate groups, you must do
|
|
138 ;;;; that yourself *before* any "in place" commands are invoked. For more
|
|
139 ;;;; information about grouping commands, see the documentation for the
|
|
140 ;;;; variables `scroll-command-groups' and `scroll-default-command-group'.
|
|
141 ;;;;
|
|
142 ;;;; + The improved scrolling commands will avoid displaying empty lines past
|
|
143 ;;;; the end of the buffer when possible. In other words, just as you can't
|
|
144 ;;;; see "dead space" before the beginning of the buffer text, the new
|
|
145 ;;;; scrolling commands try to avoid displaying "dead space" past the end of
|
|
146 ;;;; the buffer text. This behavior is somewhat configurable; see the
|
|
147 ;;;; documentation for the variable `scroll-allow-blank-lines-past-eob'.
|
|
148 ;;;;
|
|
149 ;;;; Dead space will be displayed if it is necessary in order to make a
|
|
150 ;;;; previous scrolling action reversible, however.
|
|
151 ;;;;
|
|
152 ;;;; + If the scrolling commands cannot keep point at its initial window
|
|
153 ;;;; position (because a buffer boundary is on screen and the window can't be
|
|
154 ;;;; scrolled as far as necessary to keep point at the right place), point is
|
|
155 ;;;; allowed to temporarily stray from its initial window position. That is,
|
|
156 ;;;; point moves the correct number of window lines, even if it means that it
|
|
157 ;;;; has to stray from its desired window position. This straying is undone
|
|
158 ;;;; when (and if) the scrolling action is reversed.
|
|
159 ;;;;
|
|
160 ;;;; + If a scrolling command tries to move point past a buffer boundary, point
|
|
161 ;;;; is instead moved to the boundary (the beginning or the end of the buffer
|
|
162 ;;;; as appropriate) and an appropriate message is displayed. This motion is
|
|
163 ;;;; reversible, of course.
|
|
164 ;;;;
|
|
165 ;;;; However, if point was already at the buffer boundary when the scrolling
|
|
166 ;;;; command was invoked, the command signals an appropriate error instead.
|
|
167 ;;;;
|
|
168 ;;;; + When a minibuffer window is the selected window, the new versions of
|
|
169 ;;;; `scroll-up' and `scroll-down' either scroll the window in the variable
|
|
170 ;;;; `minibuffer-scroll-window' (which is usually the window of completions)
|
|
171 ;;;; or the `next-window' if there is no `minibuffer-scroll-window'. This is
|
|
172 ;;;; usually much more useful than scrolling the minibuffer itself. (Note
|
|
173 ;;;; that this feature is available even when the variable `scroll-in-place'
|
|
174 ;;;; is `nil'.)
|
|
175 ;;;;
|
|
176 ;;;; + When a scrolling command is scrolling a window other than the selected
|
|
177 ;;;; window, it will signal an appropriate buffer boundary error if the
|
|
178 ;;;; window cannot be scrolled (because the appropriate buffer boundary is
|
|
179 ;;;; already visible). This means that an error is signalled even in cases
|
|
180 ;;;; that would be allowed (by "straying" point or by moving it to the buffer
|
|
181 ;;;; boundary) if the window were selected.
|
|
182 ;;;;
|
|
183 ;;;; (If an error were not signalled in these cases, then there would be many
|
|
184 ;;;; cases in which the last scroll in a particular direction would appear to
|
|
185 ;;;; do nothing because only the point position would change --- the
|
|
186 ;;;; displayed text would stay the same! To avoid these cases the scrolling
|
|
187 ;;;; commands signal boundary errors "prematurely" when the window to be
|
|
188 ;;;; scrolled is not selected.)
|
|
189 ;;;;
|
|
190 ;;;; So how is this package different than Joe Wells' "scroll-fix" package?
|
|
191 ;;;;
|
|
192 ;;;; + This package provides "in place" behavior for the standard GNU Emacs
|
|
193 ;;;; commands by default; "scroll-fix" does not.
|
|
194 ;;;;
|
|
195 ;;;; + "scroll-fix" behaves differently when the window is near a buffer
|
|
196 ;;;; boundary. Instead of allowing point to stray, "scroll-fix" first does
|
|
197 ;;;; an incomplete scroll (i.e., moves point less than the full distance in
|
|
198 ;;;; order to keep point at the desired window position) and then pops point
|
|
199 ;;;; to the buffer boundary. I think that the behavior of this package is
|
|
200 ;;;; somewhat move intuitive, especially for small scrolling distances.
|
|
201 ;;;;
|
|
202 ;;;; + The scrolling commands in this package will appropriately signal buffer
|
|
203 ;;;; boundary errors; the commands in "scroll-fix" never signal boundary
|
|
204 ;;;; errors. This makes it difficult to allow "scroll-fix" to replace the
|
|
205 ;;;; standard `scroll-down' and `scroll-up' commands because some other
|
|
206 ;;;; packages (e.g., VM and GNUS) expect the scrolling commands to signal
|
|
207 ;;;; these errors as necessary.
|
|
208 ;;;;
|
|
209 ;;;; + This package handles long lines correctly. (But see PROBLEMS, below.)
|
|
210 ;;;;
|
|
211 ;;;; + "scroll-fix" handles prefix arguments differently. In "scroll-fix", a
|
|
212 ;;;; number-containing prefix argument always breaks any running chain of
|
|
213 ;;;; scrolling commands. The prefix argument `-' (the symbol minus,
|
|
214 ;;;; generated by `C-u -') causes a temporary change in direction --- a
|
|
215 ;;;; change for only the current command. In this package, however, a
|
|
216 ;;;; number-containing prefix argument only breaks a running chain if it has
|
|
217 ;;;; a different magnitude than the default scrolling distance, and the
|
|
218 ;;;; prefix argument `-' causes a permanent change in the sign of the default
|
|
219 ;;;; scrolling distance --- a change visible to immediately subsequent
|
|
220 ;;;; scrolling commands.
|
|
221 ;;;;
|
|
222 ;;;; + This package keeps track of the set of "in place" scrolling commands
|
|
223 ;;;; dynamically, in order to detect "chains" of scrolling commands.
|
|
224 ;;;; "scroll-fix" has a fixed list of scrolling commands, so "scroll-fix"
|
|
225 ;;;; cannot keep track of some chains. (Again, "scroll-fix" interacts badly
|
|
226 ;;;; with VM and GNUS.) And because "scroll-fix" keeps a static list of
|
|
227 ;;;; scrolling commands, it is a bad idea to call its "in place" commands
|
|
228 ;;;; from a program. This package, because it maintains the information
|
|
229 ;;;; dynamically, has no such problems.
|
|
230 ;;;;
|
|
231 ;;;; + This package allows one to divide the "in place" scrolling commands into
|
|
232 ;;;; groups; a command in a group only forms chains with the members of its
|
|
233 ;;;; group. "scroll-fix" has no notion of command groups.
|
|
234 ;;;;
|
|
235 ;;;; + This package provides "in place" versions of the standard GNU Emacs
|
|
236 ;;;; commands `scroll-other-window-down' and `scroll-other-window'.
|
|
237 ;;;;
|
|
238 ;;;; + This package will refuse to scroll non-selected windows (by signalling
|
|
239 ;;;; an error) when the displayed text would not change, as described in the
|
|
240 ;;;; feature list above.
|
|
241 ;;;;
|
|
242 ;;;; + When a minibuffer window is selected, this package always scrolls a
|
|
243 ;;;; window other than the minibuffer. "scroll-fix" will scroll another
|
|
244 ;;;; window only if the entire minibuffer contents are visible.
|
|
245 ;;;;
|
|
246 ;;;; + "scroll-fix" provides a command to toggle the "in place" behavior of the
|
|
247 ;;;; standard GNU Emacs commands. This package doesn't; you'll have to set
|
|
248 ;;;; the option manually with the command `set-variable'.
|
|
249 ;;;;
|
|
250 ;;;; + This package has gratuitous variable renaming (insert smile here!):
|
|
251 ;;;;
|
|
252 ;;;; "scroll-fix" user variable Equivalent in this package
|
|
253 ;;;; -----------------------------------------------------------------------
|
|
254 ;;;; scroll-in-place (none)
|
|
255 ;;;; scroll-in-place-replace-original scroll-in-place
|
|
256 ;;;; scroll-in-place-eob-blank-allowed scroll-allow-blank-lines-past-eob
|
|
257 ;;;;
|
|
258 ;;;; + This package allows programmers to specify the default scrolling
|
|
259 ;;;; distance (i.e., the default distance used when starting a new chain of
|
|
260 ;;;; scrolling commands) for custom scrolling commands.
|
|
261
|
|
262 ;;;; COMMANDS AND FUNCTIONS
|
|
263 ;;;;
|
|
264 ;;;; This package provides the following "in place" versions of GNU Emacs'
|
|
265 ;;;; standard vertical scrolling commands:
|
|
266 ;;;;
|
|
267 ;;;; scroll-down-in-place
|
|
268 ;;;; scroll-up-in-place
|
|
269 ;;;; scroll-other-window-down-in-place
|
|
270 ;;;; scroll-other-window-in-place
|
|
271 ;;;;
|
|
272 ;;;; The variable `scroll-in-place', which is true by default, determines
|
|
273 ;;;; whether or not the new versions of the standard GNU Emacs scrolling
|
|
274 ;;;; commands (`scroll-down', `scroll-up', `scroll-other-window-down', and
|
|
275 ;;;; `scroll-other-window') use the "in place" features listed above. When
|
|
276 ;;;; `scroll-in-place' is `nil' the standard GNU Emacs scrolling commands
|
|
277 ;;;; essentially just call the original versions of themselves. (Note that
|
|
278 ;;;; even when `scroll-in-place' is `nil' the new versions of `scroll-down' and
|
|
279 ;;;; `scroll-up' have slightly different behavior when a minibuffer window is
|
|
280 ;;;; the selected window. See the feature list above.)
|
|
281 ;;;;
|
|
282 ;;;; NOTE that this package redefines the standard GNU Emacs commands `scroll-
|
|
283 ;;;; down', `scroll-up', `scroll-other-window-down', and `scroll-other-window'
|
|
284 ;;;; (in order to check the variable `scroll-in-place', as described above).
|
|
285 ;;;; The command `scroll-other-window-down' first appeared as a standard
|
|
286 ;;;; command in the FSF's GNU Emacs 19.26.
|
|
287 ;;;;
|
|
288 ;;;; This package also provides the following functions and variables which are
|
|
289 ;;;; of use to programmers:
|
|
290 ;;;;
|
|
291 ;;;; scroll-window
|
|
292 ;;;; scroll-window-in-place
|
|
293 ;;;; scroll-window-in-place-continue-sequence
|
|
294 ;;;; scroll-default-lines (variable)
|
|
295 ;;;; scroll-command-groups (variable)
|
|
296 ;;;;
|
|
297 ;;;; The `scroll-window-in-place' function is the heart of the "in place"
|
|
298 ;;;; scrolling commands. `scroll-window' is a function that checks the
|
|
299 ;;;; variable `scroll-in-place' and calls the appropriate scrolling function
|
|
300 ;;;; (either `scroll-window-in-place' or one of the original versions of
|
|
301 ;;;; `scroll-down' and `scroll-up'). The function `scroll-window-in-place-
|
|
302 ;;;; continue-sequence' is provided in order to preserve running "chains" of
|
|
303 ;;;; scrolling commands as described above.
|
|
304 ;;;;
|
|
305 ;;;; The variable `scroll-default-lines' determines the default scrolling
|
|
306 ;;;; distance when a new chain of "in place" scrolling commands begins. If
|
|
307 ;;;; this variable is not a number, then the default distance is the height of
|
|
308 ;;;; the window to be scrolled minus `next-screen-context-lines'. The variable
|
|
309 ;;;; `scroll-command-groups' contains the explicit groups of "in place"
|
|
310 ;;;; scrolling commands; for more information read the variable documentation.
|
|
311
|
|
312 ;;;; YOUR .EMACS FILE
|
|
313 ;;;;
|
|
314 ;;;; To use this package, you simply need to load it from within your ".emacs"
|
|
315 ;;;; file:
|
|
316 ;;;;
|
|
317 ;;;; (require 'scroll-in-place)
|
|
318 ;;;;
|
|
319 ;;;; By default, this package provides for the standard GNU Emacs vertical
|
|
320 ;;;; scrolling commands (`scroll-down', `scroll-up', `scroll-other-window-
|
|
321 ;;;; down', and `scroll-other-window') to use the "in place" features. If you
|
|
322 ;;;; would rather not have this, set the variable `scroll-in-place' to `nil':
|
|
323 ;;;;
|
|
324 ;;;; (setq scroll-in-place nil)
|
|
325 ;;;;
|
|
326 ;;;; When `scroll-in-place' is `nil' you will have to bind keys in order to
|
|
327 ;;;; call the "in place" scrolling commands. For example, you might want to do
|
|
328 ;;;; the following:
|
|
329 ;;;;
|
|
330 ;;;; (global-set-key "\M-v" 'scroll-down-in-place)
|
|
331 ;;;; (global-set-key "\C-v" 'scroll-up-in-place)
|
|
332 ;;;;
|
|
333 ;;;; Sun users should also read the PROBLEMS section, below.
|
|
334 ;;;;
|
|
335 ;;;; ADVANCED CUSTOMIZATION
|
|
336 ;;;;
|
|
337 ;;;; If you want to partition certain "in place" scrolling commands into
|
|
338 ;;;; separate groups, you should do something like the following:
|
|
339 ;;;;
|
|
340 ;;;; ;; Make one group containing the commands `scroll-down-one-line' and
|
|
341 ;;;; ;; `scroll-up-one-line'. (These are not standard GNU Emacs commands.)
|
|
342 ;;;; (setq scroll-command-groups
|
|
343 ;;;; (list '(scroll-down-one-line scroll-up-one-line)))
|
|
344 ;;;;
|
|
345 ;;;; You could write the `scroll-down-one-line' command like this:
|
|
346 ;;;;
|
|
347 ;;;; (defun scroll-down-one-line (arg)
|
|
348 ;;;; "Scroll down one line, or number of lines specified by prefix arg."
|
|
349 ;;;; (interactive "P")
|
|
350 ;;;; (let ((scroll-default-lines 1))
|
|
351 ;;;; (scroll-down-in-place arg)))
|
|
352 ;;;;
|
|
353 ;;;; If you want to disable "in place" scrolling for windows that display a
|
|
354 ;;;; particular buffer (while leaving it available in other windows), you can
|
|
355 ;;;; make `scroll-in-place' a buffer-local variable for that buffer and then
|
|
356 ;;;; bind that local copy of `scroll-in-place' to `nil'. This is the kind of
|
|
357 ;;;; thing that one generally does in a major mode hook. For example, you can
|
|
358 ;;;; disable "in place" scrolling of GNUS article windows with the following
|
|
359 ;;;; code:
|
|
360 ;;;;
|
|
361 ;;;; (setq gnus-article-mode-hook
|
|
362 ;;;; (function (lambda ()
|
|
363 ;;;; (make-local-variable 'scroll-in-place)
|
|
364 ;;;; (setq scroll-in-place nil))))
|
|
365 ;;;; ;; Set the variable `gnus-Article-mode-hook' instead if you are using
|
|
366 ;;;; ;; an old version of GNUS, say version 3.13 or 3.14.
|
|
367 ;;;;
|
|
368 ;;;; The variable `scroll-allow-blank-lines-past-eob' can also be made local to
|
|
369 ;;;; particular buffers, if you desire. (But why would you want to do that?)
|
|
370
|
|
371 ;;;; PROBLEMS
|
|
372 ;;;;
|
|
373 ;;;; + It is sometimes difficult for one's eyes to follow an incomplete scroll
|
|
374 ;;;; (i.e., a scroll in which the text doesn't move as far as one expected),
|
|
375 ;;;; especially when the scrolled window is not selected (and therefore that
|
|
376 ;;;; window's point is not highlighted). One can lose one's place in the
|
|
377 ;;;; text.
|
|
378 ;;;;
|
|
379 ;;;; + The names `scroll-down-in-place' and `scroll-up-in-place' conflict with
|
|
380 ;;;; two commands in the GNU Emacs terminal-specific file "term/sun.el".
|
|
381 ;;;; This means that in order to load this package correctly, Sunterm users
|
|
382 ;;;; will have to use the hook `term-setup-hook'. For example, you might put
|
|
383 ;;;; the following form in your ".emacs" file:
|
|
384 ;;;;
|
|
385 ;;;; (setq term-setup-hook (function (lambda () (require 'scroll-in-place))))
|
|
386 ;;;;
|
|
387 ;;;; If this is confusing, get help from your local GNU Emacs guru.
|
|
388 ;;;;
|
|
389 ;;;; + `scroll-determine-goal-column' tries to honor the variable `track-eol'
|
|
390 ;;;; if it is set. But when lines are being wrapped we can't move point past
|
|
391 ;;;; the wrap --- or else it is possible that scrolling won't work correctly.
|
|
392 ;;;; In short, this package honors `track-eol' as best it can.
|
|
393 ;;;;
|
|
394 ;;;; + `scroll-window-in-place' can become confused when something changes the
|
|
395 ;;;; window "out from under it." By "confused" I mean that it is possible
|
|
396 ;;;; for `scroll-window-in-place' to think that it should continue the
|
|
397 ;;;; running sequence of "in place" scrolls when it should really probably
|
|
398 ;;;; start a new sequence. For example, if a process filter inserts text
|
|
399 ;;;; into the buffer and moves point, `scroll-window-in-place' loses track of
|
|
400 ;;;; where point should be and where the window should start. Commands that
|
|
401 ;;;; call a "scroll in place" function and then subsequently move point can
|
|
402 ;;;; also confuse `scroll-window-in-place'.
|
|
403 ;;;;
|
|
404 ;;;; To correct some of this confusion, `scroll-window-in-place' could keep
|
|
405 ;;;; track of the final positions of `window-start' and `window-point',
|
|
406 ;;;; possibly with both markers and character positions. In my experience
|
|
407 ;;;; the "in place" scrolling commands are almost never confused (except by
|
|
408 ;;;; fancy packages that do their own fancy kinds of scrolling, as described
|
|
409 ;;;; below), so the extra sanity checking isn't worth the effort. If your
|
|
410 ;;;; mileage varies let me know.
|
|
411 ;;;;
|
|
412 ;;;; + The "in place" scrolling commands can interact poorly with packages that
|
|
413 ;;;; provide their own special scrolling commands. For example, there are
|
|
414 ;;;; varying degrees of conflict with Rmail, VM, and GNUS.
|
|
415 ;;;;
|
|
416 ;;;; RMAIL
|
|
417 ;;;;
|
|
418 ;;;; In the version of Rmail that is part of the FSF's GNU Emacs 19 (19.25
|
|
419 ;;;; through 19.28 at least), the command `rmail-summary-scroll-msg-down' in
|
|
420 ;;;; the file "rmailsum.el" fails to work properly when "in place" scrolling
|
|
421 ;;;; is enabled for the Rmail message buffer. (The source of the conflict:
|
|
422 ;;;; the "in place" scrolling commands and Emacs' standard scrolling commands
|
|
423 ;;;; interpret the argument '- in different ways.) Fortunately it is easy to
|
|
424 ;;;; patch Rmail. Send me mail if you would like to receive a copy of these
|
|
425 ;;;; patches.
|
|
426 ;;;;
|
|
427 ;;;; I know of no conflicts between the "in place" scrolling commands and
|
|
428 ;;;; older versions of Rmail (i.e., versions that came with GNU Emacs 18).
|
|
429 ;;;;
|
|
430 ;;;; VM
|
|
431 ;;;;
|
|
432 ;;;; `scroll-window-in-place' is *very* confused by VM 5's message scrolling
|
|
433 ;;;; commands, especially because VM 5 rebuilds Emacs' window configuration
|
|
434 ;;;; from scratch so often. I have written an experimental set of patches
|
|
435 ;;;; for VM 5.70 that allows VM 5 to use the "scroll-in-place" features; send
|
|
436 ;;;; me mail if you would like to receive a copy of these patches. I hope
|
|
437 ;;;; that someday my patches will be incorporated into VM.
|
|
438 ;;;;
|
|
439 ;;;; `scroll-window-in-place' is not confused by VM 4.41's message scrolling
|
|
440 ;;;; commands, however.
|
|
441 ;;;;
|
|
442 ;;;; GNUS
|
|
443 ;;;;
|
|
444 ;;;; `scroll-window-in-place' can be *slightly* confused by GNUS' article
|
|
445 ;;;; scrolling commands because they move point to the last line of the
|
|
446 ;;;; article window and then scroll the text. (This is the case for at least
|
|
447 ;;;; GNUS versions 3.13 through 4.1, inclusive.) The potential conflict is
|
|
448 ;;;; so minor, however, that you'll probably never notice it. I never do.
|
|
449 ;;;;
|
|
450 ;;;; A severe conflict, however, exists between the "in place" scrolling
|
|
451 ;;;; commands and the add-on "gnus-hide" package. "gnus-hide" can elide
|
|
452 ;;;; signatures at the ends of articles but it does so in a way that causes
|
|
453 ;;;; `scroll-window-in-place', as invoked by the GNUS scrolling commands, not
|
|
454 ;;;; to signal end-of-buffer conditions at the right times. Someday I may
|
|
455 ;;;; write new article scrolling commands for GNUS.
|
|
456 ;;;;
|
|
457 ;;;; + Process filters that call scrolling functions can cause confusion. They
|
|
458 ;;;; may break running chains of "in place" scrolling commands and they may
|
|
459 ;;;; set up inappropriate defaults for future scrolling commands. Maybe this
|
|
460 ;;;; is a moot problem, as I am currently unaware of any process filters that
|
|
461 ;;;; invoke scrolling commands (although many filters move point around,
|
|
462 ;;;; which will also confuse `scroll-window-in-place').
|
|
463
|
76
|
464 ;; sb -- Added turn-on and turn-off hook functions to prepare for making this
|
|
465 ;; a standardly dumped package with XEmacs.
|
|
466
|
0
|
467 ;; (provide 'scroll-in-place) at the end of this file.
|
|
468
|
|
469
|
|
470 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
471 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
472 ;;;;
|
|
473 ;;;; Here are the variable declarations, both user options and internal
|
|
474 ;;;; variables.
|
|
475 ;;;;
|
|
476 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
477 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
478
|
|
479 (defvar scroll-in-place t
|
|
480 "*When this variable is true (i.e., non-`nil'), the standard GNU Emacs
|
|
481 vertical scrolling commands `scroll-down', `scroll-up', `scroll-other-window-
|
|
482 down', and `scroll-other-window' will attempt to keep point at its current
|
|
483 position in the window (window line and column). In other words, point stays
|
|
484 \"in place\" within the window.
|
|
485
|
|
486 When this variable is `nil' the standard GNU Emacs vertical scrolling commands
|
|
487 behave as usual. The \"in place\" equivalents, however, are still available as
|
|
488 separate commands.
|
|
489
|
|
490 This variable may be made buffer-local in order to disable (or enable) \"in
|
|
491 place\" scrolling in particular buffers."
|
|
492 ;; I have thought about dividing `scroll-in-place' into three variables: a
|
|
493 ;; list of commands that always scroll in place, a list of commands that
|
|
494 ;; never scroll in place, and a flag that determines the default behavior of
|
|
495 ;; other scrolling commands. This could make it easier to make "in place"
|
|
496 ;; scrolling the default because one could single out certain ill-behaved
|
|
497 ;; commands. But as of now I'm sure that the added complexity would really
|
|
498 ;; be worth it.
|
|
499 )
|
|
500
|
10
|
501 (defvar scroll-allow-blank-lines-past-eob nil
|
0
|
502 "*When this variable is `nil' the \"in place\" scrolling commands will avoid
|
|
503 displaying empty lines past the end of the buffer text. In other words, just
|
|
504 as you can't see \"dead space\" before the beginning of the buffer text, the
|
|
505 \"in place\" scrolling commands try to avoid displaying \"dead space\" past the
|
|
506 end of the buffer text. This helps make the most of window real estate.
|
|
507
|
|
508 Note that sometimes it is necessary to display \"dead space\" in order to make
|
|
509 a previous scrolling action reversible.
|
|
510
|
|
511 When this variable is non-`nil' the \"in place\" scrolling commands will always
|
|
512 allow blank lines to be shown past the end of the buffer.")
|
|
513
|
|
514 ;;;;
|
|
515 ;;;; The following variables are not user options, but are intended to be set
|
|
516 ;;;; by code outside this package.
|
|
517 ;;;;
|
|
518
|
|
519 (defvar scroll-default-lines nil
|
|
520 "The default number of lines to be scrolled by when a new sequence of \"in
|
|
521 place\" scrolling commands begins. Of course, when an explicit number of lines
|
|
522 is specified, that explicit number takes precedence. See the documentation for
|
|
523 the function `scroll-window-in-place' for more information.
|
|
524
|
|
525 If this variable is not bound to a number, then the default number of lines is
|
|
526 the height of the window to be scrolled minus `next-screen-context-lines'.
|
|
527
|
|
528 This variable should not be set globally! Commands that want to specify a
|
|
529 default scrolling distance should just bind the variable `scroll-default-lines'
|
|
530 temporarily.")
|
|
531
|
|
532 (defvar scroll-command-groups nil
|
|
533 "The explicitly specified \"groups\" of \"in place\" scrolling commands.
|
|
534 This variable should be set before or immediately after the \"in place\"
|
|
535 scrolling package is loaded, and then not changed after that.
|
|
536
|
|
537 Usually, \"in place\" scrolling commands share state (e.g., the number of lines
|
|
538 to scroll by) with any and all immediately previous \"in place\" scrolling
|
|
539 commands. Sometimes, however, this is undesirable. In these cases the \"in
|
|
540 place\" scrolling commands can be divided into groups. A command in a group
|
|
541 only shares state with members of its group.
|
|
542
|
|
543 Each element of `scroll-command-groups' is a list that contains all of the
|
|
544 members of a unique command group. For example, if there were only one
|
|
545 explicit group and that group contained the commands `scroll-down-one-line' and
|
|
546 `scroll-up-one-line', then `scroll-command-groups' would be set to:
|
|
547
|
|
548 ((scroll-down-one-line scroll-up-one-line))
|
|
549
|
|
550 Commands that are not in any explicitly specified group are added to a default
|
|
551 group. That group is stored in the variable `scroll-default-command-group'.
|
|
552
|
|
553 The \"in place\" scrolling functions assume that all of the scrolling command
|
|
554 groups are nonintersecting (i.e., no command is in more than one group) and
|
|
555 only contain \"in place\" scrolling commands.")
|
|
556
|
|
557 ;;;;
|
|
558 ;;;; The variables below this point are internal to this package.
|
|
559 ;;;;
|
|
560
|
|
561 (defvar scroll-default-command-group nil
|
|
562 "The set of \"in place\" scrolling commands that are not members of any
|
|
563 explicitly defined group of commands. This set of commands is an implicitly
|
|
564 defined group, constructed as \"in place\" commands are invoked, and members of
|
|
565 this group share state among themselves. See the documentation for the
|
|
566 variable `scroll-command-groups' for more information.")
|
|
567
|
|
568 (defvar scroll-initially-displayed-lines 0
|
|
569 "The number of window lines that contained buffer text when the current
|
|
570 sequence of \"in place\" scrolling commands started. Unless the variable
|
|
571 `scroll-in-place-allow-blank-lines-past-eob' is true, the \"in place\"
|
|
572 scrolling commands ensure that at least this many text lines are visible at all
|
|
573 times.")
|
|
574
|
|
575 (defvar scroll-previous-window nil
|
|
576 "The window that was most recently scrolled by an \"in place\" scrolling
|
|
577 command.")
|
|
578
|
|
579 (defvar scroll-previous-lines 0
|
|
580 "The number of window lines that the previous \"in place\" scrolling command
|
|
581 attempted to scroll.")
|
|
582
|
|
583 (defvar scroll-goal-column 0
|
|
584 "The desired horizontal window position for point, used by the \"in place\"
|
|
585 scrolling commands.")
|
|
586
|
|
587 (defvar scroll-boundary-previous-point nil
|
|
588 "The value of point before point was moved to a buffer boundary.")
|
|
589
|
|
590 (defvar scroll-boundary-previous-lines 0
|
|
591 "The number of lines that point moved when it moved to a buffer boundary.")
|
|
592
|
|
593 (defvar scroll-boundary-error-command nil
|
|
594 "The value of `this-command' when an \"in place\" scrolling command signalled
|
|
595 a buffer boundary error. This is used to decide how subsequent scrolling
|
|
596 commands should recover from the error.")
|
|
597
|
|
598 (defvar scroll-boundary-error-point nil
|
|
599 "The value of point when an \"in place\" scrolling command signalled a buffer
|
|
600 boundary error. This is used to decide how subsequent scrolling commands
|
|
601 should recover from the error."
|
|
602 ;; This variable is used as a flag, indicating whether or not the previous
|
|
603 ;; "in place" scrolling command signalled an error.
|
|
604 )
|
|
605
|
|
606 (defvar scroll-window-debt 0
|
|
607 "The difference between the number of lines an \"in place\" scrolling command
|
|
608 tried to scroll a window and the number of lines that the window actually
|
|
609 scrolled. This difference is the \"debt\" in the window's starting position.
|
|
610 Subsequent \"in place\" scrolling commands try to make up this debt.")
|
|
611
|
|
612 (defconst scroll-pos-visible-bug-p
|
|
613 ;; On September 14, 1993, David Hughes <djh@Harston.CV.COM> told me that
|
|
614 ;; Lucid GNU Emacs 19.8 had inherited the bug from Epoch... sigh.
|
|
615 (let ((old-match-data (match-data)))
|
|
616 (unwind-protect
|
|
617 (or (and (boundp 'epoch::version)
|
|
618 (if (string-match "\\`4\\." emacs-version) t nil)
|
|
619 )
|
|
620 (and (string-match "Lucid" emacs-version)
|
|
621 (if (string-match "\\`19\\.8\\." emacs-version) t nil)
|
|
622 )
|
|
623 )
|
|
624 (store-match-data old-match-data)))
|
|
625 "A flag, set when this version of GNU Emacs has a buggy version of the
|
|
626 function `pos-visible-in-window-p' that returns `nil' when given `(point-max)'
|
|
627 and `(point-max)' is on the last line of the window. Currently, this flag is
|
|
628 set for all versions of Epoch 4 and for Lucid GNU Emacs 19.8.")
|
|
629
|
|
630
|
76
|
631 ;; Hook functions to make turning the mode on and off easier.
|
|
632 (defun turn-on-scroll-in-place ()
|
|
633 "Unconditionally turn on scroll-in-place mode."
|
|
634 (set (make-local-variable 'scroll-in-place) t))
|
|
635
|
|
636 (defun turn-off-scroll-in-place ()
|
|
637 "Unconditionally turn on scroll-in-place mode."
|
|
638 (set (make-local-variable 'scroll-in-place) nil))
|
|
639
|
|
640
|
0
|
641 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
642 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
643 ;;;;
|
|
644 ;;;; Here are the window-choosing auxiliary functions used by the new scrolling
|
|
645 ;;;; commands.
|
|
646 ;;;;
|
|
647 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
648 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
649
|
|
650 (defun scroll-choose-window ()
|
|
651 "Choose the window to be scrolled by the commands `scroll-down', `scroll-up',
|
|
652 `scroll-down-in-place', and `scroll-up-in-place'.
|
|
653
|
|
654 The rules are simple. If the selected window is not a minibuffer window, then
|
|
655 just choose the selected window.
|
|
656
|
|
657 However, when a minibuffer window is selected, look first for the `minibuffer-
|
|
658 scroll-window'. The `minibuffer-scroll-window' is usually the window that
|
|
659 displays completions. If it exists, choose it; otherwise choose the next
|
|
660 window after the selected window in the canonical ordering of windows. The
|
|
661 next window is generally the one below the selected window, or the one at the
|
|
662 top of the screen if the selected window is at the bottom of the screen."
|
|
663 (let ((selected-window (selected-window)))
|
|
664 (if (window-minibuffer-p selected-window)
|
|
665 ;; A minibuffer window is selected --- scroll some other window.
|
|
666 (if (window-live-p minibuffer-scroll-window)
|
|
667 minibuffer-scroll-window
|
|
668 ;; We know that the (selected) minibuffer is active, so `next-window'
|
|
669 ;; will examine all of the frames that share this minibuffer.
|
|
670 ;; Should we consider `other-window-scroll-buffer' here? I don't
|
|
671 ;; believe so.
|
|
672 (next-window selected-window))
|
|
673 selected-window)))
|
|
674
|
|
675 ;;;
|
|
676 ;;;
|
|
677 ;;;
|
|
678
|
|
679 (defun scroll-choose-other-window ()
|
|
680 "Choose the window to be scrolled by the commands `scroll-other-window-down',
|
|
681 `scroll-other-window', `scroll-other-window-down-in-place', and `scroll-other-
|
|
682 window-in-place'.
|
|
683
|
|
684 The rules are these. If the selected window is not a minibuffer window, then
|
|
685 choose either:
|
|
686
|
|
687 + a window that displays the `other-window-scroll-buffer', if that buffer
|
|
688 exists. Note, this function will display that buffer if necessary.
|
|
689
|
|
690 + the next window after the selected window in the canonical ordering of
|
|
691 windows. The next window is generally the one below the selected window,
|
|
692 or the one at the top of the screen if the selected window is at the bottom
|
|
693 of the screen.
|
|
694
|
|
695 However, when a minibuffer window is selected, look first for the `minibuffer-
|
|
696 scroll-window'. The `minibuffer-scroll-window' is usually the window that
|
|
697 displays completions. If it exists, choose it; otherwise choose the window to
|
|
698 be scrolled as described above (`other-window-scroll-buffer' or next window).
|
|
699
|
|
700 This function is essentially a Lisp version of the function `other-window-for-
|
|
701 scrolling' which first appeared in the FSF's GNU Emacs 19.26."
|
|
702 (let* ((no-error nil)
|
|
703 (selected-window (selected-window))
|
|
704 (other-window nil))
|
|
705 (setq other-window
|
|
706 (cond ((and (window-minibuffer-p selected-window)
|
|
707 (window-live-p minibuffer-scroll-window))
|
|
708 ;; Don't signal an error when `minibuffer-scroll-window' is
|
|
709 ;; the minibuffer itself --- which would be really weird, but
|
|
710 ;; isn't necessarily erroneous.
|
|
711 (setq no-error t)
|
|
712 minibuffer-scroll-window)
|
|
713
|
|
714 ((and ;; `other-window-scroll-buffer' is an Emacs 19 invention.
|
|
715 (boundp 'other-window-scroll-buffer)
|
|
716 (bufferp other-window-scroll-buffer)
|
|
717 ;; `buffer-name' is `nil' if the buffer has been killed.
|
|
718 (buffer-name other-window-scroll-buffer))
|
|
719 ;; This is what FSF GNU Emacs 19.26 does, but it occurred to
|
|
720 ;; me: what if one of these forms returns the selected window?
|
|
721 ;; Signalling an error would be bad news, so I added a flag.
|
|
722 (setq no-error t)
|
|
723 (or (get-buffer-window other-window-scroll-buffer)
|
|
724 (display-buffer other-window-scroll-buffer t)))
|
|
725
|
|
726 ((let ((next-window (next-window selected-window)))
|
|
727 (if (eq next-window selected-window)
|
|
728 nil
|
|
729 next-window)))
|
|
730
|
|
731 (t
|
|
732 ;; In Emacs 19 (FSF, Lucid, and XEmacs), look for a window on
|
|
733 ;; another visible frame. This could be written for
|
|
734 ;; Epoch, too, I suppose...
|
|
735 (condition-case nil
|
|
736 (let ((this-window (next-window selected-window nil t)))
|
|
737 (while (not (or (eq this-window selected-window)
|
|
738 (scroll-choose-window-frame-visible-p
|
|
739 this-window)))
|
|
740 (setq this-window (next-window this-window nil t)))
|
|
741 this-window)
|
|
742 ;; In older versions of Emacs, `next-window' didn't accept
|
|
743 ;; three arguments. Catch this error and then return the
|
|
744 ;; selected window --- which will cause another error to be
|
|
745 ;; signalled later on.
|
|
746 (wrong-number-of-arguments selected-window))
|
|
747 )
|
|
748 ))
|
|
749
|
|
750 (if (and (not no-error)
|
|
751 (eq selected-window other-window))
|
|
752 (error "There is no other window."))
|
|
753 other-window))
|
|
754
|
|
755 ;;;
|
|
756 ;;;
|
|
757 ;;;
|
|
758
|
|
759 (defun scroll-choose-window-frame-visible-p (window)
|
|
760 "Return a true value if the frame of the given WINDOW is visible."
|
|
761 (cond ((fboundp 'window-frame)
|
|
762 (eq t (frame-visible-p (window-frame window))))
|
|
763 (t t)))
|
|
764
|
|
765
|
|
766 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
767 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
768 ;;;;
|
|
769 ;;;; Here are the "in place" scrolling commands (interactive functions) and the
|
|
770 ;;;; replacements for the standard GNU Emacs vertical scrolling commands.
|
|
771 ;;;;
|
|
772 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
773 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
774
|
|
775 ;;;;
|
|
776 ;;;; Here are the new scroll "in place" commands.
|
|
777 ;;;;
|
|
778
|
|
779 (defun scroll-down-in-place (&optional lines)
|
|
780 "Scroll the text of the current window downward by LINES lines, leaving point
|
|
781 as close as possible to its current window position (window line and column).
|
|
782 In other words, point is left \"in place\" within the window. As a special
|
|
783 case, when the current window is a minibuffer window, this command scrolls the
|
|
784 `minibuffer-scroll-window' (which is usually the list of completions) if it
|
|
785 exists, or otherwise the next window in the canonical ordering of windows.
|
|
786
|
|
787 If the optional argument LINES is `nil', scroll the window by the same amount
|
|
788 it was moved by the immediately previous \"in place\" scrolling command, or by
|
|
789 the value of the variable `scroll-default-lines' (usually almost a windowful)
|
|
790 if the previous command was not an \"in place\" scrolling command (or when that
|
|
791 previous command scrolled some other window, or when other circumstances
|
|
792 prevent the previous scrolling distance from being used). If LINES is the
|
|
793 symbol `-', then the scrolling distance is determined as if LINES had been
|
|
794 `nil' and then that distance is multiplied by -1.
|
|
795
|
|
796 If the window cannot be scrolled by the full distance, point is allowed to
|
|
797 stray from its initial position so that it can move the full number of lines.
|
|
798 If point cannot move the full number of lines, point is moved to the buffer
|
|
799 boundary. Any immediately subsequent \"in place\" scrolling commands will try
|
|
800 to restore point to its initial window position."
|
|
801 (interactive "P")
|
|
802 (scroll-window-in-place (scroll-choose-window) lines -1))
|
|
803
|
|
804 ;;;
|
|
805 ;;;
|
|
806 ;;;
|
|
807
|
|
808 (defun scroll-up-in-place (&optional lines)
|
|
809 "Scroll the text of the current window upward by LINES lines, leaving point
|
|
810 as close as possible to its current window position (window line and column).
|
|
811 In other words, point is left \"in place\" within the window. As a special
|
|
812 case, when the current window is a minibuffer window, this command scrolls the
|
|
813 `minibuffer-scroll-window' (which is usually the list of completions) if it
|
|
814 exists, or otherwise the next window in the canonical ordering of windows.
|
|
815
|
|
816 If the optional argument LINES is `nil', scroll the window by the same amount
|
|
817 it was moved by the immediately previous \"in place\" scrolling command, or by
|
|
818 the value of the variable `scroll-default-lines' (usually almost a windowful)
|
|
819 if the previous command was not an \"in place\" scrolling command (or when that
|
|
820 previous command scrolled some other window, or when other circumstances
|
|
821 prevent the previous scrolling distance from being used). If LINES is the
|
|
822 symbol `-', then the scrolling distance is determined as if LINES had been
|
|
823 `nil' and then that distance is multiplied by -1.
|
|
824
|
|
825 If the window cannot be scrolled by the full distance, point is allowed to
|
|
826 stray from its initial position so that it can move the full number of lines.
|
|
827 If point cannot move the full number of lines, point is moved to the buffer
|
|
828 boundary. Any immediately subsequent \"in place\" scrolling commands will try
|
|
829 to restore point to its initial window position."
|
|
830 (interactive "P")
|
|
831 (scroll-window-in-place (scroll-choose-window) lines 1))
|
|
832
|
|
833 ;;;
|
|
834 ;;; The command `scroll-other-window-down' first appeared in FSF GNU Emacs
|
|
835 ;;; 19.26.
|
|
836 ;;;
|
|
837
|
|
838 (defun scroll-other-window-down-in-place (&optional lines)
|
|
839 "Scroll the text of the next window downward by LINES lines, leaving point in
|
|
840 that window as close as possible to its current window position (window line
|
|
841 and column). In other words, point is left \"in place\" within the window.
|
|
842 The next window is generally the one below the current one, or the one at the
|
|
843 top of the screen if the current window is at the bottom of the screen. In
|
|
844 special circumstances this command will scroll a window other than the next
|
|
845 window. Read the documentation for the function `scroll-choose-other-window'
|
|
846 for details.
|
|
847
|
|
848 If the optional argument LINES is `nil', scroll the window by the same amount
|
|
849 it was moved by the immediately previous \"in place\" scrolling command, or by
|
|
850 the value of the variable `scroll-default-lines' (usually almost a windowful)
|
|
851 if the previous command was not an \"in place\" scrolling command (or when that
|
|
852 previous command scrolled some other window, or when other circumstances
|
|
853 prevent the previous scrolling distance from being used). If LINES is the
|
|
854 symbol `-', then the scrolling distance is determined as if LINES had been
|
|
855 `nil' and then that distance is multiplied by -1.
|
|
856
|
|
857 If the window cannot be scrolled by the full distance, point is allowed to
|
|
858 stray from its initial position so that it can move the full number of lines.
|
|
859 If point cannot move the full number of lines, point is moved to the buffer
|
|
860 boundary. Any immediately subsequent \"in place\" scrolling commands will try
|
|
861 to restore point to its initial window position.
|
|
862
|
|
863 If it is impossible to scroll the text of the window at all (because a buffer
|
|
864 boundary is already visible), this command signals a buffer boundary error.
|
|
865 The error is signalled even if point could otherwise move the full number of
|
|
866 lines."
|
|
867 (interactive "P")
|
|
868 (scroll-window-in-place (scroll-choose-other-window) lines -1))
|
|
869
|
|
870 ;;;
|
|
871 ;;;
|
|
872 ;;;
|
|
873
|
|
874 (defun scroll-other-window-in-place (&optional lines)
|
|
875 "Scroll the text of the next window upward by LINES lines, leaving point in
|
|
876 that window as close as possible to its current window position (window line
|
|
877 and column). In other words, point is left \"in place\" within the window.
|
|
878 The next window is generally the one below the current one, or the one at the
|
|
879 top of the screen if the current window is at the bottom of the screen. In
|
|
880 special circumstances this command will scroll a window other than the next
|
|
881 window. Read the documentation for the function `scroll-choose-other-window'
|
|
882 for details.
|
|
883
|
|
884 If the optional argument LINES is `nil', scroll the window by the same amount
|
|
885 it was moved by the immediately previous \"in place\" scrolling command, or by
|
|
886 the value of the variable `scroll-default-lines' (usually almost a windowful)
|
|
887 if the previous command was not an \"in place\" scrolling command (or when that
|
|
888 previous command scrolled some other window, or when other circumstances
|
|
889 prevent the previous scrolling distance from being used). If LINES is the
|
|
890 symbol `-', then the scrolling distance is determined as if LINES had been
|
|
891 `nil' and then that distance is multiplied by -1.
|
|
892
|
|
893 If the window cannot be scrolled by the full distance, point is allowed to
|
|
894 stray from its initial position so that it can move the full number of lines.
|
|
895 If point cannot move the full number of lines, point is moved to the buffer
|
|
896 boundary. Any immediately subsequent \"in place\" scrolling commands will try
|
|
897 to restore point to its initial window position.
|
|
898
|
|
899 If it is impossible to scroll the text of the window at all (because a buffer
|
|
900 boundary is already visible), this command signals a buffer boundary error.
|
|
901 The error is signalled even if point could otherwise move the full number of
|
|
902 lines."
|
|
903 (interactive "P")
|
|
904 (scroll-window-in-place (scroll-choose-other-window) lines 1))
|
|
905
|
|
906 ;;;;
|
|
907 ;;;; Here are the replacements for GNU Emacs' standard vertical scrolling
|
|
908 ;;;; commands.
|
|
909 ;;;;
|
|
910
|
|
911 (or (fboundp 'original-scroll-down)
|
|
912 (fset 'original-scroll-down (symbol-function 'scroll-down)))
|
|
913 (or (fboundp 'original-scroll-up)
|
|
914 (fset 'original-scroll-up (symbol-function 'scroll-up)))
|
|
915 (or (fboundp 'original-scroll-other-window-down)
|
|
916 ;; `scroll-other-window-down' first appeared in FSF GNU Emacs 19.26.
|
|
917 (if (fboundp 'scroll-other-window-down)
|
|
918 (fset 'original-scroll-other-window-down
|
|
919 (symbol-function 'scroll-other-window-down))
|
|
920 ))
|
|
921 (or (fboundp 'original-scroll-other-window)
|
|
922 (fset 'original-scroll-other-window (symbol-function 'scroll-other-window))
|
|
923 )
|
|
924
|
|
925 ;;;
|
|
926 ;;;
|
|
927 ;;;
|
|
928
|
|
929 (defun scroll-down (&optional lines)
|
|
930 "Scroll the text of the current window downward by LINES lines. As a special
|
|
931 case, when the current window is a minibuffer window, this command scrolls the
|
|
932 `minibuffer-scroll-window' (which is usually the list of completions) if it
|
|
933 exists, or otherwise the next window in the canonical ordering of windows.
|
|
934
|
|
935 The argument LINES is optional. Its meaning depends on the current value of
|
|
936 the variable `scroll-in-place'.
|
|
937
|
|
938 When the variable `scroll-in-place' is true, this command works just like the
|
|
939 command `scroll-down-in-place', scrolling the current window and leaving point
|
|
940 \"in place\" within the window. See the documentation for the command
|
|
941 `scroll-down-in-place' for more information.
|
|
942
|
|
943 When the variable `scroll-in-place' is `nil' this command invokes the standard
|
|
944 GNU Emacs version of `scroll-down'. In that case, when LINES is `nil' the
|
|
945 current window is scrolled by nearly a complete windowful of text.
|
|
946
|
|
947 Note that this command correctly handles cases in which `scroll-in-place' has a
|
|
948 buffer-local value in the window to be scrolled. That value is honored."
|
|
949 (interactive "P")
|
|
950 (scroll-window (scroll-choose-window) lines -1))
|
|
951
|
|
952 ;;;
|
|
953 ;;;
|
|
954 ;;;
|
|
955
|
|
956 (defun scroll-up (&optional lines)
|
|
957 "Scroll the text of the current window upward by LINES lines. As a special
|
|
958 case, when the current window is a minibuffer window, this command scrolls the
|
|
959 `minibuffer-scroll-window' (which is usually the list of completions) if it
|
|
960 exists, or otherwise the next window in the canonical ordering of windows.
|
|
961
|
|
962 The argument LINES is optional. Its meaning depends on the current value of
|
|
963 the variable `scroll-in-place'.
|
|
964
|
|
965 When the variable `scroll-in-place' is true, this command works just like the
|
|
966 command `scroll-up-in-place', scrolling the current window and leaving point
|
|
967 \"in place\" within the window. See the documentation for the command
|
|
968 `scroll-up-in-place' for more information.
|
|
969
|
|
970 When the variable `scroll-in-place' is `nil' this command invokes the standard
|
|
971 GNU Emacs version of `scroll-up'. In that case, when LINES is `nil' the
|
|
972 current window is scrolled by nearly a complete windowful of text.
|
|
973
|
|
974 Note that this command correctly handles cases in which `scroll-in-place' has a
|
|
975 buffer-local value in the window to be scrolled. That value is honored."
|
|
976 (interactive "P")
|
|
977 (scroll-window (scroll-choose-window) lines 1))
|
|
978
|
|
979 ;;;
|
|
980 ;;; NOTE that in the FSF GNU Emacs 19.26 version of `scroll-other-window-down',
|
|
981 ;;; the `lines' argument is required. I've left it optional in order to be
|
|
982 ;;; like `scroll-other-window'.
|
|
983 ;;;
|
|
984
|
|
985 (defun scroll-other-window-down (&optional lines)
|
|
986 "Scroll the text of the next window downward by LINES lines. The next window
|
|
987 is generally the one below the current one, or the one at the top of the screen
|
|
988 if the current window is at the bottom of the screen. In special circumstances
|
|
989 this command will scroll a window other than the next window. Read the
|
|
990 documentation for the function `scroll-choose-other-window' for details.
|
|
991
|
|
992 The argument LINES is optional. Its meaning depends on the current value of
|
|
993 the variable `scroll-in-place'.
|
|
994
|
|
995 When the variable `scroll-in-place' is true, this command works just like the
|
|
996 command `scroll-other-window-down-in-place', scrolling the next window and
|
|
997 leaving point \"in place\" within that window. See the documentation for the
|
|
998 command `scroll-other-window-down-in-place' for more information.
|
|
999
|
|
1000 When the variable `scroll-in-place' is `nil' this command invokes the standard
|
|
1001 GNU Emacs version of `scroll-other-window-down'. In that case, when LINES is
|
|
1002 `nil' the next window is scrolled by nearly a complete windowful of text.
|
|
1003 \(Note that `scroll-other-window-down' first appeared as a standard command in
|
|
1004 the FSF's GNU Emacs 19.26. If the builtin version of that command is not
|
|
1005 available in the current Emacs system, an equivalent action is invoked
|
|
1006 instead.)
|
|
1007
|
|
1008 Note that this command correctly handles cases in which `scroll-in-place' has a
|
|
1009 buffer-local value in the window to be scrolled. That value is honored."
|
|
1010 (interactive "P")
|
|
1011 ;; This code is similar to the body of `scroll-window', below.
|
|
1012 (let* ((other-window (scroll-choose-other-window))
|
|
1013 (other-window-buffer (window-buffer other-window)))
|
|
1014 (if ;; Allow `scroll-in-place' to be a buffer-local variable.
|
|
1015 (save-excursion (set-buffer other-window-buffer) scroll-in-place)
|
|
1016 (scroll-window-in-place other-window lines -1)
|
|
1017
|
|
1018 ;; Paranoid, we forcibly break any running sequence of "in place"
|
|
1019 ;; scrolling commands.
|
|
1020 (setq scroll-previous-window nil)
|
|
1021 ;; For XEmacs and Lucid GNU Emacs, preserve the region's state.
|
|
1022 (if (boundp 'zmacs-region-stays)
|
|
1023 (setq zmacs-region-stays t))
|
|
1024 (if (fboundp 'original-scroll-other-window-down)
|
|
1025 (original-scroll-other-window-down lines)
|
|
1026 ;; `scroll-other-window-down' first appeared as a builtin in FSF GNU
|
|
1027 ;; Emacs 19.26, so it may not be available in the current Emacs system.
|
|
1028 ;; Do the equivalent thing.
|
|
1029 (original-scroll-other-window (cond
|
|
1030 ((null lines) '-)
|
|
1031 ((eq lines '-) nil)
|
|
1032 (t (- (prefix-numeric-value lines)))
|
|
1033 ))
|
|
1034 ))
|
|
1035 ))
|
|
1036
|
|
1037 ;;;
|
|
1038 ;;;
|
|
1039 ;;;
|
|
1040
|
|
1041 (defun scroll-other-window (&optional lines)
|
|
1042 "Scroll the text of the next window upward by LINES lines. The next window
|
|
1043 is generally the one below the current one, or the one at the top of the screen
|
|
1044 if the current window is at the bottom of the screen. In special circumstances
|
|
1045 this command will scroll a window other than the next window. Read the
|
|
1046 documentation for the function `scroll-choose-other-window' for details.
|
|
1047
|
|
1048 The argument LINES is optional. Its meaning depends on the current value of
|
|
1049 the variable `scroll-in-place'.
|
|
1050
|
|
1051 When the variable `scroll-in-place' is true, this command works just like the
|
|
1052 command `scroll-other-window-in-place', scrolling the next window and leaving
|
|
1053 point \"in place\" within that window. See the documentation for the command
|
|
1054 `scroll-other-window-in-place' for more information.
|
|
1055
|
|
1056 When the variable `scroll-in-place' is `nil' this command invokes the standard
|
|
1057 GNU Emacs version of `scroll-other-window'. In that case, when LINES is `nil'
|
|
1058 the next window is scrolled by nearly a complete windowful of text.
|
|
1059
|
|
1060 Note that this command correctly handles cases in which `scroll-in-place' has a
|
|
1061 buffer-local value in the window to be scrolled. That value is honored."
|
|
1062 (interactive "P")
|
|
1063 ;; This code is similar to the body of `scroll-window', below.
|
|
1064 (let* ((other-window (scroll-choose-other-window))
|
|
1065 (other-window-buffer (window-buffer other-window)))
|
|
1066 (if ;; Allow `scroll-in-place' to be a buffer-local variable.
|
|
1067 (save-excursion (set-buffer other-window-buffer) scroll-in-place)
|
|
1068 (scroll-window-in-place other-window lines 1)
|
|
1069
|
|
1070 ;; Paranoid, we forcibly break any running sequence of "in place"
|
|
1071 ;; scrolling commands.
|
|
1072 (setq scroll-previous-window nil)
|
|
1073 ;; For XEmacs and Lucid GNU Emacs, preserve the region's state.
|
|
1074 (if (boundp 'zmacs-region-stays)
|
|
1075 (setq zmacs-region-stays t))
|
|
1076 (original-scroll-other-window lines))
|
|
1077 ))
|
|
1078
|
|
1079
|
|
1080 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1081 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1082 ;;;;
|
|
1083 ;;;; Here are the new functions `scroll-window-in-place', `scroll-window', and
|
|
1084 ;;;; `scroll-window-in-place-continue-sequence'. These functions are intended
|
|
1085 ;;;; to be available to programs outside this package.
|
|
1086 ;;;;
|
|
1087 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1088 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1089
|
|
1090 (defun scroll-window-in-place (window lines direction)
|
|
1091 "Scroll WINDOW vertically by the given number of window LINES in the given
|
|
1092 DIRECTION, leaving the window's point as close as possible to its original
|
|
1093 window position (window line and column). In other words, the window's point
|
|
1094 is left \"in place\" within the window.
|
|
1095
|
|
1096 Note that the window to be scrolled does not have to be the selected window,
|
|
1097 and that this function does not change which window is selected.
|
|
1098
|
|
1099 LINES specifies the number of window lines to scroll and is interpreted as if
|
|
1100 it were a raw prefix argument. If LINES is `nil', the window is scrolled by
|
|
1101 the amount it was moved by the immediately previous \"in place\" scrolling
|
|
1102 command, or by the value of the variable `scroll-default-lines' (by default,
|
|
1103 almost a windowful) if the previous command was not an \"in place\" scrolling
|
|
1104 command (or when WINDOW is not the previously scrolled window, or when the
|
|
1105 value of `this-command' is not in the same group as the previous scrolling
|
|
1106 command (see the documentation for the variable `scroll-command-groups'), or
|
|
1107 when other circumstances prevent the previous scrolling distance from being
|
|
1108 used). If LINES is the symbol `-', then the scrolling distance is determined
|
|
1109 as if LINES had been `nil' and then that distance is multiplied by -1.
|
|
1110
|
|
1111 DIRECTION determines the direction of the scrolling motion. The values -1 and
|
|
1112 `down' indicate downward motion; the values 1 and `up' indicate upward motion.
|
|
1113 Any other value causes an error.
|
|
1114
|
|
1115 If the window cannot be scrolled by the full distance (because the window hits
|
|
1116 the boundary of its buffer), the window's point is allowed to stray from its
|
|
1117 initial position so that it can move the full number of lines. If point cannot
|
|
1118 move the full number of lines, point is moved to the buffer boundary (unless it
|
|
1119 was already there, in which case a buffer boundary error is signalled instead).
|
|
1120 Any immediately subsequent \"in place\" scrolling commands will try to restore
|
|
1121 point to its initial window position.
|
|
1122
|
|
1123 Unless the variable `scroll-allow-blank-lines-past-eob' is true, this function
|
|
1124 avoids displaying blank lines past the end of the buffer except as necessary to
|
|
1125 make a previous \"in place\" scrolling action reversible. Effectively, this
|
|
1126 means that this function will not display any more past-end-of-buffer blank
|
|
1127 lines than were visible when the current sequence of \"in place\" scrolling
|
|
1128 commands started. When the variable `scroll-allow-blank-lines-past-eob' is
|
|
1129 true, this function will display as many blank lines as is necessary to keep
|
|
1130 point \"in place\" in the window.
|
|
1131
|
|
1132 Note that if WINDOW is not the selected window and it is impossible to scroll
|
|
1133 the text of WINDOW at all (because a buffer boundary is already visible), then
|
|
1134 this function signals a buffer boundary error. The error is signalled even if
|
|
1135 point could otherwise move the full number of lines."
|
|
1136 (let* (;; Make sure that the user doesn't quit in the middle and leave us
|
|
1137 ;; with our variables out of sync.
|
|
1138 (inhibit-quit t)
|
|
1139 (original-window (selected-window))
|
|
1140 (original-buffer (current-buffer))
|
|
1141 (window-height (- (window-height window)
|
|
1142 (if (window-minibuffer-p window)
|
|
1143 0 1)))
|
|
1144 (this-command-group (scroll-get-command-group this-command))
|
|
1145 (continue-scroll-p
|
|
1146 (and ;; We're scrolling the previously scrolled window...
|
|
1147 (windowp scroll-previous-window)
|
|
1148 (eq window scroll-previous-window)
|
|
1149 ;; ...and the last command was an "in place" scrolling command
|
|
1150 ;; that can be continued by this command.
|
|
1151 (if (eq last-command t)
|
|
1152 ;; If the previous command signalled an error, the value of
|
|
1153 ;; `last-command' is `t'. Try to see if we signalled the
|
|
1154 ;; error and if point is where we left it. (NOTE that FSF
|
|
1155 ;; GNU Emacs 19.23+ no longer sets `last-command' to `t'
|
|
1156 ;; when a command signals an error. This is OK because the
|
|
1157 ;; else part of this `if' does the appropriate thing.)
|
|
1158 (and scroll-boundary-error-point
|
|
1159 (eq (window-point window) scroll-boundary-error-point)
|
|
1160 (memq scroll-boundary-error-command this-command-group)
|
|
1161 )
|
|
1162 ;; Otherwise...
|
|
1163 (memq last-command this-command-group))
|
|
1164 ))
|
|
1165 (lines-value (prefix-numeric-value lines))
|
|
1166 )
|
|
1167
|
|
1168 ;; For XEmacs and Lucid GNU Emacs, preserve the region's state. Note that
|
|
1169 ;; these Emacsen will forcibly deactivate the region if we signal an error
|
|
1170 ;; later on. Is this bad?
|
|
1171 (if (boundp 'zmacs-region-stays)
|
|
1172 (setq zmacs-region-stays t))
|
|
1173 ;; Parse the direction into a unit distance (1 or -1).
|
|
1174 (setq direction (scroll-parse-direction direction))
|
|
1175
|
|
1176 (setq scroll-previous-window window
|
|
1177 ;; `(setq scroll-boundary-error-command nil)' is not necessary.
|
|
1178 scroll-boundary-error-point nil)
|
|
1179 (unwind-protect
|
|
1180 (progn
|
|
1181 ;; `select-window' does an implicit `set-buffer'.
|
|
1182 (select-window window)
|
|
1183
|
|
1184 (if (or ;; The current command is not a continuation of a running
|
|
1185 ;; sequence of "in place" scrolling commands...
|
|
1186 (not continue-scroll-p)
|
|
1187 ;; ...or we were given an explicit number of lines to scroll,
|
|
1188 ;; and that number has a different magnitude than the last
|
|
1189 ;; number of lines we scrolled...
|
|
1190 (and (or (numberp lines) (consp lines))
|
|
1191 (/= scroll-previous-lines lines-value)
|
|
1192 (/= scroll-previous-lines (- lines-value)))
|
|
1193 ;; ...or the last successful scrolling command moved to a
|
|
1194 ;; buffer boundary, but the buffer is no longer in the state
|
|
1195 ;; we left it. (This can occur if, for example, we signal an
|
|
1196 ;; end-of-buffer error and something catches it and moves
|
|
1197 ;; point or renarrows. VM, for example, does this.)
|
|
1198 (and scroll-boundary-previous-point
|
|
1199 (or (not (or (bobp) (eobp)))
|
|
1200 (< scroll-boundary-previous-point (point-min))
|
|
1201 (> scroll-boundary-previous-point (point-max))
|
|
1202 (eq scroll-boundary-previous-point (point)))))
|
|
1203
|
|
1204 ;; We're starting a new sequence of scrolling commands.
|
|
1205 (setq lines (if (or (numberp lines) (consp lines))
|
|
1206 lines-value
|
|
1207 ;; The default number of lines...
|
|
1208 (* (if (eq lines '-) -1 1)
|
|
1209 (if (numberp scroll-default-lines)
|
|
1210 scroll-default-lines
|
|
1211 (max (- window-height
|
|
1212 next-screen-context-lines)
|
|
1213 1))))
|
|
1214 scroll-previous-lines lines
|
|
1215 scroll-goal-column (scroll-determine-goal-column window)
|
|
1216 scroll-boundary-previous-point nil
|
|
1217 ;; `(setq scroll-boundary-previous-lines 0)' is not
|
|
1218 ;; necessary.
|
|
1219 scroll-window-debt 0
|
|
1220 scroll-initially-displayed-lines
|
|
1221 (if scroll-allow-blank-lines-past-eob
|
|
1222 0
|
|
1223 (save-excursion
|
|
1224 (goto-char (window-start window))
|
|
1225 (vertical-motion (1- window-height)))))
|
|
1226
|
|
1227 ;; Otherwise we want to scroll by the same number of lines (but
|
|
1228 ;; possibly in a different direction) that we scrolled in previous
|
|
1229 ;; invocations of this function.
|
|
1230 (cond ((null lines)
|
|
1231 (setq lines scroll-previous-lines))
|
|
1232 ((eq lines '-)
|
|
1233 (setq lines (- scroll-previous-lines)
|
|
1234 scroll-previous-lines lines))
|
|
1235 (t
|
|
1236 (setq lines lines-value
|
|
1237 scroll-previous-lines lines)))
|
|
1238 )
|
|
1239
|
|
1240 (setq lines (* direction lines))
|
|
1241
|
|
1242 ;; If point is not in the window, center window around point. We try
|
|
1243 ;; to account for a bug in `pos-visible-in-window-p' in some versions
|
|
1244 ;; of Emacs (see `scroll-pos-visible-bug-p', above).
|
|
1245 (save-excursion
|
|
1246 (if (pos-visible-in-window-p (let ((point (point)))
|
|
1247 (if (and scroll-pos-visible-bug-p
|
|
1248 (= point (point-max)))
|
|
1249 (max (1- point) (point-min))
|
|
1250 point))
|
|
1251 window)
|
|
1252 nil
|
|
1253 (vertical-motion (/ (- window-height) 2))
|
|
1254 (set-window-start window (point))))
|
|
1255
|
|
1256 (cond ((and scroll-boundary-previous-point
|
|
1257 ;; `lines' is the same sign as the direction from point
|
|
1258 ;; to the `scroll-boundary-previous-point'.
|
|
1259 (cond ((> lines 0)
|
|
1260 (> (- scroll-boundary-previous-point (point)) 0))
|
|
1261 ((< lines 0)
|
|
1262 (< (- scroll-boundary-previous-point (point)) 0))
|
|
1263 (t nil)))
|
|
1264 ;; We're moving away from the buffer boundary.
|
|
1265 (goto-char scroll-boundary-previous-point)
|
|
1266 ;; Always move here (i.e., don't reject cases in which the
|
|
1267 ;; window doesn't move).
|
|
1268 (scroll-set-window-start window
|
|
1269 (- scroll-boundary-previous-lines))
|
|
1270 ;; (message "Back, window debt is %s." scroll-window-debt)
|
|
1271 (setq scroll-boundary-previous-point nil))
|
|
1272
|
|
1273 ((= lines 0)
|
|
1274 ;; We're going nowhere, so save ourselves some work.
|
|
1275 ;; (message "Scrolled zero lines.")
|
|
1276 )
|
|
1277
|
|
1278 (t
|
|
1279 ;; Perform the scrolling motion.
|
|
1280 (let ((initial-point (point))
|
|
1281 (moved nil))
|
|
1282 ;; First move point and see how far it goes.
|
|
1283 (setq moved (vertical-motion lines))
|
|
1284 (if (= moved lines)
|
|
1285 (progn
|
|
1286 ;; Point moved the full distance. Move to the desired
|
|
1287 ;; column and then try to move the window the full
|
|
1288 ;; distance, too.
|
|
1289 (move-to-column (+ (current-column)
|
|
1290 scroll-goal-column))
|
|
1291 (or (scroll-set-window-start window moved
|
|
1292 original-window)
|
|
1293 (scroll-signal-boundary-error initial-point
|
|
1294 lines))
|
|
1295 ;; (message "Normal, window debt is %s."
|
|
1296 ;; scroll-window-debt)
|
|
1297 )
|
|
1298 ;; Point couldn't move all the way. Move to the buffer
|
|
1299 ;; boundary if we're not already there, or signal a buffer
|
|
1300 ;; boundary error otherwise.
|
|
1301 (let ((boundary-point (if (< lines 0)
|
|
1302 (point-min)
|
|
1303 (point-max)))
|
|
1304 (boundary-symbol (if (< lines 0)
|
|
1305 'beginning-of-buffer
|
|
1306 'end-of-buffer)))
|
|
1307 (if (= initial-point boundary-point)
|
|
1308 (scroll-signal-boundary-error initial-point lines)
|
|
1309 ;; Scroll the window by as many lines as point could
|
|
1310 ;; move.
|
|
1311 (or (scroll-set-window-start window moved
|
|
1312 original-window)
|
|
1313 (scroll-signal-boundary-error initial-point
|
|
1314 lines))
|
|
1315 (message "%s" (get boundary-symbol 'error-message))
|
|
1316 ;; (message "Boundary, window debt is %s."
|
|
1317 ;; scroll-window-debt)
|
|
1318 (setq scroll-boundary-previous-lines moved)
|
|
1319 (setq scroll-boundary-previous-point initial-point)
|
|
1320 (goto-char boundary-point))
|
|
1321 )))
|
|
1322 )))
|
|
1323
|
|
1324 ;; The unwind forms of the `unwind-protect', above. Restore the
|
|
1325 ;; originally selected window and current buffer.
|
|
1326 (select-window original-window)
|
|
1327 (set-buffer original-buffer)))
|
|
1328
|
|
1329 ;; The standard GNU Emacs scrolling commands return `nil' so we do, too.
|
|
1330 nil)
|
|
1331
|
|
1332 ;;;
|
|
1333 ;;;
|
|
1334 ;;;
|
|
1335
|
|
1336 (defun scroll-window (window lines direction)
|
|
1337 "Scroll WINDOW vertically by the given number of window LINES in the given
|
|
1338 DIRECTION. Note that the window to be scrolled does not have to be the
|
|
1339 selected window, and that this function does not change which window is
|
|
1340 selected.
|
|
1341
|
|
1342 When the variable `scroll-in-place' is true, this function simply invokes the
|
|
1343 function `scroll-window-in-place' to scroll the window and leave point \"in
|
|
1344 place\" within that window. See the documentation for `scroll-window-in-place'
|
|
1345 for more information.
|
|
1346
|
|
1347 When the variable `scroll-in-place' is `nil' this function invokes the original
|
|
1348 version of the standard GNU Emacs command `scroll-down' or `scroll-up', as
|
|
1349 determined by DIRECTION, to scroll the window. If DIRECTION is -1 or `down',
|
|
1350 the original `scroll-down' is called; if DIRECTION is 1 or `up', the original
|
|
1351 `scroll-up' is called. Any other DIRECTION is an error. LINES is interpreted
|
|
1352 as if it were a raw prefix argument. If LINES is `nil', the window is scrolled
|
|
1353 by almost a complete windowful. If LINES is the symbol `-', the window is
|
|
1354 scrolled by almost a complete windowful in the opposite direction.
|
|
1355
|
|
1356 Note that this function correctly handles cases in which `scroll-in-place' has
|
|
1357 a buffer-local value in the WINDOW's buffer. That value is honored."
|
|
1358 (let ((current-buffer (current-buffer))
|
|
1359 (selected-window (selected-window))
|
|
1360 (window-buffer (window-buffer window)))
|
|
1361 (if ;; Allow `scroll-in-place' to be a buffer-local variable.
|
|
1362 (if (eq current-buffer window-buffer)
|
|
1363 scroll-in-place
|
|
1364 (save-excursion (set-buffer window-buffer) scroll-in-place))
|
|
1365 (scroll-window-in-place window lines direction)
|
|
1366
|
|
1367 (unwind-protect
|
|
1368 (progn
|
|
1369 ;; Paranoid, we forcibly break any running sequence of "in place"
|
|
1370 ;; scrolling commands.
|
|
1371 (setq scroll-previous-window nil)
|
|
1372 ;; For XEmacs and Lucid GNU Emacs, preserve the region's state.
|
|
1373 (if (boundp 'zmacs-region-stays)
|
|
1374 (setq zmacs-region-stays t))
|
|
1375 (select-window window)
|
|
1376 (if (= (scroll-parse-direction direction) 1)
|
|
1377 (original-scroll-up lines)
|
|
1378 (original-scroll-down lines)))
|
|
1379 (select-window selected-window)
|
|
1380 (set-buffer current-buffer))
|
|
1381 )))
|
|
1382
|
|
1383 ;;;
|
|
1384 ;;; The following function is sometimes useful. For example, I call it from
|
|
1385 ;;; functions that are invoked by certain mouse button down events in order to
|
|
1386 ;;; preserve any running chain of "in place" scrolling commands. This lets me
|
|
1387 ;;; continue the sequence from my mouse button up functions.
|
|
1388 ;;;
|
|
1389 ;;; I haven't yet needed a function to purposely break a running sequence of
|
|
1390 ;;; "in place" scrolling commands. Such a function would be easy to write,
|
|
1391 ;;; however; just set the variable `scroll-previous-window' to `nil'.
|
|
1392 ;;;
|
|
1393
|
|
1394 (defun scroll-window-in-place-continue-sequence ()
|
|
1395 "If the previous command was a \"scroll in place\" command, set the variable
|
|
1396 `this-command' to the name of that previous command. This ensures that any
|
|
1397 running sequence of \"in place\" scrolling commands will not be broken by the
|
|
1398 current command. See the documentation for the commands `scroll-down-in-place'
|
|
1399 and `scroll-up-in-place' for more information about \"in place\" scrolling.
|
|
1400
|
|
1401 NOTE that you don't need to call this function if the current command scrolls
|
|
1402 in place! You only need to call this function when the current command is not
|
|
1403 a \"scroll in place\" command but you still want to preserve any running
|
|
1404 sequence of \"in place\" commands. Such situations are rare.
|
|
1405
|
|
1406 NOTE that this function sets `this-command' in order to trick the \"in place\"
|
|
1407 scrolling commands. If something else subsequently sets `this-command', any
|
|
1408 running sequence of scrolling commands will probably be broken anyway."
|
|
1409 (if (if (eq last-command t)
|
|
1410 ;; If `last-command' is `t', then the previous command signalled an
|
|
1411 ;; error. See if the last invocation of `scroll-window-in-place'
|
|
1412 ;; signalled an error. (NOTE that FSF GNU Emacs 19.23+ no longer
|
|
1413 ;; sets `last-command' to `t' when a command signals an error. This
|
|
1414 ;; is OK because the else part of this `if' does the appropriate
|
|
1415 ;; thing.)
|
|
1416 scroll-boundary-error-point
|
|
1417 ;; Otherwise, the value of `last-command' must belong to some group of
|
|
1418 ;; "in place" scrolling commands.
|
|
1419 (or (memq last-command scroll-default-command-group)
|
|
1420 (let ((groups scroll-command-groups)
|
|
1421 (found nil))
|
|
1422 (while (and groups (not found))
|
|
1423 (if (memq last-command (car groups))
|
|
1424 (setq found t)
|
|
1425 (setq groups (cdr groups)))
|
|
1426 )
|
|
1427 found)))
|
|
1428 (setq this-command last-command)))
|
|
1429
|
|
1430
|
|
1431 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1432 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1433 ;;;;
|
|
1434 ;;;; Here are the various auxiliary functions called by the function `scroll-
|
|
1435 ;;;; window-in-place'. None of the functions are intended to be called from
|
|
1436 ;;;; outside this package.
|
|
1437 ;;;;
|
|
1438 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1439 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1440
|
|
1441 (defun scroll-get-command-group (command)
|
|
1442 "Return the group of \"in place\" scrolling commands that contains the given
|
|
1443 COMMAND. This is the list of commands with which the given command may share
|
|
1444 state and form \"chains.\"
|
|
1445
|
|
1446 This function is an auxiliary for the function `scroll-window-in-place'. Don't
|
|
1447 call this function from other code."
|
|
1448 ;; This function assumes that the given command is an "in place" scrolling
|
|
1449 ;; command.
|
|
1450 (let ((groups scroll-command-groups)
|
|
1451 (found nil))
|
|
1452 (while (and groups (not found))
|
|
1453 (if (memq command (car groups))
|
|
1454 (setq found t)
|
|
1455 (setq groups (cdr groups)))
|
|
1456 )
|
|
1457 (if groups
|
|
1458 (car groups)
|
|
1459 ;; Otherwise return the default command group. If necessary, add the
|
|
1460 ;; given command to the default command group.
|
|
1461 (or (memq command scroll-default-command-group)
|
|
1462 (setq scroll-default-command-group
|
|
1463 (cons command scroll-default-command-group)))
|
|
1464 scroll-default-command-group)
|
|
1465 ))
|
|
1466
|
|
1467 ;;;
|
|
1468 ;;;
|
|
1469 ;;;
|
|
1470
|
|
1471 (defun scroll-parse-direction (direction)
|
|
1472 "Return the signed unit distance for the given DIRECTION. If DIRECTION is
|
|
1473 unacceptable, signal an error."
|
|
1474 (cond ((or (eq direction 1) (eq direction -1)) direction)
|
|
1475 ((eq direction 'up) 1)
|
|
1476 ((eq direction 'down) -1)
|
|
1477 (t (signal 'args-out-of-range (list 'direction direction)))
|
|
1478 ))
|
|
1479
|
|
1480 ;;;
|
|
1481 ;;;
|
|
1482 ;;;
|
|
1483
|
|
1484 (defun scroll-determine-goal-column (window)
|
|
1485 "Return the goal column for the \"in place\" vertical scrolling commands.
|
|
1486 This is the horizontal window position at which these commands try to keep
|
|
1487 point.
|
|
1488
|
|
1489 This function is an auxiliary for the function `scroll-window-in-place'. Don't
|
|
1490 call this function from other code."
|
|
1491 ;; NOTE that `window' must be the selected window! `scroll-window-in-place'
|
|
1492 ;; ensures that this is so.
|
|
1493 (cond ((or truncate-lines
|
|
1494 (and truncate-partial-width-windows
|
|
1495 (< (window-width window) (screen-width)))
|
|
1496 (> (window-hscroll window) 0))
|
|
1497 ;; Lines in this window are being truncated.
|
|
1498 (if (and track-eol (eolp))
|
|
1499 9999
|
|
1500 (current-column)))
|
|
1501 ((and track-eol (eolp))
|
|
1502 ;; In some ways this isn't quite right, as point doesn't track the
|
|
1503 ;; ends of wrapped lines. But if it did so, point would be on the
|
|
1504 ;; wrong window line. This is the best we can do.
|
|
1505 (1- (window-width window)))
|
|
1506 (t (% (current-column) (1- (window-width window))))
|
|
1507 ))
|
|
1508
|
|
1509 ;;;
|
|
1510 ;;;
|
|
1511 ;;;
|
|
1512
|
|
1513 (defun scroll-set-window-start (window lines &optional original-window)
|
|
1514 "Move the `window-start' of the given window, which must be the selected
|
|
1515 window. If the window was successfully scrolled, update the variable
|
|
1516 `scroll-window-debt' and return `t'. Otherwise return `nil'.
|
|
1517
|
|
1518 This function is an auxiliary for the function `scroll-window-in-place'. Don't
|
|
1519 call this function from other code."
|
|
1520 (save-excursion
|
|
1521 (goto-char (window-start window))
|
|
1522 ;; Try to move the window start by the specified number of lines. In
|
|
1523 ;; addition, try to make up any existing debt in the window start's
|
|
1524 ;; position and make sure that we don't move too close to the end of the
|
|
1525 ;; buffer.
|
|
1526 (let ((moved (+ (vertical-motion (+ lines
|
|
1527 scroll-window-debt
|
|
1528 scroll-initially-displayed-lines))
|
|
1529 (vertical-motion (- scroll-initially-displayed-lines)))))
|
|
1530 ;; If we're not scrolling the `original-window' (i.e., the originally
|
|
1531 ;; selected window), punt if we didn't move the window start at all.
|
|
1532 (if (and original-window
|
|
1533 (not (eq window original-window))
|
|
1534 (= moved 0))
|
|
1535 nil
|
|
1536 ;; Otherwise update the window start and keep track of the debt in our
|
|
1537 ;; position. Return `t' to indicate success.
|
|
1538 (set-window-start window (point))
|
|
1539 (setq scroll-window-debt (- (+ lines scroll-window-debt) moved))
|
|
1540 t))
|
|
1541 ))
|
|
1542
|
|
1543 ;;;
|
|
1544 ;;;
|
|
1545 ;;;
|
|
1546
|
|
1547 (defun scroll-signal-boundary-error (initial-point lines)
|
|
1548 "Move point to its initial location and signal an appropriate buffer boundary
|
|
1549 error.
|
|
1550
|
|
1551 This function is an auxiliary for the function `scroll-window-in-place'. Don't
|
|
1552 call this function from other code."
|
|
1553 (goto-char initial-point)
|
|
1554 ;; Remember what we were doing and where point was when we signalled the
|
|
1555 ;; error so that subsequent "in place" scrolling commands can decide how to
|
|
1556 ;; recover.
|
|
1557 (setq scroll-boundary-error-command this-command
|
|
1558 scroll-boundary-error-point initial-point)
|
70
|
1559 (signal (if (< lines 0) 'beginning-of-buffer 'end-of-buffer)
|
|
1560 nil))
|
0
|
1561
|
|
1562
|
76
|
1563 ;;; Some convenience redefinitions for modes that don't like scroll-in-place
|
|
1564 (add-hook 'vm-mode-hook 'turn-off-scroll-in-place)
|
|
1565 (add-hook 'vm-select-message-hook 'turn-off-scroll-in-place)
|
|
1566 (add-hook 'vm-summary-mode-hook 'turn-off-scroll-in-place)
|
|
1567
|
|
1568 (add-hook 'list-mode-hook 'turn-off-scroll-in-place)
|
|
1569
|
|
1570 ;; This doesn't work with Red Gnus
|
|
1571 ;; (add-hook 'gnus-article-mode-hook 'turn-off-scroll-in-place)
|
|
1572
|
0
|
1573 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1574 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1575 ;;;;
|
|
1576 ;;;; Finally, here is the `provide' statement.
|
|
1577 ;;;;
|
|
1578 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1579 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1580
|
|
1581 (provide 'scroll-in-place)
|
|
1582
|
76
|
1583 ;;; scroll-in-place.el ends here
|