(main) [HAVE_NTGUI]: Invoke syms_of_fontset().
[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
9e265777
TTN
435 (let (ret)
436 (mapcar #'(lambda (minor-mode)
437 (and (symbol-value minor-mode)
438 (setq ret (cons minor-mode
439 ret))))
440 (mapcar #'car minor-mode-alist))
441 ret)
6343ed61 442 (point)
de9e2828 443 (list (mark t) mark-active)
6343ed61 444 buffer-read-only
ec4c6f22
RS
445 (cond ((eq major-mode 'Info-mode)
446 (list Info-current-file
447 Info-current-node))
448 ((eq major-mode 'dired-mode)
f4c73d07
RS
449 (cons
450 (expand-file-name dired-directory)
451 (cdr
452 (nreverse
453 (mapcar
454 (function car)
455 dired-subdir-alist))))))
ec4c6f22
RS
456 (let ((locals desktop-locals-to-save)
457 (loclist (buffer-local-variables))
458 (ll))
459 (while locals
460 (let ((here (assq (car locals) loclist)))
461 (if here
462 (setq ll (cons here ll))
463 (if (member (car locals) loclist)
464 (setq ll (cons (car locals) ll)))))
465 (setq locals (cdr locals)))
466 ll)
6343ed61
RS
467 )))
468 (buffer-list))))
469 (buf (get-buffer-create "*desktop*")))
470 (set-buffer buf)
471 (erase-buffer)
fa379636 472
0b9bd504
RS
473 (insert desktop-header
474 ";; Created " (current-time-string) "\n"
fa379636
KH
475 ";; Emacs version " emacs-version "\n\n"
476 ";; Global section:\n")
6343ed61
RS
477 (mapcar (function desktop-outvar) desktop-globals-to-save)
478 (if (memq 'kill-ring desktop-globals-to-save)
0b9bd504
RS
479 (insert "(setq kill-ring-yank-pointer (nthcdr "
480 (int-to-string
6343ed61
RS
481 (- (length kill-ring) (length kill-ring-yank-pointer)))
482 " kill-ring))\n"))
483
0b9bd504 484 (insert "\n;; Buffer section:\n")
de9e2828
RS
485 (mapcar
486 (function (lambda (l)
487 (if (apply 'desktop-save-buffer-p l)
488 (progn
489 (insert desktop-create-buffer-form)
490 (mapcar
491 (function (lambda (e)
492 (insert "\n "
493 (desktop-value-to-string e))))
494 l)
495 (insert ")\n\n")))))
496 info)
6343ed61
RS
497 (setq default-directory dirname)
498 (if (file-exists-p filename) (delete-file filename))
499 (write-region (point-min) (point-max) filename nil 'nomessage)))
500 (setq desktop-dirname dirname))
0b9bd504 501;; ----------------------------------------------------------------------------
6343ed61
RS
502(defun desktop-remove ()
503 "Delete the Desktop file and inactivate the desktop system."
504 (interactive)
505 (if desktop-dirname
506 (let ((filename (concat desktop-dirname desktop-basefilename)))
fa379636
KH
507 (setq desktop-dirname nil)
508 (if (file-exists-p filename)
509 (delete-file filename)))))
0b9bd504 510;; ----------------------------------------------------------------------------
478653c9 511;;;###autoload
6343ed61 512(defun desktop-read ()
253406b9
RS
513 "Read the Desktop file and the files it specifies.
514This is a no-op when Emacs is running in batch mode."
6343ed61 515 (interactive)
253406b9
RS
516 (if noninteractive
517 nil
518 (let ((dirs '("./" "~/")))
519 (while (and dirs
520 (not (file-exists-p (expand-file-name
521 desktop-basefilename
522 (car dirs)))))
523 (setq dirs (cdr dirs)))
524 (setq desktop-dirname (and dirs (expand-file-name (car dirs))))
525 (if desktop-dirname
526 (progn
527 (load (expand-file-name desktop-basefilename desktop-dirname)
528 t t t)
529 (run-hooks 'desktop-delay-hook)
530 (setq desktop-delay-hook nil)
531 (message "Desktop loaded."))
532 (desktop-clear)))))
0b9bd504 533;; ----------------------------------------------------------------------------
478653c9 534;;;###autoload
6343ed61 535(defun desktop-load-default ()
577ed2b2
RS
536 "Load the `default' start-up library manually.
537Also inhibit further loading of it. Call this from your `.emacs' file
538to provide correct modes for autoloaded files."
0b9bd504 539 (if (not inhibit-default-init) ; safety check
6343ed61
RS
540 (progn
541 (load "default" t t)
542 (setq inhibit-default-init t))))
0b9bd504
RS
543;; ----------------------------------------------------------------------------
544;; Note: the following functions use the dynamic variable binding in Lisp.
0b9bd504 545;;
6343ed61 546(defun desktop-buffer-info () "Load an info file."
569c754e 547 (if (eq 'Info-mode desktop-buffer-major-mode)
6343ed61
RS
548 (progn
549 (require 'info)
2699e23e 550 (Info-find-node (nth 0 desktop-buffer-misc) (nth 1 desktop-buffer-misc))
608b9ed2 551 (current-buffer))))
0b9bd504 552;; ----------------------------------------------------------------------------
b6105c76 553(defun desktop-buffer-rmail () "Load an RMAIL file."
569c754e 554 (if (eq 'rmail-mode desktop-buffer-major-mode)
e36d00d4 555 (condition-case error
608b9ed2
RS
556 (progn (rmail-input desktop-buffer-file-name)
557 (if (eq major-mode 'rmail-mode)
558 (current-buffer)
559 rmail-buffer))
e2247420
RS
560 (file-locked
561 (kill-buffer (current-buffer))
562 'ignored))))
0b9bd504 563;; ----------------------------------------------------------------------------
ec4c6f22 564(defun desktop-buffer-mh () "Load a folder in the mh system."
569c754e 565 (if (eq 'mh-folder-mode desktop-buffer-major-mode)
ec4c6f22
RS
566 (progn
567 (require 'mh-e)
568 (mh-find-path)
608b9ed2
RS
569 (mh-visit-folder desktop-buffer-name)
570 (current-buffer))))
ec4c6f22 571;; ----------------------------------------------------------------------------
6343ed61 572(defun desktop-buffer-dired () "Load a directory using dired."
569c754e 573 (if (eq 'dired-mode desktop-buffer-major-mode)
2699e23e 574 (if (file-directory-p (file-name-directory (car desktop-buffer-misc)))
fa379636 575 (progn
608b9ed2 576 (dired (car desktop-buffer-misc))
2699e23e 577 (mapcar 'dired-insert-subdir (cdr desktop-buffer-misc))
608b9ed2 578 (current-buffer))
2699e23e 579 (message "Directory %s no longer exists." (car desktop-buffer-misc))
fa379636
KH
580 (sit-for 1)
581 'ignored)))
0b9bd504 582;; ----------------------------------------------------------------------------
6343ed61 583(defun desktop-buffer-file () "Load a file."
569c754e
RS
584 (if desktop-buffer-file-name
585 (if (or (file-exists-p desktop-buffer-file-name)
6343ed61 586 (and desktop-missing-file-warning
0b9bd504
RS
587 (y-or-n-p (format
588 "File \"%s\" no longer exists. Re-create? "
569c754e 589 desktop-buffer-file-name))))
608b9ed2 590 (progn (find-file desktop-buffer-file-name) (current-buffer))
6343ed61 591 'ignored)))
0b9bd504
RS
592;; ----------------------------------------------------------------------------
593;; Create a buffer, load its file, set is mode, ...; called from Desktop file
6343ed61 594;; only.
569c754e
RS
595(defun desktop-create-buffer (ver desktop-buffer-file-name desktop-buffer-name
596 desktop-buffer-major-mode
2699e23e 597 mim pt mk ro desktop-buffer-misc &optional locals)
6343ed61
RS
598 (let ((hlist desktop-buffer-handlers)
599 (result)
600 (handler))
601 (while (and (not result) hlist)
602 (setq handler (car hlist))
603 (setq result (funcall handler))
604 (setq hlist (cdr hlist)))
608b9ed2
RS
605 (when (bufferp result)
606 (set-buffer result)
607 (if (not (equal (buffer-name) desktop-buffer-name))
608 (rename-buffer desktop-buffer-name))
7c3d2af2
TTN
609 (cond ((equal '(t) mim) (auto-fill-mode 1)) ; backwards compatible
610 ((equal '(nil) mim) (auto-fill-mode 0))
611 (t (mapcar #'(lambda (minor-mode) (funcall minor-mode 1)) mim)))
612 (goto-char pt)
608b9ed2
RS
613 (if (consp mk)
614 (progn
615 (set-mark (car mk))
616 (setq mark-active (car (cdr mk))))
617 (set-mark mk))
618 ;; Never override file system if the file really is read-only marked.
619 (if ro (setq buffer-read-only ro))
620 (while locals
621 (let ((this (car locals)))
622 (if (consp this)
623 ;; an entry of this form `(symbol . value)'
0b9bd504 624 (progn
608b9ed2
RS
625 (make-local-variable (car this))
626 (set (car this) (cdr this)))
627 ;; an entry of the form `symbol'
628 (make-local-variable this)
629 (makunbound this)))
630 (setq locals (cdr locals))))))
ec4c6f22
RS
631
632;; Backward compatibility -- update parameters to 205 standards.
569c754e
RS
633(defun desktop-buffer (desktop-buffer-file-name desktop-buffer-name
634 desktop-buffer-major-mode
2699e23e 635 mim pt mk ro tl fc cfs cr desktop-buffer-misc)
569c754e 636 (desktop-create-buffer 205 desktop-buffer-file-name desktop-buffer-name
2699e23e
RS
637 desktop-buffer-major-mode (cdr mim) pt mk ro
638 desktop-buffer-misc
ec4c6f22
RS
639 (list (cons 'truncate-lines tl)
640 (cons 'fill-column fc)
641 (cons 'case-fold-search cfs)
642 (cons 'case-replace cr)
643 (cons 'overwrite-mode (car mim)))))
0b9bd504 644;; ----------------------------------------------------------------------------
813dbb2d
RS
645
646;; If the user set desktop-enable to t with Custom,
647;; do the rest of what it takes to use desktop,
648;; but do it after finishing loading the init file.
649(add-hook 'after-init-hook
650 '(lambda ()
651 (when desktop-enable
652 (desktop-load-default)
653 (desktop-read))))
654
ab1d55ea 655(provide 'desktop)
6343ed61
RS
656
657;; desktop.el ends here.