;; mew.el --- Messaging in the Emacs World

;; Author:  Kazu Yamamoto <Kazu@Mew.org>
;; Created: Mar 23, 1994
;; Revised: Feb 28, 1999

;;; Commentary:

;; The updated version is available from:
;;	ftp://ftp.Mew.org/pub/Mew/mew-current.tar.gz
;;	http://www.Mew.org/
;;
;; Minimum setup:
;;	(autoload 'mew "mew" nil t)
;;	(autoload 'mew-send "mew" nil t)
;;	(setq mew-mail-domain-list '("your mail domain"))
;;	(setq mew-icon-directory "icon directory")
;;
;; Optional setup (e.g. for C-xm):
;;	(autoload 'mew-user-agent-compose "mew" nil t)
;;	(if (boundp 'mail-user-agent)
;;	    (setq mail-user-agent 'mew-user-agent))
;;	(if (fboundp 'define-mail-user-agent)
;;	    (define-mail-user-agent
;;	      'mew-user-agent
;;	      'mew-user-agent-compose
;;	      'mew-draft-send-letter
;;	      'mew-draft-kill
;;	      'mew-send-hook))

;;; Code:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Mew version
;;;

(defconst mew-version-number "1.94.2"
  "Version number for this version of Mew.")
(defconst mew-version (format "Mew version %s" mew-version-number)
  "Version string for this version of Mew.")
(provide 'mew)
(require 'mew-vars)
(require 'mew-func)

(defun mew-version-show ()
  "Show mew-version in minibuffer."
  (interactive)
  (message "%s" mew-version))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; For developers
;;;

(defvar mew-debug nil)
;;(setq mew-debug nil)
;;(setq mew-debug t)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Bootstrap
;;;

;;;###autoload
(defun mew (&optional arg)
  "Execute Mew. If 'mew-auto-get' is 't', messages stored in your
spool are fetched to the +inbox folder and messages in the +inbox
folder are listed up in Summary mode. If 'mew-auto-get' is 'nil', list
up messages in the inbox folder. If '\\[universal-argument]' is specified, perform this
function thinking that 'mew-auto-get' is reversed."
  (interactive "P")
  (mew-window-push)
  (if (null mew-mail-path) (mew-init))
  (let ((auto (if arg (not mew-auto-get) mew-auto-get)))
    (if auto
	(mew-summary-get)
      (mew-summary-goto-folder t (mew-inbox-folder)))))

;;;###autoload
(defun mew-send (&optional to cc subject)
  "Execute Mew then prepare a draft. This may be used as library
function."
  (interactive)
  (mew-current-set 'window (current-window-configuration))
  (if (null mew-mail-path) (mew-init))
  (mew-summary-send to cc subject))

;;;###autoload
(defun mew-user-agent-compose (&optional to subject other-headers continue
                                             switch-function yank-action
                                             send-actions)
  "Set up mail composition draft with Mew.
This is 'mail-user-agent' entry point to Mew.

The optional arguments TO and SUBJECT specify recipients and the
initial Subject field, respectively.

OTHER-HEADERS is an alist specifying additional
header fields.  Elements look like (HEADER . VALUE) where both
HEADER and VALUE are strings.

A Draft buffer is prepared according to SWITCH-FUNCTION.

CONTINUE, YANK-ACTION and SEND-ACTIONS are ignored."
  (if (null mew-mail-path) (mew-init))
  (let* ((draft (mew-folder-new-message mew-draft-folder))
	 (attachdir (mew-attachdir draft)))
    (mew-current-set 'window (current-window-configuration))
    (mew-window-configure (current-buffer) 'draft)
    (mew-summary-prepare-draft
     (if switch-function
	 (let ((special-display-buffer-names nil)
	       (special-display-regexps nil)
	       (same-window-buffer-names nil)
	       (same-window-regexps nil))
	   (funcall switch-function (find-file-noselect draft)))
       (switch-to-buffer (find-file-noselect draft)))
     (mew-draft-rename draft)
     (mew-delete-directory-recursively attachdir)
     (mew-draft-header subject nil to nil nil nil nil other-headers)
     (mew-draft-mode)
     (run-hooks 'mew-draft-mode-newdraft-hook))))

;;;
;;; Functions for boot time
;;;

(defun mew-init ()
  (mew-hello)
  (message "Setting Mew world ...")
  (run-hooks 'mew-env-hook)
  (mew-set-environment)
  (run-hooks 'mew-init-hook)
  (mew-status-update t)
  (mew-passwd-setup)
  (if (get-buffer mew-buffer-hello) (kill-buffer mew-buffer-hello))
  (message "Setting Mew world ... done"))

(defun mew-set-environment (&optional no-dir)
  (let (error-message)
    (condition-case nil
	(progn
	  ;; sanity check
	  (cond
	   ((string-match "^18" emacs-version)
	    (setq error-message "Not support Emacs 18 nor Mule 1\n")
	    (error ""))
	   ((null mew-mail-domain-list)
	    (setq error-message "Must set 'mew-mail-domain-list'")
	    (error "")))
	  ;; initialize IM variables
	  (if (setq error-message (mew-config-init)) (error ""))
	  ;; initializing
	  (or no-dir (mew-buffers-init))
	  (or no-dir (mew-temp-dir-init))
	  (mew-mark-init)
	  (mew-refile-init))
      (error
       (set-buffer mew-buffer-hello)
       (goto-char (point-max))
       (insert "\n\nMew errors:\n\n")
       (and error-message (insert error-message))
       (set-buffer-modified-p nil)
       (setq buffer-read-only t)
       ;; cause an error again
       (error "Mew found some errors above.")))))

(defun mew-status-update (arg)
  "Read Addrbook and update its information. If executed with '\\[universal-argument]',
information of folders is also updated in addition to that of
Addrbook. If 'mew-use-folders-file-p' is 't', the list of
folders is stored in '~/Mail/.folders'. The default value is 't'."
  (interactive "P")
  (message "Updating status ... ")
  (if (interactive-p) (mew-set-environment 'no-dir))
  (if arg (mew-folder-setup nil (interactive-p)))
  (mew-addrbook-setup)
  (mew-pgp-set-version)
  (mew-highlight-face-setup mew-highlight-header-face-list)
  (mew-highlight-face-setup mew-highlight-body-face-list)
  (mew-highlight-face-setup mew-highlight-mark-face-list)
  (mew-highlight-make-keywords-regex)
  (mew-uniq-variables)
  (message "Updating status ...   done"))

(defun mew-uniq-variables ()
  (setq mew-mime-content-type-list (mew-uniq-list mew-mime-content-type-list)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Config
;;;

(defvar mew-mail-path nil)
(defvar mew-news-path nil)
(defvar mew-queue-path nil)
(defvar mew-inbox-folder nil)
(defvar mew-draft-folder nil)
(defvar mew-addrbook-file nil)
(defvar mew-alias-file nil)
(defvar mew-petname-file nil)
(defvar mew-trash-folder nil)
(defvar mew-imap-account nil)
(defvar mew-config-cases nil)
(defvar mew-config-case-inbox nil)

(defvar mew-path-alist
  '(("MailPath" . mew-mail-path)
    ("NewsPath" . mew-news-path)
    ("QueuePath" . mew-queue-path)
    ("InboxFolder" . mew-inbox-folder)
    ("DraftFolder" . mew-draft-folder)
    ("TrashFolder" . mew-trash-folder)
    ("AddrBookFile" . mew-addrbook-file)
    ("AliasFile"    . mew-alias-file)
    ("PetnameFile"  . mew-petname-file)
    ("ImapAccount" . mew-imap-account)
    ("ConfigCases" . mew-config-cases)
    ("ConfigCaseInbox" . mew-config-case-inbox)))

(defvar mew-draft-mime-folder nil)

(defmacro mew-config-error (var key)
  (` (if (null (, var))
	 (setq errmsg (concat errmsg "\t" (, key)
			      " was NOT found in Config.\n")))))

(defun mew-config-init ()
  (mew-set-buffer-tmp)
  (if (not (mew-which mew-prog-impath exec-path))
      (format "%s is not found in 'exec-path'" mew-prog-impath)
    (mew-im-call-process nil mew-prog-impath "--path=yes")
    (goto-char (point-min))
    (let (key value pair)
      (while (not (eobp))
	(if (looking-at "^\\([^=\n]+\\)=\\(.+\\)$")
	    ;; Petname may be null string.
	    (progn
	      (setq key (mew-match 1))
	      (setq value (mew-match 2))
	      (if (setq pair (mew-assoc-match2 key mew-path-alist 0))
		  (set (cdr pair) value))))
	(forward-line)))
    (if mew-config-cases 
	(setq mew-config-list (mew-split mew-config-cases ?,))
      (setq mew-config-list (list mew-config-default)))
    (if mew-config-case-inbox
	(let (tmp)
	  (setq mew-config-case-inbox (mew-split mew-config-case-inbox ?,))
	  (while mew-config-case-inbox
	    (setq tmp (cons (mew-split (car mew-config-case-inbox) ?:) tmp))
	    (setq mew-config-case-inbox (cdr mew-config-case-inbox)))
	  (setq mew-config-case-inbox (nreverse tmp))))
    (let (errmsg)
      (mew-config-error mew-mail-path "MailDir")
      (mew-config-error mew-news-path "NewsDir")
      (mew-config-error mew-inbox-folder "InboxFolder")
      (mew-config-error mew-draft-folder "DraftFolder")
      (mew-config-error mew-trash-folder "TrashFolder")
      (if errmsg
	  errmsg ;; return value
	;; xxx hard coding... +draft/mime
	(setq mew-draft-mime-folder
	      (concat (file-name-as-directory mew-draft-folder) "mime"))
	(mew-config-set-modes (list mew-mail-path mew-news-path))
	(mew-config-create-folders (cons mew-draft-folder
					 (cons mew-trash-folder
					       (mew-inbox-folders))))
	nil)))) ;; return value

(defun mew-config-set-modes (dirs)
  (let (dir)
    (while dirs
      (setq dir (file-chase-links (car dirs)))
      (setq dirs (cdr dirs))
      (if (file-exists-p dir)
	  (if (/= mew-folder-mode (mew-file-get-mode dir))
	      (set-file-modes dir mew-folder-mode))))))

(defun mew-config-create-folders (folders)
  (let (target)
    (while folders
      (setq target (mew-expand-folder (car folders)))
      (if (file-exists-p target)
	  ()
	(mew-make-directory target)
	(message "%s was created" target))
      (setq folders (cdr folders)))))

(defun mew-config-clean-up ()
  (setq mew-mail-path nil)
  (setq mew-news-path nil)
  (setq mew-queue-path nil)
;;  (setq mew-inbox-folder nil)
  (setq mew-draft-folder nil)
  (setq mew-petname-file nil)
  (setq mew-trash-folder nil)
  (setq mew-imap-account nil)
  (setq mew-config-cases nil))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Folders
;;;

(defvar mew-folder-list nil)
(defvar mew-folder-alist nil)

(defun mew-folder-setup (&optional new-folder interactivep)
  (cond
   (new-folder
    (if (mew-folder-member new-folder mew-folder-list)
	()
      (setq mew-folder-list (sort (cons new-folder mew-folder-list)
				  (function mew-string<)))
      (setq mew-folder-alist (mew-folder-make-alist mew-folder-list))))
   (t
    (setq mew-folder-list (mew-folder-make-list interactivep))
    (setq mew-folder-alist (mew-folder-make-alist mew-folder-list)))))

(defun mew-folder-delete (folder)
  (setq mew-folder-list (delete folder mew-folder-list))
  (setq mew-folder-alist (delq (assoc folder mew-folder-alist)
			       mew-folder-alist)))
 
(defun mew-folder-clean-up ()
  (setq mew-folder-list nil)
  (setq mew-folder-alist nil))

(defun mew-folder-make-list (updatep)
  (save-excursion
    (let ((case-fold-search t)
	  (folders ())
	  (folder nil)
	  (start nil)
	  (file (expand-file-name mew-folders-file mew-mail-path)))
      (mew-set-buffer-tmp)
      (cond
       ((and (not updatep)
	     mew-use-folders-file-p
	     (file-readable-p file))
	(insert-file-contents file))
       (t
	(mapcar (function (lambda (x) (insert x "\n")))
		(nconc (funcall mew-folder-list-function "+")
		       (funcall mew-folder-list-function "=")))
	(if mew-use-imap
	    (mew-folder-mail-to-imap))
	(if mew-use-folders-file-p
	    (write-region (point-min) (point-max) file nil 'no-msg))))
      (goto-char (point-min))
      (while (not (eobp))
	(setq start (point))
	(if (not (or (looking-at "[+=]")
		     (and mew-use-imap (looking-at "%"))))
	    (forward-line)
	  (forward-line)
	  (setq folder (mew-buffer-substring start (1- (point))))
	  (if (and (car folders)
		   (string-match (concat "^" (regexp-quote 
					      (file-name-as-directory
					       (car folders))))
				 folder))
	      ;; regexp-quote is not necessary since not "+".
	      (setq folders 
		    (cons folder 
			  (cons (file-name-as-directory (car folders))
				(cdr folders))))
	    (setq folders (cons folder folders)))))
      (sort (nreverse folders) (function mew-string<)))))

(defun mew-folder-mail-to-imap ()
  (goto-char (point-min))
  (if mew-imap-account
      (while (re-search-forward "^+@[^#]+#[^/]+/\\(.*\\)$" nil t)
	(replace-match (concat "%" (mew-match 1))))))

(defmacro mew-folder-make-alist (list)
  (` (mapcar (function mew-folder-pair) (, list))))

(defun mew-folder-pair (folder)
  (let* ((dir (directory-file-name (mew-folder-to-dir folder)))
	 ;; foo/bar  -> foo/bar
	 ;; foo/bar/ -> foo/bar
	 (subdir (file-name-nondirectory dir)))
	 ;; foo/bar -> bar 
	 ;; foo -> foo
    (if (mew-folders-ignore-p folder)
	(list folder nil)
      (list folder subdir))))

(defun mew-folders-ignore-p (folder)
  (let ((ignores mew-folders-ignore))
    (catch 'ignore
      ;; while always returns nil
      (while ignores
	(if (string-match (concat "^" (car ignores)) folder)
	    (throw 'ignore t))
	(setq ignores (cdr ignores))))))

(defun mew-string< (a b)
  (let ((case-fold-search nil) (ret (string< a b)))
    (if (or (string-match (concat "^" (regexp-quote a)) b)
	    (string-match (concat "^" (regexp-quote b)) a))
	(not ret)
      ret)))

(defun mew-inbox-folder ()
  (cond
   ((string= mew-config-imget mew-config-default);; this may be lengthy
    mew-inbox-folder)
   ((assoc mew-config-imget mew-config-case-inbox)
    (nth 1 (assoc mew-config-imget mew-config-case-inbox)))
   (t 
    mew-inbox-folder)))

(defun mew-inbox-folders ()
  (if (null mew-config-case-inbox)
      (list mew-inbox-folder)
    (let ((inboxes (mapcar (function (lambda (x) (nth 1 x)))
			   mew-config-case-inbox)))
      (if (member mew-inbox-folder inboxes)
	  inboxes
	(cons mew-inbox-folder inboxes)))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Window configuration stack
;;;

(defvar mew-window-stack nil)

(defun mew-window-clean-up ()
  (setq mew-window-stack nil))

(defun mew-window-push ()
  (let ((frame (selected-frame))
	(config (current-window-configuration)))
    (setq mew-window-stack (cons (cons frame config) mew-window-stack))))

(defun mew-window-pop ()
  (let* ((frame (selected-frame))
	 (assoc (assoc frame mew-window-stack)))
    (if (and assoc (window-configuration-p (cdr assoc)))
	(set-window-configuration (cdr assoc))
      (switch-to-buffer (get-buffer-create mew-window-home-buffer)))
    (setq mew-window-stack (delete assoc mew-window-stack))))

;;;
;;; Message buffer
;;;

(defun mew-buffer-message ()
  (if window-system
      (concat
       mew-buffer-message
       (int-to-string
	(mew-member-case-equal 
	 (cdr (assq
	       'window-id
	       (frame-parameters (selected-frame))))
	 (sort
	  (mapcar (function (lambda (frame)
			      (cdr (assq 'window-id
					 (frame-parameters frame)))))
		  (frame-list))
	  (function string<)))))
    mew-buffer-message))

;;;
;;; Window configuration
;;;

(defun mew-window-configure (nbuf action)
;;; action : summary, message, draft or list
;;; list for action (1 0)  for Summary only
;;; list for action (3 10) for Summary and Message
  (let* ((windows
	  (if (listp action) 
	      action
	    (car (cdr (assq action mew-window-configuration)))))
	 (obufwin (get-buffer-window (current-buffer)))
	 (msgwin  (get-buffer-window (mew-buffer-message)))
	 (height nil) (winsum nil) (sum-height 0) (msg-height 0))
    (setq height (+ (if obufwin (window-height obufwin) 0)
		    (if msgwin  (window-height msgwin)  0)))
    (if (or mew-window-use-full
	    (<= height (* 2 window-min-height)))
	(progn
	 ;; Delete other windows and use full emacs window.
	 (delete-other-windows)
	 (setq height (window-height (selected-window)))))
    (if (get-buffer (mew-buffer-message))
	(delete-windows-on (mew-buffer-message))
      (save-excursion
	(set-buffer (get-buffer-create (mew-buffer-message)))
	;; "truncate?" is asked in Message mode.
	;; so set the same toolbar as Sumamry mode
	(mew-summary-toolbar-update)
	(mew-message-mode)))
    (setq winsum (apply (function +) windows))
    (if (not (zerop (nth 0 windows)))
	(setq sum-height (max window-min-height
			     (/ (* height (nth 0 windows)) winsum))))
    (if (and (equal action 'message) (equal (% sum-height 2) 1)) 
	(setq sum-height (1+ sum-height)))
    (if (not (zerop (nth 1 windows)))
	(setq msg-height (max window-min-height
			     (- height sum-height))))
    (setq height (+ sum-height msg-height))
    (if (null (zerop sum-height))
	(switch-to-buffer nbuf 'norecord))
    (if (zerop msg-height)
	()
      (split-window nil sum-height)
      (other-window 1)
      (switch-to-buffer (mew-buffer-message) 'norecord))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Buffers
;;;

(defvar mew-buffers nil)

(defun mew-buffers-init ()
  (setq mew-buffers (mew-inbox-folders))) ;; for quiting

(defun mew-buffers-setup (folder)
  (if (not (mew-folder-member folder mew-buffers))
      (setq mew-buffers (cons folder mew-buffers))))

(defun mew-buffers-bury ()
  (let ((buffers mew-buffers))
    (while buffers
      (if (get-buffer (car buffers))
	  (bury-buffer (car buffers)))
      (setq buffers (cdr buffers)))))

(defun mew-buffers-clean-up ()
  (while mew-buffers
    (if (get-buffer (car mew-buffers))
	(mew-kill-buffer (car mew-buffers)))
    (setq mew-buffers (cdr mew-buffers)))
  (mew-buffers-init))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Temporary directory
;;;

(defvar mew-temp-dir nil)  ;; the default is "/tmp/user_name_uniq"
(defvar mew-temp-file nil) ;; the default is "/tmp/user_name_uniq/mew"

(defun mew-temp-dir-init ()
  "Setting temporary directory for Mew.
mew-temp-file must be local and readable for the user only
for privacy/speed reasons. "
  (setq mew-temp-dir (make-temp-name mew-temp-file-initial))
  (mew-make-directory mew-temp-dir)
  (set-file-modes mew-temp-dir mew-folder-mode)
  (setq mew-temp-file (expand-file-name "mew" mew-temp-dir))
  (add-hook 'kill-emacs-hook (function mew-temp-dir-clean-up)))

(defun mew-temp-dir-clean-up ()
  "A function to remove Mew's temporary directory recursively. 
It is typically called by kill-emacs-hook."
  (remove-hook 'kill-emacs-hook (function mew-temp-dir-clean-up))
  (if (and mew-temp-dir (file-exists-p mew-temp-dir))
      (mew-delete-directory-recursively mew-temp-dir))
  (setq mew-temp-dir nil)
  (setq mew-temp-file nil))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Teer down
;;;

(defun mew-bury-buffer (&optional buf)
  (bury-buffer buf)
  (delete-windows-on buf t))

(defun mew-kill-buffer (&optional buf)
  "Erase the current mode(buffer)."
  (interactive)
  (let* ((buf (or buf (current-buffer)))
	 (folder (if (bufferp buf) (buffer-name buf) buf)))
    (if (eq major-mode 'mew-virtual-mode)
	(mew-folder-delete folder))
    (if (and (eq major-mode 'mew-summary-mode)
	     (mew-folder-remotep folder))
	(mew-remote-folder-cache-delete folder))
    (if (get-buffer buf)
	(progn
	  (save-excursion
	    (set-buffer buf)
	    (mew-overlay-delete-buffer))
	  (kill-buffer buf)))))

(defun mew-buffer-message-clean-up (func)
  (if window-system
      (let ((bl (buffer-list))
	    (regexp (concat "^" (regexp-quote mew-buffer-message)))
	    b bn)
	(while bl
	  (setq b (car bl))
	  (setq bl (cdr bl))
	  (if (and (setq bn (buffer-name b))
		   (string-match regexp bn))
	      (funcall func b))))
    (funcall func (mew-buffer-message))))

(defun mew-buffer-draft-clean-up ()
  (let ((bl (buffer-list))
	(regexp (concat "^" (regexp-quote mew-draft-folder)))
	b bn)
    (while bl
      (setq b (car bl))
      (setq bl (cdr bl))
      (if (and (setq bn (buffer-name b))
	       (string-match regexp bn)
	       (equal 'mew-draft-mode
		      (save-excursion
			(set-buffer b)
			major-mode)))
	  (mew-kill-buffer b)))))


(defmacro mew-quit-toolbar-update ()
  '(if (fboundp 'redraw-frame) ;; for BOW
       (redraw-frame (selected-frame)))) ;; update toolbar

(defun mew-summary-suspend ()
  "Suspend Mew then switch to another buffer. All buffers of 
Mew remain, so you can resume with buffer operations."
  (interactive)
  (mew-buffer-message-clean-up (function mew-bury-buffer))
  (mew-buffers-bury)
  (mew-window-pop)
  (mew-quit-toolbar-update)
  (run-hooks 'mew-suspend-hook))

(defun mew-summary-quit ()
  "Quit Mew. All buffers of Mew are erased."
  (interactive)
  (if (not (y-or-n-p "Quit Mew? "))
      ()
    ;; killing buffers
    (mew-buffer-message-clean-up (function mew-kill-buffer)) ;; Message mode
    (mew-buffer-draft-clean-up) ;; Draft mode
    (mew-cache-clean-up)
    (mapcar (function mew-kill-buffer) mew-buffer-list) ;; other buffers
    ;;
    (mew-mark-clean-up)
    (mew-buffers-clean-up) ;; Summary mode and Virtual mode
    (mew-temp-dir-clean-up)
    ;;
    (run-hooks 'mew-quit-hook)
    ;;
    ;; lastly, clean up variables
    ;;
    (mew-folder-clean-up)
    (mew-current-clean-up)
    (mew-addrbook-clean-up)
    (mew-passwd-clean-up)
    ;;
    (mew-window-pop)
    (mew-window-clean-up)
    (mew-quit-toolbar-update)
    ;;
    (mew-config-clean-up) ;; MUST be last
    ;; flush minibuffer
    (message "")))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Load Mew libraries
;;;
(require 'mew-addrbook)
(require 'mew-complete)
(require 'mew-minibuf)
(require 'mew-cache)
(require 'mew-encode)
(require 'mew-decode)
(require 'mew-mime)
(require 'mew-mark)
(require 'mew-header)
(require 'mew-pgp)
(require 'mew-bq)
(require 'mew-syntax)
(require 'mew-scan)
(require 'mew-pick)
(require 'mew-summary)
(require 'mew-virtual)
(require 'mew-message)
(require 'mew-draft)
(require 'mew-attach)
(require 'mew-demo)
(require 'mew-refile)
(require 'mew-ext)
(require 'mew-fib)
(require 'mew-sort)
(require 'mew-highlight)

;;; Copyright Notice:

;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Mew developing team.
;; All rights reserved.

;; Redistribution and use in source and binary forms, with or without
;; modification, are permitted provided that the following conditions
;; are met:
;; 
;; 1. Redistributions of source code must retain the above copyright
;;    notice, this list of conditions and the following disclaimer.
;; 2. Redistributions in binary form must reproduce the above copyright
;;    notice, this list of conditions and the following disclaimer in the
;;    documentation and/or other materials provided with the distribution.
;; 3. Neither the name of the team nor the names of its contributors
;;    may be used to endorse or promote products derived from this software
;;    without specific prior written permission.
;; 
;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND
;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
;; PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE
;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

;;; mew.el ends here
