Initial Commit
[packages] / xemacs-packages / mew / mew / mew.el
1 ;; mew.el --- Messaging in the Emacs World
2
3 ;; Author:  Kazu Yamamoto <Kazu@Mew.org>
4 ;; Created: Mar 23, 1994
5 ;; Revised: Feb 28, 1999
6
7 ;;; Commentary:
8
9 ;; The updated version is available from:
10 ;;      ftp://ftp.Mew.org/pub/Mew/mew-current.tar.gz
11 ;;      http://www.Mew.org/
12 ;;
13 ;; Minimum setup:
14 ;;      (autoload 'mew "mew" nil t)
15 ;;      (autoload 'mew-send "mew" nil t)
16 ;;      (setq mew-mail-domain-list '("your mail domain"))
17 ;;      (setq mew-icon-directory "icon directory")
18 ;;
19 ;; Optional setup (e.g. for C-xm):
20 ;;      (autoload 'mew-user-agent-compose "mew" nil t)
21 ;;      (if (boundp 'mail-user-agent)
22 ;;          (setq mail-user-agent 'mew-user-agent))
23 ;;      (if (fboundp 'define-mail-user-agent)
24 ;;          (define-mail-user-agent
25 ;;            'mew-user-agent
26 ;;            'mew-user-agent-compose
27 ;;            'mew-draft-send-letter
28 ;;            'mew-draft-kill
29 ;;            'mew-send-hook))
30
31 ;;; Code:
32
33 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
34 ;;;
35 ;;; Mew version
36 ;;;
37
38 (defconst mew-version-number "1.94.2"
39   "Version number for this version of Mew.")
40 (defconst mew-version (format "Mew version %s" mew-version-number)
41   "Version string for this version of Mew.")
42 (provide 'mew)
43 (require 'mew-vars)
44 (require 'mew-func)
45
46 (defun mew-version-show ()
47   "Show mew-version in minibuffer."
48   (interactive)
49   (message "%s" mew-version))
50
51 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
52 ;;;
53 ;;; For developers
54 ;;;
55
56 (defvar mew-debug nil)
57 ;;(setq mew-debug nil)
58 ;;(setq mew-debug t)
59
60 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
61 ;;;
62 ;;; Bootstrap
63 ;;;
64
65 ;;;###autoload
66 (defun mew (&optional arg)
67   "Execute Mew. If 'mew-auto-get' is 't', messages stored in your
68 spool are fetched to the +inbox folder and messages in the +inbox
69 folder are listed up in Summary mode. If 'mew-auto-get' is 'nil', list
70 up messages in the inbox folder. If '\\[universal-argument]' is specified, perform this
71 function thinking that 'mew-auto-get' is reversed."
72   (interactive "P")
73   (mew-window-push)
74   (if (null mew-mail-path) (mew-init))
75   (let ((auto (if arg (not mew-auto-get) mew-auto-get)))
76     (if auto
77         (mew-summary-get)
78       (mew-summary-goto-folder t (mew-inbox-folder)))))
79
80 ;;;###autoload
81 (defun mew-send (&optional to cc subject)
82   "Execute Mew then prepare a draft. This may be used as library
83 function."
84   (interactive)
85   (mew-current-set 'window (current-window-configuration))
86   (if (null mew-mail-path) (mew-init))
87   (mew-summary-send to cc subject))
88
89 ;;;###autoload
90 (defun mew-user-agent-compose (&optional to subject other-headers continue
91                                              switch-function yank-action
92                                              send-actions)
93   "Set up mail composition draft with Mew.
94 This is 'mail-user-agent' entry point to Mew.
95
96 The optional arguments TO and SUBJECT specify recipients and the
97 initial Subject field, respectively.
98
99 OTHER-HEADERS is an alist specifying additional
100 header fields.  Elements look like (HEADER . VALUE) where both
101 HEADER and VALUE are strings.
102
103 A Draft buffer is prepared according to SWITCH-FUNCTION.
104
105 CONTINUE, YANK-ACTION and SEND-ACTIONS are ignored."
106   (if (null mew-mail-path) (mew-init))
107   (let* ((draft (mew-folder-new-message mew-draft-folder))
108          (attachdir (mew-attachdir draft)))
109     (mew-current-set 'window (current-window-configuration))
110     (mew-window-configure (current-buffer) 'draft)
111     (mew-summary-prepare-draft
112      (if switch-function
113          (let ((special-display-buffer-names nil)
114                (special-display-regexps nil)
115                (same-window-buffer-names nil)
116                (same-window-regexps nil))
117            (funcall switch-function (find-file-noselect draft)))
118        (switch-to-buffer (find-file-noselect draft)))
119      (mew-draft-rename draft)
120      (mew-delete-directory-recursively attachdir)
121      (mew-draft-header subject nil to nil nil nil nil other-headers)
122      (mew-draft-mode)
123      (run-hooks 'mew-draft-mode-newdraft-hook))))
124
125 ;;;
126 ;;; Functions for boot time
127 ;;;
128
129 (defun mew-init ()
130   (mew-hello)
131   (message "Setting Mew world ...")
132   (run-hooks 'mew-env-hook)
133   (mew-set-environment)
134   (run-hooks 'mew-init-hook)
135   (mew-status-update t)
136   (mew-passwd-setup)
137   (if (get-buffer mew-buffer-hello) (kill-buffer mew-buffer-hello))
138   (message "Setting Mew world ... done"))
139
140 (defun mew-set-environment (&optional no-dir)
141   (let (error-message)
142     (condition-case nil
143         (progn
144           ;; sanity check
145           (cond
146            ((string-match "^18" emacs-version)
147             (setq error-message "Not support Emacs 18 nor Mule 1\n")
148             (error ""))
149            ((null mew-mail-domain-list)
150             (setq error-message "Must set 'mew-mail-domain-list'")
151             (error "")))
152           ;; initialize IM variables
153           (if (setq error-message (mew-config-init)) (error ""))
154           ;; initializing
155           (or no-dir (mew-buffers-init))
156           (or no-dir (mew-temp-dir-init))
157           (mew-mark-init)
158           (mew-refile-init))
159       (error
160        (set-buffer mew-buffer-hello)
161        (goto-char (point-max))
162        (insert "\n\nMew errors:\n\n")
163        (and error-message (insert error-message))
164        (set-buffer-modified-p nil)
165        (setq buffer-read-only t)
166        ;; cause an error again
167        (error "Mew found some errors above.")))))
168
169 (defun mew-status-update (arg)
170   "Read Addrbook and update its information. If executed with '\\[universal-argument]',
171 information of folders is also updated in addition to that of
172 Addrbook. If 'mew-use-folders-file-p' is 't', the list of
173 folders is stored in '~/Mail/.folders'. The default value is 't'."
174   (interactive "P")
175   (message "Updating status ... ")
176   (if (interactive-p) (mew-set-environment 'no-dir))
177   (if arg (mew-folder-setup nil (interactive-p)))
178   (mew-addrbook-setup)
179   (mew-pgp-set-version)
180   (mew-highlight-face-setup mew-highlight-header-face-list)
181   (mew-highlight-face-setup mew-highlight-body-face-list)
182   (mew-highlight-face-setup mew-highlight-mark-face-list)
183   (mew-highlight-make-keywords-regex)
184   (mew-uniq-variables)
185   (message "Updating status ...   done"))
186
187 (defun mew-uniq-variables ()
188   (setq mew-mime-content-type-list (mew-uniq-list mew-mime-content-type-list)))
189
190 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
191 ;;;
192 ;;; Config
193 ;;;
194
195 (defvar mew-mail-path nil)
196 (defvar mew-news-path nil)
197 (defvar mew-queue-path nil)
198 (defvar mew-inbox-folder nil)
199 (defvar mew-draft-folder nil)
200 (defvar mew-addrbook-file nil)
201 (defvar mew-alias-file nil)
202 (defvar mew-petname-file nil)
203 (defvar mew-trash-folder nil)
204 (defvar mew-imap-account nil)
205 (defvar mew-config-cases nil)
206 (defvar mew-config-case-inbox nil)
207
208 (defvar mew-path-alist
209   '(("MailPath" . mew-mail-path)
210     ("NewsPath" . mew-news-path)
211     ("QueuePath" . mew-queue-path)
212     ("InboxFolder" . mew-inbox-folder)
213     ("DraftFolder" . mew-draft-folder)
214     ("TrashFolder" . mew-trash-folder)
215     ("AddrBookFile" . mew-addrbook-file)
216     ("AliasFile"    . mew-alias-file)
217     ("PetnameFile"  . mew-petname-file)
218     ("ImapAccount" . mew-imap-account)
219     ("ConfigCases" . mew-config-cases)
220     ("ConfigCaseInbox" . mew-config-case-inbox)))
221
222 (defvar mew-draft-mime-folder nil)
223
224 (defmacro mew-config-error (var key)
225   (` (if (null (, var))
226          (setq errmsg (concat errmsg "\t" (, key)
227                               " was NOT found in Config.\n")))))
228
229 (defun mew-config-init ()
230   (mew-set-buffer-tmp)
231   (if (not (mew-which mew-prog-impath exec-path))
232       (format "%s is not found in 'exec-path'" mew-prog-impath)
233     (mew-im-call-process nil mew-prog-impath "--path=yes")
234     (goto-char (point-min))
235     (let (key value pair)
236       (while (not (eobp))
237         (if (looking-at "^\\([^=\n]+\\)=\\(.+\\)$")
238             ;; Petname may be null string.
239             (progn
240               (setq key (mew-match 1))
241               (setq value (mew-match 2))
242               (if (setq pair (mew-assoc-match2 key mew-path-alist 0))
243                   (set (cdr pair) value))))
244         (forward-line)))
245     (if mew-config-cases 
246         (setq mew-config-list (mew-split mew-config-cases ?,))
247       (setq mew-config-list (list mew-config-default)))
248     (if mew-config-case-inbox
249         (let (tmp)
250           (setq mew-config-case-inbox (mew-split mew-config-case-inbox ?,))
251           (while mew-config-case-inbox
252             (setq tmp (cons (mew-split (car mew-config-case-inbox) ?:) tmp))
253             (setq mew-config-case-inbox (cdr mew-config-case-inbox)))
254           (setq mew-config-case-inbox (nreverse tmp))))
255     (let (errmsg)
256       (mew-config-error mew-mail-path "MailDir")
257       (mew-config-error mew-news-path "NewsDir")
258       (mew-config-error mew-inbox-folder "InboxFolder")
259       (mew-config-error mew-draft-folder "DraftFolder")
260       (mew-config-error mew-trash-folder "TrashFolder")
261       (if errmsg
262           errmsg ;; return value
263         ;; xxx hard coding... +draft/mime
264         (setq mew-draft-mime-folder
265               (concat (file-name-as-directory mew-draft-folder) "mime"))
266         (mew-config-set-modes (list mew-mail-path mew-news-path))
267         (mew-config-create-folders (cons mew-draft-folder
268                                          (cons mew-trash-folder
269                                                (mew-inbox-folders))))
270         nil)))) ;; return value
271
272 (defun mew-config-set-modes (dirs)
273   (let (dir)
274     (while dirs
275       (setq dir (file-chase-links (car dirs)))
276       (setq dirs (cdr dirs))
277       (if (file-exists-p dir)
278           (if (/= mew-folder-mode (mew-file-get-mode dir))
279               (set-file-modes dir mew-folder-mode))))))
280
281 (defun mew-config-create-folders (folders)
282   (let (target)
283     (while folders
284       (setq target (mew-expand-folder (car folders)))
285       (if (file-exists-p target)
286           ()
287         (mew-make-directory target)
288         (message "%s was created" target))
289       (setq folders (cdr folders)))))
290
291 (defun mew-config-clean-up ()
292   (setq mew-mail-path nil)
293   (setq mew-news-path nil)
294   (setq mew-queue-path nil)
295 ;;  (setq mew-inbox-folder nil)
296   (setq mew-draft-folder nil)
297   (setq mew-petname-file nil)
298   (setq mew-trash-folder nil)
299   (setq mew-imap-account nil)
300   (setq mew-config-cases nil))
301
302 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
303 ;;;
304 ;;; Folders
305 ;;;
306
307 (defvar mew-folder-list nil)
308 (defvar mew-folder-alist nil)
309
310 (defun mew-folder-setup (&optional new-folder interactivep)
311   (cond
312    (new-folder
313     (if (mew-folder-member new-folder mew-folder-list)
314         ()
315       (setq mew-folder-list (sort (cons new-folder mew-folder-list)
316                                   (function mew-string<)))
317       (setq mew-folder-alist (mew-folder-make-alist mew-folder-list))))
318    (t
319     (setq mew-folder-list (mew-folder-make-list interactivep))
320     (setq mew-folder-alist (mew-folder-make-alist mew-folder-list)))))
321
322 (defun mew-folder-delete (folder)
323   (setq mew-folder-list (delete folder mew-folder-list))
324   (setq mew-folder-alist (delq (assoc folder mew-folder-alist)
325                                mew-folder-alist)))
326  
327 (defun mew-folder-clean-up ()
328   (setq mew-folder-list nil)
329   (setq mew-folder-alist nil))
330
331 (defun mew-folder-make-list (updatep)
332   (save-excursion
333     (let ((case-fold-search t)
334           (folders ())
335           (folder nil)
336           (start nil)
337           (file (expand-file-name mew-folders-file mew-mail-path)))
338       (mew-set-buffer-tmp)
339       (cond
340        ((and (not updatep)
341              mew-use-folders-file-p
342              (file-readable-p file))
343         (insert-file-contents file))
344        (t
345         (mapcar (function (lambda (x) (insert x "\n")))
346                 (nconc (funcall mew-folder-list-function "+")
347                        (funcall mew-folder-list-function "=")))
348         (if mew-use-imap
349             (mew-folder-mail-to-imap))
350         (if mew-use-folders-file-p
351             (write-region (point-min) (point-max) file nil 'no-msg))))
352       (goto-char (point-min))
353       (while (not (eobp))
354         (setq start (point))
355         (if (not (or (looking-at "[+=]")
356                      (and mew-use-imap (looking-at "%"))))
357             (forward-line)
358           (forward-line)
359           (setq folder (mew-buffer-substring start (1- (point))))
360           (if (and (car folders)
361                    (string-match (concat "^" (regexp-quote 
362                                               (file-name-as-directory
363                                                (car folders))))
364                                  folder))
365               ;; regexp-quote is not necessary since not "+".
366               (setq folders 
367                     (cons folder 
368                           (cons (file-name-as-directory (car folders))
369                                 (cdr folders))))
370             (setq folders (cons folder folders)))))
371       (sort (nreverse folders) (function mew-string<)))))
372
373 (defun mew-folder-mail-to-imap ()
374   (goto-char (point-min))
375   (if mew-imap-account
376       (while (re-search-forward "^+@[^#]+#[^/]+/\\(.*\\)$" nil t)
377         (replace-match (concat "%" (mew-match 1))))))
378
379 (defmacro mew-folder-make-alist (list)
380   (` (mapcar (function mew-folder-pair) (, list))))
381
382 (defun mew-folder-pair (folder)
383   (let* ((dir (directory-file-name (mew-folder-to-dir folder)))
384          ;; foo/bar  -> foo/bar
385          ;; foo/bar/ -> foo/bar
386          (subdir (file-name-nondirectory dir)))
387          ;; foo/bar -> bar 
388          ;; foo -> foo
389     (if (mew-folders-ignore-p folder)
390         (list folder nil)
391       (list folder subdir))))
392
393 (defun mew-folders-ignore-p (folder)
394   (let ((ignores mew-folders-ignore))
395     (catch 'ignore
396       ;; while always returns nil
397       (while ignores
398         (if (string-match (concat "^" (car ignores)) folder)
399             (throw 'ignore t))
400         (setq ignores (cdr ignores))))))
401
402 (defun mew-string< (a b)
403   (let ((case-fold-search nil) (ret (string< a b)))
404     (if (or (string-match (concat "^" (regexp-quote a)) b)
405             (string-match (concat "^" (regexp-quote b)) a))
406         (not ret)
407       ret)))
408
409 (defun mew-inbox-folder ()
410   (cond
411    ((string= mew-config-imget mew-config-default);; this may be lengthy
412     mew-inbox-folder)
413    ((assoc mew-config-imget mew-config-case-inbox)
414     (nth 1 (assoc mew-config-imget mew-config-case-inbox)))
415    (t 
416     mew-inbox-folder)))
417
418 (defun mew-inbox-folders ()
419   (if (null mew-config-case-inbox)
420       (list mew-inbox-folder)
421     (let ((inboxes (mapcar (function (lambda (x) (nth 1 x)))
422                            mew-config-case-inbox)))
423       (if (member mew-inbox-folder inboxes)
424           inboxes
425         (cons mew-inbox-folder inboxes)))))
426
427 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
428 ;;;
429 ;;; Window configuration stack
430 ;;;
431
432 (defvar mew-window-stack nil)
433
434 (defun mew-window-clean-up ()
435   (setq mew-window-stack nil))
436
437 (defun mew-window-push ()
438   (let ((frame (selected-frame))
439         (config (current-window-configuration)))
440     (setq mew-window-stack (cons (cons frame config) mew-window-stack))))
441
442 (defun mew-window-pop ()
443   (let* ((frame (selected-frame))
444          (assoc (assoc frame mew-window-stack)))
445     (if (and assoc (window-configuration-p (cdr assoc)))
446         (set-window-configuration (cdr assoc))
447       (switch-to-buffer (get-buffer-create mew-window-home-buffer)))
448     (setq mew-window-stack (delete assoc mew-window-stack))))
449
450 ;;;
451 ;;; Message buffer
452 ;;;
453
454 (defun mew-buffer-message ()
455   (if window-system
456       (concat
457        mew-buffer-message
458        (int-to-string
459         (mew-member-case-equal 
460          (cdr (assq
461                'window-id
462                (frame-parameters (selected-frame))))
463          (sort
464           (mapcar (function (lambda (frame)
465                               (cdr (assq 'window-id
466                                          (frame-parameters frame)))))
467                   (frame-list))
468           (function string<)))))
469     mew-buffer-message))
470
471 ;;;
472 ;;; Window configuration
473 ;;;
474
475 (defun mew-window-configure (nbuf action)
476 ;;; action : summary, message, draft or list
477 ;;; list for action (1 0)  for Summary only
478 ;;; list for action (3 10) for Summary and Message
479   (let* ((windows
480           (if (listp action) 
481               action
482             (car (cdr (assq action mew-window-configuration)))))
483          (obufwin (get-buffer-window (current-buffer)))
484          (msgwin  (get-buffer-window (mew-buffer-message)))
485          (height nil) (winsum nil) (sum-height 0) (msg-height 0))
486     (setq height (+ (if obufwin (window-height obufwin) 0)
487                     (if msgwin  (window-height msgwin)  0)))
488     (if (or mew-window-use-full
489             (<= height (* 2 window-min-height)))
490         (progn
491          ;; Delete other windows and use full emacs window.
492          (delete-other-windows)
493          (setq height (window-height (selected-window)))))
494     (if (get-buffer (mew-buffer-message))
495         (delete-windows-on (mew-buffer-message))
496       (save-excursion
497         (set-buffer (get-buffer-create (mew-buffer-message)))
498         ;; "truncate?" is asked in Message mode.
499         ;; so set the same toolbar as Sumamry mode
500         (mew-summary-toolbar-update)
501         (mew-message-mode)))
502     (setq winsum (apply (function +) windows))
503     (if (not (zerop (nth 0 windows)))
504         (setq sum-height (max window-min-height
505                              (/ (* height (nth 0 windows)) winsum))))
506     (if (and (equal action 'message) (equal (% sum-height 2) 1)) 
507         (setq sum-height (1+ sum-height)))
508     (if (not (zerop (nth 1 windows)))
509         (setq msg-height (max window-min-height
510                              (- height sum-height))))
511     (setq height (+ sum-height msg-height))
512     (if (null (zerop sum-height))
513         (switch-to-buffer nbuf 'norecord))
514     (if (zerop msg-height)
515         ()
516       (split-window nil sum-height)
517       (other-window 1)
518       (switch-to-buffer (mew-buffer-message) 'norecord))))
519
520 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
521 ;;;
522 ;;; Buffers
523 ;;;
524
525 (defvar mew-buffers nil)
526
527 (defun mew-buffers-init ()
528   (setq mew-buffers (mew-inbox-folders))) ;; for quiting
529
530 (defun mew-buffers-setup (folder)
531   (if (not (mew-folder-member folder mew-buffers))
532       (setq mew-buffers (cons folder mew-buffers))))
533
534 (defun mew-buffers-bury ()
535   (let ((buffers mew-buffers))
536     (while buffers
537       (if (get-buffer (car buffers))
538           (bury-buffer (car buffers)))
539       (setq buffers (cdr buffers)))))
540
541 (defun mew-buffers-clean-up ()
542   (while mew-buffers
543     (if (get-buffer (car mew-buffers))
544         (mew-kill-buffer (car mew-buffers)))
545     (setq mew-buffers (cdr mew-buffers)))
546   (mew-buffers-init))
547
548 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
549 ;;;
550 ;;; Temporary directory
551 ;;;
552
553 (defvar mew-temp-dir nil)  ;; the default is "/tmp/user_name_uniq"
554 (defvar mew-temp-file nil) ;; the default is "/tmp/user_name_uniq/mew"
555
556 (defun mew-temp-dir-init ()
557   "Setting temporary directory for Mew.
558 mew-temp-file must be local and readable for the user only
559 for privacy/speed reasons. "
560   (setq mew-temp-dir (make-temp-name mew-temp-file-initial))
561   (mew-make-directory mew-temp-dir)
562   (set-file-modes mew-temp-dir mew-folder-mode)
563   (setq mew-temp-file (expand-file-name "mew" mew-temp-dir))
564   (add-hook 'kill-emacs-hook (function mew-temp-dir-clean-up)))
565
566 (defun mew-temp-dir-clean-up ()
567   "A function to remove Mew's temporary directory recursively. 
568 It is typically called by kill-emacs-hook."
569   (remove-hook 'kill-emacs-hook (function mew-temp-dir-clean-up))
570   (if (and mew-temp-dir (file-exists-p mew-temp-dir))
571       (mew-delete-directory-recursively mew-temp-dir))
572   (setq mew-temp-dir nil)
573   (setq mew-temp-file nil))
574
575 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
576 ;;;
577 ;;; Teer down
578 ;;;
579
580 (defun mew-bury-buffer (&optional buf)
581   (bury-buffer buf)
582   (delete-windows-on buf t))
583
584 (defun mew-kill-buffer (&optional buf)
585   "Erase the current mode(buffer)."
586   (interactive)
587   (let* ((buf (or buf (current-buffer)))
588          (folder (if (bufferp buf) (buffer-name buf) buf)))
589     (if (eq major-mode 'mew-virtual-mode)
590         (mew-folder-delete folder))
591     (if (and (eq major-mode 'mew-summary-mode)
592              (mew-folder-remotep folder))
593         (mew-remote-folder-cache-delete folder))
594     (if (get-buffer buf)
595         (progn
596           (save-excursion
597             (set-buffer buf)
598             (mew-overlay-delete-buffer))
599           (kill-buffer buf)))))
600
601 (defun mew-buffer-message-clean-up (func)
602   (if window-system
603       (let ((bl (buffer-list))
604             (regexp (concat "^" (regexp-quote mew-buffer-message)))
605             b bn)
606         (while bl
607           (setq b (car bl))
608           (setq bl (cdr bl))
609           (if (and (setq bn (buffer-name b))
610                    (string-match regexp bn))
611               (funcall func b))))
612     (funcall func (mew-buffer-message))))
613
614 (defun mew-buffer-draft-clean-up ()
615   (let ((bl (buffer-list))
616         (regexp (concat "^" (regexp-quote mew-draft-folder)))
617         b bn)
618     (while bl
619       (setq b (car bl))
620       (setq bl (cdr bl))
621       (if (and (setq bn (buffer-name b))
622                (string-match regexp bn)
623                (equal 'mew-draft-mode
624                       (save-excursion
625                         (set-buffer b)
626                         major-mode)))
627           (mew-kill-buffer b)))))
628
629
630 (defmacro mew-quit-toolbar-update ()
631   '(if (fboundp 'redraw-frame) ;; for BOW
632        (redraw-frame (selected-frame)))) ;; update toolbar
633
634 (defun mew-summary-suspend ()
635   "Suspend Mew then switch to another buffer. All buffers of 
636 Mew remain, so you can resume with buffer operations."
637   (interactive)
638   (mew-buffer-message-clean-up (function mew-bury-buffer))
639   (mew-buffers-bury)
640   (mew-window-pop)
641   (mew-quit-toolbar-update)
642   (run-hooks 'mew-suspend-hook))
643
644 (defun mew-summary-quit ()
645   "Quit Mew. All buffers of Mew are erased."
646   (interactive)
647   (if (not (y-or-n-p "Quit Mew? "))
648       ()
649     ;; killing buffers
650     (mew-buffer-message-clean-up (function mew-kill-buffer)) ;; Message mode
651     (mew-buffer-draft-clean-up) ;; Draft mode
652     (mew-cache-clean-up)
653     (mapcar (function mew-kill-buffer) mew-buffer-list) ;; other buffers
654     ;;
655     (mew-mark-clean-up)
656     (mew-buffers-clean-up) ;; Summary mode and Virtual mode
657     (mew-temp-dir-clean-up)
658     ;;
659     (run-hooks 'mew-quit-hook)
660     ;;
661     ;; lastly, clean up variables
662     ;;
663     (mew-folder-clean-up)
664     (mew-current-clean-up)
665     (mew-addrbook-clean-up)
666     (mew-passwd-clean-up)
667     ;;
668     (mew-window-pop)
669     (mew-window-clean-up)
670     (mew-quit-toolbar-update)
671     ;;
672     (mew-config-clean-up) ;; MUST be last
673     ;; flush minibuffer
674     (message "")))
675
676 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
677 ;;;
678 ;;; Load Mew libraries
679 ;;;
680 (require 'mew-addrbook)
681 (require 'mew-complete)
682 (require 'mew-minibuf)
683 (require 'mew-cache)
684 (require 'mew-encode)
685 (require 'mew-decode)
686 (require 'mew-mime)
687 (require 'mew-mark)
688 (require 'mew-header)
689 (require 'mew-pgp)
690 (require 'mew-bq)
691 (require 'mew-syntax)
692 (require 'mew-scan)
693 (require 'mew-pick)
694 (require 'mew-summary)
695 (require 'mew-virtual)
696 (require 'mew-message)
697 (require 'mew-draft)
698 (require 'mew-attach)
699 (require 'mew-demo)
700 (require 'mew-refile)
701 (require 'mew-ext)
702 (require 'mew-fib)
703 (require 'mew-sort)
704 (require 'mew-highlight)
705
706 ;;; Copyright Notice:
707
708 ;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Mew developing team.
709 ;; All rights reserved.
710
711 ;; Redistribution and use in source and binary forms, with or without
712 ;; modification, are permitted provided that the following conditions
713 ;; are met:
714 ;; 
715 ;; 1. Redistributions of source code must retain the above copyright
716 ;;    notice, this list of conditions and the following disclaimer.
717 ;; 2. Redistributions in binary form must reproduce the above copyright
718 ;;    notice, this list of conditions and the following disclaimer in the
719 ;;    documentation and/or other materials provided with the distribution.
720 ;; 3. Neither the name of the team nor the names of its contributors
721 ;;    may be used to endorse or promote products derived from this software
722 ;;    without specific prior written permission.
723 ;; 
724 ;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND
725 ;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
726 ;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
727 ;; PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE
728 ;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
729 ;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
730 ;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
731 ;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
732 ;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
733 ;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
734 ;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
735
736 ;;; mew.el ends here