+ (buffer-name))))
+ (force-mode-line-update)
+ (run-hooks 'view-mode-hook))
+
+(defun view-mode-disable ()
+ "Turn off View mode."
+ (remove-hook 'change-major-mode-hook 'view-mode-disable t)
+ (and view-overlay (delete-overlay view-overlay))
+ (force-mode-line-update)
+ ;; Calling toggle-read-only while View mode is enabled
+ ;; sets view-read-only to t as a buffer-local variable
+ ;; after exiting View mode. That arranges that the next toggle-read-only
+ ;; will reenable View mode.
+ ;; Cancelling View mode in any other way should cancel that, too,
+ ;; 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)
+ (if buffer-read-only
+ (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.
+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.
+
+For 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.
+ (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."))))
+\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.
+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))))
+ (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
+ (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))))