(Info-build-node-completions, Info-search, Info-follow-reference)
[bpt/emacs.git] / lisp / desktop.el
CommitLineData
6343ed61
RS
1;;; desktop.el --- save partial status of Emacs when killed
2
813dbb2d 3;; Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
6343ed61
RS
4
5;; Author: Morten Welinder <terra@diku.dk>
b6105c76
RS
6;; Keywords: customization
7;; Favourite-brand-of-beer: None, I hate beer.
6343ed61
RS
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
b578f267
EN
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA.
6343ed61
RS
25
26;;; Commentary:
27
0b9bd504
RS
28;; Save the Desktop, i.e.,
29;; - some global variables
30;; - the list of buffers with associated files. For each buffer also
31;; - the major mode
32;; - the default directory
33;; - the point
34;; - the mark & mark-active
35;; - buffer-read-only
ec4c6f22 36;; - some local variables
6343ed61 37
478653c9 38;; To use this, first put these two lines in the bottom of your .emacs
0b9bd504
RS
39;; file (the later the better):
40;;
0b9bd504
RS
41;; (desktop-load-default)
42;; (desktop-read)
43;;
ec4c6f22 44;; Between the second and the third line you may wish to add something that
de9e2828 45;; updates the variables `desktop-globals-to-save' and/or
ec4c6f22
RS
46;; `desktop-locals-to-save'. If for instance you want to save the local
47;; variable `foobar' for every buffer in which it is local, you could add
48;; the line
49;;
50;; (setq desktop-locals-to-save (cons 'foobar desktop-locals-to-save))
51;;
f4c73d07 52;; To avoid saving excessive amounts of data you may also wish to add
ec4c6f22
RS
53;; something like the following
54;;
55;; (add-hook 'kill-emacs-hook
de9e2828 56;; '(lambda ()
ec4c6f22
RS
57;; (desktop-truncate search-ring 3)
58;; (desktop-truncate regexp-search-ring 3)))
59;;
60;; which will make sure that no more than three search items are saved. You
fa379636
KH
61;; must place this line *after* the (load "desktop") line. See also the
62;; variable desktop-save-hook.
6343ed61 63
0b9bd504
RS
64;; Start Emacs in the root directory of your "project". The desktop saver
65;; is inactive by default. You activate it by M-x desktop-save RET. When
66;; you exit the next time the above data will be saved. This ensures that
67;; all the files you were editing will be reloaded the next time you start
68;; Emacs from the same directory and that points will be set where you
ec4c6f22 69;; left them. If you save a desktop file in your home directory it will
de9e2828 70;; act as a default desktop when you start Emacs from a directory that
ec4c6f22
RS
71;; doesn't have its own. I never do this, but you may want to.
72
73;; By the way: don't use desktop.el to customize Emacs -- the file .emacs
74;; in your home directory is used for that. Saving global default values
75;; for buffers is an example of misuse.
76
0b9bd504
RS
77;; PLEASE NOTE: The kill ring can be saved as specified by the variable
78;; `desktop-globals-to-save' (by default it isn't). This may result in saving
79;; things you did not mean to keep. Use M-x desktop-clear RET.
ec4c6f22 80
fa379636
KH
81;; Thanks to hetrick@phys.uva.nl (Jim Hetrick) for useful ideas.
82;; avk@rtsg.mot.com (Andrew V. Klein) for a dired tip.
83;; chris@tecc.co.uk (Chris Boucher) for a mark tip.
84;; f89-kam@nada.kth.se (Klas Mellbourn) for a mh-e tip.
85;; kifer@sbkifer.cs.sunysb.edu (M. Kifer) for a bug hunt.
f4c73d07 86;; treese@lcs.mit.edu (Win Treese) for ange-ftp tips.
253406b9 87;; pot@cnuce.cnr.it (Francesco Potorti`) for misc. tips.
0b9bd504
RS
88;; ---------------------------------------------------------------------------
89;; TODO:
90;;
91;; Save window configuration.
92;; Recognize more minor modes.
93;; Save mark rings.
94;; Start-up with buffer-menu???
6343ed61
RS
95
96;;; Code:
97
ec4c6f22
RS
98;; Make the compilation more silent
99(eval-when-compile
100 ;; We use functions from these modules
fa379636
KH
101 ;; We can't (require 'mh-e) since that wants to load something.
102 (mapcar 'require '(info dired reporter)))
ec4c6f22 103;; ----------------------------------------------------------------------------
0b9bd504
RS
104;; USER OPTIONS -- settings you might want to play with.
105;; ----------------------------------------------------------------------------
bbf5eb28
RS
106
107(defgroup desktop nil
108 "Save status of Emacs when you exit."
109 :group 'frames)
110
813dbb2d
RS
111(defcustom desktop-enable nil
112 "*Non-nil enable Desktop to save the state of Emacs when you exit."
113 :group 'desktop
114 :type 'boolean
115 :require 'desktop
cd32a7ba
DN
116 :initialize 'custom-initialize-default
117 :version "20.3")
813dbb2d
RS
118
119(defcustom desktop-basefilename
fc715501 120 (convert-standard-filename ".emacs.desktop")
813dbb2d
RS
121 "File for Emacs desktop, not including the directory name."
122 :type 'file
123 :group 'desktop)
6343ed61 124
bbf5eb28 125(defcustom desktop-missing-file-warning nil
577ed2b2 126 "*If non-nil then desktop warns when a file no longer exists.
bbf5eb28
RS
127Otherwise it simply ignores that file."
128 :type 'boolean
129 :group 'desktop)
6343ed61 130
0b9bd504 131(defvar desktop-globals-to-save
6343ed61 132 (list 'desktop-missing-file-warning
0b9bd504 133 ;; Feature: saving kill-ring implies saving kill-ring-yank-pointer
ec4c6f22 134 ;; 'kill-ring
0b9bd504
RS
135 'tags-file-name
136 'tags-table-list
ec4c6f22
RS
137 'search-ring
138 'regexp-search-ring
de9e2828 139 'register-alist
0b9bd504 140 ;; 'desktop-globals-to-save ; Itself!
b6105c76 141 )
0e7c8611
RS
142 "List of global variables to save when killing Emacs.
143An element may be variable name (a symbol)
144or a cons cell of the form (VAR . MAX-SIZE),
145which means to truncate VAR's value to at most MAX-SIZE elements
146\(if the value is a list) before saving the value.")
6343ed61 147
ec4c6f22
RS
148(defvar desktop-locals-to-save
149 (list 'desktop-locals-to-save ; Itself! Think it over.
150 'truncate-lines
151 'case-fold-search
152 'case-replace
153 'fill-column
154 'overwrite-mode
155 'change-log-default-name
fa379636 156 'line-number-mode
ec4c6f22 157 )
577ed2b2
RS
158 "List of local variables to save for each buffer.
159The variables are saved only when they really are local.")
de9e2828 160(make-variable-buffer-local 'desktop-locals-to-save)
ec4c6f22 161
0b9bd504 162;; We skip .log files because they are normally temporary.
a7acbbe4 163;; (ftp) files because they require passwords and whatnot.
0b9bd504 164;; TAGS files to save time (tags-file-name is saved instead).
bbf5eb28 165(defcustom desktop-buffers-not-to-save
de9e2828 166 "\\(^nn\\.a[0-9]+\\|\\.log\\|(ftp)\\|^tags\\|^TAGS\\)$"
bbf5eb28
RS
167 "Regexp identifying buffers that are to be excluded from saving."
168 :type 'regexp
169 :group 'desktop)
6343ed61 170
fa379636 171;; Skip ange-ftp files
bbf5eb28 172(defcustom desktop-files-not-to-save
fa379636 173 "^/[^/:]*:"
bbf5eb28
RS
174 "Regexp identifying files whose buffers are to be excluded from saving."
175 :type 'regexp
176 :group 'desktop)
fa379636 177
bbf5eb28
RS
178(defcustom desktop-buffer-major-mode nil
179 "When desktop creates a buffer, this holds the desired Major mode."
180 :type 'symbol
181 :group 'desktop)
569c754e 182
bbf5eb28
RS
183(defcustom desktop-buffer-file-name nil
184 "When desktop creates a buffer, this holds the file name to visit."
185 :type '(choice file (const nil))
186 :group 'desktop)
569c754e 187
bbf5eb28
RS
188(defcustom desktop-buffer-name nil
189 "When desktop creates a buffer, this holds the desired buffer name."
190 :type '(choice string (const nil))
191 :group 'desktop)
569c754e 192
2699e23e
RS
193(defvar desktop-buffer-misc nil
194 "When desktop creates a buffer, this holds a list of misc info.
195It is used by the `desktop-buffer-handlers' functions.")
196
bbf5eb28 197(defcustom desktop-buffer-handlers
0b9bd504 198 '(desktop-buffer-dired
6343ed61 199 desktop-buffer-rmail
ec4c6f22 200 desktop-buffer-mh
6343ed61
RS
201 desktop-buffer-info
202 desktop-buffer-file)
577ed2b2 203 "*List of functions to call in order to create a buffer.
569c754e
RS
204The functions are called without explicit parameters but can use the
205variables `desktop-buffer-major-mode', `desktop-buffer-file-name',
206`desktop-buffer-name'.
207If one function returns non-nil, no further functions are called.
bbf5eb28
RS
208If the function returns t then the buffer is considered created."
209 :type '(repeat function)
210 :group 'desktop)
ec4c6f22
RS
211
212(defvar desktop-create-buffer-form "(desktop-create-buffer 205"
213 "Opening of form for creation of new buffers.")
fa379636 214
bbf5eb28 215(defcustom desktop-save-hook nil
813dbb2d
RS
216 "Hook run before desktop saves the state of Emacs.
217This is useful for truncating history lists, for example."
bbf5eb28
RS
218 :type 'hook
219 :group 'desktop)
813dbb2d 220
0b9bd504
RS
221;; ----------------------------------------------------------------------------
222(defvar desktop-dirname nil
6343ed61
RS
223 "The directory in which the current desktop file resides.")
224
225(defconst desktop-header
0b9bd504
RS
226";; --------------------------------------------------------------------------
227;; Desktop File for Emacs
228;; --------------------------------------------------------------------------
6343ed61 229" "*Header to place in Desktop file.")
de9e2828
RS
230
231(defvar desktop-delay-hook nil
232 "Hooks run after all buffers are loaded; intended for internal use.")
813dbb2d 233
0b9bd504 234;; ----------------------------------------------------------------------------
ec4c6f22
RS
235(defun desktop-truncate (l n)
236 "Truncate LIST to at most N elements destructively."
237 (let ((here (nthcdr (1- n) l)))
238 (if (consp here)
de9e2828 239 (setcdr here nil))))
ec4c6f22 240;; ----------------------------------------------------------------------------
f9be4574
RS
241(defcustom desktop-clear-preserve-buffers
242 '("*scratch*" "*Messages*")
243 "*Buffer names that `desktop-clear' should not delete."
244 :type '(repeat string)
245 :group 'desktop)
246
247(defun desktop-clear ()
248 "Empty the Desktop.
249This kills all buffers except for internal ones
250and those listed in `desktop-clear-preserve-buffers'."
6343ed61 251 (interactive)
fa379636
KH
252 (setq kill-ring nil
253 kill-ring-yank-pointer nil
254 search-ring nil
255 search-ring-yank-pointer nil
256 regexp-search-ring nil
257 regexp-search-ring-yank-pointer nil)
f9be4574
RS
258 (let ((buffers (buffer-list)))
259 (while buffers
260 (or (member (buffer-name (car buffers)) desktop-clear-preserve-buffers)
2f348ca3 261 (null (buffer-name (car buffers)))
f9be4574
RS
262 ;; Don't kill buffers made for internal purposes.
263 (and (not (equal (buffer-name (car buffers)) ""))
264 (eq (aref (buffer-name (car buffers)) 0) ?\ ))
265 (kill-buffer (car buffers)))
266 (setq buffers (cdr buffers))))
b6105c76 267 (delete-other-windows))
0b9bd504 268;; ----------------------------------------------------------------------------
de9e2828 269(add-hook 'kill-emacs-hook 'desktop-kill)
ec4c6f22 270
6343ed61 271(defun desktop-kill ()
0b9bd504 272 (if desktop-dirname
fa379636
KH
273 (condition-case err
274 (desktop-save desktop-dirname)
275 (file-error
276 (if (yes-or-no-p "Error while saving the desktop. Quit anyway? ")
277 nil
278 (signal (car err) (cdr err)))))))
0b9bd504 279;; ----------------------------------------------------------------------------
ed2f7fc8
RS
280(defun desktop-list* (&rest args)
281 (if (null (cdr args))
282 (car args)
283 (setq args (nreverse args))
284 (let ((value (cons (nth 1 args) (car args))))
285 (setq args (cdr (cdr args)))
286 (while args
287 (setq value (cons (car args) value))
288 (setq args (cdr args)))
289 value)))
290
de9e2828 291(defun desktop-internal-v2s (val)
577ed2b2
RS
292 "Convert VALUE to a pair (QUOTE . TXT); (eval (read TXT)) gives VALUE.
293TXT is a string that when read and evaluated yields value.
294QUOTE may be `may' (value may be quoted),
295`must' (values must be quoted), or nil (value may not be quoted)."
de9e2828 296 (cond
e2247420 297 ((or (numberp val) (null val) (eq t val))
de9e2828 298 (cons 'may (prin1-to-string val)))
e2247420 299 ((stringp val)
95bf6435
RS
300 (let ((copy (copy-sequence val)))
301 (set-text-properties 0 (length copy) nil copy)
302 ;; Get rid of text properties because we cannot read them
303 (cons 'may (prin1-to-string copy))))
de9e2828
RS
304 ((symbolp val)
305 (cons 'must (prin1-to-string val)))
306 ((vectorp val)
307 (let* ((special nil)
308 (pass1 (mapcar
309 (lambda (el)
310 (let ((res (desktop-internal-v2s el)))
311 (if (null (car res))
312 (setq special t))
313 res))
314 val)))
315 (if special
316 (cons nil (concat "(vector "
317 (mapconcat (lambda (el)
318 (if (eq (car el) 'must)
319 (concat "'" (cdr el))
320 (cdr el)))
321 pass1
322 " ")
323 ")"))
324 (cons 'may (concat "[" (mapconcat 'cdr pass1 " ") "]")))))
325 ((consp val)
b4929f75
RS
326 (let ((p val)
327 newlist
ed2f7fc8 328 use-list*
b4929f75
RS
329 anynil)
330 (while (consp p)
331 (let ((q.txt (desktop-internal-v2s (car p))))
332 (or anynil (setq anynil (null (car q.txt))))
333 (setq newlist (cons q.txt newlist)))
334 (setq p (cdr p)))
335 (if p
336 (let ((last (desktop-internal-v2s p))
337 (el (car newlist)))
ed2f7fc8
RS
338 (or anynil (setq anynil (null (car last))))
339 (or anynil
340 (setq newlist (cons '(must . ".") newlist)))
341 (setq use-list* t)
342 (setq newlist (cons last newlist))))
b4929f75
RS
343 (setq newlist (nreverse newlist))
344 (if anynil
345 (cons nil
ed2f7fc8 346 (concat (if use-list* "(desktop-list* " "(list ")
b4929f75
RS
347 (mapconcat (lambda (el)
348 (if (eq (car el) 'must)
349 (concat "'" (cdr el))
350 (cdr el)))
351 newlist
352 " ")
353 ")"))
354 (cons 'must
355 (concat "(" (mapconcat 'cdr newlist " ") ")")))))
de9e2828
RS
356 ((subrp val)
357 (cons nil (concat "(symbol-function '"
358 (substring (prin1-to-string val) 7 -1)
359 ")")))
360 ((markerp val)
361 (let ((pos (prin1-to-string (marker-position val)))
362 (buf (prin1-to-string (buffer-name (marker-buffer val)))))
363 (cons nil (concat "(let ((mk (make-marker)))"
364 " (add-hook 'desktop-delay-hook"
365 " (list 'lambda '() (list 'set-marker mk "
366 pos " (get-buffer " buf ")))) mk)"))))
367 (t ; save as text
fa379636 368 (cons 'may "\"Unprintable entity\""))))
de9e2828 369
ec4c6f22 370(defun desktop-value-to-string (val)
577ed2b2
RS
371 "Convert VALUE to a string that when read evaluates to the same value.
372Not all types of values are supported."
de9e2828
RS
373 (let* ((print-escape-newlines t)
374 (float-output-format nil)
375 (quote.txt (desktop-internal-v2s val))
376 (quote (car quote.txt))
377 (txt (cdr quote.txt)))
378 (if (eq quote 'must)
379 (concat "'" txt)
380 txt)))
ec4c6f22 381;; ----------------------------------------------------------------------------
0e7c8611
RS
382(defun desktop-outvar (varspec)
383 "Output a setq statement for variable VAR to the desktop file.
384The argument VARSPEC may be the variable name VAR (a symbol),
385or a cons cell of the form (VAR . MAX-SIZE),
386which means to truncate VAR's value to at most MAX-SIZE elements
387\(if the value is a list) before saving the value."
388 (let (var size)
389 (if (consp varspec)
390 (setq var (car varspec) size (cdr varspec))
391 (setq var varspec))
392 (if (boundp var)
393 (progn
394 (if (and (integerp size)
395 (> size 0)
396 (listp (eval var)))
397 (desktop-truncate (eval var) size))
398 (insert "(setq "
399 (symbol-name var)
400 " "
401 (desktop-value-to-string (symbol-value var))
402 ")\n")))))
0b9bd504 403;; ----------------------------------------------------------------------------
ec4c6f22 404(defun desktop-save-buffer-p (filename bufname mode &rest dummy)
b6105c76 405 "Return t if the desktop should record a particular buffer for next startup.
0b9bd504 406FILENAME is the visited file name, BUFNAME is the buffer name, and
6343ed61 407MODE is the major mode."
fa379636
KH
408 (let ((case-fold-search nil))
409 (or (and filename
410 (not (string-match desktop-buffers-not-to-save bufname))
411 (not (string-match desktop-files-not-to-save filename)))
412 (and (eq mode 'dired-mode)
413 (save-excursion
414 (set-buffer (get-buffer bufname))
415 (not (string-match desktop-files-not-to-save
416 default-directory))))
417 (and (null filename)
418 (memq mode '(Info-mode rmail-mode))))))
0b9bd504 419;; ----------------------------------------------------------------------------
6343ed61
RS
420(defun desktop-save (dirname)
421 "Save the Desktop file. Parameter DIRNAME specifies where to save desktop."
422 (interactive "DDirectory to save desktop file in: ")
fa379636 423 (run-hooks 'desktop-save-hook)
6343ed61 424 (save-excursion
0b9bd504 425 (let ((filename (expand-file-name
6343ed61 426 (concat dirname desktop-basefilename)))
0b9bd504
RS
427 (info (nreverse
428 (mapcar
6343ed61
RS
429 (function (lambda (b)
430 (set-buffer b)
0b9bd504 431 (list
6343ed61
RS
432 (buffer-file-name)
433 (buffer-name)
ec4c6f22 434 major-mode
201006c4
KH
435 (list ; list explaining minor modes
436 (not (null auto-fill-function)))
6343ed61 437 (point)
de9e2828 438 (list (mark t) mark-active)
6343ed61 439 buffer-read-only
ec4c6f22
RS
440 (cond ((eq major-mode 'Info-mode)
441 (list Info-current-file
442 Info-current-node))
443 ((eq major-mode 'dired-mode)
f4c73d07
RS
444 (cons
445 (expand-file-name dired-directory)
446 (cdr
447 (nreverse
448 (mapcar
449 (function car)
450 dired-subdir-alist))))))
ec4c6f22
RS
451 (let ((locals desktop-locals-to-save)
452 (loclist (buffer-local-variables))
453 (ll))
454 (while locals
455 (let ((here (assq (car locals) loclist)))
456 (if here
457 (setq ll (cons here ll))
458 (if (member (car locals) loclist)
459 (setq ll (cons (car locals) ll)))))
460 (setq locals (cdr locals)))
461 ll)
6343ed61
RS
462 )))
463 (buffer-list))))
464 (buf (get-buffer-create "*desktop*")))
465 (set-buffer buf)
466 (erase-buffer)
fa379636 467
0b9bd504
RS
468 (insert desktop-header
469 ";; Created " (current-time-string) "\n"
fa379636
KH
470 ";; Emacs version " emacs-version "\n\n"
471 ";; Global section:\n")
6343ed61
RS
472 (mapcar (function desktop-outvar) desktop-globals-to-save)
473 (if (memq 'kill-ring desktop-globals-to-save)
0b9bd504
RS
474 (insert "(setq kill-ring-yank-pointer (nthcdr "
475 (int-to-string
6343ed61
RS
476 (- (length kill-ring) (length kill-ring-yank-pointer)))
477 " kill-ring))\n"))
478
0b9bd504 479 (insert "\n;; Buffer section:\n")
de9e2828
RS
480 (mapcar
481 (function (lambda (l)
482 (if (apply 'desktop-save-buffer-p l)
483 (progn
484 (insert desktop-create-buffer-form)
485 (mapcar
486 (function (lambda (e)
487 (insert "\n "
488 (desktop-value-to-string e))))
489 l)
490 (insert ")\n\n")))))
491 info)
6343ed61
RS
492 (setq default-directory dirname)
493 (if (file-exists-p filename) (delete-file filename))
494 (write-region (point-min) (point-max) filename nil 'nomessage)))
495 (setq desktop-dirname dirname))
0b9bd504 496;; ----------------------------------------------------------------------------
6343ed61
RS
497(defun desktop-remove ()
498 "Delete the Desktop file and inactivate the desktop system."
499 (interactive)
500 (if desktop-dirname
501 (let ((filename (concat desktop-dirname desktop-basefilename)))
fa379636
KH
502 (setq desktop-dirname nil)
503 (if (file-exists-p filename)
504 (delete-file filename)))))
0b9bd504 505;; ----------------------------------------------------------------------------
478653c9 506;;;###autoload
6343ed61 507(defun desktop-read ()
253406b9
RS
508 "Read the Desktop file and the files it specifies.
509This is a no-op when Emacs is running in batch mode."
6343ed61 510 (interactive)
253406b9
RS
511 (if noninteractive
512 nil
513 (let ((dirs '("./" "~/")))
514 (while (and dirs
515 (not (file-exists-p (expand-file-name
516 desktop-basefilename
517 (car dirs)))))
518 (setq dirs (cdr dirs)))
519 (setq desktop-dirname (and dirs (expand-file-name (car dirs))))
520 (if desktop-dirname
521 (progn
522 (load (expand-file-name desktop-basefilename desktop-dirname)
523 t t t)
524 (run-hooks 'desktop-delay-hook)
525 (setq desktop-delay-hook nil)
526 (message "Desktop loaded."))
527 (desktop-clear)))))
0b9bd504 528;; ----------------------------------------------------------------------------
478653c9 529;;;###autoload
6343ed61 530(defun desktop-load-default ()
577ed2b2
RS
531 "Load the `default' start-up library manually.
532Also inhibit further loading of it. Call this from your `.emacs' file
533to provide correct modes for autoloaded files."
0b9bd504 534 (if (not inhibit-default-init) ; safety check
6343ed61
RS
535 (progn
536 (load "default" t t)
537 (setq inhibit-default-init t))))
0b9bd504
RS
538;; ----------------------------------------------------------------------------
539;; Note: the following functions use the dynamic variable binding in Lisp.
0b9bd504 540;;
6343ed61 541(defun desktop-buffer-info () "Load an info file."
569c754e 542 (if (eq 'Info-mode desktop-buffer-major-mode)
6343ed61
RS
543 (progn
544 (require 'info)
2699e23e 545 (Info-find-node (nth 0 desktop-buffer-misc) (nth 1 desktop-buffer-misc))
608b9ed2 546 (current-buffer))))
0b9bd504 547;; ----------------------------------------------------------------------------
b6105c76 548(defun desktop-buffer-rmail () "Load an RMAIL file."
569c754e 549 (if (eq 'rmail-mode desktop-buffer-major-mode)
e36d00d4 550 (condition-case error
608b9ed2
RS
551 (progn (rmail-input desktop-buffer-file-name)
552 (if (eq major-mode 'rmail-mode)
553 (current-buffer)
554 rmail-buffer))
e2247420
RS
555 (file-locked
556 (kill-buffer (current-buffer))
557 'ignored))))
0b9bd504 558;; ----------------------------------------------------------------------------
ec4c6f22 559(defun desktop-buffer-mh () "Load a folder in the mh system."
569c754e 560 (if (eq 'mh-folder-mode desktop-buffer-major-mode)
ec4c6f22
RS
561 (progn
562 (require 'mh-e)
563 (mh-find-path)
608b9ed2
RS
564 (mh-visit-folder desktop-buffer-name)
565 (current-buffer))))
ec4c6f22 566;; ----------------------------------------------------------------------------
6343ed61 567(defun desktop-buffer-dired () "Load a directory using dired."
569c754e 568 (if (eq 'dired-mode desktop-buffer-major-mode)
2699e23e 569 (if (file-directory-p (file-name-directory (car desktop-buffer-misc)))
fa379636 570 (progn
608b9ed2 571 (dired (car desktop-buffer-misc))
581bba23 572 (mapcar 'dired-maybe-insert-subdir (cdr desktop-buffer-misc))
608b9ed2 573 (current-buffer))
2699e23e 574 (message "Directory %s no longer exists." (car desktop-buffer-misc))
fa379636
KH
575 (sit-for 1)
576 'ignored)))
0b9bd504 577;; ----------------------------------------------------------------------------
6343ed61 578(defun desktop-buffer-file () "Load a file."
569c754e
RS
579 (if desktop-buffer-file-name
580 (if (or (file-exists-p desktop-buffer-file-name)
6343ed61 581 (and desktop-missing-file-warning
0b9bd504
RS
582 (y-or-n-p (format
583 "File \"%s\" no longer exists. Re-create? "
569c754e 584 desktop-buffer-file-name))))
608b9ed2 585 (progn (find-file desktop-buffer-file-name) (current-buffer))
6343ed61 586 'ignored)))
0b9bd504
RS
587;; ----------------------------------------------------------------------------
588;; Create a buffer, load its file, set is mode, ...; called from Desktop file
6343ed61 589;; only.
569c754e
RS
590(defun desktop-create-buffer (ver desktop-buffer-file-name desktop-buffer-name
591 desktop-buffer-major-mode
2699e23e 592 mim pt mk ro desktop-buffer-misc &optional locals)
6343ed61
RS
593 (let ((hlist desktop-buffer-handlers)
594 (result)
595 (handler))
596 (while (and (not result) hlist)
597 (setq handler (car hlist))
598 (setq result (funcall handler))
599 (setq hlist (cdr hlist)))
608b9ed2
RS
600 (when (bufferp result)
601 (set-buffer result)
602 (if (not (equal (buffer-name) desktop-buffer-name))
603 (rename-buffer desktop-buffer-name))
201006c4 604 (auto-fill-mode (if (nth 0 mim) 1 0))
7c3d2af2 605 (goto-char pt)
608b9ed2
RS
606 (if (consp mk)
607 (progn
608 (set-mark (car mk))
609 (setq mark-active (car (cdr mk))))
610 (set-mark mk))
611 ;; Never override file system if the file really is read-only marked.
612 (if ro (setq buffer-read-only ro))
613 (while locals
614 (let ((this (car locals)))
615 (if (consp this)
616 ;; an entry of this form `(symbol . value)'
0b9bd504 617 (progn
608b9ed2
RS
618 (make-local-variable (car this))
619 (set (car this) (cdr this)))
620 ;; an entry of the form `symbol'
621 (make-local-variable this)
622 (makunbound this)))
623 (setq locals (cdr locals))))))
ec4c6f22
RS
624
625;; Backward compatibility -- update parameters to 205 standards.
569c754e
RS
626(defun desktop-buffer (desktop-buffer-file-name desktop-buffer-name
627 desktop-buffer-major-mode
2699e23e 628 mim pt mk ro tl fc cfs cr desktop-buffer-misc)
569c754e 629 (desktop-create-buffer 205 desktop-buffer-file-name desktop-buffer-name
2699e23e
RS
630 desktop-buffer-major-mode (cdr mim) pt mk ro
631 desktop-buffer-misc
ec4c6f22
RS
632 (list (cons 'truncate-lines tl)
633 (cons 'fill-column fc)
634 (cons 'case-fold-search cfs)
635 (cons 'case-replace cr)
636 (cons 'overwrite-mode (car mim)))))
0b9bd504 637;; ----------------------------------------------------------------------------
813dbb2d
RS
638
639;; If the user set desktop-enable to t with Custom,
640;; do the rest of what it takes to use desktop,
641;; but do it after finishing loading the init file.
642(add-hook 'after-init-hook
643 '(lambda ()
644 (when desktop-enable
645 (desktop-load-default)
646 (desktop-read))))
647
ab1d55ea 648(provide 'desktop)
6343ed61
RS
649
650;; desktop.el ends here.