]> code.delx.au - gnu-emacs/blobdiff - lisp/view.el
Merge changes from emacs-23 branch.
[gnu-emacs] / lisp / view.el
index 1d2078a4bb8752908c62cf19b96b8606516d5f1a..f6698ae5a9f051b124e1ac7409fe5d562b71c832 100644 (file)
@@ -1,7 +1,7 @@
 ;;; view.el --- peruse file or buffer without editing
 
 ;; Copyright (C) 1985, 1989, 1994, 1995, 1997, 2000, 2001, 2002,
-;;   2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;;   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Author: K. Shane Hartman
 ;; Maintainer: Inge Frick <inge@nada.kth.se>
   "Peruse file or buffer without editing."
   :link '(function-link view-mode)
   :link '(custom-manual "(emacs)Misc File Ops")
-  :group 'wp
-  :group 'editing)
+  :group 'wp)
 
 (defcustom view-highlight-face 'highlight
-   "*The face used for highlighting the match found by View mode search."
+   "The face used for highlighting the match found by View mode search."
    :type 'face
    :group 'view)
 
 ;; doesn't say if leaving view mode should restore windows or not.  The latter
 ;; 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.
+  "Non-nil means scrolling past the end of buffer exits View mode.
 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 to 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."
@@ -77,7 +76,7 @@ for all scroll commands in view mode."
 
 ;;;###autoload
 (defcustom view-remove-frame-by-deleting t
-  "*Determine how View mode removes a frame no longer needed.
+  "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
@@ -86,7 +85,7 @@ If nil, make an icon of the frame.  If non-nil, delete the frame."
   :version "23.1")
 
 (defcustom view-exits-all-viewing-windows nil
-  "*Non-nil means restore all windows used to view buffer.
+  "Non-nil means restore all windows used to view buffer.
 Commands that restore windows when finished viewing a buffer, apply to all
 windows that display the buffer and have restore information in
 `view-return-to-alist'.
@@ -96,7 +95,7 @@ considered for restoring."
   :group 'view)
 
 (defcustom view-inhibit-help-message nil
-  "*Non-nil inhibits the help message shown upon entering View mode."
+  "Non-nil inhibits the help message shown upon entering View mode."
   :type 'boolean
   :group 'view
   :version "22.1")
@@ -120,9 +119,6 @@ functions that enable or disable view mode.")
 (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 that means use the window size.")
@@ -165,14 +161,6 @@ that use View mode automatically.")
   "Overlay used to display where a search operation found its match.
 This is local in each buffer, once it is used.")
 (make-variable-buffer-local 'view-overlay)
-
-(unless (assq 'view-mode minor-mode-alist)
-  (setq minor-mode-alist
-       (cons (list 'view-mode
-                   (propertize " View"
-                               '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.
@@ -182,13 +170,13 @@ This is local in each buffer, once it is used.")
     (define-key map "c" 'View-leave)
     (define-key map "Q" 'View-quit-all)
     (define-key map "E" 'View-exit-and-edit)
-;    (define-key map "v" 'View-exit)
+    ;; (define-key map "v" 'View-exit)
     (define-key map "e" 'View-exit)
     (define-key map "q" 'View-quit)
-;    (define-key map "N" 'View-search-last-regexp-backward)
+    ;; (define-key map "N" 'View-search-last-regexp-backward)
     (define-key map "p" 'View-search-last-regexp-backward)
     (define-key map "n" 'View-search-last-regexp-forward)
-;    (define-key map "?" 'View-search-regexp-backward) ; Less does this.
+    ;; (define-key map "?" 'View-search-regexp-backward) ; Less does this.
     (define-key map "\\" 'View-search-regexp-backward)
     (define-key map "/" 'View-search-regexp-forward)
     (define-key map "r" 'isearch-backward)
@@ -199,22 +187,22 @@ This is local in each buffer, once it is used.")
     (define-key map "@" 'View-back-to-mark)
     (define-key map "." 'set-mark-command)
     (define-key map "%" 'View-goto-percent)
-;    (define-key map "G" 'View-goto-line-last)
+    ;; (define-key map "G" 'View-goto-line-last)
     (define-key map "g" 'View-goto-line)
     (define-key map "=" 'what-line)
     (define-key map "F" 'View-revert-buffer-scroll-page-forward)
-;    (define-key map "k" 'View-scroll-line-backward)
+    ;; (define-key map "k" 'View-scroll-line-backward)
     (define-key map "y" 'View-scroll-line-backward)
-;    (define-key map "j" 'View-scroll-line-forward)
+    ;; (define-key map "j" 'View-scroll-line-forward)
     (define-key map "\n" 'View-scroll-line-forward)
     (define-key map "\r" 'View-scroll-line-forward)
     (define-key map "u" 'View-scroll-half-page-backward)
     (define-key map "d" 'View-scroll-half-page-forward)
     (define-key map "z" 'View-scroll-page-forward-set-page-size)
     (define-key map "w" 'View-scroll-page-backward-set-page-size)
-;    (define-key map "b" 'View-scroll-page-backward)
+    ;; (define-key map "b" 'View-scroll-page-backward)
     (define-key map "\C-?" 'View-scroll-page-backward)
-;    (define-key map "f" 'View-scroll-page-forward)
+    ;; (define-key map "f" 'View-scroll-page-forward)
     (define-key map " " 'View-scroll-page-forward)
     (define-key map "o" 'View-scroll-to-buffer-end)
     (define-key map ">" 'end-of-buffer)
@@ -234,10 +222,6 @@ This is local in each buffer, once it is used.")
     (define-key map "?" 'describe-mode)        ; Maybe do as less instead? See above.
     (define-key map "h" 'describe-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.
 
@@ -266,13 +250,7 @@ This command runs the normal hook `view-mode-hook'."
   (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-if-not-modified)))))
