(Qcenter): New variable.
[bpt/emacs.git] / lisp / desktop.el
index e22f506..e59d57c 100644 (file)
@@ -1,10 +1,9 @@
 ;;; desktop.el --- save partial status of Emacs when killed
 
-;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
 
 ;; Author: Morten Welinder <terra@diku.dk>
-;; Version: 2.08
-;; Keywords: customization
+;; Keywords: convenience
 ;; Favourite-brand-of-beer: None, I hate beer.
 
 ;; This file is part of GNU Emacs.
@@ -20,8 +19,9 @@
 ;; GNU General Public License for more details.
 
 ;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; 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.
 
 ;;; Commentary:
 
 ;;             - buffer-read-only
 ;;             - some local variables
 
-;; To use this, first put these three lines in the bottom of your .emacs
+;; To use this, first put these two lines in the bottom of your .emacs
 ;; file (the later the better):
 ;;
-;;     (load "desktop")
 ;;     (desktop-load-default)
 ;;     (desktop-read)
 ;;
-;; Between the second and the third line you may wish to add something that
-;; updates the variables `desktop-globals-to-save' and/or
-;; `desktop-locals-to-save'.  If for instance you want to save the local
-;; variable `foobar' for every buffer in which it is local, you could add
-;; the line
+;; Between these two lines you may wish to add something that updates the
+;; variables `desktop-globals-to-save' and/or `desktop-locals-to-save'.  If
+;; for instance you want to save the local variable `foobar' for every buffer
+;; in which it is local, you could add the line
 ;;
 ;;     (setq desktop-locals-to-save (cons 'foobar desktop-locals-to-save))
 ;;
-;; To avoid saving excessive amounts of data you may also with to add
+;; To avoid saving excessive amounts of data you may also wish to add
 ;; something like the following
 ;;
 ;;     (add-hook 'kill-emacs-hook
@@ -59,7 +57,8 @@
 ;;                  (desktop-truncate regexp-search-ring 3)))
 ;;
 ;; which will make sure that no more than three search items are saved.  You
-;; must place this line *after* the (load "desktop") line.
+;; must place this line *after* the `(desktop-load-default)' line.  See also
+;; the variable `desktop-save-hook'.
 
 ;; Start Emacs in the root directory of your "project". The desktop saver
 ;; is inactive by default.  You activate it by M-x desktop-save RET.  When
 ;; act as a default desktop when you start Emacs from a directory that
 ;; doesn't have its own.  I never do this, but you may want to.
 
+;; Some words on minor modes: Most minor modes are controlled by
+;; buffer-local variables, which have a standard save / restore
+;; mechanism.  To handle all minor modes, we take the following
+;; approach: (1) check whether the variable name from
+;; `minor-mode-alist' is also a function; and (2) use translation
+;; table `desktop-minor-mode-table' in the case where the two names
+;; are not the same.
+
 ;; By the way: don't use desktop.el to customize Emacs -- the file .emacs
 ;; in your home directory is used for that.  Saving global default values
 ;; for buffers is an example of misuse.
 ;; `desktop-globals-to-save' (by default it isn't).  This may result in saving
 ;; things you did not mean to keep.  Use M-x desktop-clear RET.
 
