Switch to recommended form of GPLv3 permissions notice.
[bpt/emacs.git] / lisp / view.el
CommitLineData
e8af40ee 1;;; view.el --- peruse file or buffer without editing
d501f516 2
0d30b337 3;; Copyright (C) 1985, 1989, 1994, 1995, 1997, 2000, 2001, 2002,
409cc4a3 4;; 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
eea8d4ef 5
e5167999 6;; Author: K. Shane Hartman
1036798c 7;; Maintainer: Inge Frick <inge@nada.kth.se>
284b3043 8;; Keywords: files
e6211d55
RS
9
10;; This file is part of GNU Emacs.
11
eb3fa2cf 12;; GNU Emacs is free software: you can redistribute it and/or modify
e6211d55 13;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
e6211d55
RS
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
eb3fa2cf 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
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 29;; View mode entry and exit is done through the functions view-mode-enter
66d3a2b5 30;; and view-mode-exit. Use these functions to enter or exit view-mode from
ab7782fc 31;; emacs lisp programs.
66d3a2b5 32;; We use both view- and View- as prefix for symbols. View- is used as
cae55197 33;; prefix for commands that have a key binding. view- is used for commands
66d3a2b5 34;; without key binding. The purpose of this is to make it easier for a
ab7782fc
RS
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.
0d63ba8c 44\f
e5167999 45;;; Code:
e6211d55 46
cae55197
KH
47(defgroup view nil
48 "Peruse file or buffer without editing."
49 :link '(function-link view-mode)
50 :link '(custom-manual "(emacs)Misc File Ops")
51 :group 'wp
52 :group 'editing)
53
cae55197
KH
54(defcustom view-highlight-face 'highlight
55 "*The face used for highlighting the match found by View mode search."
56 :type 'face
57 :group 'view)
82380f84 58
66d3a2b5 59;; `view-mode-auto-exit' is replaced by the following option variable which
ab7782fc 60;; only says if scrolling past buffer end should leave view mode or not, it
e51f616f 61;; doesn't say if leaving view mode should restore windows or not. The latter
ab7782fc 62;; is now controlled by the presence of a value in `view-return-to-alist'.
cae55197 63(defcustom view-scroll-auto-exit nil
ab7782fc 64 "*Non-nil means scrolling past the end of buffer exits View mode.
39d9e44f 65A value of nil means attempting to scroll past the end of the buffer,
cae55197
KH
66only rings the bell and gives a message on how to leave."
67 :type 'boolean
68 :group 'view)
ab7782fc 69
cae55197 70(defcustom view-try-extend-at-buffer-end nil
39d9e44f 71 "*Non-nil means try to load more of file when reaching end of buffer.
66d3a2b5
RS
72This variable is mainly intended to be temporarily set to non-nil by
73the F command in view-mode, but you can set it to t if you want the action
cae55197
KH
74for all scroll commands in view mode."
75 :type 'boolean
76 :group 'view)
ab7782fc 77
78ddc123
MR
78;;;###autoload
79(defcustom view-remove-frame-by-deleting t
cae55197
KH
80 "*Determine how View mode removes a frame no longer needed.
81If nil, make an icon of the frame. If non-nil, delete the frame."
82 :type 'boolean
78ddc123
MR
83 :group 'view
84 ;; Changed the default of this to t for Emacs 23. Users consider
85 ;; frame iconification annoying.
86 :version "23.1")
ab7782fc 87
cae55197 88(defcustom view-exits-all-viewing-windows nil
66d3a2b5
RS
89 "*Non-nil means restore all windows used to view buffer.
90Commands that restore windows when finished viewing a buffer, apply to all
91windows that display the buffer and have restore information in
cae55197 92`view-return-to-alist'.
d9855810 93If `view-exits-all-viewing-windows' is nil, only the selected window is
cae55197
KH
94considered for restoring."
95 :type 'boolean
96 :group 'view)
ab7782fc 97
1c0484e2 98(defcustom view-inhibit-help-message nil
39d9e44f 99 "*Non-nil inhibits the help message shown upon entering View mode."
1c0484e2
RF
100 :type 'boolean
101 :group 'view
102 :version "22.1")
103
0093dc5a 104;;;###autoload
cae55197
KH
105(defvar view-mode nil
106 "Non-nil if View mode is enabled.
107Don't change this variable directly, you must change it by one of the
108functions that enable or disable view mode.")
0093dc5a 109;;;###autoload
bab0c3c1
KH
110(make-variable-buffer-local 'view-mode)
111
cae55197
KH
112(defcustom view-mode-hook nil
113 "Normal hook run when starting to view a buffer or file."
114 :type 'hook
115 :group 'view)
0d63ba8c 116\f
c88daaef
RS
117(defvar view-old-buffer-read-only nil)
118(make-variable-buffer-local 'view-old-buffer-read-only)
ab7782fc 119
c88daaef
RS
120(defvar view-old-Helper-return-blurb)
121(make-variable-buffer-local 'view-old-Helper-return-blurb)
122
0d63ba8c
RS
123;; Just to avoid warnings.
124(defvar Helper-return-blurb)
125
ab7782fc
RS
126(defvar view-page-size nil
127 "Default number of lines to scroll by View page commands.
5bf70f47 128If nil that means use the window size.")
ab7782fc 129(make-variable-buffer-local 'view-page-size)
c88daaef 130
ab7782fc
RS
131(defvar view-half-page-size nil
132 "Default number of lines to scroll by View half page commands.
5bf70f47 133If nil that means use half the window size.")
ab7782fc 134(make-variable-buffer-local 'view-half-page-size)
c88daaef 135
ab7782fc
RS
136(defvar view-last-regexp nil)
137(make-variable-buffer-local 'view-last-regexp) ; Global is better???
138
139(defvar view-return-to-alist nil
66d3a2b5
RS
140 "What to do with used windows and where to go when finished viewing buffer.
141This is local in each buffer being viewed.
d9855810
RS
142It is added to by `view-mode-enter' when starting to view a buffer and
143subtracted from by `view-mode-exit' when finished viewing the buffer.
66d3a2b5
RS
144
145See RETURN-TO-ALIST argument of function `view-mode-exit' for the format of
e51f616f 146`view-return-to-alist'.")
ab7782fc 147(make-variable-buffer-local 'view-return-to-alist)
da932079 148(put 'view-return-to-alist 'permanent-local t)
ab7782fc
RS
149
150(defvar view-exit-action nil
78ddc123
MR
151 "If non-nil, a function with one argument (a buffer) called when finished viewing.
152Commands like \\[view-file] and \\[view-file-other-window] may
153set this to bury or kill the viewed buffer.
154Observe that the buffer viewed might not appear in any window at
155the time this function is called.")
c88daaef 156(make-variable-buffer-local 'view-exit-action)
c88daaef 157
1a552841
RS
158(defvar view-no-disable-on-exit nil
159 "If non-nil, View mode \"exit\" commands don't actually disable View mode.
160Instead, these commands just switch buffers or windows.
161This is set in certain buffers by specialized features such as help commands
162that use View mode automatically.")
163
4fe11426 164(defvar view-overlay nil
82380f84
RS
165 "Overlay used to display where a search operation found its match.
166This is local in each buffer, once it is used.")
4fe11426
RS
167(make-variable-buffer-local 'view-overlay)
168
fd78d527
GM
169(unless (assq 'view-mode minor-mode-alist)
170 (setq minor-mode-alist
171 (cons (list 'view-mode
172 (propertize " View"
173 'local-map mode-line-minor-mode-keymap
174 'help-echo "mouse-3: minor mode menu"))
175 minor-mode-alist)))
0d63ba8c 176\f
ab7782fc 177;; Define keymap inside defvar to make it easier to load changes.
cae55197 178;; Some redundant "less"-like key bindings below have been commented out.
ab7782fc
RS
179(defvar view-mode-map
180 (let ((map (make-sparse-keymap)))
181 (define-key map "C" 'View-kill-and-leave)
182 (define-key map "c" 'View-leave)
183 (define-key map "Q" 'View-quit-all)
184 (define-key map "E" 'View-exit-and-edit)
185; (define-key map "v" 'View-exit)
186 (define-key map "e" 'View-exit)
187 (define-key map "q" 'View-quit)
188; (define-key map "N" 'View-search-last-regexp-backward)
189 (define-key map "p" 'View-search-last-regexp-backward)
190 (define-key map "n" 'View-search-last-regexp-forward)
191; (define-key map "?" 'View-search-regexp-backward) ; Less does this.
192 (define-key map "\\" 'View-search-regexp-backward)
193 (define-key map "/" 'View-search-regexp-forward)
194 (define-key map "r" 'isearch-backward)
195 (define-key map "s" 'isearch-forward)
196 (define-key map "m" 'point-to-register)
197 (define-key map "'" 'register-to-point)
198 (define-key map "x" 'exchange-point-and-mark)
d1ed8492 199 (define-key map "@" 'View-back-to-mark)
ab7782fc
RS
200 (define-key map "." 'set-mark-command)
201 (define-key map "%" 'View-goto-percent)
202; (define-key map "G" 'View-goto-line-last)
203 (define-key map "g" 'View-goto-line)
204 (define-key map "=" 'what-line)
205 (define-key map "F" 'View-revert-buffer-scroll-page-forward)
206; (define-key map "k" 'View-scroll-line-backward)
207 (define-key map "y" 'View-scroll-line-backward)
208; (define-key map "j" 'View-scroll-line-forward)
209 (define-key map "\n" 'View-scroll-line-forward)
210 (define-key map "\r" 'View-scroll-line-forward)
211 (define-key map "u" 'View-scroll-half-page-backward)
212 (define-key map "d" 'View-scroll-half-page-forward)
213 (define-key map "z" 'View-scroll-page-forward-set-page-size)
214 (define-key map "w" 'View-scroll-page-backward-set-page-size)
215; (define-key map "b" 'View-scroll-page-backward)
216 (define-key map "\C-?" 'View-scroll-page-backward)
217; (define-key map "f" 'View-scroll-page-forward)
218 (define-key map " " 'View-scroll-page-forward)
219 (define-key map "o" 'View-scroll-to-buffer-end)
220 (define-key map ">" 'end-of-buffer)
221 (define-key map "<" 'beginning-of-buffer)
222 (define-key map "-" 'negative-argument)
223 (define-key map "9" 'digit-argument)
224 (define-key map "8" 'digit-argument)
225 (define-key map "7" 'digit-argument)
226 (define-key map "6" 'digit-argument)
227 (define-key map "5" 'digit-argument)
228 (define-key map "4" 'digit-argument)
229 (define-key map "3" 'digit-argument)
230 (define-key map "2" 'digit-argument)
231 (define-key map "1" 'digit-argument)
232 (define-key map "0" 'digit-argument)
233 (define-key map "H" 'describe-mode)
d1ed8492 234 (define-key map "?" 'describe-mode) ; Maybe do as less instead? See above.
ab7782fc
RS
235 (define-key map "h" 'describe-mode)
236 map))
e6211d55 237
c88daaef
RS
238(or (assq 'view-mode minor-mode-map-alist)
239 (setq minor-mode-map-alist
240 (cons (cons 'view-mode view-mode-map) minor-mode-map-alist)))
0d63ba8c 241\f
ab7782fc 242;;; Commands that enter or exit view mode.
e6211d55 243
404967ca
EZ
244;; This is used when view mode is exited, to make sure we don't try to
245;; kill a buffer modified by the user. A buffer in view mode can
246;; become modified if the user types C-x C-q, edits the buffer, then
247;; types C-x C-q again to return to view mode.
5e4f40ee 248;;;###autoload
dd18f44f
EZ
249(defun kill-buffer-if-not-modified (buf)
250 "Like `kill-buffer', but does nothing if the buffer is modified."
ce173b30 251 (let ((buf (get-buffer buf)))
dd18f44f
EZ
252 (and buf (not (buffer-modified-p buf))
253 (kill-buffer buf))))
254
7229064d 255;;;###autoload
d1ed8492 256(defun view-file (file)
e6211d55 257 "View FILE in View mode, returning to previous buffer when done.
78ddc123
MR
258Emacs commands editing the buffer contents are not available; instead, a
259special set of commands (mostly letters and punctuation) are defined for
260moving around in the buffer.
e6211d55 261Space scrolls forward, Delete scrolls backward.
78ddc123 262For a list of all View commands, type H or h while viewing.
e6211d55 263
bd0d2c58 264This command runs the normal hook `view-mode-hook'."
e6211d55 265 (interactive "fView file: ")
981b7b0c 266 (unless (file-exists-p file) (error "%s does not exist" file))
90bb2ff4
RS
267 (let ((had-a-buf (get-file-buffer file))
268 (buffer (find-file-noselect file)))
269 (if (eq (with-current-buffer buffer
270 (get major-mode 'mode-class))
271 'special)
272 (progn
273 (switch-to-buffer buffer)
274 (message "Not using View mode because the major mode is special"))
dd18f44f 275 (view-buffer buffer (and (not had-a-buf) 'kill-buffer-if-not-modified)))))
e6211d55 276
b82fef5c 277;;;###autoload
d1ed8492 278(defun view-file-other-window (file)
ab7782fc 279 "View FILE in View mode in another window.
48d93beb
EZ
280When done, return that window to its previous buffer, and kill the
281buffer visiting FILE if unmodified and if it wasn't visited before.
282
ab7782fc 283Emacs commands editing the buffer contents are not available; instead,
b82fef5c
JB
284a special set of commands (mostly letters and punctuation)
285are defined for moving around in the buffer.
286Space scrolls forward, Delete scrolls backward.
78ddc123 287For a list of all View commands, type H or h while viewing.
b82fef5c 288
bd0d2c58 289This command runs the normal hook `view-mode-hook'."
ab7782fc 290 (interactive "fIn other window view file: ")
981b7b0c 291 (unless (file-exists-p file) (error "%s does not exist" file))
48d93beb
EZ
292 (let ((had-a-buf (get-file-buffer file))
293 (buf-to-view (find-file-noselect file)))
294 (view-buffer-other-window buf-to-view nil
295 (and (not had-a-buf)
dd18f44f 296 'kill-buffer-if-not-modified))))
b82fef5c 297
7229064d 298;;;###autoload
d1ed8492 299(defun view-file-other-frame (file)
ab7782fc 300 "View FILE in View mode in another frame.
48d93beb
EZ
301When done, kill the buffer visiting FILE if unmodified and if it wasn't
302visited before; also, maybe delete other frame and/or return to previous
303buffer.
304
ab7782fc 305Emacs commands editing the buffer contents are not available; instead,
e6211d55
RS
306a special set of commands (mostly letters and punctuation)
307are defined for moving around in the buffer.
308Space scrolls forward, Delete scrolls backward.
78ddc123 309For a list of all View commands, type H or h while viewing.
e6211d55 310
bd0d2c58 311This command runs the normal hook `view-mode-hook'."
ab7782fc 312 (interactive "fIn other frame view file: ")
981b7b0c 313 (unless (file-exists-p file) (error "%s does not exist" file))
48d93beb
EZ
314 (let ((had-a-buf (get-file-buffer file))
315 (buf-to-view (find-file-noselect file)))
316 (view-buffer-other-frame buf-to-view nil
317 (and (not had-a-buf)
dd18f44f 318 'kill-buffer-if-not-modified))))
ab7782fc
RS
319
320
321;;;###autoload
d1ed8492 322(defun view-buffer (buffer &optional exit-action)
ab7782fc 323 "View BUFFER in View mode, returning to previous buffer when done.
78ddc123
MR
324Emacs commands editing the buffer contents are not available; instead, a
325special set of commands (mostly letters and punctuation) are defined for
326moving around in the buffer.
ab7782fc 327Space scrolls forward, Delete scrolls backward.
78ddc123 328For a list of all View commands, type H or h while viewing.
ab7782fc
RS
329
330This command runs the normal hook `view-mode-hook'.
331
332Optional argument EXIT-ACTION is either nil or a function with buffer as
78ddc123 333argument. This function is called when finished viewing buffer. Use
5e613c02
MR
334this argument instead of explicitly setting `view-exit-action'.
335
336Do not set EXIT-ACTION to `kill-buffer' when BUFFER visits a
337file: Users may suspend viewing in order to modify the buffer.
338Exiting View mode will then discard the user's edits. Setting
339EXIT-ACTION to `kill-buffer-if-not-modified' avoids this."
e6211d55 340 (interactive "bView buffer: ")
ab7782fc 341 (let ((undo-window (list (window-buffer) (window-start) (window-point))))
d1ed8492 342 (switch-to-buffer buffer)
ab7782fc
RS
343 (view-mode-enter (cons (selected-window) (cons nil undo-window))
344 exit-action)))
e6211d55 345
b82fef5c 346;;;###autoload
d1ed8492 347(defun view-buffer-other-window (buffer &optional not-return exit-action)
bab0c3c1 348 "View BUFFER in View mode in another window.
78ddc123
MR
349Return to previous buffer when done, unless optional NOT-RETURN is
350non-nil. Emacs commands editing the buffer contents are not available;
351instead, a special set of commands (mostly letters and punctuation) are
352defined for moving around in the buffer.
ab7782fc 353Space scrolls forward, Delete scrolls backward.
78ddc123 354For a list of all View commands, type H or h while viewing.
ab7782fc
RS
355
356This command runs the normal hook `view-mode-hook'.
357
358Optional argument EXIT-ACTION is either nil or a function with buffer as
78ddc123
MR
359argument. This function is called when finished viewing buffer. Use
360this argument instead of explicitly setting `view-exit-action'."
ab7782fc
RS
361 (interactive "bIn other window view buffer:\nP")
362 (let* ((win ; This window will be selected by
363 (get-lru-window)) ; switch-to-buffer-other-window below.
364 (return-to
365 (and (not not-return)
366 (cons (selected-window)
367 (if (eq win (selected-window))
368 t ; Has to make new window.
d1ed8492 369 (list
ab7782fc
RS
370 (window-buffer win) ; Other windows old buffer.
371 (window-start win)
372 (window-point win)))))))
d1ed8492 373 (switch-to-buffer-other-window buffer)
ab7782fc
RS
374 (view-mode-enter (and return-to (cons (selected-window) return-to))
375 exit-action)))
5c05f569 376
ab7782fc 377;;;###autoload
d1ed8492 378(defun view-buffer-other-frame (buffer &optional not-return exit-action)
ab7782fc 379 "View BUFFER in View mode in another frame.
78ddc123
MR
380Return to previous buffer when done, unless optional NOT-RETURN is
381non-nil. Emacs commands editing the buffer contents are not available;
382instead, a special set of commands (mostly letters and punctuation) are
383defined for moving around in the buffer.
b82fef5c 384Space scrolls forward, Delete scrolls backward.
78ddc123 385For a list of all View commands, type H or h while viewing.
b82fef5c 386
ab7782fc
RS
387This command runs the normal hook `view-mode-hook'.
388
389Optional argument EXIT-ACTION is either nil or a function with buffer as
78ddc123
MR
390argument. This function is called when finished viewing buffer. Use
391this argument instead of explicitly setting `view-exit-action'."
ab7782fc
RS
392 (interactive "bView buffer in other frame: \nP")
393 (let ((return-to
394 (and (not not-return) (cons (selected-window) t)))) ; Old window.
d1ed8492 395 (switch-to-buffer-other-frame buffer)
ab7782fc
RS
396 (view-mode-enter (and return-to (cons (selected-window) return-to))
397 exit-action)))
0d63ba8c 398\f
7229064d 399;;;###autoload
c88daaef 400(defun view-mode (&optional arg)
ab7782fc 401 ;; In the following documentation string we have to use some explicit key
e51f616f 402 ;; bindings instead of using the \\[] construction. The reason for this
ab7782fc
RS
403 ;; is that most commands have more than one key binding.
404 "Toggle View mode, a minor mode for viewing text but not editing it.
4837b516
GM
405With prefix argument ARG, turn View mode on if ARG is positive, otherwise
406turn it off.
ab7782fc
RS
407
408Emacs commands that do not change the buffer contents are available as usual.
e51f616f 409Kill commands insert text in kill buffers but do not delete. Other commands
ab7782fc
RS
410\(among them most letters and punctuation) beep and tell that the buffer is
411read-only.
412\\<view-mode-map>
413The following additional commands are provided. Most commands take prefix
414arguments. Page commands default to \"page size\" lines which is almost a whole
415window 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
416and set \"half page size\" lines which initially is half a window full. Search
417commands default to a repeat count of one.
418
419H, h, ? This message.
420Digits provide prefix arguments.
421\\[negative-argument] negative prefix argument.
422\\[beginning-of-buffer] move to the beginning of buffer.
423> move to the end of buffer.
424\\[View-scroll-to-buffer-end] scroll so that buffer end is at last line of window.
d1ed8492
GM
425SPC scroll forward \"page size\" lines.
426 With prefix scroll forward prefix lines.
427DEL scroll backward \"page size\" lines.
428 With prefix scroll backward prefix lines.
429\\[View-scroll-page-forward-set-page-size] like \\[View-scroll-page-forward] but with prefix sets \"page size\" to prefix.
430\\[View-scroll-page-backward-set-page-size] like \\[View-scroll-page-backward] but with prefix sets \"page size\" to prefix.
431\\[View-scroll-half-page-forward] scroll forward \"half page size\" lines. With prefix, sets
432 \"half page size\" to prefix lines and scrolls forward that much.
433\\[View-scroll-half-page-backward] scroll backward \"half page size\" lines. With prefix, sets
434 \"half page size\" to prefix lines and scrolls backward that much.
435RET, LFD scroll forward one line. With prefix scroll forward prefix line(s).
436y scroll backward one line. With prefix scroll backward prefix line(s).
ab7782fc
RS
437\\[View-revert-buffer-scroll-page-forward] revert-buffer if necessary and scroll forward.
438 Use this to view a changing file.
439\\[what-line] prints the current line number.
440\\[View-goto-percent] goes prefix argument (default 100) percent into buffer.
441\\[View-goto-line] goes to line given by prefix argument (default first line).
442. set the mark.
443x exchanges point and mark.
444\\[View-back-to-mark] return to mark and pops mark ring.
445 Mark ring is pushed at start of every successful search and when
e51f616f 446 jump to line occurs. The mark is set on jump to buffer start or end.
ab7782fc
RS
447\\[point-to-register] save current position in character register.
448' go to position saved in character register.
449s do forward incremental search.
450r do reverse incremental search.
451\\[View-search-regexp-forward] searches forward for regular expression, starting after current page.
452 ! and @ have a special meaning at the beginning of the regexp.
e51f616f 453 ! means search for a line with no match for regexp. @ means start
ab7782fc
RS
454 search at beginning (end for backward search) of buffer.
455\\ searches backward for regular expression, starting before current page.
456\\[View-search-last-regexp-forward] searches forward for last regular expression.
457p searches backward for last regular expression.
4790accb 458\\[View-quit] quit View mode, restoring this window and buffer to previous state.
ab7782fc 459 \\[View-quit] is the normal way to leave view mode.
e51f616f 460\\[View-exit] exit View mode but stay in current buffer. Use this if you started
ab7782fc 461 viewing a buffer (file) and find out you want to edit it.
4790accb
RS
462 This command restores the previous read-only status of the buffer.
463\\[View-exit-and-edit] exit View mode, and make the current buffer editable
464 even if it was not editable before entry to View mode.
465\\[View-quit-all] quit View mode, restoring all windows to previous state.
ab7782fc
RS
466\\[View-leave] quit View mode and maybe switch buffers, but don't kill this buffer.
467\\[View-kill-and-leave] quit View mode, kill current buffer and go back to other buffer.
468
38acf670 469The effect of \\[View-leave], \\[View-quit] and \\[View-kill-and-leave] depends on how view-mode was entered. If it was
2f33468c
EZ
470entered by view-file, view-file-other-window, view-file-other-frame, or
471\\[dired-view-file] \(\\[view-file], \\[view-file-other-window],
472\\[view-file-other-frame], or the Dired mode v command),
473then \\[View-quit] will try to kill the current buffer.
474If view-mode was entered from another buffer, by \\[view-buffer],
475\\[view-buffer-other-window], \\[view-buffer-other frame], \\[view-file],
476\\[view-file-other-window], or \\[view-file-other-frame],
38acf670 477then \\[View-leave], \\[View-quit] and \\[View-kill-and-leave] will return to that buffer.
ab7782fc
RS
478
479Entry to view-mode runs the normal hook `view-mode-hook'."
bc15ba42 480 (interactive "P")
cae55197
KH
481 (unless (and arg ; Do nothing if already OK.
482 (if (> (prefix-numeric-value arg) 0) view-mode (not view-mode)))
483 (if view-mode (view-mode-disable)
484 (view-mode-enable))))
0d63ba8c 485\f
e51f616f
RS
486(defun view-mode-enable ()
487 "Turn on View mode."
8b7037d9
RS
488 ;; Always leave view mode before changing major mode.
489 ;; This is to guarantee that the buffer-read-only variable is restored.
8b7037d9 490 (add-hook 'change-major-mode-hook 'view-mode-disable nil t)
e51f616f 491 (setq view-mode t
5bf70f47
RS
492 view-page-size nil
493 view-half-page-size nil
e51f616f
RS
494 view-old-buffer-read-only buffer-read-only
495 buffer-read-only t
496 view-old-Helper-return-blurb (and (boundp 'Helper-return-blurb)
497 Helper-return-blurb)
498 Helper-return-blurb
499 (format "continue viewing %s"
500 (if (buffer-file-name)
501 (file-name-nondirectory (buffer-file-name))
502 (buffer-name))))
19b7f6c9 503 (force-mode-line-update)
e51f616f
RS
504 (run-hooks 'view-mode-hook))
505
506(defun view-mode-disable ()
507 "Turn off View mode."
8b7037d9 508 (remove-hook 'change-major-mode-hook 'view-mode-disable t)
e51f616f 509 (and view-overlay (delete-overlay view-overlay))
19b7f6c9 510 (force-mode-line-update)
b75c9917
RS
511 ;; Calling toggle-read-only while View mode is enabled
512 ;; sets view-read-only to t as a buffer-local variable
513 ;; after exiting View mode. That arranges that the next toggle-read-only
514 ;; will reenable View mode.
515 ;; Cancelling View mode in any other way should cancel that, too,
516 ;; so that View mode stays off if toggle-read-only is called.
517 (if (local-variable-p 'view-read-only)
518 (kill-local-variable 'view-read-only))
e51f616f 519 (setq view-mode nil
bf551cf7
KH
520 Helper-return-blurb view-old-Helper-return-blurb)
521 (if buffer-read-only
522 (setq buffer-read-only view-old-buffer-read-only)))
ab7782fc
RS
523
524;;;###autoload
78ddc123
MR
525(defun view-return-to-alist-update (buffer &optional item)
526 "Update `view-return-to-alist' of buffer BUFFER.
527Remove from `view-return-to-alist' all entries referencing dead
528windows. Optional argument ITEM non-nil means add ITEM to
529`view-return-to-alist' after purging. For a decsription of items
530that can be added see the RETURN-TO-ALIST argument of the
531function `view-mode-exit'. If `view-return-to-alist' contains an
532entry for the selected window, purge that entry from
533`view-return-to-alist' before adding ITEM."
534 (with-current-buffer buffer
535 (when view-return-to-alist
536 (let* ((list view-return-to-alist)
537 entry entry-window last)
538 (while list
539 (setq entry (car list))
540 (setq entry-window (car entry))
541 (if (and (windowp entry-window)
542 (or (and item (eq entry-window (selected-window)))
543 (not (window-live-p entry-window))))
544 ;; Remove that entry.
545 (if last
546 (setcdr last (cdr list))
547 (setq view-return-to-alist
548 (cdr view-return-to-alist)))
549 ;; Leave entry alone.
550 (setq last entry))
551 (setq list (cdr list)))))
552 ;; Add ITEM.
553 (when item
554 (setq view-return-to-alist
555 (cons item view-return-to-alist)))))
556
557;;;###autoload
558(defun view-mode-enter (&optional return-to exit-action)
559 "Enter View mode and set up exit from view mode depending on optional arguments.
560RETURN-TO non-nil means add RETURN-TO as an element to the buffer
561local alist `view-return-to-alist'. Save EXIT-ACTION in buffer
562local variable `view-exit-action'. It should be either nil or a
563function that takes a buffer as argument. This function will be
564called by `view-mode-exit'.
565
566RETURN-TO is either nil, meaning do nothing when exiting view
567mode, or must have the format (WINDOW OLD-WINDOW . OLD-BUF-INFO).
568WINDOW is the window used for viewing. OLD-WINDOW is nil or the
569window to select after viewing. OLD-BUF-INFO tells what to do
570with WINDOW when exiting. It is one of:
5711) nil Do nothing.
5722) t Delete WINDOW or, if it is the only window and
573 `view-remove-frame-by-deleting' is non-nil, its
574 frame.
e51f616f 5753) (OLD-BUFF START POINT) Display buffer OLD-BUFF with displayed text
78ddc123
MR
576 starting at START and point at POINT in WINDOW.
5774) quit-window Do `quit-window' in WINDOW.
5785) keep-frame Like case 2) but do not delete the frame.
ab7782fc 579
78ddc123 580For a list of all View commands, type H or h while viewing.
ab7782fc
RS
581
582This function runs the normal hook `view-mode-hook'."
78ddc123
MR
583 (when return-to
584 (let ((entry (assq (car return-to) view-return-to-alist)))
585 (if entry
586 (setcdr entry (cdr return-to))
587 (setq view-return-to-alist (cons return-to view-return-to-alist)))))
588 (when exit-action
589 (setq view-exit-action exit-action))
590
591 (unless view-mode
e51f616f 592 (view-mode-enable)
ab7782fc 593 (force-mode-line-update)
1c0484e2
RF
594 (unless view-inhibit-help-message
595 (message "%s"
596 (substitute-command-keys "\
597View mode: type \\[help-command] for help, \\[describe-mode] for commands, \\[View-quit] to quit.")))))
0d63ba8c 598\f
ab7782fc 599(defun view-mode-exit (&optional return-to-alist exit-action all-win)
7f9fcc0f 600 "Exit View mode in various ways, depending on optional arguments.
78ddc123
MR
601RETURN-TO-ALIST, EXIT-ACTION and ALL-WIN determine what to do
602after exit. EXIT-ACTION is nil or a function that is called with
603current buffer as argument.
604
605RETURN-TO-ALIST is an alist that, for some of the windows
606displaying the current buffer, maintains information on what to
607do when exiting those windows. If ALL-WIN is non-nil or the
608variable `view-exits-all-viewing-windows' is non-nil,
609view-mode-exit attempts to restore all windows showing the
610current buffer to their old state. Otherwise, only the selected
611window is affected (provided it is on RETURN-TO-ALIST).
612
613Elements of RETURN-TO-ALIST must have the format
614 (WINDOW OLD-WINDOW . OLD-BUF-INFO) where
615
616WINDOW is a window displaying the current buffer and OLD-WINDOW
617is either nil or a window to select after viewing. OLD-BUF-INFO
618provides information on what to do with WINDOW and may be one of:
6191) nil Do nothing.
6202) t Delete WINDOW and, if it is the only window and
621 `view-remove-frame-by-deleting' is non-nil, its
622 frame.
e51f616f 6233) (OLD-BUF START POINT) Display buffer OLD-BUF with displayed text
78ddc123
MR
624 starting at START and point at POINT in WINDOW.
6254) quit-window Do `quit-window' in WINDOW.
6265) keep-frame Like case 2) but do not delete the frame.
627
628If one of the WINDOW in RETURN-TO-ALIST is the selected window
629and the corresponding OLD-WINDOW is a live window, then select
630OLD-WINDOW."
631 (when view-mode ; Only do something if in view mode.
632 (setq all-win
633 (and return-to-alist
634 (or all-win view-exits-all-viewing-windows)))
635 (let* ((buffer (current-buffer))
636 window notlost
637 (sel-old (assq (selected-window) return-to-alist))
638 (alist (cond
639 (all-win ; Try to restore all windows.
640 (append return-to-alist nil)) ; Copy.
641 (sel-old ; Only selected window.
642 (list sel-old))))
643 (old-window (if sel-old (car (cdr sel-old)))))
644 (if all-win ; Follow chains of old-windows.
645 (let ((c (length alist)) a)
646 (while (and (> c 0) ; Safety if mutually refering windows.
647 (or (not (window-live-p old-window))
648 (eq buffer (window-buffer old-window)))
649 (setq a (assq old-window alist)))
650 (setq c (1- c))
651 (setq old-window (car (cdr a))))
652 (if (or (zerop c) (not (window-live-p old-window)))
653 (setq old-window (selected-window)))))
654 (unless view-no-disable-on-exit
655 (view-mode-disable))
656 (while alist ; Restore windows with info.
657 (setq notlost nil)
658 (when (and (window-live-p (setq window (car (car alist))))
ab7782fc 659 (eq buffer (window-buffer window)))
78ddc123
MR
660 (let ((frame (window-frame window))
661 (old-buf-info (cdr (cdr (car alist)))))
662 (if all-win (select-window window))
663 (cond
664 ((and (consp old-buf-info) ; Case 3.
665 (buffer-live-p (car old-buf-info)))
666 (set-window-buffer window (car old-buf-info)) ; old-buf
667 (set-window-start window (car (cdr old-buf-info)))
668 (set-window-point window (car (cdr (cdr old-buf-info)))))
669 ((eq old-buf-info 'quit-window)
670 (quit-window)) ; Case 4.
671 (old-buf-info ; Case 2 or 5.
672 (cond
673 ((not (one-window-p t)) ; Not only window.
674 (delete-window))
675 ((eq old-buf-info 'keep-frame) ; Case 5.
676 (bury-buffer))
677 ((not (eq frame (next-frame))) ; Case 2 and only window.
678 ;; Not the only frame, so can safely be removed.
679 (if view-remove-frame-by-deleting
680 (delete-frame frame)
681 (setq notlost t) ; Keep the window. See below.
682 (iconify-frame frame))))))))
683 ;; If a frame is removed by iconifying it, the window is not
684 ;; really lost. In this case we keep the entry in
685 ;; `view-return-to-alist' so that if the user deiconifies the
686 ;; frame and then hits q, the frame is iconified again.
687 (unless notlost
688 (with-current-buffer buffer
d1ed8492 689 (setq view-return-to-alist
78ddc123
MR
690 (delete (car alist) view-return-to-alist))))
691 (setq alist (cdr alist)))
692 (when (window-live-p old-window)
693 ;; old-window is still alive => select it.
694 (select-window old-window))
695 (when exit-action
696 ;; Don't do that: If the user wants to quit the *Help* buffer a
697 ;; second time it won't have any effect.
698;;; (setq view-exit-action nil)
699 (funcall exit-action buffer))
700 (force-mode-line-update))))
0d63ba8c 701\f
ab7782fc
RS
702(defun View-exit ()
703 "Exit View mode but stay in current buffer."
e6211d55 704 (interactive)
ab7782fc 705 (view-mode-exit))
e6211d55 706
0093dc5a 707;;;###autoload
ab7782fc
RS
708(defun View-exit-and-edit ()
709 "Exit View mode and make the current buffer editable."
710 (interactive)
72b5cb89
KH
711 (let ((view-old-buffer-read-only nil)
712 (view-no-disable-on-exit nil))
66d3a2b5 713 (view-mode-exit)))
ab7782fc
RS
714
715(defun View-leave ()
716 "Quit View mode and maybe switch buffers, but don't kill this buffer."
717 (interactive)
718 (view-mode-exit view-return-to-alist))
719
720(defun View-quit ()
721 "Quit View mode, trying to restore window and buffer to previous state.
e51f616f 722Maybe kill this buffer. Try to restore selected window to previous state
ab7782fc
RS
723and go to previous buffer or window."
724 (interactive)
725 (view-mode-exit view-return-to-alist view-exit-action))
726
727(defun View-quit-all ()
e51f616f
RS
728 "Quit View mode, trying to restore windows and buffers to previous state.
729Maybe kill current buffer. Try to restore all windows viewing buffer to
ab7782fc
RS
730previous state and go to previous buffer or window."
731 (interactive)
732 (view-mode-exit view-return-to-alist view-exit-action t))
733
734(defun View-kill-and-leave ()
735 "Quit View mode, kill current buffer and return to previous buffer."
736 (interactive)
737 (view-mode-exit view-return-to-alist (or view-exit-action 'kill-buffer) t))
0d63ba8c 738\f
ab7782fc
RS
739
740;;; Some help routines.
741
742(defun view-window-size ()
743 ;; Window height excluding mode line.
744 (1- (window-height)))
bd0d2c58 745
e6211d55
RS
746;(defun view-last-command (&optional who what)
747; (setq view-last-command-entry this-command)
748; (setq view-last-command who)
749; (setq view-last-command-argument what))
750
751;(defun View-repeat-last-command ()
752; "Repeat last command issued in View mode."
753; (interactive)
754; (if (and view-last-command
755; (eq view-last-command-entry last-command))
756; (funcall view-last-command view-last-command-argument))
757; (setq this-command view-last-command-entry))
758
ab7782fc
RS
759(defun view-recenter ()
760 ;; Center point in window.
761 (recenter (/ (view-window-size) 2)))
762
763(defun view-page-size-default (lines)
764 ;; Get page size.
765 (let ((default (- (view-window-size) next-screen-context-lines)))
766 (if (or (null lines) (zerop (setq lines (prefix-numeric-value lines))))
767 default
768 (min (abs lines) default))))
769
770(defun view-set-half-page-size-default (lines)
771 ;; Get and maybe set half page size.
5bf70f47
RS
772 (if (not lines) (or view-half-page-size
773 (/ (view-window-size) 2))
ab7782fc
RS
774 (setq view-half-page-size
775 (if (zerop (setq lines (prefix-numeric-value lines)))
776 (/ (view-window-size) 2)
777 (view-page-size-default lines)))))
778
779
780;;; Commands for moving around in the buffer.
781
782(defun View-goto-percent (&optional percent)
783 "Move to end (or prefix PERCENT) of buffer in View mode.
784Display is centered at point.
e51f616f 785Also set the mark at the position where point was."
ab7782fc
RS
786 (interactive "P")
787 (push-mark)
788 (goto-char
789 (if percent
790 (+ (point-min)
791 (floor (* (- (point-max) (point-min)) 0.01
792 (max 0 (min 100 (prefix-numeric-value percent))))))
793 (point-max)))
794 (view-recenter))
795
796;(defun View-goto-line-last (&optional line)
797;"Move to last (or prefix LINE) line in View mode.
798;Display is centered at LINE.
799;Sets mark at starting position and pushes mark ring."
800; (interactive "P")
801; (push-mark)
802; (if line (goto-line (prefix-numeric-value line))
803; (goto-char (point-max))
804; (beginning-of-line))
805; (view-recenter))
f1180544 806
ab7782fc
RS
807(defun View-goto-line (&optional line)
808 "Move to first (or prefix LINE) line in View mode.
809Display is centered at LINE.
e51f616f 810Also set the mark at the position where point was."
e6211d55
RS
811 (interactive "p")
812 (push-mark)
bab0c3c1 813 (goto-line line)
ab7782fc 814 (view-recenter))
e6211d55 815
0d63ba8c
RS
816(defun View-back-to-mark (&optional ignore)
817 "Return to last mark set in View mode, else beginning of file.
818Display that line at the center of the window.
819This command pops the mark ring, so that successive
820invocations return to earlier marks."
ab7782fc 821 (interactive)
0d63ba8c
RS
822 (goto-char (or (mark t) (point-min)))
823 (pop-mark)
824 (view-recenter))
825\f
ab7782fc
RS
826(defun view-scroll-lines (lines backward default maxdefault)
827 ;; This function does the job for all the scrolling commands.
e51f616f
RS
828 ;; Scroll forward LINES lines. If BACKWARD is true scroll backwards.
829 ;; If LINES is negative scroll in the other direction. If LINES is 0 or nil,
830 ;; scroll DEFAULT lines. If MAXDEFAULT is true then scroll no more than a
ab7782fc
RS
831 ;; window full.
832 (if (or (null lines) (zerop (setq lines (prefix-numeric-value lines))))
833 (setq lines default))
cae55197
KH
834 (when (< lines 0)
835 (setq backward (not backward)) (setq lines (- lines)))
ab7782fc
RS
836 (setq default (view-page-size-default nil)) ; Max scrolled at a time.
837 (if maxdefault (setq lines (min lines default)))
838 (cond
839 (backward (scroll-down lines))
840 ((view-really-at-end)
841 (if view-scroll-auto-exit (View-quit)
842 (ding)
843 (view-end-message)))
844 (t (while (> lines default)
845 (scroll-up default)
846 (setq lines (- lines default))
847 (if (view-really-at-end) (setq lines 0)))
848 (scroll-up lines)
849 (if (view-really-at-end) (view-end-message))
850 (move-to-window-line -1)
851 (beginning-of-line))))
852
853(defun view-really-at-end ()
e51f616f 854 ;; Return true if buffer end visible. Maybe revert buffer and test.
ab7782fc
RS
855 (and (pos-visible-in-window-p (point-max))
856 (let ((buf (current-buffer))
857 (bufname (buffer-name))
858 (file (buffer-file-name)))
69576401
AS
859 (or (not view-try-extend-at-buffer-end)
860 (null file)
861 (verify-visited-file-modtime buf)
862 (not (file-exists-p file))
863 (when (buffer-modified-p buf)
864 (setq file (file-name-nondirectory file))
865 (not (yes-or-no-p
866 (format
867 "File %s changed on disk. Discard your edits%s? "
868 file
869 (if (string= bufname file) ""
870 (concat " in " bufname))))))
871 (progn
872 (revert-buffer t t t)
873 (pos-visible-in-window-p (point-max)))))))
ab7782fc
RS
874
875(defun view-end-message ()
876 ;; Tell that we are at end of buffer.
877 (goto-char (point-max))
19d73313
RS
878 (if view-return-to-alist
879 (message "End of buffer. Type %s to quit viewing."
880 (substitute-command-keys
881 (if view-scroll-auto-exit "\\[View-scroll-page-forward]"
882 "\\[View-quit]")))
883 (message "End of buffer")))
0d63ba8c
RS
884\f
885(defun View-scroll-to-buffer-end ()
886 "Scroll backward or forward so that buffer end is at last line of window."
887 (interactive)
888 (let ((p (if (pos-visible-in-window-p (point-max)) (point))))
889 (goto-char (point-max))
890 (recenter -1)
891 (and p (goto-char p))))
ab7782fc
RS
892
893(defun View-scroll-page-forward (&optional lines)
894 "Scroll \"page size\" or prefix LINES lines forward in View mode.
e51f616f 895Exit if end of text is visible and `view-scroll-auto-exit' is non-nil.
ab7782fc
RS
896\"page size\" is whole window full, or number of lines set by
897\\[View-scroll-page-forward-set-page-size] or
898\\[View-scroll-page-backward-set-page-size].
899If LINES is more than a window-full, only the last window-full is shown."
e6211d55 900 (interactive "P")
5bf70f47 901 (view-scroll-lines lines nil (view-page-size-default view-page-size) nil))
ab7782fc 902
d1ed8492 903(defun View-scroll-page-backward (&optional lines)
ab7782fc 904 "Scroll \"page size\" or prefix LINES lines backward in View mode.
e51f616f 905See also `View-scroll-page-forward'."
e6211d55 906 (interactive "P")
5bf70f47 907 (view-scroll-lines lines t (view-page-size-default view-page-size) nil))
f1180544 908
ab7782fc 909(defun View-scroll-page-forward-set-page-size (&optional lines)
e51f616f 910 "Scroll forward LINES lines in View mode, setting the \"page size\".
ab7782fc 911This is the number of lines which \\[View-scroll-page-forward] and
66d3a2b5
RS
912\\[View-scroll-page-backward] scroll by default.
913If LINES is omitted or = 0, sets \"page size\" to window height and
914scrolls forward that much, otherwise scrolls forward LINES lines and sets
915\"page size\" to the minimum of window height and the absolute value of LINES.
e51f616f 916See also `View-scroll-page-forward'."
e6211d55 917 (interactive "P")
ab7782fc
RS
918 (view-scroll-lines lines nil
919 (setq view-page-size (view-page-size-default lines))
920 nil))
e6211d55 921
ab7782fc
RS
922(defun View-scroll-page-backward-set-page-size (&optional lines)
923 "Scroll backward prefix LINES lines in View mode, setting the \"page size\".
e51f616f 924See also `View-scroll-page-forward-set-page-size'."
e6211d55 925 (interactive "P")
ab7782fc
RS
926 (view-scroll-lines lines t
927 (setq view-page-size (view-page-size-default lines))
928 nil))
929
930(defun View-scroll-line-forward (&optional lines)
931 "Scroll forward one line (or prefix LINES lines) in View mode.
e51f616f 932See also `View-scroll-page-forward,' but note that scrolling is limited
ab7782fc
RS
933to minimum of LINES and one window-full."
934 (interactive "P")
935 (view-scroll-lines lines nil 1 t))
936
937(defun View-scroll-line-backward (&optional lines)
938 "Scroll backward one line (or prefix LINES lines) in View mode.
e51f616f 939See also `View-scroll-line-forward'."
ab7782fc
RS
940 (interactive "P")
941 (view-scroll-lines lines t 1 t))
942
943(defun View-scroll-half-page-forward (&optional lines)
e51f616f 944 "Scroll forward a \"half page\" (or prefix LINES) lines in View mode.
ab7782fc
RS
945If LINES is not omitted, the \"half page size\" is set to the minimum of
946window height and the absolute value of LINES.
947LINES=0 resets \"half page size\" to half window height."
948 (interactive "P")
949 (view-scroll-lines lines nil (view-set-half-page-size-default lines) t))
950
951(defun View-scroll-half-page-backward (&optional lines)
e51f616f
RS
952 "Scroll backward a \"half page\" (or prefix LINES) lines in View mode.
953See also `View-scroll-half-page-forward'."
ab7782fc
RS
954 (interactive "P")
955 (view-scroll-lines lines t (view-set-half-page-size-default lines) t))
956
e51f616f
RS
957(defun View-revert-buffer-scroll-page-forward (&optional lines)
958 "Scroll forward, reverting buffer if needed, in View mode.
ab7782fc
RS
959If buffer has not been changed and the corresponding file is newer, first
960revert the buffer, then scroll.
961This command is useful if you are viewing a changing file.
e51f616f
RS
962
963The prefix argument LINES says how many lines to scroll.
964If you don't specify a prefix argument, it uses the number of lines set by
ab7782fc
RS
965\\[View-scroll-page-forward-set-page-size] or
966\\[View-scroll-page-backward-set-page-size].
967If LINES is more than a window-full, only the last window-full is shown."
968 (interactive "P")
5d9b78b7 969 (let ((view-scroll-auto-exit nil)
ab7782fc 970 (view-try-extend-at-buffer-end t))
a312f214 971 (view-scroll-lines lines nil (view-page-size-default view-page-size) nil)))
0d63ba8c 972\f
5c05f569 973(defun View-search-regexp-forward (n regexp)
ab7782fc 974 "Search forward for first (or prefix Nth) occurrence of REGEXP in View mode.
66d3a2b5
RS
975
976Displays line found at center of window. Sets mark at starting position and
977pushes mark ring.
978
979Characters @ and ! are special at the beginning of REGEXP. They modify
980the search rather than become part of the pattern searched for.
981@ means search all the buffer i.e. start search at the beginning of buffer.
982! means search for a line that contains no match for the pattern.
983If REGEXP is empty or only consist of these control characters, then
984an earlier remembered REGEXP is used, otherwise REGEXP is remembered
985for use by later search commands.
5534818b
RS
986
987The variable `view-highlight-face' controls the face that is used
988for highlighting the match that is found."
d1ed8492 989 (interactive "p\nsSearch forward (regexp): ")
ab7782fc 990 (view-search n regexp))
e6211d55 991
5c05f569 992(defun View-search-regexp-backward (n regexp)
ab7782fc 993 "Search backward for first (or prefix Nth) occurrence of REGEXP in View mode.
66d3a2b5
RS
994
995Displays line found at center of window. Sets mark at starting position and
996pushes mark ring.
997
998Characters @ and ! are special at the beginning of REGEXP. They modify
999the search rather than become part of the pattern searched for.
1000@ means search all the buffer i.e. start search at the end of buffer.
1001! means search for a line that contains no match for the pattern.
1002If REGEXP is empty or only consist of these control characters, then
1003an earlier remembered REGEXP is used, otherwise REGEXP is remembered
1004for use by later search commands.
5534818b
RS
1005
1006The variable `view-highlight-face' controls the face that is used
1007for highlighting the match that is found."
e6211d55 1008 (interactive "p\nsSearch backward (regexp): ")
ab7782fc 1009 (view-search (- n) regexp))
e6211d55 1010
ab7782fc
RS
1011(defun View-search-last-regexp-forward (n) "\
1012Search forward for first (or prefix Nth) instance of last regexp in View mode.
1013Displays line found at center of window. Sets mark at starting position and
1014pushes mark ring.
5534818b
RS
1015
1016The variable `view-highlight-face' controls the face that is used
1017for highlighting the match that is found."
e6211d55 1018 (interactive "p")
ab7782fc 1019 (view-search n nil))
e6211d55 1020
ab7782fc
RS
1021(defun View-search-last-regexp-backward (n) "\
1022Search backward for first (or prefix Nth) instance of last regexp in View mode.
e6211d55 1023Displays line found at center of window. Sets mark at starting position and
5534818b
RS
1024pushes mark ring.
1025
1026The variable `view-highlight-face' controls the face that is used
1027for highlighting the match that is found."
e6211d55 1028 (interactive "p")
ab7782fc 1029 (view-search (- n) nil))
e6211d55 1030
e6211d55 1031(defun view-search (times regexp)
66d3a2b5 1032 ;; This function does the job for all the View-search- commands.
cae55197
KH
1033 ;; Search for the TIMESt match for REGEXP. If TIMES is negative
1034 ;; search backwards. If REGEXP is nil use `view-last-regexp'.
1035 ;; Charcters "!" and "@" have a special meaning at the beginning of
1036 ;; REGEXP and are removed from REGEXP before the search "!" means
1037 ;; search for lines with no match for REGEXP. "@" means search in
1038 ;; the whole buffer, don't start searching from the present point.
ab7782fc
RS
1039 (let (where no end ln)
1040 (cond
1041 ((and regexp (> (length regexp) 0)
1042 (or (not (memq (string-to-char regexp) '(?! ?@)))
1043 (progn
1044 (if (member (substring regexp 0 2) '("!@" "@!"))
1045 (setq end t no t ln 2)
1046 (setq no (not (setq end (eq ?@ (string-to-char regexp))))
1047 ln 1))
1048 (> (length (setq regexp (substring regexp ln))) 0))))
1049 (setq view-last-regexp (if no (list regexp) regexp)))
1050 ((consp view-last-regexp)
1051 (setq regexp (car view-last-regexp))
cae55197 1052 (unless (setq no (not no)) (setq view-last-regexp regexp)))
ab7782fc
RS
1053 (view-last-regexp (setq regexp view-last-regexp)
1054 (if no (setq view-last-regexp (list regexp))))
1055 (t (error "No previous View-mode search")))
e6211d55 1056 (save-excursion
ab7782fc
RS
1057 (if end (goto-char (if (< times 0) (point-max) (point-min)))
1058 (move-to-window-line (if (< times 0) 0 -1)))
1059 (if (if no (view-search-no-match-lines times regexp)
1060 (re-search-forward regexp nil t times))
e6211d55
RS
1061 (setq where (point))))
1062 (if where
1063 (progn
1064 (push-mark)
1065 (goto-char where)
4fe11426
RS
1066 (if view-overlay
1067 (move-overlay view-overlay (match-beginning 0) (match-end 0))
1068 (setq view-overlay
1069 (make-overlay (match-beginning 0) (match-end 0))))
82380f84 1070 (overlay-put view-overlay 'face view-highlight-face)
e6211d55 1071 (beginning-of-line)
ab7782fc
RS
1072 (view-recenter))
1073 (message "Can't find occurrence %d of %s%s"
1074 times (if no "no " "") regexp)
e6211d55
RS
1075 (sit-for 4))))
1076
5aca5ac3
GM
1077;; This is the dumb approach, looking at each line. The original
1078;; version of this function looked like it might have been trying to
1079;; do something clever, but not succeeding:
1080;; http://lists.gnu.org/archive/html/bug-gnu-emacs/2007-09/msg00073.html
ab7782fc 1081(defun view-search-no-match-lines (times regexp)
5aca5ac3
GM
1082 "Search for the TIMESth occurrence of a line with no match for REGEXP.
1083If such a line is found, return non-nil and set the match-data to that line.
1084If TIMES is negative, search backwards."
138c66b0
GM
1085 (let ((step (if (>= times 0) 1
1086 (setq times (- times))
1087 -1)))
5aca5ac3
GM
1088 ;; Note that we do not check the current line.
1089 (while (and (> times 0)
1090 (zerop (forward-line step)))
138c66b0
GM
1091 ;; (forward-line 1) returns 0 on moving within the last line.
1092 (if (eobp)
1093 (setq times -1)
1094 (or (re-search-forward regexp (line-end-position) t)
1095 (setq times (1- times))))))
1096 (and (zerop times)
1097 (looking-at ".*")))
ab7782fc 1098
49116ac0
JB
1099(provide 'view)
1100
cbee283d 1101;; arch-tag: 6d0ace36-1d12-4de3-8de3-1fa3231636d7
d501f516 1102;;; view.el ends here