- (if desktop-dirname
- (progn
- (desktop-save desktop-dirname))))
-
-;(defun kill-emacs (&optional query)
-; "End this Emacs session.
-;Prefix ARG or optional first ARG non-nil means exit with no questions asked,
-;even if there are unsaved buffers. If Emacs is running non-interactively
-;and ARG is an integer, then Emacs exits with ARG as its exit code.
-;
-;If the variable `desktop-dirname' is non-nil,
-;the function desktop-save will be called first."
-; (interactive "P")
-; (if desktop-dirname (desktop-save desktop-dirname))
-; (original-kill-emacs query))
-; ---------------------------------------------------------------------------
-(defun desktop-outvar (VAR)
- "Output a setq statement for VAR to the desktop file."
- (if (boundp VAR)
- (progn
- (insert "(setq ")
- (prin1 VAR (current-buffer))
- (insert " '")
- (prin1 (symbol-value VAR) (current-buffer))
- (insert ")\n"))))
-; ---------------------------------------------------------------------------
-(defun desktop-save-buffer-p (filename bufname mode)
- "Return t if should record a particular buffer for next startup.
-FILENAME is the visited file name, BUFNAME is the buffer name, and
+ (if 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); (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) (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)
+ (let* ((special nil)
+ (pass1 (mapcar
+ (lambda (el)
+ (let ((res (desktop-internal-v2s el)))
+ (if (null (car res))
+ (setq special t))
+ res))
+ val)))
+ (if special
+ (cons nil (concat "(vector "
+ (mapconcat (lambda (el)
+ (if (eq (car el) 'must)
+ (concat "'" (cdr el))
+ (cdr el)))
+ pass1
+ " ")
+ ")"))
+ (cons 'may (concat "[" (mapconcat 'cdr pass1 " ") "]")))))
+ ((consp val)
+ (let ((p val)
+ newlist
+ use-list*
+ anynil)
+ (while (consp p)
+ (let ((q.txt (desktop-internal-v2s (car p))))
+ (or anynil (setq anynil (null (car q.txt))))
+ (setq newlist (cons q.txt newlist)))
+ (setq p (cdr p)))
+ (if p
+ (let ((last (desktop-internal-v2s p))
+ (el (car newlist)))
+ (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 (if use-list* "(desktop-list* " "(list ")
+ (mapconcat (lambda (el)
+ (if (eq (car el) 'must)
+ (concat "'" (cdr el))
+ (cdr el)))
+ newlist
+ " ")
+ ")"))
+ (cons 'must
+ (concat "(" (mapconcat 'cdr newlist " ") ")")))))
+ ((subrp val)
+ (cons nil (concat "(symbol-function '"
+ (substring (prin1-to-string val) 7 -1)
+ ")")))
+ ((markerp val)
+ (let ((pos (prin1-to-string (marker-position val)))
+ (buf (prin1-to-string (buffer-name (marker-buffer val)))))
+ (cons nil (concat "(let ((mk (make-marker)))"
+ " (add-hook 'desktop-delay-hook"
+ " (list 'lambda '() (list 'set-marker mk "
+ pos " (get-buffer " buf ")))) mk)"))))
+ (t ; save as text
+ (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."
+ (let* ((print-escape-newlines t)
+ (float-output-format nil)
+ (quote.txt (desktop-internal-v2s val))
+ (quote (car quote.txt))
+ (txt (cdr quote.txt)))
+ (if (eq quote 'must)
+ (concat "'" txt)
+ txt)))
+;; ----------------------------------------------------------------------------
+(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