* wl-util.el (wl-biff-check-folders): Set biff flag.
[elisp/wanderlust.git] / wl / wl-summary.el
index 3bee35b..9537bb3 100644 (file)
@@ -602,6 +602,10 @@ See also variable `wl-use-petname'."
       (setq wl-summary-buffer-message-ring
            (cdr wl-summary-buffer-message-ring)))))
 
+(defmacro wl-summary-message-status (&optional number)
+  `(elmo-message-status wl-summary-buffer-elmo-folder
+                       (or ,number (wl-summary-message-number))))
+
 (defun wl-summary-update-mark-and-highlight-window (&optional win beg)
   "A function to be called as window-scroll-functions."
   (with-current-buffer (window-buffer win)
@@ -609,20 +613,13 @@ See also variable `wl-use-petname'."
       (let ((beg (or beg (window-start win)))
            (end (condition-case nil
                     (window-end win t) ; old emacsen doesn't support 2nd arg.
-                  (error (window-end win))))
-           number flags)
+                  (error (window-end win)))))
        (save-excursion
          (goto-char beg)
          (while (and (< (point) end) (not (eobp)))
            (when (or (null (get-text-property (point) 'face))
                      (wl-summary-persistent-mark-invalid-p))
-             (setq number (wl-summary-message-number))
-             (when number
-               (setq flags (elmo-message-flags wl-summary-buffer-elmo-folder
-                                               number)))
-             (let (wl-summary-highlight)
-               (wl-summary-update-persistent-mark number flags))
-             (wl-highlight-summary-current-line number flags))
+             (wl-summary-update-persistent-mark (wl-summary-message-number)))
            (forward-line 1)))))
     (set-buffer-modified-p nil)))
 
@@ -691,10 +688,10 @@ See also variable `wl-use-petname'."
        (wl-summary-update-persistent-mark-on-event buffer numbers)))
     (elmo-connect-signal
      wl-summary-buffer-elmo-folder
-     'cache-changed
+     'status-changed
      (current-buffer)
-     (elmo-define-signal-handler (buffer folder number)
-       (wl-summary-update-persistent-mark-on-event buffer (list number))))
+     (elmo-define-signal-handler (buffer folder numbers)
+       (wl-summary-update-persistent-mark-on-event buffer numbers)))
     (elmo-connect-signal
      wl-summary-buffer-elmo-folder
      'update-overview
@@ -707,7 +704,7 @@ See also variable `wl-use-petname'."
   (when (and (eq major-mode 'wl-summary-mode)
             wl-summary-buffer-elmo-folder)
     (elmo-disconnect-signal 'flag-changed (current-buffer))
-    (elmo-disconnect-signal 'cache-changed (current-buffer))
+    (elmo-disconnect-signal 'status-changed (current-buffer))
     (elmo-disconnect-signal 'update-overview (current-buffer))))
 
 (defun wl-status-update ()
@@ -819,11 +816,12 @@ you."
 (defun wl-summary-detect-mark-position ()
   (let ((column wl-summary-buffer-number-column)
        (formatter wl-summary-buffer-line-formatter)
+       (lang wl-summary-buffer-weekday-name-lang)
+       (dummy-number 10000)
        (dummy-temp (char-to-string 200))
        ;; bind only for the check.
        (wl-summary-new-uncached-mark (char-to-string 201))
        (wl-summary-persistent-mark-priority-list '(new))     ; ditto.
-       (lang wl-summary-buffer-weekday-name-lang)
        wl-summary-highlight
        temp persistent)
     (with-temp-buffer
@@ -834,14 +832,16 @@ you."
        (wl-summary-create-line
        (elmo-msgdb-make-message-entity
         (luna-make-entity 'modb-entity-handler)
-        :number 10000
+        :number dummy-number
         :from "foo"
         :subject "bar"
         :size 100)
        nil
        dummy-temp
-       '(new)
-       nil))
+       (let ((status (elmo-message-status nil dummy-number)))
+         (elmo-message-status-set-flags status '(new))
+         (elmo-message-status-set-killed status nil)
+         status)))
       (goto-char (point-min))
       (setq temp (save-excursion
                   (when (search-forward dummy-temp nil t)
@@ -1017,41 +1017,30 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
       (string< (or (car list-info-x) "")
               (or (car list-info-y) "")))))
 
-(defun wl-summary-sort-by-date (reverse)
-  "Sort summary lines into the order by message date; argument means descending order."
-  (interactive "P")
-  (wl-summary-rescan "date" reverse))
-(defun wl-summary-sort-by-number (reverse)
-  "Sort summary lines into the order by message number; argument means descending order."
-  (interactive "P")
-  (wl-summary-rescan "number" reverse))
-(defun wl-summary-sort-by-subject (reverse)
-  "Sort summary lines into the order by subject; argument means descending order."
-  (interactive "P")
-  (wl-summary-rescan "subject" reverse))
-(defun wl-summary-sort-by-from (reverse)
-  "Sort summary lines into the order by from; argument means descending order."
-  (interactive "P")
-  (wl-summary-rescan "from" reverse))
-(defun wl-summary-sort-by-list-info (reverse)
-  "Sort summary lines into the order by mailing list info; argument means descending order."
-  (interactive "P")
-  (wl-summary-rescan "list-info" reverse))
-(defun wl-summary-sort-by-size (reverse)
-  "Sort summary lines into the order by message size; argument means descending order."
-  (interactive "P")
-  (wl-summary-rescan "size" reverse))
+(defun wl-summary-define-sort-command ()
+  "Define functions to sort summary lines by `wl-summary-sort-specs'."
+  (interactive)
+  (dolist (sort-by wl-summary-sort-specs)
+    (fset (intern (format "wl-summary-sort-by-%s" sort-by))
+         `(lambda (&optional reverse)
+            ,(format "\
+Sort summary lines into the order by %s.
+If optional argument REVERSE is non-nil, sort into descending order.
+
+This function is defined by `wl-summary-define-sort-command'." sort-by)
+            (interactive "P")
+            (wl-summary-rescan ,(symbol-name sort-by) reverse)))))
 
 (defun wl-summary-sort-function-from-spec (spec reverse)
-  (let (funtion)
+  (let (function)
     (when (string-match "^!\\(.+\\)$" spec)
       (setq spec (match-string 1 spec)
            reverse (not reverse)))
-    (setq funtion
+    (setq function
          (intern (format "wl-summary-overview-entity-compare-by-%s" spec)))
     (if reverse
-       `(lambda (x y) (not (,funtion x y)))
-      funtion)))
+       `(lambda (x y) (not (,function x y)))
+      function)))
 
 (defun wl-summary-sort-messages (numbers sort-by reverse)
   (let* ((functions (mapcar
@@ -1091,7 +1080,6 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
         (and disable-thread wl-summary-search-parent-by-subject-regexp))
        (wl-summary-divide-thread-when-subject-changed
         (and disable-thread wl-summary-divide-thread-when-subject-changed))
-       (i 0)
        num
        expunged)
     (erase-buffer)
@@ -1112,20 +1100,14 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
          wl-summary-buffer-temp-mark-list nil
          wl-summary-delayed-update nil)
     (elmo-kill-buffer wl-summary-search-buf-name)
-    (while numbers
-      (wl-summary-insert-message (elmo-message-entity
-                                 wl-summary-buffer-elmo-folder
-                                 (car numbers))
-                                wl-summary-buffer-elmo-folder
-                                nil)
-      (setq numbers (cdr numbers))
-      (when (> num elmo-display-progress-threshold)
-       (setq i (+ i 1))
-       (if (or (zerop (% i 5)) (= i num))
-           (elmo-display-progress
-            'wl-summary-rescan "Constructing summary structure..."
-            (/ (* i 100) num)))))
-    (when wl-summary-delayed-update
+    (elmo-with-progress-display (wl-summary-insert-line num)
+       "Constructing summary structure"
+      (dolist (number numbers)
+       (wl-summary-insert-message (elmo-message-entity
+                                   wl-summary-buffer-elmo-folder
+                                   number)
+                                  wl-summary-buffer-elmo-folder
+                                  nil))
       (while wl-summary-delayed-update
        (message "Parent (%d) of message %d is no entity"
                 (caar wl-summary-delayed-update)
@@ -1135,12 +1117,8 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
         (cdar wl-summary-delayed-update)
         wl-summary-buffer-elmo-folder nil t)
        (setq wl-summary-delayed-update (cdr wl-summary-delayed-update))))
-    (message "Constructing summary structure...done")
-    (if (eq wl-summary-buffer-view 'thread)
-       (progn
-         (message "Inserting thread...")
-         (wl-thread-insert-top)
-         (message "Inserting thread...done")))
+    (when (eq wl-summary-buffer-view 'thread)
+      (wl-thread-insert-top))
     (when wl-use-scoring
       (wl-summary-score-headers (wl-summary-rescore-msgs
                                 wl-summary-buffer-number-list)
@@ -1195,8 +1173,7 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
            (wl-summary-insert-line
             (wl-summary-create-line entity nil
                                     (wl-summary-temp-mark number)
-                                    (elmo-message-flags folder number)
-                                    (elmo-message-cached-p folder number)))))
+                                    (elmo-message-status folder number)))))
       (when (and wl-summary-buffer-disp-msg
                 wl-summary-buffer-current-msg)
        (save-excursion
@@ -1272,9 +1249,9 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
   (when wl-summary-buffer-temp-mark-list
     (wl-summary-exec-with-confirmation
      (format "Execute marks in %s? (answer \"n\" to discard them) "
-            (wl-summary-buffer-folder-name)))
-    (wl-summary-delete-all-temp-marks 'no-msg)
-    (setq wl-summary-scored nil)))
+            (wl-summary-buffer-folder-name))))
+  (wl-summary-delete-all-temp-marks 'no-msg)
+  (setq wl-summary-scored nil))
 
 ;; a subroutine for wl-summary-exit/wl-save-status
 ;; Note that folder is not commited here.
@@ -1402,6 +1379,8 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
         (msgdb-dir (elmo-folder-msgdb-path folder))
         (range (or force-range (wl-summary-input-range
                                 (elmo-folder-name-internal folder)))))
+    (when (symbolp range)
+      (setq range (symbol-name range)))
     (cond ((string-match "rescan" range)
           (let ((msg (wl-summary-message-number))
                 (wl-use-scoring (if (string-match "noscore" range)
@@ -1561,25 +1540,27 @@ If ARG is non-nil, checking is omitted."
   "All uncached messages are cached."
   (interactive)
   (unless (elmo-folder-local-p wl-summary-buffer-elmo-folder)
-    (let ((targets (elmo-folder-list-flagged wl-summary-buffer-elmo-folder
-                                            'uncached 'in-msgdb))
-         (count 0)
-         wl-prefetch-confirm
-         wl-prefetch-threshold
-         (elmo-inhibit-display-retrieval-progress t)
-         length msg)
+    (let* ((targets (elmo-folder-list-flagged wl-summary-buffer-elmo-folder
+                                             'uncached 'in-msgdb))
+          (count 0)
+          wl-prefetch-confirm
+          wl-prefetch-threshold
+          (length (length targets))
+          msg)
       (save-excursion
-       (goto-char (point-min))
-       (setq length (length targets))
-       (dolist (target targets)
-         (when (if (not (wl-thread-entity-parent-invisible-p
-                         (wl-thread-get-entity target)))
-                   (progn
-                     (wl-summary-jump-to-msg target)
-                     (wl-summary-prefetch-msg
-                      (wl-summary-message-number)))
-                 (wl-summary-prefetch-msg target))
-           (message "Retrieving... %d/%d" (incf count) length)))
+       (elmo-with-progress-display (wl-summary-prefetch-message length)
+           "Retrieving"
+         (goto-char (point-min))
+         (dolist (target targets)
+           (when (if (not (wl-thread-entity-parent-invisible-p
+                           (wl-thread-get-entity target)))
+                     (progn
+                       (wl-summary-jump-to-msg target)
+                       (wl-summary-prefetch-msg
+                        (wl-summary-message-number)))
+                   (wl-summary-prefetch-msg target))
+             (incf count))
+           (elmo-progress-notify 'wl-summary-prefetch-message)))
        (message "Retrieved %d/%d message(s)" count length)))))
 
 (defun wl-summary-prefetch-msg (number &optional arg)
@@ -1664,8 +1645,8 @@ If ARG is non-nil, checking is omitted."
        (message "Collecting marks...")
        (goto-char (point-min))
        (while (not (eobp))
-         (setq mark (wl-summary-persistent-mark)
-               msg (wl-summary-message-number))
+         (setq msg (wl-summary-message-number))
+         (setq mark (wl-summary-persistent-mark msg))
          (if (or (and (null prefetch-marks)
                       msg
                       (null (elmo-file-cache-exists-p
@@ -1789,6 +1770,15 @@ If ARG is non-nil, checking is omitted."
       (wl-summary-count-unread)
       (wl-summary-update-modeline))))
 
+(defun wl-summary-recover-messages-region (beg end)
+  "Recover killed messages in region."
+  (interactive "r")
+  (let ((number-list (wl-summary-number-list-from-region beg end)))
+    (if (null number-list)
+       (message "No message.")
+      (elmo-folder-recover-messages wl-summary-buffer-elmo-folder
+                                   number-list))))
+
 (defun wl-summary-mark-as-read-all ()
   (interactive)
   (if (or (not (interactive-p))
@@ -1839,7 +1829,7 @@ If ARG is non-nil, checking is omitted."
       (wl-summary-update-modeline)
       (message "Resuming cache status...done"))))
 
-(defun wl-summary-delete-messages-on-buffer (msgs &optional deleting-info)
+(defun wl-summary-delete-messages-on-buffer (msgs)
   (interactive)
   (save-excursion
     (let ((inhibit-read-only t)
@@ -1847,7 +1837,6 @@ If ARG is non-nil, checking is omitted."
          (msgs2 msgs)
          (len (length msgs))
          (i 0)
-         ;(deleting-info (or deleting-info "Deleting..."))
          update-list)
       (elmo-kill-buffer wl-summary-search-buf-name)
       (while msgs
@@ -1865,17 +1854,13 @@ If ARG is non-nil, checking is omitted."
                (delete-char 1) ; delete '\n'
                (setq wl-summary-buffer-number-list
                      (delq (car msgs) wl-summary-buffer-number-list)))))
-;      (when (> len elmo-display-progress-threshold)
-;        (setq i (1+ i))
-;        (if (or (zerop (% i 5)) (= i len))
-;            (elmo-display-progress
-;             'wl-summary-delete-messages-on-buffer deleting-info
-;             (/ (* i 100) len))))
        (setq msgs (cdr msgs)))
       (when (eq wl-summary-buffer-view 'thread)
-       (wl-thread-update-line-msgs (elmo-uniq-list update-list))
-       (wl-thread-cleanup-symbols msgs2))
-      ;;(message (concat deleting-info "done"))
+       (let ((updates (elmo-uniq-list update-list)))
+         (elmo-with-progress-display (wl-thread-update-line (length updates))
+             "Updating deleted thread"
+           (wl-thread-update-line-msgs updates)
+           (wl-thread-cleanup-symbols msgs2))))
       (wl-summary-count-unread)
       (wl-summary-update-modeline)
       (wl-summary-folder-info-update))))
@@ -1987,8 +1972,7 @@ This function is defined for `window-scroll-functions'"
                          (not wl-summary-lazy-highlight)))
                    append-list delete-list
                    update-thread update-top-list
-                   num diff entity
-                   (i 0))
+                   num diff entity)
                ;; Setup sync-all
                (if sync-all (wl-summary-sync-all-init))
                (setq diff (elmo-list-diff (elmo-folder-list-messages
@@ -2010,28 +1994,22 @@ This function is defined for `window-scroll-functions'"
                (setq num (length append-list))
                (setq wl-summary-delayed-update nil)
                (elmo-kill-buffer wl-summary-search-buf-name)
-               (dolist (number append-list)
-                 (setq entity (elmo-message-entity folder number))
-                 (when (setq update-thread
-                             (wl-summary-insert-message
-                              entity folder
-                              (not sync-all)))
-                   (wl-append update-top-list update-thread))
-                 (if elmo-use-database
-                     (elmo-database-msgid-put
-                      (elmo-message-entity-field entity 'message-id)
-                      (elmo-folder-name-internal folder)
-                      (elmo-message-entity-number entity)))
-                 (when (> num elmo-display-progress-threshold)
-                   (setq i (+ i 1))
-                   (if (or (zerop (% i 5)) (= i num))
-                       (elmo-display-progress
-                        'wl-summary-sync-update
-                        (if (eq wl-summary-buffer-view 'thread)
-                            "Making thread..."
-                          "Inserting message...")
-                        (/ (* i 100) num)))))
-               (when wl-summary-delayed-update
+               (elmo-with-progress-display (wl-summary-insert-line num)
+                   (if (eq wl-summary-buffer-view 'thread)
+                       "Making thread"
+                     "Inserting message")
+                 (dolist (number append-list)
+                   (setq entity (elmo-message-entity folder number))
+                   (when (setq update-thread
+                               (wl-summary-insert-message
+                                entity folder
+                                (not sync-all)))
+                     (wl-append update-top-list update-thread))
+                   (if elmo-use-database
+                       (elmo-database-msgid-put
+                        (elmo-message-entity-field entity 'message-id)
+                        (elmo-folder-name-internal folder)
+                        (elmo-message-entity-number entity))))
                  (while wl-summary-delayed-update
                    (message "Parent (%d) of message %d is no entity"
                             (caar wl-summary-delayed-update)
@@ -2049,16 +2027,11 @@ This function is defined for `window-scroll-functions'"
                           update-top-list)
                  (wl-thread-update-indent-string-thread
                   (elmo-uniq-list update-top-list)))
-               (message (if (eq wl-summary-buffer-view 'thread)
-                            "Making thread...done"
-                          "Inserting message...done"))
                (when (or delete-list append-list)
                  (wl-summary-set-message-modified))
                (when (and sync-all (eq wl-summary-buffer-view 'thread))
                  (elmo-kill-buffer wl-summary-search-buf-name)
-                 (message "Inserting message...")
-                 (wl-thread-insert-top)
-                 (message "Inserting message...done"))
+                 (wl-thread-insert-top))
                (if elmo-use-database
                    (elmo-database-close))
                (run-hooks 'wl-summary-sync-updated-hook)
@@ -2167,21 +2140,13 @@ This function is defined for `window-scroll-functions'"
 
 (defun wl-summary-highlight-msgs (msgs)
   (save-excursion
-    (let ((len (length msgs))
-         i)
-      (message "Hilighting...")
-      (setq i 0)
+    (elmo-with-progress-display (wl-summary-highlight-line (length msgs))
+       "Hilighting"
       (while msgs
        (if (wl-summary-jump-to-msg (car msgs))
            (wl-highlight-summary-current-line))
        (setq msgs (cdr msgs))
-       (when (> len elmo-display-progress-threshold)
-         (setq i (+ i 1))
-         (if (or (zerop (% i 5)) (= i len))
-             (elmo-display-progress
-              'wl-summary-highlight-msgs "Highlighting..."
-              (/ (* i 100) len)))))
-      (message "Highlighting...done"))))
+       (elmo-progress-notify 'wl-summary-highlight-line)))))
 
 (defun wl-summary-message-number ()
   (save-excursion
@@ -2352,9 +2317,13 @@ If ARG, without confirm."
       (beginning-of-line))))
 
 (defun wl-summary-get-buffer (folder)
-  (or (and folder
-          (get-buffer (wl-summary-sticky-buffer-name folder)))
-      (get-buffer wl-summary-buffer-name)))
+  (and folder
+       (or (get-buffer (wl-summary-sticky-buffer-name folder))
+          (let ((buffer (get-buffer wl-summary-buffer-name)))
+            (and buffer
+                 (with-current-buffer buffer
+                   (string= (wl-summary-buffer-folder-name) folder))
+                 buffer)))))
 
 (defun wl-summary-get-buffer-create (name &optional force-sticky)
   (if force-sticky
@@ -2409,10 +2378,13 @@ If ARG, without confirm."
               (eq major-mode 'wl-summary-mode)) ; called in summary.
       (setq wl-summary-last-visited-folder (wl-summary-buffer-folder-name))
       (run-hooks 'wl-summary-exit-pre-hook)
-      (if (or force-exit (not (wl-summary-sticky-p)))
+      (let ((discard-contents (or force-exit (not (wl-summary-sticky-p)))))
+       (when discard-contents
          (wl-summary-cleanup-temp-marks))
-      (wl-summary-save-view)
-      (elmo-folder-commit wl-summary-buffer-elmo-folder)
+       (wl-summary-save-view)
+       (if discard-contents
+           (elmo-folder-close wl-summary-buffer-elmo-folder)
+         (elmo-folder-commit wl-summary-buffer-elmo-folder)))
       (if (and (wl-summary-sticky-p) force-exit)
          (kill-buffer (current-buffer))))
     (setq buf (wl-summary-get-buffer-create (elmo-folder-name-internal folder)
@@ -2628,6 +2600,7 @@ If ARG, without confirm."
        (save-excursion (beginning-of-line)(point))
        (save-excursion (end-of-line)(point))
        'mouse-face nil))
+  (elmo-progress-notify 'wl-summary-insert-line)
   (ignore-errors
     (run-hooks 'wl-summary-line-inserted-hook)))
 
@@ -2639,12 +2612,7 @@ If ARG, without confirm."
       (goto-char (point-max))
       (wl-summary-insert-line
        (wl-summary-create-line entity nil nil
-                              (elmo-message-flags
-                               wl-summary-buffer-elmo-folder
-                               number)
-                              (elmo-message-cached-p
-                               wl-summary-buffer-elmo-folder
-                               number)))
+                              (elmo-message-status folder number)))
       (setq wl-summary-buffer-number-list
            (wl-append wl-summary-buffer-number-list
                       (list (elmo-message-entity-number entity))))
@@ -2851,8 +2819,7 @@ If ARG, without confirm."
          entity
          parent-entity
          nil
-         (elmo-message-flags wl-summary-buffer-elmo-folder number)
-         (elmo-message-cached-p wl-summary-buffer-elmo-folder number)
+         (wl-summary-message-status number)
          (wl-thread-maybe-get-children-num number)
          (wl-thread-make-indent-string thr-entity)
          (wl-thread-entity-get-linked thr-entity)))))))
@@ -2977,60 +2944,60 @@ If ARG, exit virtual folder."
   (setq wl-summary-buffer-persistent-mark-version
        (1+ wl-summary-buffer-persistent-mark-version)))
 
-(defsubst wl-summary-persistent-mark-string (folder flags cached)
+(defsubst wl-summary-persistent-mark-string (folder status)
   "Return the persistent mark string.
-The mark is decided according to the FOLDER, FLAGS and CACHED."
+The mark is decided according to the FOLDER and STATUS."
   (let ((priorities wl-summary-persistent-mark-priority-list)
+       (flags (elmo-message-status-flags status))
+       (cached (elmo-message-status-cached-p status))
        mark)
     (while (and (null mark) priorities)
-      (if (and (eq (car priorities) 'flag)
-              (elmo-get-global-flags flags 'ignore-preserved))
-         (let ((specs wl-summary-flag-alist)
+      (let ((flag (car priorities)))
+       (cond
+        ((eq flag 'flag)
+         (let ((flags (elmo-get-global-flags flags 'ignore-preserved))
+               (specs wl-summary-flag-alist)
                spec)
-           (while (setq spec (car specs))
-             (if (memq (car spec) flags)
-                 (setq mark (or (nth 2 spec) wl-summary-flag-mark)
-                       specs nil)
-               (setq specs (cdr specs))))
-           (unless mark
-             (setq mark wl-summary-flag-mark)))
-       (when (memq (car priorities) flags)
+           (when flags
+             (while (setq spec (car specs))
+               (if (memq (car spec) flags)
+                   (setq mark (or (nth 2 spec) wl-summary-flag-mark)
+                         specs nil)
+                 (setq specs (cdr specs))))
+             (unless mark
+               (setq mark wl-summary-flag-mark)))))
+        ((eq flag 'killed)
+         (when (elmo-message-status-killed-p status)
+           (setq mark wl-summary-killed-mark)))
+        ((memq flag flags)
          (setq mark
-               (let ((var
-                      (intern
-                       (if cached
+               (let ((var (intern-soft
                            (format
-                            "wl-summary-%s-cached-mark" (car priorities))
-                         (format
-                          "wl-summary-%s-uncached-mark" (car priorities))))))
-                 (if (and (boundp var)
-                          (symbol-value var))
-                     (symbol-value var)
-                   (if cached
-                       (downcase (substring (symbol-name (car priorities))
-                                            0 1))
-                     (upcase (substring (symbol-name (car priorities))
-                                        0 1))))))))
-      (setq priorities (cdr priorities)))
+                            (if cached
+                                "wl-summary-%s-cached-mark"
+                              "wl-summary-%s-uncached-mark")
+                            flag))))
+                 (or (and var (boundp var) (symbol-value var))
+                     (funcall (if cached #'downcase #'upcase)
+                              (substring (symbol-name flag) 0 1)))))))
+       (setq priorities (cdr priorities))))
     (or mark
        (if (or cached (elmo-folder-local-p folder))
            nil
          wl-summary-uncached-mark))))
 
-(defsubst wl-summary-message-mark (folder number &optional flags)
+(defsubst wl-summary-message-mark (folder number &optional status)
   "Return mark of the message."
   (ignore-errors
     (wl-summary-persistent-mark-string
      folder
-     (or flags (setq flags (elmo-message-flags folder number)))
-     (memq 'cached flags) ; XXX for speed-up.
-     )))
+     (or status (elmo-message-status folder number)))))
 
-(defsubst wl-summary-persistent-mark (&optional number flags)
+(defsubst wl-summary-persistent-mark (&optional number status)
   "Return persistent-mark string of current line."
   (or (wl-summary-message-mark wl-summary-buffer-elmo-folder
                               (or number (wl-summary-message-number))
-                              flags)
+                              status)
       " "))
 
 (defun wl-summary-put-temp-mark (mark)
@@ -3127,6 +3094,19 @@ The mark is decided according to the FOLDER, FLAGS and CACHED."
       (wl-summary-count-unread)
       (wl-summary-update-modeline))))
 
+(defun wl-summary-target-mark-recover ()
+  "Recover killed messages which have target mark."
+  (interactive)
+  (wl-summary-check-target-mark)
+  (save-excursion
+    (let ((inhibit-read-only t)
+         (buffer-read-only nil)
+         wl-summary-buffer-disp-msg)
+      (elmo-folder-recover-messages wl-summary-buffer-elmo-folder
+                                   wl-summary-buffer-target-mark-list)
+      (dolist (number wl-summary-buffer-target-mark-list)
+       (wl-summary-unset-mark number)))))
+
 (defun wl-summary-target-mark-save ()
   (interactive)
   (wl-summary-check-target-mark)
@@ -3146,29 +3126,30 @@ The mark is decided according to the FOLDER, FLAGS and CACHED."
   (wl-summary-check-target-mark)
   (wl-summary-pick wl-summary-buffer-target-mark-list 'delete))
 
-(defun wl-summary-update-persistent-mark (&optional number flags)
+(defun wl-summary-update-persistent-mark (&optional number)
   "Synch up persistent mark of current line with msgdb's.
 Return non-nil if the mark is updated"
   (interactive)
-  (prog1
-      (when wl-summary-buffer-persistent-mark-column
-       (save-excursion
-         (move-to-column wl-summary-buffer-persistent-mark-column)
-         (let ((inhibit-read-only t)
-               (buffer-read-only nil)
-               (mark (buffer-substring (- (point) 1) (point)))
-               (new-mark (wl-summary-persistent-mark number flags)))
-           (prog1
-               (unless (string= new-mark mark)
-                 (delete-backward-char 1)
-                 (insert new-mark)
-                 (wl-summary-set-message-modified)
-                 t)
-             (wl-summary-validate-persistent-mark (point-at-bol)
-                                                  (point-at-eol))))))
-    (when wl-summary-highlight
-      (wl-highlight-summary-current-line))
-    (set-buffer-modified-p nil)))
+  (let ((status (wl-summary-message-status number)))
+    (prog1
+       (when wl-summary-buffer-persistent-mark-column
+         (save-excursion
+           (move-to-column wl-summary-buffer-persistent-mark-column)
+           (let ((inhibit-read-only t)
+                 (buffer-read-only nil)
+                 (mark (buffer-substring (- (point) 1) (point)))
+                 (new-mark (wl-summary-persistent-mark number status)))
+             (prog1
+                 (unless (string= new-mark mark)
+                   (delete-backward-char 1)
+                   (insert new-mark)
+                   (wl-summary-set-message-modified)
+                   t)
+               (wl-summary-validate-persistent-mark (point-at-bol)
+                                                    (point-at-eol))))))
+      (when wl-summary-highlight
+       (wl-highlight-summary-current-line number status))
+      (set-buffer-modified-p nil))))
 
 (defsubst wl-summary-mark-as-read-internal (inverse
                                            number-or-numbers
@@ -3433,6 +3414,14 @@ Return non-nil if the mark is updated"
      'important
      nil nil nil (interactive-p))))
 
+(defun wl-summary-recover-message (number)
+  "Recover current message if it is killed."
+  (interactive (list (wl-summary-message-number)))
+  (if (null number)
+      (message "No message.")
+    (elmo-folder-recover-messages wl-summary-buffer-elmo-folder
+                                 (list number))))
+
 ;;; Summary line.
 (defvar wl-summary-line-formatter nil)
 
@@ -3557,8 +3546,7 @@ Return non-nil if the mark is updated"
 (defun wl-summary-create-line (wl-message-entity
                               wl-parent-message-entity
                               wl-temp-mark
-                              wl-flags
-                              wl-cached
+                              wl-status
                               &optional
                               wl-thr-children-number
                               wl-thr-indent-string
@@ -3567,8 +3555,7 @@ Return non-nil if the mark is updated"
   (let ((wl-mime-charset wl-summary-buffer-mime-charset)
        (wl-persistent-mark (wl-summary-persistent-mark-string
                             wl-summary-buffer-elmo-folder
-                            wl-flags
-                            wl-cached))
+                            wl-status))
        (elmo-mime-charset wl-summary-buffer-mime-charset)
        (elmo-lang wl-summary-buffer-weekday-name-lang)
        (wl-datevec (or (elmo-time-to-datevec
@@ -3599,7 +3586,7 @@ Return non-nil if the mark is updated"
        (wl-highlight-summary-line-string
         (elmo-message-entity-number wl-message-entity)
         line
-        wl-flags
+        wl-status
         wl-temp-mark
         wl-thr-indent-string))
     line))
@@ -4233,8 +4220,7 @@ Return t if message exists."
             nil)))))
 
 (defun wl-summary-reply (&optional arg without-setup-hook)
-  "Reply to current message. Default is \"wide\" reply.
-Reply to author if invoked with ARG."
+  "Reply to current message. See also `wl-draft-reply'."
   (interactive "P")
   (let ((folder wl-summary-buffer-elmo-folder)
        (number (wl-summary-message-number))
@@ -4256,11 +4242,10 @@ Reply to author if invoked with ARG."
       (with-current-buffer summary-buf (run-hooks 'wl-summary-reply-hook))
       t)))
 
-(defun wl-summary-write ()
+(defun wl-summary-write (folder)
   "Write a new draft from Summary."
-  (interactive)
-  (wl-draft (list (cons 'To ""))
-           nil nil nil nil (wl-summary-buffer-folder-name))
+  (interactive (list (wl-summary-buffer-folder-name)))
+  (wl-draft (list (cons 'To "")) nil nil nil nil folder)
   (run-hooks 'wl-mail-setup-hook)
   (mail-position-on-field "To"))
 
@@ -4272,12 +4257,10 @@ Reply to author if invoked with ARG."
 Call from `wl-summary-write-current-folder'.
 When guess function return nil, challenge next guess-function.")
 
-(defun wl-summary-write-current-folder (&optional folder)
+(defun wl-summary-write-current-folder (folder)
   "Write message to current FOLDER's newsgroup or mailing-list.
 Use function list is `wl-summary-write-current-folder-functions'."
-  (interactive)
-  ;; default FOLDER is current buffer folder
-  (setq folder (or folder (wl-summary-buffer-folder-name)))
+  (interactive (list (wl-summary-buffer-folder-name)))
   (let ((func-list wl-summary-write-current-folder-functions)
        guess-list guess-func)
     (while func-list
@@ -4287,7 +4270,7 @@ Use function list is `wl-summary-write-current-folder-functions'."
        (setq guess-func (car func-list))
        (setq func-list nil)))
     (if (null guess-func)
-       (wl-summary-write)
+       (wl-summary-write folder)
       (unless (or (stringp (nth 0 guess-list))
                  (stringp (nth 1 guess-list))
                  (stringp (nth 2 guess-list)))
@@ -4815,8 +4798,8 @@ If ARG is numeric number, decode message as following:
   (interactive (list current-prefix-arg nil))
   (if (null (wl-summary-message-number))
       (message "No message.")
-    (setq command (read-string "Shell command on message: "
-                              wl-summary-shell-command-last))
+    (setq command (wl-read-shell-command "Shell command on message: "
+                                        wl-summary-shell-command-last))
     (if (y-or-n-p "Send this message to pipe? ")
        (wl-summary-pipe-message-subr prefix command))))
 
@@ -4825,8 +4808,9 @@ If ARG is numeric number, decode message as following:
   (interactive (list current-prefix-arg nil))
   (if (null wl-summary-buffer-target-mark-list)
       (message "No marked message.")
-    (setq command (read-string "Shell command on each marked message: "
-                              wl-summary-shell-command-last))
+    (setq command (wl-read-shell-command
+                  "Shell command on each marked message: "
+                  wl-summary-shell-command-last))
     (when (y-or-n-p "Send each marked message to pipe? ")
       (while (car wl-summary-buffer-target-mark-list)
        (let ((num (car wl-summary-buffer-target-mark-list)))