* elmo-archive.el (elmo-archive-get-archive-name): Cause an error when
[elisp/wanderlust.git] / wl / wl-summary.el
index 9e31097..67ebaac 100644 (file)
 (defvar wl-summary-buffer-saved-message nil)
 (defvar wl-summary-buffer-prev-folder-func nil)
 (defvar wl-summary-buffer-next-folder-func nil)
+(defvar wl-summary-buffer-next-message-func nil)
 (defvar wl-summary-buffer-exit-func nil)
+(defvar wl-summary-buffer-number-list nil)
+
 (defvar wl-thread-indent-level-internal nil)
 (defvar wl-thread-have-younger-brother-str-internal nil)
 (defvar wl-thread-youngest-child-str-internal nil)
 (make-variable-buffer-local 'wl-thread-space-str-internal)
 (make-variable-buffer-local 'wl-summary-buffer-prev-folder-func)
 (make-variable-buffer-local 'wl-summary-buffer-next-folder-func)
+(make-variable-buffer-local 'wl-summary-buffer-next-message-func)
 (make-variable-buffer-local 'wl-summary-buffer-exit-func)
+(make-variable-buffer-local 'wl-summary-buffer-number-list)
 
 ;; internal functions (dummy)
 (unless (fboundp 'wl-summary-append-message-func-internal)
   (if wl-summary-buffer-disp-msg
       (wl-summary-redisplay)))
 
-(defun wl-summary-collect-unread (mark-alist &optional folder)
-  (let (mark ret-val)
-    (while mark-alist
-      (setq mark (cadr (car mark-alist)))
-      (and mark
-          (or (string= mark wl-summary-new-mark)
-              (string= mark wl-summary-unread-uncached-mark)
-              (string= mark wl-summary-unread-cached-mark))
-          (setq ret-val (cons (car (car mark-alist)) ret-val)))
-      (setq mark-alist (cdr mark-alist)))
-    ret-val))
-
 (defun wl-summary-count-unread (mark-alist &optional folder)
   (let ((new 0)
        (unread 0)
@@ -600,7 +593,7 @@ you."
        (cond
         ((and
           (re-search-forward
-           (concat "^\\($\\|[Cc]ontent-[Tt]ype:[ \t]+multipart/report\\)") nil t)
+           (concat "^\\($\\|[Cc]ontent-[Tt]ype:[ \t]+multipart/\\(report\\|mixed\\)\\)") nil t)
           (not (bolp))
           (re-search-forward "boundary=\"\\([^\"]+\\)\"" nil t))
          (let ((boundary (buffer-substring (match-beginning 1) (match-end 1)))
@@ -608,6 +601,7 @@ you."
            (cond
             ((and (setq start (re-search-forward
                           (concat "^--" boundary "\n"
+                                  "\\([Cc]ontent-[Dd]escription:.*\n\\)?"
                                   "[Cc]ontent-[Tt]ype:[ \t]+"
                                   "\\(message/rfc822\\|text/rfc822-headers\\)\n"
                                   "\\(.+\n\\)*\n") nil t))
@@ -777,6 +771,9 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
                                        wl-summary-buffer-folder-indicator
                                        wl-summary-buffer-unread-status))
   (easy-menu-add wl-summary-mode-menu)
+  (when wl-summary-lazy-highlight
+    (make-local-hook 'window-scroll-functions)
+    (add-hook 'window-scroll-functions 'wl-highlight-summary-window nil t))
   ;; This hook may contain the function `wl-setup-summary' for reasons
   ;; of system internal to accord facilities for the Emacs variants.
   (run-hooks 'wl-summary-mode-hook))
@@ -861,6 +858,7 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
     (setq wl-thread-entity-hashtb (elmo-make-hash (* (length overview) 2)))
     (setq wl-thread-entity-list nil)
     (setq wl-thread-entities nil)
+    (setq wl-summary-buffer-number-list nil)
     (setq wl-summary-buffer-target-mark-list nil)
     (setq wl-summary-buffer-refile-list nil)
     (setq wl-summary-buffer-delete-list nil)
@@ -890,10 +888,12 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
        (setq wl-summary-delayed-update (cdr wl-summary-delayed-update))))
     (message "Constructing summary structure...done")
     (set-buffer cur-buf)
-    (when (eq wl-summary-buffer-view 'thread)
-      (message "Inserting thread...")
-      (wl-thread-insert-top)
-      (message "Inserting thread...done"))
+    (if (eq wl-summary-buffer-view 'thread)
+       (progn
+         (message "Inserting thread...")
+         (wl-thread-insert-top)
+         (message "Inserting thread...done"))
+      (wl-summary-make-number-list))
     (when wl-use-scoring
       (setq wl-summary-scored nil)
       (wl-summary-score-headers nil msgdb
@@ -1068,12 +1068,25 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
        (if (setq message-buf (get-buffer wl-message-buf-name))
            (if (setq message-win (get-buffer-window message-buf))
                (delete-window message-win)))
+       (if (and wl-summary-use-frame
+                (> (length (visible-frame-list)) 1))
+           (delete-frame))
        (if (setq folder-buf (get-buffer wl-folder-buffer-name))
-           (if (setq folder-win (get-buffer-window folder-buf))
-               ;; folder win is already displayed.
-               (select-window folder-win)
-             ;; folder win is not displayed.
-             (switch-to-buffer folder-buf))
+           (if wl-summary-use-frame
+               (let (select-frame)
+                 (save-selected-window
+                   (dolist (frame (visible-frame-list))
+                     (select-frame frame)
+                     (if (get-buffer-window folder-buf)
+                         (setq select-frame frame))))
+                 (if select-frame
+                     (select-frame select-frame)
+                   (switch-to-buffer folder-buf)))
+             (if (setq folder-win (get-buffer-window folder-buf))
+                 ;; folder win is already displayed.
+                 (select-window folder-win)
+               ;; folder win is not displayed.
+               (switch-to-buffer folder-buf)))
          ;; currently no folder buffer
          (wl-folder))
        (and wl-folder-move-cur-folder
@@ -1138,6 +1151,7 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
   (setq wl-summary-buffer-msgdb (elmo-msgdb-clear)) ;;'(nil nil nil nil))
   (setq wl-thread-entity-list nil)
   (setq wl-thread-entities nil)
+  (setq wl-summary-buffer-number-list nil)
   (setq wl-summary-buffer-target-mark-list nil)
   (setq wl-summary-buffer-refile-list nil)
   (setq wl-summary-buffer-copy-list nil)
@@ -1153,7 +1167,8 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
                     folder))
         (range (or force-range (wl-summary-input-range folder)))
         mes seen-list killed-list)
-    (cond ((string= range "all")
+    (cond ((or (string= range "all")
+              (string= range "all-visible"))
           ;; initialize buffer local databases.
           (unless (elmo-folder-plugged-p folder) ; forbidden
             (error "Unplugged"))
@@ -1171,7 +1186,7 @@ Entering Folder mode calls the value of `wl-summary-mode-hook'."
           (elmo-clear-killed wl-summary-buffer-folder-name)
           (condition-case nil
               (setq mes (wl-summary-sync-update3 seen-list unset-cursor
-                                                 'sync-all))
+                                                 (string= range "all")))
             (quit
              ;; Resume killed-list if quit.
              (message "") ; clear minibuffer.
@@ -1689,7 +1704,7 @@ If ARG is non-nil, checking is omitted."
       (let* ((folder wl-summary-buffer-folder-name)
             (cur-buf (current-buffer))
             (msgdb wl-summary-buffer-msgdb)
-;;;         (number-alist (elmo-msgdb-get-number-alist msgdb))
+            (number-alist (elmo-msgdb-get-number-alist msgdb))
             (mark-alist (elmo-msgdb-get-mark-alist msgdb))
             (malist mark-alist)
             (inhibit-read-only t)
@@ -1697,7 +1712,14 @@ If ARG is non-nil, checking is omitted."
             (case-fold-search nil)
             msg mark)
        (message "Setting all msgs as read...")
-       (elmo-mark-as-read folder (wl-summary-collect-unread mark-alist)
+       (elmo-mark-as-read folder
+                          (elmo-list-folder-unread
+                           folder
+                           number-alist
+                           mark-alist
+                           (list wl-summary-unread-cached-mark
+                                 wl-summary-unread-uncached-mark
+                                 wl-summary-new-mark))
                           msgdb)
        (save-excursion
          (goto-char (point-min))
@@ -1918,7 +1940,8 @@ If ARG is non-nil, checking is omitted."
              (progn
                (delete-region (match-beginning 0) (match-end 0))
                (delete-char 1) ; delete '\n'
-               )))
+               (setq wl-summary-buffer-number-list
+                     (delq (car msgs) wl-summary-buffer-number-list)))))
        (when (and deleting-info
                   (> len elmo-display-progress-threshold))
          (setq i (1+ i))
@@ -2163,7 +2186,7 @@ If ARG is non-nil, checking is omitted."
     (wl-folder-confirm-existence folder 'force)
     (message "Checking folder diff...")
     (elmo-commit folder)
-    (setq in-folder (elmo-list-folder folder))
+    (setq in-folder (elmo-list-folder folder sync-all))
     (setq in-db (unless sync-all (sort (mapcar 'car number-alist) '<)))
     (if (not elmo-use-killed-list)
        (setq diff (if (eq (elmo-folder-get-type folder) 'multi)
@@ -2290,6 +2313,8 @@ If ARG is non-nil, checking is omitted."
            (message "Updating thread...done")
 ;;;        (set-buffer cur-buf)
            ))
+      (unless (eq wl-summary-buffer-view 'thread)
+       (wl-summary-make-number-list))
       (wl-summary-set-message-modified)
       (wl-summary-set-mark-modified)
       (when (and sync-all (eq wl-summary-buffer-view 'thread))
@@ -2602,7 +2627,8 @@ If ARG, without confirm."
                   wl-summary-buffer-number-regexp
                   wl-summary-buffer-message-modified
                   wl-summary-buffer-mark-modified
-                  wl-summary-buffer-thread-modified)
+                  wl-summary-buffer-thread-modified
+                  wl-summary-buffer-number-list)
                 (and (eq wl-summary-buffer-view 'thread)
                      '(wl-thread-entity-hashtb
                        wl-thread-entities
@@ -2678,6 +2704,20 @@ If ARG, without confirm."
       (delete-window mes-win)
       (run-hooks 'wl-summary-toggle-disp-off-hook))))
 
+(defun wl-summary-make-number-list ()
+  (setq wl-summary-buffer-number-list
+       (mapcar
+        (lambda (x) (elmo-msgdb-overview-entity-get-number x))
+        (elmo-msgdb-get-overview wl-summary-buffer-msgdb))))
+
+(defun wl-summary-auto-select-msg-p (unread-msg)
+  (and unread-msg
+       (not (string=
+            (cadr (assoc unread-msg
+                         (elmo-msgdb-get-mark-alist
+                          wl-summary-buffer-msgdb)))
+            wl-summary-important-mark))))
+
 (defun wl-summary-goto-folder-subr (&optional folder scan-type other-window
                                              sticky interactive scoring)
   "Display target folder on summary."
@@ -2717,15 +2757,21 @@ If ARG, without confirm."
          (let ((case-fold-search nil)
                (inhibit-read-only t)
                (buffer-read-only nil))
+           ;; Load msgdb
+           (setq wl-summary-buffer-msgdb nil) ; new msgdb
+           (setq wl-summary-buffer-msgdb
+                 (wl-summary-msgdb-load-async fld))
+           (if (null wl-summary-buffer-msgdb)
+               (setq wl-summary-buffer-msgdb
+                     (elmo-msgdb-load (elmo-string fld))))
            (erase-buffer)
-           ;; resume summary cache
+           ;; Resume summary view
            (if wl-summary-cache-use
                (let* ((dir (elmo-msgdb-expand-path fld))
                       (cache (expand-file-name wl-summary-cache-file dir))
                       (view (expand-file-name wl-summary-view-file dir)))
                  (when (file-exists-p cache)
-                   (as-binary-input-file
-                    (insert-file-contents cache))
+                   (insert-file-contents-as-binary cache)
                    (elmo-set-buffer-multibyte
                     default-enable-multibyte-characters)
                    (decode-mime-charset-region
@@ -2735,21 +2781,20 @@ If ARG, without confirm."
                    (setq wl-summary-buffer-view
                          (wl-summary-load-file-object view)))
                  (if (eq wl-summary-buffer-view 'thread)
-                     (wl-thread-resume-entity fld))))
-           ;; Load msgdb
-           (setq wl-summary-buffer-msgdb nil) ; new msgdb
-           (setq wl-summary-buffer-msgdb
-                 (wl-summary-msgdb-load-async fld))
-           (if (null wl-summary-buffer-msgdb)
-               (setq wl-summary-buffer-msgdb
-                     (elmo-msgdb-load (elmo-string fld))))
+                     (wl-thread-resume-entity fld)
+                   (wl-summary-make-number-list)))
+             (setq wl-summary-buffer-view
+                   (wl-summary-load-file-object
+                    (expand-file-name wl-summary-view-file
+                                      (elmo-msgdb-expand-path fld))))
+             (wl-summary-rescan))
            (wl-summary-count-unread
             (elmo-msgdb-get-mark-alist wl-summary-buffer-msgdb))
            (wl-summary-update-modeline)))
       (wl-summary-buffer-number-column-detect t)
       (wl-summary-disp-msg fld (and reuse-buf keep-cursor))
       (unless (and reuse-buf keep-cursor)
-       (setq hilit wl-summary-highlight)
+       ;(setq hilit wl-summary-highlight)
        (unwind-protect
            (let ((wl-summary-highlight (if reuse-buf wl-summary-highlight))
                  (wl-use-scoring
@@ -2777,21 +2822,25 @@ If ARG, without confirm."
          (set-buffer-modified-p nil)
          (goto-char (point-min))
          (if (wl-summary-cursor-down t)
-             (let ((unreadp (wl-thread-next-mark-p
-                             (wl-thread-entity-get-mark
-                              (wl-summary-message-number))
-                             wl-summary-move-order)))
-               (cond ((and wl-auto-select-first unreadp)
+             (let ((unreadp (wl-summary-next-message 
+                             (wl-summary-message-number)
+                             'down t)))
+               (cond ((and wl-auto-select-first
+                           (wl-summary-auto-select-msg-p unreadp))
+                      ;; wl-auto-select-first is non-nil and
+                      ;; unreadp is non-nil but not important
                       (setq retval 'disp-msg))
-                     ((not unreadp)
+                     ((not (wl-summary-auto-select-msg-p unreadp))
+                      ;; unreadp is nil or important
                       (setq retval 'more-next))))
            (goto-char (point-max))
            (if (elmo-folder-plugged-p folder)
                (forward-line -1)
              (wl-summary-prev))
            (setq retval 'more-next))
-         (setq wl-summary-highlight hilit)
+         ;(setq wl-summary-highlight hilit)
          (if (and wl-summary-highlight
+                  (not wl-summary-lazy-highlight)
                   (not reuse-buf))
              (if (and wl-summary-highlight-partial-threshold
                       (> (count-lines (point-min) (point-max))
@@ -2898,7 +2947,7 @@ If ARG, without confirm."
 
 (defun wl-summary-default-subject-filter (subject)
   (let ((case-fold-search t))
-    (setq subject (elmo-replace-in-string subject "[ \t]*\\(re\\|was\\):" ""))
+    (setq subject (elmo-replace-in-string subject "[ \t]*\\(re\\|was\\)[:>]" ""))
     (setq subject (elmo-replace-in-string subject "[ \t]" ""))
     (elmo-replace-in-string subject "^\\[.*\\]" "")))
 
@@ -4462,107 +4511,87 @@ If ARG, exit virtual folder."
        (wl-match-string 1 wday-str)
       (elmo-date-get-week year month mday))))
 
-(defmacro wl-summary-cursor-move-regex ()
-  (` (let ((mark-alist
-           (if (elmo-folder-plugged-p wl-summary-buffer-folder-name)
-               (cond ((eq wl-summary-move-order 'new)
-                      (list
-                       (list
-                        wl-summary-new-mark)
-                       (list
-                        wl-summary-unread-uncached-mark
-                        wl-summary-unread-cached-mark
-                        wl-summary-important-mark)))
-                     ((eq wl-summary-move-order 'unread)
-                      (list
-                      (list
-                       wl-summary-unread-uncached-mark
-                       wl-summary-unread-cached-mark
-                       wl-summary-new-mark)
-                      (list
-                       wl-summary-important-mark)))
-                     (t
-                      (list
-                      (list
-                       wl-summary-unread-uncached-mark
-                       wl-summary-unread-cached-mark
-                       wl-summary-new-mark
-                       wl-summary-important-mark))))
-             (cond ((eq wl-summary-move-order 'unread)
-                    (list
-                    (list
-                     wl-summary-unread-cached-mark)
-                    (list
-                     wl-summary-important-mark)))
-                   (t
-                    (list
-                    (list
-                     wl-summary-unread-cached-mark
-                     wl-summary-important-mark)))))))
-       (mapcar
-       (function
-        (lambda (mark-list)
-          (concat wl-summary-message-regexp
-                  ".\\("
-                  (mapconcat 'regexp-quote
-                             mark-list
-                             "\\|")
-                  "\\)\\|"
-                  wl-summary-message-regexp "\\*")))
-       mark-alist))))
-
-;;
-;; Goto unread or important
-;;
-(defun wl-summary-cursor-up (&optional hereto)
-  (interactive "P")
-  (if (and (not wl-summary-buffer-target-mark-list)
-          (eq wl-summary-buffer-view 'thread))
-      (progn
-       (if (eobp)
-           (forward-line -1))
-       (wl-thread-jump-to-prev-unread hereto))
-    (if hereto
-       (end-of-line)
-      (beginning-of-line))
-    (let ((case-fold-search nil)
-         regex-list)
-      (setq regex-list (wl-summary-cursor-move-regex))
-      (catch 'done
-       (while regex-list
-         (when (re-search-backward
-                (car regex-list)
-                nil t nil)
-           (beginning-of-line)
-           (throw 'done t))
-         (setq regex-list (cdr regex-list)))
-       (beginning-of-line)
-       (throw 'done nil)))))
-
+(defvar wl-summary-move-spec-plugged-alist
+  (list (cons 'new (list (cons 't nil)
+                        (cons 'p wl-summary-new-mark)
+                        (cons 'p (wl-regexp-opt
+                                  (list wl-summary-unread-uncached-mark
+                                        wl-summary-unread-cached-mark)))
+                        (cons 'p (regexp-quote wl-summary-important-mark))))
+       (cons 'unread (list (cons 't nil)
+                           (cons 'p (wl-regexp-opt
+                                     (list wl-summary-new-mark
+                                           wl-summary-unread-uncached-mark
+                                           wl-summary-unread-cached-mark)))
+                           (cons 'p (regexp-quote
+                                     wl-summary-important-mark))))))
+
+(defvar wl-summary-move-spec-unplugged-alist
+  (list (cons 'new (list (cons 't nil)
+                        (cons 'p wl-summary-unread-cached-mark)
+                        (cons 'p (regexp-quote wl-summary-important-mark))))
+       (cons 'unread (list (cons 't nil)
+                           (cons 'p wl-summary-unread-cached-mark)
+                           (cons 'p (regexp-quote
+                                     wl-summary-important-mark))))))
+
+(defsubst wl-summary-next-message (num direction hereto)
+  (if wl-summary-buffer-next-message-func
+      (funcall wl-summary-buffer-next-message-func num direction hereto)  
+    (let ((cur-spec (cdr (assq wl-summary-move-order 
+                              (if (elmo-folder-plugged-p 
+                                   wl-summary-buffer-folder-name)
+                                  wl-summary-move-spec-plugged-alist
+                                wl-summary-move-spec-unplugged-alist))))
+         (nums (memq num (if (eq direction 'up)
+                             (reverse wl-summary-buffer-number-list)
+                           wl-summary-buffer-number-list)))
+         marked-list nums2)
+      (unless hereto (setq nums (cdr nums)))
+      (setq nums2 nums)
+      (if cur-spec
+         (catch 'done
+           (while cur-spec
+             (setq nums nums2)
+             (cond ((eq (car (car cur-spec)) 'p)
+                    (if (setq marked-list (elmo-msgdb-list-messages-mark-match
+                                           wl-summary-buffer-msgdb
+                                           (cdr (car cur-spec))))
+                        (while nums
+                          (if (memq (car nums) marked-list)
+                              (throw 'done (car nums)))
+                          (setq nums (cdr nums)))))
+                   ((eq (car (car cur-spec)) 't)
+                    (while nums
+                      (if (and wl-summary-buffer-target-mark-list
+                               (memq (car nums)
+                                     wl-summary-buffer-target-mark-list))
+                          (throw 'done (car nums)))
+                      (setq nums (cdr nums)))))
+             (setq cur-spec (cdr cur-spec))))
+       (car nums)))))
+
+(defsubst wl-summary-cursor-move (direction hereto)
+  (when (and (eq direction 'up)
+            (eobp))
+    (forward-line -1)
+    (setq hereto t))
+  (let (num)
+    (when (setq num (wl-summary-next-message (wl-summary-message-number)
+                                            direction hereto))
+      (if (numberp num)
+         (wl-thread-jump-to-msg num))
+      t)))
 ;;
 ;; Goto unread or important
 ;; returns t if next message exists in this folder.
 (defun wl-summary-cursor-down (&optional hereto)
   (interactive "P")
-  (if (and (null wl-summary-buffer-target-mark-list)
-          (eq wl-summary-buffer-view 'thread))
-      (wl-thread-jump-to-next-unread hereto)
-    (if hereto
-       (beginning-of-line)
-      (end-of-line))
-    (let ((case-fold-search nil)
-         regex-list)
-      (setq regex-list (wl-summary-cursor-move-regex))
-      (catch 'done
-       (while regex-list
-         (when (re-search-forward
-                (car regex-list)
-                nil t nil)
-           (beginning-of-line)
-           (throw 'done t))
-         (setq regex-list (cdr regex-list)))
-       (beginning-of-line)
-       (throw 'done nil)))))
+  (wl-summary-cursor-move 'down hereto))
+
+(defun wl-summary-cursor-up (&optional hereto)
+  (interactive "P")
+  (wl-summary-cursor-move 'up hereto))
 
 (defun wl-summary-save-view-cache ()
   (save-excursion
@@ -4612,7 +4641,7 @@ If ARG, exit virtual folder."
   "returns update or all or rescan."
   ;; for the case when parts are expanded in the bottom of the folder
   (let ((input-range-list '("update" "all" "rescan" "first:" "last:"
-                           "no-sync" "rescan-noscore"))
+                           "no-sync" "rescan-noscore" "all-visible"))
        (default (or (wl-get-assoc-list-value
                      wl-folder-sync-range-alist
                      folder)
@@ -5114,16 +5143,13 @@ Use function list is `wl-summary-write-current-folder-functions'."
                (nth 2 guess-list))     ; Newsgroups:
            (setq flist nil)
          (setq flist (cdr flist))))
-      (if guess-list
-         (progn
-           (wl-draft (nth 0 guess-list) ; To:
-                     nil nil
-                     (nth 1 guess-list) ; Cc:
-                     nil               
-                     (nth 2 guess-list)) ; Newsgroups:
-           (run-hooks 'wl-mail-setup-hook))
-;;;    (error "%s is not newsgroup" folder)
-       (error "Can't guess by folder %s" folder)))))
+      (when (null guess-list)
+       (error "Can't guess by folder %s" folder))
+      (wl-draft (nth 0 guess-list) nil nil ; To:
+               (nth 1 guess-list) nil  ; Cc:
+               (nth 2 guess-list))     ; Newsgroups:
+      (run-hooks 'wl-mail-setup-hook)
+      (mail-position-on-field "Subject"))))
 
 (defun wl-summary-forward (&optional without-setup-hook)
   ""
@@ -5405,7 +5431,10 @@ Use function list is `wl-summary-write-current-folder-functions'."
              (if (setq fld-win (get-buffer-window fld-buf))
                  (delete-window fld-win)))
           (setq wl-current-summary-buffer (current-buffer))
-         (if (wl-message-redisplay fld num 'mime msgdb force-reload)
+         (if (wl-message-redisplay fld num 'mime msgdb
+                                   (or force-reload
+                                       ;; if draft folder, force reload.
+                                       (string= fld wl-draft-folder)))
              (wl-summary-mark-as-read nil
                                       ;; cached, then change server-mark.
                                       (if wl-message-cache-used
@@ -5447,7 +5476,9 @@ Use function list is `wl-summary-write-current-folder-functions'."
          (setq wl-summary-buffer-last-displayed-msg
                wl-summary-buffer-current-msg)
          (setq wl-current-summary-buffer (current-buffer))
-         (wl-normal-message-redisplay fld num 'no-mime msgdb)
+         (wl-normal-message-redisplay fld num 'no-mime msgdb
+                                      ;; if draft folder, force reload.
+                                      (string= fld wl-draft-folder))
          (wl-summary-mark-as-read nil nil t)
          (setq wl-summary-buffer-current-msg num)
          (when wl-summary-recenter
@@ -5474,7 +5505,9 @@ Use function list is `wl-summary-write-current-folder-functions'."
          (setq wl-summary-buffer-last-displayed-msg
                wl-summary-buffer-current-msg)
          (setq wl-current-summary-buffer (current-buffer))
-         (if (wl-message-redisplay fld num 'all-header msgdb); t if displayed.
+         (if (wl-message-redisplay fld num 'all-header msgdb
+                                   ;; if draft folder, force reload.
+                                   (string= fld wl-draft-folder))
              (wl-summary-mark-as-read nil nil t))
          (setq wl-summary-buffer-current-msg num)
          (when wl-summary-recenter
@@ -5942,22 +5975,13 @@ Use function list is `wl-summary-write-current-folder-functions'."
        (message "Dropping...done"))))
 
 (defun wl-summary-default-get-next-msg (msg)
-  (let (next)
-    (if (and (not wl-summary-buffer-target-mark-list)
-            (eq wl-summary-buffer-view 'thread)
-            (if (eq wl-summary-move-direction-downward nil)
-                (setq next (wl-thread-get-prev-unread msg))
-              (setq next (wl-thread-get-next-unread msg))))
-       next
-      (save-excursion
-       (wl-summary-jump-to-msg msg)
-       (let (wl-summary-buffer-disp-msg)
-         (if (eq wl-summary-move-direction-downward nil)
-             (unless (wl-summary-cursor-up)
-               (wl-summary-prev))
-           (unless (wl-summary-cursor-down)
-             (wl-summary-next)))
-         (wl-summary-message-number))))))
+  (or (wl-summary-next-message msg
+                              (if wl-summary-move-direction-downward 'down
+                                'up)
+                              nil)
+      (cadr (memq msg (if wl-summary-move-direction-downward
+                         wl-summary-buffer-number-list
+                       (reverse wl-summary-buffer-number-list))))))
 
 (defsubst wl-cache-prefetch-p (fld &optional num)
   (cond ((and num wl-cache-prefetch-folder-type-list)
@@ -6020,7 +6044,7 @@ Use function list is `wl-summary-write-current-folder-functions'."
                                                              folder next)))))
                  (if wl-cache-prefetch-debug
                      (message "Reading %d..." msg))
-                 (elmo-buffer-cache-message folder next msgdb)
+                 (elmo-buffer-cache-message folder next msgdb nil 'unread)
                  (if wl-cache-prefetch-debug
                      (message "Reading %d... done" msg))))))))))