+    (view-buffer buffer (and (not had-a-buf) 'kill-buffer-if-not-modified))))
 
 ;;;###autoload
 (defun view-file-other-window (file)
@@ -338,10 +316,16 @@ file: Users may suspend viewing in order to modify the buffer.
 Exiting View mode will then discard the user's edits.  Setting
 EXIT-ACTION to `kill-buffer-if-not-modified' avoids this."
   (interactive "bView buffer: ")
-  (let ((undo-window (list (window-buffer) (window-start) (window-point))))
-    (switch-to-buffer buffer)
-    (view-mode-enter (cons (selected-window) (cons nil undo-window))
-                    exit-action)))
+  (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"))
+    (let ((undo-window (list (window-buffer) (window-start) (window-point))))
+      (switch-to-buffer buffer)
+      (view-mode-enter (cons (selected-window) (cons nil undo-window))
+                      exit-action))))
 
 ;;;###autoload
 (defun view-buffer-other-window (buffer &optional not-return exit-action)
@@ -397,7 +381,7 @@ this argument instead of explicitly setting `view-exit-action'."
                     exit-action)))
 \f
 ;;;###autoload
-(defun view-mode (&optional arg)
+(define-minor-mode view-mode
   ;; 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.
@@ -477,11 +461,8 @@ If view-mode was entered from another buffer, by \\[view-buffer],
 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")
-  (unless (and arg                     ; Do nothing if already OK.
-              (if (> (prefix-numeric-value arg) 0) view-mode (not view-mode)))
-    (if view-mode (view-mode-disable)
-      (view-mode-enable))))
+  :lighter " View" :keymap view-mode-map
+  (if view-mode (view-mode-enable) (view-mode-disable)))
 \f
 (defun view-mode-enable ()
   "Turn on View mode."
@@ -492,14 +473,15 @@ Entry to view-mode runs the normal hook `view-mode-hook'."
        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)
-                                         Helper-return-blurb)
-       Helper-return-blurb
-       (format "continue viewing %s"
-               (if (buffer-file-name)
-                   (file-name-nondirectory (buffer-file-name))
-                 (buffer-name))))
+       buffer-read-only t)
+  (if (boundp 'Helper-return-blurb)
+      (setq view-old-Helper-return-blurb (and (boundp 'Helper-return-blurb)
+                                             Helper-return-blurb)
+           Helper-return-blurb
+           (format "continue viewing %s"
+                   (if (buffer-file-name)
+                       (file-name-nondirectory (buffer-file-name))
+                     (buffer-name)))))
   (force-mode-line-update)
   (run-hooks 'view-mode-hook))
 
@@ -516,8 +498,9 @@ Entry to view-mode runs the normal hook `view-mode-hook'."
   ;; so that View mode stays off if toggle-read-only is called.
   (if (local-variable-p 'view-read-only)
       (kill-local-variable 'view-read-only))
-  (setq view-mode nil
-       Helper-return-blurb view-old-Helper-return-blurb)
+  (setq view-mode nil)
+  (if (boundp 'Helper-return-blurb)
+      (setq Helper-return-blurb view-old-Helper-return-blurb))
   (if buffer-read-only
       (setq buffer-read-only view-old-buffer-read-only)))
 
@@ -661,11 +644,13 @@ OLD-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)))))
+            ((consp old-buf-info)              ; Case 3.
+             (if (buffer-live-p (car old-buf-info))
+                 (progn
+                   (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)))))
+               (bury-buffer)))
             ((eq old-buf-info 'quit-window)
              (quit-window))                    ; Case 4.
             (old-buf-info                      ; Case 2 or 5.
@@ -678,7 +663,7 @@ OLD-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.
+                 (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
@@ -695,7 +680,7 @@ 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)
+       ;;(setq view-exit-action nil)
        (funcall exit-action buffer))
       (force-mode-line-update))))
 \f
@@ -740,32 +725,40 @@ previous state and go to previous buffer or window."
 ;;; Some help routines.
 
 (defun view-window-size ()
-  ;; Window height excluding mode line.
-  (1- (window-height)))
-
-;(defun view-last-command (&optional who what)
-;  (setq view-last-command-entry this-command)
-;  (setq view-last-command who)
-;  (setq view-last-command-argument what))
-
-;(defun View-repeat-last-command ()
-;  "Repeat last command issued in View mode."
-;  (interactive)
-;  (if (and view-last-command
-;         (eq view-last-command-entry last-command))
-;      (funcall view-last-command view-last-command-argument))
-;  (setq this-command view-last-command-entry))
+  ;; Return the height of the current window, excluding the mode line.
+  ;; Using `window-line-height' accounts for variable-height fonts.
+  (let ((h (window-line-height -1)))
+    (if h
+       (1+ (nth 1 h))
+      ;; This should not happen, but if `window-line-height' returns
+      ;; nil, fall back on `window-height'.
+      (1- (window-height)))))
+
+;; (defun view-last-command (&optional who what)
+;;  (setq view-last-command-entry this-command)
+;;  (setq view-last-command who)
+;;  (setq view-last-command-argument what))
+
+;; (defun View-repeat-last-command ()
+;;  "Repeat last command issued in View mode."
+;;  (interactive)
+;;  (if (and view-last-command
+;;        (eq view-last-command-entry last-command))
+;;      (funcall view-last-command view-last-command-argument))
+;;  (setq this-command view-last-command-entry))
 
 (defun view-recenter ()
-  ;; Center point in window.
-  (recenter (/ (view-window-size) 2)))
+  ;; Recenter point in window and redisplay normally.
+  (recenter '(1)))
 
 (defun view-page-size-default (lines)
-  ;; Get page size.
-  (let ((default (- (view-window-size) next-screen-context-lines)))
-    (if (or (null lines) (zerop (setq lines (prefix-numeric-value lines))))
-       default
-      (min (abs lines) default))))
+  ;; If LINES is nil, 0, or larger than `view-window-size', return nil.
+  ;; Otherwise, return LINES.
+  (and lines
+       (not (zerop (setq lines (prefix-numeric-value lines))))
+       (<= (abs lines)
+          (abs (- (view-window-size) next-screen-context-lines)))
+       (abs lines)))
 
 (defun view-set-half-page-size-default (lines)
   ;; Get and maybe set half page size.
@@ -793,16 +786,16 @@ Also set the mark at the position where point was."
      (point-max)))
   (view-recenter))
 
