;;; view.el --- peruse file or buffer without editing
-;; Copyright (C) 1985, 1989, 1994, 1995, 1997, 2000, 2001
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1989, 1994, 1995, 1997, 2000, 2001, 2002,
+;; 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
;; Author: K. Shane Hartman
;; Maintainer: Inge Frick <inge@nada.kth.se>
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
;;
;; You could also bind view-file, view-buffer, view-buffer-other-window and
;; view-buffer-other-frame to keys.
-
+\f
;;; Code:
(defgroup view nil
:group 'wp
:group 'editing)
-(defcustom view-read-only nil
- "*Non-nil means buffers visiting files read-only, do it in view mode."
- :type 'boolean
- :group 'view)
-
(defcustom view-highlight-face 'highlight
"*The face used for highlighting the match found by View mode search."
:type 'face
;; is now controlled by the presence of a value in `view-return-to-alist'.
(defcustom view-scroll-auto-exit nil
"*Non-nil means scrolling past the end of buffer exits View mode.
-nil means attempting to scroll past the end of the buffer,
+A value of nil means attempting to scroll past the end of the buffer,
only rings the bell and gives a message on how to leave."
:type 'boolean
:group 'view)
(defcustom view-try-extend-at-buffer-end nil
- "*Non-nil means try load more of file when reaching end of buffer.
+ "*Non-nil means try to load more of file when reaching end of buffer.
This variable is mainly intended to be temporarily set to non-nil by
the F command in view-mode, but you can set it to t if you want the action
for all scroll commands in view mode."
:type 'boolean
:group 'view)
-(defcustom view-remove-frame-by-deleting nil
+;;;###autoload
+(defcustom view-remove-frame-by-deleting t
"*Determine how View mode removes a frame no longer needed.
If nil, make an icon of the frame. If non-nil, delete the frame."
:type 'boolean
- :group 'view)
+ :group 'view
+ ;; Changed the default of this to t for Emacs 23. Users consider
+ ;; frame iconification annoying.
+ :version "23.1")
(defcustom view-exits-all-viewing-windows nil
"*Non-nil means restore all windows used to view buffer.
:type 'boolean
:group 'view)
+(defcustom view-inhibit-help-message nil
+ "*Non-nil inhibits the help message shown upon entering View mode."
+ :type 'boolean
+ :group 'view
+ :version "22.1")
+
;;;###autoload
(defvar view-mode nil
"Non-nil if View mode is enabled.
"Normal hook run when starting to view a buffer or file."
:type 'hook
:group 'view)
-
+\f
(defvar view-old-buffer-read-only nil)
(make-variable-buffer-local 'view-old-buffer-read-only)
(defvar view-old-Helper-return-blurb)
(make-variable-buffer-local 'view-old-Helper-return-blurb)
+;; Just to avoid warnings.
+(defvar Helper-return-blurb)
+
(defvar view-page-size nil
"Default number of lines to scroll by View page commands.
-If nil then the local value of this is initially set to window size.")
+If nil that means use the window size.")
(make-variable-buffer-local 'view-page-size)
(defvar view-half-page-size nil
"Default number of lines to scroll by View half page commands.
-If nil then the local value of this is initially set to half window size.")
+If nil that means use half the window size.")
(make-variable-buffer-local 'view-half-page-size)
(defvar view-last-regexp nil)
See RETURN-TO-ALIST argument of function `view-mode-exit' for the format of
`view-return-to-alist'.")
(make-variable-buffer-local 'view-return-to-alist)
+(put 'view-return-to-alist 'permanent-local t)
(defvar view-exit-action nil
- "nil or a function with one argument (a buffer) called when finished viewing.
-This is local in each buffer being viewed.
-The \\[view-file] and \\[view-file-other-window] commands may set this to
-`kill-buffer'.")
+ "If non-nil, a function with one argument (a buffer) called when finished viewing.
+Commands like \\[view-file] and \\[view-file-other-window] may
+set this to bury or kill the viewed buffer.
+Observe that the buffer viewed might not appear in any window at
+the time this function is called.")
(make-variable-buffer-local 'view-exit-action)
(defvar view-no-disable-on-exit nil
'local-map mode-line-minor-mode-keymap
'help-echo "mouse-3: minor mode menu"))
minor-mode-alist)))
-
+\f
;; Define keymap inside defvar to make it easier to load changes.
;; Some redundant "less"-like key bindings below have been commented out.
(defvar view-mode-map
(or (assq 'view-mode minor-mode-map-alist)
(setq minor-mode-map-alist
(cons (cons 'view-mode view-mode-map) minor-mode-map-alist)))
-
+\f
;;; Commands that enter or exit view mode.
;;;###autoload
(defun view-file (file)
"View FILE in View mode, returning to previous buffer when done.
-Emacs commands editing the buffer contents are not available; instead,
-a special set of commands (mostly letters and punctuation)
-are defined for moving around in the buffer.
+Emacs commands editing the buffer contents are not available; instead, a
+special set of commands (mostly letters and punctuation) are defined for
+moving around in the buffer.
Space scrolls forward, Delete scrolls backward.
-For list of all View commands, type H or h while viewing.
+For a list of all View commands, type H or h while viewing.
This command runs the normal hook `view-mode-hook'."
(interactive "fView file: ")
- (let ((had-a-buf (get-file-buffer file)))
- (view-buffer (find-file-noselect file)
- (and (not had-a-buf) 'kill-buffer))))
+ (unless (file-exists-p file) (error "%s does not exist" file))
+ (let ((had-a-buf (get-file-buffer file))
+ (buffer (find-file-noselect file)))
+ (if (eq (with-current-buffer buffer
+ (get major-mode 'mode-class))
+ 'special)
+ (progn
+ (switch-to-buffer buffer)
+ (message "Not using View mode because the major mode is special"))
+ (view-buffer buffer (and (not had-a-buf) 'kill-buffer)))))
;;;###autoload
(defun view-file-other-window (file)
"View FILE in View mode in another window.
-Return that window to its previous buffer when done.
-Emacs commands editing the buffer contents are not available; instead,
-a special set of commands (mostly letters and punctuation)
-are defined for moving around in the buffer.
+Return that window to its previous buffer when done. Emacs commands
+editing the buffer contents are not available; instead, a special set of
+commands (mostly letters and punctuation) are defined for moving around
+in the buffer.
Space scrolls forward, Delete scrolls backward.
-For list of all View commands, type H or h while viewing.
+For a list of all View commands, type H or h while viewing.
This command runs the normal hook `view-mode-hook'."
(interactive "fIn other window view file: ")
+ (unless (file-exists-p file) (error "%s does not exist" file))
(let ((had-a-buf (get-file-buffer file)))
(view-buffer-other-window (find-file-noselect file) nil
(and (not had-a-buf) 'kill-buffer))))
(defun view-file-other-frame (file)
"View FILE in View mode in another frame.
Maybe delete other frame and/or return to previous buffer when done.
-Emacs commands editing the buffer contents are not available; instead,
-a special set of commands (mostly letters and punctuation)
-are defined for moving around in the buffer.
+Emacs commands editing the buffer contents are not available; instead, a
+special set of commands (mostly letters and punctuation) are defined for
+moving around in the buffer.
Space scrolls forward, Delete scrolls backward.
-For list of all View commands, type H or h while viewing.
+For a list of all View commands, type H or h while viewing.
This command runs the normal hook `view-mode-hook'."
(interactive "fIn other frame view file: ")
+ (unless (file-exists-p file) (error "%s does not exist" file))
(let ((had-a-buf (get-file-buffer file)))
(view-buffer-other-frame (find-file-noselect file) nil
(and (not had-a-buf) 'kill-buffer))))
;;;###autoload
(defun view-buffer (buffer &optional exit-action)
"View BUFFER in View mode, returning to previous buffer when done.
-Emacs commands editing the buffer contents are not available; instead,
-a special set of commands (mostly letters and punctuation)
-are defined for moving around in the buffer.
+Emacs commands editing the buffer contents are not available; instead, a
+special set of commands (mostly letters and punctuation) are defined for
+moving around in the buffer.
Space scrolls forward, Delete scrolls backward.
-For list of all View commands, type H or h while viewing.
+For a list of all View commands, type H or h while viewing.
This command runs the normal hook `view-mode-hook'.
Optional argument EXIT-ACTION is either nil or a function with buffer as
-argument. This function is called when finished viewing buffer.
-Use this argument instead of explicitly setting `view-exit-action'."
-
+argument. This function is called when finished viewing buffer. Use
+this argument instead of explicitly setting `view-exit-action'."
(interactive "bView buffer: ")
(let ((undo-window (list (window-buffer) (window-start) (window-point))))
(switch-to-buffer buffer)
;;;###autoload
(defun view-buffer-other-window (buffer &optional not-return exit-action)
"View BUFFER in View mode in another window.
-Return to previous buffer when done, unless optional NOT-RETURN is non-nil.
-Emacs commands editing the buffer contents are not available; instead,
-a special set of commands (mostly letters and punctuation)
-are defined for moving around in the buffer.
+Return to previous buffer when done, unless optional NOT-RETURN is
+non-nil. Emacs commands editing the buffer contents are not available;
+instead, a special set of commands (mostly letters and punctuation) are
+defined for moving around in the buffer.
Space scrolls forward, Delete scrolls backward.
-For list of all View commands, type H or h while viewing.
+For a list of all View commands, type H or h while viewing.
This command runs the normal hook `view-mode-hook'.
Optional argument EXIT-ACTION is either nil or a function with buffer as
-argument. This function is called when finished viewing buffer.
-Use this argument instead of explicitly setting `view-exit-action'."
+argument. This function is called when finished viewing buffer. Use
+this argument instead of explicitly setting `view-exit-action'."
(interactive "bIn other window view buffer:\nP")
(let* ((win ; This window will be selected by
(get-lru-window)) ; switch-to-buffer-other-window below.
;;;###autoload
(defun view-buffer-other-frame (buffer &optional not-return exit-action)
"View BUFFER in View mode in another frame.
-Return to previous buffer when done, unless optional NOT-RETURN is non-nil.
-Emacs commands editing the buffer contents are not available; instead,
-a special set of commands (mostly letters and punctuation)
-are defined for moving around in the buffer.
+Return to previous buffer when done, unless optional NOT-RETURN is
+non-nil. Emacs commands editing the buffer contents are not available;
+instead, a special set of commands (mostly letters and punctuation) are
+defined for moving around in the buffer.
Space scrolls forward, Delete scrolls backward.
-For list of all View commands, type H or h while viewing.
+For a list of all View commands, type H or h while viewing.
This command runs the normal hook `view-mode-hook'.
Optional argument EXIT-ACTION is either nil or a function with buffer as
-argument. This function is called when finished viewing buffer.
-Use this argument instead of explicitly setting `view-exit-action'."
+argument. This function is called when finished viewing buffer. Use
+this argument instead of explicitly setting `view-exit-action'."
(interactive "bView buffer in other frame: \nP")
(let ((return-to
(and (not not-return) (cons (selected-window) t)))) ; Old window.
(switch-to-buffer-other-frame buffer)
(view-mode-enter (and return-to (cons (selected-window) return-to))
exit-action)))
-
+\f
;;;###autoload
(defun view-mode (&optional arg)
;; In the following documentation string we have to use some explicit key
;; bindings instead of using the \\[] construction. The reason for this
;; is that most commands have more than one key binding.
"Toggle View mode, a minor mode for viewing text but not editing it.
-With ARG, turn View mode on iff ARG is positive.
+With prefix argument ARG, turn View mode on if ARG is positive, otherwise
+turn it off.
Emacs commands that do not change the buffer contents are available as usual.
Kill commands insert text in kill buffers but do not delete. Other commands
\\[View-leave] quit View mode and maybe switch buffers, but don't kill this buffer.
\\[View-kill-and-leave] quit View mode, kill current buffer and go back to other buffer.
-The effect of \\[View-leave] , \\[View-quit] and \\[View-kill-and-leave] depends on how view-mode was entered. If it was
-entered by view-file, view-file-other-window or view-file-other-frame
-\(\\[view-file], \\[view-file-other-window], \\[view-file-other-frame] or the dired mode v command), then \\[View-quit] will
-try to kill the current buffer. If view-mode was entered from another buffer
-as is done by View-buffer, View-buffer-other-window, View-buffer-other frame,
-View-file, View-file-other-window or View-file-other-frame then \\[View-leave] , \\[View-quit] and \\[View-kill-and-leave]
-will return to that buffer.
+The effect of \\[View-leave], \\[View-quit] and \\[View-kill-and-leave] depends on how view-mode was entered. If it was
+entered by view-file, view-file-other-window, view-file-other-frame, or
+\\[dired-view-file] \(\\[view-file], \\[view-file-other-window],
+\\[view-file-other-frame], or the Dired mode v command),
+then \\[View-quit] will try to kill the current buffer.
+If view-mode was entered from another buffer, by \\[view-buffer],
+\\[view-buffer-other-window], \\[view-buffer-other frame], \\[view-file],
+\\[view-file-other-window], or \\[view-file-other-frame],
+then \\[View-leave], \\[View-quit] and \\[View-kill-and-leave] will return to that buffer.
Entry to view-mode runs the normal hook `view-mode-hook'."
(interactive "P")
(if (> (prefix-numeric-value arg) 0) view-mode (not view-mode)))
(if view-mode (view-mode-disable)
(view-mode-enable))))
-
+\f
(defun view-mode-enable ()
"Turn on View mode."
;; Always leave view mode before changing major mode.
;; This is to guarantee that the buffer-read-only variable is restored.
(add-hook 'change-major-mode-hook 'view-mode-disable nil t)
(setq view-mode t
- view-page-size (view-page-size-default view-page-size)
- view-half-page-size (or view-half-page-size (/ (view-window-size) 2))
+ view-page-size nil
+ view-half-page-size nil
view-old-buffer-read-only buffer-read-only
buffer-read-only t
view-old-Helper-return-blurb (and (boundp 'Helper-return-blurb)
(setq buffer-read-only view-old-buffer-read-only)))
;;;###autoload
-(defun view-mode-enter (&optional return-to exit-action) "\
-Enter View mode and set up exit from view mode depending on optional arguments.
-If RETURN-TO is non-nil it is added as an element to the buffer local alist
-`view-return-to-alist'.
-Save EXIT-ACTION in buffer local variable `view-exit-action'.
-It should be either nil or a function that takes a buffer as argument.
-This function will be called by `view-mode-exit'.
-
-RETURN-TO is either nil, meaning do nothing when exiting view mode, or
-it has the format (WINDOW OLD-WINDOW . OLD-BUF-INFO).
-WINDOW is a window used for viewing.
-OLD-WINDOW is nil or the window to select after viewing.
-OLD-BUF-INFO tells what to do with WINDOW when exiting. It is one of:
-1) nil Do nothing.
-2) t Delete WINDOW or, if it is the only window, its frame.
+(defun view-return-to-alist-update (buffer &optional item)
+ "Update `view-return-to-alist' of buffer BUFFER.
+Remove from `view-return-to-alist' all entries referencing dead
+windows. Optional argument ITEM non-nil means add ITEM to
+`view-return-to-alist' after purging. For a decsription of items
+that can be added see the RETURN-TO-ALIST argument of the
+function `view-mode-exit'. If `view-return-to-alist' contains an
+entry for the selected window, purge that entry from
+`view-return-to-alist' before adding ITEM."
+ (with-current-buffer buffer
+ (when view-return-to-alist
+ (let* ((list view-return-to-alist)
+ entry entry-window last)
+ (while list
+ (setq entry (car list))
+ (setq entry-window (car entry))
+ (if (and (windowp entry-window)
+ (or (and item (eq entry-window (selected-window)))
+ (not (window-live-p entry-window))))
+ ;; Remove that entry.
+ (if last
+ (setcdr last (cdr list))
+ (setq view-return-to-alist
+ (cdr view-return-to-alist)))
+ ;; Leave entry alone.
+ (setq last entry))
+ (setq list (cdr list)))))
+ ;; Add ITEM.
+ (when item
+ (setq view-return-to-alist
+ (cons item view-return-to-alist)))))
+
+;;;###autoload
+(defun view-mode-enter (&optional return-to exit-action)
+ "Enter View mode and set up exit from view mode depending on optional arguments.
+RETURN-TO non-nil means add RETURN-TO as an element to the buffer
+local alist `view-return-to-alist'. Save EXIT-ACTION in buffer
+local variable `view-exit-action'. It should be either nil or a
+function that takes a buffer as argument. This function will be
+called by `view-mode-exit'.
+
+RETURN-TO is either nil, meaning do nothing when exiting view
+mode, or must have the format (WINDOW OLD-WINDOW . OLD-BUF-INFO).
+WINDOW is the window used for viewing. OLD-WINDOW is nil or the
+window to select after viewing. OLD-BUF-INFO tells what to do
+with WINDOW when exiting. It is one of:
+1) nil Do nothing.
+2) t Delete WINDOW or, if it is the only window and
+ `view-remove-frame-by-deleting' is non-nil, its
+ frame.
3) (OLD-BUFF START POINT) Display buffer OLD-BUFF with displayed text
- starting at START and point at POINT in WINDOW.
-4) quit-window Do `quit-window' in WINDOW.
+ starting at START and point at POINT in WINDOW.
+4) quit-window Do `quit-window' in WINDOW.
+5) keep-frame Like case 2) but do not delete the frame.
-For list of all View commands, type H or h while viewing.
+For a list of all View commands, type H or h while viewing.
This function runs the normal hook `view-mode-hook'."
- (if return-to
- (let ((entry (assq (car return-to) view-return-to-alist)))
- (if entry (setcdr entry (cdr return-to))
- (setq view-return-to-alist (cons return-to view-return-to-alist)))))
- (if exit-action (setq view-exit-action exit-action))
- (unless view-mode ; Do nothing if already in view mode.
+ (when return-to
+ (let ((entry (assq (car return-to) view-return-to-alist)))
+ (if entry
+ (setcdr entry (cdr return-to))
+ (setq view-return-to-alist (cons return-to view-return-to-alist)))))
+ (when exit-action
+ (setq view-exit-action exit-action))
+
+ (unless view-mode
(view-mode-enable)
(force-mode-line-update)
- (message "%s"
- (substitute-command-keys "\
-View mode: type \\[help-command] for help, \\[describe-mode] for commands, \\[View-quit] to quit."))))
-
+ (unless view-inhibit-help-message
+ (message "%s"
+ (substitute-command-keys "\
+View mode: type \\[help-command] for help, \\[describe-mode] for commands, \\[View-quit] to quit.")))))
+\f
(defun view-mode-exit (&optional return-to-alist exit-action all-win)
"Exit View mode in various ways, depending on optional arguments.
-RETURN-TO-ALIST, EXIT-ACTION and ALL-WIN determine what to do after exit.
-EXIT-ACTION is nil or a function that is called with current buffer as
-argument.
-RETURN-TO-ALIST is an alist that for some of the windows displaying the
-current buffer, associate information on what to do with those windows.
-If ALL-WIN or the variable `view-exits-all-viewing-windows' is non-nil,
-then all windows on RETURN-TO-ALIST are restored to their old state.
-Otherwise only the selected window is affected (if it is on RETURN-TO-ALIST).
-
-Elements of RETURN-TO-ALIST have the format (WINDOW OLD-WINDOW . OLD-BUF-INFO).
-WINDOW is a window displaying the current buffer.
-OLD-WINDOW is nil or a window to select after viewing.
-OLD-BUF-INFO is information on what to do with WINDOW and is one of:
-1) nil Do nothing.
-2) t Delete WINDOW and, if it is the only window, its frame.
+RETURN-TO-ALIST, EXIT-ACTION and ALL-WIN determine what to do
+after exit. EXIT-ACTION is nil or a function that is called with
+current buffer as argument.
+
+RETURN-TO-ALIST is an alist that, for some of the windows
+displaying the current buffer, maintains information on what to
+do when exiting those windows. If ALL-WIN is non-nil or the
+variable `view-exits-all-viewing-windows' is non-nil,
+view-mode-exit attempts to restore all windows showing the
+current buffer to their old state. Otherwise, only the selected
+window is affected (provided it is on RETURN-TO-ALIST).
+
+Elements of RETURN-TO-ALIST must have the format
+ (WINDOW OLD-WINDOW . OLD-BUF-INFO) where
+
+WINDOW is a window displaying the current buffer and OLD-WINDOW
+is either nil or a window to select after viewing. OLD-BUF-INFO
+provides information on what to do with WINDOW and may be one of:
+1) nil Do nothing.
+2) t Delete WINDOW and, if it is the only window and
+ `view-remove-frame-by-deleting' is non-nil, its
+ frame.
3) (OLD-BUF START POINT) Display buffer OLD-BUF with displayed text
- starting at START and point at POINT in WINDOW.
-4) quit-window Do `quit-window' in WINDOW.
-
-If one of the WINDOW in RETURN-TO-ALIST is the selected window and the
-corresponding OLD-WINDOW is a live window, then select OLD-WINDOW."
- (setq all-win
- (and return-to-alist (or all-win view-exits-all-viewing-windows)))
- (if view-mode ; Only do something if in view mode.
- (let* ((buffer (current-buffer))
- window notlost
- (sel-old (assq (selected-window) return-to-alist))
- (alist (cond
- (all-win ; Try to restore all windows.
- (append return-to-alist nil)) ; Copy.
- (sel-old ; Only selected window.
- (list sel-old))))
- (old-window (if sel-old (car (cdr sel-old)))))
- (if all-win ; Follow chains of old-windows.
- (let ((c (length alist)) a)
- (while (and (> c 0) ; Safety if mutually refering windows.
- (or (not (window-live-p old-window))
- (eq buffer (window-buffer old-window)))
- (setq a (assq old-window alist)))
- (setq c (1- c))
- (setq old-window (car (cdr a))))
- (if (or (zerop c) (not (window-live-p old-window)))
- (setq old-window (selected-window)))))
- (or view-no-disable-on-exit
- (view-mode-disable))
- (while alist ; Restore windows with info.
- (setq notlost nil)
- (if (and (window-live-p (setq window (car (car alist))))
+ starting at START and point at POINT in WINDOW.
+4) quit-window Do `quit-window' in WINDOW.
+5) keep-frame Like case 2) but do not delete the frame.
+
+If one of the WINDOW in RETURN-TO-ALIST is the selected window
+and the corresponding OLD-WINDOW is a live window, then select
+OLD-WINDOW."
+ (when view-mode ; Only do something if in view mode.
+ (setq all-win
+ (and return-to-alist
+ (or all-win view-exits-all-viewing-windows)))
+ (let* ((buffer (current-buffer))
+ window notlost
+ (sel-old (assq (selected-window) return-to-alist))
+ (alist (cond
+ (all-win ; Try to restore all windows.
+ (append return-to-alist nil)) ; Copy.
+ (sel-old ; Only selected window.
+ (list sel-old))))
+ (old-window (if sel-old (car (cdr sel-old)))))
+ (if all-win ; Follow chains of old-windows.
+ (let ((c (length alist)) a)
+ (while (and (> c 0) ; Safety if mutually refering windows.
+ (or (not (window-live-p old-window))
+ (eq buffer (window-buffer old-window)))
+ (setq a (assq old-window alist)))
+ (setq c (1- c))
+ (setq old-window (car (cdr a))))
+ (if (or (zerop c) (not (window-live-p old-window)))
+ (setq old-window (selected-window)))))
+ (unless view-no-disable-on-exit
+ (view-mode-disable))
+ (while alist ; Restore windows with info.
+ (setq notlost nil)
+ (when (and (window-live-p (setq window (car (car alist))))
(eq buffer (window-buffer window)))
- (let ((frame (window-frame window))
- (old-buf-info (cdr (cdr (car alist)))))
- (if all-win (select-window window))
- (cond
- ((and (consp old-buf-info) ; Case 3.
- (buffer-live-p (car old-buf-info)))
- (set-window-buffer window (car old-buf-info)) ; old-buf
- (set-window-start window (car (cdr old-buf-info)))
- (set-window-point window (car (cdr (cdr old-buf-info)))))
- ((eq old-buf-info 'quit-window)
- (quit-window)) ; Case 4.
- ((not (eq old-buf-info t)) nil) ; Not case 2, do nothing.
- ((not (one-window-p t)) (delete-window))
- ((not (eq frame (next-frame)))
- ;; Not the only frame, so can safely be removed.
- (if view-remove-frame-by-deleting
- (delete-frame frame)
- (setq notlost t) ; Keep the window. See below.
- (iconify-frame frame))))))
- ;; If a frame is removed by iconifying it, then the window is not
- ;; really lost. In this case we keep the entry in
- ;; view-return-to-alist so that if the user deiconifies the frame
- ;; and then press q, then the frame is iconified again.
- (unless notlost
+ (let ((frame (window-frame window))
+ (old-buf-info (cdr (cdr (car alist)))))
+ (if all-win (select-window window))
+ (cond
+ ((and (consp old-buf-info) ; Case 3.
+ (buffer-live-p (car old-buf-info)))
+ (set-window-buffer window (car old-buf-info)) ; old-buf
+ (set-window-start window (car (cdr old-buf-info)))
+ (set-window-point window (car (cdr (cdr old-buf-info)))))
+ ((eq old-buf-info 'quit-window)
+ (quit-window)) ; Case 4.
+ (old-buf-info ; Case 2 or 5.
+ (cond
+ ((not (one-window-p t)) ; Not only window.
+ (delete-window))
+ ((eq old-buf-info 'keep-frame) ; Case 5.
+ (bury-buffer))
+ ((not (eq frame (next-frame))) ; Case 2 and only window.
+ ;; Not the only frame, so can safely be removed.
+ (if view-remove-frame-by-deleting
+ (delete-frame frame)
+ (setq notlost t) ; Keep the window. See below.
+ (iconify-frame frame))))))))
+ ;; If a frame is removed by iconifying it, the window is not
+ ;; really lost. In this case we keep the entry in
+ ;; `view-return-to-alist' so that if the user deiconifies the
+ ;; frame and then hits q, the frame is iconified again.
+ (unless notlost
+ (with-current-buffer buffer
(setq view-return-to-alist
- (delete (car alist) view-return-to-alist)))
- (setq alist (cdr alist)))
- (if (window-live-p old-window) ; still existing window
- (select-window old-window))
- (when exit-action
- (setq view-exit-action nil)
- (funcall exit-action buffer))
- (force-mode-line-update))))
-
+ (delete (car alist) view-return-to-alist))))
+ (setq alist (cdr alist)))
+ (when (window-live-p old-window)
+ ;; old-window is still alive => select it.
+ (select-window old-window))
+ (when exit-action
+ ;; Don't do that: If the user wants to quit the *Help* buffer a
+ ;; second time it won't have any effect.
+;;; (setq view-exit-action nil)
+ (funcall exit-action buffer))
+ (force-mode-line-update))))
+\f
(defun View-exit ()
"Exit View mode but stay in current buffer."
(interactive)
"Quit View mode, kill current buffer and return to previous buffer."
(interactive)
(view-mode-exit view-return-to-alist (or view-exit-action 'kill-buffer) t))
-
+\f
;;; Some help routines.
(defun view-set-half-page-size-default (lines)
;; Get and maybe set half page size.
- (if (not lines) view-half-page-size
+ (if (not lines) (or view-half-page-size
+ (/ (view-window-size) 2))
(setq view-half-page-size
(if (zerop (setq lines (prefix-numeric-value lines)))
(/ (view-window-size) 2)
; (goto-char (point-max))
; (beginning-of-line))
; (view-recenter))
-
+
(defun View-goto-line (&optional line)
"Move to first (or prefix LINE) line in View mode.
Display is centered at LINE.
(goto-line line)
(view-recenter))
-(defun View-scroll-to-buffer-end ()
- "Scroll backward or forward so that buffer end is at last line of window."
+(defun View-back-to-mark (&optional ignore)
+ "Return to last mark set in View mode, else beginning of file.
+Display that line at the center of the window.
+This command pops the mark ring, so that successive
+invocations return to earlier marks."
(interactive)
- (let ((p (if (pos-visible-in-window-p (point-max)) (point))))
- (goto-char (point-max))
- (recenter -1)
- (and p (goto-char p))))
-
+ (goto-char (or (mark t) (point-min)))
+ (pop-mark)
+ (view-recenter))
+\f
(defun view-scroll-lines (lines backward default maxdefault)
;; This function does the job for all the scrolling commands.
;; Scroll forward LINES lines. If BACKWARD is true scroll backwards.
(if view-scroll-auto-exit "\\[View-scroll-page-forward]"
"\\[View-quit]")))
(message "End of buffer")))
+\f
+(defun View-scroll-to-buffer-end ()
+ "Scroll backward or forward so that buffer end is at last line of window."
+ (interactive)
+ (let ((p (if (pos-visible-in-window-p (point-max)) (point))))
+ (goto-char (point-max))
+ (recenter -1)
+ (and p (goto-char p))))
(defun View-scroll-page-forward (&optional lines)
"Scroll \"page size\" or prefix LINES lines forward in View mode.
\\[View-scroll-page-backward-set-page-size].
If LINES is more than a window-full, only the last window-full is shown."
(interactive "P")
- (view-scroll-lines lines nil view-page-size nil))
+ (view-scroll-lines lines nil (view-page-size-default view-page-size) nil))
(defun View-scroll-page-backward (&optional lines)
"Scroll \"page size\" or prefix LINES lines backward in View mode.
See also `View-scroll-page-forward'."
(interactive "P")
- (view-scroll-lines lines t view-page-size nil))
-
+ (view-scroll-lines lines t (view-page-size-default view-page-size) nil))
+
(defun View-scroll-page-forward-set-page-size (&optional lines)
"Scroll forward LINES lines in View mode, setting the \"page size\".
This is the number of lines which \\[View-scroll-page-forward] and
(interactive "P")
(let ((view-scroll-auto-exit nil)
(view-try-extend-at-buffer-end t))
- (view-scroll-lines lines nil view-page-size nil)))
-
-(defun View-back-to-mark (&optional ignore)
- "Return to last mark set in View mode, else beginning of file.
-Display that line at the center of the window.
-This command pops the mark ring, so that successive
-invocations return to earlier marks."
- (interactive)
- (goto-char (or (mark t) (point-min)))
- (pop-mark)
- (view-recenter))
-
+ (view-scroll-lines lines nil (view-page-size-default view-page-size) nil)))
+\f
(defun View-search-regexp-forward (n regexp)
"Search forward for first (or prefix Nth) occurrence of REGEXP in View mode.
times (if no "no " "") regexp)
(sit-for 4))))
+;; This is the dumb approach, looking at each line. The original
+;; version of this function looked like it might have been trying to
+;; do something clever, but not succeeding:
+;; http://lists.gnu.org/archive/html/bug-gnu-emacs/2007-09/msg00073.html
(defun view-search-no-match-lines (times regexp)
- ;; Search for the TIMESt occurrence of line with no match for REGEXP.
- (let ((back (and (< times 0) (setq times (- times)) -1))
- n)
- (while (> times 0)
- (save-excursion (beginning-of-line (if back (- times) (1+ times)))
- (setq n (point)))
- (setq times
- (cond
- ((< (count-lines (point) n) times) -1) ; Not enough lines.
- ((or (null (re-search-forward regexp nil t back))
- (if back (and (< (match-end 0) n)
- (> (count-lines (match-end 0) n) 1))
- (and (< n (match-beginning 0))
- (> (count-lines n (match-beginning 0)) 1))))
- 0) ; No match within lines.
- (back (count-lines (max n (match-beginning 0)) (match-end 0)))
- (t (count-lines (match-beginning 0) (min n (match-end 0))))))
- (goto-char n))
- (and (zerop times) (looking-at "^.*$"))))
-
+ "Search for the TIMESth occurrence of a line with no match for REGEXP.
+If such a line is found, return non-nil and set the match-data to that line.
+If TIMES is negative, search backwards."
+ (let ((step (if (>= times 0) 1
+ (setq times (- times))
+ -1)))
+ ;; Note that we do not check the current line.
+ (while (and (> times 0)
+ (zerop (forward-line step)))
+ ;; (forward-line 1) returns 0 on moving within the last line.
+ (if (eobp)
+ (setq times -1)
+ (or (re-search-forward regexp (line-end-position) t)
+ (setq times (1- times))))))
+ (and (zerop times)
+ (looking-at ".*")))
(provide 'view)
+;;; arch-tag: 6d0ace36-1d12-4de3-8de3-1fa3231636d7
;;; view.el ends here