;;; mew-summary.el --- Summary mode for Mew

;; Author:  Kazu Yamamoto <Kazu@Mew.org>
;; Created: Oct  2, 1996
;; Revised: Oct 25, 1997

;;; Code:

(defconst mew-summary-version "mew-summary.el version 0.35")

(require 'mew)
(if mew-xemacs-p (require 'easymenu))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; User customize variables
;;;

(defvar mew-summary-mode-map nil)

(defvar mew-summary-mode-menu-spec
  '("Mew"
    ["Show" mew-summary-show t]
    ["Next part" mew-summary-display-down t]
    ["Previous part" mew-summary-display-up t]
    ["Top" mew-summary-display-top t]
    ["Bottom" mew-summary-display-bottom t]
    ["Jump" mew-summary-jump-message t]
    "----"
    ["Delete" mew-summary-delete (equal major-mode 'mew-summary-mode)]
    ["Refile" mew-summary-refile (equal major-mode 'mew-summary-mode)]
    ["Mark multi" mew-summary-mark-multi t]
    ["Mark review" mew-summary-mark-review t]
    ["Sort marked msgs" mew-summary-mark-sort t]
    ["Undo" mew-summary-undo t]
    ["Undo all" mew-summary-undo-all t]
    ["Execute" mew-summary-exec (equal major-mode 'mew-summary-mode)]
    ["Suspend" mew-summary-suspend t]
    ["Quit" mew-summary-quit t]
    "----"
    ("Manipulate folder"
     ["Get" mew-summary-get t]
     ["List" mew-summary-ls (equal major-mode 'mew-summary-mode)]
     ["Pack" mew-summary-pack (equal major-mode 'mew-summary-mode)]
     ["Sort" mew-summary-sort (equal major-mode 'mew-summary-mode)]
     ["Burst" mew-summary-burst t]
     ["Go to folder" mew-summary-goto-folder t]
     )
    ("Manipulate file"
     ["Save" mew-summary-save t]
     ["Convert to local character set" mew-summary-convert-local-cs t]
     ["Display X-Face" mew-summary-x-face t]
     )
    ("Write/Reply/Forward"
     ["Write a message" mew-summary-send t]
     ["Reedit" mew-summary-reedit t]
     ["Reply" mew-summary-reply t]
     ["Reply with citation" mew-summary-reply-with-citation t]
     ["Forward" mew-summary-forward t]
     ["Multi forward" mew-summary-multi-forward t]
     )
    ("Select"
     ["Search then Mark" mew-summary-search-mark
      (equal major-mode 'mew-summary-mode)]
     ["Search" mew-summary-search (equal major-mode 'mew-summary-mode)]
     ["Virtual mode" mew-summary-virtual (equal major-mode 'mew-summary-mode)]
     )
    ("Misc"
     ["Recenter" mew-summary-recenter t]
     ["Uudecode" mew-summary-uudecode t]
     ["Unshar" mew-summary-unshar t]
     ["Print" mew-summary-print t]
     ["Pipe message" mew-summary-pipe-message t]
     ["Isearch forward" mew-summary-isearch-forward t]
     ["Isearch backward" mew-summary-isearch-backward t]
     ["Toggle disp msg" mew-summary-toggle-disp-msg t]
     ["Toggle analysis" mew-summary-toggle-analysis t]
     ["Config for imget" mew-summary-config-imget t]
     ["PGP public key fetch" mew-pgp-fetch-key t]
     ["Kill Sub-Process"
      mew-summary-kill-subprocess 
      (and (processp mew-summary-buffer-process)
	   (equal major-mode 'mew-summary-mode))]
     )
    )
  )

(if mew-summary-mode-map
    ()
  (setq mew-summary-mode-map (make-sparse-keymap))
  (define-key mew-summary-mode-map " "    'mew-summary-show)
  (define-key mew-summary-mode-map "."    'mew-summary-display)
  (define-key mew-summary-mode-map "<"    'mew-summary-display-top)
  (define-key mew-summary-mode-map ">"    'mew-summary-display-bottom)
  (define-key mew-summary-mode-map "\177" 'mew-summary-prev-page)
  (define-key mew-summary-mode-map "\r"   'mew-summary-scroll-up)
  (define-key mew-summary-mode-map "-"    'mew-summary-scroll-down)
  (define-key mew-summary-mode-map "\e\r" 'mew-summary-scroll-down)
  (define-key mew-summary-mode-map "g"    'mew-summary-goto-folder)
  (define-key mew-summary-mode-map "j"    'mew-summary-jump-message)
  (define-key mew-summary-mode-map "i"    'mew-summary-get)
  (define-key mew-summary-mode-map "a"    'mew-summary-reply)
  (define-key mew-summary-mode-map "A"    'mew-summary-reply-with-citation)
  (define-key mew-summary-mode-map "E"    'mew-summary-reedit)
  (define-key mew-summary-mode-map "\ee"  'mew-summary-edit-again)
  (define-key mew-summary-mode-map "f"    'mew-summary-forward)
  (define-key mew-summary-mode-map "F"    'mew-summary-multi-forward)
  (define-key mew-summary-mode-map "r"    'mew-summary-redist)
  (define-key mew-summary-mode-map "@"    'mew-summary-multi)
  (define-key mew-summary-mode-map "*"    'mew-summary-review)
  (define-key mew-summary-mode-map "y"    'mew-summary-save)
  (define-key mew-summary-mode-map "u"    'mew-summary-undo)
  (define-key mew-summary-mode-map "U"    'mew-summary-undo-all)
  (define-key mew-summary-mode-map "n"    'mew-summary-display-down)
  (define-key mew-summary-mode-map "p"    'mew-summary-display-up)
  (define-key mew-summary-mode-map "N"    'mew-summary-display-review-down)
  (define-key mew-summary-mode-map "P"    'mew-summary-display-review-up)
  (define-key mew-summary-mode-map "w"    'mew-summary-send)
  (define-key mew-summary-mode-map "B"    'mew-summary-burst)
  (define-key mew-summary-mode-map "J"    'mew-summary-join)
  (define-key mew-summary-mode-map "Z"    'mew-status-update)
  (define-key mew-summary-mode-map "#"    'mew-summary-print)
  (define-key mew-summary-mode-map "|"    'mew-summary-pipe-message)
  (define-key mew-summary-mode-map "q"    'mew-summary-suspend)
  (define-key mew-summary-mode-map "Q"    'mew-summary-quit)
  (define-key mew-summary-mode-map "C"    'mew-summary-config-imget)
  (define-key mew-summary-mode-map "\C-c\C-c" 'mew-summary-flush-queue)
  (define-key mew-summary-mode-map "\C-c\C-e" 'mew-summary-execute-external)
  (define-key mew-summary-mode-map "\C-c\C-f" 'mew-pgp-fetch-key)
  (define-key mew-summary-mode-map "\C-c\C-i" 'mew-summary-insert)
  (define-key mew-summary-mode-map "\C-c\C-s" 'mew-summary-isearch-forward)
  (define-key mew-summary-mode-map "\C-c\C-r" 'mew-summary-isearch-backward)
  (define-key mew-summary-mode-map "\C-c\C-o" 
    'mew-summary-jump-to-draft-buffer)
  (define-key mew-summary-mode-map "\el"  'mew-summary-recenter)
  (define-key mew-summary-mode-map "\et"  'mew-summary-uudecode)
  (define-key mew-summary-mode-map "\C-c\C-l" 'mew-summary-convert-local-cs)
  (define-key mew-summary-mode-map "\es"  'mew-summary-unshar)
  (define-key mew-summary-mode-map "v"    'mew-summary-toggle-disp-msg)
  (define-key mew-summary-mode-map "\ea"  'mew-summary-toggle-analysis)
  (define-key mew-summary-mode-map "\C-c\C-x" 'mew-summary-x-face)
  (define-key mew-summary-mode-map "\C-c\C-q" 'mew-kill-buffer)
  ;;
  ;; not provided in Virtual mode
  ;;
  (define-key mew-summary-mode-map "!"    'mew-summary-refile-again)
  (define-key mew-summary-mode-map "o"    'mew-summary-refile)
  (define-key mew-summary-mode-map "O"    'mew-summary-pack)
  (define-key mew-summary-mode-map "s"    'mew-summary-ls)
  (define-key mew-summary-mode-map "S"    'mew-summary-sort)
  (define-key mew-summary-mode-map "d"    'mew-summary-delete)
  (define-key mew-summary-mode-map "x"    'mew-summary-exec)
  (define-key mew-summary-mode-map "X"    'mew-summary-exec-current)
  (define-key mew-summary-mode-map "V"    'mew-summary-virtual)
  (define-key mew-summary-mode-map "/"    'mew-summary-search)
  (define-key mew-summary-mode-map "?"    'mew-summary-search-mark)
  (define-key mew-summary-mode-map "m"	  (make-sparse-keymap))
  (define-key mew-summary-mode-map "mo"   'mew-summary-mark-refile)
  (define-key mew-summary-mode-map "md"   'mew-summary-mark-delete)
  (define-key mew-summary-mode-map "m@"   'mew-summary-mark-multi)
  (define-key mew-summary-mode-map "m*"   'mew-summary-mark-review)
  (define-key mew-summary-mode-map "ms"   'mew-summary-mark-swap)
  (define-key mew-summary-mode-map "mr"   'mew-summary-mark-regexp)
  (define-key mew-summary-mode-map "ma"   'mew-summary-mark-all)
  (define-key mew-summary-mode-map "mu"   'mew-summary-mark-undo-all)
  (define-key mew-summary-mode-map "mS"   'mew-summary-mark-sort)
  (define-key mew-summary-mode-map "\C-c\C-k" 'mew-summary-kill-subprocess)
  (define-key mew-summary-mode-map "\C-c\C-b" 'mew-summary-exchange-point)
  ;;
  (if mew-xemacs-p
      (define-key mew-summary-mode-map 'button2 'mew-summary-mouse-show)
    (define-key mew-summary-mode-map [mouse-2] 'mew-summary-mouse-show)
    (easy-menu-define
     mew-summary-mode-menu
     mew-summary-mode-map
     "Menu used in Summary mode."
     mew-summary-mode-menu-spec))
  )

(defvar mew-summary-mode-toolbar-menu
  '("Mew Part Commands"
    ["Save" mew-summary-save t]
    ["Reply" mew-summary-reply t]
    ))

(defvar mew-summary-mode-popup-menu nil)

(defvar mew-touch-folder-p nil) 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; 
;;;

(defvar mew-field-delete
  '("Date:" "Message-Id:" "Return-Path:" "Received:"
    "From:" "Sender:" "Delivery-Date:" "X-Mailer:" "Lines:"
    "X-Dispatcher" "X-Resent-Dispatcher:" "X-UIDL:"
    "Resent.*:" "Prev-Resent.*:" "Forwarded:" "Replied:"
    "Config:"))

(defvar mew-last-shell-command "")

(defvar mew-summary-message-regex "^ *\\([0-9]+\\)")

(defvar mew-summary-edit-again-regex
  "----- Original message follows -----\\|----- Unsent message follows -----")

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Summary mode
;;;

(defun mew-summary-mode ()
  "Major mode for reading messages.
The keys that are defined for this mode are:

SPC	Read through messages. That is, display a message, scroll it, 
	and move-then-display another message. 
	See 'mew-summary-show-direction' to set 'up, 'down, 
	'next(current direction) or 'stop. Default is 'down.
DEL	Back-scroll this message. Unnecessary header fields are hidden
	over the window. Type DEL to see them when a message is displayed.
.	Force to display this message. If without MIME analysis, force 
	to analyze this message.

RET	Make this message scroll up with one line.
M-RET	Make this message scroll down with one line.
-	Make this message scroll down with one line.

C-n	Go to the next line.
C-p	Go to the previous line.
n	Move to below then display. Targets includes parts, messages 
	marked with '*', and non-marked messages. When called with 'C-u',
	parts are skipped.
p	Move to above then display. Targets includes parts, messages 
	marked with '*', and non-marked messages. When called with 'C-u',
	parts are skipped.
j	Jump to a message according to the number which you input.

i	Get +inbox asynchronously.
s	List this folder asynchronously. 
g	Go to the folder which you input.

w	Write a message. A new draft is prepared in Draft mode.
a	Answer to this message. A new draft is prepared in Draft mode. 
	Mew automatically decides To: and Cc:.
A	Answer to this message. A new draft is prepared in Draft mode. 
	Mew automatically decides To: and Cc: and cites the body.
f	Forward this message to a third person. A new draft is prepared in 
	Draft mode and this message is automatically attached.
F	Forward messages marked with '@' to a third person. A new draft 
	is prepared in Draft mode and this message is automatically 
	attached.

E	Edit this message again to send. Or edit this rfc822 part
	typically included MIME-encapsulated error message.
	In the +draft folder, it just edits the message. Otherwise, 
	copy the message to the +draft folder, then edit.
M-e	Edit an old fashioned error message in which the original message 
	is encapsulated after \"----- Original message follows -----\".
r	Re-distribute this message with Resent-To:. It is strongly 
	discouraged to use this command since beginners are always 
	confused. Please use 'f' instead.

v	Toggle \"Summary mode only\" and \"Summary & Message mode\". If 
	you choose \"Summary mode only\", you can quickly put the delete 
	marks since the next message is not displayed.
M-a	Toggle \"MIME analysis mode\" and \"non MIME analysis mode\". In 
	\"non MIME analysis mode\", the message is quickly displayed in 
	Message mode because MIME analysis is skipped.
M-l	Make the current line to the center of Summary mode.

o	Put the refile mark(default is 'o') on this message. 
	If already marked with 'o', it prints where this message 
	will be refiled. This can overlay other marks. When it overlays, 
	the cursor stays on the message. If it marks newly, displays 
	the next message.
!	Put a refile mark on this message according to the previous 
	refile folder.
d	Put the delete mark(default is 'D') on this message.
	This can overlay other marks. When it overlays, the cursor stays
	on the message. If it marks newly, displays the next message.

*	Put the review the '*' mark on this message. 
	Use 'N' or 'P' to jump to a message marked with '*'.
	It can overlay '@'. The cursor stays always.
	See also 'mo', 'md', 'mr', and 'ma'.
N	Jump to the message marked with '*' below.
P	Jump to the message marked with '*' above.

@	Put the multi the '@' mark on this message for 'F', 'M-s', 
	and 'M-t'. It can overlay the '*' mark. The cursor stays always.
u	Cancel the mark on this message.
U	Cancel all marks according to what you input.
x	Process marked messages. To cancel the '*' mark, use 'u' or 'U'.

mo	Put the refile mark onto all messages marked with '*'.
	This is very convenient to refile all messages picked by '?'.
md	Put the delete mark onto all messages marked with '*'.
mr	Put the '*' mark onto Mall messages matched to a regular expression.
ma	Put the '*' mark onto all messages which are not marked.
m*	Change the '@' mark into the '*' mark.
m@	Change the '*' mark into the '@' mark.
mu	Unmark all message marked with 'o' or 'D'.
ms	Swap the '@' mark and the '*' mark.
mS	Sort messages marked with '*'.

C-cC-s	Incremental search forward in Message mode.
C-cC-r	Incremental search backward in Message mode.

M-s	Apply \"unshar\" on messages marked with '@'.
M-t	Apply \"uudecode\" on messages marked with '@'.

/	Pick messages according to a pick pattern which you input, 
	then list them up.
?	Pick messages according to a pick pattern which you input, 
	then put the '*' mark onto them.
V	Go to Virtual mode which gives a single view to picked messages
	from multiple folders. Enter a virtual folder name, 
	comma-separated	folders, and pick pattern.

y	Copy this message or save this part as the file name which 
	you input.
#	Print this message or this part.
|	Send this message via pipe.

S	Sort messages and list them up again.
O	Pack messages and list them up again.
B	De-capsulate embedded messages in MIME format.
Z	Update the list of aliases. If you type 'C-u Z' the list 
	of folders are also updated in addition to that of aliases.
	If 'mew-use-folders-file-p' is t, the list of folders is 
	stored in \"~/Mail/.folders\".
C	Set the config value for imget.
q	Suspend Mew then switch to another buffer. All buffers of 
	Mew retain, so you can resume with buffer operations.
Q	Quit Mew. All buffers of Mew are erased.
C-cC-q	Kill this Summary mode.

C-cC-l	Convert to character sets used locally.
C-cC-x	Display xface.
C-cC-f	Fetch the PGP public key whose key ID appears in the X-Mew: field.

C-cC-k	Kill a process in Summary mode such as 'imget' and 'imls'.
	Sometime a process accidentally remains in Summary mode. 
	In this situation, you cannot execute 's', 'i', nor 'x'.
	Use this command to solve this problem.

Range means as follows;
	all, update, 
	<num1>-<num2>, <num>:+N, <num>:-N, 
	first:N, prev:N, next:N, last:N

Use 'all' to flush the summary buffer. 'update' means the range
between the last message included in Summary mode + 1 and the real last
message on the folder.

Pick pattern is as follews:
- field=string
	Match if the 'field' field contains the 'string' string.
	If you specify 'head', 'body' or 'all' as 'field', it means
	the entire header, the body, and the entire message, respectively.
- <pattern1> & <pattern2>
	Match if <pattern1> AND <pattern2>.
- <pattern1> | <pattern2>
	Match if <pattern1> OR <pattern2>.
- ! <pattern>
	Match if not <pattern>.
- ( <pattern> )
	Evaluate <pattern> first.
"
  (interactive)
  (setq major-mode 'mew-summary-mode)
  (setq mode-name "Summary")
  (setq mode-line-buffer-identification mew-mode-line-id)
  (use-local-map mew-summary-mode-map)
  (setq buffer-read-only t)
  (setq truncate-lines t)
  (make-local-variable 'tab-width)
  (make-local-variable 'zmacs-regions)
  (setq zmacs-regions nil)
  ;; xxx gee dirty
  (if (equal (nth (- (length mode-line-format) 2) mode-line-format)
	     '(-3 . "%p"))
      (setq mode-line-format
	    (let ((mlf (copy-sequence mode-line-format))
		  (l (length mode-line-format)))
	      (setcdr (nthcdr (- l 3) mlf)
		      '("[" mew-summary-buffer-left-msgs " more]" "-%-"))
	      mlf)
	    ))
  (if mew-xemacs-p
      (progn
	(if mew-icon-p
	    (set-specifier default-toolbar
			   (cons (current-buffer) mew-summary-toolbar)))
	(set-specifier scrollbar-height (cons (current-buffer) 0))
        (set-buffer-menubar current-menubar)
        (add-submenu nil mew-summary-mode-menu-spec)
	(mew-summary-make-popup-menu nil)
	))
  (mew-summary-highlight-setup)
  (mew-highlight-cursor-line)
  (run-hooks 'mew-summary-mode-hook)
  )

(defun mew-summary-make-popup-menu (virtual)
  (unless mew-summary-mode-popup-menu
    (easy-menu-define
     mew-summary-mode-popup-menu
     (if virtual
	 mew-virtual-mode-map
       mew-summary-mode-map)
     "Popup Menu used in Summary and Virtual mode."
     mew-summary-mode-menu-spec))
  (easy-menu-add mew-summary-mode-popup-menu))

(defun mew-summary-folder-name ()
  (cond 
   ((equal major-mode 'mew-summary-mode)
    (buffer-name))
   ((equal major-mode 'mew-virtual-mode)
    (save-excursion
      (beginning-of-line)
      (if (looking-at ".*\r \\(\\+.*\\) \\(.*\\)$")
	  (mew-match 1)
	nil
	)))
   (t nil)
   )
  )

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Folder
;;;

(defun mew-summary-goto-folder (&optional arg fld)
  "Go to the folder which you input.
If executed with 'C-u', the cursor always goes to the bottom of 
Summary mode."
  (interactive "P")
  (let* ((folder (or fld (mew-input-folder mew-inbox-folder)))
	 (dir (mew-expand-folder folder)))
    (cond ((mew-folder-newsp folder)
	   (mew-summary-goto-folder-subr folder arg))
	  ((mew-folder-imapp folder)
	   (if (or (file-directory-p dir)
		   (and (y-or-n-p
			 (format
			  "Cache directory for %s does not exist. Create it? "
			  folder))
			(mew-make-directory dir)))
	       (mew-summary-goto-folder-subr folder arg)))
	  (t   ;; mail or local news
	   (if (null dir)
	       (message "Folder is wrong")
	     (if (not (file-directory-p dir))
		 (message "No such folder %s" folder)
	       (mew-summary-goto-folder-subr folder arg)
	       (if mew-summary-trace-directory (cd dir))))))))

(defun mew-summary-goto-folder-subr (folder arg)
  (let (new-folder)
    (if (get-buffer folder)
	(switch-to-buffer folder)
      (mew-summary-folder-create folder)
      (setq new-folder t))
    (mew-summary-ls t (or arg new-folder))))

(defun mew-summary-folder-create (folder)
  (switch-to-buffer (get-buffer-create folder))
  (mew-summary-mode)
  (if (and mew-summary-cache-use
	   (not (mew-folder-newsp folder)))
      (let ((cache (mew-expand-folder folder mew-summary-cache-file))
	    (buffer-read-only nil))
	(if (file-exists-p cache)
	    (mew-frwlet mew-cs-scan mew-cs-noconv
	      (insert-file-contents cache)
	      (setq mew-summary-buffer-folder-cache-time 
		    (nth 5 (file-attributes cache)))
	      (mew-highlight-mark-region (point-min) (point-max))
	      )))))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Summary file cache
;;;

(defun mew-summary-folder-dir-newp ()
  ;; buffer switched
  (let* ((dir (file-chase-links (mew-expand-folder (buffer-name))))
	 (tdir (nth 5 (file-attributes dir)))
	 (da (car tdir))
	 (db (car (cdr tdir)))
	 (cache (expand-file-name mew-summary-cache-file dir))
	 (tcache (nth 5 (file-attributes cache)))
	 (fa (car tcache))
	 (fb (car (cdr tcache))))
    (cond
     ((null tdir) nil)
     ((null tcache) t) ;; no cache, do update!
     ((> da fa) t)
     ((= da fa) (if (> db fb) t nil)) ;; nil if same 
     (t nil)
     )
    ))

(defun mew-summary-folder-cache-oldp ()
  ;; buffer switched
  (let* ((file (mew-expand-folder (buffer-name) mew-summary-cache-file))
	 (tfile (nth 5 (file-attributes file)))
	 (fa (car tfile))
	 (fb (car (cdr tfile)))
	 (tbuf mew-summary-buffer-folder-cache-time)
	 (ba (car tbuf))
	 (bb (car (cdr tbuf))))
    (cond
     ((or (null tfile) (null tbuf)) nil) ;; xxx
     ((> fa ba) t)
     ((= fa ba) (if (> fb bb) t nil)) ;; nil if same 
     (t nil)
     )
    ))

(defun mew-summary-folder-cache-manage (folder)
  (switch-to-buffer folder)
  (if (and mew-summary-cache-use (not (mew-folder-newsp folder)))
      (let ((cache (mew-expand-folder folder mew-summary-cache-file)))
        (if (and (file-exists-p cache) (mew-summary-folder-cache-oldp))
	    (let ((buffer-read-only nil))
	      (erase-buffer)
	      (mew-frwlet mew-cs-scan mew-cs-noconv
		 (insert-file-contents cache))
              (setq mew-summary-buffer-folder-cache-time 
                    (nth 5 (file-attributes cache)))
	      (mew-summary-batch-unmark (list mew-mark-refile) nil)
	      (mew-highlight-mark-region (point-min) (point-max))
	      (set-buffer-modified-p nil))
	  )))
  (if (not (equal major-mode 'mew-summary-mode)) (mew-summary-mode))
  )

(defun mew-summary-folder-cache-save ()
  (let ((cache (mew-expand-folder (buffer-name) mew-summary-cache-file)))
    (if (file-writable-p cache)
	(mew-frwlet mew-cs-noconv mew-cs-scan
          (write-region (point-min) (point-max) cache nil 'no-msg)
          (setq mew-summary-buffer-folder-cache-time
                (nth 5 (file-attributes cache)))
          ))
    ))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; show
;;;

(defun mew-summary-toggle-analysis ()
  "Toggle \"MIME analysis mode\" and \"non MIME analysis mode\". In 
\"non MIME analysis mode\", the message is quickly displayed in 
Message mode because MIME analysis is skipped."
  (interactive)
  (cond 
   (mew-analysis
    (message "Skip MIME analysis")
    (mew-summary-goto-message)
    (setq mew-analysis nil))
   (t
    (message "Display message with MIME analysis")
    (setq mew-analysis t))
   )
  (mew-cache-flush)
  )

(defun mew-summary-show ()
  "Read through messages. That is, display a message, scroll it, 
and move-then-display another message. 
See 'mew-summary-show-direction' to set 'up, 'down, 
'next(current direction) or 'stop. Default is 'down."
  (interactive)
  (let* ((fld (mew-summary-folder-name))
	 (msg (mew-summary-message-number))
	 (ofld-msg (mew-current-get 'message))
	 (part (mew-syntax-number))
	 (opart (mew-current-get 'part))
	 (buf (buffer-name))
	 (next nil))
    (mew-summary-toggle-disp-msg 'on)
    (unwind-protect
	(progn
	  ;; message buffer
	  (cond 
	   (msg 
	    (mew-window-configure buf 'message)
	    (if (or (null ofld-msg)
		    (null (equal (cons fld msg) ofld-msg))
		    (and (equal (cons fld msg) ofld-msg) 
			 (null (equal opart part))))
		(mew-summary-display-message fld msg buf)
	      (if (mew-message-next-page)
		  (setq next t)))
	    )
	   (part
	    (mew-window-configure buf 'message)
	    (if (or (null opart) (null (equal opart part)))
		(mew-summary-display-part 
		 (mew-cache-decode-syntax (mew-cache-hit ofld-msg)) part)
	      (if (mew-message-next-page)
		  (setq next t)))
	    )
	   (t
	    (message "No message")
	    nil
	    )
	   ))
      (if (or msg part)
	  (progn
	    (mew-pop-to-buffer buf)
	    (mew-summary-recenter)
	    (mew-highlight-cursor-line)
	    (if next
		(cond 
		 ((equal mew-summary-show-direction 'down)
		  (mew-summary-display-down))
		 ((equal mew-summary-show-direction 'up)
		  (mew-summary-display-up))
		 ((equal mew-summary-show-direction 'next)
		  (mew-summary-display-next))
		 (t ())
		 )
	      )
	    )
	)
      ))
  (set-buffer-modified-p nil)
  )

(defun mew-summary-toggle-disp-msg (&optional arg)
  "Go to Virtual mode which gives a single view to picked messages
from multiple folders. Enter a virtual folder name, 
comma-separated	folders, and pick pattern."
  (interactive)
  (cond 
   ((equal arg 'on)
    (setq mew-summary-buffer-disp-msg t))
   ((equal arg 'off)
    (setq mew-summary-buffer-disp-msg nil))
   (t
    (setq mew-summary-buffer-disp-msg (not mew-summary-buffer-disp-msg))
    (if mew-summary-buffer-disp-msg
	(mew-summary-display)
      (mew-summary-goto-message)
      (mew-decode-syntax-delete)
      (mew-window-configure (current-buffer) 'summary)))))

(defun mew-summary-display (&optional notforce)
  "Force to display this message. If without MIME analysis, force 
to analyze this message."
  (interactive)
  (let* ((fld (mew-summary-folder-name))
	 (msg (mew-summary-message-number))
	 (ofld-msg (mew-current-get 'message))
	 (part (mew-syntax-number))
	 (opart (mew-current-get 'part))
	 (buf (buffer-name))
	 (cache nil)
	 (redisplay mew-summary-buffer-disp-msg))
    (cond 
     ((and (null msg) (null part))
      (message "No message"))
     (t
      (unwind-protect
	  (progn
	    ;; Interactive "." forces to display.
	    (if (or (interactive-p) redisplay)
		(progn 
		  (mew-summary-toggle-disp-msg 'on)
		  (mew-window-configure buf 'message))
	      (mew-window-configure (current-buffer) 'summary)
	      (set-buffer (mew-buffer-message)))
	    (cond
	     (msg
	      (if (or (not notforce)
		      (not ofld-msg)
		      (not (equal (cons fld msg) ofld-msg)))
		  (if (interactive-p)
		      (setq cache
			    (mew-summary-display-message
			     fld msg buf 'analysis nil)) ;; nil to force
		    (setq cache
			  (mew-summary-display-message
			   fld msg buf nil (not redisplay)))))
	      )
	     (part
	      (if (or (null opart) (null (equal opart part)))
		  (mew-summary-display-part 
		   (mew-cache-decode-syntax (mew-cache-hit ofld-msg)) part)))
	     (t (message "No message"))
	     ))
	(progn
	  (mew-pop-to-buffer buf)
	  (if (null notforce) (mew-summary-recenter))
	  (mew-highlight-cursor-line)
	  )
	)
      (set-buffer-modified-p nil)
      (or cache (mew-cache-hit ofld-msg)) ;; return value
      )
     )
    ))

(defun mew-summary-mode-line (buf)
  (save-excursion
    (set-buffer buf)
    ;; if not running process in this buffer
    ;; display how many messages are unread
    (if (null mew-summary-buffer-process)
	(let ((left (count-lines (point) (point-max))))
	  (if (equal left 0)
	      (setq mew-summary-buffer-left-msgs  "-");; local variable
	    (setq mew-summary-buffer-left-msgs (int-to-string (1- left))))))
    ))

(defun mew-summary-display-message (fld msg buf &optional analysis nodisplay)
  ;; message buffer
  (let ((hit nil) (zmacs-regions nil) (buffer-read-only nil)
	(file (mew-expand-folder fld msg))
	(ealist (if mew-xemacs-p (extent-list))))
    (erase-buffer) ;; for PGP pass phrase input
    (if mew-xemacs-p 
	(while ealist
	  (delete-extent (car ealist))
	  (setq ealist (cdr ealist))))
    (set-buffer-modified-p nil)
    (mew-decode-syntax-delete)
    (mew-summary-mode-line buf)
    (set-buffer-modified-p nil)
    (set-marker (mark-marker) nil) ;; kill mark for cite
    (mew-current-set 'message (cons fld msg))
    (mew-current-set 'part nil)
    (mew-current-set 'cache nil)
    (mew-decode-syntax-clear-privacy)
    (setq mew-decode-syntax nil)
    (if (not (or (file-exists-p file)
		 (mew-folder-newsp fld)
		 (mew-folder-imapp fld)))
	(message "File does not exist.")
      (cond
       ((equal fld mew-draft-folder)
	(insert-file-contents file))
       ((and (not analysis)
	     (not (mew-folder-newsp fld)) ;; xxx
	     (or (not mew-analysis)
		 (and (not (mew-folder-imapp fld))
		      (> (mew-file-size file) mew-file-max-size)
		      (null (mew-cache-hit (cons fld msg))))))
	(if (mew-folder-imapp fld)
	    (mew-piolet mew-cs-autoconv mew-cs-noconv
			(call-process mew-prog-imcat nil t nil
				      (format "--src=%s" fld) msg))
	  (insert-file-contents file))
	(mew-header-arrange nodisplay)
	(setq mew-message-citation 'header)
	(if (and (not (mew-folder-imapp fld))
		 (> (mew-file-size file) mew-file-max-size))
	    (message 
	     (concat
	      "Too large, MIME analysis was skipped. "
	      "To analyze, type "
	      (substitute-command-keys
	       "\"\\<mew-summary-mode-map>\\[mew-summary-display]\"."))))
	)
       (t
	(setq hit (mew-cache-message fld msg))
	(mew-current-set 'cache hit)
	(setq mew-decode-syntax (mew-cache-decode-syntax hit))
	(setq mew-decode-error  (mew-cache-decode-error hit))
	(if nodisplay
	    ()
	  (mew-decode-syntax-clear-privacy)
	  (if (mew-syntax-multipart-p (mew-syntax-get-part mew-decode-syntax))
	      (mew-decode-syntax-print msg mew-decode-syntax buf)
	    (mew-decode-syntax-set-privacy
	     (mew-syntax-get-part mew-decode-syntax) "body"))
	  (mew-mime-message/rfc822 mew-decode-syntax))
	(if mew-decode-error 
	    (message "MIME decoding error: %s" mew-decode-error))
	))
      (mew-decode-syntax-clear-privacy)
      (run-hooks 'mew-message-hook)
      )
    (set-buffer-modified-p nil)
;;    (let ((garbage-collection-message nil))
;;      (garbage-collect))
    hit ;; return value
    ))

(defun mew-summary-display-part (fullpart num &optional non-erase execute)
;; called in message buffer
  (let* ((syntax  (mew-syntax-get-entry-strnum fullpart num))
	 (begin   (mew-syntax-get-begin  syntax))
	 (end     (mew-syntax-get-end    syntax))
	 (ctl     (mew-syntax-get-ct syntax))
	 (ct      (car ctl))
	 (cdpl    (mew-syntax-get-cdp syntax))
	 (fname   (and cdpl (mew-syntax-get-member cdpl "filename")))
	 (cd      (mew-syntax-get-cd syntax))
	 (params  (cdr ctl))
	 (attr    (mew-attr-by-ct ct))
	 (program (mew-attr-get-prog attr))
	 (options (mew-attr-get-opt attr))
	 (async   (mew-attr-get-async attr))
	 (zmacs-regions nil)  ;; for XEmacs
	 file)
    (if (null non-erase)
	(let ((buffer-read-only nil)
	      (ealist (if mew-xemacs-p (extent-list))))
	  (erase-buffer)
	  (if mew-xemacs-p 
	      (while ealist
		(delete-extent (car ealist))
		(setq ealist (cdr ealist))))
	  (set-buffer-modified-p nil))) ;; xxx
    (set-marker (mark-marker) nil) ;; kill mark for cite
    (setq mew-message-citation 'noheader)
    ;;
    (if (symbolp program)
	(if (fboundp program)
	    (cond
	     ((eq program 'mew-mime-message/rfc822)
	      (funcall program syntax)) ;; for recursive MIME
	     ((eq program 'mew-mime-text/html)
	      (funcall program begin end params execute))
	     ((eq program 'mew-mime-external-body)
	      (funcall program begin end params execute))
	     ((eq program 'mew-mime-application/octet-stream)
	      (funcall program begin end params ct))
	     (t
	      (funcall program begin end params))
	     ))
      (save-excursion
	(set-buffer (mew-buffer-message))
	(let ((buffer-read-only nil))
	  (insert " ######  ######  #######  #####  ######     #    #     #\n"
		  " #     # #     # #     # #     # #     #   # #   ##   ##\n"
		  " #     # #     # #     # #       #     #  #   #  # # # #\n"
		  " ######  ######  #     # #  #### ######  #     # #  #  #\n"
		  " #       #   #   #     # #     # #   #   ####### #     #\n"
		  " #       #    #  #     # #     # #    #  #     # #     #\n"
		  " #       #     # #######  #####  #     # #     # #     #\n"
		  "\n\n")
	  (and ct (insert (format "Content-Type:\t%s\n" ct)))
	  (insert (format "Size:\t\t%d bytes\n" (- end begin)))
	  (and fname (insert (format "Filename:\t%s\n" fname)))
	  (and cd (insert (format "Description: \t%s\n" cd)))
	  (and program (insert (format "Program:\t%s\n" program)))
	  (if (not execute)
	      (progn
		(insert "\nTo execute this external command, type "
			(substitute-command-keys
			 "\\<mew-summary-mode-map>\\[mew-summary-execute-external].")
			"\nTo save this part, type "
			(substitute-command-keys
			 "\\<mew-summary-mode-map>\\[mew-summary-save].")
			"\nTo display this part in Message mode, type "
			(substitute-command-keys
			 "\\<mew-summary-mode-map>\\[mew-summary-insert].")))
	    (if (not (mew-which program exec-path))
		(message "Program %s is not found" program)
	      (setq file (mew-make-temp-name))
	      (set-buffer (mew-current-get 'cache))
	      ;; NEVER use call-process-region for privacy reasons
	      (if (mew-member-case-equal ct mew-mime-content-type-text-list)
	        (mew-frwlet mew-cs-noconv mew-cs-outfile
	         (write-region begin end file nil 'no-msg))
	        (mew-flet
	         (write-region begin end file nil 'no-msg)))
	      (if async
		  (mew-mime-start-process program options file)
		(mew-mime-call-process program options file))
	      )))))
    (mew-current-set 'part num) ;; should be after funcall
    (if (null non-erase)
	(run-hooks 'mew-message-hook))
    (set-buffer-modified-p nil)
    ))

(defun mew-summary-execute-external ()
  (interactive)
  (let* ((ofld-msg (mew-current-get 'message))
	 (part (mew-syntax-number))
	 (buf (buffer-name)))
    (unwind-protect
	(progn
	  (mew-summary-toggle-disp-msg 'on)
	  (mew-window-configure buf 'message)
	  (set-buffer (mew-buffer-message))
	  (mew-summary-display-part
	   (mew-cache-decode-syntax (mew-cache-hit ofld-msg)) part nil t))
      (mew-pop-to-buffer buf))))

(defun mew-summary-recenter ()
  "Make the current line to the center of Summary mode."
  (interactive)
  (if (or mew-summary-recenter-p
	  (interactive-p))
      (recenter (/ (- (window-height) 2) 2))
    ))

(defun mew-summary-display-top ()
  (interactive)
  (goto-char (point-min))
  (if mew-summary-buffer-disp-msg
      (mew-summary-display)
    (setq mew-summary-buffer-disp-msg t)))

(defun mew-summary-display-bottom ()
  (interactive)
  (goto-char (point-max))
  (if (not (bobp)) (forward-line -1))
  (if mew-summary-buffer-disp-msg
      (mew-summary-display)
    (setq mew-summary-buffer-disp-msg t)))

(defun mew-summary-mouse-show (e)
  (interactive "e")
  (mouse-set-point e)
  (beginning-of-line)
  (mew-summary-show))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; direction
;;;

(defun mew-summary-next ()
  (if (equal mew-summary-buffer-direction 'up)
      (mew-summary-up)
    (mew-summary-down))
  )

(defun mew-summary-message-next ()
  (if (equal mew-summary-buffer-direction 'up)
      (mew-summary-message-up)
    (mew-summary-message-down))
  )

(defun mew-summary-down ()
  (forward-line)
  (cond 
   ((re-search-forward 
     (concat mew-summary-message-regex 
	     "[ " (char-to-string mew-mark-review) "]\\|"
	     mew-syntax-number-text-regex)
     nil t nil)
    (beginning-of-line)
    (setq mew-summary-buffer-direction 'down)
    t)
   (t 
    (mew-decode-syntax-delete)
    (mew-current-set 'message nil)
    (forward-line -1)
    (mew-window-configure (current-buffer) 'summary)
    (message "No more message")
    nil)
   )
  )

(defun mew-summary-message-down (&optional nomsg)
  (forward-line)
  (cond 
   ((re-search-forward
     (concat mew-summary-message-regex "[ " (char-to-string mew-mark-review) "]")
     nil t nil)
    (beginning-of-line)
    (setq mew-summary-buffer-direction 'down)
    t)
   (nomsg
    nil)
   (t 
    (message "No more message")
    nil)
   )
  )

(defun mew-summary-up ()
  (interactive)
  (cond 
   ((re-search-backward
     (concat mew-summary-message-regex 
	     "[ " (char-to-string mew-mark-review) "]\\|"
	     mew-syntax-number-text-regex)
     nil t nil)
    (setq mew-summary-buffer-direction 'up)
    t)
   (t 
    (mew-decode-syntax-delete)
    (mew-window-configure (current-buffer) 'summary)
    (message "No more message")
    nil)
   ))

(defun mew-summary-message-up (&optional nochange mark)
  "Display above message or part."
  (interactive)
  (let ((regex (concat " "
		       (char-to-string mew-mark-review)
		       (if mark (char-to-string mark)))))
    (setq regex (concat mew-summary-message-regex "[" regex "]"))
    (cond 
     ((re-search-backward regex nil t nil)
      (if (null nochange)
	  (setq mew-summary-buffer-direction 'up))
      t)
     (t 
      (message "No more message")
      nil)
     ))
  )

(defun mew-summary-display-up (&optional arg)
  "Move to above then display. Targets includes parts, messages 
marked with '*', and non-marked messages. When called with 'C-u',
parts are skipped."
  (interactive "P")
  (beginning-of-line)
  (if arg
      (progn
	(mew-summary-goto-message)
	(mew-decode-syntax-delete)))
  (if (and (mew-summary-up) mew-summary-buffer-disp-msg)
      (mew-summary-display))
  )

(defun mew-summary-display-next ()
  (interactive)
  (cond
   ((and (mew-summary-next) mew-summary-buffer-disp-msg)
    (mew-summary-display)
    ))
  )

(defun mew-summary-display-down (&optional arg)
  "Move to below then display. Targets includes parts, messages 
marked with '*', and non-marked messages. When called with 'C-u',
parts are skipped."
  (interactive "P")
  (if arg
      (progn
	(mew-summary-goto-message)
	(mew-decode-syntax-delete)))
  (if (and (mew-summary-down) mew-summary-buffer-disp-msg)
      (mew-summary-display))
  )

(defun mew-summary-prev-page ()
  "Back-scroll this message. Unnecessary header fields are hidden
over the window. Type DEL to see them when a message is displayed."
  (interactive)
  (let ((fld (mew-summary-folder-name))
	(msg (mew-summary-message-number))
	(part (mew-syntax-number)))
    (cond
     ((not (or msg part))
      (message "No message or part here"))
     ((and msg (not (equal (cons fld msg) (mew-current-get 'message))))
      (message "Please show the current message first"))
     ;; part exist only when msg = current msg
     ((and part (not (equal part (mew-current-get 'part)))) 
      (message "Please show the current part first"))
     (t 
      (let* ((buf (current-buffer)))
	(unwind-protect
	    (progn
	      (mew-pop-to-buffer (mew-buffer-message))
	      (mew-message-prev-page))
	  (mew-pop-to-buffer buf)))
      )
     )
    ))

(defun mew-summary-scroll-up ()
  "Make this message scroll up with one line."
  (interactive)
  (let ((buf (current-buffer))
	(msg (mew-summary-message-number))
	(ofld-msg (mew-current-get 'message))
	(part (mew-syntax-number))
	(opart (mew-current-get 'part)))
    (cond
     ((or (and msg (null part) (string= msg (cdr ofld-msg)))
	  (and part (string= part opart)))
      (unwind-protect
	  (progn
	    (mew-window-configure buf 'message)
	    (mew-message-next-page 1))
	(mew-pop-to-buffer buf)))
     ((or msg part)
      (mew-summary-show))
     (t
      (message "No message or part here")))))

(defun mew-summary-scroll-down ()
  "Make this message scroll down with one line."
  (interactive)
  (let ((buf (current-buffer))
	(msg (mew-summary-message-number))
	(ofld-msg (mew-current-get 'message))
	(part (mew-syntax-number))
	(opart (mew-current-get 'part)))
    (cond
     ((or (and msg (null part) (string= msg (cdr ofld-msg)))
	  (and part (string= part opart)))
      (unwind-protect
	  (progn
	    (mew-window-configure buf 'message)
	    (mew-message-prev-page 1))
	(mew-pop-to-buffer buf)))
     ((or msg part)
      (mew-summary-show))
     (t
      (message "No message or part here")))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; to Draft mode
;;;

(defun mew-summary-send (&optional unconfig to cc subject)
  "Write a message. A new draft is prepared in Draft mode."
  (interactive)
  (let ((file (mew-folder-new-message mew-draft-folder))
	(find-file-hooks nil)
	(inhibit-quit t))
    (if (null unconfig)
	(mew-current-set 'window (current-window-configuration)))
    (mew-window-configure (current-buffer) 'draft)
    (unwind-protect
	(progn
	  (switch-to-buffer (find-file-noselect file))
	  (mew-draft-rename file)
	  (mew-draft-header subject nil to cc)
	  (mew-draft-mode) ;; hack hack mew-draft-buffer-header
	  )
      (sit-for 0)  ;; force to redisplay before save-buffer
      (save-buffer))) ;; to make sure not to use this draft again
  (if mew-touch-folder-p (mew-touch-folder mew-draft-folder))
  (message "Draft is prepared")
  )

(defun mew-summary-reply (&optional arg)
  "Answer to this message. A new draft is prepared in Draft mode. 
Mew automatically decides To: and Cc:."
  (interactive "P")
  (cond 
   ((or (mew-summary-message-number)
	(mew-syntax-number))
    (mew-current-set 'window (current-window-configuration))
    (let ((buf (buffer-name))
	  (file (mew-folder-new-message mew-draft-folder))
	  (find-file-hooks nil)
	  (inhibit-quit t)
	  from to cc newsgroups subject in-reply-to references
	  cbuf cache)
      (unwind-protect
	  (progn
	    (if (get-buffer (mew-buffer-message))
		(delete-windows-on (mew-buffer-message)))
	    (if (< (window-height) 25) (delete-other-windows))
	    (let ((split-window-keep-point t))
	      (split-window-vertically))
	    (switch-to-buffer-other-window (find-file-noselect file))
	    (mew-draft-rename file)
	    (setq cbuf (current-buffer)) ;; draft
	    (mew-pop-to-buffer buf) 
	    ;; summary or virtual
	    ;;
	    (if arg
		(set-buffer (mew-buffer-message))
	      (setq cache (mew-summary-display 'notforce))
	      (if cache
		  (set-buffer cache)
		(set-buffer (mew-buffer-message))))
	    ;; now cache buffer
	    (setq from (mew-header-address-collect '("From:")))
	    (cond 
	     ;; This message was sent by me.
	     ;; So, maintain To: and Cc:.
	     ((and from (string-match (concat "^" mew-mail-address "$")
				      (car from)))
	      (setq to (mew-header-address-collect '("To:" "Apparently-To:")))
 	      (if (and (null (cdr to))
		       (car to) ;; not null
		       (string-match ":;" (car to)))
		  (setq to (or (mew-header-address-collect '("Reply-To:"))
			       from)))
	      (setq cc (mew-header-address-collect '("Cc:"))))
	     ;;
	     (t
	      (cond 
	       ((mew-header-get-value "Reply-To:")
		(setq to (mew-header-address-collect mew-replyto-to-list))
		(setq cc (mew-header-address-collect mew-replyto-cc-list)))
	       (t
		(setq to (mew-header-address-collect mew-noreplyto-to-list))
		(setq cc (mew-header-address-collect mew-noreplyto-cc-list)))
	       )
	      )
	     )
	    (setq newsgroups (or (mew-header-get-value "Followup-To:")
				 (mew-header-get-value "Newsgroups:")))
	    (if (and newsgroups (mew-case-equal newsgroups "poster"))
		(setq newsgroups nil))
	    (setq subject (mew-header-get-value "Subject:"))
	    (if (and subject (not (string-match mew-reply-regex subject)))
		(setq subject (concat mew-reply-string subject)))
	    (setq in-reply-to (mew-header-get-value "Date:"))
	    (setq references (mew-header-get-value "Message-ID:"))
	    ;;
	    (mew-pop-to-buffer cbuf) ;; draft
	    (mew-draft-header subject nil to cc newsgroups in-reply-to references)
	    (undo-boundary)
	    (mew-draft-mode) ;; for hilight
	    (sit-for 0)
	    )
	(save-buffer))) ;; to make sure not to use this draft again
    (if mew-touch-folder-p (mew-touch-folder mew-draft-folder))
    (message "Draft is prepared")
    t) ;; preparation is succeeded.
   (t 
    (message "No message")
    nil) ;; preparation is failed.
   )
  )

(defun mew-summary-reply-with-citation (&optional arg)
  "Answer to this message. A new draft is prepared in Draft mode. 
Mew automatically decides To: and Cc: and cites the body."
  (interactive "P")
  (if (not mew-summary-buffer-disp-msg)
      (message "You can't reply with cite. Type \"%s\" first."
	       (substitute-command-keys
		"\\<mew-summary-mode-map>\\[mew-summary-toggle-disp-msg]"))
    (if (mew-summary-reply arg)
	(let ((p (point)) (m (point-max)))
	  ;; mew-draft-mode-hook may move the cursor somewhere.
	  ;; Let's make sure that the cursor locates on the top of the body
	  ;; for citation.
	  (goto-char (point-min))
	  (re-search-forward mew-eoh2 nil t)
	  (forward-line 1)
	  (beginning-of-line)
	  (run-hooks 'mew-before-cite-hook)
	  (mew-draft-cite)
	  (if (not (equal p m))
	      (goto-char p))))))

(defun mew-summary-forward ()
  "Forward this message to a third person. A new draft is prepared in 
Draft mode and this message is automatically attached."
  (interactive)
  (if (not (or (mew-summary-message-number) (mew-syntax-number)))
      (message "No message")
    (mew-current-set 'window (current-window-configuration))
    (if (mew-summary-in-multi-p)
	(progn
	  (mew-summary-message-up t) ;; no direction change
	  (mew-summary-goto-message)
	  (mew-summary-display) 
	  )
      )
    (let* ((buf (buffer-name))
	   (fld (mew-summary-folder-name))
	   (msg (mew-summary-message-number))
	   (find-file-hooks nil)
	   (inhibit-quit t)
	   (file (mew-folder-new-message mew-draft-folder))
	   (dirname (file-name-nondirectory file))
	   subject fwsubject cbuf)
      (unwind-protect
	  (progn
	    (delete-other-windows)
	    (let ((split-window-keep-point t))
	      (split-window-vertically))
	    (switch-to-buffer-other-window (find-file-noselect file))
	    (mew-draft-rename file)
	    (setq cbuf (current-buffer)) ;; draft
	    (mew-pop-to-buffer buf)
	    ;;
	    (let ((mew-analysis t))
	      (set-buffer (mew-summary-display))) ;; force to display
	    ;; now cache buffer
	    (setq subject (mew-header-get-value "Subject:"))
	    (if (and subject (not (string-match mew-forward-regex subject)))
		(setq fwsubject (concat mew-forward-string subject))
	      (setq fwsubject subject))
	    (mew-pop-to-buffer cbuf) ;;; draft
	    ;;
	    (mew-draft-header fwsubject 'nl)
	    (mew-draft-mode)
	    (mew-draft-multi-copy file (list (cons fld msg)))
	    (setq mew-encode-syntax
		  (mew-encode-syntax-initial-multi dirname 1))
	    (save-excursion
	      (mew-draft-prepare-attachments)
	      )
	    ;; XEmacs doesn't draw attachments unless sit for 0...
	    (sit-for 0) 
	    ;; XEmacs doesn't draw toolbar, so...
	    (if (and mew-icon-p
                     (specifier-instance default-toolbar-visible-p))
		(progn
		  (set-specifier default-toolbar-visible-p nil)
		  (set-specifier default-toolbar-visible-p t)
		  ))
	    )
	(save-buffer))) ;; to make sure not to use this draft again
    (if mew-touch-folder-p (mew-touch-folder mew-draft-folder))
    (message "Draft is prepared"))
  )

(defun mew-summary-multi-forward ()
  "Forward messages marked with '@' to a third person. A new draft 
is prepared in Draft mode and this message is automatically 
attached."
  (interactive)
  (let ((fld-msg (mew-summary-mark-collect2 mew-mark-multi)))
    (cond
     (fld-msg
      (mew-current-set 'window (current-window-configuration))
      (let* ((file (mew-folder-new-message mew-draft-folder))
	     (dirname (file-name-nondirectory file))
	     (find-file-hooks nil)
	     (inhibit-quit t))
	(unwind-protect
	    (progn
	      (delete-other-windows)
	      (let ((split-window-keep-point t))
		(split-window-vertically))
	      (switch-to-buffer-other-window (find-file-noselect file))
	      (mew-draft-rename file)
	      (mew-draft-header nil 'nl)
	      (mew-draft-mode)
	      (mew-draft-multi-copy file fld-msg)
	      (setq mew-encode-syntax
		    (mew-encode-syntax-initial-multi dirname (length fld-msg)))
	      (save-excursion
		(mew-draft-prepare-attachments)
		)
	      ;; XEmacs doesn't draw attachments unless sit for 0...
	      (sit-for 0) 
	      ;; XEmacs doesn't draw toolbar, so...
	      (if (and mew-icon-p
                       (specifier-instance default-toolbar-visible-p))
		  (progn
		    (set-specifier default-toolbar-visible-p nil)
		    (set-specifier default-toolbar-visible-p t)
		    ))
	      )
	  (save-buffer)) ;; to make sure not to use this draft again
    (if mew-touch-folder-p (mew-touch-folder mew-draft-folder))
	(message "Draft is prepared"))
      )
     (t (message "No marks"))
     )
    ))

(defun mew-draft-multi-copy (draft fld-msg-list)
  (let* ((mimefolder (mew-draft-to-mime draft))
	 (mimedir (mew-expand-folder mimefolder)))
    (if (null (file-directory-p mimedir))
	(mew-make-directory mimedir)
      (if (null (mew-directory-empty-p mimedir))
	  (if (y-or-n-p (format "%s is not empty. Delete it? " mimefolder))
	      (progn
		(mew-delete-directory-recursively mimedir)
		(mew-make-directory mimedir))
	    )))
    (while fld-msg-list
      (mew-symbolic-link (mew-expand-folder
			  (car (car fld-msg-list))
			  (cdr (car fld-msg-list)))
			 (mew-folder-new-message mimefolder))
      (setq fld-msg-list (cdr fld-msg-list)))
    ))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Edit again
;;;

(defun mew-summary-edit-header ()
  (mew-header-delete-lines mew-field-delete)
  (let ((ct (mew-header-get-value mew-ct:)))
    (if (and ct (equal mew-ct-txt
		       (capitalize (car (mew-header-syntax-list ct)))))
	(mew-header-delete-lines (list mew-ct: mew-cte:))))
  ;; delimiter setup
  ;; Both "^$" and "----" are OK.
  (goto-char (point-min))
  (re-search-forward mew-eoh2 nil t)
  (beginning-of-line)
  (let ((beg (point)))
    (forward-line)
    (delete-region beg (point)))
  ;; Dcc or Fcc:
  (if (and mew-fcc (not (mew-header-get-value "Fcc:")))
      (mew-header-insert-here "Fcc:" mew-fcc))
  (if (and mew-dcc (not (mew-header-get-value "Dcc:"))) 
      (mew-header-insert-here "Dcc:" mew-dcc))
  (if (and mew-from (not (mew-header-get-value "From:")))
      (mew-header-insert-here "From:" mew-from))
  (if (and mew-reply-to (not (mew-header-get-value "Reply-To:")))
      (mew-header-insert-here "Reply-To:" mew-reply-to))
  (if (and mew-x-mailer (not (mew-header-get-value "X-Mailer:")))
      (mew-header-insert-here "X-Mailer:" mew-x-mailer))
  ;; xxx Config:?
  ;; (if mew-config-insert-when-prepared
  ;;    (mew-draft-insert-config 'here))
  (setq mew-draft-buffer-header (point-marker))
  (insert mew-header-separator "\n")
  )

(defun mew-summary-reedit ()
  "Edit this message again to send. Or edit this rfc822 part
typically included MIME-encapsulated error message.
In a draft folder, it just edits the message. Otherwise, 
copy the message to draft folder, then edit."
  (interactive)
  (let* ((msg (mew-summary-message-number)) ;; must get msg here
	(part (mew-syntax-number))
	(fld (mew-summary-folder-name))
	(rename nil)
	(cache (if part (mew-current-get 'cache)))
	(syntax (if part (mew-syntax-get-entry-strnum
			  (mew-cache-decode-syntax cache) part)))
	(ct (if syntax (capitalize (car (mew-syntax-get-ct syntax)))))
	(find-file-hooks nil)
	(inhibit-quit t))
    (cond
     ((and (null msg) (null part))
      (message "No message"))
     ((and part (not (equal (capitalize mew-ct-msg) ct)))
      (message "Can't reedit %s" ct))
     (t
      (mew-current-set 'window (current-window-configuration))
      (mew-window-configure (current-buffer) 'summary)
      (unwind-protect
	  (progn
	    (if (or part (not (equal fld mew-draft-folder)))
		(setq rename (mew-folder-new-message mew-draft-folder))
	      (setq rename (mew-expand-folder fld msg)))
	    ;; prepare draft file
	    (switch-to-buffer (find-file-noselect rename))
	    (cond
	     (part
	      (insert-buffer-substring
	       cache
	       (mew-syntax-get-begin syntax)
	       (mew-syntax-get-end (mew-syntax-get-part syntax)))) ;;; xxxx
	     ((not (equal fld mew-draft-folder))
	      (insert-file-contents (mew-expand-folder fld msg))
	      )
	     ;; if fld equal mew-draft-folder, message already exists.
	     )
	    (mew-draft-rename rename)
	    (mew-summary-edit-header)
	    (mew-draft-mode)
	    )
	(save-buffer))
      (if mew-touch-folder-p (mew-touch-folder mew-draft-folder))
      (message "Draft is prepared"))
     )
    ))

(defun mew-summary-edit-again ()
  "Edit an old fashioned error message in which the original message 
is encapsulated after \"----- Original message follows -----\"."
  (interactive)
  (let ((msg (mew-summary-message-number)) ;; must get msg here
	(fld (mew-summary-folder-name))
	(rename nil)
	(find-file-hooks nil)
	(inhibit-quit t))
    (cond 
     ((eobp) (message "No message"))
     ((null msg)
      (message "Please use this command on a message"))
     (t
      (mew-current-set 'window (current-window-configuration))
      (mew-window-configure (current-buffer) 'summary)
      (unwind-protect
	  (progn
	    (cond
	     ((not (equal fld mew-draft-folder))
	      (setq rename (mew-folder-new-message mew-draft-folder)))
	     (t 
	      (setq rename msg))
	     )
	    ;; prepare draft file
	    (switch-to-buffer 
	     (find-file-noselect 
	      (mew-expand-folder mew-draft-folder rename)))
	    (cond
	     ((not (equal fld mew-draft-folder))
	      (insert-file-contents (mew-expand-folder fld msg))
	      )
	     ;; if fld equal mew-draft-folder, message already exists.
	     )
	    (mew-draft-rename rename)
	    (goto-char (point-min))
	    (if (re-search-forward mew-summary-edit-again-regex nil t)
		(progn
		  (forward-line)
		  ;; skip blank lines
		  (while (looking-at "^$") (forward-line))
		  (delete-region (point-min) (point))
		  ))
	    (mew-summary-edit-header)
	    (mew-draft-mode)
	    )
	(save-buffer))
      (if mew-touch-folder-p (mew-touch-folder mew-draft-folder))
      (message "Draft is prepared"))
     )
    ))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Packing
;;;

(defun mew-summary-pack ()
  "Pack messages and list them up again."
  (interactive)
  (let ((folder (buffer-name))
	lines)
    (if (not (mew-summary-exclusive-p))
	()
      (mew-mark-clean-up)
      (if (and mew-ask-pack (not (y-or-n-p (format "Pack %s? " folder))))
	  ()
	(setq lines (mew-summary-mark-collect3 mew-mark-review))
	(setq mew-summary-buffer-process t)
	(mew-im-call-process-no-output
	 (concat "Packing " folder)
	 mew-prog-impack
	 (format "--src=%s" folder))
	(setq mew-summary-buffer-process nil)
	(let ((buffer-read-only nil)) (erase-buffer)) ;; for update
	(mew-summary-scan-body mew-prog-imls
			       'mew-summary-mode
			       folder
			       mew-cs-scan
			       nil nil nil
			       lines)))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Good old days...
;;;

(defun mew-summary-unshar ()
  "Apply \"unshar\" on messages marked with '@'."
  (interactive)
  (let ((fld-msg (nreverse (mew-summary-mark-collect2 mew-mark-multi)))
	(files nil)
	(dir nil))
    (if (not fld-msg)
	(message "No marked messages")
      (if (not (y-or-n-p (format "Execute %s for these messages? " 
				 mew-prog-unshar)))
	  ()
	(setq dir (mew-input-directory-name
		   (file-name-as-directory mew-save-dir)))
	(while fld-msg
	  (setq files (cons (mew-expand-folder
			     (car (car fld-msg))
			     (cdr (car fld-msg)))
			    files))
	  (setq fld-msg (cdr fld-msg))
	  )
	(message "Executing %s ... " mew-prog-unshar)
	(save-excursion
	  (mew-set-buffer-tmp dir)
	  (apply (function call-process) mew-prog-unshar nil nil nil files)
	  )
	(message "Executing %s ... done" mew-prog-unshar)
	))
    ))

(defun mew-summary-uudecode ()
  "Apply \"uudecode\" on messages marked with '@'."
  (interactive)
  (let ((fld-msg (nreverse (mew-summary-mark-collect2 mew-mark-multi)))
	(files nil)
	(dir nil)
	(tarfile nil)
	(case-fold-search nil))
    (if (not fld-msg)
	(message "No marked messages")
      (if (not (y-or-n-p (format "Execute %s for these messages? "
				 mew-prog-uumerge)))
	  ()
	(setq dir (mew-input-directory-name
		   (file-name-as-directory mew-save-dir)))
	(while fld-msg
	  (setq files (cons (mew-expand-folder
			     (car (car fld-msg))
			     (cdr (car fld-msg)))
			    files))
	  (setq fld-msg (cdr fld-msg))
	  )
	(save-excursion
	  (mew-set-buffer-tmp dir)
	  (message "Executing %s ..." mew-prog-uumerge)
	  (apply (function call-process) mew-prog-uumerge nil t nil files)
	  (message "Executing %s ... done" mew-prog-uumerge)
	  (goto-char (point-min))
	  (if (looking-at "^uumerge:")
	      (message "Failed to executing %s" mew-prog-uumerge)
	    (forward-line)
	    (setq tarfile (mew-buffer-substring (point-min) (1- (point))))
	    (setq tarfile
		  (mew-summary-prog-exec mew-prog-compress "-df" "Z" tarfile))
	    (setq tarfile
		  (mew-summary-prog-exec mew-prog-gzip "-df" "gz" tarfile))
	    (if (string-match "^\\(.*\\)\\.tar$" tarfile)
		(if (not (y-or-n-p (format "Execute %s for %s? " 
					   mew-prog-tar tarfile)))
		    ()
		  (message (format "Executing %s for %s ... "
				    mew-prog-tar tarfile))
		  (call-process mew-prog-tar nil nil nil "-xf" tarfile)
		  (message (format "Executing %s for %s ... done"
				   mew-prog-tar tarfile))
		  ))
	    ))
	))
    ))


(defun mew-summary-prog-exec (prog opts suffix tarfile)
  (if (string-match (format "^\\(.*\\)\\.%s$" suffix) tarfile)
      (let ((data (match-data)))
	;; save match data here for OS/2
	(unwind-protect
	    (if (not (y-or-n-p (format "Execute %s for %s? " prog tarfile)))
		tarfile
	      (message (format "Executing %s for %s ... " prog tarfile))
	      (call-process prog nil nil nil opts tarfile)
	      (message (format "Executing %s for %s ... done" prog tarfile))
	      (set-match-data data)
	      (mew-match 1 tarfile))))
    tarfile))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Misc
;;;

(defun mew-summary-save (&optional user-coding-system)
  "Copy this message or save this part as the file name which 
you input."
  (interactive
   (list
    (and mew-mule-p current-prefix-arg
	 (read-coding-system "Coding-system: "))))
  (let* ((msg (mew-summary-message-number))
	 (part (mew-syntax-number))
	 (action "Save")
	 (append-p nil)
	 (cbuf (mew-summary-folder-name))
	 (doit nil)
	 (cache (if part (mew-current-get 'cache)))
	 (syntax (if part (mew-syntax-get-entry-strnum
			   (mew-cache-decode-syntax cache) part)))
	 (cdpl (if syntax (mew-syntax-get-cdp syntax)))
	 file)
    (if (not (or msg part))
	(message "No message or part here")
      (if (car cdpl)
	  ;; even if "inline", we can use "filename"
	  (setq file (mew-syntax-get-member cdpl "filename")))
      (setq file (mew-input-file-name 
		  nil (concat (file-name-as-directory mew-save-dir) file)))
      (if (not (file-exists-p file))
	  (setq doit t)
	(if (null mew-file-append-p)
	    (setq action "Overwrite")
	  (setq action "Append")
	  (setq append-p t))
	(cond
	 (part
	  (if (y-or-n-p (format "%s part %s to %s? " action part file))
	      (setq doit t)))
	 (msg
	  (if (y-or-n-p (format "%s message %s to %s? " action msg file))
	      (setq doit t)))
	 )))
    (if (not doit)
	(message "Didn't save anything.")
      (cond
       (part
	(save-excursion
	  (set-buffer (mew-current-get 'cache))
	  (let* ((case-fold-search t)
		 (syntax (mew-syntax-get-entry-strnum
			  (mew-cache-decode-syntax
			   (mew-current-get 'cache)) part))
		 (begin (mew-syntax-get-begin syntax))
		 (end (mew-syntax-get-end syntax))
		 (ct (car (mew-syntax-get-ct syntax))))
	    (if (string-match mew-ct-msg ct)
		(setq end (mew-syntax-get-end
			   (mew-syntax-get-part syntax)))) ;;; xxxx
	    (if (mew-member-case-equal ct mew-mime-content-type-text-list)
		(mew-frwlet
		 mew-cs-noconv (or user-coding-system mew-cs-outfile)
		 (write-region begin end file append-p))
	      (mew-flet
	       (write-region begin end file append-p))
	      ))
	  (message "Saved to %s" file))
	)
       (msg
	(save-excursion
	  (mew-set-buffer-tmp)
	  (mew-flet
	   (insert-file-contents (mew-expand-folder cbuf msg))
	   (if (and mew-mule-p user-coding-system (not append-p))
	       (progn
		 (mew-cs-decode-region (point-min) (point-max) 
				       mew-cs-autoconv)
		 (mew-cs-encode-region (point-min) (point-max) 
				       user-coding-system)))
	   (write-region (point-min) (point-max) file append-p nil nil))
	  (message "Saved to %s" file))
	)
       ))
    ))

(defun mew-summary-print ()
  "Print this message or this part."
  (interactive)
  (mew-summary-display)
  (save-excursion
    (set-buffer (mew-buffer-message))
    (save-restriction
      (widen)
      (if (y-or-n-p "Print this message? ")
	  (funcall mew-print-function))
      )
    ))

(defun mew-summary-jump-message (&optional msg)
  "Jump to a message according to the number which you input."
  (interactive)
  (let ((here (point)))
    (if (null msg) (setq msg (read-string "Message No. : " "")))
    (cond 
     ((equal msg "") ())
     ((equal msg t)
      (goto-char (point-max))) ;; (forward-line -1)
     (t 
      (goto-char (point-min))
      (if (re-search-forward (format "^[ ]*%s[^0-9]+" msg) nil t) ;; xxx regex?
	  (beginning-of-line)
	(goto-char here))))
    ))

(defun mew-summary-jump-to-draft-buffer ()
  "Jump to the newest draft if exists."
  (interactive)
  (let ((bufs (buffer-list))
	draft-bufs)
    (while bufs
      (if (string-match (concat "^" (regexp-quote mew-draft-folder))
			(buffer-name (car bufs)))
	  (setq draft-bufs (cons (buffer-name (car bufs)) draft-bufs)))
      (setq bufs (cdr bufs)))
    (cond
     ((null draft-bufs)
      (message "No draft buffer exist!"))
     (t
      (switch-to-buffer
       (car (sort draft-bufs (function (lambda (a b) (not (string< a b)))))))
      )
     )
    ))

(defun mew-summary-convert-local-cs (&optional code)
  "Convert to character sets used locally."
  (interactive
   (list
    (and mew-mule-p current-prefix-arg
         (read-coding-system "Coding-system: "))))
  (if mew-mule-p
      (save-excursion
	(set-buffer (mew-buffer-message))
	(goto-char (point-min))
	(if (eq mew-message-citation 'header)
	    (progn
	      (re-search-forward mew-eoh nil t)
	      (forward-line)
	      ))
	(let ((buffer-read-only nil))
	  (mew-cs-decode-region (point) (point-max)
				(if code code mew-cs-rfc822-trans))
	  )
	))
  )

(defun mew-summary-redist ()
  "Re-distribute this message with Resent-To:. It is strongly 
discouraged to use this command since beginners are always 
confused. Please use 'f' instead."
  (interactive)
  (if (not (mew-summary-message-number))
      (message "No message")
    (mew-current-set 'window (current-window-configuration))
    (let* ((to (mew-input-address "Resent-To:"))
	   (cc (if mew-ask-cc (mew-input-address "Resent-Cc:")))
	   (srcnum (mew-summary-message-number))
	   (srcfile (mew-expand-folder (mew-summary-folder-name) srcnum))
	   (hdrfile (mew-folder-new-message mew-draft-folder))
	   (find-file-hooks nil)
	   (inhibit-quit t))
      (if (equal to "") (setq to nil))
      (if (equal cc "") (setq cc nil))
      (if (not (or to cc))
	  (message "Not re-distributed since both to and cc wasn't specified.")
	(save-excursion
	  (set-buffer (find-file-noselect hdrfile))
	  (and to (mew-header-insert-here "Resent-To:" to))
	  (and cc (mew-header-insert-here "Resent-Cc:" cc))
	  (save-buffer) 
	  (mew-im-call-process-no-output
	   "Redistributing"
	   mew-prog-imput
	   "--dist=1"
	   (format "--distmsg=%s" srcfile)
	   (format "--message=%s" hdrfile))
	  (kill-buffer (current-buffer))
	  ))
      ))
  )

(defun mew-summary-isearch-forward ()
  "Incremental search forward in Message mode."
  (interactive)
  (let ((cwin (get-buffer-window (current-buffer)))
	(mwin (get-buffer-window (mew-buffer-message))))
    (if mwin 
	(progn
	  (select-window mwin)
	  (unwind-protect
	      (isearch-forward)
	    (select-window cwin))
	  ))
    ))

(defun mew-summary-isearch-backward ()
  "Incremental search backward in Message mode."
  (interactive)
  (let ((cwin (get-buffer-window (current-buffer)))
	(mwin (get-buffer-window (mew-buffer-message))))
    (if mwin 
	(progn
	  (select-window mwin)
	  (unwind-protect
	      (isearch-backward)
	    (select-window cwin))
	  ))
    ))

(defun mew-summary-x-face ()
  "Display xface."
  (interactive)
  (save-excursion
    (let (xface)
      (set-buffer (mew-buffer-message))
      (if (null (setq xface (mew-header-get-value "X-Face:")))
	  ()
	(mew-set-buffer-tmp)
	(insert xface)
	(let ((filters mew-x-face-filter) file)
	  (while filters
	    ;; call-process-region is OK...
	    (mew-plet
	       (call-process-region (point-min) (point-max) 
				    (car filters)
				    'delete t nil))
	    (setq filters (cdr filters))
	    )
	  (setq file (mew-make-temp-name))
	  ;; NEVER use call-process-region for privary reasons
	  (mew-flet
	   (write-region (point-min) (point-max) file nil 'no-msg))
	  (mew-mime-start-process mew-x-face-prog mew-x-face-args file)
	  )
	))
    ))

(defun mew-summary-pipe-message (prefix command)
  "Send this message via pipe."
  (interactive
   (list current-prefix-arg 
	 (read-string "Shell command on message: " mew-last-shell-command)))
  (mew-summary-display)
  (save-excursion
    (set-buffer (mew-buffer-message))
    (widen)
    (if (string-equal command "")
	(setq command mew-last-shell-command))
    (goto-char (point-min)) ; perhaps this line won't be necessary
    (if prefix
	(search-forward "\n\n"))
    (shell-command-on-region (point) (point-max) command nil)
    (setq mew-last-shell-command command))
  (mew-message-narrow-to-page)
  )

;;
;; Burst
;;

(defun mew-summary-burst ()
  "De-capsulate embedded messages in MIME format."
  (interactive)
  (cond
   ((eobp) (message "No message"))
   ((not (or (mew-summary-message-number) (mew-syntax-number)))
    (message "No message"))
   (t
    (save-excursion
      (mew-summary-goto-message)
      (let ((target (mew-expand-folder (mew-summary-folder-name)
				       (mew-summary-message-number)))
	    n m mstr syntax len entry folder multi)
	(message "Bursting ... ")
	(set-buffer (get-buffer-create mew-buffer-burst))
	(mew-erase-buffer)
	(mew-frwlet mew-cs-noconv-eol mew-cs-noconv
	  (insert-file-contents target))
	(setq syntax (mew-decode-message (mew-decode-syntax-rfc822-head) t))
	(setq multi (mew-syntax-get-part syntax))
	(if (not (mew-syntax-multipart-p multi))
	    (message "Can't burst")
	  (setq folder (mew-input-folder mew-inbox-folder))
	  (if (not (mew-folder-check folder))
	      (message "%s is wrong. Nothing was processed." folder)
	    (setq mstr (mew-folder-new-message folder t))
	    (if (not (stringp mstr))
		(message "Error in %s. Nothing was processed" folder)
	      (setq m (string-to-int mstr))
	      (setq len (- (length multi) mew-syntax-magic))
	      (setq n 1)
	      (while (<= n len)
		(setq entry (mew-syntax-get-entry syntax (list n)))
		(if (not (mew-case-equal (car (mew-syntax-get-ct entry))
					 mew-ct-msg))
		    ()
		  (mew-frwlet mew-cs-noconv mew-cs-noconv-eol
		    (write-region
		     (mew-syntax-get-begin entry)
		     (mew-syntax-get-end entry)
		     (mew-expand-folder folder (int-to-string m))))
		  (setq m (1+ m)))
		(setq n (1+ n))
		)
	      (message "Bursting ... done")
	      (message "Messages from %s to %d were extracted in %s"
		       mstr (1- m) folder)
	      (if mew-touch-folder-p (mew-touch-folder folder))
	      ))))))))

;;
;;  Join message/partial message
;;
(defun mew-summary-join ()
  (interactive)
  (let ((fld-msg (or (mew-summary-mark-collect2 mew-mark-multi)
		     (list (mew-current-get 'message))))
	(folder (mew-input-folder mew-inbox-folder))
	fld msgs)
    (if fld-msg
	(progn
	  (setq fld (car (car fld-msg)))
	  (setq msgs (mapcar 'cdr fld-msg)))
      (setq fld (car (mew-current-get 'message)))
      (setq msgs (cdr (mew-current-get 'message))))
    (message "Joining marked messages to %s ..." fld)
    (apply 'mew-im-call-process nil mew-prog-imjoin
	   (format "--src=%s" fld) (format "--dst=%s" folder) msgs)
    (message "Joining marked messages to %s ... done" fld)
    ))

(defun mew-summary-kill-subprocess ()
  "Kill a process in Summary mode such as 'imget' and 'imls'.
Sometime a process accidentally remains in Summary mode. 
In this situation, you cannot execute 's', 'i', nor 'x'.
Use this command to solve this problem."
  (interactive)
  (unwind-protect
      (if (null (processp mew-summary-buffer-process))
	  (message "No process to kill. This buffer is unlocked anyway.")
	(message "%s was killed" (process-name mew-summary-buffer-process))
	(kill-process mew-summary-buffer-process))
    (setq mew-summary-buffer-process nil)))

(defun mew-touch-folder (fld)
  (if (mew-which mew-prog-utime exec-path)
      (call-process mew-prog-utime nil nil nil (mew-expand-folder fld))))

(defun mew-summary-flush-queue ()
  (interactive)
  (mew-im-call-process-no-output "Sending message" mew-prog-imput "-q"))

(provide 'mew-summary)

;;; Copyright Notice:

;; Copyright (C) 1996, 1997, 1998 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. All advertising materials mentioning features or use of this software
;;    must display the following acknowledgement:
;;       This product includes software developed by 
;;       Mew developing team and its contributors.
;; 4. 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-summary.el ends here
