Mercurial > hg > xemacs-beta
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
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, | |
20 ;;;; Inc., 675 Mass Ave., Cambridge, MA 02139, USA. | |
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 | |
464 ;; (provide 'scroll-in-place) at the end of this file. | |
465 | |
466 | |
467 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
468 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
469 ;;;; | |
470 ;;;; Here are the variable declarations, both user options and internal | |
471 ;;;; variables. | |
472 ;;;; | |
473 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
474 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
475 | |
476 (defvar scroll-in-place t | |
477 "*When this variable is true (i.e., non-`nil'), the standard GNU Emacs | |
478 vertical scrolling commands `scroll-down', `scroll-up', `scroll-other-window- | |
479 down', and `scroll-other-window' will attempt to keep point at its current | |
480 position in the window (window line and column). In other words, point stays | |
481 \"in place\" within the window. | |
482 | |
483 When this variable is `nil' the standard GNU Emacs vertical scrolling commands | |
484 behave as usual. The \"in place\" equivalents, however, are still available as | |
485 separate commands. | |
486 | |
487 This variable may be made buffer-local in order to disable (or enable) \"in | |
488 place\" scrolling in particular buffers." | |
489 ;; I have thought about dividing `scroll-in-place' into three variables: a | |
490 ;; list of commands that always scroll in place, a list of commands that | |
491 ;; never scroll in place, and a flag that determines the default behavior of | |
492 ;; other scrolling commands. This could make it easier to make "in place" | |
493 ;; scrolling the default because one could single out certain ill-behaved | |
494 ;; commands. But as of now I'm sure that the added complexity would really | |
495 ;; be worth it. | |
496 ) | |
497 | |
498 (defvar scroll-allow-blank-lines-past-eob nil | |
499 "*When this variable is `nil' the \"in place\" scrolling commands will avoid | |
500 displaying empty lines past the end of the buffer text. In other words, just | |
501 as you can't see \"dead space\" before the beginning of the buffer text, the | |
502 \"in place\" scrolling commands try to avoid displaying \"dead space\" past the | |
503 end of the buffer text. This helps make the most of window real estate. | |
504 | |
505 Note that sometimes it is necessary to display \"dead space\" in order to make | |
506 a previous scrolling action reversible. | |
507 | |
508 When this variable is non-`nil' the \"in place\" scrolling commands will always | |
509 allow blank lines to be shown past the end of the buffer.") | |
510 | |
511 ;;;; | |
512 ;;;; The following variables are not user options, but are intended to be set | |
513 ;;;; by code outside this package. | |
514 ;;;; | |
515 | |
516 (defvar scroll-default-lines nil | |
517 "The default number of lines to be scrolled by when a new sequence of \"in | |
518 place\" scrolling commands begins. Of course, when an explicit number of lines | |
519 is specified, that explicit number takes precedence. See the documentation for | |
520 the function `scroll-window-in-place' for more information. | |
521 | |
522 If this variable is not bound to a number, then the default number of lines is | |
523 the height of the window to be scrolled minus `next-screen-context-lines'. | |
524 | |
525 This variable should not be set globally! Commands that want to specify a | |
526 default scrolling distance should just bind the variable `scroll-default-lines' | |
527 temporarily.") | |
528 | |
529 (defvar scroll-command-groups nil | |
530 "The explicitly specified \"groups\" of \"in place\" scrolling commands. | |
531 This variable should be set before or immediately after the \"in place\" | |
532 scrolling package is loaded, and then not changed after that. | |
533 | |
534 Usually, \"in place\" scrolling commands share state (e.g., the number of lines | |
535 to scroll by) with any and all immediately previous \"in place\" scrolling | |
536 commands. Sometimes, however, this is undesirable. In these cases the \"in | |
537 place\" scrolling commands can be divided into groups. A command in a group | |
538 only shares state with members of its group. | |
539 | |
540 Each element of `scroll-command-groups' is a list that contains all of the | |
541 members of a unique command group. For example, if there were only one | |
542 explicit group and that group contained the commands `scroll-down-one-line' and | |
543 `scroll-up-one-line', then `scroll-command-groups' would be set to: | |
544 | |
545 ((scroll-down-one-line scroll-up-one-line)) | |
546 | |
547 Commands that are not in any explicitly specified group are added to a default | |
548 group. That group is stored in the variable `scroll-default-command-group'. | |
549 | |
550 The \"in place\" scrolling functions assume that all of the scrolling command | |
551 groups are nonintersecting (i.e., no command is in more than one group) and | |
552 only contain \"in place\" scrolling commands.") | |
553 | |
554 ;;;; | |
555 ;;;; The variables below this point are internal to this package. | |
556 ;;;; | |
557 | |
558 (defvar scroll-default-command-group nil | |
559 "The set of \"in place\" scrolling commands that are not members of any | |
560 explicitly defined group of commands. This set of commands is an implicitly | |
561 defined group, constructed as \"in place\" commands are invoked, and members of | |
562 this group share state among themselves. See the documentation for the | |
563 variable `scroll-command-groups' for more information.") | |
564 | |
565 (defvar scroll-initially-displayed-lines 0 | |
566 "The number of window lines that contained buffer text when the current | |
567 sequence of \"in place\" scrolling commands started. Unless the variable | |
568 `scroll-in-place-allow-blank-lines-past-eob' is true, the \"in place\" | |
569 scrolling commands ensure that at least this many text lines are visible at all | |
570 times.") | |
571 | |
572 (defvar scroll-previous-window nil | |
573 "The window that was most recently scrolled by an \"in place\" scrolling | |
574 command.") | |
575 | |
576 (defvar scroll-previous-lines 0 | |
577 "The number of window lines that the previous \"in place\" scrolling command | |
578 attempted to scroll.") | |
579 | |
580 (defvar scroll-goal-column 0 | |
581 "The desired horizontal window position for point, used by the \"in place\" | |
582 scrolling commands.") | |
583 | |
584 (defvar scroll-boundary-previous-point nil | |
585 "The value of point before point was moved to a buffer boundary.") | |
586 | |
587 (defvar scroll-boundary-previous-lines 0 | |
588 "The number of lines that point moved when it moved to a buffer boundary.") | |
589 | |
590 (defvar scroll-boundary-error-command nil | |
591 "The value of `this-command' when an \"in place\" scrolling command signalled | |
592 a buffer boundary error. This is used to decide how subsequent scrolling | |
593 commands should recover from the error.") | |
594 | |
595 (defvar scroll-boundary-error-point nil | |
596 "The value of point when an \"in place\" scrolling command signalled a buffer | |
597 boundary error. This is used to decide how subsequent scrolling commands | |
598 should recover from the error." | |
599 ;; This variable is used as a flag, indicating whether or not the previous | |
600 ;; "in place" scrolling command signalled an error. | |
601 ) | |
602 | |
603 (defvar scroll-window-debt 0 | |
604 "The difference between the number of lines an \"in place\" scrolling command | |
605 tried to scroll a window and the number of lines that the window actually | |
606 scrolled. This difference is the \"debt\" in the window's starting position. | |
607 Subsequent \"in place\" scrolling commands try to make up this debt.") | |
608 | |
609 (defconst scroll-pos-visible-bug-p | |
610 ;; On September 14, 1993, David Hughes <djh@Harston.CV.COM> told me that | |
611 ;; Lucid GNU Emacs 19.8 had inherited the bug from Epoch... sigh. | |
612 (let ((old-match-data (match-data))) | |
613 (unwind-protect | |
614 (or (and (boundp 'epoch::version) | |
615 (if (string-match "\\`4\\." emacs-version) t nil) | |
616 ) | |
617 (and (string-match "Lucid" emacs-version) | |
618 (if (string-match "\\`19\\.8\\." emacs-version) t nil) | |
619 ) | |
620 ) | |
621 (store-match-data old-match-data))) | |
622 "A flag, set when this version of GNU Emacs has a buggy version of the | |
623 function `pos-visible-in-window-p' that returns `nil' when given `(point-max)' | |
624 and `(point-max)' is on the last line of the window. Currently, this flag is | |
625 set for all versions of Epoch 4 and for Lucid GNU Emacs 19.8.") | |
626 | |
627 | |
628 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
629 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
630 ;;;; | |
631 ;;;; Here are the window-choosing auxiliary functions used by the new scrolling | |
632 ;;;; commands. | |
633 ;;;; | |
634 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
635 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
636 | |
637 (defun scroll-choose-window () | |
638 "Choose the window to be scrolled by the commands `scroll-down', `scroll-up', | |
639 `scroll-down-in-place', and `scroll-up-in-place'. | |
640 | |
641 The rules are simple. If the selected window is not a minibuffer window, then | |
642 just choose the selected window. | |
643 | |
644 However, when a minibuffer window is selected, look first for the `minibuffer- | |
645 scroll-window'. The `minibuffer-scroll-window' is usually the window that | |
646 displays completions. If it exists, choose it; otherwise choose the next | |
647 window after the selected window in the canonical ordering of windows. The | |
648 next window is generally the one below the selected window, or the one at the | |
649 top of the screen if the selected window is at the bottom of the screen." | |
650 (let ((selected-window (selected-window))) | |
651 (if (window-minibuffer-p selected-window) | |
652 ;; A minibuffer window is selected --- scroll some other window. | |
653 (if (window-live-p minibuffer-scroll-window) | |
654 minibuffer-scroll-window | |
655 ;; We know that the (selected) minibuffer is active, so `next-window' | |
656 ;; will examine all of the frames that share this minibuffer. | |
657 ;; Should we consider `other-window-scroll-buffer' here? I don't | |
658 ;; believe so. | |
659 (next-window selected-window)) | |
660 selected-window))) | |
661 | |
662 ;;; | |
663 ;;; | |
664 ;;; | |
665 | |
666 (defun scroll-choose-other-window () | |
667 "Choose the window to be scrolled by the commands `scroll-other-window-down', | |
668 `scroll-other-window', `scroll-other-window-down-in-place', and `scroll-other- | |
669 window-in-place'. | |
670 | |
671 The rules are these. If the selected window is not a minibuffer window, then | |
672 choose either: | |
673 | |
674 + a window that displays the `other-window-scroll-buffer', if that buffer | |
675 exists. Note, this function will display that buffer if necessary. | |
676 | |
677 + the next window after the selected window in the canonical ordering of | |
678 windows. The next window is generally the one below the selected window, | |
679 or the one at the top of the screen if the selected window is at the bottom | |
680 of the screen. | |
681 | |
682 However, when a minibuffer window is selected, look first for the `minibuffer- | |
683 scroll-window'. The `minibuffer-scroll-window' is usually the window that | |
684 displays completions. If it exists, choose it; otherwise choose the window to | |
685 be scrolled as described above (`other-window-scroll-buffer' or next window). | |
686 | |
687 This function is essentially a Lisp version of the function `other-window-for- | |
688 scrolling' which first appeared in the FSF's GNU Emacs 19.26." | |
689 (let* ((no-error nil) | |
690 (selected-window (selected-window)) | |
691 (other-window nil)) | |
692 (setq other-window | |
693 (cond ((and (window-minibuffer-p selected-window) | |
694 (window-live-p minibuffer-scroll-window)) | |
695 ;; Don't signal an error when `minibuffer-scroll-window' is | |
696 ;; the minibuffer itself --- which would be really weird, but | |
697 ;; isn't necessarily erroneous. | |
698 (setq no-error t) | |
699 minibuffer-scroll-window) | |
700 | |
701 ((and ;; `other-window-scroll-buffer' is an Emacs 19 invention. | |
702 (boundp 'other-window-scroll-buffer) | |
703 (bufferp other-window-scroll-buffer) | |
704 ;; `buffer-name' is `nil' if the buffer has been killed. | |
705 (buffer-name other-window-scroll-buffer)) | |
706 ;; This is what FSF GNU Emacs 19.26 does, but it occurred to | |
707 ;; me: what if one of these forms returns the selected window? | |
708 ;; Signalling an error would be bad news, so I added a flag. | |
709 (setq no-error t) | |
710 (or (get-buffer-window other-window-scroll-buffer) | |
711 (display-buffer other-window-scroll-buffer t))) | |
712 | |
713 ((let ((next-window (next-window selected-window))) | |
714 (if (eq next-window selected-window) | |
715 nil | |
716 next-window))) | |
717 | |
718 (t | |
719 ;; In Emacs 19 (FSF, Lucid, and XEmacs), look for a window on | |
720 ;; another visible frame. This could be written for | |
721 ;; Epoch, too, I suppose... | |
722 (condition-case nil | |
723 (let ((this-window (next-window selected-window nil t))) | |
724 (while (not (or (eq this-window selected-window) | |
725 (scroll-choose-window-frame-visible-p | |
726 this-window))) | |
727 (setq this-window (next-window this-window nil t))) | |
728 this-window) | |
729 ;; In older versions of Emacs, `next-window' didn't accept | |
730 ;; three arguments. Catch this error and then return the | |
731 ;; selected window --- which will cause another error to be | |
732 ;; signalled later on. | |
733 (wrong-number-of-arguments selected-window)) | |
734 ) | |
735 )) | |
736 | |
737 (if (and (not no-error) | |
738 (eq selected-window other-window)) | |
739 (error "There is no other window.")) | |
740 other-window)) | |
741 | |
742 ;;; | |
743 ;;; | |
744 ;;; | |
745 | |
746 (defun scroll-choose-window-frame-visible-p (window) | |
747 "Return a true value if the frame of the given WINDOW is visible." | |
748 (cond ((fboundp 'window-frame) | |
749 (eq t (frame-visible-p (window-frame window)))) | |
750 (t t))) | |
751 | |
752 | |
753 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
754 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
755 ;;;; | |
756 ;;;; Here are the "in place" scrolling commands (interactive functions) and the | |
757 ;;;; replacements for the standard GNU Emacs vertical scrolling commands. | |
758 ;;;; | |
759 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
760 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
761 | |
762 ;;;; | |
763 ;;;; Here are the new scroll "in place" commands. | |
764 ;;;; | |
765 | |
766 (defun scroll-down-in-place (&optional lines) | |
767 "Scroll the text of the current window downward by LINES lines, leaving point | |
768 as close as possible to its current window position (window line and column). | |
769 In other words, point is left \"in place\" within the window. As a special | |
770 case, when the current window is a minibuffer window, this command scrolls the | |
771 `minibuffer-scroll-window' (which is usually the list of completions) if it | |
772 exists, or otherwise the next window in the canonical ordering of windows. | |
773 | |
774 If the optional argument LINES is `nil', scroll the window by the same amount | |
775 it was moved by the immediately previous \"in place\" scrolling command, or by | |
776 the value of the variable `scroll-default-lines' (usually almost a windowful) | |
777 if the previous command was not an \"in place\" scrolling command (or when that | |
778 previous command scrolled some other window, or when other circumstances | |
779 prevent the previous scrolling distance from being used). If LINES is the | |
780 symbol `-', then the scrolling distance is determined as if LINES had been | |
781 `nil' and then that distance is multiplied by -1. | |
782 | |
783 If the window cannot be scrolled by the full distance, point is allowed to | |
784 stray from its initial position so that it can move the full number of lines. | |
785 If point cannot move the full number of lines, point is moved to the buffer | |
786 boundary. Any immediately subsequent \"in place\" scrolling commands will try | |
787 to restore point to its initial window position." | |
788 (interactive "P") | |
789 (scroll-window-in-place (scroll-choose-window) lines -1)) | |
790 | |
791 ;;; | |
792 ;;; | |
793 ;;; | |
794 | |
795 (defun scroll-up-in-place (&optional lines) | |
796 "Scroll the text of the current window upward by LINES lines, leaving point | |
797 as close as possible to its current window position (window line and column). | |
798 In other words, point is left \"in place\" within the window. As a special | |
799 case, when the current window is a minibuffer window, this command scrolls the | |
800 `minibuffer-scroll-window' (which is usually the list of completions) if it | |
801 exists, or otherwise the next window in the canonical ordering of windows. | |
802 | |
803 If the optional argument LINES is `nil', scroll the window by the same amount | |
804 it was moved by the immediately previous \"in place\" scrolling command, or by | |
805 the value of the variable `scroll-default-lines' (usually almost a windowful) | |
806 if the previous command was not an \"in place\" scrolling command (or when that | |
807 previous command scrolled some other window, or when other circumstances | |
808 prevent the previous scrolling distance from being used). If LINES is the | |
809 symbol `-', then the scrolling distance is determined as if LINES had been | |
810 `nil' and then that distance is multiplied by -1. | |
811 | |
812 If the window cannot be scrolled by the full distance, point is allowed to | |
813 stray from its initial position so that it can move the full number of lines. | |
814 If point cannot move the full number of lines, point is moved to the buffer | |
815 boundary. Any immediately subsequent \"in place\" scrolling commands will try | |
816 to restore point to its initial window position." | |
817 (interactive "P") | |
818 (scroll-window-in-place (scroll-choose-window) lines 1)) | |
819 | |
820 ;;; | |
821 ;;; The command `scroll-other-window-down' first appeared in FSF GNU Emacs | |
822 ;;; 19.26. | |
823 ;;; | |
824 | |
825 (defun scroll-other-window-down-in-place (&optional lines) | |
826 "Scroll the text of the next window downward by LINES lines, leaving point in | |
827 that window as close as possible to its current window position (window line | |
828 and column). In other words, point is left \"in place\" within the window. | |
829 The next window is generally the one below the current one, or the one at the | |
830 top of the screen if the current window is at the bottom of the screen. In | |
831 special circumstances this command will scroll a window other than the next | |
832 window. Read the documentation for the function `scroll-choose-other-window' | |
833 for details. | |
834 | |
835 If the optional argument LINES is `nil', scroll the window by the same amount | |
836 it was moved by the immediately previous \"in place\" scrolling command, or by | |
837 the value of the variable `scroll-default-lines' (usually almost a windowful) | |
838 if the previous command was not an \"in place\" scrolling command (or when that | |
839 previous command scrolled some other window, or when other circumstances | |
840 prevent the previous scrolling distance from being used). If LINES is the | |
841 symbol `-', then the scrolling distance is determined as if LINES had been | |
842 `nil' and then that distance is multiplied by -1. | |
843 | |
844 If the window cannot be scrolled by the full distance, point is allowed to | |
845 stray from its initial position so that it can move the full number of lines. | |
846 If point cannot move the full number of lines, point is moved to the buffer | |
847 boundary. Any immediately subsequent \"in place\" scrolling commands will try | |
848 to restore point to its initial window position. | |
849 | |
850 If it is impossible to scroll the text of the window at all (because a buffer | |
851 boundary is already visible), this command signals a buffer boundary error. | |
852 The error is signalled even if point could otherwise move the full number of | |
853 lines." | |
854 (interactive "P") | |
855 (scroll-window-in-place (scroll-choose-other-window) lines -1)) | |
856 | |
857 ;;; | |
858 ;;; | |
859 ;;; | |
860 | |
861 (defun scroll-other-window-in-place (&optional lines) | |
862 "Scroll the text of the next window upward by LINES lines, leaving point in | |
863 that window as close as possible to its current window position (window line | |
864 and column). In other words, point is left \"in place\" within the window. | |
865 The next window is generally the one below the current one, or the one at the | |
866 top of the screen if the current window is at the bottom of the screen. In | |
867 special circumstances this command will scroll a window other than the next | |
868 window. Read the documentation for the function `scroll-choose-other-window' | |
869 for details. | |
870 | |
871 If the optional argument LINES is `nil', scroll the window by the same amount | |
872 it was moved by the immediately previous \"in place\" scrolling command, or by | |
873 the value of the variable `scroll-default-lines' (usually almost a windowful) | |
874 if the previous command was not an \"in place\" scrolling command (or when that | |
875 previous command scrolled some other window, or when other circumstances | |
876 prevent the previous scrolling distance from being used). If LINES is the | |
877 symbol `-', then the scrolling distance is determined as if LINES had been | |
878 `nil' and then that distance is multiplied by -1. | |
879 | |
880 If the window cannot be scrolled by the full distance, point is allowed to | |
881 stray from its initial position so that it can move the full number of lines. | |
882 If point cannot move the full number of lines, point is moved to the buffer | |
883 boundary. Any immediately subsequent \"in place\" scrolling commands will try | |
884 to restore point to its initial window position. | |
885 | |
886 If it is impossible to scroll the text of the window at all (because a buffer | |
887 boundary is already visible), this command signals a buffer boundary error. | |
888 The error is signalled even if point could otherwise move the full number of | |
889 lines." | |
890 (interactive "P") | |
891 (scroll-window-in-place (scroll-choose-other-window) lines 1)) | |
892 | |
893 ;;;; | |
894 ;;;; Here are the replacements for GNU Emacs' standard vertical scrolling | |
895 ;;;; commands. | |
896 ;;;; | |
897 | |
898 (or (fboundp 'original-scroll-down) | |
899 (fset 'original-scroll-down (symbol-function 'scroll-down))) | |
900 (or (fboundp 'original-scroll-up) | |
901 (fset 'original-scroll-up (symbol-function 'scroll-up))) | |
902 (or (fboundp 'original-scroll-other-window-down) | |
903 ;; `scroll-other-window-down' first appeared in FSF GNU Emacs 19.26. | |
904 (if (fboundp 'scroll-other-window-down) | |
905 (fset 'original-scroll-other-window-down | |
906 (symbol-function 'scroll-other-window-down)) | |
907 )) | |
908 (or (fboundp 'original-scroll-other-window) | |
909 (fset 'original-scroll-other-window (symbol-function 'scroll-other-window)) | |
910 ) | |
911 | |
912 ;;; | |
913 ;;; | |
914 ;;; | |
915 | |
916 (defun scroll-down (&optional lines) | |
917 "Scroll the text of the current window downward by LINES lines. As a special | |
918 case, when the current window is a minibuffer window, this command scrolls the | |
919 `minibuffer-scroll-window' (which is usually the list of completions) if it | |
920 exists, or otherwise the next window in the canonical ordering of windows. | |
921 | |
922 The argument LINES is optional. Its meaning depends on the current value of | |
923 the variable `scroll-in-place'. | |
924 | |
925 When the variable `scroll-in-place' is true, this command works just like the | |
926 command `scroll-down-in-place', scrolling the current window and leaving point | |
927 \"in place\" within the window. See the documentation for the command | |
928 `scroll-down-in-place' for more information. | |
929 | |
930 When the variable `scroll-in-place' is `nil' this command invokes the standard | |
931 GNU Emacs version of `scroll-down'. In that case, when LINES is `nil' the | |
932 current window is scrolled by nearly a complete windowful of text. | |
933 | |
934 Note that this command correctly handles cases in which `scroll-in-place' has a | |
935 buffer-local value in the window to be scrolled. That value is honored." | |
936 (interactive "P") | |
937 (scroll-window (scroll-choose-window) lines -1)) | |
938 | |
939 ;;; | |
940 ;;; | |
941 ;;; | |
942 | |
943 (defun scroll-up (&optional lines) | |
944 "Scroll the text of the current window upward by LINES lines. As a special | |
945 case, when the current window is a minibuffer window, this command scrolls the | |
946 `minibuffer-scroll-window' (which is usually the list of completions) if it | |
947 exists, or otherwise the next window in the canonical ordering of windows. | |
948 | |
949 The argument LINES is optional. Its meaning depends on the current value of | |
950 the variable `scroll-in-place'. | |
951 | |
952 When the variable `scroll-in-place' is true, this command works just like the | |
953 command `scroll-up-in-place', scrolling the current window and leaving point | |
954 \"in place\" within the window. See the documentation for the command | |
955 `scroll-up-in-place' for more information. | |
956 | |
957 When the variable `scroll-in-place' is `nil' this command invokes the standard | |
958 GNU Emacs version of `scroll-up'. In that case, when LINES is `nil' the | |
959 current window is scrolled by nearly a complete windowful of text. | |
960 | |
961 Note that this command correctly handles cases in which `scroll-in-place' has a | |
962 buffer-local value in the window to be scrolled. That value is honored." | |
963 (interactive "P") | |
964 (scroll-window (scroll-choose-window) lines 1)) | |
965 | |
966 ;;; | |
967 ;;; NOTE that in the FSF GNU Emacs 19.26 version of `scroll-other-window-down', | |
968 ;;; the `lines' argument is required. I've left it optional in order to be | |
969 ;;; like `scroll-other-window'. | |
970 ;;; | |
971 | |
972 (defun scroll-other-window-down (&optional lines) | |
973 "Scroll the text of the next window downward by LINES lines. The next window | |
974 is generally the one below the current one, or the one at the top of the screen | |
975 if the current window is at the bottom of the screen. In special circumstances | |
976 this command will scroll a window other than the next window. Read the | |
977 documentation for the function `scroll-choose-other-window' for details. | |
978 | |
979 The argument LINES is optional. Its meaning depends on the current value of | |
980 the variable `scroll-in-place'. | |
981 | |
982 When the variable `scroll-in-place' is true, this command works just like the | |
983 command `scroll-other-window-down-in-place', scrolling the next window and | |
984 leaving point \"in place\" within that window. See the documentation for the | |
985 command `scroll-other-window-down-in-place' for more information. | |
986 | |
987 When the variable `scroll-in-place' is `nil' this command invokes the standard | |
988 GNU Emacs version of `scroll-other-window-down'. In that case, when LINES is | |
989 `nil' the next window is scrolled by nearly a complete windowful of text. | |
990 \(Note that `scroll-other-window-down' first appeared as a standard command in | |
991 the FSF's GNU Emacs 19.26. If the builtin version of that command is not | |
992 available in the current Emacs system, an equivalent action is invoked | |
993 instead.) | |
994 | |
995 Note that this command correctly handles cases in which `scroll-in-place' has a | |
996 buffer-local value in the window to be scrolled. That value is honored." | |
997 (interactive "P") | |
998 ;; This code is similar to the body of `scroll-window', below. | |
999 (let* ((other-window (scroll-choose-other-window)) | |
1000 (other-window-buffer (window-buffer other-window))) | |
1001 (if ;; Allow `scroll-in-place' to be a buffer-local variable. | |
1002 (save-excursion (set-buffer other-window-buffer) scroll-in-place) | |
1003 (scroll-window-in-place other-window lines -1) | |
1004 | |
1005 ;; Paranoid, we forcibly break any running sequence of "in place" | |
1006 ;; scrolling commands. | |
1007 (setq scroll-previous-window nil) | |
1008 ;; For XEmacs and Lucid GNU Emacs, preserve the region's state. | |
1009 (if (boundp 'zmacs-region-stays) | |
1010 (setq zmacs-region-stays t)) | |
1011 (if (fboundp 'original-scroll-other-window-down) | |
1012 (original-scroll-other-window-down lines) | |
1013 ;; `scroll-other-window-down' first appeared as a builtin in FSF GNU | |
1014 ;; Emacs 19.26, so it may not be available in the current Emacs system. | |
1015 ;; Do the equivalent thing. | |
1016 (original-scroll-other-window (cond | |
1017 ((null lines) '-) | |
1018 ((eq lines '-) nil) | |
1019 (t (- (prefix-numeric-value lines))) | |
1020 )) | |
1021 )) | |
1022 )) | |
1023 | |
1024 ;;; | |
1025 ;;; | |
1026 ;;; | |
1027 | |
1028 (defun scroll-other-window (&optional lines) | |
1029 "Scroll the text of the next window upward by LINES lines. The next window | |
1030 is generally the one below the current one, or the one at the top of the screen | |
1031 if the current window is at the bottom of the screen. In special circumstances | |
1032 this command will scroll a window other than the next window. Read the | |
1033 documentation for the function `scroll-choose-other-window' for details. | |
1034 | |
1035 The argument LINES is optional. Its meaning depends on the current value of | |
1036 the variable `scroll-in-place'. | |
1037 | |
1038 When the variable `scroll-in-place' is true, this command works just like the | |
1039 command `scroll-other-window-in-place', scrolling the next window and leaving | |
1040 point \"in place\" within that window. See the documentation for the command | |
1041 `scroll-other-window-in-place' for more information. | |
1042 | |
1043 When the variable `scroll-in-place' is `nil' this command invokes the standard | |
1044 GNU Emacs version of `scroll-other-window'. In that case, when LINES is `nil' | |
1045 the next window is scrolled by nearly a complete windowful of text. | |
1046 | |
1047 Note that this command correctly handles cases in which `scroll-in-place' has a | |
1048 buffer-local value in the window to be scrolled. That value is honored." | |
1049 (interactive "P") | |
1050 ;; This code is similar to the body of `scroll-window', below. | |
1051 (let* ((other-window (scroll-choose-other-window)) | |
1052 (other-window-buffer (window-buffer other-window))) | |
1053 (if ;; Allow `scroll-in-place' to be a buffer-local variable. | |
1054 (save-excursion (set-buffer other-window-buffer) scroll-in-place) | |
1055 (scroll-window-in-place other-window lines 1) | |
1056 | |
1057 ;; Paranoid, we forcibly break any running sequence of "in place" | |
1058 ;; scrolling commands. | |
1059 (setq scroll-previous-window nil) | |
1060 ;; For XEmacs and Lucid GNU Emacs, preserve the region's state. | |
1061 (if (boundp 'zmacs-region-stays) | |
1062 (setq zmacs-region-stays t)) | |
1063 (original-scroll-other-window lines)) | |
1064 )) | |
1065 | |
1066 | |
1067 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1068 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1069 ;;;; | |
1070 ;;;; Here are the new functions `scroll-window-in-place', `scroll-window', and | |
1071 ;;;; `scroll-window-in-place-continue-sequence'. These functions are intended | |
1072 ;;;; to be available to programs outside this package. | |
1073 ;;;; | |
1074 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1075 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1076 | |
1077 (defun scroll-window-in-place (window lines direction) | |
1078 "Scroll WINDOW vertically by the given number of window LINES in the given | |
1079 DIRECTION, leaving the window's point as close as possible to its original | |
1080 window position (window line and column). In other words, the window's point | |
1081 is left \"in place\" within the window. | |
1082 | |
1083 Note that the window to be scrolled does not have to be the selected window, | |
1084 and that this function does not change which window is selected. | |
1085 | |
1086 LINES specifies the number of window lines to scroll and is interpreted as if | |
1087 it were a raw prefix argument. If LINES is `nil', the window is scrolled by | |
1088 the amount it was moved by the immediately previous \"in place\" scrolling | |
1089 command, or by the value of the variable `scroll-default-lines' (by default, | |
1090 almost a windowful) if the previous command was not an \"in place\" scrolling | |
1091 command (or when WINDOW is not the previously scrolled window, or when the | |
1092 value of `this-command' is not in the same group as the previous scrolling | |
1093 command (see the documentation for the variable `scroll-command-groups'), or | |
1094 when other circumstances prevent the previous scrolling distance from being | |
1095 used). If LINES is the symbol `-', then the scrolling distance is determined | |
1096 as if LINES had been `nil' and then that distance is multiplied by -1. | |
1097 | |
1098 DIRECTION determines the direction of the scrolling motion. The values -1 and | |
1099 `down' indicate downward motion; the values 1 and `up' indicate upward motion. | |
1100 Any other value causes an error. | |
1101 | |
1102 If the window cannot be scrolled by the full distance (because the window hits | |
1103 the boundary of its buffer), the window's point is allowed to stray from its | |
1104 initial position so that it can move the full number of lines. If point cannot | |
1105 move the full number of lines, point is moved to the buffer boundary (unless it | |
1106 was already there, in which case a buffer boundary error is signalled instead). | |
1107 Any immediately subsequent \"in place\" scrolling commands will try to restore | |
1108 point to its initial window position. | |
1109 | |
1110 Unless the variable `scroll-allow-blank-lines-past-eob' is true, this function | |
1111 avoids displaying blank lines past the end of the buffer except as necessary to | |
1112 make a previous \"in place\" scrolling action reversible. Effectively, this | |
1113 means that this function will not display any more past-end-of-buffer blank | |
1114 lines than were visible when the current sequence of \"in place\" scrolling | |
1115 commands started. When the variable `scroll-allow-blank-lines-past-eob' is | |
1116 true, this function will display as many blank lines as is necessary to keep | |
1117 point \"in place\" in the window. | |
1118 | |
1119 Note that if WINDOW is not the selected window and it is impossible to scroll | |
1120 the text of WINDOW at all (because a buffer boundary is already visible), then | |
1121 this function signals a buffer boundary error. The error is signalled even if | |
1122 point could otherwise move the full number of lines." | |
1123 (let* (;; Make sure that the user doesn't quit in the middle and leave us | |
1124 ;; with our variables out of sync. | |
1125 (inhibit-quit t) | |
1126 (original-window (selected-window)) | |
1127 (original-buffer (current-buffer)) | |
1128 (window-height (- (window-height window) | |
1129 (if (window-minibuffer-p window) | |
1130 0 1))) | |
1131 (this-command-group (scroll-get-command-group this-command)) | |
1132 (continue-scroll-p | |
1133 (and ;; We're scrolling the previously scrolled window... | |
1134 (windowp scroll-previous-window) | |
1135 (eq window scroll-previous-window) | |
1136 ;; ...and the last command was an "in place" scrolling command | |
1137 ;; that can be continued by this command. | |
1138 (if (eq last-command t) | |
1139 ;; If the previous command signalled an error, the value of | |
1140 ;; `last-command' is `t'. Try to see if we signalled the | |
1141 ;; error and if point is where we left it. (NOTE that FSF | |
1142 ;; GNU Emacs 19.23+ no longer sets `last-command' to `t' | |
1143 ;; when a command signals an error. This is OK because the | |
1144 ;; else part of this `if' does the appropriate thing.) | |
1145 (and scroll-boundary-error-point | |
1146 (eq (window-point window) scroll-boundary-error-point) | |
1147 (memq scroll-boundary-error-command this-command-group) | |
1148 ) | |
1149 ;; Otherwise... | |
1150 (memq last-command this-command-group)) | |
1151 )) | |
1152 (lines-value (prefix-numeric-value lines)) | |
1153 ) | |
1154 | |
1155 ;; For XEmacs and Lucid GNU Emacs, preserve the region's state. Note that | |
1156 ;; these Emacsen will forcibly deactivate the region if we signal an error | |
1157 ;; later on. Is this bad? | |
1158 (if (boundp 'zmacs-region-stays) | |
1159 (setq zmacs-region-stays t)) | |
1160 ;; Parse the direction into a unit distance (1 or -1). | |
1161 (setq direction (scroll-parse-direction direction)) | |
1162 | |
1163 (setq scroll-previous-window window | |
1164 ;; `(setq scroll-boundary-error-command nil)' is not necessary. | |
1165 scroll-boundary-error-point nil) | |
1166 (unwind-protect | |
1167 (progn | |
1168 ;; `select-window' does an implicit `set-buffer'. | |
1169 (select-window window) | |
1170 | |
1171 (if (or ;; The current command is not a continuation of a running | |
1172 ;; sequence of "in place" scrolling commands... | |
1173 (not continue-scroll-p) | |
1174 ;; ...or we were given an explicit number of lines to scroll, | |
1175 ;; and that number has a different magnitude than the last | |
1176 ;; number of lines we scrolled... | |
1177 (and (or (numberp lines) (consp lines)) | |
1178 (/= scroll-previous-lines lines-value) | |
1179 (/= scroll-previous-lines (- lines-value))) | |
1180 ;; ...or the last successful scrolling command moved to a | |
1181 ;; buffer boundary, but the buffer is no longer in the state | |
1182 ;; we left it. (This can occur if, for example, we signal an | |
1183 ;; end-of-buffer error and something catches it and moves | |
1184 ;; point or renarrows. VM, for example, does this.) | |
1185 (and scroll-boundary-previous-point | |
1186 (or (not (or (bobp) (eobp))) | |
1187 (< scroll-boundary-previous-point (point-min)) | |
1188 (> scroll-boundary-previous-point (point-max)) | |
1189 (eq scroll-boundary-previous-point (point))))) | |
1190 | |
1191 ;; We're starting a new sequence of scrolling commands. | |
1192 (setq lines (if (or (numberp lines) (consp lines)) | |
1193 lines-value | |
1194 ;; The default number of lines... | |
1195 (* (if (eq lines '-) -1 1) | |
1196 (if (numberp scroll-default-lines) | |
1197 scroll-default-lines | |
1198 (max (- window-height | |
1199 next-screen-context-lines) | |
1200 1)))) | |
1201 scroll-previous-lines lines | |
1202 scroll-goal-column (scroll-determine-goal-column window) | |
1203 scroll-boundary-previous-point nil | |
1204 ;; `(setq scroll-boundary-previous-lines 0)' is not | |
1205 ;; necessary. | |
1206 scroll-window-debt 0 | |
1207 scroll-initially-displayed-lines | |
1208 (if scroll-allow-blank-lines-past-eob | |
1209 0 | |
1210 (save-excursion | |
1211 (goto-char (window-start window)) | |
1212 (vertical-motion (1- window-height))))) | |
1213 | |
1214 ;; Otherwise we want to scroll by the same number of lines (but | |
1215 ;; possibly in a different direction) that we scrolled in previous | |
1216 ;; invocations of this function. | |
1217 (cond ((null lines) | |
1218 (setq lines scroll-previous-lines)) | |
1219 ((eq lines '-) | |
1220 (setq lines (- scroll-previous-lines) | |
1221 scroll-previous-lines lines)) | |
1222 (t | |
1223 (setq lines lines-value | |
1224 scroll-previous-lines lines))) | |
1225 ) | |
1226 | |
1227 (setq lines (* direction lines)) | |
1228 | |
1229 ;; If point is not in the window, center window around point. We try | |
1230 ;; to account for a bug in `pos-visible-in-window-p' in some versions | |
1231 ;; of Emacs (see `scroll-pos-visible-bug-p', above). | |
1232 (save-excursion | |
1233 (if (pos-visible-in-window-p (let ((point (point))) | |
1234 (if (and scroll-pos-visible-bug-p | |
1235 (= point (point-max))) | |
1236 (max (1- point) (point-min)) | |
1237 point)) | |
1238 window) | |
1239 nil | |
1240 (vertical-motion (/ (- window-height) 2)) | |
1241 (set-window-start window (point)))) | |
1242 | |
1243 (cond ((and scroll-boundary-previous-point | |
1244 ;; `lines' is the same sign as the direction from point | |
1245 ;; to the `scroll-boundary-previous-point'. | |
1246 (cond ((> lines 0) | |
1247 (> (- scroll-boundary-previous-point (point)) 0)) | |
1248 ((< lines 0) | |
1249 (< (- scroll-boundary-previous-point (point)) 0)) | |
1250 (t nil))) | |
1251 ;; We're moving away from the buffer boundary. | |
1252 (goto-char scroll-boundary-previous-point) | |
1253 ;; Always move here (i.e., don't reject cases in which the | |
1254 ;; window doesn't move). | |
1255 (scroll-set-window-start window | |
1256 (- scroll-boundary-previous-lines)) | |
1257 ;; (message "Back, window debt is %s." scroll-window-debt) | |
1258 (setq scroll-boundary-previous-point nil)) | |
1259 | |
1260 ((= lines 0) | |
1261 ;; We're going nowhere, so save ourselves some work. | |
1262 ;; (message "Scrolled zero lines.") | |
1263 ) | |
1264 | |
1265 (t | |
1266 ;; Perform the scrolling motion. | |
1267 (let ((initial-point (point)) | |
1268 (moved nil)) | |
1269 ;; First move point and see how far it goes. | |
1270 (setq moved (vertical-motion lines)) | |
1271 (if (= moved lines) | |
1272 (progn | |
1273 ;; Point moved the full distance. Move to the desired | |
1274 ;; column and then try to move the window the full | |
1275 ;; distance, too. | |
1276 (move-to-column (+ (current-column) | |
1277 scroll-goal-column)) | |
1278 (or (scroll-set-window-start window moved | |
1279 original-window) | |
1280 (scroll-signal-boundary-error initial-point | |
1281 lines)) | |
1282 ;; (message "Normal, window debt is %s." | |
1283 ;; scroll-window-debt) | |
1284 ) | |
1285 ;; Point couldn't move all the way. Move to the buffer | |
1286 ;; boundary if we're not already there, or signal a buffer | |
1287 ;; boundary error otherwise. | |
1288 (let ((boundary-point (if (< lines 0) | |
1289 (point-min) | |
1290 (point-max))) | |
1291 (boundary-symbol (if (< lines 0) | |
1292 'beginning-of-buffer | |
1293 'end-of-buffer))) | |
1294 (if (= initial-point boundary-point) | |
1295 (scroll-signal-boundary-error initial-point lines) | |
1296 ;; Scroll the window by as many lines as point could | |
1297 ;; move. | |
1298 (or (scroll-set-window-start window moved | |
1299 original-window) | |
1300 (scroll-signal-boundary-error initial-point | |
1301 lines)) | |
1302 (message "%s" (get boundary-symbol 'error-message)) | |
1303 ;; (message "Boundary, window debt is %s." | |
1304 ;; scroll-window-debt) | |
1305 (setq scroll-boundary-previous-lines moved) | |
1306 (setq scroll-boundary-previous-point initial-point) | |
1307 (goto-char boundary-point)) | |
1308 ))) | |
1309 ))) | |
1310 | |
1311 ;; The unwind forms of the `unwind-protect', above. Restore the | |
1312 ;; originally selected window and current buffer. | |
1313 (select-window original-window) | |
1314 (set-buffer original-buffer))) | |
1315 | |
1316 ;; The standard GNU Emacs scrolling commands return `nil' so we do, too. | |
1317 nil) | |
1318 | |
1319 ;;; | |
1320 ;;; | |
1321 ;;; | |
1322 | |
1323 (defun scroll-window (window lines direction) | |
1324 "Scroll WINDOW vertically by the given number of window LINES in the given | |
1325 DIRECTION. Note that the window to be scrolled does not have to be the | |
1326 selected window, and that this function does not change which window is | |
1327 selected. | |
1328 | |
1329 When the variable `scroll-in-place' is true, this function simply invokes the | |
1330 function `scroll-window-in-place' to scroll the window and leave point \"in | |
1331 place\" within that window. See the documentation for `scroll-window-in-place' | |
1332 for more information. | |
1333 | |
1334 When the variable `scroll-in-place' is `nil' this function invokes the original | |
1335 version of the standard GNU Emacs command `scroll-down' or `scroll-up', as | |
1336 determined by DIRECTION, to scroll the window. If DIRECTION is -1 or `down', | |
1337 the original `scroll-down' is called; if DIRECTION is 1 or `up', the original | |
1338 `scroll-up' is called. Any other DIRECTION is an error. LINES is interpreted | |
1339 as if it were a raw prefix argument. If LINES is `nil', the window is scrolled | |
1340 by almost a complete windowful. If LINES is the symbol `-', the window is | |
1341 scrolled by almost a complete windowful in the opposite direction. | |
1342 | |
1343 Note that this function correctly handles cases in which `scroll-in-place' has | |
1344 a buffer-local value in the WINDOW's buffer. That value is honored." | |
1345 (let ((current-buffer (current-buffer)) | |
1346 (selected-window (selected-window)) | |
1347 (window-buffer (window-buffer window))) | |
1348 (if ;; Allow `scroll-in-place' to be a buffer-local variable. | |
1349 (if (eq current-buffer window-buffer) | |
1350 scroll-in-place | |
1351 (save-excursion (set-buffer window-buffer) scroll-in-place)) | |
1352 (scroll-window-in-place window lines direction) | |
1353 | |
1354 (unwind-protect | |
1355 (progn | |
1356 ;; Paranoid, we forcibly break any running sequence of "in place" | |
1357 ;; scrolling commands. | |
1358 (setq scroll-previous-window nil) | |
1359 ;; For XEmacs and Lucid GNU Emacs, preserve the region's state. | |
1360 (if (boundp 'zmacs-region-stays) | |
1361 (setq zmacs-region-stays t)) | |
1362 (select-window window) | |
1363 (if (= (scroll-parse-direction direction) 1) | |
1364 (original-scroll-up lines) | |
1365 (original-scroll-down lines))) | |
1366 (select-window selected-window) | |
1367 (set-buffer current-buffer)) | |
1368 ))) | |
1369 | |
1370 ;;; | |
1371 ;;; The following function is sometimes useful. For example, I call it from | |
1372 ;;; functions that are invoked by certain mouse button down events in order to | |
1373 ;;; preserve any running chain of "in place" scrolling commands. This lets me | |
1374 ;;; continue the sequence from my mouse button up functions. | |
1375 ;;; | |
1376 ;;; I haven't yet needed a function to purposely break a running sequence of | |
1377 ;;; "in place" scrolling commands. Such a function would be easy to write, | |
1378 ;;; however; just set the variable `scroll-previous-window' to `nil'. | |
1379 ;;; | |
1380 | |
1381 (defun scroll-window-in-place-continue-sequence () | |
1382 "If the previous command was a \"scroll in place\" command, set the variable | |
1383 `this-command' to the name of that previous command. This ensures that any | |
1384 running sequence of \"in place\" scrolling commands will not be broken by the | |
1385 current command. See the documentation for the commands `scroll-down-in-place' | |
1386 and `scroll-up-in-place' for more information about \"in place\" scrolling. | |
1387 | |
1388 NOTE that you don't need to call this function if the current command scrolls | |
1389 in place! You only need to call this function when the current command is not | |
1390 a \"scroll in place\" command but you still want to preserve any running | |
1391 sequence of \"in place\" commands. Such situations are rare. | |
1392 | |
1393 NOTE that this function sets `this-command' in order to trick the \"in place\" | |
1394 scrolling commands. If something else subsequently sets `this-command', any | |
1395 running sequence of scrolling commands will probably be broken anyway." | |
1396 (if (if (eq last-command t) | |
1397 ;; If `last-command' is `t', then the previous command signalled an | |
1398 ;; error. See if the last invocation of `scroll-window-in-place' | |
1399 ;; signalled an error. (NOTE that FSF GNU Emacs 19.23+ no longer | |
1400 ;; sets `last-command' to `t' when a command signals an error. This | |
1401 ;; is OK because the else part of this `if' does the appropriate | |
1402 ;; thing.) | |
1403 scroll-boundary-error-point | |
1404 ;; Otherwise, the value of `last-command' must belong to some group of | |
1405 ;; "in place" scrolling commands. | |
1406 (or (memq last-command scroll-default-command-group) | |
1407 (let ((groups scroll-command-groups) | |
1408 (found nil)) | |
1409 (while (and groups (not found)) | |
1410 (if (memq last-command (car groups)) | |
1411 (setq found t) | |
1412 (setq groups (cdr groups))) | |
1413 ) | |
1414 found))) | |
1415 (setq this-command last-command))) | |
1416 | |
1417 | |
1418 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1419 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1420 ;;;; | |
1421 ;;;; Here are the various auxiliary functions called by the function `scroll- | |
1422 ;;;; window-in-place'. None of the functions are intended to be called from | |
1423 ;;;; outside this package. | |
1424 ;;;; | |
1425 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1426 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1427 | |
1428 (defun scroll-get-command-group (command) | |
1429 "Return the group of \"in place\" scrolling commands that contains the given | |
1430 COMMAND. This is the list of commands with which the given command may share | |
1431 state and form \"chains.\" | |
1432 | |
1433 This function is an auxiliary for the function `scroll-window-in-place'. Don't | |
1434 call this function from other code." | |
1435 ;; This function assumes that the given command is an "in place" scrolling | |
1436 ;; command. | |
1437 (let ((groups scroll-command-groups) | |
1438 (found nil)) | |
1439 (while (and groups (not found)) | |
1440 (if (memq command (car groups)) | |
1441 (setq found t) | |
1442 (setq groups (cdr groups))) | |
1443 ) | |
1444 (if groups | |
1445 (car groups) | |
1446 ;; Otherwise return the default command group. If necessary, add the | |
1447 ;; given command to the default command group. | |
1448 (or (memq command scroll-default-command-group) | |
1449 (setq scroll-default-command-group | |
1450 (cons command scroll-default-command-group))) | |
1451 scroll-default-command-group) | |
1452 )) | |
1453 | |
1454 ;;; | |
1455 ;;; | |
1456 ;;; | |
1457 | |
1458 (defun scroll-parse-direction (direction) | |
1459 "Return the signed unit distance for the given DIRECTION. If DIRECTION is | |
1460 unacceptable, signal an error." | |
1461 (cond ((or (eq direction 1) (eq direction -1)) direction) | |
1462 ((eq direction 'up) 1) | |
1463 ((eq direction 'down) -1) | |
1464 (t (signal 'args-out-of-range (list 'direction direction))) | |
1465 )) | |
1466 | |
1467 ;;; | |
1468 ;;; | |
1469 ;;; | |
1470 | |
1471 (defun scroll-determine-goal-column (window) | |
1472 "Return the goal column for the \"in place\" vertical scrolling commands. | |
1473 This is the horizontal window position at which these commands try to keep | |
1474 point. | |
1475 | |
1476 This function is an auxiliary for the function `scroll-window-in-place'. Don't | |
1477 call this function from other code." | |
1478 ;; NOTE that `window' must be the selected window! `scroll-window-in-place' | |
1479 ;; ensures that this is so. | |
1480 (cond ((or truncate-lines | |
1481 (and truncate-partial-width-windows | |
1482 (< (window-width window) (screen-width))) | |
1483 (> (window-hscroll window) 0)) | |
1484 ;; Lines in this window are being truncated. | |
1485 (if (and track-eol (eolp)) | |
1486 9999 | |
1487 (current-column))) | |
1488 ((and track-eol (eolp)) | |
1489 ;; In some ways this isn't quite right, as point doesn't track the | |
1490 ;; ends of wrapped lines. But if it did so, point would be on the | |
1491 ;; wrong window line. This is the best we can do. | |
1492 (1- (window-width window))) | |
1493 (t (% (current-column) (1- (window-width window)))) | |
1494 )) | |
1495 | |
1496 ;;; | |
1497 ;;; | |
1498 ;;; | |
1499 | |
1500 (defun scroll-set-window-start (window lines &optional original-window) | |
1501 "Move the `window-start' of the given window, which must be the selected | |
1502 window. If the window was successfully scrolled, update the variable | |
1503 `scroll-window-debt' and return `t'. Otherwise return `nil'. | |
1504 | |
1505 This function is an auxiliary for the function `scroll-window-in-place'. Don't | |
1506 call this function from other code." | |
1507 (save-excursion | |
1508 (goto-char (window-start window)) | |
1509 ;; Try to move the window start by the specified number of lines. In | |
1510 ;; addition, try to make up any existing debt in the window start's | |
1511 ;; position and make sure that we don't move too close to the end of the | |
1512 ;; buffer. | |
1513 (let ((moved (+ (vertical-motion (+ lines | |
1514 scroll-window-debt | |
1515 scroll-initially-displayed-lines)) | |
1516 (vertical-motion (- scroll-initially-displayed-lines))))) | |
1517 ;; If we're not scrolling the `original-window' (i.e., the originally | |
1518 ;; selected window), punt if we didn't move the window start at all. | |
1519 (if (and original-window | |
1520 (not (eq window original-window)) | |
1521 (= moved 0)) | |
1522 nil | |
1523 ;; Otherwise update the window start and keep track of the debt in our | |
1524 ;; position. Return `t' to indicate success. | |
1525 (set-window-start window (point)) | |
1526 (setq scroll-window-debt (- (+ lines scroll-window-debt) moved)) | |
1527 t)) | |
1528 )) | |
1529 | |
1530 ;;; | |
1531 ;;; | |
1532 ;;; | |
1533 | |
1534 (defun scroll-signal-boundary-error (initial-point lines) | |
1535 "Move point to its initial location and signal an appropriate buffer boundary | |
1536 error. | |
1537 | |
1538 This function is an auxiliary for the function `scroll-window-in-place'. Don't | |
1539 call this function from other code." | |
1540 (goto-char initial-point) | |
1541 ;; Remember what we were doing and where point was when we signalled the | |
1542 ;; error so that subsequent "in place" scrolling commands can decide how to | |
1543 ;; recover. | |
1544 (setq scroll-boundary-error-command this-command | |
1545 scroll-boundary-error-point initial-point) | |
1546 (signal (if (< lines 0) 'beginning-of-buffer 'end-of-buffer) | |
1547 nil)) | |
1548 | |
1549 | |
1550 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1551 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1552 ;;;; | |
1553 ;;;; Finally, here is the `provide' statement. | |
1554 ;;;; | |
1555 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1556 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1557 | |
1558 (provide 'scroll-in-place) | |
1559 | |
1560 ;; End of file. | |
1561 |