-;(defun View-goto-line-last (&optional line)
-;"Move to last (or prefix LINE) line in View mode.
-;Display is centered at LINE.
-;Sets mark at starting position and pushes mark ring."
-;  (interactive "P")
-;  (push-mark)
-;  (if line (goto-line (prefix-numeric-value line))
-;    (goto-char (point-max))
-;    (beginning-of-line))
-;  (view-recenter))
+;(defun View-goto-line-last (&optional line)
+;"Move to last (or prefix LINE) line in View mode.
+;Display is centered at LINE.
+;Sets mark at starting position and pushes mark ring."
+;;  (interactive "P")
+;;  (push-mark)
+;;  (if line (goto-line (prefix-numeric-value line))
+;;    (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.
@@ -810,7 +803,8 @@ Display is centered at LINE.
 Also set the mark at the position where point was."
   (interactive "p")
   (push-mark)
-  (goto-line line)
+  (goto-char (point-min))
+  (forward-line (1- line))
   (view-recenter))
 
 (defun View-back-to-mark (&optional ignore)
@@ -825,30 +819,24 @@ invocations return to earlier marks."
 \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 LINES is negative scroll in the other direction.  If LINES is 0 or nil,
-  ;; scroll DEFAULT lines.  If MAXDEFAULT is true then scroll no more than a
-  ;; window full.
+  ;; Scroll forward LINES lines.  If BACKWARD is non-nil, scroll backwards.
+  ;; If LINES is negative scroll in the other direction.
+  ;; If LINES is 0 or nil, scroll DEFAULT lines (if DEFAULT is nil, scroll
+  ;; by one page).  If MAXDEFAULT is non-nil, scroll no more than a window.
   (if (or (null lines) (zerop (setq lines (prefix-numeric-value lines))))
       (setq lines default))
-  (when (< lines 0)
-    (setq backward (not backward)) (setq lines (- lines)))
-  (setq default (view-page-size-default nil)) ; Max scrolled at a time.
-  (if maxdefault (setq lines (min lines default)))
-  (cond
-   (backward (scroll-down lines))
-   ((view-really-at-end)
-    (if view-scroll-auto-exit (View-quit)
-      (ding)
-      (view-end-message)))
-   (t (while (> lines default)
-       (scroll-up default)
-       (setq lines (- lines default))
-       (if (view-really-at-end) (setq lines 0)))
-      (scroll-up lines)
-      (if (view-really-at-end) (view-end-message))
-      (move-to-window-line -1)
-      (beginning-of-line))))
+  (when (and lines (< lines 0))
+    (setq backward (not backward) lines (- lines)))
+  (when (and maxdefault lines (> lines (view-window-size)))
+    (setq lines nil))
+  (cond (backward (scroll-down lines))
+       ((view-really-at-end)
+        (if view-scroll-auto-exit
+            (View-quit)
+          (ding)
+          (view-end-message)))
+       (t (scroll-up lines)
+          (if (view-really-at-end) (view-end-message)))))
 
 (defun view-really-at-end ()
   ;; Return true if buffer end visible.  Maybe revert buffer and test.
@@ -929,7 +917,7 @@ See also `View-scroll-page-forward-set-page-size'."
 
 (defun View-scroll-line-forward (&optional lines)
   "Scroll forward one line (or prefix LINES lines) in View mode.
-See also `View-scroll-page-forward,' but note that scrolling is limited
+See also `View-scroll-page-forward', but note that scrolling is limited
 to minimum of LINES and one window-full."
   (interactive "P")
   (view-scroll-lines lines nil 1 t))
@@ -1030,9 +1018,9 @@ for highlighting the match that is found."
 
 (defun view-search (times regexp)
   ;; This function does the job for all the View-search- commands.
-  ;; Search for the TIMESt match for REGEXP. If TIMES is negative
-  ;; search backwards. If REGEXP is nil use `view-last-regexp'.
-  ;; Charcters "!" and "@" have a special meaning at the beginning of
+  ;; Search for the TIMESt match for REGEXP.  If TIMES is negative
+  ;; search backwards.  If REGEXP is nil use `view-last-regexp'.
+  ;; Characters "!" and "@" have a special meaning at the beginning of
   ;; REGEXP and are removed from REGEXP before the search "!" means
   ;; search for lines with no match for REGEXP.  "@" means search in
   ;; the whole buffer, don't start searching from the present point.