Create paren-blinking custom group and put all blink-matching-paren variables in it.
[bpt/emacs.git] / lisp / view.el
CommitLineData
d501f516
ER
1;;; view.el --- peruse file or buffer without editing.
2
ab7782fc 3;; Copyright (C) 1985, 1989, 1994, 1995, 1997 Free Software Foundation, Inc.
eea8d4ef 4
e5167999 5;; Author: K. Shane Hartman
1036798c 6;; Maintainer: Inge Frick <inge@nada.kth.se>
e6211d55
RS
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
e5167999 12;; the Free Software Foundation; either version 2, or (at your option)
e6211d55
RS
13;; any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
b578f267
EN
21;; along with GNU Emacs; see the file COPYING. If not, write to the
22;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23;; Boston, MA 02111-1307, USA.
e6211d55 24
c91c4e6d
ER
25;;; Commentary:
26
bab0c3c1 27;; This package provides the `view' minor mode documented in the Emacs
c91c4e6d 28;; user's manual.
ab7782fc
RS
29;; View mode entry and exit is done through the functions view-mode-enter
30;; and view-mode-exit. Use these functions to enter or exit view-mode from
31;; emacs lisp programs.
32;; We use both view- and View- as prefix for symbols. View- is used as
33;; prefix for commands that have a key binding. view- is used for commands
34;; without key binding. The purpose of this is to make it easier for a
35;; user to use command name completion.
36
37;;; Suggested key bindings:
38;;
39;; (define-key ctl-x-4-map "v" 'view-file-other-window) ; ^x4v
40;; (define-key ctl-x-5-map "v" 'view-file-other-frame) ; ^x5v
41;;
42;; You could also bind view-file, view-buffer, view-buffer-other-window and
43;; view-buffer-other-frame to keys.
c91c4e6d 44
e5167999 45;;; Code:
e6211d55 46
82380f84
RS
47;;;###autoload
48(defvar view-highlight-face 'highlight
e51f616f 49 "*The face used for highlighting the match found by View mode search.")
82380f84 50
ab7782fc
RS
51;; `view-mode-auto-exit' is replaced by the following global variable which
52;; only says if scrolling past buffer end should leave view mode or not, it
e51f616f 53;; doesn't say if leaving view mode should restore windows or not. The latter
ab7782fc
RS
54;; is now controlled by the presence of a value in `view-return-to-alist'.
55;;;###autoload
56(defvar view-scroll-auto-exit nil
57 "*Non-nil means scrolling past the end of buffer exits View mode.
58nil means attempting to scroll past the end of the buffer,
59only rings the bell and gives a message on how to leave.")
60
61;;;###autoload
62(defvar view-try-extend-at-buffer-end nil
63 "*Non-nil means try load more of file when reaching end of buffer.")
64
65;;;###autoload
66(defvar view-remove-frame-by-deleting nil
67 "*Determine how to remove a not needed frame.
e51f616f 68If nil, make an icon of the frame. If non-nil, delete the frame.")
ab7782fc
RS
69
70;;;###autoload
71(defvar view-exit-all-windows-at-exit nil
72 "*Non-nil means restore all windows displaying buffer.
73Commands that restore windows apply to all windows displaying buffer.
74Buffer is removed from all windows displaying it, by using information in
75`view-return-to-alist' if that is available, otherwise by using
76`replace-buffer-in-windows'.")
77
c88daaef 78(defvar view-mode nil "Non-nil if View mode is enabled.")
bab0c3c1
KH
79(make-variable-buffer-local 'view-mode)
80
ab7782fc
RS
81(defvar view-mode-hook nil
82 "Normal hook run when starting to view a buffer or file.")
c88daaef
RS
83
84(defvar view-old-buffer-read-only nil)
85(make-variable-buffer-local 'view-old-buffer-read-only)
ab7782fc 86
c88daaef
RS
87(defvar view-old-Helper-return-blurb)
88(make-variable-buffer-local 'view-old-Helper-return-blurb)
89
ab7782fc
RS
90(defvar view-page-size nil
91 "Default number of lines to scroll by View page commands.
92If nil then the local value of this is initially set to window size.")
93(make-variable-buffer-local 'view-page-size)
c88daaef 94
ab7782fc
RS
95(defvar view-half-page-size nil
96 "Default number of lines to scroll by View half page commands.
97If nil then the local value of this is initially set to half window size.")
98(make-variable-buffer-local 'view-half-page-size)
c88daaef 99
ab7782fc
RS
100(defvar view-last-regexp nil)
101(make-variable-buffer-local 'view-last-regexp) ; Global is better???
102
103(defvar view-return-to-alist nil
104 "What to do with selected window and where to go when leaving View mode.
105Added to by view-mode-enter when entering View mode.
106See RETURN-TO-ALIST argument of function `view-mode-exit' for format of
e51f616f 107`view-return-to-alist'.")
ab7782fc
RS
108(make-variable-buffer-local 'view-return-to-alist)
109
110(defvar view-exit-action nil
111 "\\<view-mode-map>
112nil or a function with one argument (a buffer) called at exit of view mode.
113The \\[view-file] and \\[view-file-other-window] commands may set this to
114`kill-buffer'.")
c88daaef 115(make-variable-buffer-local 'view-exit-action)
c88daaef 116
4fe11426 117(defvar view-overlay nil
82380f84
RS
118 "Overlay used to display where a search operation found its match.
119This is local in each buffer, once it is used.")
4fe11426
RS
120(make-variable-buffer-local 'view-overlay)
121
bab0c3c1
KH
122(or (assq 'view-mode minor-mode-alist)
123 (setq minor-mode-alist
124 (cons '(view-mode " View") minor-mode-alist)))
125
ab7782fc
RS
126;; Define keymap inside defvar to make it easier to load changes.
127(defvar view-mode-map
128 (let ((map (make-sparse-keymap)))
129 (define-key map "C" 'View-kill-and-leave)
130 (define-key map "c" 'View-leave)
131 (define-key map "Q" 'View-quit-all)
132 (define-key map "E" 'View-exit-and-edit)
133; (define-key map "v" 'View-exit)
134 (define-key map "e" 'View-exit)
135 (define-key map "q" 'View-quit)
136; (define-key map "N" 'View-search-last-regexp-backward)
137 (define-key map "p" 'View-search-last-regexp-backward)
138 (define-key map "n" 'View-search-last-regexp-forward)
139; (define-key map "?" 'View-search-regexp-backward) ; Less does this.
140 (define-key map "\\" 'View-search-regexp-backward)
141 (define-key map "/" 'View-search-regexp-forward)
142 (define-key map "r" 'isearch-backward)
143 (define-key map "s" 'isearch-forward)
144 (define-key map "m" 'point-to-register)
145 (define-key map "'" 'register-to-point)
146 (define-key map "x" 'exchange-point-and-mark)
147 (define-key map "@" 'View-back-to-mark)
148 (define-key map "." 'set-mark-command)
149 (define-key map "%" 'View-goto-percent)
150; (define-key map "G" 'View-goto-line-last)
151 (define-key map "g" 'View-goto-line)
152 (define-key map "=" 'what-line)
153 (define-key map "F" 'View-revert-buffer-scroll-page-forward)
154; (define-key map "k" 'View-scroll-line-backward)
155 (define-key map "y" 'View-scroll-line-backward)
156; (define-key map "j" 'View-scroll-line-forward)
157 (define-key map "\n" 'View-scroll-line-forward)
158 (define-key map "\r" 'View-scroll-line-forward)
159 (define-key map "u" 'View-scroll-half-page-backward)
160 (define-key map "d" 'View-scroll-half-page-forward)
161 (define-key map "z" 'View-scroll-page-forward-set-page-size)
162 (define-key map "w" 'View-scroll-page-backward-set-page-size)
163; (define-key map "b" 'View-scroll-page-backward)
164 (define-key map "\C-?" 'View-scroll-page-backward)
165; (define-key map "f" 'View-scroll-page-forward)
166 (define-key map " " 'View-scroll-page-forward)
167 (define-key map "o" 'View-scroll-to-buffer-end)
168 (define-key map ">" 'end-of-buffer)
169 (define-key map "<" 'beginning-of-buffer)
170 (define-key map "-" 'negative-argument)
171 (define-key map "9" 'digit-argument)
172 (define-key map "8" 'digit-argument)
173 (define-key map "7" 'digit-argument)
174 (define-key map "6" 'digit-argument)
175 (define-key map "5" 'digit-argument)
176 (define-key map "4" 'digit-argument)
177 (define-key map "3" 'digit-argument)
178 (define-key map "2" 'digit-argument)
179 (define-key map "1" 'digit-argument)
180 (define-key map "0" 'digit-argument)
181 (define-key map "H" 'describe-mode)
182 (define-key map "?" 'describe-mode) ; Maybe do as less instead?
183 (define-key map "h" 'describe-mode)
184 map))
e6211d55 185
c88daaef
RS
186(or (assq 'view-mode minor-mode-map-alist)
187 (setq minor-mode-map-alist
188 (cons (cons 'view-mode view-mode-map) minor-mode-map-alist)))
189
ab7782fc 190;;; Commands that enter or exit view mode.
e6211d55 191
7229064d 192;;;###autoload
e6211d55
RS
193(defun view-file (file-name)
194 "View FILE in View mode, returning to previous buffer when done.
ab7782fc 195Emacs commands editing the buffer contents are not available; instead,
e6211d55
RS
196a special set of commands (mostly letters and punctuation)
197are defined for moving around in the buffer.
198Space scrolls forward, Delete scrolls backward.
ab7782fc 199For list of all View commands, type H or h while viewing.
e6211d55 200
bd0d2c58 201This command runs the normal hook `view-mode-hook'."
e6211d55 202 (interactive "fView file: ")
ab7782fc
RS
203 (let ((had-a-buf (get-file-buffer file-name)))
204 (view-buffer (find-file-noselect file-name)
205 (and (not had-a-buf) 'kill-buffer))))
e6211d55 206
b82fef5c
JB
207;;;###autoload
208(defun view-file-other-window (file-name)
ab7782fc
RS
209 "View FILE in View mode in another window.
210Return that window to its previous buffer when done.
211Emacs commands editing the buffer contents are not available; instead,
b82fef5c
JB
212a special set of commands (mostly letters and punctuation)
213are defined for moving around in the buffer.
214Space scrolls forward, Delete scrolls backward.
ab7782fc 215For list of all View commands, type H or h while viewing.
b82fef5c 216
bd0d2c58 217This command runs the normal hook `view-mode-hook'."
ab7782fc
RS
218 (interactive "fIn other window view file: ")
219 (let ((had-a-buf (get-file-buffer file-name)))
220 (view-buffer-other-window (find-file-noselect file-name) nil
221 (and (not had-a-buf) 'kill-buffer))))
b82fef5c 222
7229064d 223;;;###autoload
ab7782fc
RS
224(defun view-file-other-frame (file-name)
225 "View FILE in View mode in another frame.
226Maybe delete other frame and/or return to previous buffer when done.
227Emacs commands editing the buffer contents are not available; instead,
e6211d55
RS
228a special set of commands (mostly letters and punctuation)
229are defined for moving around in the buffer.
230Space scrolls forward, Delete scrolls backward.
ab7782fc 231For list of all View commands, type H or h while viewing.
e6211d55 232
bd0d2c58 233This command runs the normal hook `view-mode-hook'."
ab7782fc
RS
234 (interactive "fIn other frame view file: ")
235 (let ((had-a-buf (get-file-buffer file-name)))
236 (view-buffer-other-frame (find-file-noselect file-name) nil
237 (and (not had-a-buf) 'kill-buffer))))
238
239
240;;;###autoload
241(defun view-buffer (buffer-name &optional exit-action)
242 "View BUFFER in View mode, returning to previous buffer when done.
243Emacs commands editing the buffer contents are not available; instead,
244a special set of commands (mostly letters and punctuation)
245are defined for moving around in the buffer.
246Space scrolls forward, Delete scrolls backward.
247For list of all View commands, type H or h while viewing.
248
249This command runs the normal hook `view-mode-hook'.
250
251Optional argument EXIT-ACTION is either nil or a function with buffer as
e51f616f 252argument. This function is called when finished viewing buffer.
ab7782fc
RS
253Use this argument instead of explicitly setting `view-exit-action'."
254
e6211d55 255 (interactive "bView buffer: ")
ab7782fc
RS
256 (let ((undo-window (list (window-buffer) (window-start) (window-point))))
257 (switch-to-buffer buffer-name)
258 (view-mode-enter (cons (selected-window) (cons nil undo-window))
259 exit-action)))
e6211d55 260
b82fef5c 261;;;###autoload
ab7782fc
RS
262(defun view-buffer-other-window
263 (buffer-name &optional not-return exit-action)
bab0c3c1 264 "View BUFFER in View mode in another window.
ab7782fc
RS
265Return to previous buffer when done, unless optional NOT-RETURN is non-nil.
266Emacs commands editing the buffer contents are not available; instead,
267a special set of commands (mostly letters and punctuation)
268are defined for moving around in the buffer.
269Space scrolls forward, Delete scrolls backward.
270For list of all View commands, type H or h while viewing.
271
272This command runs the normal hook `view-mode-hook'.
273
274Optional argument EXIT-ACTION is either nil or a function with buffer as
e51f616f 275argument. This function is called when finished viewing buffer.
ab7782fc
RS
276Use this argument instead of explicitly setting `view-exit-action'."
277 (interactive "bIn other window view buffer:\nP")
278 (let* ((win ; This window will be selected by
279 (get-lru-window)) ; switch-to-buffer-other-window below.
280 (return-to
281 (and (not not-return)
282 (cons (selected-window)
283 (if (eq win (selected-window))
284 t ; Has to make new window.
285 (list
286 (window-buffer win) ; Other windows old buffer.
287 (window-start win)
288 (window-point win)))))))
289 (switch-to-buffer-other-window buffer-name)
290 (view-mode-enter (and return-to (cons (selected-window) return-to))
291 exit-action)))
5c05f569 292
ab7782fc
RS
293;;;###autoload
294(defun view-buffer-other-frame
295 (buffer-name &optional not-return exit-action)
296 "View BUFFER in View mode in another frame.
297Return to previous buffer when done, unless optional NOT-RETURN is non-nil.
298Emacs commands editing the buffer contents are not available; instead,
b82fef5c
JB
299a special set of commands (mostly letters and punctuation)
300are defined for moving around in the buffer.
301Space scrolls forward, Delete scrolls backward.
ab7782fc 302For list of all View commands, type H or h while viewing.
b82fef5c 303
ab7782fc
RS
304This command runs the normal hook `view-mode-hook'.
305
306Optional argument EXIT-ACTION is either nil or a function with buffer as
e51f616f 307argument. This function is called when finished viewing buffer.
ab7782fc
RS
308Use this argument instead of explicitly setting `view-exit-action'."
309 (interactive "bView buffer in other frame: \nP")
310 (let ((return-to
311 (and (not not-return) (cons (selected-window) t)))) ; Old window.
312 (switch-to-buffer-other-frame buffer-name)
313 (view-mode-enter (and return-to (cons (selected-window) return-to))
314 exit-action)))
b82fef5c 315
7229064d 316;;;###autoload
c88daaef 317(defun view-mode (&optional arg)
ab7782fc 318 ;; In the following documentation string we have to use some explicit key
e51f616f 319 ;; bindings instead of using the \\[] construction. The reason for this
ab7782fc
RS
320 ;; is that most commands have more than one key binding.
321 "Toggle View mode, a minor mode for viewing text but not editing it.
322With arg, turn View mode on iff arg is positive.
323
324Emacs commands that do not change the buffer contents are available as usual.
e51f616f 325Kill commands insert text in kill buffers but do not delete. Other commands
ab7782fc
RS
326\(among them most letters and punctuation) beep and tell that the buffer is
327read-only.
328\\<view-mode-map>
329The following additional commands are provided. Most commands take prefix
330arguments. Page commands default to \"page size\" lines which is almost a whole
331window full, or number of lines set by \\[View-scroll-page-forward-set-page-size] or \\[View-scroll-page-backward-set-page-size]. Half page commands default to
332and set \"half page size\" lines which initially is half a window full. Search
333commands default to a repeat count of one.
334
335H, h, ? This message.
336Digits provide prefix arguments.
337\\[negative-argument] negative prefix argument.
338\\[beginning-of-buffer] move to the beginning of buffer.
339> move to the end of buffer.
340\\[View-scroll-to-buffer-end] scroll so that buffer end is at last line of window.
341SPC scroll forward prefix (default \"page size\") lines.
342DEL scroll backward prefix (default \"page size\") lines.
343\\[View-scroll-page-forward-set-page-size] like \\[View-scroll-page-forward] except prefix sets \"page size\".
344\\[View-scroll-page-backward-set-page-size] like \\[View-scroll-page-backward] except prefix sets \"page size\".
345\\[View-scroll-half-page-forward] scroll forward (and if prefix set) \"half page size\" lines.
346\\[View-scroll-half-page-backward] scroll backward (and if prefix set) \"half page size\" lines.
347RET, LFD scroll forward prefix (default one) line(s).
348y scroll backward prefix (default one) line(s).
349\\[View-revert-buffer-scroll-page-forward] revert-buffer if necessary and scroll forward.
350 Use this to view a changing file.
351\\[what-line] prints the current line number.
352\\[View-goto-percent] goes prefix argument (default 100) percent into buffer.
353\\[View-goto-line] goes to line given by prefix argument (default first line).
354. set the mark.
355x exchanges point and mark.
356\\[View-back-to-mark] return to mark and pops mark ring.
357 Mark ring is pushed at start of every successful search and when
e51f616f 358 jump to line occurs. The mark is set on jump to buffer start or end.
ab7782fc
RS
359\\[point-to-register] save current position in character register.
360' go to position saved in character register.
361s do forward incremental search.
362r do reverse incremental search.
363\\[View-search-regexp-forward] searches forward for regular expression, starting after current page.
364 ! and @ have a special meaning at the beginning of the regexp.
e51f616f 365 ! means search for a line with no match for regexp. @ means start
ab7782fc
RS
366 search at beginning (end for backward search) of buffer.
367\\ searches backward for regular expression, starting before current page.
368\\[View-search-last-regexp-forward] searches forward for last regular expression.
369p searches backward for last regular expression.
370\\[View-quit] quit View mode, trying to restore window and buffer to previous state.
371 \\[View-quit] is the normal way to leave view mode.
e51f616f 372\\[View-exit] exit View mode but stay in current buffer. Use this if you started
ab7782fc
RS
373 viewing a buffer (file) and find out you want to edit it.
374\\[View-exit-and-edit] exit View mode and make the current buffer editable.
375\\[View-quit-all] quit View mode, trying to restore windows and buffer to previous state.
376\\[View-leave] quit View mode and maybe switch buffers, but don't kill this buffer.
377\\[View-kill-and-leave] quit View mode, kill current buffer and go back to other buffer.
378
e51f616f 379The effect of \\[View-leave] , \\[View-quit] and \\[View-kill-and-leave] depends on how view-mode was entered. If it was
ab7782fc
RS
380entered by view-file, view-file-other-window or view-file-other-frame (\\[view-file],
381\\[view-file-other-window], \\[view-file-other-frame] or the dired mode v command), then \\[View-quit] will try to kill the
e51f616f 382current buffer. If view-mode was entered from another buffer as is done by
ab7782fc
RS
383View-buffer, View-buffer-other-window, View-buffer-other frame, View-file,
384View-file-other-window or View-file-other-frame then \\[view-leave] , \\[view-quit] and \\[view-kill-and-leave] will return
385to that buffer.
386
387Entry to view-mode runs the normal hook `view-mode-hook'."
bc15ba42 388 (interactive "P")
ab7782fc
RS
389 (cond
390 ((and arg
391 (if (> (prefix-numeric-value arg) 0) view-mode (not view-mode)))
392 ()) ; Do nothing if already OK.
e51f616f
RS
393 (view-mode (view-mode-disable))
394 (t (view-mode-enable))))
395
396(defun view-mode-enable ()
397 "Turn on View mode."
8b7037d9
RS
398 ;; Always leave view mode before changing major mode.
399 ;; This is to guarantee that the buffer-read-only variable is restored.
400 (make-local-hook 'change-major-mode-hook)
401 (add-hook 'change-major-mode-hook 'view-mode-disable nil t)
e51f616f
RS
402 (setq view-mode t
403 view-page-size (view-page-size-default view-page-size)
404 view-half-page-size (or view-half-page-size (/ (view-window-size) 2))
405 view-old-buffer-read-only buffer-read-only
406 buffer-read-only t
407 view-old-Helper-return-blurb (and (boundp 'Helper-return-blurb)
408 Helper-return-blurb)
409 Helper-return-blurb
410 (format "continue viewing %s"
411 (if (buffer-file-name)
412 (file-name-nondirectory (buffer-file-name))
413 (buffer-name))))
414 (run-hooks 'view-mode-hook))
415
416(defun view-mode-disable ()
417 "Turn off View mode."
8b7037d9 418 (remove-hook 'change-major-mode-hook 'view-mode-disable t)
e51f616f
RS
419 (and view-overlay (delete-overlay view-overlay))
420 (setq view-mode nil
421 Helper-return-blurb view-old-Helper-return-blurb
422 buffer-read-only view-old-buffer-read-only))
ab7782fc
RS
423
424;;;###autoload
425(defun view-mode-enter (&optional return-to exit-action) "\
426Enter View mode and set up exit from view mode depending on optional arguments.
427If RETURN-TO is non-nil it is added as an element to the buffer local alist
428view-return-to-alist.
e51f616f
RS
429Save EXIT-ACTION in buffer local variable `view-exit-action'.
430It should be either nil or a function that takes a buffer as argument.
431This function will called by `view-mode-exit'.
432
ab7782fc 433RETURN-TO is either nil, meaning do nothing when exiting view mode, or
e51f616f
RS
434 \(WINDOW OLD-WINDOW . OLD-BUF-INFO).
435WINDOW is a window used for viewing.
436OLD-WINDOW is nil or the window to select after viewing.
437OLD-BUF-INFO tells what to do with WINDOW when exiting. It is one of:
ab7782fc 4381) nil Do nothing.
e51f616f
RS
4392) t Delete WINDOW or, if it is the only window, its frame.
4403) (OLD-BUFF START POINT) Display buffer OLD-BUFF with displayed text
441 starting at START and point at POINT in WINDOW.
ab7782fc 442
e51f616f 443See the function `view-mode' for the commands of View mode.
ab7782fc
RS
444
445This function runs the normal hook `view-mode-hook'."
446 (if return-to
447 (let ((entry (assq (car return-to) view-return-to-alist)))
448 (if entry (setcdr entry (cdr return-to))
449 (setq view-return-to-alist (cons return-to view-return-to-alist)))))
e51f616f
RS
450 (if view-mode ; Do nothing if already in view mode.
451 nil
452 (setq view-exit-action exit-action)
453 (view-mode-enable)
ab7782fc
RS
454 (force-mode-line-update)
455 (message "%s"
456 (substitute-command-keys "\
457Type \\[help-command] for help, \\[describe-mode] for commands, \\[View-quit] to quit."))))
458
459(defun view-mode-exit (&optional return-to-alist exit-action all-win)
460 "Exit view-mode in various ways, depending on optional arguments.
461RETURN-TO-ALIST, EXIT-ACTION and ALL-WIN determine what to do after
462exit.
463EXIT-ACTION is nil or a function that is called with current buffer as
464argument.
465RETURN-TO-ALIST is an alist that for some of the windows displaying the current
e51f616f 466buffer, associate information on what to do with those windows. If ALL-WIN is
ab7782fc
RS
467non-nil, then all windows on RETURN-TO-ALIST are restored to their old state.
468If ALL-WIN is nil, then only the selected window is affected (if it is on
e51f616f
RS
469ALL-WIN). Each element has the format (WINDOW OLD-WINDOW . OLD-BUF-INFO)
470where WINDOW is a window displaying the current buffer and OLD-BUF-INFO is
471information on what to do with WINDOW. OLD-BUF-INFO is one of:
ab7782fc 4721) nil Do nothing.
e51f616f
RS
4732) t Delete WINDOW or, if it is the only window, its frame.
4743) (OLD-BUF START POINT) Display buffer OLD-BUF with displayed text
475 starting at START and point at POINT in WINDOW.
476If one of the WINDOW in RETURN-TO-ALIST is the selected window and the
477corresponding OLD-WINDOW is a live window, then select OLD-WINDOW."
ab7782fc
RS
478 (if view-mode ; Only do something if in view mode.
479 (let* ((buffer (current-buffer))
480 window
481 (sel-old (assq (selected-window) return-to-alist))
482 (old-window (or (and sel-old (car (cdr sel-old)))
483 (and all-win (selected-window))))
484 (alist (if (setq all-win
485 (or all-win view-exit-all-windows-at-exit))
486 return-to-alist ; Try to restore all windows.
487 (and sel-old (list sel-old))))) ; Only selected window.
e51f616f
RS
488 (view-mode-disable)
489 (setq view-exit-action nil
490 view-return-to-alist nil)
ab7782fc
RS
491 (while alist ; Restore windows with info.
492 (if (and (window-live-p (setq window (car (car alist))))
493 (eq buffer (window-buffer window)))
494 (let ((frame (window-frame window))
495 (old-buf-info (cdr (cdr (car alist)))))
496 (if all-win (select-window window))
497 (cond
498 ((and (consp old-buf-info) ; Case 3.
499 (buffer-live-p (car old-buf-info)))
500 (set-window-buffer window (car old-buf-info)) ; old-buf
501 (set-window-start window (car (cdr old-buf-info)))
502 (set-window-point window (car (cdr (cdr old-buf-info)))))
503 ((not (eq old-buf-info t)) nil) ; Not case 2, do nothing.
504 ((not (one-window-p t)) (delete-window))
505 ((not (eq frame (next-frame))) ; Not the only frame, so
506 (if view-remove-frame-by-deleting (delete-frame frame)
507 (iconify-frame frame)))))) ; can safely be removed.
508 (setq alist (cdr alist)))
509 (if (and return-to-alist view-exit-all-windows-at-exit)
510 (replace-buffer-in-windows buffer))
511 (if (window-live-p old-window) ; still existing window
512 (select-window old-window))
513 (if (and exit-action (not (get-buffer-window buffer)))
514 (funcall exit-action buffer))
515 (force-mode-line-update))))
516
517(defun View-exit ()
518 "Exit View mode but stay in current buffer."
e6211d55 519 (interactive)
ab7782fc 520 (view-mode-exit))
e6211d55 521
ab7782fc
RS
522(defun View-exit-and-edit ()
523 "Exit View mode and make the current buffer editable."
524 (interactive)
525 (view-mode-exit)
526 (setq buffer-read-only nil))
527
528(defun View-leave ()
529 "Quit View mode and maybe switch buffers, but don't kill this buffer."
530 (interactive)
531 (view-mode-exit view-return-to-alist))
532
533(defun View-quit ()
534 "Quit View mode, trying to restore window and buffer to previous state.
e51f616f 535Maybe kill this buffer. Try to restore selected window to previous state
ab7782fc
RS
536and go to previous buffer or window."
537 (interactive)
538 (view-mode-exit view-return-to-alist view-exit-action))
539
540(defun View-quit-all ()
e51f616f
RS
541 "Quit View mode, trying to restore windows and buffers to previous state.
542Maybe kill current buffer. Try to restore all windows viewing buffer to
ab7782fc
RS
543previous state and go to previous buffer or window."
544 (interactive)
545 (view-mode-exit view-return-to-alist view-exit-action t))
546
547(defun View-kill-and-leave ()
548 "Quit View mode, kill current buffer and return to previous buffer."
549 (interactive)
550 (view-mode-exit view-return-to-alist (or view-exit-action 'kill-buffer) t))
551
552
553;;; Some help routines.
554
555(defun view-window-size ()
556 ;; Window height excluding mode line.
557 (1- (window-height)))
bd0d2c58 558
e6211d55
RS
559;(defun view-last-command (&optional who what)
560; (setq view-last-command-entry this-command)
561; (setq view-last-command who)
562; (setq view-last-command-argument what))
563
564;(defun View-repeat-last-command ()
565; "Repeat last command issued in View mode."
566; (interactive)
567; (if (and view-last-command
568; (eq view-last-command-entry last-command))
569; (funcall view-last-command view-last-command-argument))
570; (setq this-command view-last-command-entry))
571
ab7782fc
RS
572(defun view-recenter ()
573 ;; Center point in window.
574 (recenter (/ (view-window-size) 2)))
575
576(defun view-page-size-default (lines)
577 ;; Get page size.
578 (let ((default (- (view-window-size) next-screen-context-lines)))
579 (if (or (null lines) (zerop (setq lines (prefix-numeric-value lines))))
580 default
581 (min (abs lines) default))))
582
583(defun view-set-half-page-size-default (lines)
584 ;; Get and maybe set half page size.
585 (if (not lines) view-half-page-size
586 (setq view-half-page-size
587 (if (zerop (setq lines (prefix-numeric-value lines)))
588 (/ (view-window-size) 2)
589 (view-page-size-default lines)))))
590
591
592;;; Commands for moving around in the buffer.
593
594(defun View-goto-percent (&optional percent)
595 "Move to end (or prefix PERCENT) of buffer in View mode.
596Display is centered at point.
e51f616f 597Also set the mark at the position where point was."
ab7782fc
RS
598 (interactive "P")
599 (push-mark)
600 (goto-char
601 (if percent
602 (+ (point-min)
603 (floor (* (- (point-max) (point-min)) 0.01
604 (max 0 (min 100 (prefix-numeric-value percent))))))
605 (point-max)))
606 (view-recenter))
607
608;(defun View-goto-line-last (&optional line)
609;"Move to last (or prefix LINE) line in View mode.
610;Display is centered at LINE.
611;Sets mark at starting position and pushes mark ring."
612; (interactive "P")
613; (push-mark)
614; (if line (goto-line (prefix-numeric-value line))
615; (goto-char (point-max))
616; (beginning-of-line))
617; (view-recenter))
618
619(defun View-goto-line (&optional line)
620 "Move to first (or prefix LINE) line in View mode.
621Display is centered at LINE.
e51f616f 622Also set the mark at the position where point was."
e6211d55
RS
623 (interactive "p")
624 (push-mark)
bab0c3c1 625 (goto-line line)
ab7782fc 626 (view-recenter))
e6211d55 627
ab7782fc
RS
628(defun View-scroll-to-buffer-end ()
629 "Scroll backward or forward so that buffer end is at last line of window."
630 (interactive)
631 (let ((p (if (pos-visible-in-window-p (point-max)) (point))))
632 (goto-char (point-max))
633 (recenter -1)
634 (and p (goto-char p))))
635
636(defun view-scroll-lines (lines backward default maxdefault)
637 ;; This function does the job for all the scrolling commands.
e51f616f
RS
638 ;; Scroll forward LINES lines. If BACKWARD is true scroll backwards.
639 ;; If LINES is negative scroll in the other direction. If LINES is 0 or nil,
640 ;; scroll DEFAULT lines. If MAXDEFAULT is true then scroll no more than a
ab7782fc
RS
641 ;; window full.
642 (if (or (null lines) (zerop (setq lines (prefix-numeric-value lines))))
643 (setq lines default))
644 (if (< lines 0)
645 (progn (setq backward (not backward)) (setq lines (- lines))))
646 (setq default (view-page-size-default nil)) ; Max scrolled at a time.
647 (if maxdefault (setq lines (min lines default)))
648 (cond
649 (backward (scroll-down lines))
650 ((view-really-at-end)
651 (if view-scroll-auto-exit (View-quit)
652 (ding)
653 (view-end-message)))
654 (t (while (> lines default)
655 (scroll-up default)
656 (setq lines (- lines default))
657 (if (view-really-at-end) (setq lines 0)))
658 (scroll-up lines)
659 (if (view-really-at-end) (view-end-message))
660 (move-to-window-line -1)
661 (beginning-of-line))))
662
663(defun view-really-at-end ()
e51f616f 664 ;; Return true if buffer end visible. Maybe revert buffer and test.
ab7782fc
RS
665 (and (pos-visible-in-window-p (point-max))
666 (let ((buf (current-buffer))
667 (bufname (buffer-name))
668 (file (buffer-file-name)))
669 (or (not view-try-extend-at-buffer-end)
670 (not file)
671 (verify-visited-file-modtime buf)
672 (not (file-exists-p file))
673 (and (buffer-modified-p buf)
674 (setq file (file-name-nondirectory file))
675 (not (yes-or-no-p
676 (format
677 "File %s changed on disk. Discard your edits%s? "
678 file
679 (if (string= bufname file) ""
680 (concat " in " bufname))))))
681 (progn (revert-buffer t t t)
682 (pos-visible-in-window-p (point-max)))))))
683
684(defun view-end-message ()
685 ;; Tell that we are at end of buffer.
686 (goto-char (point-max))
687 (message "End of buffer. Type %s to quit viewing."
688 (substitute-command-keys
689 (if view-scroll-auto-exit "\\[View-scroll-page-forward]"
690 "\\[View-quit]"))))
691
692(defun View-scroll-page-forward (&optional lines)
693 "Scroll \"page size\" or prefix LINES lines forward in View mode.
e51f616f 694Exit if end of text is visible and `view-scroll-auto-exit' is non-nil.
ab7782fc
RS
695\"page size\" is whole window full, or number of lines set by
696\\[View-scroll-page-forward-set-page-size] or
697\\[View-scroll-page-backward-set-page-size].
698If LINES is more than a window-full, only the last window-full is shown."
e6211d55 699 (interactive "P")
ab7782fc
RS
700 (view-scroll-lines lines nil view-page-size nil))
701
702(defun View-scroll-page-backward (&optional lines)
703 "Scroll \"page size\" or prefix LINES lines backward in View mode.
e51f616f 704See also `View-scroll-page-forward'."
e6211d55 705 (interactive "P")
ab7782fc
RS
706 (view-scroll-lines lines t view-page-size nil))
707
708(defun View-scroll-page-forward-set-page-size (&optional lines)
e51f616f 709 "Scroll forward LINES lines in View mode, setting the \"page size\".
ab7782fc 710This is the number of lines which \\[View-scroll-page-forward] and
e51f616f 711\\[View-scroll-page-backward] scroll by default. If LINES is omitted or = 0,
ab7782fc
RS
712sets \"page size\" to window height and scrolls forward that much, otherwise
713scrolls forward LINES lines and sets \"page size\" to the minimum of window
714height and the absolute value of LINES.
e51f616f 715See also `View-scroll-page-forward'."
e6211d55 716 (interactive "P")
ab7782fc
RS
717 (view-scroll-lines lines nil
718 (setq view-page-size (view-page-size-default lines))
719 nil))
e6211d55 720
ab7782fc
RS
721(defun View-scroll-page-backward-set-page-size (&optional lines)
722 "Scroll backward prefix LINES lines in View mode, setting the \"page size\".
e51f616f 723See also `View-scroll-page-forward-set-page-size'."
e6211d55 724 (interactive "P")
ab7782fc
RS
725 (view-scroll-lines lines t
726 (setq view-page-size (view-page-size-default lines))
727 nil))
728
729(defun View-scroll-line-forward (&optional lines)
730 "Scroll forward one line (or prefix LINES lines) in View mode.
e51f616f 731See also `View-scroll-page-forward,' but note that scrolling is limited
ab7782fc
RS
732to minimum of LINES and one window-full."
733 (interactive "P")
734 (view-scroll-lines lines nil 1 t))
735
736(defun View-scroll-line-backward (&optional lines)
737 "Scroll backward one line (or prefix LINES lines) in View mode.
e51f616f 738See also `View-scroll-line-forward'."
ab7782fc
RS
739 (interactive "P")
740 (view-scroll-lines lines t 1 t))
741
742(defun View-scroll-half-page-forward (&optional lines)
e51f616f 743 "Scroll forward a \"half page\" (or prefix LINES) lines in View mode.
ab7782fc
RS
744If LINES is not omitted, the \"half page size\" is set to the minimum of
745window height and the absolute value of LINES.
746LINES=0 resets \"half page size\" to half window height."
747 (interactive "P")
748 (view-scroll-lines lines nil (view-set-half-page-size-default lines) t))
749
750(defun View-scroll-half-page-backward (&optional lines)
e51f616f
RS
751 "Scroll backward a \"half page\" (or prefix LINES) lines in View mode.
752See also `View-scroll-half-page-forward'."
ab7782fc
RS
753 (interactive "P")
754 (view-scroll-lines lines t (view-set-half-page-size-default lines) t))
755
e51f616f
RS
756(defun View-revert-buffer-scroll-page-forward (&optional lines)
757 "Scroll forward, reverting buffer if needed, in View mode.
ab7782fc
RS
758If buffer has not been changed and the corresponding file is newer, first
759revert the buffer, then scroll.
760This command is useful if you are viewing a changing file.
e51f616f
RS
761
762The prefix argument LINES says how many lines to scroll.
763If you don't specify a prefix argument, it uses the number of lines set by
ab7782fc
RS
764\\[View-scroll-page-forward-set-page-size] or
765\\[View-scroll-page-backward-set-page-size].
766If LINES is more than a window-full, only the last window-full is shown."
767 (interactive "P")
768 (let ((view-mode-auto-exit nil)
769 (view-try-extend-at-buffer-end t))
770 (view-scroll-lines lines nil view-page-size nil)))
771
772(defun View-back-to-mark (&optional ignore)
773 "Return to last mark set in View mode, else beginning of file.
e51f616f
RS
774Display that line at the center of the window.
775This command pops the mark ring, so that successive
ab7782fc
RS
776invocations return to earlier marks."
777 (interactive)
778 (goto-char (or (mark t) (point-min)))
779 (pop-mark)
780 (view-recenter))
781
5c05f569 782(defun View-search-regexp-forward (n regexp)
ab7782fc
RS
783 "Search forward for first (or prefix Nth) occurrence of REGEXP in View mode.
784Displays line found at center of window. REGEXP is remembered for searching
e51f616f 785with \\[View-search-last-regexp-forward] and \\[View-search-last-regexp-backward]. Sets mark at starting position and pushes mark ring.
ab7782fc 786Characters @ or ! or combined as @! or !@ are special if entered at the
e51f616f
RS
787beginning of REGEXP. They modify the search rather than become part of pattern
788searched for. @ means start search at the beginning of buffer. ! means search
789for line that not contains match for pattern. If REGEXP only consist of these
ab7782fc 790control characters, then an earlier remembered REGEXP is used.
5534818b
RS
791
792The variable `view-highlight-face' controls the face that is used
793for highlighting the match that is found."
ab7782fc
RS
794 (interactive "p\nsSearch forward (regexp): ")
795 (view-search n regexp))
e6211d55 796
5c05f569 797(defun View-search-regexp-backward (n regexp)
ab7782fc
RS
798 "Search backward for first (or prefix Nth) occurrence of REGEXP in View mode.
799Displays line found at center of window. REGEXP is remembered for searching
e51f616f 800with \\[View-search-last-regexp-forward] and \\[View-search-last-regexp-backward]. Sets mark at starting position and pushes mark ring.
ab7782fc 801Characters @ or ! or combined as @! or !@ are special if entered at the
e51f616f
RS
802beginning of REGEXP. They modify the search rather than become part of pattern
803searched for. @ means start search at the end of buffer. ! means search
804for line that not contains match for pattern. If REGEXP only consist of these
ab7782fc 805control characters, then an earlier remembered REGEXP is used.
5534818b
RS
806
807The variable `view-highlight-face' controls the face that is used
808for highlighting the match that is found."
e6211d55 809 (interactive "p\nsSearch backward (regexp): ")
ab7782fc 810 (view-search (- n) regexp))
e6211d55 811
ab7782fc
RS
812(defun View-search-last-regexp-forward (n) "\
813Search forward for first (or prefix Nth) instance of last regexp in View mode.
814Displays line found at center of window. Sets mark at starting position and
815pushes mark ring.
5534818b
RS
816
817The variable `view-highlight-face' controls the face that is used
818for highlighting the match that is found."
e6211d55 819 (interactive "p")
ab7782fc 820 (view-search n nil))
e6211d55 821
ab7782fc
RS
822(defun View-search-last-regexp-backward (n) "\
823Search backward for first (or prefix Nth) instance of last regexp in View mode.
e6211d55 824Displays line found at center of window. Sets mark at starting position and
5534818b
RS
825pushes mark ring.
826
827The variable `view-highlight-face' controls the face that is used
828for highlighting the match that is found."
e6211d55 829 (interactive "p")
ab7782fc 830 (view-search (- n) nil))
e6211d55 831
e6211d55 832(defun view-search (times regexp)
ab7782fc
RS
833 ;; This function does the job for all the view-search commands.
834 (let (where no end ln)
835 (cond
836 ((and regexp (> (length regexp) 0)
837 (or (not (memq (string-to-char regexp) '(?! ?@)))
838 (progn
839 (if (member (substring regexp 0 2) '("!@" "@!"))
840 (setq end t no t ln 2)
841 (setq no (not (setq end (eq ?@ (string-to-char regexp))))
842 ln 1))
843 (> (length (setq regexp (substring regexp ln))) 0))))
844 (setq view-last-regexp (if no (list regexp) regexp)))
845 ((consp view-last-regexp)
846 (setq regexp (car view-last-regexp))
847 (if (not (setq no (not no))) (setq view-last-regexp regexp)))
848 (view-last-regexp (setq regexp view-last-regexp)
849 (if no (setq view-last-regexp (list regexp))))
850 (t (error "No previous View-mode search")))
e6211d55 851 (save-excursion
ab7782fc
RS
852 (if end (goto-char (if (< times 0) (point-max) (point-min)))
853 (move-to-window-line (if (< times 0) 0 -1)))
854 (if (if no (view-search-no-match-lines times regexp)
855 (re-search-forward regexp nil t times))
e6211d55
RS
856 (setq where (point))))
857 (if where
858 (progn
859 (push-mark)
860 (goto-char where)
4fe11426
RS
861 (if view-overlay
862 (move-overlay view-overlay (match-beginning 0) (match-end 0))
863 (setq view-overlay
864 (make-overlay (match-beginning 0) (match-end 0))))
82380f84 865 (overlay-put view-overlay 'face view-highlight-face)
e6211d55 866 (beginning-of-line)
ab7782fc
RS
867 (view-recenter))
868 (message "Can't find occurrence %d of %s%s"
869 times (if no "no " "") regexp)
e6211d55
RS
870 (sit-for 4))))
871
ab7782fc
RS
872(defun view-search-no-match-lines (times regexp)
873 ;; Search for the TIMESt occurrence of line with no match for REGEXP.
874 (let ((back (and (< times 0) (setq times (- times)) -1))
875 n)
876 (while (> times 0)
877 (save-excursion (beginning-of-line (if back (- times) (1+ times)))
878 (setq n (point)))
879 (setq times
880 (cond
881 ((< (count-lines (point) n) times) -1) ; Not enough lines.
882 ((or (null (re-search-forward regexp nil t back))
883 (if back (and (< (match-end 0) n)
884 (> (count-lines (match-end 0) n) 1))
885 (and (< n (match-beginning 0))
886 (> (count-lines n (match-beginning 0)) 1))))
887 0) ; No match within lines.
888 (back (count-lines (max n (match-beginning 0)) (match-end 0)))
889 (t (count-lines (match-beginning 0) (min n (match-end 0))))))
890 (goto-char n))
891 (and (zerop times) (looking-at "^.*$"))))
892
893
49116ac0
JB
894(provide 'view)
895
d501f516 896;;; view.el ends here