-;; Thanks to  hetrick@phys.uva.nl (Jim Hetrick)     for useful ideas.
-;;            avk@rtsg.mot.com (Andrew V. Klein)    for a dired tip.
-;;            chris@tecc.co.uk (Chris Boucher)      for a mark tip.
-;;            f89-kam@nada.kth.se (Klas Mellbourn)  for a mh-e tip.
+;; Thanks to  hetrick@phys.uva.nl (Jim Hetrick)      for useful ideas.
+;;            avk@rtsg.mot.com (Andrew V. Klein)     for a dired tip.
+;;            chris@tecc.co.uk (Chris Boucher)       for a mark tip.
+;;            f89-kam@nada.kth.se (Klas Mellbourn)   for a mh-e tip.
+;;            kifer@sbkifer.cs.sunysb.edu (M. Kifer) for a bug hunt.
+;;            treese@lcs.mit.edu (Win Treese)        for ange-ftp tips.
+;;            pot@cnuce.cnr.it (Francesco Potorti`)  for misc. tips.
 ;; ---------------------------------------------------------------------------
 ;; TODO:
 ;;
 ;; Make the compilation more silent
 (eval-when-compile
   ;; We use functions from these modules
-  (mapcar 'require '(info mh-e dired reporter)))
+  ;; We can't (require 'mh-e) since that wants to load something.
+  (mapcar 'require '(info dired reporter)))
 ;; ----------------------------------------------------------------------------
 ;; USER OPTIONS -- settings you might want to play with.
 ;; ----------------------------------------------------------------------------
-(defconst desktop-basefilename
-  (if (eq system-type 'ms-dos)
-      "emacs.dsk" ; Ms-Dos does not support multiple dots in file name
-    ".emacs.desktop")
-  "File for Emacs desktop.  A directory name will be prepended to this name.")
 
-(defvar desktop-missing-file-warning t
-  "*If non-nil then issue warning if a file no longer exists.
-Otherwise simply ignore the file.")
+(defgroup desktop nil
+  "Save status of Emacs when you exit."
+  :group 'frames)
+
+(defcustom desktop-enable nil
+  "*Non-nil enable Desktop to save the state of Emacs when you exit."
+  :group 'desktop
+  :type 'boolean
+  :require 'desktop
+  :initialize 'custom-initialize-default
+  :version "20.3")
+
+(defcustom desktop-basefilename
+  (convert-standard-filename ".emacs.desktop")
+  "File for Emacs desktop, not including the directory name."
+  :type 'file
+  :group 'desktop)
+
+(defcustom desktop-missing-file-warning nil
+  "*If non-nil then desktop warns when a file no longer exists.
+Otherwise it simply ignores that file."
+  :type 'boolean
+  :group 'desktop)
 
 (defvar desktop-globals-to-save
   (list 'desktop-missing-file-warning
@@ -120,7 +146,11 @@ Otherwise simply ignore the file.")
        'register-alist
        ;; 'desktop-globals-to-save     ; Itself!
        )
-  "List of global variables to save when killing Emacs.")
+  "List of global variables to save when killing Emacs.
+An element may be variable name (a symbol)
+or a cons cell of the form  (VAR . MAX-SIZE),
+which means to truncate VAR's value to at most MAX-SIZE elements
+\(if the value is a list) before saving the value.")
 
 (defvar desktop-locals-to-save
   (list 'desktop-locals-to-save                ; Itself!  Think it over.
@@ -130,32 +160,85 @@ Otherwise simply ignore the file.")
        'fill-column
        'overwrite-mode
        'change-log-default-name
+       'line-number-mode
        )
-  "List of local variables to save for each buffer.  The variables are saved
-only when they really are local.")
+  "List of local variables to save for each buffer.
+The variables are saved only when they really are local.")
 (make-variable-buffer-local 'desktop-locals-to-save)
 
 ;; We skip .log files because they are normally temporary.
-;;         (ftp) files because they require passwords and whatsnot.
+;;         (ftp) files because they require passwords and whatnot.
 ;;         TAGS files to save time (tags-file-name is saved instead).
-(defvar desktop-buffers-not-to-save
+(defcustom desktop-buffers-not-to-save
  "\\(^nn\\.a[0-9]+\\|\\.log\\|(ftp)\\|^tags\\|^TAGS\\)$"
- "Regexp identifying buffers that are to be excluded from saving.")
+ "Regexp identifying buffers that are to be excluded from saving."
+ :type 'regexp
+ :group 'desktop)
+
+;; Skip ange-ftp files
+(defcustom desktop-files-not-to-save
+  "^/[^/:]*:"
+  "Regexp identifying files whose buffers are to be excluded from saving."
+  :type 'regexp
+  :group 'desktop)
+
+(defcustom desktop-buffer-major-mode nil
+  "When desktop creates a buffer, this holds the desired Major mode."
+  :type 'symbol
+  :group 'desktop)
 
-(defvar desktop-buffer-handlers
+(defcustom desktop-buffer-file-name nil
+  "When desktop creates a buffer, this holds the file name to visit."
+  :type '(choice file (const nil))
+  :group 'desktop)
+
+(defcustom desktop-buffer-name nil
+  "When desktop creates a buffer, this holds the desired buffer name."
+  :type '(choice string (const nil))
+  :group 'desktop)
+
+(defvar desktop-buffer-misc nil
+  "When desktop creates a buffer, this holds a list of misc info.
+It is used by the `desktop-buffer-handlers' functions.")
+
+(defcustom desktop-buffer-handlers
   '(desktop-buffer-dired
     desktop-buffer-rmail
     desktop-buffer-mh
     desktop-buffer-info
     desktop-buffer-file)
-  "*List of functions to call in order to create a buffer.  The functions are
-called without explicit parameters but may access the the major mode as `mam',
-the file name as `fn', the buffer name as `bn', the default directory as
-`dd'.  If some function returns non-nil no further functions are called.
-If the function returns t then the buffer is considered created.")
+  "*List of functions to call in order to create a buffer.
+The functions are called without explicit parameters but can use the
+variables `desktop-buffer-major-mode', `desktop-buffer-file-name',
+`desktop-buffer-name'.
+If one function returns non-nil, no further functions are called.
+If the function returns t then the buffer is considered created."
+  :type '(repeat function)
+  :group 'desktop)
 
 (defvar desktop-create-buffer-form "(desktop-create-buffer 205"
   "Opening of form for creation of new buffers.")
+
+(defcustom desktop-save-hook nil
+  "Hook run before desktop saves the state of Emacs.
+This is useful for truncating history lists, for example."
+  :type 'hook
+  :group 'desktop)
+
+(defcustom desktop-minor-mode-table
+  '((auto-fill-function auto-fill-mode)
+    (vc-mode nil))
+  "Table mapping minor mode variables to minor mode functions.
+Each entry has the form (NAME RESTORE-FUNCTION).
+NAME is the name of the buffer-local variable indicating that the minor
+mode is active.  RESTORE-FUNCTION is the function to activate the minor mode.
+called.  RESTORE-FUNCTION nil means don't try to restore the minor mode.
+Only minor modes for which the name of the buffer-local variable
+and the name of the minor mode function are different have to added to
+this table."
+  :type 'sexp
+  :group 'desktop)
+
 ;; ----------------------------------------------------------------------------
 (defvar desktop-dirname nil
   "The directory in which the current desktop file resides.")
@@ -168,6 +251,7 @@ If the function returns t then the buffer is considered created.")
 
 (defvar desktop-delay-hook nil
   "Hooks run after all buffers are loaded; intended for internal use.")
+
 ;; ----------------------------------------------------------------------------
 (defun desktop-truncate (l n)
   "Truncate LIST to at most N elements destructively."
@@ -175,27 +259,69 @@ If the function returns t then the buffer is considered created.")
     (if (consp here)
        (setcdr here nil))))
 ;; ----------------------------------------------------------------------------
-(defun desktop-clear () "Empty the Desktop."
+(defcustom desktop-clear-preserve-buffers
+  '("*scratch*" "*Messages*")
+  "*Buffer names that `desktop-clear' should not delete."
+  :type '(repeat string)
+  :group 'desktop)
+
+(defun desktop-clear ()
+  "Empty the Desktop.
+This kills all buffers except for internal ones
+and those listed in `desktop-clear-preserve-buffers'."
   (interactive)
-  (setq kill-ring nil)
-  (setq kill-ring-yank-pointer nil)
-  (mapcar (function kill-buffer) (buffer-list))
+  (setq kill-ring nil
+       kill-ring-yank-pointer nil
+       search-ring nil
+       search-ring-yank-pointer nil
+       regexp-search-ring nil
+       regexp-search-ring-yank-pointer nil)
+  (let ((buffers (buffer-list)))
+    (while buffers
+      (or (member (buffer-name (car buffers)) desktop-clear-preserve-buffers)
+         (null (buffer-name (car buffers)))
+         ;; Don't kill buffers made for internal purposes.
+         (and (not (equal (buffer-name (car buffers)) ""))
+              (eq (aref (buffer-name (car buffers)) 0) ?\ ))
+         (kill-buffer (car buffers)))
+      (setq buffers (cdr buffers))))
   (delete-other-windows))
 ;; ----------------------------------------------------------------------------
 (add-hook 'kill-emacs-hook 'desktop-kill)
 
 (defun desktop-kill ()
   (if desktop-dirname
-      (progn
-       (desktop-save desktop-dirname))))
+      (condition-case err
+         (desktop-save desktop-dirname)
+       (file-error
+        (if (yes-or-no-p "Error while saving the desktop.  Quit anyway? ")
+            nil
+          (signal (car err) (cdr err)))))))
 ;; ----------------------------------------------------------------------------
+(defun desktop-list* (&rest args)
+  (if (null (cdr args))
+      (car args)
+    (setq args (nreverse args))
+    (let ((value (cons (nth 1 args) (car args))))
+      (setq args (cdr (cdr args)))
+      (while args
+       (setq value (cons (car args) value))
+       (setq args (cdr args)))
+      value)))
+
 (defun desktop-internal-v2s (val)
-  "Convert VALUE to a pair (quote . txt) where txt is a string that when read
-and evaluated yields value.  quote may be 'may (value may be quoted),
-'must (values must be quoted), or nil (value may not be quoted)."
+  "Convert VALUE to a pair (QUOTE . TXT); (eval (read TXT)) gives VALUE.
+TXT is a string that when read and evaluated yields value.
+QUOTE may be `may' (value may be quoted),
+`must' (values must be quoted), or nil (value may not be quoted)."
   (cond
-   ((or (numberp val) (stringp val) (null val) (eq t val))
+   ((or (numberp val) (null val) (eq t val))
     (cons 'may (prin1-to-string val)))
+   ((stringp val)
+    (let ((copy (copy-sequence val)))
+      (set-text-properties 0 (length copy) nil copy)
+      ;; Get rid of text properties because we cannot read them
+      (cons 'may (prin1-to-string copy))))
    ((symbolp val)
     (cons 'must (prin1-to-string val)))
    ((vectorp val)
@@ -220,6 +346,7 @@ and evaluated yields value.  quote may be 'may (value may be quoted),
    ((consp val)
     (let ((p val)
          newlist
+         use-list*
          anynil)
       (while (consp p)
        (let ((q.txt (desktop-internal-v2s (car p))))
@@ -229,22 +356,15 @@ and evaluated yields value.  quote may be 'may (value may be quoted),
       (if p
          (let ((last (desktop-internal-v2s p))
                (el (car newlist)))
-           (setcar newlist
-                   (if (or anynil (setq anynil (null (car last))))
-                       (cons nil
-                             (concat "(cons "
-                                     (if (eq (car el) 'must) "'" "")
-                                     (cdr el)
-                                     " "
-                                     (if (eq (car last) 'must) "'" "")
-                                     (cdr last)
-                                     ")"))
-                     (cons 'must
-                           (concat (cdr el) " . " (cdr last)))))))
+           (or anynil (setq anynil (null (car last))))
+           (or anynil
+               (setq newlist (cons '(must . ".") newlist)))
+           (setq use-list* t)
+           (setq newlist (cons last newlist))))
       (setq newlist (nreverse newlist))
       (if anynil
          (cons nil
-               (concat "(list "
+               (concat (if use-list* "(desktop-list* "  "(list ")
                        (mapconcat (lambda (el)
                                     (if (eq (car el) 'must)
                                         (concat "'" (cdr el))
@@ -266,11 +386,11 @@ and evaluated yields value.  quote may be 'may (value may be quoted),
                        " (list 'lambda '() (list 'set-marker mk "
                        pos " (get-buffer " buf ")))) mk)"))))
    (t                                  ; save as text
-    (cons 'may (prin1-to-string val)))))
+    (cons 'may "\"Unprintable entity\""))))
 
 (defun desktop-value-to-string (val)
-  "Convert VALUE to a string that when read evaluates to the same value.  Not
-all types of values are supported."
+  "Convert VALUE to a string that when read evaluates to the same value.
+Not all types of values are supported."
   (let* ((print-escape-newlines t)
         (float-output-format nil)
         (quote.txt (desktop-internal-v2s val))
@@ -280,40 +400,73 @@ all types of values are supported."
        (concat "'" txt)
       txt)))
 ;; ----------------------------------------------------------------------------
-(defun desktop-outvar (var)
-  "Output a setq statement for VAR to the desktop file."
-  (if (boundp var)
-      (insert "(setq "
-             (symbol-name var)
-             " "
-             (desktop-value-to-string (symbol-value var))
-             ")\n")))
+(defun desktop-outvar (varspec)
+  "Output a setq statement for variable VAR to the desktop file.
+The argument VARSPEC may be the variable name VAR (a symbol),
+or a cons cell of the form  (VAR . MAX-SIZE),
+which means to truncate VAR's value to at most MAX-SIZE elements
+\(if the value is a list) before saving the value."
+  (let (var size)
+    (if (consp varspec)
+       (setq var (car varspec) size (cdr varspec))
+      (setq var varspec))
+    (if (boundp var)
+       (progn
+         (if (and (integerp size)
+                  (> size 0)
+                  (listp (eval var)))
+             (desktop-truncate (eval var) size))
+         (insert "(setq "
+                 (symbol-name var)
+                 " "
+                 (desktop-value-to-string (symbol-value var))
+                 ")\n")))))
 ;; ----------------------------------------------------------------------------
 (defun desktop-save-buffer-p (filename bufname mode &rest dummy)
   "Return t if the desktop should record a particular buffer for next startup.
 FILENAME is the visited file name, BUFNAME is the buffer name, and
 MODE is the major mode."
-  (or (and filename
-          (not (string-match desktop-buffers-not-to-save bufname)))
-      (and (null filename)
-          (memq mode '(Info-mode dired-mode rmail-mode)))))
+  (let ((case-fold-search nil))
+    (or (and filename
+            (not (string-match desktop-buffers-not-to-save bufname))
+            (not (string-match desktop-files-not-to-save filename)))
+       (and (eq mode 'dired-mode)
+            (save-excursion
+              (set-buffer (get-buffer bufname))
+              (not (string-match desktop-files-not-to-save
+                                 default-directory))))
+       (and (null filename)
+            (memq mode '(Info-mode rmail-mode))))))
 ;; ----------------------------------------------------------------------------
 (defun desktop-save (dirname)
   "Save the Desktop file.  Parameter DIRNAME specifies where to save desktop."
   (interactive "DDirectory to save desktop file in: ")
+  (run-hooks 'desktop-save-hook)
   (save-excursion
     (let ((filename (expand-file-name
                     (concat dirname desktop-basefilename)))
          (info (nreverse
                 (mapcar
-                 (function (lambda (b)
+                 (function
+                  (lambda (b)
                              (set-buffer b)
                              (list
                               (buffer-file-name)
                               (buffer-name)
                               major-mode
-                              (list    ; list explaining minor modes
-                                    (not (null auto-fill-function)))
+                              ;; minor modes
+                              (let (ret)
+                                (mapcar
+                                 #'(lambda (mim)
+                                     (and (symbol-value mim)
+                                          (setq ret
+                                                (cons (let ((special (assq mim desktop-minor-mode-table)))
+                                                       (if special
+                                                           (cadr special)
+                                                         mim))
+                                                     ret))))
+                                 (mapcar #'car minor-mode-alist))
+                                ret)
                               (point)
                               (list (mark t) mark-active)
                               buffer-read-only
@@ -321,11 +474,13 @@ MODE is the major mode."
                                      (list Info-current-file
                                            Info-current-node))
                                     ((eq major-mode 'dired-mode)
-                                     (nreverse
-                                      (mapcar
-                                       (function car)
-                                       dired-subdir-alist)))
-                                    )
+                                     (cons
+                                      (expand-file-name dired-directory)
+                                      (cdr
+                                       (nreverse
+                                        (mapcar
+                                         (function car)
+                                         dired-subdir-alist))))))
                               (let ((locals desktop-locals-to-save)
                                     (loclist (buffer-local-variables))
                                     (ll))
@@ -342,11 +497,11 @@ MODE is the major mode."
          (buf (get-buffer-create "*desktop*")))
       (set-buffer buf)
       (erase-buffer)
-      
+
       (insert desktop-header
              ";; Created " (current-time-string) "\n"
-                 ";; Emacs version " emacs-version "\n\n"
-                     ";; Global section:\n")
+             ";; Emacs version " emacs-version "\n\n"
+             ";; Global section:\n")
       (mapcar (function desktop-outvar) desktop-globals-to-save)
       (if (memq 'kill-ring desktop-globals-to-save)
          (insert "(setq kill-ring-yank-pointer (nthcdr "
@@ -377,29 +532,38 @@ MODE is the major mode."
   (interactive)
   (if desktop-dirname
       (let ((filename (concat desktop-dirname desktop-basefilename)))
-       (if (file-exists-p filename) (delete-file filename))
-       (setq desktop-dirname nil))))
+       (setq desktop-dirname nil)
+       (if (file-exists-p filename)
+           (delete-file filename)))))
 ;; ----------------------------------------------------------------------------
+;;;###autoload
 (defun desktop-read ()
-  "Read the Desktop file and the files it specifies."
+  "Read the Desktop file and the files it specifies.
+This is a no-op when Emacs is running in batch mode."
   (interactive)
-  (let ((filename))
-    (if (file-exists-p (concat "./" desktop-basefilename))
-       (setq desktop-dirname (expand-file-name "./"))
-      (if (file-exists-p (concat "~/" desktop-basefilename))
-         (setq desktop-dirname (expand-file-name "~/"))
-       (setq desktop-dirname nil)))
-    (if desktop-dirname
-       (progn
-         (load (concat desktop-dirname desktop-basefilename) t t t)
-         (run-hooks 'desktop-delay-hook)
-         (message "Desktop loaded."))
-      (desktop-clear))))
+  (if noninteractive
+      nil
+    (let ((dirs '("./" "~/")))
+      (while (and dirs
+                 (not (file-exists-p (expand-file-name
+                                      desktop-basefilename
+                                      (car dirs)))))
+       (setq dirs (cdr dirs)))
+      (setq desktop-dirname (and dirs (expand-file-name (car dirs))))
+      (if desktop-dirname
+         (progn
+           (load (expand-file-name desktop-basefilename desktop-dirname)
+                 t t t)
+           (run-hooks 'desktop-delay-hook)
+           (setq desktop-delay-hook nil)
+           (message "Desktop loaded."))
+       (desktop-clear)))))
 ;; ----------------------------------------------------------------------------
+;;;###autoload
 (defun desktop-load-default ()
-  "Load the `default' start-up library manually.  Also inhibit further loading
-of it.  Call this from your `.emacs' file to provide correct modes for
-autoloaded files."
+  "Load the `default' start-up library manually.
+Also inhibit further loading of it.  Call this from your `.emacs' file
+to provide correct modes for autoloaded files."
   (if (not inhibit-default-init)       ; safety check
       (progn
        (load "default" t t)
@@ -408,44 +572,58 @@ autoloaded files."
 ;; Note: the following functions use the dynamic variable binding in Lisp.
 ;;
 (defun desktop-buffer-info () "Load an info file."
-  (if (eq 'Info-mode mam)
+  (if (eq 'Info-mode desktop-buffer-major-mode)
       (progn
        (require 'info)
-       (Info-find-node (nth 0 misc) (nth 1 misc))
-       t)))
+       (Info-find-node (nth 0 desktop-buffer-misc) (nth 1 desktop-buffer-misc))
+       (current-buffer))))
 ;; ----------------------------------------------------------------------------
 (defun desktop-buffer-rmail () "Load an RMAIL file."
-  (if (eq 'rmail-mode mam)
-      (progn (rmail-input fn) t)))
+  (if (eq 'rmail-mode desktop-buffer-major-mode)
+      (condition-case error
+         (progn (rmail-input desktop-buffer-file-name)
+                         (if (eq major-mode 'rmail-mode)
+                             (current-buffer)
+                           rmail-buffer))
+       (file-locked
+        (kill-buffer (current-buffer))
+        'ignored))))
 ;; ----------------------------------------------------------------------------
 (defun desktop-buffer-mh () "Load a folder in the mh system."
-  (if (eq 'mh-folder-mode mam)
+  (if (eq 'mh-folder-mode desktop-buffer-major-mode)
       (progn
        (require 'mh-e)
        (mh-find-path)
-       (mh-visit-folder bn)
-       t)))
+        (mh-visit-folder desktop-buffer-name)
+       (current-buffer))))
 ;; ----------------------------------------------------------------------------
 (defun desktop-buffer-dired () "Load a directory using dired."
-  (if (eq 'dired-mode mam)
-      (progn
-       (dired (car misc))
-       (mapcar (function dired-maybe-insert-subdir) (cdr misc))
-       t)))
+  (if (eq 'dired-mode desktop-buffer-major-mode)
+      (if (file-directory-p (file-name-directory (car desktop-buffer-misc)))
+         (progn
+            (dired (car desktop-buffer-misc))
+           (mapcar 'dired-maybe-insert-subdir (cdr desktop-buffer-misc))
+           (current-buffer))
+       (message "Directory %s no longer exists." (car desktop-buffer-misc))
+       (sit-for 1)
+       'ignored)))
 ;; ----------------------------------------------------------------------------
 (defun desktop-buffer-file () "Load a file."
-  (if fn
-      (if (or (file-exists-p fn)
+  (if desktop-buffer-file-name
+      (if (or (file-exists-p desktop-buffer-file-name)
              (and desktop-missing-file-warning
                   (y-or-n-p (format
                              "File \"%s\" no longer exists. Re-create? "
-                             fn))))
-         (progn (find-file fn) t)
+                             desktop-buffer-file-name))))
+         (progn (find-file desktop-buffer-file-name) (current-buffer))
        'ignored)))
 ;; ----------------------------------------------------------------------------
 ;; Create a buffer, load its file, set is mode, ...;  called from Desktop file
 ;; only.
-(defun desktop-create-buffer (ver fn bn mam mim pt mk ro misc &optional locals)
+(defun desktop-create-buffer (ver desktop-buffer-file-name desktop-buffer-name
+                                 desktop-buffer-major-mode
+                                 mim pt mk ro desktop-buffer-misc
+                                 &optional locals)
   (let ((hlist desktop-buffer-handlers)
        (result)
        (handler))
@@ -453,41 +631,59 @@ autoloaded files."
       (setq handler (car hlist))
       (setq result (funcall handler))
       (setq hlist (cdr hlist)))
-    (if (eq result t)
-       (progn
-         (if (not (equal (buffer-name) bn))
-             (rename-buffer bn))
-         (auto-fill-mode (if (nth 0 mim) 1 0))
-         (goto-char pt)
-         (if (consp mk)
+    (when (bufferp result)
+      (set-buffer result)
+      (if (not (equal (buffer-name) desktop-buffer-name))
+         (rename-buffer desktop-buffer-name))
+      ;; minor modes
+      (cond ((equal '(t) mim)   (auto-fill-mode 1))    ; backwards compatible
+           ((equal '(nil) mim) (auto-fill-mode 0))
+           (t (mapcar #'(lambda (minor-mode)
+                          (when minor-mode (funcall minor-mode 1)))
+                          mim)))
+      (goto-char pt)
+      (if (consp mk)
+         (progn
+           (set-mark (car mk))
+           (setq mark-active (car (cdr mk))))
+       (set-mark mk))
+      ;; Never override file system if the file really is read-only marked.
+      (if ro (setq buffer-read-only ro))
+      (while locals
+       (let ((this (car locals)))
+         (if (consp this)
+             ;; an entry of this form `(symbol . value)'
              (progn
-               (set-mark (car mk))
-               (setq mark-active (car (cdr mk))))
-           (set-mark mk))
-         ;; Never override file system if the file really is read-only marked.
-         (if ro (setq buffer-read-only ro))
-         (while locals
-           (let ((this (car locals)))
-             (if (consp this)
-                 ;; an entry of this form `(symbol . value)'
-                 (progn
-                   (make-local-variable (car this))
-                   (set (car this) (cdr this)))
-               ;; an entry of the form `symbol'
-               (make-local-variable this)
-               (makunbound this)))
-           (setq locals (cdr locals)))
-         ))))
+               (make-local-variable (car this))
+               (set (car this) (cdr this)))
+           ;; an entry of the form `symbol'
+           (make-local-variable this)
+           (makunbound this)))
+       (setq locals (cdr locals))))))
 
 ;; Backward compatibility -- update parameters to 205 standards.
-(defun desktop-buffer (fn bn mam mim pt mk ro tl fc cfs cr misc)
-  (desktop-create-buffer 205 fn bn mam (cdr mim) pt mk ro misc
+(defun desktop-buffer (desktop-buffer-file-name desktop-buffer-name
+                      desktop-buffer-major-mode
+                      mim pt mk ro tl fc cfs cr desktop-buffer-misc)
+  (desktop-create-buffer 205 desktop-buffer-file-name desktop-buffer-name
+                        desktop-buffer-major-mode (cdr mim) pt mk ro
+                        desktop-buffer-misc
                         (list (cons 'truncate-lines tl)
                               (cons 'fill-column fc)
                               (cons 'case-fold-search cfs)
                               (cons 'case-replace cr)
                               (cons 'overwrite-mode (car mim)))))
 ;; ----------------------------------------------------------------------------
+
+;; If the user set desktop-enable to t with Custom,
+;; do the rest of what it takes to use desktop,
+;; but do it after finishing loading the init file.
+(add-hook 'after-init-hook
+         '(lambda ()
+            (when desktop-enable
+              (desktop-load-default)
+              (desktop-read))))
+
 (provide 'desktop)
 
 ;; desktop.el ends here.