]> code.delx.au - gnu-emacs/blobdiff - lisp/desktop.el
Fix puny-encoding all-non-ASCII domains
[gnu-emacs] / lisp / desktop.el
index bad0073fbbab4dbf961f5ded557c11ca3e396553..e95a8c9288b4ab41a56150005d84d1b8f6efcf8d 100644 (file)
@@ -1,6 +1,7 @@
 ;;; desktop.el --- save partial status of Emacs when killed -*- lexical-binding: t -*-
 
 ;;; desktop.el --- save partial status of Emacs when killed -*- lexical-binding: t -*-
 
-;; Copyright (C) 1993-1995, 1997, 2000-2014 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 1997, 2000-2015 Free Software Foundation,
+;; Inc.
 
 ;; Author: Morten Welinder <terra@diku.dk>
 ;; Keywords: convenience
 
 ;; Author: Morten Welinder <terra@diku.dk>
 ;; Keywords: convenience
 ;;    (add-to-list 'desktop-minor-mode-handlers
 ;;                 '(bar-mode . bar-desktop-restore))
 
 ;;    (add-to-list 'desktop-minor-mode-handlers
 ;;                 '(bar-mode . bar-desktop-restore))
 
-;; in the module itself, and make sure that the mode function is
-;; autoloaded.  See the docstrings of `desktop-buffer-mode-handlers' and
+;; in the module itself.  The mode function must either be autoloaded,
+;; or of the form "foobar-mode" and defined in library "foobar", so that
+;; desktop can guess how to load its definition.
+;; See the docstrings of `desktop-buffer-mode-handlers' and
 ;; `desktop-minor-mode-handlers' for more info.
 
 ;; Minor modes.
 ;; `desktop-minor-mode-handlers' for more info.
 
 ;; Minor modes.
 (require 'cl-lib)
 (require 'frameset)
 
 (require 'cl-lib)
 (require 'frameset)
 
-(defvar desktop-file-version "206"
+(defvar desktop-file-version "208"
   "Version number of desktop file format.
 Written into the desktop file and used at desktop read to provide
 backward compatibility.")
   "Version number of desktop file format.
 Written into the desktop file and used at desktop read to provide
 backward compatibility.")
@@ -162,8 +165,8 @@ one session to another.  In particular, Emacs will save the desktop when
 it exits (this may prompt you; see the option `desktop-save').  The next
 time Emacs starts, if this mode is active it will restore the desktop.
 
 it exits (this may prompt you; see the option `desktop-save').  The next
 time Emacs starts, if this mode is active it will restore the desktop.
 
-To manually save the desktop at any time, use the command `M-x desktop-save'.
-To load it, use `M-x desktop-read'.
+To manually save the desktop at any time, use the command `\\[desktop-save]'.
+To load it, use `\\[desktop-read]'.
 
 Once a desktop file exists, Emacs will auto-save it according to the
 option `desktop-auto-save-timeout'.
 
 Once a desktop file exists, Emacs will auto-save it according to the
 option `desktop-auto-save-timeout'.
@@ -519,7 +522,9 @@ code like
    (add-to-list 'desktop-buffer-mode-handlers
                 '(foo-mode . foo-restore-desktop-buffer))
 
    (add-to-list 'desktop-buffer-mode-handlers
                 '(foo-mode . foo-restore-desktop-buffer))
 
-Furthermore the major mode function must be autoloaded.")
+The major mode function must either be autoloaded, or of the form
+\"foobar-mode\" and defined in library \"foobar\", so that desktop
+can guess how to load the mode's definition.")
 
 ;;;###autoload
 (put 'desktop-buffer-mode-handlers 'risky-local-variable t)
 
 ;;;###autoload
 (put 'desktop-buffer-mode-handlers 'risky-local-variable t)
@@ -584,7 +589,9 @@ code like
    (add-to-list 'desktop-minor-mode-handlers
                 '(foo-mode . foo-desktop-restore))
 
    (add-to-list 'desktop-minor-mode-handlers
                 '(foo-mode . foo-desktop-restore))
 
-Furthermore the minor mode function must be autoloaded.
+The minor mode function must either be autoloaded, or of the form
+\"foobar-mode\" and defined in library \"foobar\", so that desktop
+can guess how to load the mode's definition.
 
 See also `desktop-minor-mode-table'.")
 
 
 See also `desktop-minor-mode-table'.")
 
@@ -628,6 +635,18 @@ Only valid during frame saving & restoring; intended for internal use.")
   "When the desktop file was last modified to the knowledge of this Emacs.
 Used to detect desktop file conflicts.")
 
   "When the desktop file was last modified to the knowledge of this Emacs.
 Used to detect desktop file conflicts.")
 
+(defvar desktop-var-serdes-funs
+  (list (list
+        'mark-ring
+        (lambda (mr)
+          (mapcar #'marker-position mr))
+        (lambda (mr)
+          (mapcar #'copy-marker mr))))
+  "Table of serialization/deserialization functions for variables.
+Each record is a list of form: (var serializer deserializer).
+These records can be freely reordered, deleted, or new ones added.
+However, for compatibility, don't modify the functions for existing records.")
+
 (defun desktop-owner (&optional dirname)
   "Return the PID of the Emacs process that owns the desktop file in DIRNAME.
 Return nil if no desktop file found or no Emacs process is using it.
 (defun desktop-owner (&optional dirname)
   "Return the PID of the Emacs process that owns the desktop file in DIRNAME.
 Return nil if no desktop file found or no Emacs process is using it.
@@ -743,6 +762,24 @@ is nil, ask the user where to save the desktop."
 
 ;; ----------------------------------------------------------------------------
 (defun desktop-buffer-info (buffer)
 
 ;; ----------------------------------------------------------------------------
 (defun desktop-buffer-info (buffer)
+  "Return information describing BUFFER.
+This function is not pure, as BUFFER is made current with
+`set-buffer'.
+
+Returns a list of all the necessary information to recreate the
+buffer, which is (in order):
+
+    `uniquify-buffer-base-name';
+    `buffer-file-name';
+    `buffer-name';
+    `major-mode';
+    list of minor-modes,;
+    `point';
+    `mark';
+    `buffer-read-only';
+    auxiliary information given by `desktop-save-buffer';
+    local variables;
+    auxiliary information given by `desktop-var-serdes-funs'."
   (set-buffer buffer)
   (list
    ;; base name of the buffer; replaces the buffer name if managed by uniquify
   (set-buffer buffer)
   (list
    ;; base name of the buffer; replaces the buffer name if managed by uniquify
@@ -753,16 +790,13 @@ is nil, ask the user where to save the desktop."
    major-mode
    ;; minor modes
    (let (ret)
    major-mode
    ;; minor modes
    (let (ret)
-     (mapc
-      #'(lambda (minor-mode)
-         (and (boundp minor-mode)
-              (symbol-value minor-mode)
-              (let* ((special (assq minor-mode desktop-minor-mode-table))
-                     (value (cond (special (cadr special))
-                                  ((functionp minor-mode) minor-mode))))
-                (when value (add-to-list 'ret value)))))
-      (mapcar #'car minor-mode-alist))
-     ret)
+     (dolist (minor-mode (mapcar #'car minor-mode-alist) ret)
+       (and (boundp minor-mode)
+            (symbol-value minor-mode)
+            (let* ((special (assq minor-mode desktop-minor-mode-table))
+                   (value (cond (special (cadr special))
+                                ((functionp minor-mode) minor-mode))))
+              (when value (cl-pushnew value ret))))))
    ;; point and mark, and read-only status
    (point)
    (list (mark t) mark-active)
    ;; point and mark, and read-only status
    (point)
    (list (mark t) mark-active)
@@ -779,7 +813,12 @@ is nil, ask the user where to save the desktop."
                (push here ll))
               ((member local loclist)
                (push local ll)))))
                (push here ll))
               ((member local loclist)
                (push local ll)))))
-     ll)))
+     ll)
+   (mapcar (lambda (record)
+            (let ((var (car record)))
+              (list var
+                    (funcall (cadr record) (symbol-value var)))))
+          desktop-var-serdes-funs)))
 
 ;; ----------------------------------------------------------------------------
 (defun desktop--v2s (value)
 
 ;; ----------------------------------------------------------------------------
 (defun desktop--v2s (value)
@@ -940,7 +979,7 @@ Frames with a non-nil `desktop-dont-save' parameter are not saved."
        (and desktop-restore-frames
             (frameset-save nil
                            :app desktop--app-id
        (and desktop-restore-frames
             (frameset-save nil
                            :app desktop--app-id
-                           :name (concat user-login-name "@" system-name)
+                           :name (concat user-login-name "@" (system-name))
                            :predicate #'desktop--check-dont-save))))
 
 ;;;###autoload
                            :predicate #'desktop--check-dont-save))))
 
 ;;;###autoload
@@ -1118,7 +1157,8 @@ It returns t if a desktop file was loaded, nil otherwise."
              (desktop-buffer-fail-count 0)
              (owner (desktop-owner))
              ;; Avoid desktop saving during evaluation of desktop buffer.
              (desktop-buffer-fail-count 0)
              (owner (desktop-owner))
              ;; Avoid desktop saving during evaluation of desktop buffer.
-             (desktop-save nil))
+             (desktop-save nil)
+             (desktop-autosave-was-enabled))
          (if (and owner
                   (memq desktop-load-locked-desktop '(nil ask))
                   (or (null desktop-load-locked-desktop)
          (if (and owner
                   (memq desktop-load-locked-desktop '(nil ask))
                   (or (null desktop-load-locked-desktop)
@@ -1134,6 +1174,8 @@ Using it may cause conflicts.  Use it anyway? " owner)))))
            ;; Temporarily disable the autosave that will leave it
            ;; disabled when loading the desktop fails with errors,
            ;; thus not overwriting the desktop with broken contents.
            ;; Temporarily disable the autosave that will leave it
            ;; disabled when loading the desktop fails with errors,
            ;; thus not overwriting the desktop with broken contents.
+           (setq desktop-autosave-was-enabled
+                 (memq 'desktop-auto-save-set-timer window-configuration-change-hook))
            (desktop-auto-save-disable)
            ;; Evaluate desktop buffer and remember when it was modified.
            (load (desktop-full-file-name) t t t)
            (desktop-auto-save-disable)
            ;; Evaluate desktop buffer and remember when it was modified.
            (load (desktop-full-file-name) t t t)
@@ -1187,10 +1229,9 @@ Using it may cause conflicts.  Use it anyway? " owner)))))
                                  (set-window-prev-buffers window nil)
                                  (set-window-next-buffers window nil))))
            (setq desktop-saved-frameset nil)
                                  (set-window-prev-buffers window nil)
                                  (set-window-next-buffers window nil))))
            (setq desktop-saved-frameset nil)
-           (desktop-auto-save-enable)
+           (if desktop-autosave-was-enabled (desktop-auto-save-enable))
            t))
       ;; No desktop file found.
            t))
       ;; No desktop file found.
-      (desktop-clear)
       (let ((default-directory desktop-dirname))
         (run-hooks 'desktop-no-desktop-file-hook))
       (message "No desktop file.")
       (let ((default-directory desktop-dirname))
         (run-hooks 'desktop-no-desktop-file-hook))
       (message "No desktop file.")
@@ -1317,9 +1358,18 @@ after that many seconds of idle time."
       nil)))
 
 (defun desktop-load-file (function)
       nil)))
 
 (defun desktop-load-file (function)
-  "Load the file where auto loaded FUNCTION is defined."
-  (when (fboundp function)
-    (autoload-do-load (symbol-function function) function)))
+  "Load the file where auto loaded FUNCTION is defined.
+If FUNCTION is not currently defined, guess the library that defines it
+and try to load that."
+  (if (fboundp function)
+      (autoload-do-load (symbol-function function) function)
+    ;; Guess that foobar-mode is defined in foobar.
+    ;; TODO rather than guessing or requiring an autoload, the desktop
+    ;; file should record the name of the library.
+    (let ((name (symbol-name function)))
+      (if (string-match "\\`\\(.*\\)-mode\\'" name)
+          (with-demoted-errors "Require error in desktop-load-file: %S"
+              (require (intern (match-string 1 name)) nil t))))))
 
 ;; ----------------------------------------------------------------------------
 ;; Create a buffer, load its file, set its mode, ...;
 
 ;; ----------------------------------------------------------------------------
 ;; Create a buffer, load its file, set its mode, ...;
@@ -1336,7 +1386,9 @@ after that many seconds of idle time."
      buffer-readonly
      buffer-misc
      &optional
      buffer-readonly
      buffer-misc
      &optional
-     buffer-locals)
+     buffer-locals
+     compacted-vars
+     &rest _unsupported)
 
   (let ((desktop-file-version      file-version)
        (desktop-buffer-file-name   buffer-filename)
 
   (let ((desktop-file-version      file-version)
        (desktop-buffer-file-name   buffer-filename)
@@ -1426,7 +1478,14 @@ after that many seconds of idle time."
                  (set (car this) (cdr this)))
              ;; An entry of the form `symbol'.
              (make-local-variable this)
                  (set (car this) (cdr this)))
              ;; An entry of the form `symbol'.
              (make-local-variable this)
-             (makunbound this))))))))
+             (makunbound this)))
+         (unless (< desktop-file-version 208) ; Don't misinterpret any old custom args
+           (dolist (record compacted-vars)
+             (let*
+                 ((var (car record))
+                  (deser-fun (nth 2 (assq var desktop-var-serdes-funs))))
+               (if deser-fun (set var (funcall deser-fun (cadr record))))))))
+       result))))
 
 ;; ----------------------------------------------------------------------------
 ;; Backward compatibility -- update parameters to 205 standards.
 
 ;; ----------------------------------------------------------------------------
 ;; Backward compatibility -- update parameters to 205 standards.
@@ -1528,13 +1587,6 @@ If there are no buffers left to create, kill the timer."
         (desktop-read)
         (setq inhibit-startup-screen t)))))
 
         (desktop-read)
         (setq inhibit-startup-screen t)))))
 
-;; So we can restore vc-dir buffers.
-(autoload 'vc-dir-mode "vc-dir" nil t)
-
 (provide 'desktop)
 
 ;;; desktop.el ends here
 (provide 'desktop)
 
 ;;; desktop.el ends here
-
-;; Local Variables:
-;; coding: utf-8
-;; End: