* wl-draft.el (wl-draft-reply): Set default position.
[elisp/wanderlust.git] / wl / wl-summary.el
index 994cade..7f0b615 100644 (file)
@@ -86,7 +86,7 @@
 (defvar wl-summary-buffer-mime-charset  nil)
 (defvar wl-summary-buffer-weekday-name-lang  nil)
 (defvar wl-summary-buffer-thread-indent-set-alist  nil)
-(defvar wl-summary-buffer-view 'thread)
+(defvar wl-summary-buffer-view nil)
 (defvar wl-summary-buffer-message-modified nil)
 (defvar wl-summary-buffer-mark-modified nil)
 (defvar wl-summary-buffer-thread-modified nil)
 (defvar wl-summary-buffer-msgdb nil)
 (defvar wl-summary-buffer-folder-name nil)
 (defvar wl-summary-buffer-line-formatter nil)
+(defvar wl-summary-buffer-line-format nil)
 (defvar wl-summary-buffer-mode-line-formatter nil)
 (defvar wl-summary-buffer-mode-line nil)
 
 (make-variable-buffer-local 'wl-summary-buffer-msgdb)
 (make-variable-buffer-local 'wl-summary-buffer-folder-name)
 (make-variable-buffer-local 'wl-summary-buffer-line-formatter)
+(make-variable-buffer-local 'wl-summary-buffer-line-format)
 (make-variable-buffer-local 'wl-summary-buffer-mode-line-formatter)
 (make-variable-buffer-local 'wl-summary-buffer-mode-line)
 
     subject-string))
 
 (defun wl-summary-default-from (from)
+  "Instance of `wl-summary-from-function'.
+Ordinarily returns the sender name. Returns recipient names if (1)
+summary's folder name matches with `wl-summary-showto-folder-regexp'
+and (2) sender address is yours.
+
+See also variable `wl-use-petname'."
   (let (retval tos ng)
     (unless
        (and (eq major-mode 'wl-summary-mode)
                                 (eword-decode-string
                                  (if wl-use-petname
                                      (or
-                                      (funcall wl-summary-get-petname-function to)
+                                      (funcall
+                                       wl-summary-get-petname-function to)
                                       (car
                                        (std11-extract-address-components to))
                                       to)
          string)
     string))
 
+(defvar wl-summary-sort-specs '(number date subject from list-info))
+(defvar wl-summary-default-sort-spec 'date)
+
 (defvar wl-summary-mode-menu-spec
   '("Summary"
     ["Read" wl-summary-read t]
      ["By Number" wl-summary-sort-by-number t]
      ["By Date" wl-summary-sort-by-date t]
      ["By From" wl-summary-sort-by-from t]
-     ["By Subject" wl-summary-sort-by-subject t])
+     ["By Subject" wl-summary-sort-by-subject t]
+     ["By List Info" wl-summary-sort-by-list-info t])
     "----"
     ("Message Operation"
      ["Mark as read"    wl-summary-mark-as-read t]
   (define-key wl-summary-mode-map "g"    'wl-summary-goto-folder)
   (define-key wl-summary-mode-map "G"    'wl-summary-goto-folder-sticky)
   (define-key wl-summary-mode-map "c"    'wl-summary-mark-as-read-all)
-;  (define-key wl-summary-mode-map "D"    'wl-summary-drop-unsync)
 
   (define-key wl-summary-mode-map "a"    'wl-summary-reply)
   (define-key wl-summary-mode-map "A"    'wl-summary-reply-with-citation)
   (define-key wl-summary-mode-map "p"    'wl-summary-prev)
   (define-key wl-summary-mode-map "N"    'wl-summary-down)
   (define-key wl-summary-mode-map "P"    'wl-summary-up)
-;;;(define-key wl-summary-mode-map "w"    'wl-draft)
   (define-key wl-summary-mode-map "w"    'wl-summary-write)
   (define-key wl-summary-mode-map "W"    'wl-summary-write-current-folder)
-;;;(define-key wl-summary-mode-map "e"     'wl-draft-open-file)
   (define-key wl-summary-mode-map "e"     'wl-summary-save)
   (define-key wl-summary-mode-map "\C-c\C-o" 'wl-jump-to-draft-buffer)
   (define-key wl-summary-mode-map "\C-c\C-a" 'wl-addrmgr)
   (define-key wl-summary-mode-map "d"    'wl-summary-delete)
   (define-key wl-summary-mode-map "u"    'wl-summary-unmark)
   (define-key wl-summary-mode-map "U"    'wl-summary-unmark-all)
+  (define-key wl-summary-mode-map "D"    'wl-summary-erase)
 
   ;; thread commands
   (define-key wl-summary-mode-map "t"  (make-sparse-keymap))
   (define-key wl-summary-mode-map "m?"   'wl-summary-target-mark-pick)
   (define-key wl-summary-mode-map "m#"   'wl-summary-target-mark-print)
   (define-key wl-summary-mode-map "m|"   'wl-summary-target-mark-pipe)
+  (define-key wl-summary-mode-map "mD"   'wl-summary-target-mark-erase)
 
   ;; region commands
   (define-key wl-summary-mode-map "r"    (make-sparse-keymap))
 (defun wl-summary-display-top ()
   (interactive)
   (goto-char (point-min))
+  (when wl-summary-lazy-highlight
+    (wl-highlight-summary-window))
   (if wl-summary-buffer-disp-msg
       (wl-summary-redisplay)))
 
   (interactive)
   (goto-char (point-max))
   (forward-line -1)
+  (when wl-summary-lazy-highlight
+    (wl-highlight-summary-window))
   (if wl-summary-buffer-disp-msg
       (wl-summary-redisplay)))
 
@@ -594,16 +610,15 @@ If optional USE-CACHE is non-nil, use cache if exists."
   "Re-edit current message.
 If ARG is non-nil, Supersedes message"
   (interactive "P")
+  (wl-summary-toggle-disp-msg 'off)
   (if arg
       (wl-summary-supersedes-message)
     (if (string= (wl-summary-buffer-folder-name) wl-draft-folder)
-       (if (wl-summary-message-number)
-           (progn
-             (wl-draft-reedit (wl-summary-message-number))
-             (if (wl-message-news-p)
-                 (mail-position-on-field "Newsgroups")
-               (mail-position-on-field "To"))
-             (delete-other-windows)))
+       (when (wl-summary-message-number)
+         (wl-draft-reedit (wl-summary-message-number))
+         (if (wl-message-news-p)
+             (mail-position-on-field "Newsgroups")
+           (mail-position-on-field "To")))
       (wl-draft-edit-string (wl-summary-message-string)))))
 
 (defun wl-summary-resend-bounced-mail ()
@@ -612,6 +627,7 @@ This only makes sense if the current message is a bounce message which
 contains some mail you have written but has been bounced back to
 you."
   (interactive)
+  (wl-summary-toggle-disp-msg 'off)
   (save-excursion
     (wl-summary-set-message-buffer-or-redisplay)
     (set-buffer (wl-message-get-original-buffer))
@@ -630,7 +646,7 @@ you."
                              (concat "^--" boundary "\n"
                                      "\\([Cc]ontent-[Dd]escription:.*\n\\)?"
                                      "[Cc]ontent-[Tt]ype:[ \t]+"
-                                     "\\(message/rfc822\\|text/rfc822-headers\\)\n"
+                                     "\\(message/rfc822\\|text/rfc822-headers\\).*\n"
                                      "\\(.+\n\\)*\n") nil t))
                 (re-search-forward
                  (concat "\n\\(--" boundary "\\)--\n") nil t))
@@ -721,7 +737,7 @@ you."
                         (current-column))))
     (setq wl-summary-buffer-temp-mark-column temp
          wl-summary-buffer-persistent-mark-column persistent)))
-  
+
 (defun wl-summary-buffer-set-folder (folder)
   (if (stringp folder)
       (setq folder (wl-folder-get-elmo-folder folder)))
@@ -746,10 +762,11 @@ you."
            wl-summary-default-number-column))
   (wl-line-formatter-setup
    wl-summary-buffer-line-formatter
-   (or (wl-get-assoc-list-value
-       wl-folder-summary-line-format-alist
-       (elmo-folder-name-internal folder))
-       wl-summary-line-format)
+   (setq wl-summary-buffer-line-format
+        (or (wl-get-assoc-list-value
+             wl-folder-summary-line-format-alist
+             (elmo-folder-name-internal folder))
+            wl-summary-line-format))
    wl-summary-line-format-spec-alist)
   (wl-line-formatter-setup
    wl-summary-buffer-mode-line-formatter
@@ -783,13 +800,6 @@ you."
    wl-thread-space-str-internal
    (or (nth 5 wl-summary-buffer-thread-indent-set)
        wl-thread-space-str))
-  (setq wl-thread-indent-regexp
-       (concat
-        (regexp-quote wl-thread-have-younger-brother-str-internal) "\\|"
-        (regexp-quote wl-thread-youngest-child-str-internal) "\\|"
-        (regexp-quote wl-thread-vertical-str-internal) "\\|"
-        (regexp-quote wl-thread-horizontal-str-internal) "\\|"
-        (regexp-quote wl-thread-space-str-internal)))
   (run-hooks 'wl-summary-buffer-set-folder-hook))
 
 (defun wl-summary-mode ()
@@ -857,6 +867,60 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
   (string< (elmo-msgdb-overview-entity-get-subject-no-decode x)
           (elmo-msgdb-overview-entity-get-subject-no-decode y)))
 
+(defun wl-summary-get-list-info (entity)
+  "Returns (\"ML-name\" . ML-count) of ENTITY."
+  (let (sequence ml-name ml-count subject return-path delivered-to mailing-list)
+    (setq sequence (elmo-msgdb-overview-entity-get-extra-field
+                   entity "x-sequence")
+         ml-name (or (elmo-msgdb-overview-entity-get-extra-field
+                      entity "x-ml-name")
+                     (and sequence
+                          (car (split-string sequence " "))))
+         ml-count (or (elmo-msgdb-overview-entity-get-extra-field
+                       entity "x-mail-count")
+                      (elmo-msgdb-overview-entity-get-extra-field
+                       entity "x-ml-count")
+                      (and sequence
+                           (cadr (split-string sequence " ")))))
+    (and (setq subject (elmo-msgdb-overview-entity-get-subject
+                       entity))
+        (setq subject (elmo-delete-char ?\n subject))
+        (string-match "^\\s(\\(\\S)+\\)[ :]\\([0-9]+\\)\\s)[ \t]*" subject)
+        (progn
+          (or ml-name (setq ml-name (match-string 1 subject)))
+          (or ml-count (setq ml-count (match-string 2 subject)))))
+    (and (setq return-path
+              (elmo-msgdb-overview-entity-get-extra-field
+               entity "return-path"))
+        (string-match "^<\\([^@>]+\\)-return-\\([0-9]+\\)-" return-path)
+        (progn
+          (or ml-name (setq ml-name (match-string 1 return-path)))
+          (or ml-count (setq ml-count (match-string 2 return-path)))))
+    (and (setq delivered-to
+              (elmo-msgdb-overview-entity-get-extra-field
+               entity "delivered-to"))
+        (string-match "^mailing list \\([^@]+\\)@" delivered-to)
+        (or ml-name (setq ml-name (match-string 1 delivered-to))))
+    (and (setq mailing-list
+              (elmo-msgdb-overview-entity-get-extra-field
+               entity "mailing-list"))
+        (string-match "\\(^\\|; \\)contact \\([^@]+\\)-[^-@]+@" mailing-list)  ; *-help@, *-owner@, etc.
+        (or ml-name (setq ml-name (match-string 2 mailing-list))))
+    (cons (and ml-name (car (split-string ml-name " ")))
+         (and ml-count (string-to-int ml-count)))))
+
+(defun wl-summary-overview-entity-compare-by-list-info (x y)
+  "Compare entity X and Y by mailing-list info."
+  (let* ((list-info-x (wl-summary-get-list-info x))
+        (list-info-y (wl-summary-get-list-info y)))
+    (if (equal (car list-info-x) (car list-info-y))
+       (if (equal (cdr list-info-x) (cdr list-info-y))
+           (wl-summary-overview-entity-compare-by-date x y)
+         (< (or (cdr list-info-x) 0)
+            (or (cdr list-info-y) 0)))
+      (string< (or (car list-info-x) "")
+              (or (car list-info-y) "")))))
+
 (defun wl-summary-sort-by-date ()
   (interactive)
   (wl-summary-rescan "date"))
@@ -869,6 +933,9 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
 (defun wl-summary-sort-by-from ()
   (interactive)
   (wl-summary-rescan "from"))
+(defun wl-summary-sort-by-list-info ()
+  (interactive)
+  (wl-summary-rescan "list-info"))
 
 (defun wl-summary-rescan (&optional sort-by)
   "Rescan current folder without updating."
@@ -910,7 +977,6 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
     (setq wl-summary-buffer-delete-list nil)
     (setq wl-summary-delayed-update nil)
     (elmo-kill-buffer wl-summary-search-buf-name)
-    (message "Constructing summary structure...")
     (while curp
       (setq entity (car curp))
       (wl-summary-append-message-func-internal entity msgdb nil)
@@ -1017,7 +1083,8 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
   (if (or wl-summary-buffer-refile-list
          wl-summary-buffer-copy-list
          wl-summary-buffer-delete-list)
-      (if (y-or-n-p "Marks remain to be executed.  Execute them? ")
+      (if (y-or-n-p (format "Execute remaining marks in %s? "
+                           (wl-summary-buffer-folder-name)))
          (progn
            (wl-summary-exec)
            (if (or wl-summary-buffer-refile-list
@@ -1056,7 +1123,7 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
   (elmo-folder-commit wl-summary-buffer-elmo-folder)
   (elmo-folder-check wl-summary-buffer-elmo-folder)
   (if wl-use-scoring (wl-score-save))
-  (if (interactive-p) (message "Saving summary status...done.")))
+  (if (interactive-p) (message "Saving summary status...done")))
 
 (defun wl-summary-force-exit ()
   "Exit current summary.  Buffer is deleted even the buffer is sticky."
@@ -1323,13 +1390,15 @@ If ARG is non-nil, checking is omitted."
           (number-alist (elmo-msgdb-get-number-alist msgdb))
           (message-id (cdr (assq number number-alist)))
           (ov (elmo-msgdb-overview-get-entity message-id msgdb))
-          (entity ov)
+          (wl-message-entity ov)
+          (entity ov)                  ; backward compatibility.
           (size (elmo-msgdb-overview-entity-get-size ov))
           (inhibit-read-only t)
           (buffer-read-only nil)
           (file-cached (elmo-file-cache-exists-p message-id))
           (force-read (and size
-                           (or (null wl-prefetch-threshold)
+                           (or (and (null wl-prefetch-confirm) arg)
+                               (null wl-prefetch-threshold)
                                (< size wl-prefetch-threshold))))
           mark new-mark)
       (unwind-protect
@@ -1507,15 +1576,11 @@ If ARG is non-nil, checking is omitted."
          (insert " "))
        (forward-line 1)))))
 
-;; Does not work correctly...
 (defun wl-summary-mark-as-read-region (beg end)
   (interactive "r")
   (save-excursion
     (save-restriction
       (narrow-to-region beg end)
-;;; use narrowing.
-;;;   (save-excursion (goto-char end)
-;;;                  (end-of-line) (point)))
       (goto-char (point-min))
       (if (eq wl-summary-buffer-view 'thread)
          (progn
@@ -1525,17 +1590,16 @@ If ARG is non-nil, checking is omitted."
                     children)
                (if (wl-thread-entity-get-opened entity)
                    ;; opened...mark line.
-                   ;; Crossposts are not processed
-                   (wl-summary-mark-as-read t)
+                   (wl-summary-mark-as-read number)
                  ;; closed
-                 (wl-summary-mark-as-read t) ; mark itself.
+                 (wl-summary-mark-as-read number) ; mark itself.
                  (setq children (wl-thread-get-children-msgs number))
                  (while children
-                   (wl-summary-mark-as-read t nil nil (car children))
+                   (wl-summary-mark-as-read (car children))
                    (setq children (cdr children))))
                (forward-line 1))))
        (while (not (eobp))
-         (wl-summary-mark-as-read t)
+         (wl-summary-mark-as-read (wl-summary-message-number))
          (forward-line 1)))))
   (wl-summary-count-unread)
   (wl-summary-update-modeline))
@@ -1763,7 +1827,7 @@ If ARG is non-nil, checking is omitted."
          (goto-char (point-min))
          (if (wl-summary-jump-to-msg (car msgs))
              (progn
-               (delete-region (match-beginning 0) (match-end 0))
+               (delete-region (point-at-bol) (point-at-eol))
                (delete-char 1) ; delete '\n'
                (setq wl-summary-buffer-number-list
                      (delq (car msgs) wl-summary-buffer-number-list)))))
@@ -1826,21 +1890,13 @@ If ARG is non-nil, checking is omitted."
 
 (defun wl-summary-sort ()
   (interactive)
-  (let ((sort-by (let ((input-range-list '("number" "date" "subject" "from"))
-                      (default "date")
-                      in)
-                  (setq in
-                        (completing-read
-                         (format "Sort by (%s): " default)
-                         (mapcar
-                          (function (lambda (x) (cons x x)))
-                          input-range-list)))
-                  (if (string= in "")
-                      default
-                    in))))
-    (if (not (member sort-by '("number" "date" "subject" "from")))
-       (error "Sort by %s is not implemented"  sort-by))
-    (wl-summary-rescan sort-by)))
+  (wl-summary-rescan
+   (completing-read
+    (format "Sort by (%s): " (symbol-name wl-summary-default-sort-spec))
+    (mapcar (lambda (spec)
+             (list (symbol-name spec)))
+           wl-summary-sort-specs)
+    nil t nil nil (symbol-name wl-summary-default-sort-spec))))
 
 (defun wl-summary-sync-marks ()
   "Update marks in summary."
@@ -1887,7 +1943,7 @@ If ARG is non-nil, checking is omitted."
       (setq diffs (cadr diff))
       (setq mes (concat mes (format "(-%d" (length diffs))))
       (while diffs
-       (wl-summary-mark-as-read t 'no-server nil (car diffs))
+       (wl-summary-mark-as-read (car diffs) 'no-folder)
        (setq diffs (cdr diffs)))
       (setq diffs (car diff)) ; unread-appends
       (setq mes (concat mes (format "/+%d) unread mark(s)." (length diffs))))
@@ -2009,7 +2065,6 @@ If ARG is non-nil, checking is omitted."
                (when (and sync-all (eq wl-summary-buffer-view 'thread))
                  (elmo-kill-buffer wl-summary-search-buf-name)
                  (message "Inserting thread...")
-                 (setq wl-thread-entity-cur 0)
                  (wl-thread-insert-top)
                  (message "Inserting thread...done"))
                (if elmo-use-database
@@ -2414,9 +2469,14 @@ If ARG, without confirm."
                    (decode-mime-charset-region
                     (point-min)(point-max)
                     wl-summary-buffer-mime-charset 'LF))
-                 (when (file-exists-p view)
+                 (if (file-exists-p view)
+                     (setq wl-summary-buffer-view
+                           (wl-summary-load-file-object view))
                    (setq wl-summary-buffer-view
-                         (wl-summary-load-file-object view)))
+                         (or (wl-get-assoc-list-value
+                              wl-summary-default-view-alist
+                              (elmo-folder-name-internal folder))
+                             wl-summary-default-view)))
                  (wl-thread-resume-entity folder)
                  (wl-summary-open-folder folder))
              (setq wl-summary-buffer-view
@@ -2429,12 +2489,11 @@ If ARG, without confirm."
            (wl-summary-update-modeline)))
       (unless (eq wl-summary-buffer-view 'thread)
        (wl-summary-make-number-list))
-      ;; XXX old summary format; do rescan.
-      (save-excursion
-       (goto-char (point-min))
-       (if (and wl-summary-buffer-number-list
-                (not (re-search-forward "\r-?[0-9]+" (point-at-eol) t)))
-           (wl-summary-rescan)))
+      (when (and wl-summary-cache-use
+                (or (and wl-summary-check-line-format
+                         (wl-summary-line-format-changed-p))
+                    (wl-summary-view-old-p)))
+       (wl-summary-rescan))
       (wl-summary-toggle-disp-msg (if wl-summary-buffer-disp-msg 'on 'off))
       (unless (and reuse-buf keep-cursor)
        ;(setq hilit wl-summary-highlight)
@@ -2613,7 +2672,7 @@ If ARG, without confirm."
       (setq this (funcall func ov))
       (and this (setq this (std11-unfold-string this)))
       (if (equal last this)
-         (wl-append alike (list ov))
+         (setq alike (cons ov alike))
        (when last
          (wl-summary-put-alike alike)
          (insert last ?\n))
@@ -2633,47 +2692,53 @@ If ARG, without confirm."
   (let ((summary-buf (current-buffer))
        (buf (get-buffer-create wl-summary-search-buf-name))
        (folder-name (wl-summary-buffer-folder-name))
-       match founds found-entity)
+       match founds cur result)
     (with-current-buffer buf
       (let ((case-fold-search t))
        (when (or (not (string= wl-summary-search-buf-folder-name folder-name))
                  (zerop (buffer-size)))
          (setq wl-summary-search-buf-folder-name folder-name)
+         (message "Creating subject cache...")
          (wl-summary-insert-headers
           overview
           (function
            (lambda (x)
              (funcall wl-summary-subject-filter-function
-              (elmo-msgdb-overview-entity-get-subject-no-decode x))))
-          t))
+                      (elmo-msgdb-overview-entity-get-subject-no-decode x))))
+          t)
+         (message "Creating subject cache...done"))
        (setq match (funcall wl-summary-subject-filter-function
                             (elmo-msgdb-overview-entity-get-subject entity)))
        (if (string= match "")
            (setq match "\n"))
-       (goto-char (point-min))
-       (while (and (not founds)
-                   (not (= (point) (point-max)))
-                   (search-forward match nil t))
+       (goto-char (point-max))
+       (while (and (null result)
+                   (not (= (point) (point-min)))
+                   (search-backward match nil t))
          ;; check exactly match
-         (when (and (eolp)
-                    (= (point-at-bol)
-                       (match-beginning 0)))
-           (setq found-entity (wl-summary-get-alike))
-           (if (and found-entity
-                    ;; Is founded entity myself or children?
-                    (not (string=
-                          (elmo-msgdb-overview-entity-get-id entity)
-                          (elmo-msgdb-overview-entity-get-id
-                           (car found-entity))))
-                    (with-current-buffer summary-buf
+         (when (and (bolp) (= (point-at-eol)(match-end 0)))
+           (setq founds (wl-summary-get-alike))
+           (with-current-buffer summary-buf
+             (while founds
+               (when (and
+                      ;; the first element of found-entity list exists on
+                      ;; thread tree.
+                      (wl-thread-get-entity
+                       (elmo-msgdb-overview-entity-get-number
+                        (car founds)))
+                      ;; message id is not same as myself.
+                      (not (string=
+                            (elmo-msgdb-overview-entity-get-id entity)
+                            (elmo-msgdb-overview-entity-get-id (car founds))))
+                      ;; not a descendant.
                       (not (wl-thread-descendant-p
                             (elmo-msgdb-overview-entity-get-number entity)
                             (elmo-msgdb-overview-entity-get-number
-                             (car found-entity))))))
-               ;; return matching entity
-               (setq founds found-entity))))
-       (if founds
-           (car founds))))))
+                             (car founds)))))
+                 (setq result (car founds)
+                       founds nil))
+               (setq founds (cdr founds))))))
+       result))))
 
 (defun wl-summary-insert-thread-entity (entity msgdb update
                                               &optional force-insert)
@@ -2682,6 +2747,7 @@ If ARG, without confirm."
         parent-entity
         parent-number
         (case-fold-search t)
+        (depth 0) relatives anumber
         cur number overview2 cur-entity linked retval delayed-entity
         update-list entity-stack)
     (while entity
@@ -2691,14 +2757,18 @@ If ARG, without confirm."
            parent-number (elmo-msgdb-overview-entity-get-number
                           parent-entity))
       (setq number (elmo-msgdb-overview-entity-get-number entity))
-      ;; If thread loop detected, set parent as nil.
       (setq cur entity)
+      ;; If thread loop detected, set parent as nil.
       (while cur
-       (if (eq number (elmo-msgdb-overview-entity-get-number
-                       (setq cur
-                             (elmo-msgdb-get-parent-entity cur msgdb))))
+       (setq anumber
+             (elmo-msgdb-overview-entity-get-number
+              (setq cur (elmo-msgdb-get-parent-entity cur msgdb))))
+       (if (memq anumber relatives)
            (setq parent-number nil
-                 cur nil)))
+                 cur nil))
+       (setq relatives (cons
+                        (elmo-msgdb-overview-entity-get-number cur)
+                        relatives)))
       (if (and parent-number
               (not (wl-thread-get-entity parent-number))
               (not force-insert))
@@ -2752,26 +2822,29 @@ If ARG, without confirm."
         (overview-entity entity)
         (parent-id (elmo-msgdb-overview-entity-get-id parent-entity))
         (number (elmo-msgdb-overview-entity-get-number entity))
-        (parent-number (elmo-msgdb-overview-entity-get-number parent-entity)))
+        (parent-number (elmo-msgdb-overview-entity-get-number parent-entity))
+        insert-line)
     (cond
      ((or (not parent-id)
          (string= this-id parent-id))
       (goto-char (point-max))
-      (beginning-of-line))
+      (beginning-of-line)
+      (setq insert-line t))
      ;; parent already exists in buffer.
      ((wl-summary-jump-to-msg parent-number)
-      (wl-thread-goto-bottom-of-sub-thread)))
-    (let ((inhibit-read-only t)
-         (buffer-read-only nil))
-      (wl-summary-insert-line
-       (wl-summary-create-line
-       entity
-       parent-entity
-       nil
-       (elmo-msgdb-get-mark (wl-summary-buffer-msgdb) number)
-       (wl-thread-maybe-get-children-num number)
-       (wl-thread-make-indent-string thr-entity)
-       (wl-thread-entity-get-linked thr-entity))))))
+      (wl-thread-goto-bottom-of-sub-thread)
+      (setq insert-line t)))
+    (when insert-line
+      (let (buffer-read-only)
+       (wl-summary-insert-line
+        (wl-summary-create-line
+         entity
+         parent-entity
+         nil
+         (elmo-msgdb-get-mark (wl-summary-buffer-msgdb) number)
+         (wl-thread-maybe-get-children-num number)
+         (wl-thread-make-indent-string thr-entity)
+         (wl-thread-entity-get-linked thr-entity)))))))
 
 (defun wl-summary-mark-as-unread (&optional number
                                            no-server-update
@@ -2937,7 +3010,7 @@ If optional argument NUMBER is specified, mark message specified by NUMBER."
 
 (defun wl-summary-exec-region (beg end)
   (interactive "r")
-  (message "Collecting marks ...")
+  (message "Collecting marks...")
   (save-excursion
     (goto-char beg)
     (beginning-of-line)
@@ -2966,7 +3039,7 @@ If optional argument NUMBER is specified, mark message specified by NUMBER."
            refile-len
            dst-msgs                    ; loop counter
            result)
-       (message "Executing ...")
+       (message "Executing...")
        (while dels
          (when (not (assq (car dels) wl-summary-buffer-refile-list))
            (wl-append wl-summary-buffer-refile-list
@@ -3057,7 +3130,7 @@ If optional argument NUMBER is specified, mark message specified by NUMBER."
                           wl-message-buffer-cur-number)))
          (wl-summary-toggle-disp-msg 'off))
        (set-buffer-modified-p nil)
-       (message (concat "Executing ... done"
+       (message (concat "Executing...done"
                         (if (> refile-failures 0)
                             (format " (%d refiling failed)" refile-failures)
                           "")
@@ -3066,6 +3139,45 @@ If optional argument NUMBER is specified, mark message specified by NUMBER."
                           "")
                         "."))))))
 
+(defun wl-summary-erase (&optional number)
+  "Erase message actually, without moving it to trash."
+  (interactive)
+  (if (elmo-folder-writable-p wl-summary-buffer-elmo-folder)
+      (let* ((buffer-num (wl-summary-message-number))
+            (msg-num (or number buffer-num)))
+       (if (null msg-num)
+           (message "No message.")
+         (let* ((msgdb (wl-summary-buffer-msgdb))
+                (entity (elmo-msgdb-overview-get-entity msg-num msgdb))
+                (subject (elmo-delete-char
+                          ?\n (or (elmo-msgdb-overview-entity-get-subject
+                                   entity)
+                                  wl-summary-no-subject-message))))
+           (when (yes-or-no-p
+                  (format "Erase \"%s\" without moving it to trash? "
+                          (truncate-string subject 30)))
+             (wl-summary-unmark msg-num)
+             (elmo-folder-delete-messages wl-summary-buffer-elmo-folder
+                                          (list msg-num))
+             (wl-summary-delete-messages-on-buffer (list msg-num))
+             (save-excursion (wl-summary-sync nil "update"))))))
+    (message "Read-only folder.")))
+
+(defun wl-summary-target-mark-erase ()
+  (interactive)
+  (if (elmo-folder-writable-p wl-summary-buffer-elmo-folder)
+      (if (null wl-summary-buffer-target-mark-list)
+         (message "No marked message.")
+       (when (yes-or-no-p
+              "Erase all marked messages without moving them to trash? ")
+         (elmo-folder-delete-messages wl-summary-buffer-elmo-folder
+                                      wl-summary-buffer-target-mark-list)
+         (wl-summary-delete-messages-on-buffer
+          wl-summary-buffer-target-mark-list)
+         (setq wl-summary-buffer-target-mark-list nil)
+         (save-excursion (wl-summary-sync nil "update"))))
+    (message "Read-only folder.")))
+
 (defun wl-summary-read-folder (default &optional purpose ignore-error
                                no-create init)
   (let ((fld (completing-read
@@ -3114,7 +3226,8 @@ If optional argument NUMBER is specified, mark message specified by NUMBER."
        (setq c (+ c (char-width (following-char)))))
       (and (> c len) (setq folder (concat " " folder)))
       (setq rs (point))
-      (put-text-property rs re 'invisible t)
+      (when wl-summary-width
+         (put-text-property rs re 'invisible t))
       (put-text-property rs re 'wl-summary-destination t)
       (goto-char re)
       (wl-highlight-refile-destination-string folder)
@@ -3383,7 +3496,7 @@ If optional argument NUMBER is specified, mark message specified by NUMBER."
 
 
 (defun wl-summary-refile-region (beg end)
-  "Put copy mark on messages in the region specified by BEG and END."
+  "Put refile mark on messages in the region specified by BEG and END."
   (interactive "r")
   (wl-summary-refile-region-subr "refile" beg end))
 
@@ -3697,7 +3810,7 @@ If ARG, exit virtual folder."
          (setq skipped (cons (car mlist) skipped)))
        (setq mlist (cdr mlist)))
       (setq wl-summary-buffer-target-mark-list skipped)
-      (message "Prefetching... %d/%d message(s)." count length)
+      (message "Prefetching... %d/%d message(s)" count length)
       (set-buffer-modified-p nil))))
 
 (defun wl-summary-target-mark-refile-subr (copy-or-refile)
@@ -3721,11 +3834,9 @@ If ARG, exit virtual folder."
                      number (wl-summary-buffer-msgdb)))
        (if (null entity)
            (error "Cannot %s" copy-or-refile))
-       (funcall function
-                (setq folder (wl-summary-read-folder
-                              (wl-refile-guess entity)
-                              (format "for %s" copy-or-refile)))
-                number)
+       (setq folder (wl-summary-read-folder
+                     (wl-refile-guess entity)
+                     (format "for %s" copy-or-refile)))
        (goto-char (point-min))
        (while (not (eobp))
          (when (string= (wl-summary-temp-mark) "*")
@@ -3788,15 +3899,17 @@ If ARG, exit virtual folder."
          ;; delete target-mark from buffer.
          (delete-backward-char 1)
          (insert " ")
-         (setq number (wl-summary-mark-as-read t))
+         (setq number (wl-summary-message-number))
+         (wl-summary-mark-as-read number)
          (if wl-summary-highlight
              (wl-highlight-summary-current-line))
          (if number
              (setq wl-summary-buffer-target-mark-list
-                   (delq number wl-summary-buffer-target-mark-list)))))
+                   (delq number wl-summary-buffer-target-mark-list))))
+       (forward-line 1))
       (setq mlist wl-summary-buffer-target-mark-list)
       (while mlist
-       (wl-summary-mark-as-read t nil nil (car mlist))
+       (wl-summary-mark-as-read (car mlist))
        (setq wl-summary-buffer-target-mark-list
              (delq (car mlist) wl-summary-buffer-target-mark-list))
        (setq mlist (cdr mlist)))
@@ -3879,87 +3992,67 @@ If ARG, exit virtual folder."
   (interactive)
   (wl-summary-pick wl-summary-buffer-target-mark-list 'delete))
 
-(defun wl-summary-mark-as-read (&optional notcrosses
-                                         leave-server-side-mark-untouched
-                                         displayed
-                                         number
-                                         cached)
+(defun wl-summary-mark-as-read (&optional number no-folder-mark)
   (interactive)
   (save-excursion
-    (let* (eol
-          (inhibit-read-only t)
-          (buffer-read-only nil)
-          (folder wl-summary-buffer-elmo-folder)
-          (msgdb (wl-summary-buffer-msgdb))
-;;;       (number-alist (elmo-msgdb-get-number-alist msgdb))
-          (case-fold-search nil)
-          cur-mark mark stat visible uncached new-mark marked)
-      (if number
-         (progn
-           (setq visible (wl-summary-jump-to-msg number))
-           (setq mark (elmo-msgdb-get-mark msgdb number)))
-       ;; interactive
-       (setq visible t))
-      (beginning-of-line)
-      (if (or (not visible)
-             (progn
-               (setq cur-mark (wl-summary-persistent-mark))
-               (or (string= cur-mark wl-summary-read-uncached-mark)
-                   (string= cur-mark wl-summary-unread-uncached-mark)
-                   (string= cur-mark wl-summary-unread-cached-mark)
-                   (string= cur-mark wl-summary-new-mark))))
-         (progn
-           (setq mark (or mark cur-mark))
-           (when mark
-             (cond
-              ((string= mark wl-summary-new-mark) ; N
-               (setq stat 'new)
-               (setq uncached t))
-              ((string= mark wl-summary-unread-uncached-mark) ; U
-               (setq stat 'unread)
-               (setq uncached t))
-              ((string= mark wl-summary-unread-cached-mark)  ; !
-               (setq stat 'unread))
-              (t
-               ;; no need to mark server.
-               (setq leave-server-side-mark-untouched t))))
-           (setq number (or number (wl-summary-message-number)))
-           ;; set server side mark...
-           (setq new-mark
-                 (if (and uncached
-                          (if (elmo-message-use-cache-p folder number)
-                              (not (elmo-folder-local-p folder)))
-                          (not cached))
-                     wl-summary-read-uncached-mark
-                   nil))
-           (if (not leave-server-side-mark-untouched)
-               (save-match-data
-                 (setq marked (elmo-folder-mark-as-read
-                               folder
-                               (list number)))))
-           (if (or leave-server-side-mark-untouched
-                   marked)
-               (progn
-                 (cond ((eq stat 'unread)
-                        (setq wl-summary-buffer-unread-count
-                              (1- wl-summary-buffer-unread-count)))
-                       ((eq stat 'new)
-                        (setq wl-summary-buffer-new-count
-                              (1- wl-summary-buffer-new-count))))
-                 (wl-summary-update-modeline)
-                 (wl-folder-update-unread
-                  (wl-summary-buffer-folder-name)
-                  (+ wl-summary-buffer-unread-count
-                     wl-summary-buffer-new-count))
-                 (when (or stat cached)
-                   (when visible
-                     (delete-backward-char 1)
-                     (insert (or new-mark " ")))
-                   (elmo-msgdb-set-mark msgdb number new-mark)
-                   (wl-summary-set-mark-modified))
-                 (if (and visible wl-summary-highlight)
-                     (wl-highlight-summary-current-line nil nil t)))
-             (if mark (message "Warning: Changing mark failed.")))))
+    (let ((buffer-read-only nil)
+         (folder wl-summary-buffer-elmo-folder)
+         (msgdb (wl-summary-buffer-msgdb))
+         (case-fold-search nil)
+         cur-mark mark stat visible uncached new-mark marked)
+      (setq number (or number (wl-summary-message-number))
+           visible (if number
+                       (wl-summary-jump-to-msg number)
+                     ;; interactive
+                     t)
+           mark (elmo-msgdb-get-mark msgdb number))
+      (cond
+       ((string= mark wl-summary-new-mark) ; N
+       (setq stat 'new))
+       ((string= mark wl-summary-unread-uncached-mark) ; U
+       (setq stat 'unread))
+       ((string= mark wl-summary-unread-cached-mark)  ; !
+       (setq stat 'unread))
+       ((string= mark wl-summary-read-uncached-mark)  ; u
+       (setq stat 'read))
+       (t
+       ;; no need to mark server.
+       (setq no-folder-mark t)))
+      (setq new-mark
+           (if (and (if (elmo-message-use-cache-p folder number)
+                        (not (elmo-folder-local-p folder)))
+                    (not (elmo-file-cache-exists-p
+                          (elmo-message-field wl-summary-buffer-elmo-folder
+                                              number 'message-id))))
+               wl-summary-read-uncached-mark
+             nil))
+      ;; folder mark.
+      (unless no-folder-mark
+       (setq marked (elmo-folder-mark-as-read folder (list number))))
+      (when (or no-folder-mark marked)
+       (cond ((eq stat 'unread)
+              (setq wl-summary-buffer-unread-count
+                    (1- wl-summary-buffer-unread-count)))
+             ((eq stat 'new)
+              (setq wl-summary-buffer-new-count
+                    (1- wl-summary-buffer-new-count))))
+       (wl-summary-update-modeline)
+       (wl-folder-update-unread
+        (wl-summary-buffer-folder-name)
+        (+ wl-summary-buffer-unread-count
+           wl-summary-buffer-new-count))
+       (when stat
+         ;; set mark on buffer
+         (when visible
+           (unless (string= (wl-summary-persistent-mark) new-mark)
+             (delete-backward-char 1)
+             (insert (or new-mark " "))))
+         ;; set msgdb mark.
+         (unless (string= mark new-mark)
+           (elmo-msgdb-set-mark msgdb number new-mark))
+         (wl-summary-set-mark-modified))
+       (if (and visible wl-summary-highlight)
+           (wl-highlight-summary-current-line nil nil t)))
       (set-buffer-modified-p nil)
       (if stat
          (run-hooks 'wl-summary-unread-message-hook))
@@ -4047,6 +4140,33 @@ If ARG, exit virtual folder."
 ;;; Summary line.
 (defvar wl-summary-line-formatter nil)
 
+(defun wl-summary-view-old-p ()
+  "Return non-nil when summary view cache has old format."
+  (save-excursion
+    (goto-char (point-min))
+    (and wl-summary-buffer-number-list
+        (not (re-search-forward "\r-?[0-9]+" (point-at-eol) t)))))
+
+(defun wl-summary-line-format-changed-p ()
+  "Return non-nil when summary line format is changed."
+  (not (string=
+       wl-summary-buffer-line-format
+       (or (elmo-object-load (expand-file-name 
+                              wl-summary-line-format-file
+                              (elmo-folder-msgdb-path
+                               wl-summary-buffer-elmo-folder))
+                             wl-summary-buffer-mime-charset)
+           wl-summary-buffer-line-format))))
+
+(defun wl-summary-line-format-save ()
+  "Save current summary line format."
+  (elmo-object-save
+   (expand-file-name wl-summary-line-format-file
+                    (elmo-folder-msgdb-path
+                     wl-summary-buffer-elmo-folder))
+   wl-summary-buffer-line-format
+   wl-summary-buffer-mime-charset))
+
 (defun wl-summary-line-number ()
   (wl-set-string-width
    (- wl-summary-buffer-number-column)
@@ -4081,7 +4201,6 @@ If ARG, exit virtual folder."
         (t (format "%dB" size)))
       "")))
 
-(defvar wl-summary-line-subject-minimum-length nil)
 (defun wl-summary-line-subject ()
   (let (no-parent subject parent-raw-subject parent-subject)
     (if (string= wl-thr-indent-string "")
@@ -4096,24 +4215,12 @@ If ARG, exit virtual folder."
     (setq parent-subject
          (if parent-raw-subject
              (elmo-delete-char ?\n parent-raw-subject)))
-    (setq subject
-         (if (or no-parent
-                 (null parent-subject)
-                 (not (wl-summary-subject-equal
-                       subject parent-subject)))
-             (funcall wl-summary-subject-function subject)
-           ""))
-    (when (and wl-summary-line-subject-minimum-length
-              (< (string-width subject)
-                 wl-summary-line-subject-minimum-length))
-      (while (< (string-width subject)
-               wl-summary-line-subject-minimum-length)
-       (setq subject (concat subject " "))))
-    (if (and (not wl-summary-width)
-            wl-summary-subject-length-limit)
-       (truncate-string subject
-                        wl-summary-subject-length-limit)
-      subject)))
+    (if (or no-parent
+           (null parent-subject)
+           (not (wl-summary-subject-equal
+                 subject parent-subject)))
+       (funcall wl-summary-subject-function subject)
+      "")))
 
 (defun wl-summary-line-from ()
   (elmo-delete-char ?\n
@@ -4122,69 +4229,23 @@ If ARG, exit virtual folder."
                              wl-message-entity))))
 
 (defun wl-summary-line-list-info ()
-  (let ((folder wl-summary-buffer-folder-name)
-       (sequence) (ml-name) (ml-count) (subject-string))
-    (setq sequence (elmo-msgdb-overview-entity-get-extra-field
-                   wl-message-entity "x-sequence")
-         ml-name (or (elmo-msgdb-overview-entity-get-extra-field
-                      wl-message-entity "x-ml-name")
-                     (and sequence
-                          (car (split-string sequence " "))))
-         ml-count (or (elmo-msgdb-overview-entity-get-extra-field
-                       wl-message-entity "x-mail-count")
-                      (elmo-msgdb-overview-entity-get-extra-field
-                       wl-message-entity "x-ml-count")
-                      (and sequence
-                           (cadr (split-string sequence " "))))
-         subject-string
-         (elmo-delete-char ?\n
-                           (or (elmo-msgdb-overview-entity-get-subject
-                                wl-message-entity)
-                               wl-summary-no-subject-message)))
-    (if (string-match
-        "^\\s(\\(\\S)+\\)[ :]\\([0-9]+\\)\\s)[ \t]*"
-        subject-string)
-       (progn
-         (if (not ml-name) (setq ml-name (match-string 1 subject-string)))
-         (if (not ml-count) (setq ml-count (match-string 2 subject-string)))))
-    (condition-case nil
-       (if (and ml-name ml-count)
-           (if (string= folder wl-default-folder)
-               (format "(%s %05d)"
-                       (car (split-string ml-name " "))
-                       (string-to-int ml-count))
-             (format "#%05d" (string-to-int ml-count)))
-         "")
-      (error ""))))
+  (let ((list-info (wl-summary-get-list-info wl-message-entity)))
+    (if (car list-info)
+       (format (if (cdr list-info) "(%s %05d)" "(%s)")
+               (car list-info) (cdr list-info))
+      "")))
 
 (defun wl-summary-line-list-count ()
-  (let ((folder wl-summary-buffer-folder-name)
-       (sequence) (ml-count) (subject-string))
-    (setq sequence (elmo-msgdb-overview-entity-get-extra-field
-                   wl-message-entity "x-sequence")
-         ml-count (or (elmo-msgdb-overview-entity-get-extra-field
-                       wl-message-entity "x-mail-count")
-                      (elmo-msgdb-overview-entity-get-extra-field
-                       wl-message-entity "x-ml-count")
-                      (and sequence
-                           (cadr (split-string sequence " ")))))
+  (let ((ml-count (cdr (wl-summary-get-list-info wl-message-entity))))
     (if ml-count
-       (format "%d" (string-to-int ml-count))
-      (setq subject-string
-           (elmo-delete-char ?\n
-                             (or (elmo-msgdb-overview-entity-get-subject
-                                  wl-message-entity)
-                                 "")))
-      (if (string-match
-          "^\\s(\\(\\S)+\\)[ :]\\([0-9]+\\)\\s)[ \t]*"
-          subject-string)
-         (match-string 2 subject-string))
+       (format "%.0f" ml-count)
       "")))
 
 (defun wl-summary-line-attached ()
   (let ((content-type (elmo-msgdb-overview-entity-get-extra-field
-                      wl-message-entity "content-type")))
-    (if (and content-type 
+                      wl-message-entity "content-type"))
+       (case-fold-search t))
+    (if (and content-type
             (string-match "multipart/mixed" content-type))
        "@"
       "")))
@@ -4219,7 +4280,8 @@ If ARG, exit virtual folder."
     (setq line (funcall wl-summary-buffer-line-formatter))
     (if wl-summary-width (setq line
                               (wl-set-string-width
-                               (- wl-summary-width 1) line)))
+                               (- wl-summary-width 1) line nil
+                               'ignore-invalid)))
     (setq line (concat line
                       "\r"
                       (number-to-string
@@ -4339,13 +4401,17 @@ If ARG, exit virtual folder."
          (elmo-make-directory dir)))
       (if (eq save-view 'thread)
          (wl-thread-save-entity dir))
+      (when wl-summary-check-line-format
+       (wl-summary-line-format-save))
       (unwind-protect
          (progn
            (when (file-writable-p cache)
              (copy-to-buffer tmp-buffer (point-min) (point-max))
              (with-current-buffer tmp-buffer
                (widen)
-               (setq wl-summary-buffer-target-mark-list mark-list
+               (make-local-variable 'wl-summary-highlight)
+               (setq wl-summary-highlight nil
+                     wl-summary-buffer-target-mark-list mark-list
                      wl-summary-buffer-refile-list refile-list
                      wl-summary-buffer-copy-list copy-list
                      wl-summary-buffer-delete-list delete-list
@@ -4353,7 +4419,8 @@ If ARG, exit virtual folder."
                (wl-summary-delete-all-temp-marks)
                (encode-coding-region
                 (point-min) (point-max)
-                (or (mime-charset-to-coding-system charset 'LF)
+                (or (and wl-on-mule ; one in mcs-ltn1(apel<10.4) cannot take 2 arg.
+                         (mime-charset-to-coding-system charset 'LF))
                     ;; Mule 2 doesn't have `*ctext*unix'.
                     (mime-charset-to-coding-system charset)))
                (write-region-as-binary (point-min)(point-max)
@@ -4628,31 +4695,33 @@ Return t if message exists."
        draft-buf)
     (wl-summary-jump-to-msg (car mlist))
     (wl-summary-reply arg t)
-    (goto-char (point-max))
-    (setq start-point (point-marker))
-    (setq draft-buf (current-buffer))
-    (save-window-excursion
-      (while mlist
-       (set-buffer summary-buf)
-       (delete-other-windows)
-       (wl-summary-jump-to-msg (car mlist))
-       (wl-summary-redisplay)
-       (set-buffer draft-buf)
-       (goto-char (point-max))
-       (wl-draft-yank-original)
-       (setq mlist (cdr mlist)))
-      (goto-char start-point)
-      (save-excursion
-       (set-buffer summary-buf)
-       (wl-summary-delete-all-temp-marks)))
-    (run-hooks 'wl-mail-setup-hook)))
+    (save-excursion
+      (goto-char (point-max))
+      (setq start-point (point-marker))
+      (setq draft-buf (current-buffer))
+      (save-window-excursion
+       (while mlist
+         (set-buffer summary-buf)
+         (delete-other-windows)
+         (wl-summary-jump-to-msg (car mlist))
+         (wl-summary-redisplay)
+         (set-buffer draft-buf)
+         (goto-char (point-max))
+         (wl-draft-yank-original)
+         (setq mlist (cdr mlist)))
+       (goto-char start-point)
+       (save-excursion
+         (set-buffer summary-buf)
+         (wl-summary-delete-all-temp-marks)))
+      (run-hooks 'wl-mail-setup-hook))))
 
 (defun wl-summary-reply-with-citation (&optional arg)
   (interactive "P")
   (when (wl-summary-reply arg t)
-    (goto-char (point-max))
-    (wl-draft-yank-original)
-    (run-hooks 'wl-mail-setup-hook)))
+    (save-excursion
+      (goto-char (point-max))
+      (wl-draft-yank-original)
+      (run-hooks 'wl-mail-setup-hook))))
 
 (defun wl-summary-jump-to-msg-by-message-id (&optional id)
   (interactive)
@@ -4767,6 +4836,7 @@ Return t if message exists."
 (defun wl-summary-jump-to-parent-message (arg)
   (interactive "P")
   (let ((cur-buf (current-buffer))
+       (disp-msg wl-summary-buffer-disp-msg)
        (number (wl-summary-message-number))
        (regexp "\\(<[^<>]*>\\)[ \t]*$")
        (i -1) ;; xxx
@@ -4820,17 +4890,18 @@ Return t if message exists."
          (setq msg-id
                (if (null arg) (nth 0 ref-list) ;; previous
                  (if (<= arg i) (nth (1- arg) ref-list)
-                   (nth i ref-list)))))))
-      (set-buffer cur-buf)
+                   (nth i ref-list))))))
+       (set-buffer cur-buf)
+       (or disp-msg (wl-summary-toggle-disp-msg 'off)))
       (cond ((and (null msg-id) (null msg-num))
             (message "No parent message!")
             nil)
            ((and msg-id (wl-summary-jump-to-msg-by-message-id msg-id))
-            (wl-summary-redisplay)
+            (if wl-summary-buffer-disp-msg (wl-summary-redisplay))
             (message "Searching parent message...done")
             t)
            ((and msg-num (wl-summary-jump-to-msg msg-num))
-            (wl-summary-redisplay)
+            (if wl-summary-buffer-disp-msg (wl-summary-redisplay))
             (message "Searching parent message...done")
             t)
            (t ; failed.
@@ -4852,13 +4923,11 @@ Reply to author if invoked with ARG."
       (wl-message-select-buffer wl-message-buffer)
       (set-buffer mes-buf)
       (goto-char (point-min))
-      (unless wl-draft-use-frame
-       (split-window-vertically)
-       (other-window 1))
       (when (setq mes-buf (wl-message-get-original-buffer))
        (wl-draft-reply mes-buf arg summary-buf)
        (unless without-setup-hook
-         (run-hooks 'wl-mail-setup-hook)))
+         (save-excursion
+           (run-hooks 'wl-mail-setup-hook))))
       t)))
 
 (defun wl-summary-write ()
@@ -4926,9 +4995,6 @@ Use function list is `wl-summary-write-current-folder-functions'."
        (wl-summary-redisplay-internal folder number))
       (setq mes-buf wl-message-buffer)
       (wl-message-select-buffer mes-buf)
-      (unless wl-draft-use-frame
-       (split-window-vertically)
-       (other-window 1))
       ;; get original subject.
       (if summary-buf
          (save-excursion
@@ -4973,7 +5039,7 @@ Use function list is `wl-summary-write-current-folder-functions'."
       (if downward
          (forward-line 1)
        (forward-line -1))
-      (setq skip (or (string-match skip-tmark-regexp 
+      (setq skip (or (string-match skip-tmark-regexp
                                   (save-excursion
                                     (wl-summary-temp-mark)))
                     (and skip-pmark-regexp
@@ -4992,8 +5058,12 @@ Use function list is `wl-summary-write-current-folder-functions'."
        (if wl-summary-buffer-disp-msg
            (wl-summary-redisplay))
       (if interactive
-         (if wl-summary-buffer-next-folder-function
-             (funcall wl-summary-buffer-next-folder-function)
+         (cond
+          ((and (not downward) wl-summary-buffer-prev-folder-function)
+           (funcall wl-summary-buffer-prev-folder-function))
+          ((and downward wl-summary-buffer-next-folder-function)
+           (funcall wl-summary-buffer-next-folder-function))
+          (t
            (when wl-auto-select-next
              (setq next-entity
                    (if downward
@@ -5005,7 +5075,7 @@ Use function list is `wl-summary-write-current-folder-functions'."
             '(lambda () (wl-summary-next-folder-or-exit next-entity))
             (format
              "No more messages. Type SPC to go to %s."
-             (wl-summary-entity-info-msg next-entity finfo))))))))
+             (wl-summary-entity-info-msg next-entity finfo)))))))))
 
 (defun wl-summary-prev (&optional interactive)
   (interactive)
@@ -5145,7 +5215,7 @@ Use function list is `wl-summary-write-current-folder-functions'."
                  (delete-window fld-win)))
          (setq wl-current-summary-buffer (current-buffer))
          (wl-summary-mark-as-read
-          nil
+          num
           ;; not fetched, then change server-mark.
           (if (wl-message-redisplay folder num 'mime
                                     (or force-reload
@@ -5160,11 +5230,7 @@ Use function list is `wl-summary-write-current-folder-functions'."
                    wl-summary-buffer-elmo-folder))
                  (elmo-folder-plugged-p
                   wl-summary-buffer-elmo-folder))
-                'leave))
-          t ; displayed
-          nil
-          'cached ; cached by reading.
-          )
+                'leave)))
          (setq wl-summary-buffer-current-msg num)
          (when wl-summary-recenter
            (recenter (/ (- (window-height) 2) 2))
@@ -5202,7 +5268,7 @@ If ASK-CODING is non-nil, coding-system for the message is asked."
          (wl-message-redisplay fld num 'as-is
                                (string= (elmo-folder-name-internal fld)
                                         wl-draft-folder))
-         (wl-summary-mark-as-read nil nil t)
+         (wl-summary-mark-as-read num)
          (setq wl-summary-buffer-current-msg num)
          (when wl-summary-recenter
            (recenter (/ (- (window-height) 2) 2))
@@ -5229,7 +5295,7 @@ If ASK-CODING is non-nil, coding-system for the message is asked."
          (if (wl-message-redisplay fld num 'all-header
                                    (string= (elmo-folder-name-internal fld)
                                             wl-draft-folder))
-             (wl-summary-mark-as-read nil nil t))
+             (wl-summary-mark-as-read num))
          (setq wl-summary-buffer-current-msg num)
          (when wl-summary-recenter
            (recenter (/ (- (window-height) 2) 2))
@@ -5303,6 +5369,7 @@ If ASK-CODING is non-nil, coding-system for the message is asked."
 (defun wl-summary-supersedes-message ()
   "Supersede current message."
   (interactive)
+  (wl-summary-toggle-disp-msg 'off)
   (let ((summary-buf (current-buffer))
        message-buf from)
     (wl-summary-set-message-buffer-or-redisplay)