* wl-summary.el (wl-summary-line-list-count): Use ".0f" for ml-count
[elisp/wanderlust.git] / wl / wl-summary.el
1 ;;; wl-summary.el --- Summary mode for Wanderlust.
2
3 ;; Copyright (C) 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
4 ;; Copyright (C) 1998,1999,2000 Masahiro MURATA <muse@ba2.so-net.ne.jp>
5 ;; Copyright (C) 1999,2000      TSUMURA Tomoaki <tsumura@kuis.kyoto-u.ac.jp>
6 ;; Copyright (C) 1999,2000      Kenichi OKADA <okada@opaopa.org>
7
8 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
9 ;;      Masahiro MURATA <muse@ba2.so-net.ne.jp>
10 ;;      TSUMURA Tomoaki <tsumura@kuis.kyoto-u.ac.jp>
11 ;;      Kenichi OKADA <okada@opaopa.org>
12 ;; Keywords: mail, net news
13
14 ;; This file is part of Wanderlust (Yet Another Message Interface on Emacsen).
15
16 ;; This program is free software; you can redistribute it and/or modify
17 ;; it under the terms of the GNU General Public License as published by
18 ;; the Free Software Foundation; either version 2, or (at your option)
19 ;; any later version.
20 ;;
21 ;; This program is distributed in the hope that it will be useful,
22 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
23 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 ;; GNU General Public License for more details.
25 ;;
26 ;; You should have received a copy of the GNU General Public License
27 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
28 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
29 ;; Boston, MA 02111-1307, USA.
30 ;;
31
32 ;;; Commentary:
33 ;;
34
35 ;;; Code:
36 ;;
37
38 (require 'elmo)
39 (require 'elmo-multi)
40 (require 'wl-message)
41 (require 'wl-vars)
42 (require 'wl-highlight)
43 (require 'wl-refile)
44 (require 'wl-util)
45 (condition-case nil (require 'timezone) (error nil))
46 (condition-case nil (require 'easymenu) (error nil))
47 (require 'elmo-date)
48 (condition-case nil (require 'ps-print) (error nil))
49
50 (eval-when-compile
51   (require 'cl)
52   (condition-case () (require 'timer) (error nil))
53   (defalias-maybe 'ps-print-buffer-with-faces 'ignore)
54   (defalias-maybe 'elmo-database-msgid-put 'ignore)
55   (defalias-maybe 'elmo-database-close 'ignore)
56   (defalias-maybe 'elmo-database-msgid-get 'ignore)
57   (defalias-maybe 'run-with-idle-timer 'ignore)
58   (defalias-maybe 'ps-print-preprint 'ignore))
59
60 (defvar dragdrop-drop-functions)
61 (defvar scrollbar-height)
62 (defvar mail-reply-buffer)
63
64 (defvar wl-summary-buffer-name "Summary")
65 (defvar wl-summary-mode-map nil)
66 (defvar wl-current-summary-buffer nil)
67
68 (defvar wl-summary-buffer-elmo-folder nil)
69
70 (defmacro wl-summary-buffer-folder-name ()
71   (` (and wl-summary-buffer-elmo-folder
72           (elmo-folder-name-internal wl-summary-buffer-elmo-folder))))
73
74 (defmacro wl-summary-buffer-msgdb ()
75   (` (and wl-summary-buffer-elmo-folder
76           (elmo-folder-msgdb wl-summary-buffer-elmo-folder))))
77
78 (defvar wl-summary-buffer-disp-msg    nil)
79 (defvar wl-summary-buffer-disp-folder nil)
80 (defvar wl-summary-buffer-refile-list nil)
81 (defvar wl-summary-buffer-delete-list nil)
82 (defvar wl-summary-buffer-last-displayed-msg nil)
83 (defvar wl-summary-buffer-current-msg nil)
84 (defvar wl-summary-buffer-unread-count 0)
85 (defvar wl-summary-buffer-new-count    0)
86 (defvar wl-summary-buffer-mime-charset  nil)
87 (defvar wl-summary-buffer-weekday-name-lang  nil)
88 (defvar wl-summary-buffer-thread-indent-set-alist  nil)
89 (defvar wl-summary-buffer-view 'thread)
90 (defvar wl-summary-buffer-message-modified nil)
91 (defvar wl-summary-buffer-mark-modified nil)
92 (defvar wl-summary-buffer-thread-modified nil)
93
94 (defvar wl-summary-buffer-number-column nil)
95 (defvar wl-summary-buffer-temp-mark-column nil)
96 (defvar wl-summary-buffer-persistent-mark-column nil)
97
98 (defvar wl-summary-buffer-persistent nil)
99 (defvar wl-summary-buffer-thread-nodes nil)
100 (defvar wl-summary-buffer-target-mark-list nil)
101 (defvar wl-summary-buffer-copy-list nil)
102 (defvar wl-summary-buffer-prev-refile-destination nil)
103 (defvar wl-summary-buffer-prev-copy-destination nil)
104 (defvar wl-summary-buffer-saved-message nil)
105 (defvar wl-summary-buffer-prev-folder-function nil)
106 (defvar wl-summary-buffer-next-folder-function nil)
107 (defvar wl-summary-buffer-exit-function nil)
108 (defvar wl-summary-buffer-next-message-function nil)
109 (defvar wl-summary-buffer-number-list nil)
110 (defvar wl-summary-buffer-msgdb nil)
111 (defvar wl-summary-buffer-folder-name nil)
112 (defvar wl-summary-buffer-line-formatter nil)
113 (defvar wl-summary-buffer-line-format nil)
114 (defvar wl-summary-buffer-mode-line-formatter nil)
115 (defvar wl-summary-buffer-mode-line nil)
116
117 (defvar wl-thread-indent-level-internal nil)
118 (defvar wl-thread-have-younger-brother-str-internal nil)
119 (defvar wl-thread-youngest-child-str-internal nil)
120 (defvar wl-thread-vertical-str-internal nil)
121 (defvar wl-thread-horizontal-str-internal nil)
122 (defvar wl-thread-space-str-internal nil)
123 (defvar wl-summary-last-visited-folder nil)
124 (defvar wl-read-folder-hist nil)
125 (defvar wl-summary-scored nil)
126 (defvar wl-crosspost-alist-modified nil)
127 (defvar wl-summary-alike-hashtb nil)
128 (defvar wl-summary-search-buf-name " *wl-search-subject*")
129 (defvar wl-summary-delayed-update nil)
130 (defvar wl-summary-search-buf-folder-name nil)
131
132 (defvar wl-summary-get-petname-function 'wl-address-get-petname-1)
133
134 (defvar wl-summary-shell-command-last "")
135
136 (defvar wl-ps-preprint-hook nil)
137 (defvar wl-ps-print-hook nil)
138
139 (make-variable-buffer-local 'wl-summary-buffer-elmo-folder)
140 (make-variable-buffer-local 'wl-summary-search-buf-folder-name)
141 (make-variable-buffer-local 'wl-summary-buffer-disp-msg)
142 (make-variable-buffer-local 'wl-summary-buffer-disp-folder)
143 (make-variable-buffer-local 'wl-summary-buffer-refile-list)
144 (make-variable-buffer-local 'wl-summary-buffer-copy-list)
145 (make-variable-buffer-local 'wl-summary-buffer-target-mark-list)
146 (make-variable-buffer-local 'wl-summary-buffer-delete-list)
147 (make-variable-buffer-local 'wl-summary-buffer-last-displayed-msg)
148 (make-variable-buffer-local 'wl-summary-buffer-unread-count)
149 (make-variable-buffer-local 'wl-summary-buffer-new-count)
150 (make-variable-buffer-local 'wl-summary-buffer-mime-charset)
151 (make-variable-buffer-local 'wl-summary-buffer-weekday-name-lang)
152 (make-variable-buffer-local 'wl-summary-buffer-thread-indent-set)
153 (make-variable-buffer-local 'wl-summary-buffer-view)
154 (make-variable-buffer-local 'wl-summary-buffer-message-modified)
155 (make-variable-buffer-local 'wl-summary-buffer-mark-modified)
156 (make-variable-buffer-local 'wl-summary-buffer-thread-modified)
157 (make-variable-buffer-local 'wl-summary-buffer-number-column)
158 (make-variable-buffer-local 'wl-summary-buffer-temp-mark-column)
159 (make-variable-buffer-local 'wl-summary-buffer-persistent-mark-column)
160 (make-variable-buffer-local 'wl-summary-buffer-persistent)
161 (make-variable-buffer-local 'wl-summary-buffer-thread-nodes)
162 (make-variable-buffer-local 'wl-summary-buffer-prev-refile-destination)
163 (make-variable-buffer-local 'wl-summary-buffer-saved-message)
164 (make-variable-buffer-local 'wl-summary-scored)
165 (make-variable-buffer-local 'wl-summary-default-score)
166 (make-variable-buffer-local 'wl-summary-move-direction-downward)
167 (make-variable-buffer-local 'wl-summary-important-above)
168 (make-variable-buffer-local 'wl-summary-target-above)
169 (make-variable-buffer-local 'wl-summary-mark-below)
170 (make-variable-buffer-local 'wl-summary-expunge-below)
171 (make-variable-buffer-local 'wl-thread-indent-level-internal)
172 (make-variable-buffer-local 'wl-thread-have-younger-brother-str-internal)
173 (make-variable-buffer-local 'wl-thread-youngest-child-str-internal)
174 (make-variable-buffer-local 'wl-thread-vertical-str-internal)
175 (make-variable-buffer-local 'wl-thread-horizontal-str-internal)
176 (make-variable-buffer-local 'wl-thread-space-str-internal)
177 (make-variable-buffer-local 'wl-summary-buffer-prev-folder-function)
178 (make-variable-buffer-local 'wl-summary-buffer-next-folder-function)
179 (make-variable-buffer-local 'wl-summary-buffer-exit-function)
180 (make-variable-buffer-local 'wl-summary-buffer-next-message-function)
181 (make-variable-buffer-local 'wl-summary-buffer-number-list)
182 (make-variable-buffer-local 'wl-summary-buffer-msgdb)
183 (make-variable-buffer-local 'wl-summary-buffer-folder-name)
184 (make-variable-buffer-local 'wl-summary-buffer-line-formatter)
185 (make-variable-buffer-local 'wl-summary-buffer-line-format)
186 (make-variable-buffer-local 'wl-summary-buffer-mode-line-formatter)
187 (make-variable-buffer-local 'wl-summary-buffer-mode-line)
188
189 (defvar wl-datevec)
190 (defvar wl-thr-indent-string)
191 (defvar wl-thr-children-number)
192 (defvar wl-thr-linked)
193 (defvar wl-message-entity)
194 (defvar wl-parent-message-entity)
195 (defvar wl-temp-mark)
196 (defvar wl-persistent-mark)
197
198 ;; internal functions (dummy)
199 (unless (fboundp 'wl-summary-append-message-func-internal)
200   (defun wl-summary-append-message-func-internal (entity msgdb update
201                                                          &optional force-insert)))
202
203 (defmacro wl-summary-sticky-buffer-name (name)
204   (` (concat wl-summary-buffer-name ":" (, name))))
205
206 (defun wl-summary-default-subject (subject-string)
207   (if (string-match "^[ \t]*\\[[^:]+[,: ][0-9]+\\][ \t]*" subject-string)
208       (substring subject-string (match-end 0))
209     subject-string))
210
211 (defun wl-summary-default-from (from)
212   (let (retval tos ng)
213     (unless
214         (and (eq major-mode 'wl-summary-mode)
215              (stringp wl-summary-showto-folder-regexp)
216              (string-match wl-summary-showto-folder-regexp
217                            (wl-summary-buffer-folder-name))
218              (wl-address-user-mail-address-p from)
219              (cond
220               ((and (setq tos (elmo-msgdb-overview-entity-get-to
221                                wl-message-entity))
222                     (not (string= "" tos)))
223                (setq retval
224                      (concat "To:"
225                              (mapconcat
226                               (function
227                                (lambda (to)
228                                  (eword-decode-string
229                                   (if wl-use-petname
230                                       (or
231                                        (funcall
232                                         wl-summary-get-petname-function to)
233                                        (car
234                                         (std11-extract-address-components to))
235                                        to)
236                                     to))))
237                               (wl-parse-addresses tos)
238                               ","))))
239               ((setq ng (elmo-msgdb-overview-entity-get-extra-field
240                          wl-message-entity "newsgroups"))
241                (setq retval (concat "Ng:" ng)))))
242       (if wl-use-petname
243           (setq retval (or (funcall wl-summary-get-petname-function from)
244                            (car (std11-extract-address-components from))
245                            from))
246         (setq retval from)))
247     retval))
248
249 (defun wl-summary-simple-from (string)
250   (if wl-use-petname
251       (or (funcall wl-summary-get-petname-function string)
252           (car (std11-extract-address-components string))
253           string)
254     string))
255
256 (defvar wl-summary-mode-menu-spec
257   '("Summary"
258     ["Read" wl-summary-read t]
259     ["Prev page" wl-summary-prev-page t]
260     ["Next page" wl-summary-next-page t]
261     ["Top"       wl-summary-display-top t]
262     ["Bottom"    wl-summary-display-bottom t]
263     ["Prev"      wl-summary-prev t]
264     ["Next"      wl-summary-next t]
265     ["Up"        wl-summary-up t]
266     ["Down"      wl-summary-down t]
267     ["Parent message" wl-summary-jump-to-parent-message t]
268     "----"
269     ["Sync"            wl-summary-sync t]
270     ["Execute"         wl-summary-exec t]
271     ["Go to other folder" wl-summary-goto-folder t]
272     ["Pick" wl-summary-pick t]
273     ["Mark as read all" wl-summary-mark-as-read-all t]
274     ["Unmark all"      wl-summary-unmark-all t]
275     ["Toggle display message" wl-summary-toggle-disp-msg t]
276     ["Display folder" wl-summary-toggle-disp-folder t]
277     ["Toggle threading" wl-summary-toggle-thread t]
278     ["Stick" wl-summary-stick t]
279     ("Sort"
280      ["By Number" wl-summary-sort-by-number t]
281      ["By Date" wl-summary-sort-by-date t]
282      ["By From" wl-summary-sort-by-from t]
283      ["By Subject" wl-summary-sort-by-subject t])
284     "----"
285     ("Message Operation"
286      ["Mark as read"    wl-summary-mark-as-read t]
287      ["Mark as important" wl-summary-mark-as-important t]
288      ["Mark as unread"   wl-summary-mark-as-unread t]
289      ["Set delete mark" wl-summary-delete t]
290      ["Set refile mark" wl-summary-refile t]
291      ["Set copy mark"   wl-summary-copy t]
292      ["Prefetch"        wl-summary-prefetch t]
293      ["Set target mark" wl-summary-target-mark t]
294      ["Unmark"          wl-summary-unmark t]
295      ["Save"            wl-summary-save t]
296      ["Cancel posted news" wl-summary-cancel-message t]
297      ["Supersedes message" wl-summary-supersedes-message t]
298      ["Resend bounced mail" wl-summary-resend-bounced-mail t]
299      ["Resend message" wl-summary-resend-message t]
300      ["Enter the message" wl-summary-jump-to-current-message t]
301      ["Pipe message" wl-summary-pipe-message t]
302      ["Print message" wl-summary-print-message t])
303     ("Thread Operation"
304      ["Open or Close" wl-thread-open-close (eq wl-summary-buffer-view 'thread)]
305      ["Open all"     wl-thread-open-all (eq wl-summary-buffer-view 'thread)]
306      ["Close all"    wl-thread-close-all (eq wl-summary-buffer-view 'thread)]
307      ["Mark as read" wl-thread-mark-as-read (eq wl-summary-buffer-view 'thread)]
308      ["Mark as important"       wl-thread-mark-as-important (eq wl-summary-buffer-view 'thread)]
309      ["Mark as unread"          wl-thread-mark-as-unread (eq wl-summary-buffer-view 'thread)]
310      ["Set delete mark"  wl-thread-delete (eq wl-summary-buffer-view 'thread)]
311      ["Set refile mark"  wl-thread-refile (eq wl-summary-buffer-view 'thread)]
312      ["Set copy mark"    wl-thread-copy (eq wl-summary-buffer-view 'thread)]
313      ["Prefetch"     wl-thread-prefetch (eq wl-summary-buffer-view 'thread)]
314      ["Set target mark"        wl-thread-target-mark (eq wl-summary-buffer-view 'thread)]
315      ["Unmark"      wl-thread-unmark (eq wl-summary-buffer-view 'thread)]
316      ["Save"            wl-thread-save (eq wl-summary-buffer-view 'thread)]
317      ["Execute"      wl-thread-exec (eq wl-summary-buffer-view 'thread)])
318     ("Region Operation"
319      ["Mark as read" wl-summary-mark-as-read-region t]
320      ["Mark as important" wl-summary-mark-as-important-region t]
321      ["Mark as unread" wl-summary-mark-as-unread-region t]
322      ["Set delete mark" wl-summary-delete-region t]
323      ["Set refile mark" wl-summary-refile-region t]
324      ["Set copy mark" wl-summary-copy-region t]
325      ["Prefetch" wl-summary-prefetch-region t]
326      ["Set target mark" wl-summary-target-mark-region t]
327      ["Unmark" wl-summary-unmark-region t]
328      ["Save" wl-summary-save-region t]
329      ["Execute" wl-summary-exec-region t])
330     ("Mark Operation"
331      ["Mark as read" wl-summary-target-mark-mark-as-read t]
332      ["Mark as important" wl-summary-target-mark-mark-as-important t]
333      ["Mark as unread" wl-summary-target-mark-mark-as-unread t]
334      ["Set delete mark" wl-summary-target-mark-delete t]
335      ["Set refile mark" wl-summary-target-mark-refile t]
336      ["Set copy mark" wl-summary-target-mark-copy t]
337      ["Prefetch" wl-summary-target-mark-prefetch t]
338      ["Save" wl-summary-target-mark-save t]
339      ["Reply with citation" wl-summary-target-mark-reply-with-citation t]
340      ["Forward" wl-summary-target-mark-forward t]
341      ["uudecode" wl-summary-target-mark-uudecode t])
342     ("Score Operation"
343      ["Switch current score file" wl-score-change-score-file t]
344      ["Edit current score file" wl-score-edit-current-scores t]
345      ["Edit score file" wl-score-edit-file t]
346      ["Set mark below" wl-score-set-mark-below t]
347      ["Set expunge below" wl-score-set-expunge-below t]
348      ["Rescore buffer" wl-summary-rescore t]
349      ["Increase score" wl-summary-increase-score t]
350      ["Lower score" wl-summary-lower-score t])
351     "----"
352     ("Writing Messages"
353      ["Write a message" wl-summary-write t]
354      ["Write for current folder" wl-summary-write-current-folder t]
355      ["Reply" wl-summary-reply t]
356      ["Reply with citation" wl-summary-reply-with-citation t]
357      ["Forward" wl-summary-forward t])
358     "----"
359     ["Toggle Plug Status" wl-toggle-plugged t]
360     ["Change Plug Status" wl-plugged-change t]
361     "----"
362     ["Exit Current Folder" wl-summary-exit t]))
363
364 (if wl-on-xemacs
365     (defun wl-summary-setup-mouse ()
366       (define-key wl-summary-mode-map 'button4 'wl-summary-prev)
367       (define-key wl-summary-mode-map 'button5 'wl-summary-next)
368       (define-key wl-summary-mode-map [(shift button4)]
369         'wl-summary-up)
370       (define-key wl-summary-mode-map [(shift button5)]
371         'wl-summary-down)
372       (define-key wl-summary-mode-map 'button2 'wl-summary-click))
373   (defun wl-summary-setup-mouse ()
374     (define-key wl-summary-mode-map [mouse-4] 'wl-summary-prev)
375     (define-key wl-summary-mode-map [mouse-5] 'wl-summary-next)
376     (define-key wl-summary-mode-map [S-mouse-4] 'wl-summary-up)
377     (define-key wl-summary-mode-map [S-mouse-5] 'wl-summary-down)
378     (define-key wl-summary-mode-map [mouse-2] 'wl-summary-click)))
379
380 (if wl-summary-mode-map
381     ()
382   (setq wl-summary-mode-map (make-sparse-keymap))
383   (define-key wl-summary-mode-map " "    'wl-summary-read)
384   (define-key wl-summary-mode-map "."    'wl-summary-redisplay)
385   (define-key wl-summary-mode-map "<"    'wl-summary-display-top)
386   (define-key wl-summary-mode-map ">"    'wl-summary-display-bottom)
387   (define-key wl-summary-mode-map "\177" 'wl-summary-prev-page)
388   (define-key wl-summary-mode-map [backspace] 'wl-summary-prev-page)
389   (define-key wl-summary-mode-map "\r"   'wl-summary-next-line-content)
390   (define-key wl-summary-mode-map "\C-m" 'wl-summary-next-line-content)
391   (define-key wl-summary-mode-map "/"    'wl-thread-open-close)
392   (define-key wl-summary-mode-map "["    'wl-thread-open-all)
393   (define-key wl-summary-mode-map "]"    'wl-thread-close-all)
394   (define-key wl-summary-mode-map "-"    'wl-summary-prev-line-content)
395   (define-key wl-summary-mode-map "\e\r" 'wl-summary-prev-line-content)
396   (define-key wl-summary-mode-map "g"    'wl-summary-goto-folder)
397   (define-key wl-summary-mode-map "G"    'wl-summary-goto-folder-sticky)
398   (define-key wl-summary-mode-map "c"    'wl-summary-mark-as-read-all)
399 ;  (define-key wl-summary-mode-map "D"    'wl-summary-drop-unsync)
400
401   (define-key wl-summary-mode-map "a"    'wl-summary-reply)
402   (define-key wl-summary-mode-map "A"    'wl-summary-reply-with-citation)
403   (define-key wl-summary-mode-map "C"    'wl-summary-cancel-message)
404   (define-key wl-summary-mode-map "E"    'wl-summary-reedit)
405   (define-key wl-summary-mode-map "\eE"  'wl-summary-resend-bounced-mail)
406   (define-key wl-summary-mode-map "f"    'wl-summary-forward)
407   (define-key wl-summary-mode-map "$"    'wl-summary-mark-as-important)
408   (define-key wl-summary-mode-map "@"    'wl-summary-edit-addresses)
409
410   (define-key wl-summary-mode-map "y"    'wl-summary-save)
411   (define-key wl-summary-mode-map "n"    'wl-summary-next)
412   (define-key wl-summary-mode-map "p"    'wl-summary-prev)
413   (define-key wl-summary-mode-map "N"    'wl-summary-down)
414   (define-key wl-summary-mode-map "P"    'wl-summary-up)
415 ;;;(define-key wl-summary-mode-map "w"    'wl-draft)
416   (define-key wl-summary-mode-map "w"    'wl-summary-write)
417   (define-key wl-summary-mode-map "W"    'wl-summary-write-current-folder)
418 ;;;(define-key wl-summary-mode-map "e"     'wl-draft-open-file)
419   (define-key wl-summary-mode-map "e"     'wl-summary-save)
420   (define-key wl-summary-mode-map "\C-c\C-o" 'wl-jump-to-draft-buffer)
421   (define-key wl-summary-mode-map "\C-c\C-a" 'wl-addrmgr)
422   (define-key wl-summary-mode-map "\C-c\C-p" 'wl-summary-previous-buffer)
423   (define-key wl-summary-mode-map "\C-c\C-n" 'wl-summary-next-buffer)
424   (define-key wl-summary-mode-map "H"    'wl-summary-redisplay-all-header)
425   (define-key wl-summary-mode-map "M"    'wl-summary-redisplay-no-mime)
426   (define-key wl-summary-mode-map "B"    'wl-summary-burst)
427   (define-key wl-summary-mode-map "Z"    'wl-status-update)
428   (define-key wl-summary-mode-map "#"    'wl-summary-print-message)
429   (define-key wl-summary-mode-map "|"    'wl-summary-pipe-message)
430   (define-key wl-summary-mode-map "z"    'wl-summary-suspend)
431   (define-key wl-summary-mode-map "q"    'wl-summary-exit)
432   (define-key wl-summary-mode-map "Q"    'wl-summary-force-exit)
433
434   (define-key wl-summary-mode-map "j"    'wl-summary-jump-to-current-message)
435   (define-key wl-summary-mode-map "J"    'wl-thread-jump-to-msg)
436   (define-key wl-summary-mode-map "I"    'wl-summary-incorporate)
437   (define-key wl-summary-mode-map "\M-j" 'wl-summary-jump-to-msg-by-message-id)
438   (define-key wl-summary-mode-map "^"    'wl-summary-jump-to-parent-message)
439   (define-key wl-summary-mode-map "!"    'wl-summary-mark-as-unread)
440
441   (define-key wl-summary-mode-map "s"    'wl-summary-sync)
442   (define-key wl-summary-mode-map "S"    'wl-summary-sort)
443   (define-key wl-summary-mode-map "\M-s"    'wl-summary-stick)
444   (define-key wl-summary-mode-map "T"    'wl-summary-toggle-thread)
445
446   (define-key wl-summary-mode-map "l"    'wl-summary-toggle-disp-folder)
447   (define-key wl-summary-mode-map "v"    'wl-summary-toggle-disp-msg)
448   (define-key wl-summary-mode-map "V"    'wl-summary-virtual)
449
450   (define-key wl-summary-mode-map "\C-i"  'wl-summary-goto-last-displayed-msg)
451   (define-key wl-summary-mode-map "?"    'wl-summary-pick)
452   (define-key wl-summary-mode-map "\ee"  'wl-summary-expire)
453
454   ;; copy & paste.
455   (define-key wl-summary-mode-map "\ew"  'wl-summary-save-current-message)
456   (define-key wl-summary-mode-map "\C-y"  'wl-summary-yank-saved-message)
457
458   ;; line commands
459   (define-key wl-summary-mode-map "R"    'wl-summary-mark-as-read)
460   (define-key wl-summary-mode-map "i"    'wl-summary-prefetch)
461   (define-key wl-summary-mode-map "x"    'wl-summary-exec)
462   (define-key wl-summary-mode-map "*"    'wl-summary-target-mark)
463   (define-key wl-summary-mode-map "o"    'wl-summary-refile)
464   (define-key wl-summary-mode-map "O"    'wl-summary-copy)
465   (define-key wl-summary-mode-map "\M-o" 'wl-summary-refile-prev-destination)
466 ;  (define-key wl-summary-mode-map "\M-O" 'wl-summary-copy-prev-destination)
467   (define-key wl-summary-mode-map "\C-o" 'wl-summary-auto-refile)
468   (define-key wl-summary-mode-map "d"    'wl-summary-delete)
469   (define-key wl-summary-mode-map "u"    'wl-summary-unmark)
470   (define-key wl-summary-mode-map "U"    'wl-summary-unmark-all)
471
472   ;; thread commands
473   (define-key wl-summary-mode-map "t"   (make-sparse-keymap))
474   (define-key wl-summary-mode-map "tR" 'wl-thread-mark-as-read)
475   (define-key wl-summary-mode-map "ti" 'wl-thread-prefetch)
476   (define-key wl-summary-mode-map "tx" 'wl-thread-exec)
477   (define-key wl-summary-mode-map "t*" 'wl-thread-target-mark)
478   (define-key wl-summary-mode-map "to" 'wl-thread-refile)
479   (define-key wl-summary-mode-map "tO" 'wl-thread-copy)
480   (define-key wl-summary-mode-map "td" 'wl-thread-delete)
481   (define-key wl-summary-mode-map "tu" 'wl-thread-unmark)
482   (define-key wl-summary-mode-map "t!" 'wl-thread-mark-as-unread)
483   (define-key wl-summary-mode-map "t$" 'wl-thread-mark-as-important)
484   (define-key wl-summary-mode-map "ty" 'wl-thread-save)
485   (define-key wl-summary-mode-map "ts" 'wl-thread-set-parent)
486
487   ;; target-mark commands
488   (define-key wl-summary-mode-map "m"     (make-sparse-keymap))
489   (define-key wl-summary-mode-map "mi"   'wl-summary-target-mark-prefetch)
490   (define-key wl-summary-mode-map "mR"   'wl-summary-target-mark-mark-as-read)
491   (define-key wl-summary-mode-map "mo"   'wl-summary-target-mark-refile)
492   (define-key wl-summary-mode-map "mO"   'wl-summary-target-mark-copy)
493   (define-key wl-summary-mode-map "md"   'wl-summary-target-mark-delete)
494   (define-key wl-summary-mode-map "my"   'wl-summary-target-mark-save)
495   (define-key wl-summary-mode-map "m!"   'wl-summary-target-mark-mark-as-unread)
496   (define-key wl-summary-mode-map "m$"   'wl-summary-target-mark-mark-as-important)
497   (define-key wl-summary-mode-map "mu"   'wl-summary-delete-all-temp-marks)
498   (define-key wl-summary-mode-map "mU"   'wl-summary-target-mark-uudecode)
499   (define-key wl-summary-mode-map "ma"   'wl-summary-target-mark-all)
500   (define-key wl-summary-mode-map "mt"   'wl-summary-target-mark-thread)
501   (define-key wl-summary-mode-map "mA"   'wl-summary-target-mark-reply-with-citation)
502   (define-key wl-summary-mode-map "mf"   'wl-summary-target-mark-forward)
503   (define-key wl-summary-mode-map "m?"   'wl-summary-target-mark-pick)
504   (define-key wl-summary-mode-map "m#"   'wl-summary-target-mark-print)
505   (define-key wl-summary-mode-map "m|"   'wl-summary-target-mark-pipe)
506
507   ;; region commands
508   (define-key wl-summary-mode-map "r"    (make-sparse-keymap))
509   (define-key wl-summary-mode-map "rR"   'wl-summary-mark-as-read-region)
510   (define-key wl-summary-mode-map "ri"   'wl-summary-prefetch-region)
511   (define-key wl-summary-mode-map "rx"   'wl-summary-exec-region)
512   (define-key wl-summary-mode-map "mr"   'wl-summary-target-mark-region)
513   (define-key wl-summary-mode-map "r*"   'wl-summary-target-mark-region)
514   (define-key wl-summary-mode-map "ro"   'wl-summary-refile-region)
515   (define-key wl-summary-mode-map "rO"   'wl-summary-copy-region)
516   (define-key wl-summary-mode-map "rd"   'wl-summary-delete-region)
517   (define-key wl-summary-mode-map "ru"   'wl-summary-unmark-region)
518   (define-key wl-summary-mode-map "r!"   'wl-summary-mark-as-unread-region)
519   (define-key wl-summary-mode-map "r$"   'wl-summary-mark-as-important-region)
520   (define-key wl-summary-mode-map "ry"   'wl-summary-save-region)
521
522   ;; score commands
523   (define-key wl-summary-mode-map "K"    'wl-summary-increase-score)
524   (define-key wl-summary-mode-map "L"    'wl-summary-lower-score)
525   (define-key wl-summary-mode-map "h"    (make-sparse-keymap))
526   (define-key wl-summary-mode-map "hR"   'wl-summary-rescore)
527   (define-key wl-summary-mode-map "hc"   'wl-score-change-score-file)
528   (define-key wl-summary-mode-map "he"   'wl-score-edit-current-scores)
529   (define-key wl-summary-mode-map "hf"   'wl-score-edit-file)
530   (define-key wl-summary-mode-map "hF"   'wl-score-flush-cache)
531   (define-key wl-summary-mode-map "hm"   'wl-score-set-mark-below)
532   (define-key wl-summary-mode-map "hx"   'wl-score-set-expunge-below)
533
534   (define-key wl-summary-mode-map "\M-t" 'wl-toggle-plugged)
535   (define-key wl-summary-mode-map "\C-t" 'wl-plugged-change)
536   ;;
537   (define-key wl-summary-mode-map "\C-x\C-s" 'wl-summary-save-status)
538   (wl-summary-setup-mouse)
539   (easy-menu-define
540    wl-summary-mode-menu
541    wl-summary-mode-map
542    "Menu used in Summary mode."
543    wl-summary-mode-menu-spec))
544
545 (defun wl-status-update ()
546   (interactive)
547   (wl-address-init))
548
549 (defun wl-summary-display-top ()
550   (interactive)
551   (goto-char (point-min))
552   (when wl-summary-lazy-highlight
553     (wl-highlight-summary-window))
554   (if wl-summary-buffer-disp-msg
555       (wl-summary-redisplay)))
556
557 (defun wl-summary-display-bottom ()
558   (interactive)
559   (goto-char (point-max))
560   (forward-line -1)
561   (when wl-summary-lazy-highlight
562     (wl-highlight-summary-window))
563   (if wl-summary-buffer-disp-msg
564       (wl-summary-redisplay)))
565
566 (defun wl-summary-count-unread ()
567   (let ((pair
568          (elmo-msgdb-count-marks (wl-summary-buffer-msgdb)
569                                  wl-summary-new-mark
570                                  (list wl-summary-unread-uncached-mark
571                                        wl-summary-unread-cached-mark))))
572     (if (eq major-mode 'wl-summary-mode)
573         (setq wl-summary-buffer-new-count (car pair)
574               wl-summary-buffer-unread-count (cdr pair)))
575     pair))
576
577 (defun wl-summary-message-string (&optional use-cache)
578   "Return full body string of current message.
579 If optional USE-CACHE is non-nil, use cache if exists."
580   (let ((number (wl-summary-message-number))
581         (folder wl-summary-buffer-elmo-folder))
582     (if (null number)
583         (message "No message.")
584       (elmo-set-work-buf
585        (elmo-message-fetch folder
586                            number
587                            (elmo-make-fetch-strategy
588                             'entire
589                             use-cache ; use cache
590                             nil ; save cache (should `t'?)
591                             (and
592                              use-cache
593                              (elmo-file-cache-get-path
594                               (elmo-message-field folder number 'message-id))))
595                            nil
596                            (current-buffer)
597                            'unread)
598        (buffer-string)))))
599
600 (defun wl-summary-reedit (&optional arg)
601   "Re-edit current message.
602 If ARG is non-nil, Supersedes message"
603   (interactive "P")
604   (if arg
605       (wl-summary-supersedes-message)
606     (if (string= (wl-summary-buffer-folder-name) wl-draft-folder)
607         (if (wl-summary-message-number)
608             (progn
609               (wl-draft-reedit (wl-summary-message-number))
610               (if (wl-message-news-p)
611                   (mail-position-on-field "Newsgroups")
612                 (mail-position-on-field "To"))
613               (delete-other-windows)))
614       (wl-draft-edit-string (wl-summary-message-string)))))
615
616 (defun wl-summary-resend-bounced-mail ()
617   "Re-mail the current message.
618 This only makes sense if the current message is a bounce message which
619 contains some mail you have written but has been bounced back to
620 you."
621   (interactive)
622   (save-excursion
623     (wl-summary-set-message-buffer-or-redisplay)
624     (set-buffer (wl-message-get-original-buffer))
625     (goto-char (point-min))
626     (let ((case-fold-search nil))
627       (cond
628        ((and
629          (re-search-forward
630           (concat "^\\($\\|[Cc]ontent-[Tt]ype:[ \t]+multipart/\\(report\\|mixed\\)\\)") nil t)
631          (not (bolp))
632          (re-search-forward "boundary=\"\\([^\"]+\\)\"" nil t))
633         (let ((boundary (buffer-substring (match-beginning 1) (match-end 1)))
634               start)
635           (cond
636            ((and (setq start (re-search-forward
637                               (concat "^--" boundary "\n"
638                                       "\\([Cc]ontent-[Dd]escription:.*\n\\)?"
639                                       "[Cc]ontent-[Tt]ype:[ \t]+"
640                                       "\\(message/rfc822\\|text/rfc822-headers\\)\n"
641                                       "\\(.+\n\\)*\n") nil t))
642                  (re-search-forward
643                   (concat "\n\\(--" boundary "\\)--\n") nil t))
644             (wl-draft-edit-string (buffer-substring start (match-beginning 1))))
645            (t
646             (message "Seems no message/rfc822 part.")))))
647        ((let ((case-fold-search t))
648           (re-search-forward wl-rejected-letter-start nil t))
649         (skip-chars-forward " \t\n")
650         (wl-draft-edit-string (buffer-substring (point) (point-max))))
651        (t
652         (message "Does not appear to be a rejected letter."))))))
653
654 (defun wl-summary-resend-message (address)
655   "Resend the current message to ADDRESS."
656   (interactive "sResend message to: ")
657   (if (or (null address) (string-match "^[ \t]*$" address))
658       (message "No address specified.")
659     (message "Resending message to %s..." address)
660     (save-excursion
661       (let ((original (wl-summary-get-original-buffer)))
662         ;; We first set up a normal mail buffer.
663         (set-buffer (get-buffer-create " *wl-draft-resend*"))
664         (buffer-disable-undo (current-buffer))
665         (erase-buffer)
666         (setq wl-sent-message-via nil)
667         ;; Insert our usual headers.
668         (wl-draft-insert-from-field)
669         (wl-draft-insert-date-field)
670         (insert "to: " address "\n")
671         (goto-char (point-min))
672         ;; Rename them all to "Resent-*".
673         (while (re-search-forward "^[A-Za-z]" nil t)
674           (forward-char -1)
675           (insert "Resent-"))
676         (widen)
677         (forward-line)
678         (delete-region (point) (point-max))
679         (let ((beg  (point)))
680           ;; Insert the message to be resent.
681           (insert-buffer-substring original)
682           (goto-char (point-min))
683           (search-forward "\n\n")
684           (forward-char -1)
685           (save-restriction
686             (narrow-to-region beg (point))
687             (wl-draft-delete-fields wl-ignored-resent-headers)
688             (goto-char (point-max)))
689           (insert mail-header-separator)
690           ;; Rename all old ("Previous-")Resent headers.
691           (while (re-search-backward "^\\(Previous-\\)*Resent-" beg t)
692             (beginning-of-line)
693             (insert "Previous-"))
694           ;; Quote any "From " lines at the beginning.
695           (goto-char beg)
696           (when (looking-at "From ")
697             (replace-match "X-From-Line: ")))
698         ;; Send it.
699         (wl-draft-dispatch-message)
700         (kill-buffer (current-buffer)))
701       (message "Resending message to %s...done" address))))
702
703 (defun wl-summary-detect-mark-position ()
704   (let ((column wl-summary-buffer-number-column)
705         (formatter wl-summary-buffer-line-formatter)
706         (dummy-temp (char-to-string 200))
707         (dummy-persistent (char-to-string 201))
708         temp persistent)
709     (with-temp-buffer
710       (setq wl-summary-buffer-number-column column
711             wl-summary-buffer-line-formatter formatter)
712       (insert
713        (wl-summary-create-line
714         (elmo-msgdb-make-entity
715          :number 10000
716          :from "foo"
717          :subject "bar"
718          :size 100)
719         nil
720         dummy-temp
721         dummy-persistent))
722       (goto-char (point-min))
723       (setq temp (save-excursion
724                    (search-forward dummy-temp nil t)
725                    (current-column))
726             persistent (save-excursion
727                          (search-forward dummy-persistent nil t)
728                          (current-column))))
729     (setq wl-summary-buffer-temp-mark-column temp
730           wl-summary-buffer-persistent-mark-column persistent)))
731
732 (defun wl-summary-buffer-set-folder (folder)
733   (if (stringp folder)
734       (setq folder (wl-folder-get-elmo-folder folder)))
735   (setq wl-summary-buffer-elmo-folder folder)
736   (make-local-variable 'wl-message-buffer)
737   (setq wl-summary-buffer-mime-charset (or (wl-get-assoc-list-value
738                                             wl-folder-mime-charset-alist
739                                             (elmo-folder-name-internal folder))
740                                            wl-mime-charset))
741   (setq wl-summary-buffer-weekday-name-lang
742         (or (wl-get-assoc-list-value
743              wl-folder-weekday-name-lang-alist
744              (elmo-folder-name-internal folder))
745             wl-summary-weekday-name-lang))
746   (setq wl-summary-buffer-thread-indent-set
747         (wl-get-assoc-list-value
748          wl-folder-thread-indent-set-alist
749          (elmo-folder-name-internal folder)))
750   (setq wl-summary-buffer-number-column
751         (or (wl-get-assoc-list-value wl-summary-number-column-alist
752                                      (wl-summary-buffer-folder-name))
753             wl-summary-default-number-column))
754   (wl-line-formatter-setup
755    wl-summary-buffer-line-formatter
756    (setq wl-summary-buffer-line-format
757          (or (wl-get-assoc-list-value
758               wl-folder-summary-line-format-alist
759               (elmo-folder-name-internal folder))
760              wl-summary-line-format))
761    wl-summary-line-format-spec-alist)
762   (wl-line-formatter-setup
763    wl-summary-buffer-mode-line-formatter
764    wl-summary-mode-line-format
765    wl-summary-mode-line-format-spec-alist)
766   (wl-summary-detect-mark-position)
767   (setq wl-summary-buffer-persistent
768         (wl-folder-persistent-p (elmo-folder-name-internal folder)))
769   (elmo-folder-set-persistent-internal folder wl-summary-buffer-persistent)
770   ;; process duplicates.
771   (elmo-folder-set-process-duplicates-internal
772    folder (cdr (elmo-string-matched-assoc
773                 (elmo-folder-name-internal folder)
774                 wl-folder-process-duplicates-alist)))
775   (setq
776    wl-thread-indent-level-internal
777    (or (nth 0 wl-summary-buffer-thread-indent-set)
778        wl-thread-indent-level)
779    wl-thread-have-younger-brother-str-internal
780    (or (nth 1 wl-summary-buffer-thread-indent-set)
781        wl-thread-have-younger-brother-str)
782    wl-thread-youngest-child-str-internal
783    (or (nth 2 wl-summary-buffer-thread-indent-set)
784        wl-thread-youngest-child-str)
785    wl-thread-vertical-str-internal
786    (or (nth 3 wl-summary-buffer-thread-indent-set)
787        wl-thread-vertical-str)
788    wl-thread-horizontal-str-internal
789    (or (nth 4 wl-summary-buffer-thread-indent-set)
790        wl-thread-horizontal-str)
791    wl-thread-space-str-internal
792    (or (nth 5 wl-summary-buffer-thread-indent-set)
793        wl-thread-space-str))
794   (run-hooks 'wl-summary-buffer-set-folder-hook))
795
796 (defun wl-summary-mode ()
797   "Major mode for reading threaded messages.
798 See Info under Wanderlust for full documentation.
799
800 Special commands:
801 \\{wl-summary-mode-map}
802
803 Entering Folder mode calls the value of `wl-summary-mode-hook'."
804   (interactive)
805   (unless (interactive-p) (kill-all-local-variables))
806   (setq major-mode 'wl-summary-mode)
807   (setq mode-name "Summary")
808   (use-local-map wl-summary-mode-map)
809 ;;;(setq default-directory (or wl-tmp-dir (expand-file-name "~/")))
810   (setq buffer-read-only t)
811   (setq truncate-lines t)
812 ;;;(make-local-variable 'tab-width)
813 ;;;(setq tab-width 1)
814   (buffer-disable-undo (current-buffer))
815   (setq selective-display t
816         selective-display-ellipses nil)
817   (wl-mode-line-buffer-identification '(wl-summary-buffer-mode-line))
818   (easy-menu-add wl-summary-mode-menu)
819   (when wl-summary-lazy-highlight
820     (if wl-on-xemacs 
821         (progn
822           (make-local-variable 'pre-idle-hook)
823           (add-hook 'pre-idle-hook 'wl-highlight-summary-window))
824       (make-local-variable 'window-scroll-functions)
825       (add-hook 'window-scroll-functions 'wl-highlight-summary-window)))
826   ;; This hook may contain the function `wl-setup-summary' for reasons
827   ;; of system internal to accord facilities for the Emacs variants.
828   (run-hooks 'wl-summary-mode-hook))
829
830 (defun wl-summary-overview-entity-compare-by-date (x y)
831   "Compare entity X and Y by date."
832   (condition-case nil
833       (string<
834        (timezone-make-date-sortable
835         (elmo-msgdb-overview-entity-get-date x))
836        (timezone-make-date-sortable
837         (elmo-msgdb-overview-entity-get-date y)))
838     (error))) ;; ignore error.
839
840 (defun wl-summary-overview-entity-compare-by-number (x y)
841    "Compare entity X and Y by number."
842   (<
843    (elmo-msgdb-overview-entity-get-number x)
844    (elmo-msgdb-overview-entity-get-number y)))
845
846 (defun wl-summary-overview-entity-compare-by-from (x y)
847   "Compare entity X and Y by from."
848   (string<
849    (wl-address-header-extract-address
850     (or (elmo-msgdb-overview-entity-get-from-no-decode x)
851         wl-summary-no-from-message))
852    (wl-address-header-extract-address
853     (or (elmo-msgdb-overview-entity-get-from-no-decode y)
854         wl-summary-no-from-message))))
855
856 (defun wl-summary-overview-entity-compare-by-subject (x y)
857   "Compare entity X and Y by subject."
858   (string< (elmo-msgdb-overview-entity-get-subject-no-decode x)
859            (elmo-msgdb-overview-entity-get-subject-no-decode y)))
860
861 (defun wl-summary-sort-by-date ()
862   (interactive)
863   (wl-summary-rescan "date"))
864 (defun wl-summary-sort-by-number ()
865   (interactive)
866   (wl-summary-rescan "number"))
867 (defun wl-summary-sort-by-subject ()
868   (interactive)
869   (wl-summary-rescan "subject"))
870 (defun wl-summary-sort-by-from ()
871   (interactive)
872   (wl-summary-rescan "from"))
873
874 (defun wl-summary-rescan (&optional sort-by)
875   "Rescan current folder without updating."
876   (interactive)
877   (let* ((cur-buf (current-buffer))
878          (msgdb (wl-summary-buffer-msgdb))
879          (overview (elmo-msgdb-get-overview msgdb))
880          (number-alist (elmo-msgdb-get-number-alist msgdb))
881          (elmo-mime-charset wl-summary-buffer-mime-charset)
882          i percent num
883          gc-message entity
884          curp
885          (inhibit-read-only t)
886          (buffer-read-only nil)
887          expunged)
888     (fset 'wl-summary-append-message-func-internal
889           (wl-summary-get-append-message-func))
890     (erase-buffer)
891     (message "Re-scanning...")
892     (setq i 0)
893     (setq num (length overview))
894     (when sort-by
895       (message "Sorting by %s..." sort-by)
896       (setq overview
897             (sort overview
898                   (intern (format "wl-summary-overview-entity-compare-by-%s"
899                                   sort-by))))
900       (message "Sorting by %s...done" sort-by)
901       (elmo-msgdb-set-overview (wl-summary-buffer-msgdb)
902                                overview))
903     (setq curp overview)
904     (set-buffer cur-buf)
905     (setq wl-thread-entity-hashtb (elmo-make-hash (* (length overview) 2)))
906     (setq wl-thread-entity-list nil)
907     (setq wl-thread-entities nil)
908     (setq wl-summary-buffer-number-list nil)
909     (setq wl-summary-buffer-target-mark-list nil)
910     (setq wl-summary-buffer-refile-list nil)
911     (setq wl-summary-buffer-delete-list nil)
912     (setq wl-summary-delayed-update nil)
913     (elmo-kill-buffer wl-summary-search-buf-name)
914     (while curp
915       (setq entity (car curp))
916       (wl-summary-append-message-func-internal entity msgdb nil)
917       (setq curp (cdr curp))
918       (when (> num elmo-display-progress-threshold)
919         (setq i (+ i 1))
920         (if (or (zerop (% i 5)) (= i num))
921             (elmo-display-progress
922              'wl-summary-rescan "Constructing summary structure..."
923              (/ (* i 100) num)))))
924     (when wl-summary-delayed-update
925       (while wl-summary-delayed-update
926         (message "Parent (%d) of message %d is no entity"
927                  (caar wl-summary-delayed-update)
928                  (elmo-msgdb-overview-entity-get-number
929                   (cdar wl-summary-delayed-update)))
930         (wl-summary-append-message-func-internal
931          (cdar wl-summary-delayed-update) msgdb nil t)
932         (setq wl-summary-delayed-update (cdr wl-summary-delayed-update))))
933     (message "Constructing summary structure...done")
934     (set-buffer cur-buf)
935     (if (eq wl-summary-buffer-view 'thread)
936         (progn
937           (message "Inserting thread...")
938           (wl-thread-insert-top)
939           (message "Inserting thread...done"))
940       (wl-summary-make-number-list))
941     (when wl-use-scoring
942       (setq wl-summary-scored nil)
943       (wl-summary-score-headers nil msgdb
944                                 (wl-summary-rescore-msgs number-alist)
945                                 t)
946       (when (and wl-summary-scored
947                  (setq expunged (wl-summary-score-update-all-lines)))
948         (message "%d message(s) are expunged by scoring." (length expunged))))
949     (wl-summary-set-message-modified)
950     (wl-summary-count-unread)
951     (wl-summary-update-modeline)
952     (goto-char (point-max))
953     (forward-line -1)
954     (set-buffer-modified-p nil)))
955
956 (defun wl-summary-next-folder-or-exit (&optional next-entity upward)
957   (if (and next-entity
958            wl-auto-select-next)
959       (let (retval)
960         (wl-summary-toggle-disp-msg 'off)
961         (unwind-protect
962             (setq retval
963                   (wl-summary-goto-folder-subr next-entity
964                                                'force-update
965                                                nil
966                                                nil ; not sticky
967                                                t   ; interactive!
968                                                ))
969           (wl-folder-set-current-entity-id (wl-folder-get-entity-id next-entity))
970           (if (and (eq retval 'more-next)
971                    (memq wl-auto-select-next '(unread skip-no-unread))
972                    (memq this-command wl-summary-next-no-unread-command))
973               (if upward
974                   (wl-summary-up
975                    t (eq wl-auto-select-next 'skip-no-unread))
976                 (goto-char (point-max))
977                 (forward-line -1)
978                 (wl-summary-down
979                  t (eq wl-auto-select-next 'skip-no-unread))))))
980     (wl-summary-exit)))
981
982 (defun wl-summary-entity-info-msg (entity finfo)
983   (or (and entity
984            (concat
985             (elmo-replace-in-string
986              (if (memq 'ask-folder wl-use-folder-petname)
987                  (wl-folder-get-petname entity)
988                entity)
989              "%" "%%")
990             (if (null (car finfo))
991                 " (? new/? unread)"
992               (format
993                " (%d new/%d unread)"
994                (nth 0 finfo)
995                (+ (nth 0 finfo)
996                   (nth 1 finfo))))))
997       "folder mode"))
998
999 (defun wl-summary-set-message-modified ()
1000   (elmo-folder-set-message-modified-internal
1001    wl-summary-buffer-elmo-folder t)
1002   (setq wl-summary-buffer-message-modified t))
1003 (defun wl-summary-message-modified-p ()
1004   wl-summary-buffer-message-modified)
1005 (defun wl-summary-set-mark-modified ()
1006   (elmo-folder-set-mark-modified-internal
1007    wl-summary-buffer-elmo-folder t)
1008   (setq wl-summary-buffer-mark-modified t))
1009 (defun wl-summary-mark-modified-p ()
1010   wl-summary-buffer-mark-modified)
1011 (defun wl-summary-set-thread-modified ()
1012   (setq wl-summary-buffer-thread-modified t))
1013 (defun wl-summary-thread-modified-p ()
1014   wl-summary-buffer-thread-modified)
1015
1016 (defsubst wl-summary-cleanup-temp-marks (&optional sticky)
1017   (if (or wl-summary-buffer-refile-list
1018           wl-summary-buffer-copy-list
1019           wl-summary-buffer-delete-list)
1020       (if (y-or-n-p "Marks remain to be executed.  Execute them? ")
1021           (progn
1022             (wl-summary-exec)
1023             (if (or wl-summary-buffer-refile-list
1024                     wl-summary-buffer-copy-list
1025                     wl-summary-buffer-delete-list)
1026                 (error "Some execution was failed")))
1027         ;; delete temp-marks
1028         (message "")
1029         (wl-summary-delete-all-refile-marks)
1030         (wl-summary-delete-all-copy-marks)
1031         (wl-summary-delete-all-delete-marks)))
1032   (if wl-summary-buffer-target-mark-list
1033       (progn
1034         (wl-summary-delete-all-target-marks)
1035         (setq wl-summary-buffer-target-mark-list nil)))
1036   (wl-summary-delete-all-temp-marks-on-buffer sticky)
1037   (setq wl-summary-scored nil))
1038
1039 ;; a subroutine for wl-summary-exit/wl-save-status
1040 ;; Note that folder is not commited here.
1041 (defun wl-summary-save-view ()
1042   ;; already in summary buffer.
1043   (when wl-summary-buffer-persistent
1044     ;; save the current summary buffer view.
1045     (if (and wl-summary-cache-use
1046              (or (wl-summary-message-modified-p)
1047                  (wl-summary-mark-modified-p)
1048                  (wl-summary-thread-modified-p)))
1049         (wl-summary-save-view-cache))))
1050
1051 (defun wl-summary-save-status ()
1052   "Save summary view and msgdb."
1053   (interactive)
1054   (if (interactive-p) (message "Saving summary status..."))
1055   (wl-summary-save-view)
1056   (elmo-folder-commit wl-summary-buffer-elmo-folder)
1057   (elmo-folder-check wl-summary-buffer-elmo-folder)
1058   (if wl-use-scoring (wl-score-save))
1059   (if (interactive-p) (message "Saving summary status...done.")))
1060
1061 (defun wl-summary-force-exit ()
1062   "Exit current summary.  Buffer is deleted even the buffer is sticky."
1063   (interactive)
1064   (wl-summary-exit 'force-exit))
1065
1066 (defun wl-summary-exit (&optional force-exit)
1067   "Exit current summary.  if FORCE-EXIT, exits even the summary is sticky."
1068   (interactive "P")
1069   (let ((summary-buf (current-buffer))
1070         (sticky (wl-summary-sticky-p))
1071         summary-win
1072         message-buf message-win
1073         folder-buf folder-win)
1074     (run-hooks 'wl-summary-exit-pre-hook)
1075     (if wl-summary-buffer-exit-function
1076         (funcall wl-summary-buffer-exit-function)
1077       (if (or force-exit (not sticky))
1078           (wl-summary-cleanup-temp-marks sticky))
1079       (unwind-protect
1080           ;; save summary status
1081           (progn
1082             (wl-summary-save-view)
1083             (if (or force-exit (not sticky))
1084                 (elmo-folder-close wl-summary-buffer-elmo-folder)
1085               (elmo-folder-commit wl-summary-buffer-elmo-folder)
1086               (elmo-folder-check wl-summary-buffer-elmo-folder))
1087             (if wl-use-scoring (wl-score-save)))
1088         ;; for sticky summary
1089         (wl-delete-all-overlays)
1090         (setq wl-summary-buffer-disp-msg nil)
1091         (elmo-kill-buffer wl-summary-search-buf-name)
1092         ;; delete message window if displayed.
1093         (if (and wl-message-buffer (get-buffer-window wl-message-buffer))
1094             (delete-window (get-buffer-window wl-message-buffer)))
1095         (if (and wl-summary-use-frame
1096                  (> (length (visible-frame-list)) 1))
1097             (delete-frame))
1098         (if (setq folder-buf (get-buffer wl-folder-buffer-name))
1099             (if wl-summary-use-frame
1100                 (let (select-frame)
1101                   (save-selected-window
1102                     (dolist (frame (visible-frame-list))
1103                       (select-frame frame)
1104                       (if (get-buffer-window folder-buf)
1105                           (setq select-frame frame))))
1106                   (if select-frame
1107                       (select-frame select-frame)
1108                     (switch-to-buffer folder-buf)))
1109               (if (setq folder-win (get-buffer-window folder-buf))
1110                   ;; folder win is already displayed.
1111                   (select-window folder-win)
1112                 ;; folder win is not displayed.
1113                 (switch-to-buffer folder-buf)))
1114           ;; currently no folder buffer
1115           (wl-folder))
1116         (and wl-folder-move-cur-folder
1117              wl-folder-buffer-cur-point
1118              (goto-char wl-folder-buffer-cur-point))
1119         (setq wl-folder-buffer-cur-path nil)
1120         (setq wl-folder-buffer-cur-entity-id nil)
1121         (wl-delete-all-overlays)
1122         (if wl-summary-exit-next-move
1123             (wl-folder-next-unsync t)
1124           (beginning-of-line))
1125         (if (setq summary-win (get-buffer-window summary-buf))
1126             (delete-window summary-win))
1127         (if (or force-exit
1128                 (not sticky))
1129             (progn
1130               (set-buffer summary-buf)
1131               (kill-buffer summary-buf)))
1132         (run-hooks 'wl-summary-exit-hook)))))
1133
1134 (defun wl-summary-suspend ()
1135   (interactive)
1136   (wl-summary-exit)
1137   (wl-folder-suspend))
1138
1139 (defun wl-summary-sync-force-update (&optional unset-cursor no-check)
1140   (interactive)
1141   (wl-summary-sync-update unset-cursor nil no-check))
1142
1143 (defsubst wl-summary-sync-all-init ()
1144   (wl-summary-cleanup-temp-marks)
1145   (erase-buffer)
1146   (wl-summary-set-message-modified)
1147   (wl-summary-set-mark-modified)
1148   (setq wl-thread-entity-hashtb (elmo-make-hash
1149                                  (* (length (elmo-msgdb-get-number-alist
1150                                              (wl-summary-buffer-msgdb))) 2)))
1151   (setq wl-thread-entity-list nil)
1152   (setq wl-thread-entities nil)
1153   (setq wl-summary-buffer-number-list nil)
1154   (setq wl-summary-buffer-target-mark-list nil)
1155   (setq wl-summary-buffer-refile-list nil)
1156   (setq wl-summary-buffer-copy-list nil)
1157   (setq wl-summary-buffer-delete-list nil))
1158
1159 (defun wl-summary-sync (&optional unset-cursor force-range)
1160   (interactive)
1161   (let* ((folder wl-summary-buffer-elmo-folder)
1162          (inhibit-read-only t)
1163          (buffer-read-only nil)
1164          (msgdb-dir (elmo-folder-msgdb-path folder))
1165          (range (or force-range (wl-summary-input-range
1166                                  (elmo-folder-name-internal folder)))))
1167     (cond ((string= range "rescan")
1168            (let ((msg (wl-summary-message-number)))
1169              (wl-summary-rescan)
1170              (and msg (wl-summary-jump-to-msg msg))))
1171           ((string= range "rescan-noscore")
1172            (let ((msg (wl-summary-message-number))
1173                  wl-use-scoring)
1174              (wl-summary-rescan)
1175              (and msg (wl-summary-jump-to-msg msg))))
1176           ((string= range "cache-status")
1177            (let ((msg (wl-summary-message-number)))
1178              (wl-summary-resume-cache-status)
1179              (and msg (wl-summary-jump-to-msg msg))))
1180           ((or (string-match "last:" range)
1181                (string-match "first:" range))
1182            (wl-summary-goto-folder-subr (concat "/" range "/"
1183                                                 (elmo-folder-name-internal
1184                                                  folder))
1185             'force-update nil nil t))
1186           (t
1187            (wl-summary-sync-update unset-cursor
1188                                    (cond ((string= range "all") 'all)
1189                                          ((string= range "all-visible")
1190                                           'visible-only)))))))
1191
1192 (defvar wl-summary-edit-addresses-candidate-fields
1193   ;; First element becomes default.
1194   '("from" "to" "cc"))
1195
1196 (defun wl-summary-edit-addresses-collect-candidate-fields (mime-charset)
1197   (let ((fields wl-summary-edit-addresses-candidate-fields)
1198         body candidates components)
1199     (while fields
1200       (setq body
1201             (mapconcat 'identity (elmo-multiple-field-body (car fields))
1202                        ","))
1203       (setq body (wl-parse-addresses body))
1204       (if body (setq candidates (append candidates body)))
1205       (setq fields (cdr fields)))
1206     (setq candidates (elmo-uniq-list candidates))
1207     (elmo-set-work-buf
1208      (elmo-set-buffer-multibyte default-enable-multibyte-characters)
1209      (mapcar (function
1210               (lambda (x)
1211                 (setq components (std11-extract-address-components x))
1212                 (cons (nth 1 components)
1213                       (and (car components)
1214                            (eword-decode-string
1215                             (decode-mime-charset-string
1216                              (car components)
1217                              mime-charset))))))
1218              candidates))))
1219
1220 (defun wl-summary-edit-addresses-subr (the-email name-in-addr)
1221   ;; returns nil if there's no change.
1222   (if (elmo-get-hash-val (downcase the-email) wl-address-petname-hash)
1223       (let (char)
1224         (message "'%s' already exists. (e)dit/(d)elete/(c)ancel?"
1225                  the-email)
1226         (while (not (or (eq (setq char (read-char)) ?\r)
1227                         (eq char ?\n)
1228                         (eq char ? )
1229                         (eq char ?e)
1230                         (eq char ?c)
1231                         (eq char ?d)))
1232           (message
1233            "Please answer `e' or `d' or `c'. (e)dit/(d)elete/(c)ancel?"))
1234         (cond
1235          ((or (eq char ?e)
1236               (eq char ?\n)
1237               (eq char ?\r)
1238               (eq char ? ))
1239           ;; Change Addresses
1240           (wl-address-add-or-change
1241            the-email
1242            (wl-address-header-extract-realname
1243             (cdr (assoc
1244                   (let ((completion-ignore-case t) comp)
1245                     (setq comp
1246                           (try-completion the-email wl-address-completion-list))
1247                     (if (equal comp t) the-email comp))
1248                   wl-address-completion-list))))
1249           "edited")
1250          ((eq char ?d)
1251           ;; Delete Addresses
1252           (if (y-or-n-p (format "Delete '%s'? "
1253                                 the-email))
1254               (progn
1255                 (wl-address-delete the-email)
1256                 "deleted")
1257             (message "")
1258             nil))
1259          (t (message "")
1260             nil)))
1261     ;; Add Petname
1262     (wl-address-add-or-change the-email name-in-addr)
1263     "added"))
1264
1265 (defun wl-summary-edit-addresses (&optional addr-str)
1266   "Edit address book interactively.
1267 Optional argument ADDR-STR is used as a target address if specified."
1268   (interactive (if current-prefix-arg
1269                    (list (read-from-minibuffer "Target address: "))))
1270   (if (null (wl-summary-message-number))
1271       (message "No message.")
1272     (save-excursion
1273       (let* ((charset wl-summary-buffer-mime-charset)
1274              (candidates
1275               (with-current-buffer (wl-summary-get-original-buffer)
1276                 (wl-summary-edit-addresses-collect-candidate-fields
1277                  charset)))
1278              address pair result)
1279         (if addr-str
1280             (setq address addr-str)
1281           (when candidates
1282             (setq address (car (car candidates)))
1283             (setq address
1284                   (completing-read
1285                    (format "Target address (%s): " address)
1286                    (mapcar
1287                     (function (lambda (x) (cons (car x) (car x))))
1288                     candidates)
1289                    nil nil nil nil address))))
1290         (when address
1291           (setq pair (assoc address candidates))
1292           (unless pair
1293             (setq pair (cons address nil)))
1294           (when (setq result (wl-summary-edit-addresses-subr (car pair) (cdr pair)))
1295             ;; update alias
1296             (wl-status-update)
1297             (setq address (assoc (car pair) wl-address-list))
1298             (if address
1299                 (message "%s, %s, <%s> is %s."
1300                          (nth 2 address)
1301                          (nth 1 address)
1302                          (nth 0 address)
1303                          result)))
1304 ;;; i'd like to update summary-buffer, but...
1305 ;;;     (wl-summary-rescan)
1306           (run-hooks 'wl-summary-edit-addresses-hook))))))
1307
1308 (defun wl-summary-incorporate (&optional arg)
1309   "Check and prefetch all uncached messages.
1310 If ARG is non-nil, checking is omitted."
1311   (interactive "P")
1312   (unless arg
1313     (save-excursion
1314       (wl-summary-sync-force-update)))
1315   (wl-summary-prefetch-region (point-min) (point-max)
1316                               wl-summary-incorporate-marks))
1317
1318 (defun wl-summary-prefetch-msg (number &optional arg)
1319   "Returns status-mark. if skipped, returns nil."
1320   ;; prefetching procedure.
1321   (save-excursion
1322     (let* ((msgdb (wl-summary-buffer-msgdb))
1323            (number-alist (elmo-msgdb-get-number-alist msgdb))
1324            (message-id (cdr (assq number number-alist)))
1325            (ov (elmo-msgdb-overview-get-entity message-id msgdb))
1326            (entity ov)
1327            (size (elmo-msgdb-overview-entity-get-size ov))
1328            (inhibit-read-only t)
1329            (buffer-read-only nil)
1330            (file-cached (elmo-file-cache-exists-p message-id))
1331            (force-read (and size
1332                             (or (and (null wl-prefetch-confirm) arg)
1333                                 (null wl-prefetch-threshold)
1334                                 (< size wl-prefetch-threshold))))
1335            mark new-mark)
1336       (unwind-protect
1337           (progn
1338             (when (and (or arg (not file-cached))
1339                        size (not force-read) wl-prefetch-confirm)
1340               (setq force-read
1341                     (save-restriction
1342                       (widen)
1343                       (y-or-n-p
1344                        (format
1345                         "Message from %s has %d bytes.  Prefetch it? "
1346                         (concat
1347                          "[ "
1348                          (save-match-data
1349                            (wl-set-string-width
1350                             17
1351                             (funcall wl-summary-from-function
1352                              (eword-decode-string
1353                               (elmo-delete-char
1354                                ?\"
1355                                (or
1356                                 (elmo-msgdb-overview-entity-get-from ov)
1357                                 "??")))))) " ]")
1358                         size))))
1359               (message ""))             ; flush.
1360             (setq mark (elmo-msgdb-get-mark msgdb number))
1361             (if force-read
1362                 (save-excursion
1363                   (save-match-data
1364                     ;; online
1365                     (if (or arg (not file-cached))
1366                         (elmo-message-encache
1367                          wl-summary-buffer-elmo-folder
1368                          number))
1369                     (setq new-mark
1370                           (cond
1371                            ((string= mark
1372                                      wl-summary-unread-uncached-mark)
1373                             wl-summary-unread-cached-mark)
1374                            ((string= mark wl-summary-new-mark)
1375                             (setq wl-summary-buffer-new-count
1376                                   (- wl-summary-buffer-new-count 1))
1377                             (setq wl-summary-buffer-unread-count
1378                                   (+ wl-summary-buffer-unread-count 1))
1379                             wl-summary-unread-cached-mark)
1380                            ((string= mark wl-summary-read-uncached-mark)
1381                             nil)
1382                            (t mark)))
1383                     (elmo-msgdb-set-mark msgdb number new-mark)
1384                     (or new-mark (setq new-mark " "))
1385                     (wl-summary-set-mark-modified)
1386                     (wl-summary-update-modeline)
1387                     (wl-folder-update-unread
1388                      (wl-summary-buffer-folder-name)
1389                      (+ wl-summary-buffer-unread-count
1390                         wl-summary-buffer-new-count)))
1391                   new-mark)))))))
1392
1393 ;;(defvar wl-summary-message-uncached-marks
1394 ;;  (list wl-summary-new-mark
1395 ;;      wl-summary-unread-uncached-mark
1396 ;;      wl-summary-read-uncached-mark))
1397
1398 (defun wl-summary-prefetch-region (beg end &optional prefetch-marks)
1399   (interactive "r")
1400   (let ((count 0)
1401         targets
1402         mark length
1403         entity msg
1404         start-pos pos)
1405     (save-excursion
1406       (setq start-pos (point))
1407       (save-restriction
1408         (narrow-to-region beg end)
1409         ;; collect prefetch targets.
1410         (message "Collecting marks...")
1411         (goto-char (point-min))
1412         (while (not (eobp))
1413           (setq mark (wl-summary-persistent-mark)
1414                 msg (wl-summary-message-number))
1415           (if (or (and (null prefetch-marks)
1416                        msg
1417                        (null (elmo-file-cache-exists-p
1418                               (elmo-message-field
1419                                wl-summary-buffer-elmo-folder
1420                                msg
1421                                'message-id))))
1422                   (member mark prefetch-marks))
1423               (setq targets (nconc targets (list msg))))
1424           (setq entity (wl-thread-get-entity msg))
1425           (if (or (not (eq wl-summary-buffer-view 'thread))
1426                   (wl-thread-entity-get-opened entity))
1427               (); opened. no hidden children.
1428             (setq targets (nconc
1429                            targets
1430                            (wl-thread-get-children-msgs-uncached
1431                             msg prefetch-marks))))
1432           (forward-line 1))
1433         (setq length (length targets))
1434         (message "Prefetching...")
1435         (while targets
1436           (setq mark (if (not (wl-thread-entity-parent-invisible-p
1437                                (wl-thread-get-entity (car targets))))
1438                          (progn
1439                            (wl-summary-jump-to-msg (car targets))
1440                            (wl-summary-prefetch))
1441                        (wl-summary-prefetch-msg (car targets))))
1442           (if (if prefetch-marks
1443                   (string= mark wl-summary-unread-cached-mark)
1444                 (or (string= mark wl-summary-unread-cached-mark)
1445                     (string= mark " ")))
1446               (message "Prefetching... %d/%d message(s)"
1447                        (setq count (+ 1 count)) length))
1448           ;; redisplay!
1449           (save-excursion
1450             (setq pos (point))
1451             (goto-char start-pos)
1452             (if (pos-visible-in-window-p pos)
1453                 (save-restriction
1454                   (widen)
1455                   (sit-for 0))))
1456           (setq targets (cdr targets)))
1457         (message "Prefetched %d/%d message(s)" count length)
1458         (cons count length)))))
1459
1460 (defun wl-summary-prefetch (&optional arg)
1461   "Prefetch current message."
1462   (interactive "P")
1463   (save-excursion
1464     (let ((inhibit-read-only t)
1465           (buffer-read-only nil)
1466           (mark (wl-summary-persistent-mark)))
1467       (setq mark (wl-summary-prefetch-msg (wl-summary-message-number) arg))
1468       (when mark
1469         (delete-backward-char 1)
1470         (insert mark)
1471         (if wl-summary-highlight
1472             (wl-highlight-summary-current-line)))
1473       (set-buffer-modified-p nil)
1474       mark)))
1475
1476 (defun wl-summary-delete-marks-on-buffer (marks)
1477   (while marks
1478     (wl-summary-unmark (pop marks))))
1479
1480 (defun wl-summary-delete-copy-marks-on-buffer (copies)
1481   (wl-summary-delete-marks-on-buffer copies))
1482
1483 (defun wl-summary-delete-all-refile-marks ()
1484   (let ((marks wl-summary-buffer-refile-list))
1485     (while marks
1486       (wl-summary-unmark (car (pop marks))))))
1487
1488 (defun wl-summary-delete-all-copy-marks ()
1489   (let ((marks wl-summary-buffer-copy-list))
1490     (while marks
1491       (wl-summary-unmark (car (pop marks))))))
1492
1493 (defun wl-summary-delete-all-delete-marks ()
1494   (wl-summary-delete-marks-on-buffer wl-summary-buffer-delete-list))
1495
1496 (defun wl-summary-delete-all-target-marks ()
1497   (wl-summary-delete-marks-on-buffer wl-summary-buffer-target-mark-list))
1498
1499 (defun wl-summary-delete-all-temp-marks-on-buffer (&optional sticky)
1500   ;; for summary view cache saving.
1501   (save-excursion
1502     (goto-char (point-min))
1503     (let ((inhibit-read-only t)
1504           (buffer-read-only nil))
1505        (while (not (eobp))
1506         (unless (string= (wl-summary-temp-mark) " ")
1507           (delete-backward-char 1)
1508           (insert " "))
1509         (forward-line 1)))))
1510
1511 (defun wl-summary-mark-as-read-region (beg end)
1512   (interactive "r")
1513   (save-excursion
1514     (save-restriction
1515       (narrow-to-region beg end)
1516       (goto-char (point-min))
1517       (if (eq wl-summary-buffer-view 'thread)
1518           (progn
1519             (while (not (eobp))
1520               (let* ((number (wl-summary-message-number))
1521                      (entity (wl-thread-get-entity number))
1522                      children)
1523                 (if (wl-thread-entity-get-opened entity)
1524                     ;; opened...mark line.
1525                     (wl-summary-mark-as-read number)
1526                   ;; closed
1527                   (wl-summary-mark-as-read number) ; mark itself.
1528                   (setq children (wl-thread-get-children-msgs number))
1529                   (while children
1530                     (wl-summary-mark-as-read (car children))
1531                     (setq children (cdr children))))
1532                 (forward-line 1))))
1533         (while (not (eobp))
1534           (wl-summary-mark-as-read (wl-summary-message-number))
1535           (forward-line 1)))))
1536   (wl-summary-count-unread)
1537   (wl-summary-update-modeline))
1538
1539 (defun wl-summary-mark-as-unread-region (beg end)
1540   (interactive "r")
1541   (save-excursion
1542     (save-restriction
1543       (narrow-to-region beg end)
1544 ;;; use narrowing.
1545 ;;;      (save-excursion (goto-char end)
1546 ;;;                   (end-of-line) (point)))
1547       (goto-char (point-min))
1548       (if (eq wl-summary-buffer-view 'thread)
1549           (progn
1550             (while (not (eobp))
1551               (let* ((number (wl-summary-message-number))
1552                      (entity (wl-thread-get-entity number))
1553                      children)
1554                 (if (wl-thread-entity-get-opened entity)
1555                     ;; opened...mark line.
1556                     ;; Crossposts are not processed
1557                     (wl-summary-mark-as-unread)
1558                   ;; closed
1559                   (wl-summary-mark-as-unread) ; mark itself.
1560                   (setq children
1561                         (delq number (wl-thread-get-children-msgs number)))
1562                   (while children
1563                     (wl-summary-mark-as-unread (car children))
1564                     (setq children (cdr children))))
1565                 (forward-line 1))))
1566         (while (not (eobp))
1567           (wl-summary-mark-as-unread)
1568           (forward-line 1)))))
1569   (wl-summary-count-unread)
1570   (wl-summary-update-modeline))
1571
1572 (defun wl-summary-mark-as-important-region (beg end)
1573   (interactive "r")
1574   (save-excursion
1575     (save-restriction
1576       (narrow-to-region beg end);(save-excursion (goto-char end)
1577                                         ;    (end-of-line) (point)))
1578       (goto-char (point-min))
1579       (if (eq wl-summary-buffer-view 'thread)
1580           (progn
1581             (while (not (eobp))
1582               (let* ((number (wl-summary-message-number))
1583                      (entity (wl-thread-get-entity number))
1584                      children)
1585                 (if (wl-thread-entity-get-opened entity)
1586                     ;; opened...mark line.
1587                     ;; Crossposts are not processed
1588                     (wl-summary-mark-as-important)
1589                   ;; closed
1590                   (wl-summary-mark-as-important) ; mark itself.
1591                   (setq children
1592                         (delq number (wl-thread-get-children-msgs number)))
1593                   (while children
1594                     (wl-thread-msg-mark-as-important (car children))
1595                     (setq children (cdr children))))
1596                 (forward-line 1))))
1597         (while (not (eobp))
1598           (wl-summary-mark-as-important)
1599           (forward-line 1)))))
1600   (wl-summary-count-unread)
1601   (wl-summary-update-modeline))
1602
1603 (defun wl-summary-mark-as-read-all ()
1604   (interactive)
1605   (if (or (not (interactive-p))
1606           (y-or-n-p "Mark all messages as read? "))
1607       (let* ((folder wl-summary-buffer-elmo-folder)
1608              (cur-buf (current-buffer))
1609              (msgdb (wl-summary-buffer-msgdb))
1610              (inhibit-read-only t)
1611              (buffer-read-only nil)
1612              (case-fold-search nil)
1613              msg mark)
1614         (message "Setting all msgs as read...")
1615         (elmo-folder-mark-as-read folder
1616                                   (elmo-folder-list-unreads
1617                                    folder
1618                                    (list wl-summary-unread-cached-mark
1619                                          wl-summary-unread-uncached-mark
1620                                          wl-summary-new-mark)))
1621         (save-excursion
1622           (goto-char (point-min))
1623           (while (not (eobp))
1624             (setq msg (wl-summary-message-number))
1625             (setq mark (wl-summary-persistent-mark))
1626             (when (and (not (string= mark " "))
1627                        (not (string= mark wl-summary-important-mark))
1628                        (not (string= mark wl-summary-read-uncached-mark)))
1629               (delete-backward-char 1)
1630               (if (or (not (elmo-message-use-cache-p folder msg))
1631                       (string= mark wl-summary-unread-cached-mark))
1632                   (progn
1633                     (insert " ")
1634                     (elmo-msgdb-set-mark msgdb msg nil))
1635                 ;; New mark and unread-uncached mark
1636                 (insert wl-summary-read-uncached-mark)
1637                 (elmo-msgdb-set-mark
1638                  msgdb msg wl-summary-read-uncached-mark))
1639               (if wl-summary-highlight
1640                   (wl-highlight-summary-current-line nil nil t)))
1641             (forward-line 1)))
1642         (elmo-folder-replace-marks
1643          folder
1644          (list (cons wl-summary-unread-cached-mark
1645                      nil)
1646                (cons wl-summary-unread-uncached-mark
1647                      wl-summary-read-uncached-mark)
1648                (cons wl-summary-new-mark
1649                      wl-summary-read-uncached-mark)))
1650         (wl-summary-set-mark-modified)
1651         (wl-folder-update-unread (wl-summary-buffer-folder-name) 0)
1652         (setq wl-summary-buffer-unread-count 0)
1653         (setq wl-summary-buffer-new-count    0)
1654         (wl-summary-update-modeline)
1655         (message "Setting all msgs as read...done")
1656         (set-buffer-modified-p nil))))
1657
1658 (defun wl-summary-delete-cache ()
1659   "Delete cache of current message."
1660   (interactive)
1661   (save-excursion
1662     (let* ((inhibit-read-only t)
1663            (buffer-read-only nil)
1664            (folder wl-summary-buffer-elmo-folder)
1665            (msgdb (wl-summary-buffer-msgdb))
1666            (number-alist (elmo-msgdb-get-number-alist msgdb))
1667            (case-fold-search nil)
1668            mark number unread new-mark)
1669       (setq mark (wl-summary-persistent-mark))
1670       (cond
1671        ((or (string= mark wl-summary-new-mark)
1672             (string= mark wl-summary-unread-uncached-mark)
1673             (string= mark wl-summary-important-mark))
1674         ;; noop
1675         )
1676        ((string= mark wl-summary-unread-cached-mark)
1677         (setq new-mark wl-summary-unread-uncached-mark))
1678        (t
1679         (setq new-mark wl-summary-read-uncached-mark)))
1680       (when new-mark
1681         (setq number (wl-summary-message-number))
1682         (delete-backward-char 1)
1683         (insert new-mark)
1684         (elmo-file-cache-delete
1685          (elmo-file-cache-get-path
1686           (elmo-message-field wl-summary-buffer-elmo-folder
1687                               number
1688                               'message-id)))
1689         (elmo-msgdb-set-mark msgdb number new-mark)
1690         (wl-summary-set-mark-modified)
1691         (if wl-summary-highlight
1692             (wl-highlight-summary-current-line nil nil t))
1693         (set-buffer-modified-p nil)))))
1694
1695 (defun wl-summary-resume-cache-status ()
1696   "Resume the cache status of all messages in the current folder."
1697   (interactive)
1698   (let* ((folder wl-summary-buffer-elmo-folder)
1699          (cur-buf (current-buffer))
1700          (msgdb (wl-summary-buffer-msgdb))
1701          (number-alist (elmo-msgdb-get-number-alist msgdb))
1702          (inhibit-read-only t)
1703          (buffer-read-only nil)
1704          (case-fold-search nil)
1705          msg mark msgid set-mark)
1706     (message "Resuming cache status...")
1707     (save-excursion
1708       (goto-char (point-min))
1709       (while (not (eobp))
1710         (setq msg (wl-summary-message-number))
1711         (setq mark (wl-summary-persistent-mark))
1712         (setq msgid (elmo-msgdb-get-field msgdb msg 'message-id))
1713         (setq set-mark nil)
1714         (if (elmo-file-cache-exists-p msgid)
1715             (if (or
1716                  (string= mark wl-summary-unread-uncached-mark) ; U -> !
1717                  (string= mark wl-summary-new-mark)             ; N -> !
1718                  )
1719                 (setq set-mark wl-summary-unread-cached-mark)
1720               (if (string= mark wl-summary-read-uncached-mark)  ; u -> ' '
1721                   (setq set-mark " ")))
1722           (if (string= mark " ")
1723               (setq set-mark wl-summary-read-uncached-mark)     ;' ' -> u
1724             (if (string= mark wl-summary-unread-cached-mark)
1725                 (setq set-mark wl-summary-unread-uncached-mark) ; !  -> U
1726               )))
1727         (when set-mark
1728           (delete-backward-char 1)
1729           (insert set-mark)
1730           (elmo-msgdb-set-mark msgdb msg
1731                                (if (string= set-mark " ") nil set-mark))
1732           (if wl-summary-highlight
1733               (wl-highlight-summary-current-line)))
1734         (forward-line 1))
1735       (wl-summary-set-mark-modified)
1736       (wl-summary-count-unread)
1737       (wl-summary-update-modeline)
1738       (message "Resuming cache status...done")
1739       (set-buffer-modified-p nil))))
1740
1741 (defun wl-summary-delete-messages-on-buffer (msgs &optional deleting-info)
1742   (interactive)
1743   (save-excursion
1744     (let ((inhibit-read-only t)
1745           (buffer-read-only nil)
1746           (msgs2 msgs)
1747           (len (length msgs))
1748           (i 0)
1749           update-list)
1750       (elmo-kill-buffer wl-summary-search-buf-name)
1751       (while msgs
1752         (if (eq wl-summary-buffer-view 'thread)
1753             (progn
1754               ;; don't use wl-append(nconc), because list is broken. ...why?
1755               (setq update-list
1756                     (append update-list
1757                             (wl-thread-delete-message (car msgs))))
1758               (setq update-list (delq (car msgs) update-list)))
1759           (goto-char (point-min))
1760           (if (wl-summary-jump-to-msg (car msgs))
1761               (progn
1762                 (delete-region (point-at-bol) (point-at-eol))
1763                 (delete-char 1) ; delete '\n'
1764                 (setq wl-summary-buffer-number-list
1765                       (delq (car msgs) wl-summary-buffer-number-list)))))
1766         (when (and deleting-info
1767                    (> len elmo-display-progress-threshold))
1768           (setq i (1+ i))
1769           (if (or (zerop (% i 5)) (= i len))
1770               (elmo-display-progress
1771                'wl-summary-delete-messages-on-buffer deleting-info
1772                (/ (* i 100) len))))
1773         (setq msgs (cdr msgs)))
1774       (when (eq wl-summary-buffer-view 'thread)
1775         (wl-thread-update-line-msgs (elmo-uniq-list update-list)
1776                                     (unless deleting-info 'no-msg))
1777         (wl-thread-cleanup-symbols msgs2))
1778       (wl-summary-count-unread)
1779       (wl-summary-update-modeline)
1780       (wl-folder-update-unread
1781        (wl-summary-buffer-folder-name)
1782        (+ wl-summary-buffer-unread-count wl-summary-buffer-new-count)))))
1783
1784 (defun wl-summary-replace-status-marks (before after)
1785   "Replace the status marks on buffer."
1786   (interactive)
1787   (save-excursion
1788     (goto-char (point-min))
1789     (let ((inhibit-read-only t)
1790           (buffer-read-only nil))
1791       (while (not (eobp))
1792         (when (string= (wl-summary-persistent-mark) before)
1793           (delete-backward-char 1)
1794           (insert after)
1795           (if wl-summary-highlight
1796               (wl-highlight-summary-current-line)))
1797         (forward-line 1)))))
1798
1799 (defun wl-summary-get-delete-folder (folder)
1800   (if (string= folder wl-trash-folder)
1801       'null
1802     (let* ((type (or (wl-get-assoc-list-value wl-delete-folder-alist folder)
1803                      'trash)))
1804       (cond ((stringp type)
1805              type)
1806             ((or (equal type 'remove) (equal type 'null))
1807              'null)
1808             (t;; (equal type 'trash)
1809              (let ((trash-folder (wl-folder-get-elmo-folder wl-trash-folder)))
1810                (unless (elmo-folder-exists-p trash-folder)
1811                  (if (y-or-n-p
1812                       (format "Trash Folder %s does not exist, create it? "
1813                               wl-trash-folder))
1814                      (elmo-folder-create trash-folder)
1815                    (error "Trash Folder is not created"))))
1816                wl-trash-folder)))))
1817
1818 (defun wl-summary-get-append-message-func ()
1819   (if (eq wl-summary-buffer-view 'thread)
1820       'wl-summary-insert-thread-entity
1821     'wl-summary-insert-sequential))
1822
1823 (defun wl-summary-sort ()
1824   (interactive)
1825   (let ((sort-by (let ((input-range-list '("number" "date" "subject" "from"))
1826                        (default "date")
1827                        in)
1828                    (setq in
1829                          (completing-read
1830                           (format "Sort by (%s): " default)
1831                           (mapcar
1832                            (function (lambda (x) (cons x x)))
1833                            input-range-list)))
1834                    (if (string= in "")
1835                        default
1836                      in))))
1837     (if (not (member sort-by '("number" "date" "subject" "from")))
1838         (error "Sort by %s is not implemented"  sort-by))
1839     (wl-summary-rescan sort-by)))
1840
1841 (defun wl-summary-sync-marks ()
1842   "Update marks in summary."
1843   (interactive)
1844   (let ((last-progress 0)
1845         (i 0)
1846         unread-marks importants unreads
1847         importants-in-db unreads-in-db diff diffs
1848         mes progress)
1849     ;; synchronize marks.
1850     (when (not (eq (elmo-folder-type-internal
1851                     wl-summary-buffer-elmo-folder)
1852                    'internal))
1853       (message "Updating marks...")
1854       (setq unread-marks (list wl-summary-unread-cached-mark
1855                                wl-summary-unread-uncached-mark
1856                                wl-summary-new-mark)
1857             importants-in-db (elmo-folder-list-messages-mark-match
1858                               wl-summary-buffer-elmo-folder
1859                               (regexp-quote wl-summary-important-mark))
1860             unreads-in-db (elmo-folder-list-messages-mark-match
1861                            wl-summary-buffer-elmo-folder
1862                            (wl-regexp-opt unread-marks))
1863             importants (elmo-folder-list-importants
1864                         wl-summary-buffer-elmo-folder
1865                         wl-summary-important-mark)
1866             unreads (elmo-folder-list-unreads
1867                      wl-summary-buffer-elmo-folder
1868                      unread-marks))
1869       (setq diff (elmo-list-diff importants importants-in-db))
1870       (setq diffs (cadr diff)) ; important-deletes
1871       (setq mes (format "Updated (-%d" (length diffs)))
1872       (while diffs
1873         (wl-summary-mark-as-important (car diffs)
1874                                       wl-summary-important-mark
1875                                       'no-server)
1876         (setq diffs (cdr diffs)))
1877       (setq diffs (car diff)) ; important-appends
1878       (setq mes (concat mes (format "/+%d) important," (length diffs))))
1879       (while diffs
1880         (wl-summary-mark-as-important (car diffs) " " 'no-server)
1881         (setq diffs (cdr diffs)))
1882       (setq diff (elmo-list-diff unreads unreads-in-db))
1883       (setq diffs (cadr diff))
1884       (setq mes (concat mes (format "(-%d" (length diffs))))
1885       (while diffs
1886         (wl-summary-mark-as-read (car diffs) 'no-folder)
1887         (setq diffs (cdr diffs)))
1888       (setq diffs (car diff)) ; unread-appends
1889       (setq mes (concat mes (format "/+%d) unread mark(s)." (length diffs))))
1890       (while diffs
1891         (wl-summary-mark-as-unread (car diffs) 'no-server 'no-modeline)
1892         (setq diffs (cdr diffs)))
1893       (if (interactive-p) (message mes)))))
1894
1895 (defun wl-summary-sync-update (&optional unset-cursor sync-all no-check)
1896   "Update the summary view to the newest folder status."
1897   (interactive)
1898   (let* ((folder wl-summary-buffer-elmo-folder)
1899          (case-fold-search nil)
1900          (elmo-mime-charset wl-summary-buffer-mime-charset)
1901          (inhibit-read-only t)
1902          (buffer-read-only nil)
1903          gc-message
1904          overview number-alist
1905          curp num i new-msgdb
1906          append-list delete-list crossed
1907          update-thread update-top-list
1908          expunged mes sync-result entity)
1909     (unwind-protect
1910         (progn
1911           (unless wl-summary-buffer-elmo-folder
1912             (error "(Internal error) Folder is not set:%s" (buffer-name
1913                                                             (current-buffer))))
1914           (fset 'wl-summary-append-message-func-internal
1915                 (wl-summary-get-append-message-func))
1916           ;; Flush pending append operations (disconnected operation).
1917           ;;(setq seen-list
1918           ;;(wl-summary-flush-pending-append-operations seen-list))
1919           (goto-char (point-max))
1920           (wl-folder-confirm-existence folder (elmo-folder-plugged-p folder))
1921           (setq sync-result (elmo-folder-synchronize
1922                              folder
1923                              wl-summary-new-mark
1924                              wl-summary-unread-uncached-mark
1925                              wl-summary-unread-cached-mark
1926                              wl-summary-read-uncached-mark
1927                              wl-summary-important-mark
1928                              sync-all no-check))
1929           (setq new-msgdb (nth 0 sync-result))
1930           (setq delete-list (nth 1 sync-result))
1931           (setq crossed (nth 2 sync-result))
1932           (if sync-result
1933               (progn
1934                 ;; Setup sync-all
1935                 (if sync-all (wl-summary-sync-all-init))
1936 ;    (if (and has-nntp
1937 ;            (elmo-nntp-max-number-precedes-list-active-p))
1938         ;; XXX this does not work correctly in rare case.
1939 ;       (setq delete-list
1940 ;             (wl-summary-delete-canceled-msgs-from-list
1941 ;              delete-list
1942 ;              (wl-summary-buffer-msgdb))))
1943                 (when delete-list
1944                   (wl-summary-delete-messages-on-buffer delete-list "Deleting...")
1945                   (message "Deleting...done"))
1946                 (when new-msgdb
1947                   (wl-summary-replace-status-marks
1948                    wl-summary-new-mark
1949                    wl-summary-unread-uncached-mark))
1950                 (setq append-list (elmo-msgdb-get-overview new-msgdb))
1951                 (setq curp append-list)
1952                 (setq num (length curp))
1953                 (when append-list
1954                   (setq i 0)
1955
1956                   ;; set these value for append-message-func
1957                   (setq overview (elmo-msgdb-get-overview
1958                                   (elmo-folder-msgdb folder)))
1959                   (setq number-alist (elmo-msgdb-get-number-alist
1960                                       (elmo-folder-msgdb folder)))
1961
1962                   (setq wl-summary-delayed-update nil)
1963                   (elmo-kill-buffer wl-summary-search-buf-name)
1964                   (while curp
1965                     (setq entity (car curp))
1966                     (when (setq update-thread
1967                                 (wl-summary-append-message-func-internal
1968                                  entity (elmo-folder-msgdb folder)
1969                                  (not sync-all)))
1970                       (wl-append update-top-list update-thread))
1971                     (if elmo-use-database
1972                         (elmo-database-msgid-put
1973                          (car entity) (elmo-folder-name-internal folder)
1974                          (elmo-msgdb-overview-entity-get-number entity)))
1975                     (setq curp (cdr curp))
1976                     (when (> num elmo-display-progress-threshold)
1977                       (setq i (+ i 1))
1978                       (if (or (zerop (% i 5)) (= i num))
1979                           (elmo-display-progress
1980                            'wl-summary-sync-update "Updating thread..."
1981                            (/ (* i 100) num)))))
1982                   (when wl-summary-delayed-update
1983                     (while wl-summary-delayed-update
1984                       (message "Parent (%d) of message %d is no entity"
1985                                (caar wl-summary-delayed-update)
1986                                (elmo-msgdb-overview-entity-get-number
1987                                 (cdar wl-summary-delayed-update)))
1988                       (when (setq update-thread
1989                                   (wl-summary-append-message-func-internal
1990                                    (cdar wl-summary-delayed-update)
1991                                    (elmo-folder-msgdb folder)
1992                                    (not sync-all) t))
1993                         (wl-append update-top-list update-thread))
1994                       (setq wl-summary-delayed-update
1995                             (cdr wl-summary-delayed-update))))
1996                   (when (and (eq wl-summary-buffer-view 'thread)
1997                              update-top-list)
1998                     (wl-thread-update-indent-string-thread
1999                      (elmo-uniq-list update-top-list)))
2000                   (message "Updating thread...done"))
2001                 (unless (eq wl-summary-buffer-view 'thread)
2002                   (wl-summary-make-number-list))
2003                 (wl-summary-set-message-modified)
2004                 (wl-summary-set-mark-modified)
2005                 (when (and sync-all (eq wl-summary-buffer-view 'thread))
2006                   (elmo-kill-buffer wl-summary-search-buf-name)
2007                   (message "Inserting thread...")
2008                   (wl-thread-insert-top)
2009                   (message "Inserting thread...done"))
2010                 (if elmo-use-database
2011                     (elmo-database-close))
2012                 (run-hooks 'wl-summary-sync-updated-hook)
2013                 (setq mes
2014                       (if (and (eq (length delete-list) 0)
2015                                (eq num 0))
2016                           (format
2017                            "No updates for \"%s\"" (elmo-folder-name-internal
2018                                                     folder))
2019                         (format "Updated (-%d/+%d) message(s)"
2020                                 (length delete-list) num))))
2021             (setq mes "Quit updating.")))
2022       ;; synchronize marks.
2023       (if (and wl-summary-auto-sync-marks sync-result)
2024           (wl-summary-sync-marks))
2025       ;; scoring
2026       (when wl-use-scoring
2027         (setq wl-summary-scored nil)
2028         (wl-summary-score-headers nil (wl-summary-buffer-msgdb)
2029                                   (and sync-all
2030                                        (wl-summary-rescore-msgs number-alist))
2031                                   sync-all)
2032         (when (and wl-summary-scored
2033                    (setq expunged (wl-summary-score-update-all-lines)))
2034           (setq mes (concat mes
2035                             (format " (%d expunged)"
2036                                     (length expunged))))))
2037       (if (and crossed (> crossed 0))
2038           (setq mes
2039                 (if mes
2040                     (concat mes
2041                             (format " (%d crosspost)" crossed))
2042                   (format "%d crosspost message(s)" crossed)))
2043         (and mes (setq mes (concat mes "."))))
2044       ;; Update Folder mode
2045       (wl-folder-set-folder-updated
2046        (elmo-folder-name-internal folder)
2047        (list 0
2048              (let ((pair (wl-summary-count-unread)))
2049                (+ (car pair) (cdr pair)))
2050              (elmo-folder-messages folder)))
2051       (wl-summary-update-modeline)
2052       ;;
2053       (unless unset-cursor
2054         (goto-char (point-min))
2055         (if (not (wl-summary-cursor-down t))
2056             (progn
2057               (goto-char (point-max))
2058               (forward-line -1))
2059           (if (and wl-summary-highlight
2060                    (not (get-text-property (point) 'face)))
2061               (save-excursion
2062                 (forward-line (- 0
2063                                  (or
2064                                   wl-summary-partial-highlight-above-lines
2065                                   wl-summary-highlight-partial-threshold)))
2066                 (wl-highlight-summary (point) (point-max))))))
2067       (setq wl-summary-buffer-msgdb (elmo-folder-msgdb folder))
2068       (wl-delete-all-overlays)
2069       (set-buffer-modified-p nil)
2070       (if mes (message "%s" mes)))))
2071
2072 (defun wl-summary-set-score-mark (mark)
2073   (save-excursion
2074     (beginning-of-line)
2075     (let ((inhibit-read-only t)
2076           (buffer-read-only nil)
2077           msg-num
2078           cur-mark)
2079       (setq msg-num (wl-summary-message-number))
2080       (setq cur-mark (wl-summary-temp-mark))
2081       (when (member cur-mark (list " "
2082                                    wl-summary-score-below-mark
2083                                    wl-summary-score-over-mark))
2084         (delete-backward-char 1)
2085         (insert mark)
2086         (if wl-summary-highlight
2087             (wl-highlight-summary-current-line nil nil t))
2088         (set-buffer-modified-p nil)))))
2089
2090 (defun wl-summary-get-score-mark (msg-num)
2091   (let ((score (cdr (assq msg-num wl-summary-scored))))
2092     (if score
2093         (cond ((< score wl-summary-default-score)
2094                "-")
2095               ((> score wl-summary-default-score)
2096                "+")))))
2097
2098 (defun wl-summary-update-modeline ()
2099   (setq wl-summary-buffer-mode-line
2100         (funcall wl-summary-buffer-mode-line-formatter)))
2101
2102 (defun wl-summary-jump-to-msg (&optional number)
2103   (interactive)
2104   (let ((num (or number
2105                  (string-to-int
2106                   (read-from-minibuffer "Jump to Message(No.): ")))))
2107     (setq num (int-to-string num))
2108     (beginning-of-line)
2109     (if (or (and (re-search-forward (concat "\r" num "[^0-9]") nil t)
2110                  (progn (backward-char 1) t))
2111             (re-search-backward (concat "\r" num "[^0-9]") nil t))
2112         (progn (beginning-of-line) t)
2113       nil)))
2114
2115 (defun wl-summary-highlight-msgs (msgs)
2116   (save-excursion
2117     (let ((len (length msgs))
2118           i)
2119       (message "Hilighting...")
2120       (setq i 0)
2121       (while msgs
2122         (if (wl-summary-jump-to-msg (car msgs))
2123             (wl-highlight-summary-current-line))
2124         (setq msgs (cdr msgs))
2125         (when (> len elmo-display-progress-threshold)
2126           (setq i (+ i 1))
2127           (if (or (zerop (% i 5)) (= i len))
2128               (elmo-display-progress
2129                'wl-summary-highlight-msgs "Highlighting..."
2130                (/ (* i 100) len)))))
2131       (message "Highlighting...done"))))
2132
2133 (defun wl-summary-message-number ()
2134   (save-excursion
2135     (beginning-of-line)
2136     (if (or (re-search-forward "\r\\(-?[0-9]+\\)" (point-at-eol) t)
2137             (re-search-forward "^ *\\(-?[0-9]+\\)" (point-at-eol) t))
2138         (string-to-int (wl-match-buffer 1))
2139       nil)))
2140
2141 (defun wl-summary-delete-all-msgs ()
2142   (interactive)
2143   (let ((cur-buf (current-buffer))
2144         (dels (elmo-folder-list-messages wl-summary-buffer-elmo-folder)))
2145     (set-buffer cur-buf)
2146     (if (null dels)
2147         (message "No message to delete.")
2148       (if (y-or-n-p (format "%s has %d message(s).  Delete all? "
2149                             (wl-summary-buffer-folder-name)
2150                             (length dels)))
2151           (progn
2152             (message "Deleting...")
2153             (elmo-folder-delete-messages
2154              wl-summary-buffer-elmo-folder dels)
2155             (elmo-msgdb-delete-msgs (wl-summary-buffer-msgdb)
2156                                     dels)
2157 ;;;         (elmo-msgdb-save (wl-summary-buffer-folder-name) nil)
2158             (wl-summary-set-message-modified)
2159             (wl-summary-set-mark-modified)
2160             (wl-folder-set-folder-updated (wl-summary-buffer-folder-name)
2161                                           (list 0 0 0))
2162 ;;; for thread.
2163 ;;;         (setq wl-thread-top-entity '(nil t nil nil))
2164             (setq wl-summary-buffer-unread-count 0)
2165             (setq wl-summary-buffer-new-count    0)
2166             (wl-summary-update-modeline)
2167             (set-buffer cur-buf)
2168             (let ((inhibit-read-only t)
2169                   (buffer-read-only nil))
2170               (erase-buffer))
2171 ;;;         (if wl-summary-cache-use (wl-summary-save-view-cache))
2172             (message "Deleting...done")
2173             t)
2174         nil))))
2175
2176 (defun wl-summary-toggle-thread (&optional arg)
2177   "Toggle thread status (T)hread and (S)equential.
2178 If ARG, without confirm."
2179   (interactive "P")
2180   (when (or arg
2181             (y-or-n-p (format "Toggle threading? (y=%s): "
2182                               (if (eq wl-summary-buffer-view 'thread)
2183                                   "\"off\"" "\"on\""))))
2184     (if (eq wl-summary-buffer-view 'thread)
2185         (setq wl-summary-buffer-view 'sequence)
2186       (setq wl-summary-buffer-view 'thread))
2187     (wl-summary-update-modeline)
2188     (force-mode-line-update)
2189     (wl-summary-rescan)))
2190
2191 (defun wl-summary-load-file-object (filename)
2192   "Load lisp object from dir."
2193   (save-excursion
2194     (let ((tmp-buffer (get-buffer-create " *wl-summary-load-file-object*"))
2195           insert-file-contents-pre-hook   ; To avoid autoconv-xmas...
2196           insert-file-contents-post-hook
2197           ret-val)
2198       (if (not (file-readable-p filename))
2199           ()
2200         (set-buffer tmp-buffer)
2201         (as-binary-input-file (insert-file-contents filename))
2202         (setq ret-val
2203               (condition-case nil
2204                   (read (current-buffer))
2205                 (error (error "Reading failed")))))
2206       (kill-buffer tmp-buffer)
2207       ret-val)))
2208
2209 (defun wl-summary-goto-folder (&optional arg)
2210   (interactive "P")
2211   (wl-summary-goto-folder-subr nil nil nil nil t nil arg))
2212
2213 (defun wl-summary-goto-folder-sticky ()
2214   (interactive)
2215   (wl-summary-goto-folder-subr nil nil nil t t))
2216
2217 (defun wl-summary-goto-last-visited-folder ()
2218   (interactive)
2219   (let ((entity
2220          (wl-folder-search-entity-by-name wl-summary-last-visited-folder
2221                                           wl-folder-entity
2222                                           'folder)))
2223     (if entity (wl-folder-set-current-entity-id
2224                 (wl-folder-get-entity-id entity))))
2225   (wl-summary-goto-folder-subr wl-summary-last-visited-folder nil nil nil t))
2226
2227 (defun wl-summary-sticky-p (&optional folder)
2228   (if folder
2229       (get-buffer (wl-summary-sticky-buffer-name
2230                    (elmo-folder-name-internal folder)))
2231     (not (string= wl-summary-buffer-name (buffer-name)))))
2232
2233 (defun wl-summary-always-sticky-folder-p (folder)
2234   (or (eq t wl-summary-always-sticky-folder-list)
2235       (wl-string-match-member
2236        (elmo-folder-name-internal folder)
2237        wl-summary-always-sticky-folder-list)))
2238
2239 (defun wl-summary-stick (&optional force)
2240   "Make current summary buffer sticky."
2241   (interactive "P")
2242   (if (wl-summary-sticky-p)
2243       (message "Current summary buffer is already sticky.")
2244     (when (or force (y-or-n-p "Stick current summary buffer? "))
2245       (wl-summary-toggle-disp-msg 'off)
2246       (wl-summary-switch-to-clone-buffer
2247        (wl-summary-sticky-buffer-name
2248         (wl-summary-buffer-folder-name)))
2249 ;;; ???hang up
2250 ;;;   (rename-buffer (wl-summary-sticky-buffer-name
2251 ;;;                   (wl-summary-buffer-folder-name))))
2252       (message "Folder `%s' is now sticky." (wl-summary-buffer-folder-name)))))
2253
2254 (defun wl-summary-switch-to-clone-buffer (buffer-name)
2255   (let ((cur-buf (current-buffer))
2256         (msg (wl-summary-message-number))
2257         (buf (get-buffer-create buffer-name))
2258         (folder wl-summary-buffer-elmo-folder)
2259         (copy-variables
2260          (append '(wl-summary-buffer-view
2261                    wl-summary-buffer-refile-list
2262                    wl-summary-buffer-delete-list
2263                    wl-summary-buffer-copy-list
2264                    wl-summary-buffer-target-mark-list
2265                    wl-summary-buffer-elmo-folder
2266                    wl-summary-buffer-number-column
2267                    wl-summary-buffer-temp-mark-column
2268                    wl-summary-buffer-persistent-mark-column
2269                    wl-summary-buffer-message-modified
2270                    wl-summary-buffer-mark-modified
2271                    wl-summary-buffer-thread-modified
2272                    wl-summary-buffer-number-list
2273                    wl-summary-buffer-msgdb
2274                    wl-summary-buffer-folder-name
2275                    wl-summary-buffer-line-formatter)
2276                  (and (eq wl-summary-buffer-view 'thread)
2277                       '(wl-thread-entity-hashtb
2278                         wl-thread-entities
2279                         wl-thread-entity-list))
2280                  (and wl-use-scoring
2281                       '(wl-summary-scored
2282                         wl-summary-default-score
2283                         wl-summary-important-above
2284                         wl-summary-target-above
2285                         wl-summary-mark-below
2286                         wl-summary-expunge-below))
2287                  (and (featurep 'wl-score)
2288                       '(wl-current-score-file
2289                         wl-score-alist)))))
2290     (set-buffer buf)
2291     (wl-summary-mode)
2292     (wl-summary-buffer-set-folder folder)
2293     (let ((buffer-read-only nil))
2294       (insert-buffer cur-buf))
2295     (set-buffer-modified-p nil)
2296     (while copy-variables
2297       (set (car copy-variables)
2298            (save-excursion
2299              (set-buffer cur-buf)
2300              (symbol-value (car copy-variables))))
2301       (setq copy-variables (cdr copy-variables)))
2302     (switch-to-buffer buf)
2303     (kill-buffer cur-buf)
2304     (wl-summary-count-unread)
2305     (wl-summary-update-modeline)
2306     (if msg
2307         (if (eq wl-summary-buffer-view 'thread)
2308             (wl-thread-jump-to-msg msg)
2309           (wl-summary-jump-to-msg msg))
2310       (goto-char (point-max))
2311       (beginning-of-line))))
2312
2313 (defun wl-summary-get-buffer (folder)
2314   (or (and folder
2315            (get-buffer (wl-summary-sticky-buffer-name folder)))
2316       (get-buffer wl-summary-buffer-name)))
2317
2318 (defun wl-summary-get-buffer-create (name &optional force-sticky)
2319   (if force-sticky
2320       (get-buffer-create
2321        (wl-summary-sticky-buffer-name name))
2322     (or (get-buffer (wl-summary-sticky-buffer-name name))
2323         (get-buffer-create wl-summary-buffer-name))))
2324
2325 (defun wl-summary-make-number-list ()
2326   (setq wl-summary-buffer-number-list
2327         (mapcar
2328          (lambda (x) (elmo-msgdb-overview-entity-get-number x))
2329          (elmo-msgdb-get-overview (wl-summary-buffer-msgdb)))))
2330
2331 (defun wl-summary-auto-select-msg-p (unread-msg)
2332   (and unread-msg
2333        (not (string=
2334              (elmo-msgdb-get-mark
2335               (wl-summary-buffer-msgdb)
2336               unread-msg)
2337              wl-summary-important-mark))))
2338
2339 (defsubst wl-summary-open-folder (folder)
2340   ;; Select folder
2341   (let ((elmo-mime-charset wl-summary-buffer-mime-charset))
2342     (unwind-protect
2343         (elmo-folder-open folder 'load-msgdb)
2344       ;; For compatibility
2345       (setq wl-summary-buffer-msgdb (elmo-folder-msgdb folder))
2346       (setq wl-summary-buffer-folder-name (elmo-folder-name-internal
2347                                            folder)))))
2348
2349 (defun wl-summary-goto-folder-subr (&optional name scan-type other-window
2350                                               sticky interactive scoring
2351                                               force-exit)
2352   "Display target folder on summary."
2353   (interactive)
2354   (let* ((keep-cursor (memq this-command
2355                             wl-summary-keep-cursor-command))
2356          (name (or name (wl-summary-read-folder wl-default-folder)))
2357          (cur-fld wl-summary-buffer-elmo-folder)
2358          folder buf mes hilit reuse-buf
2359          retval entity)
2360     (if (string= name "")
2361         (setq name wl-default-folder))
2362     (setq folder (wl-folder-get-elmo-folder name))
2363     (when (and (not (string=
2364                      (and cur-fld (elmo-folder-name-internal cur-fld))
2365                      (elmo-folder-name-internal folder))) ; folder is moved.
2366                (eq major-mode 'wl-summary-mode)) ; called in summary.
2367       (setq wl-summary-last-visited-folder (wl-summary-buffer-folder-name))
2368       (run-hooks 'wl-summary-exit-pre-hook)
2369       (if (or force-exit (not (wl-summary-sticky-p)))
2370           (wl-summary-cleanup-temp-marks (wl-summary-sticky-p)))
2371       (wl-summary-save-view)
2372       (elmo-folder-commit wl-summary-buffer-elmo-folder)
2373       (if (and (wl-summary-sticky-p) force-exit)
2374           (kill-buffer (current-buffer))))
2375     (setq buf (wl-summary-get-buffer-create (elmo-folder-name-internal folder)
2376                                             sticky))
2377     (setq reuse-buf
2378           (save-excursion
2379             (set-buffer buf)
2380             (string= (elmo-folder-name-internal folder)
2381                      (wl-summary-buffer-folder-name))))
2382     (unwind-protect
2383         (if reuse-buf
2384             (if interactive
2385                 (switch-to-buffer buf)
2386               (set-buffer buf))
2387           (if other-window
2388               (delete-other-windows))
2389           (set-buffer buf)
2390           (unless (eq major-mode 'wl-summary-mode)
2391             (wl-summary-mode))
2392           (wl-summary-buffer-set-folder folder)
2393           (setq wl-summary-buffer-disp-msg nil)
2394           (setq wl-summary-buffer-last-displayed-msg nil)
2395           (setq wl-summary-buffer-current-msg nil)
2396           (let ((case-fold-search nil)
2397                 (inhibit-read-only t)
2398                 (buffer-read-only nil))
2399             (erase-buffer)
2400             ;; Resume summary view
2401             (if wl-summary-cache-use
2402                 (let* ((dir (elmo-folder-msgdb-path folder))
2403                        (cache (expand-file-name wl-summary-cache-file dir))
2404                        (view (expand-file-name wl-summary-view-file dir)))
2405                   (when (file-exists-p cache)
2406                     (insert-file-contents-as-binary cache)
2407                     (elmo-set-buffer-multibyte
2408                      default-enable-multibyte-characters)
2409                     (decode-mime-charset-region
2410                      (point-min)(point-max)
2411                      wl-summary-buffer-mime-charset 'LF))
2412                   (when (file-exists-p view)
2413                     (setq wl-summary-buffer-view
2414                           (wl-summary-load-file-object view)))
2415                   (wl-thread-resume-entity folder)
2416                   (wl-summary-open-folder folder))
2417               (setq wl-summary-buffer-view
2418                     (wl-summary-load-file-object
2419                      (expand-file-name wl-summary-view-file
2420                                        (elmo-folder-msgdb-path folder))))
2421               (wl-summary-open-folder folder)
2422               (wl-summary-rescan))
2423             (wl-summary-count-unread)
2424             (wl-summary-update-modeline)))
2425       (unless (eq wl-summary-buffer-view 'thread)
2426         (wl-summary-make-number-list))
2427       (when (and wl-summary-cache-use
2428                  (or (and wl-summary-check-line-format
2429                           (wl-summary-line-format-changed-p))
2430                      (wl-summary-view-old-p)))
2431         (wl-summary-rescan))
2432       (wl-summary-toggle-disp-msg (if wl-summary-buffer-disp-msg 'on 'off))
2433       (unless (and reuse-buf keep-cursor)
2434         ;(setq hilit wl-summary-highlight)
2435         (unwind-protect
2436             (let ((wl-summary-highlight (if reuse-buf wl-summary-highlight))
2437                   (wl-use-scoring
2438                    (if (or scoring interactive) wl-use-scoring)))
2439               (if (and (not scan-type)
2440                        interactive
2441                        (not wl-ask-range))
2442                   (setq scan-type (wl-summary-get-sync-range folder)))
2443               (cond
2444                ((eq scan-type nil)
2445                 (wl-summary-sync 'unset-cursor))
2446                ((eq scan-type 'all)
2447                 (wl-summary-sync 'unset-cursor "all"))
2448                ((eq scan-type 'no-sync))
2449                ((or (eq scan-type 'force-update)
2450                     (eq scan-type 'update))
2451                 (setq mes (wl-summary-sync-force-update
2452                            'unset-cursor 'no-check)))))
2453           (if interactive
2454               (switch-to-buffer buf)
2455             (set-buffer buf))
2456           ;; stick always-sticky-folder
2457           (when (wl-summary-always-sticky-folder-p folder)
2458             (or (wl-summary-sticky-p) (wl-summary-stick t)))
2459           (run-hooks 'wl-summary-prepared-pre-hook)
2460           (set-buffer-modified-p nil)
2461           (goto-char (point-min))
2462           (if (wl-summary-cursor-down t)
2463               (let ((unreadp (wl-summary-next-message
2464                               (wl-summary-message-number)
2465                               'down t)))
2466                 (cond ((and wl-auto-select-first
2467                             (wl-summary-auto-select-msg-p unreadp))
2468                        ;; wl-auto-select-first is non-nil and
2469                        ;; unreadp is non-nil but not important
2470                        (setq retval 'disp-msg))
2471                       ((and wl-auto-prefetch-first
2472                             (wl-summary-auto-select-msg-p unreadp))
2473                        ;; wl-auto-select-first is non-nil and
2474                        ;; unreadp is non-nil but not important
2475                        (setq retval 'prefetch-msg))
2476                       ((not (wl-summary-auto-select-msg-p unreadp))
2477                        ;; unreadp is nil or important
2478                        (setq retval 'more-next))))
2479             (goto-char (point-max))
2480             (if (elmo-folder-plugged-p folder)
2481                 (forward-line -1)
2482               (wl-summary-prev))
2483             (setq retval 'more-next))
2484           ;(setq wl-summary-highlight hilit)
2485           (if (and wl-summary-highlight
2486                    (not wl-summary-lazy-highlight)
2487                    (not reuse-buf))
2488               (if (and wl-summary-highlight-partial-threshold
2489                        (> (count-lines (point-min) (point-max))
2490                           wl-summary-highlight-partial-threshold))
2491                   (save-excursion
2492                     (forward-line (-
2493                                    0
2494                                    (or
2495                                     wl-summary-partial-highlight-above-lines
2496                                     wl-summary-highlight-partial-threshold)))
2497                     (wl-highlight-summary (point) (point-max)))
2498                 (wl-highlight-summary (point-min) (point-max))))
2499           (if (eq retval 'disp-msg)
2500               (wl-summary-redisplay))
2501           (if (eq retval 'prefetch-msg)
2502               (wl-message-buffer-prefetch
2503                folder
2504                (wl-summary-message-number)
2505                wl-message-buffer-prefetch-depth
2506                (current-buffer)
2507                wl-summary-buffer-mime-charset))
2508           (if mes (message "%s" mes))
2509           (if (and interactive wl-summary-recenter)
2510               (recenter (/ (- (window-height) 2) 2))))))
2511     ;; set current entity-id
2512     (if (and (not folder)
2513              (setq entity
2514                    (wl-folder-search-entity-by-name (elmo-folder-name-internal
2515                                                      folder)
2516                                                     wl-folder-entity
2517                                                     'folder)))
2518         ;; entity-id is unknown.
2519         (wl-folder-set-current-entity-id
2520          (wl-folder-get-entity-id entity)))
2521     (when (and wl-summary-lazy-highlight
2522                wl-on-xemacs)
2523       (sit-for 0))
2524     (unwind-protect
2525         (run-hooks 'wl-summary-prepared-hook)
2526       (set-buffer-modified-p nil))
2527     retval))
2528
2529 (defun wl-summary-goto-previous-message-beginning ()
2530   (end-of-line)
2531   (re-search-backward "\r\\(-?[0-9]+\\)" nil t)
2532   (beginning-of-line))
2533
2534 (defun wl-summary-goto-top-of-current-thread ()
2535   (wl-summary-jump-to-msg
2536    (wl-thread-entity-get-number
2537     (wl-thread-entity-get-top-entity (wl-thread-get-entity
2538                                       (wl-summary-message-number))))))
2539
2540 (defun wl-summary-goto-bottom-of-sub-thread (&optional depth)
2541   (interactive)
2542   (let ((depth (or depth
2543                    (wl-thread-get-depth-of-current-line))))
2544     (forward-line 1)
2545     (while (and (not (eobp))
2546                 (>= (wl-thread-get-depth-of-current-line)
2547                     depth))
2548       (forward-line 1))
2549     (beginning-of-line)))
2550
2551 (defun wl-summary-insert-line (line)
2552   "Insert LINE in the Summary."
2553   (if wl-use-highlight-mouse-line
2554       ;; remove 'mouse-face of current line.
2555       (put-text-property
2556        (save-excursion (beginning-of-line)(point))
2557        (save-excursion (end-of-line)(point))
2558        'mouse-face nil))
2559   (insert line "\n")
2560   (if wl-use-highlight-mouse-line
2561       ;; remove 'mouse-face of current line.
2562       (put-text-property
2563        (save-excursion (beginning-of-line)(point))
2564        (save-excursion (end-of-line)(point))
2565        'mouse-face nil))
2566   (ignore-errors
2567     (run-hooks 'wl-summary-line-inserted-hook)))
2568
2569 (defun wl-summary-insert-sequential (entity msgdb &rest args)
2570   (let ((inhibit-read-only t)
2571         buffer-read-only)
2572     (goto-char (point-max))
2573     (wl-summary-insert-line
2574      (wl-summary-create-line entity nil nil
2575                              (elmo-msgdb-get-mark
2576                               msgdb
2577                               (elmo-msgdb-overview-entity-get-number
2578                                entity))))))
2579
2580 (defun wl-summary-default-subject-filter (subject)
2581   (let ((case-fold-search t))
2582     (setq subject (elmo-replace-in-string subject "[ \t]*\\(re\\|was\\)[:>]" ""))
2583     (setq subject (elmo-replace-in-string subject "[ \t]" ""))
2584     (elmo-replace-in-string subject "^\\[.*\\]" "")))
2585
2586 (defun wl-summary-subject-equal (subject1 subject2)
2587   (string= (funcall wl-summary-subject-filter-function subject1)
2588            (funcall wl-summary-subject-filter-function subject2)))
2589
2590 (defmacro wl-summary-put-alike (alike)
2591   (` (elmo-set-hash-val (format "#%d" (wl-count-lines))
2592                         (, alike)
2593                         wl-summary-alike-hashtb)))
2594
2595 (defmacro wl-summary-get-alike ()
2596   (` (elmo-get-hash-val (format "#%d" (wl-count-lines))
2597                         wl-summary-alike-hashtb)))
2598
2599 (defun wl-summary-insert-headers (overview func mime-decode)
2600   (message "Creating subject cache...")
2601   (let (ov this last alike)
2602     (buffer-disable-undo (current-buffer))
2603     (make-local-variable 'wl-summary-alike-hashtb)
2604     (setq wl-summary-alike-hashtb (elmo-make-hash (* (length overview) 2)))
2605     (when mime-decode
2606       (elmo-set-buffer-multibyte default-enable-multibyte-characters))
2607     (while (setq ov (pop overview))
2608       (setq this (funcall func ov))
2609       (and this (setq this (std11-unfold-string this)))
2610       (if (equal last this)
2611           (wl-append alike (list ov))
2612         (when last
2613           (wl-summary-put-alike alike)
2614           (insert last ?\n))
2615         (setq alike (list ov)
2616               last this)))
2617     (when last
2618       (wl-summary-put-alike alike)
2619       (insert last ?\n))
2620     (when mime-decode
2621       (decode-mime-charset-region (point-min) (point-max)
2622                                   elmo-mime-charset)
2623       (when (eq mime-decode 'mime)
2624         (eword-decode-region (point-min) (point-max))))
2625     (message "Creating subject cache...done")
2626     (run-hooks 'wl-summary-insert-headers-hook)))
2627
2628 (defun wl-summary-search-by-subject (entity overview)
2629   (let ((summary-buf (current-buffer))
2630         (buf (get-buffer-create wl-summary-search-buf-name))
2631         (folder-name (wl-summary-buffer-folder-name))
2632         match founds found-entity)
2633     (with-current-buffer buf
2634       (let ((case-fold-search t))
2635         (when (or (not (string= wl-summary-search-buf-folder-name folder-name))
2636                   (zerop (buffer-size)))
2637           (setq wl-summary-search-buf-folder-name folder-name)
2638           (wl-summary-insert-headers
2639            overview
2640            (function
2641             (lambda (x)
2642               (funcall wl-summary-subject-filter-function
2643                (elmo-msgdb-overview-entity-get-subject-no-decode x))))
2644            t))
2645         (setq match (funcall wl-summary-subject-filter-function
2646                              (elmo-msgdb-overview-entity-get-subject entity)))
2647         (if (string= match "")
2648             (setq match "\n"))
2649         (goto-char (point-min))
2650         (while (and (not founds)
2651                     (not (= (point) (point-max)))
2652                     (search-forward match nil t))
2653           ;; check exactly match
2654           (when (and (eolp)
2655                      (= (point-at-bol)
2656                         (match-beginning 0)))
2657             (setq found-entity (wl-summary-get-alike))
2658             (if (and found-entity
2659                      ;; Is founded entity myself or children?
2660                      (not (string=
2661                            (elmo-msgdb-overview-entity-get-id entity)
2662                            (elmo-msgdb-overview-entity-get-id
2663                             (car found-entity))))
2664                      (with-current-buffer summary-buf
2665                        (not (wl-thread-descendant-p
2666                              (elmo-msgdb-overview-entity-get-number entity)
2667                              (elmo-msgdb-overview-entity-get-number
2668                               (car found-entity))))))
2669                 ;; return matching entity
2670                 (setq founds found-entity))))
2671         (if founds
2672             (car founds))))))
2673
2674 (defun wl-summary-insert-thread-entity (entity msgdb update
2675                                                &optional force-insert)
2676   (let* ((overview (elmo-msgdb-get-overview msgdb))
2677          this-id
2678          parent-entity
2679          parent-number
2680          (case-fold-search t)
2681          cur number overview2 cur-entity linked retval delayed-entity
2682          update-list entity-stack)
2683     (while entity
2684       (setq this-id (elmo-msgdb-overview-entity-get-id entity)
2685             parent-entity
2686             (elmo-msgdb-get-parent-entity entity msgdb)
2687             parent-number (elmo-msgdb-overview-entity-get-number
2688                            parent-entity))
2689       (setq number (elmo-msgdb-overview-entity-get-number entity))
2690       ;; If thread loop detected, set parent as nil.
2691       (setq cur entity)
2692       (while cur
2693         (if (eq number (elmo-msgdb-overview-entity-get-number
2694                         (setq cur
2695                               (elmo-msgdb-get-parent-entity cur msgdb))))
2696             (setq parent-number nil
2697                   cur nil)))
2698       (if (and parent-number
2699                (not (wl-thread-get-entity parent-number))
2700                (not force-insert))
2701           ;; parent exists in overview, but not in wl-thread-entities
2702           (progn
2703             (wl-append wl-summary-delayed-update
2704                        (list (cons parent-number entity)))
2705             (setq entity nil)) ;; exit loop
2706         ;; Search parent by subject.
2707         (when (and (null parent-number)
2708                    wl-summary-search-parent-by-subject-regexp
2709                    (string-match
2710                     wl-summary-search-parent-by-subject-regexp
2711                     (elmo-msgdb-overview-entity-get-subject entity)))
2712           (let ((found (wl-summary-search-by-subject entity overview)))
2713             (when (and found
2714                        (not (member found wl-summary-delayed-update)))
2715               (setq parent-entity found)
2716               (setq parent-number
2717                     (elmo-msgdb-overview-entity-get-number parent-entity))
2718               (setq linked t))))
2719         ;; If subject is change, divide thread.
2720         (if (and parent-number
2721                  wl-summary-divide-thread-when-subject-changed
2722                  (not (wl-summary-subject-equal
2723                        (or (elmo-msgdb-overview-entity-get-subject
2724                             entity) "")
2725                        (or (elmo-msgdb-overview-entity-get-subject
2726                             parent-entity) ""))))
2727             (setq parent-number nil))
2728         (setq retval
2729               (wl-thread-insert-message entity
2730                                         number parent-number update linked))
2731         (and retval
2732              (wl-append update-list (list retval)))
2733         (setq entity nil) ; exit loop
2734         (while (setq delayed-entity (assq number wl-summary-delayed-update))
2735           (setq wl-summary-delayed-update
2736                 (delq delayed-entity wl-summary-delayed-update))
2737           ;; update delayed message
2738           (wl-append entity-stack (list (cdr delayed-entity)))))
2739       (if (and (not entity)
2740                entity-stack)
2741           (setq entity (pop entity-stack))))
2742     update-list))
2743
2744 (defun wl-summary-update-thread (entity
2745                                  thr-entity
2746                                  parent-entity)
2747   (let* ((this-id (elmo-msgdb-overview-entity-get-id entity))
2748          (overview-entity entity)
2749          (parent-id (elmo-msgdb-overview-entity-get-id parent-entity))
2750          (number (elmo-msgdb-overview-entity-get-number entity))
2751          (parent-number (elmo-msgdb-overview-entity-get-number parent-entity)))
2752     (cond
2753      ((or (not parent-id)
2754           (string= this-id parent-id))
2755       (goto-char (point-max))
2756       (beginning-of-line))
2757      ;; parent already exists in buffer.
2758      ((wl-summary-jump-to-msg parent-number)
2759       (wl-thread-goto-bottom-of-sub-thread)))
2760     (let ((inhibit-read-only t)
2761           (buffer-read-only nil))
2762       (wl-summary-insert-line
2763        (wl-summary-create-line
2764         entity
2765         parent-entity
2766         nil
2767         (elmo-msgdb-get-mark (wl-summary-buffer-msgdb) number)
2768         (wl-thread-maybe-get-children-num number)
2769         (wl-thread-make-indent-string thr-entity)
2770         (wl-thread-entity-get-linked thr-entity))))))
2771
2772 (defun wl-summary-mark-as-unread (&optional number
2773                                             no-server-update
2774                                             no-modeline-update)
2775   (interactive)
2776   (save-excursion
2777     (let* (eol
2778           (inhibit-read-only t)
2779           (buffer-read-only nil)
2780           (folder wl-summary-buffer-elmo-folder)
2781           (msgdb (wl-summary-buffer-msgdb))
2782 ;;;       (number-alist (elmo-msgdb-get-number-alist msgdb))
2783           new-mark visible mark cur-mark)
2784       (if number
2785           (progn
2786             (setq visible (wl-summary-jump-to-msg number))
2787             (unless (setq mark (elmo-msgdb-get-mark msgdb number))
2788               (setq mark " ")))
2789         ;; interactive
2790         (setq visible t))
2791       (when visible
2792         (if (null (wl-summary-message-number))
2793             (message "No message.")
2794           (end-of-line)
2795           (setq eol (point))
2796           (wl-summary-goto-previous-message-beginning)))
2797       (if (or (and (not visible)
2798                    ;; already exists in msgdb.
2799                    (elmo-msgdb-overview-get-entity number msgdb))
2800               (progn
2801                 ;; visible.
2802                 (setq cur-mark (wl-summary-persistent-mark))
2803                 (or (string= cur-mark " ")
2804                     (string= cur-mark wl-summary-read-uncached-mark))))
2805           (progn
2806             (setq number (or number (wl-summary-message-number)))
2807             (setq mark (or mark cur-mark))
2808             (save-match-data
2809               (setq new-mark (if (string= mark
2810                                           wl-summary-read-uncached-mark)
2811                                  wl-summary-unread-uncached-mark
2812                                (if (elmo-message-use-cache-p folder number)
2813                                    wl-summary-unread-mark
2814                                  wl-summary-unread-uncached-mark))))
2815             ;; server side mark
2816             (unless no-server-update
2817               (save-match-data
2818                 (unless (elmo-folder-unmark-read folder (list number))
2819                   (error "Setting mark failed"))))
2820             (when visible
2821               (delete-backward-char 1)
2822               (insert new-mark))
2823             (elmo-msgdb-set-mark msgdb number new-mark)
2824             (unless no-modeline-update
2825               (setq wl-summary-buffer-unread-count
2826                     (+ 1 wl-summary-buffer-unread-count))
2827               (wl-summary-update-modeline)
2828               (wl-folder-update-unread
2829                (wl-summary-buffer-folder-name)
2830                (+ wl-summary-buffer-unread-count
2831                   wl-summary-buffer-new-count)))
2832             (wl-summary-set-mark-modified)
2833             (if (and visible wl-summary-highlight)
2834                 (wl-highlight-summary-current-line))))))
2835   (set-buffer-modified-p nil))
2836
2837 (defun wl-summary-delete (&optional number)
2838   "Mark a delete mark 'D'.
2839 If optional argument NUMBER is specified, mark message specified by NUMBER."
2840   (interactive)
2841   (let* ((buffer-num (wl-summary-message-number))
2842          (msg-num (or number buffer-num))
2843          mark)
2844     (catch 'done
2845       (when (null msg-num)
2846         (if (interactive-p)
2847             (message "No message."))
2848         (throw 'done nil))
2849       (when (setq mark (wl-summary-get-mark msg-num))
2850         (when (wl-summary-reserve-temp-mark-p mark)
2851           (if (interactive-p)
2852               (error "Already marked as `%s'" mark))
2853           (throw 'done nil))
2854         (wl-summary-unmark msg-num))
2855       (if (or (interactive-p)
2856               (eq number buffer-num))
2857           (wl-summary-mark-line "D"))
2858       (setq wl-summary-buffer-delete-list
2859             (cons msg-num wl-summary-buffer-delete-list))
2860       (if (interactive-p)
2861           (if (eq wl-summary-move-direction-downward nil)
2862               (wl-summary-prev)
2863             (wl-summary-next)))
2864       msg-num)))
2865
2866 (defun wl-summary-remove-destination ()
2867   (save-excursion
2868     (let ((inhibit-read-only t)
2869           (buffer-read-only nil)
2870           (buf (current-buffer))
2871           sol eol rs re)
2872       (beginning-of-line)
2873       (setq sol (point))
2874       (search-forward "\r")
2875       (forward-char -1)
2876       (setq eol (point))
2877       (setq rs (next-single-property-change sol 'wl-summary-destination
2878                                             buf eol))
2879       (setq re (next-single-property-change rs 'wl-summary-destination
2880                                             buf eol))
2881       (put-text-property rs re 'wl-summary-destination nil)
2882       (put-text-property rs re 'invisible nil)
2883       (goto-char re)
2884       (delete-char (- eol re)))))
2885
2886 (defun wl-summary-check-mark (msg mark)
2887   (let ((check-func (cond ((string= mark "o")
2888                            'wl-summary-msg-marked-as-refiled)
2889                           ((string= mark "O")
2890                            'wl-summary-msg-marked-as-copied)
2891                           ((string= mark "D")
2892                            'wl-summary-msg-marked-as-deleted)
2893                           ((string= mark "*")
2894                            'wl-summary-msg-marked-as-target))))
2895     (if check-func
2896         (funcall check-func msg))))
2897
2898 (defun wl-summary-mark-collect (mark &optional begin end)
2899   (save-excursion
2900     (save-restriction
2901       (let (msglist)
2902         (narrow-to-region (or begin (point-min))
2903                           (or end (point-max)))
2904         (goto-char (point-min))
2905         ;; for thread...
2906         (if (eq wl-summary-buffer-view 'thread)
2907             (progn
2908               (while (not (eobp))
2909                 (let* ((number (wl-summary-message-number))
2910                        (entity (wl-thread-get-entity number))
2911                        result)
2912                   ;; opened...only myself is checked.
2913                   (if (wl-summary-check-mark number mark)
2914                       (wl-append msglist (list number)))
2915                   (unless (wl-thread-entity-get-opened entity)
2916                     ;; closed...children is also checked.
2917                     (if (setq result (wl-thread-get-children-msgs-with-mark
2918                                       number
2919                                       mark))
2920                         (wl-append msglist result)))
2921                   (forward-line 1)))
2922               (elmo-uniq-list msglist))
2923           (while (not (eobp))
2924             (when (string= (wl-summary-temp-mark) mark)
2925               (setq msglist (cons (wl-summary-message-number) msglist)))
2926             (forward-line 1)))))))
2927
2928 (defun wl-summary-exec ()
2929   (interactive)
2930   (wl-summary-exec-subr (mapcar 'car wl-summary-buffer-refile-list)
2931                         (reverse wl-summary-buffer-delete-list)
2932                         (mapcar 'car wl-summary-buffer-copy-list)))
2933
2934 (defun wl-summary-exec-region (beg end)
2935   (interactive "r")
2936   (message "Collecting marks ...")
2937   (save-excursion
2938     (goto-char beg)
2939     (beginning-of-line)
2940     (setq beg (point))
2941     (goto-char (1- end))
2942     (forward-line)
2943     (setq end (point))
2944     (wl-summary-exec-subr (wl-summary-mark-collect "o" beg end)
2945                           (wl-summary-mark-collect "D" beg end)
2946                           (wl-summary-mark-collect "O" beg end))))
2947
2948 (defun wl-summary-exec-subr (moves dels copies)
2949   (if (not (or moves dels copies))
2950       (message "No marks")
2951     (save-excursion
2952       (let ((del-fld (wl-summary-get-delete-folder
2953                       (wl-summary-buffer-folder-name)))
2954             (start (point))
2955             (unread-marks (list wl-summary-unread-cached-mark
2956                                 wl-summary-unread-uncached-mark
2957                                 wl-summary-new-mark))
2958             (refiles (append moves dels))
2959             (refile-failures 0)
2960             (copy-failures 0)
2961             (copy-len (length copies))
2962             refile-len
2963             dst-msgs                    ; loop counter
2964             result)
2965         (message "Executing ...")
2966         (while dels
2967           (when (not (assq (car dels) wl-summary-buffer-refile-list))
2968             (wl-append wl-summary-buffer-refile-list
2969                        (list (cons (car dels) del-fld)))
2970             (setq wl-summary-buffer-delete-list
2971                   (delete (car dels) wl-summary-buffer-delete-list)))
2972           (setq dels (cdr dels)))
2973         ;; begin refile...
2974         (setq refile-len (length refiles))
2975         (setq dst-msgs
2976               (wl-inverse-alist refiles wl-summary-buffer-refile-list))
2977         (goto-char start)               ; avoid moving cursor to
2978                                         ; the bottom line.
2979         (when (> refile-len elmo-display-progress-threshold)
2980           (elmo-progress-set 'elmo-folder-move-messages
2981                              refile-len "Moving messages..."))
2982         (while dst-msgs
2983           (setq result nil)
2984           (condition-case nil
2985               (setq result (elmo-folder-move-messages
2986                             wl-summary-buffer-elmo-folder
2987                             (cdr (car dst-msgs))
2988                             (if (eq 'null (car (car dst-msgs)))
2989                                 'null
2990                               (wl-folder-get-elmo-folder
2991                                (car (car dst-msgs))))
2992                             (wl-summary-buffer-msgdb)
2993                             (not (null (cdr dst-msgs)))
2994                             nil ; no-delete
2995                             nil ; same-number
2996                             unread-marks
2997                             t))
2998             (error nil))
2999           (if result                    ; succeeded.
3000               (progn
3001                 ;; update buffer.
3002                 (wl-summary-delete-messages-on-buffer (cdr (car dst-msgs)))
3003                 ;; update refile-alist.
3004                 (setq wl-summary-buffer-refile-list
3005                       (wl-delete-associations (cdr (car dst-msgs))
3006                                               wl-summary-buffer-refile-list)))
3007             (setq refile-failures
3008                   (+ refile-failures (length (cdr (car dst-msgs))))))
3009           (setq dst-msgs (cdr dst-msgs)))
3010         (elmo-progress-clear 'elmo-folder-move-messages)
3011         ;; end refile
3012         ;; begin cOpy...
3013         (setq dst-msgs (wl-inverse-alist copies wl-summary-buffer-copy-list))
3014         (when (> copy-len elmo-display-progress-threshold)
3015           (elmo-progress-set 'elmo-folder-move-messages
3016                              copy-len "Copying messages..."))
3017         (while dst-msgs
3018           (setq result nil)
3019           (condition-case nil
3020               (setq result (elmo-folder-move-messages
3021                             wl-summary-buffer-elmo-folder
3022                             (cdr (car dst-msgs))
3023                             (wl-folder-get-elmo-folder
3024                              (car (car dst-msgs)))
3025                             (wl-summary-buffer-msgdb)
3026                             (not (null (cdr dst-msgs)))
3027                             t ; t is no-delete (copy)
3028                             nil ; same number
3029                             unread-marks
3030                             t))
3031             (error nil))
3032           (if result                    ; succeeded.
3033               (progn
3034                 ;; update buffer.
3035                 (wl-summary-delete-copy-marks-on-buffer (cdr (car dst-msgs)))
3036                 ;; update copy-alist
3037                 (setq wl-summary-buffer-copy-list
3038                       (wl-delete-associations (cdr (car dst-msgs))
3039                                               wl-summary-buffer-copy-list)))
3040             (setq copy-failures
3041                   (+ copy-failures (length (cdr (car dst-msgs))))))
3042           (setq dst-msgs (cdr dst-msgs)))
3043         ;; Hide progress bar.
3044         (elmo-progress-clear 'elmo-folder-move-messages)
3045         ;; end cOpy
3046         (wl-summary-folder-info-update)
3047         (wl-summary-set-message-modified)
3048         (wl-summary-set-mark-modified)
3049         (run-hooks 'wl-summary-exec-hook)
3050         (unless (and wl-message-buffer
3051                      (eq (wl-summary-message-number)
3052                          (with-current-buffer wl-message-buffer
3053                            wl-message-buffer-cur-number)))
3054           (wl-summary-toggle-disp-msg 'off))
3055         (set-buffer-modified-p nil)
3056         (message (concat "Executing ... done"
3057                          (if (> refile-failures 0)
3058                              (format " (%d refiling failed)" refile-failures)
3059                            "")
3060                          (if (> copy-failures 0)
3061                              (format " (%d copying failed)" copy-failures)
3062                            "")
3063                          "."))))))
3064
3065 (defun wl-summary-read-folder (default &optional purpose ignore-error
3066                                 no-create init)
3067   (let ((fld (completing-read
3068               (format "Folder name %s(%s): " (or purpose "")
3069                       default)
3070               (or wl-folder-completion-function
3071                   (if (memq 'read-folder wl-use-folder-petname)
3072                       (wl-folder-get-entity-with-petname)
3073                     wl-folder-entity-hashtb))
3074               nil nil (or init wl-default-spec)
3075               'wl-read-folder-hist)))
3076     (if (or (string= fld wl-default-spec)
3077             (string= fld ""))
3078         (setq fld default))
3079     (setq fld (elmo-string (wl-folder-get-realname fld)))
3080     (if (string-match "\n" fld)
3081         (error "Not supported folder name: %s" fld))
3082     (unless no-create
3083       (if ignore-error
3084           (condition-case nil
3085               (wl-folder-confirm-existence
3086                (wl-folder-get-elmo-folder
3087                 fld))
3088             (error))
3089         (wl-folder-confirm-existence (wl-folder-get-elmo-folder
3090                                       fld))))
3091     fld))
3092
3093 (defun wl-summary-print-destination (msg-num folder)
3094   "Print refile destination on line."
3095   (wl-summary-remove-destination)
3096   (let ((inhibit-read-only t)
3097         (folder (copy-sequence folder))
3098         (buffer-read-only nil)
3099         len rs re c)
3100     (setq len (string-width folder))
3101     (if (< len 1) ()
3102       ;;(end-of-line)
3103       (beginning-of-line)
3104       (search-forward "\r")
3105       (forward-char -1)
3106       (setq re (point))
3107       (setq c 0)
3108       (while (< c len)
3109         (forward-char -1)
3110         (setq c (+ c (char-width (following-char)))))
3111       (and (> c len) (setq folder (concat " " folder)))
3112       (setq rs (point))
3113       (put-text-property rs re 'invisible t)
3114       (put-text-property rs re 'wl-summary-destination t)
3115       (goto-char re)
3116       (wl-highlight-refile-destination-string folder)
3117       (insert folder)
3118       (set-buffer-modified-p nil))))
3119
3120 (defsubst wl-summary-get-mark (number)
3121   "Return a temporal mark of message specified by NUMBER."
3122   (or (and (memq number wl-summary-buffer-delete-list) "D")
3123       (and (assq number wl-summary-buffer-copy-list) "O")
3124       (and (assq number wl-summary-buffer-refile-list) "o")
3125       (and (memq number wl-summary-buffer-target-mark-list) "*")))
3126
3127 (defsubst wl-summary-reserve-temp-mark-p (mark)
3128   "Return t if temporal MARK should be reserved."
3129   (member mark wl-summary-reserve-mark-list))
3130
3131 (defun wl-summary-refile (&optional dst number)
3132   "Put refile mark on current line message.
3133 If optional argument DST is specified, put mark without asking
3134 destination folder.
3135 If optional argument NUMBER is specified, mark message specified by NUMBER.
3136
3137 If folder is read-only, message should be copied.
3138 See `wl-refile-policy-alist' for more details."
3139   (interactive)
3140   (let ((policy (wl-get-assoc-list-value wl-refile-policy-alist
3141                                          (wl-summary-buffer-folder-name))))
3142     (cond ((eq policy 'copy)
3143            (if (interactive-p)
3144                (call-interactively 'wl-summary-copy)
3145              (wl-summary-copy dst number)))
3146           (t
3147            (wl-summary-refile-subr 'refile (interactive-p) dst number)))))
3148
3149 (defun wl-summary-copy (&optional dst number)
3150   "Put copy mark on current line message.
3151 If optional argument DST is specified, put mark without asking
3152 destination folder.
3153 If optional argument NUMBER is specified, mark message specified by NUMBER."
3154   (interactive)
3155   (wl-summary-refile-subr 'copy (interactive-p) dst number))
3156
3157 (defun wl-summary-refile-subr (copy-or-refile interactive &optional dst number)
3158   (let* ((buffer-num (wl-summary-message-number))
3159          (msg-num (or number buffer-num))
3160          (msgid (and msg-num
3161                      (elmo-message-field wl-summary-buffer-elmo-folder
3162                                          msg-num 'message-id)))
3163          (entity (and msg-num
3164                       (elmo-msgdb-overview-get-entity
3165                        msg-num (wl-summary-buffer-msgdb))))
3166          (variable
3167           (intern (format "wl-summary-buffer-%s-list" copy-or-refile)))
3168          folder mark already tmp-folder)
3169     (catch 'done
3170       (when (null entity)
3171         ;; msgdb is empty?
3172         (if interactive
3173             (message "Cannot refile."))
3174         (throw 'done nil))
3175       (when (null msg-num)
3176         (if interactive
3177             (message "No message."))
3178         (throw 'done nil))
3179       (when (setq mark (wl-summary-get-mark msg-num))
3180         (when (wl-summary-reserve-temp-mark-p mark)
3181           (if interactive
3182               (error "Already marked as `%s'" mark))
3183           (throw 'done nil)))
3184       (setq folder (and msg-num
3185                         (or dst (wl-summary-read-folder
3186                                  (or (wl-refile-guess entity) wl-trash-folder)
3187                                  (format "for %s" copy-or-refile)))))
3188       ;; Cache folder hack by okada@opaopa.org
3189       (if (and (eq (elmo-folder-type-internal
3190                     (wl-folder-get-elmo-folder
3191                      (wl-folder-get-realname folder))) 'cache)
3192                (not (string= folder
3193                              (setq tmp-folder
3194                                    (concat "'cache/"
3195                                            (elmo-cache-get-path-subr
3196                                             (elmo-msgid-to-cache msgid)))))))
3197           (progn
3198             (setq folder tmp-folder)
3199             (message "Force refile to %s." folder)))
3200       (if (string= folder (wl-summary-buffer-folder-name))
3201           (error "Same folder"))
3202       (if (or (not (elmo-folder-writable-p (wl-folder-get-elmo-folder folder)))
3203               (string= folder wl-queue-folder)
3204               (string= folder wl-draft-folder))
3205           (error "Don't %s messages to %s" copy-or-refile folder))
3206       ;; learn for refile.
3207       (if (eq copy-or-refile 'refile)
3208           (wl-refile-learn entity folder))
3209       (wl-summary-unmark msg-num)
3210       (set variable (append
3211                      (symbol-value variable)
3212                      (list (cons msg-num folder))))
3213       (when (or interactive
3214                 (eq number buffer-num))
3215         (wl-summary-mark-line (if (eq copy-or-refile 'refile)
3216                                   "o" "O"))
3217         ;; print refile destination
3218         (wl-summary-print-destination msg-num folder))
3219       (if interactive
3220           (if (eq wl-summary-move-direction-downward nil)
3221               (wl-summary-prev)
3222             (wl-summary-next)))
3223       (run-hooks (intern (format "wl-summary-%s-hook" copy-or-refile)))
3224       (setq wl-summary-buffer-prev-refile-destination folder)
3225       msg-num)))
3226
3227 (defun wl-summary-refile-prev-destination ()
3228   "Refile message to previously refiled destination."
3229   (interactive)
3230   (wl-summary-refile wl-summary-buffer-prev-refile-destination
3231                      (wl-summary-message-number))
3232   (if (eq wl-summary-move-direction-downward nil)
3233       (wl-summary-prev)
3234     (wl-summary-next)))
3235
3236 (defun wl-summary-copy-prev-destination ()
3237   "Refile message to previously refiled destination."
3238   (interactive)
3239   (wl-summary-copy wl-summary-buffer-prev-copy-destination
3240                    (wl-summary-message-number))
3241   (if (eq wl-summary-move-direction-downward nil)
3242       (wl-summary-prev)
3243     (wl-summary-next)))
3244
3245 (defsubst wl-summary-no-auto-refile-message-p (msg)
3246   (member (elmo-msgdb-get-mark (wl-summary-buffer-msgdb) msg)
3247           wl-summary-auto-refile-skip-marks))
3248
3249 (defun wl-summary-auto-refile (&optional open-all)
3250   "Set refile mark automatically according to 'wl-refile-guess-by-rule'."
3251   (interactive "P")
3252   (message "Marking...")
3253   (save-excursion
3254     (if (and (eq wl-summary-buffer-view 'thread)
3255              open-all)
3256         (wl-thread-open-all))
3257     (let* ((spec (wl-summary-buffer-folder-name))
3258            checked-dsts
3259            (count 0)
3260            number dst thr-entity)
3261       (goto-line 1)
3262       (while (not (eobp))
3263         (setq number (wl-summary-message-number))
3264         (dolist (number (cons number
3265                               (and (eq wl-summary-buffer-view 'thread)
3266                                    ;; process invisible children.
3267                                    (not (wl-thread-entity-get-opened
3268                                          (setq thr-entity
3269                                                (wl-thread-get-entity number))))
3270                                    (wl-thread-entity-get-descendant
3271                                     thr-entity))))
3272           (when (and (not (wl-summary-no-auto-refile-message-p
3273                            number))
3274                      (setq dst
3275                            (wl-folder-get-realname
3276                             (wl-refile-guess-by-rule
3277                              (elmo-msgdb-overview-get-entity
3278                               number (wl-summary-buffer-msgdb)))))
3279                      (not (equal dst spec))
3280                      (let ((pair (assoc dst checked-dsts))
3281                            ret)
3282                        (if pair
3283                            (cdr pair)
3284                          (setq ret
3285                                (condition-case nil
3286                                    (progn
3287                                      (wl-folder-confirm-existence
3288                                       (wl-folder-get-elmo-folder dst))
3289                                      t)
3290                                  (error)))
3291                          (setq checked-dsts (cons (cons dst ret) checked-dsts))
3292                          ret)))
3293             (if (wl-summary-refile dst number)
3294                 (incf count))
3295             (message "Marking...%d message(s)." count)))
3296         (forward-line))
3297       (if (eq count 0)
3298           (message "No message was marked.")
3299         (message "Marked %d message(s)." count)))))
3300
3301 (defun wl-summary-unmark (&optional number)
3302   "Unmark marks (temporary, refile, copy, delete)of current line.
3303 If optional argument NUMBER is specified, unmark message specified by NUMBER."
3304   (interactive)
3305   (save-excursion
3306     (beginning-of-line)
3307     (let ((inhibit-read-only t)
3308           (buffer-read-only nil)
3309           visible
3310           msg-num
3311           cur-mark
3312           score-mark)
3313       (if number
3314           (setq visible (wl-summary-jump-to-msg number))
3315         (setq visible t))
3316       ;; Delete mark on buffer.
3317       (when visible
3318         (setq cur-mark (wl-summary-temp-mark))
3319         (if (string= cur-mark " ")
3320             ()
3321           (delete-backward-char 1)
3322           (or number
3323               (setq number (wl-summary-message-number)))
3324           (if (setq score-mark (wl-summary-get-score-mark number))
3325               (insert score-mark)
3326             (insert " ")))
3327         (if (or (string= cur-mark "o")
3328                 (string= cur-mark "O"))
3329             (wl-summary-remove-destination))
3330         (if wl-summary-highlight
3331             (wl-highlight-summary-current-line nil nil score-mark))
3332         (set-buffer-modified-p nil))
3333       ;; Remove from temporal mark structure.
3334       (and number
3335            (wl-summary-delete-mark number)))))
3336
3337 (defun wl-summary-msg-marked-as-target (msg)
3338   (if (memq msg wl-summary-buffer-target-mark-list)
3339       t))
3340
3341 (defun wl-summary-msg-marked-as-copied (msg)
3342   (assq msg wl-summary-buffer-copy-list))
3343
3344 (defun wl-summary-msg-marked-as-deleted (msg)
3345   (if (memq msg wl-summary-buffer-delete-list)
3346       t))
3347
3348 (defun wl-summary-msg-marked-as-refiled (msg)
3349   (assq msg wl-summary-buffer-refile-list))
3350
3351 (defun wl-summary-target-mark (&optional number)
3352   "Put target mark '*' on current message.
3353 If optional argument NUMBER is specified, mark message specified by NUMBER."
3354   (interactive)
3355   (let* ((buffer-num (wl-summary-message-number))
3356          (msg-num (or number buffer-num))
3357          mark)
3358     (catch 'done
3359       (when (null msg-num)
3360         (if (interactive-p)
3361             (message "No message."))
3362         (throw 'done nil))
3363       (when (setq mark (wl-summary-get-mark msg-num))
3364         (when (wl-summary-reserve-temp-mark-p mark)
3365           (if (interactive-p)
3366               (error "Already marked as `%s'" mark))
3367           (throw 'done nil))
3368         (wl-summary-unmark msg-num))
3369       (if (or (interactive-p)
3370               (eq number buffer-num))
3371           (wl-summary-mark-line "*"))
3372       (setq wl-summary-buffer-target-mark-list
3373             (cons msg-num wl-summary-buffer-target-mark-list))
3374       (if (interactive-p)
3375           (if (eq wl-summary-move-direction-downward nil)
3376               (wl-summary-prev)
3377             (wl-summary-next)))
3378       msg-num)))
3379
3380
3381 (defun wl-summary-refile-region (beg end)
3382   "Put copy mark on messages in the region specified by BEG and END."
3383   (interactive "r")
3384   (wl-summary-refile-region-subr "refile" beg end))
3385
3386 (defun wl-summary-copy-region (beg end)
3387   "Put copy mark on messages in the region specified by BEG and END."
3388   (interactive "r")
3389   (wl-summary-refile-region-subr "copy" beg end))
3390
3391 (defun wl-summary-refile-region-subr (copy-or-refile beg end)
3392   (save-excursion
3393     (save-restriction
3394       (goto-char beg)
3395       ;; guess by first msg
3396       (let* ((msgid (cdr (assq (wl-summary-message-number)
3397                                (elmo-msgdb-get-number-alist
3398                                 (wl-summary-buffer-msgdb)))))
3399              (function (intern (format "wl-summary-%s" copy-or-refile)))
3400              (entity (assoc msgid (elmo-msgdb-get-overview
3401                                    (wl-summary-buffer-msgdb))))
3402              folder)
3403         (if entity
3404             (setq folder (wl-summary-read-folder (wl-refile-guess entity)
3405                                                  (format "for %s"
3406                                                          copy-or-refile))))
3407         (narrow-to-region beg end)
3408         (if (eq wl-summary-buffer-view 'thread)
3409             (progn
3410               (while (not (eobp))
3411                 (let* ((number (wl-summary-message-number))
3412                        (entity (wl-thread-get-entity number))
3413                        children)
3414                   (if (wl-thread-entity-get-opened entity)
3415                       ;; opened...refile line.
3416                       (funcall function folder number)
3417                     ;; closed
3418                     (setq children (wl-thread-get-children-msgs number))
3419                     (while children
3420                       (funcall function folder (pop children))))
3421                   (forward-line 1))))
3422           (while (not (eobp))
3423             (funcall function folder (wl-summary-message-number))
3424             (forward-line 1)))))))
3425
3426 (defun wl-summary-unmark-region (beg end)
3427   (interactive "r")
3428   (save-excursion
3429     (save-restriction
3430       (narrow-to-region beg end)
3431       (goto-char (point-min))
3432       (if (eq wl-summary-buffer-view 'thread)
3433           (progn
3434             (while (not (eobp))
3435               (let* ((number (wl-summary-message-number))
3436                      (entity (wl-thread-get-entity number)))
3437                 (if (wl-thread-entity-get-opened entity)
3438                     ;; opened...unmark line.
3439                     (wl-summary-unmark)
3440                   ;; closed
3441                   (wl-summary-delete-marks-on-buffer
3442                    (wl-thread-get-children-msgs number))))
3443               (forward-line 1)))
3444         (while (not (eobp))
3445           (wl-summary-unmark)
3446           (forward-line 1))))))
3447
3448 (defun wl-summary-mark-region-subr (function beg end)
3449   (save-excursion
3450     (save-restriction
3451       (narrow-to-region beg end)
3452       (goto-char (point-min))
3453       (if (eq wl-summary-buffer-view 'thread)
3454           (progn
3455             (while (not (eobp))
3456               (let* ((number (wl-summary-message-number))
3457                      (entity (wl-thread-get-entity number))
3458                      (wl-summary-move-direction-downward t)
3459                      children)
3460                 (if (wl-thread-entity-get-opened entity)
3461                     ;; opened...delete line.
3462                     (funcall function number)
3463                   ;; closed
3464                   (setq children (wl-thread-get-children-msgs number))
3465                   (while children
3466                     (funcall function (pop children))))
3467                 (forward-line 1))))
3468         (while (not (eobp))
3469           (funcall function (wl-summary-message-number))
3470           (forward-line 1))))))
3471
3472 (defun wl-summary-delete-region (beg end)
3473   (interactive "r")
3474   (wl-summary-mark-region-subr 'wl-summary-delete beg end))
3475
3476 (defun wl-summary-target-mark-region (beg end)
3477   (interactive "r")
3478   (wl-summary-mark-region-subr 'wl-summary-target-mark beg end))
3479
3480 (defun wl-summary-target-mark-all ()
3481   (interactive)
3482   (wl-summary-target-mark-region (point-min) (point-max))
3483   (setq wl-summary-buffer-target-mark-list
3484         (mapcar 'car
3485                 (elmo-msgdb-get-number-alist (wl-summary-buffer-msgdb)))))
3486
3487 (defun wl-summary-delete-all-mark (mark)
3488   (goto-char (point-min))
3489   (while (not (eobp))
3490     (when (string= (wl-summary-temp-mark) mark)
3491       (wl-summary-unmark))
3492     (forward-line 1))
3493   (cond ((string= mark "*")
3494          (setq wl-summary-buffer-target-mark-list nil))
3495         ((string= mark "D")
3496          (setq wl-summary-buffer-delete-list nil))
3497         ((string= mark "O")
3498          (setq wl-summary-buffer-copy-list nil))
3499         ((string= mark "o")
3500          (setq wl-summary-buffer-refile-list nil))))
3501
3502 (defun wl-summary-unmark-all ()
3503   "Unmark all according to what you input."
3504   (interactive)
3505   (let ((unmarks (string-to-char-list (read-from-minibuffer "Unmark: ")))
3506         cur-mark)
3507     (save-excursion
3508       (while unmarks
3509         (setq cur-mark (char-to-string (car unmarks)))
3510         (wl-summary-delete-all-mark cur-mark)
3511         (setq unmarks (cdr unmarks))))))
3512
3513 (defun wl-summary-target-mark-thread ()
3514   (interactive)
3515   (wl-thread-call-region-func 'wl-summary-target-mark-region t))
3516
3517 (defun wl-summary-target-mark-msgs (msgs)
3518   "Return the number of marked messages."
3519   (let ((i 0) num)
3520     (while msgs
3521       (if (eq wl-summary-buffer-view 'thread)
3522           (wl-thread-jump-to-msg (car msgs))
3523         (wl-summary-jump-to-msg (car msgs)))
3524       (setq num (wl-summary-message-number))
3525       (when (eq num (car msgs))
3526         (wl-summary-target-mark num)
3527         (setq i (1+ i)))
3528       (setq msgs (cdr msgs)))
3529     i))
3530
3531 (defun wl-summary-pick (&optional from-list delete-marks)
3532   (interactive)
3533   (save-excursion
3534     (let* ((condition (car (elmo-parse-search-condition
3535                             (elmo-read-search-condition
3536                              wl-summary-pick-field-default))))
3537            (result (elmo-folder-search wl-summary-buffer-elmo-folder
3538                                        condition
3539                                        from-list))
3540            num)
3541       (if delete-marks
3542           (let ((mlist wl-summary-buffer-target-mark-list))
3543             (while mlist
3544               (when (wl-summary-jump-to-msg (car mlist))
3545                 (wl-summary-unmark))
3546               (setq mlist (cdr mlist)))
3547             (setq wl-summary-buffer-target-mark-list nil)))
3548       (if (and result
3549                (setq num (wl-summary-target-mark-msgs result))
3550                (> num 0))
3551           (if (= num (length result))
3552               (message "%d message(s) are picked." num)
3553             (message "%d(%d) message(s) are picked." num
3554                      (- (length result) num)))
3555         (message "No message was picked.")))))
3556
3557 (defun wl-summary-unvirtual ()
3558   "Exit from current virtual folder."
3559   (interactive)
3560   (if (eq 'filter
3561           (elmo-folder-type-internal wl-summary-buffer-elmo-folder))
3562       (wl-summary-goto-folder-subr
3563        (elmo-folder-name-internal
3564         (elmo-filter-folder-target-internal
3565          wl-summary-buffer-elmo-folder))
3566        'update nil nil t)
3567     (error "This folder is not filtered")))
3568
3569 (defun wl-summary-virtual (&optional arg)
3570   "Goto virtual folder.
3571 If ARG, exit virtual folder."
3572   (interactive "P")
3573   (if arg
3574       (wl-summary-unvirtual)
3575     (wl-summary-goto-folder-subr (concat "/"
3576                                          (elmo-read-search-condition
3577                                           wl-summary-pick-field-default)
3578                                          "/"
3579                                          (wl-summary-buffer-folder-name))
3580                                  'update nil nil t)))
3581
3582 (defun wl-summary-delete-all-temp-marks (&optional no-msg)
3583   "Erase all temp marks from buffer."
3584   (interactive)
3585   (when (or wl-summary-buffer-target-mark-list
3586             wl-summary-buffer-delete-list
3587             wl-summary-buffer-refile-list
3588             wl-summary-buffer-copy-list)
3589     (save-excursion
3590       (goto-char (point-min))
3591       (unless no-msg
3592         (message "Unmarking..."))
3593       (while (not (eobp))
3594         (wl-summary-unmark)
3595         (forward-line 1))
3596       (unless no-msg
3597         (message "Unmarking...done"))
3598       (setq wl-summary-buffer-target-mark-list nil)
3599       (setq wl-summary-buffer-delete-list nil)
3600       (setq wl-summary-buffer-refile-list nil)
3601       (setq wl-summary-buffer-copy-list nil))))
3602
3603 (defun wl-summary-delete-mark (number)
3604   "Delete temporary mark of the message specified by NUMBER."
3605   (cond
3606    ((memq number wl-summary-buffer-target-mark-list)
3607     (setq wl-summary-buffer-target-mark-list
3608           (delq number wl-summary-buffer-target-mark-list)))
3609    ((memq number wl-summary-buffer-delete-list)
3610     (setq wl-summary-buffer-delete-list
3611           (delq number wl-summary-buffer-delete-list)))
3612    (t
3613     (let (pair)
3614       (cond
3615        ((setq pair (assq number wl-summary-buffer-copy-list))
3616         (setq wl-summary-buffer-copy-list
3617               (delq pair wl-summary-buffer-copy-list)))
3618        ((setq pair (assq number wl-summary-buffer-refile-list))
3619         (setq wl-summary-buffer-refile-list
3620               (delq pair wl-summary-buffer-refile-list))))))))
3621
3622 (defsubst wl-summary-temp-mark ()
3623   "Move to the temp-mark column and return mark string."
3624   (move-to-column wl-summary-buffer-temp-mark-column)
3625   (buffer-substring (- (point) 1) (point)))
3626
3627 (defsubst wl-summary-persistent-mark ()
3628   "Move to the persistent-mark column and return mark string."
3629   (move-to-column wl-summary-buffer-persistent-mark-column)
3630   (buffer-substring (- (point) 1) (point)))
3631
3632 (defun wl-summary-mark-line (mark)
3633   "Put MARK on current line.  Return message number."
3634   (save-excursion
3635     (beginning-of-line)
3636     (let ((inhibit-read-only t)
3637           (buffer-read-only nil))
3638       (wl-summary-temp-mark) ; mark
3639       (delete-backward-char 1)
3640       (insert mark)
3641       (if wl-summary-highlight
3642           (wl-highlight-summary-current-line nil nil t))
3643       (set-buffer-modified-p nil))))
3644
3645 (defun wl-summary-target-mark-delete ()
3646   (interactive)
3647   (save-excursion
3648     (goto-char (point-min))
3649     (let (number mlist)
3650       (while (not (eobp))
3651         (when (string= (wl-summary-temp-mark) "*")
3652           (let (wl-summary-buffer-disp-msg)
3653             (when (setq number (wl-summary-message-number))
3654               (wl-summary-delete number)
3655               (setq wl-summary-buffer-target-mark-list
3656                     (delq number wl-summary-buffer-target-mark-list)))))
3657         (forward-line 1))
3658       (setq mlist wl-summary-buffer-target-mark-list)
3659       (while mlist
3660         (wl-append wl-summary-buffer-delete-list (list (car mlist)))
3661         (setq wl-summary-buffer-target-mark-list
3662               (delq (car mlist) wl-summary-buffer-target-mark-list))
3663         (setq mlist (cdr mlist))))))
3664
3665 (defun wl-summary-target-mark-prefetch (&optional ignore-cache)
3666   (interactive "P")
3667   (save-excursion
3668     (let* ((mlist (nreverse wl-summary-buffer-target-mark-list))
3669            (inhibit-read-only t)
3670            (buffer-read-only nil)
3671            (count 0)
3672            (length (length mlist))
3673            (pos (point))
3674            skipped
3675            new-mark)
3676       (while mlist
3677         (setq new-mark (wl-summary-prefetch-msg (car mlist) ignore-cache))
3678         (if new-mark
3679             (progn
3680               (message "Prefetching... %d/%d message(s)"
3681                        (setq count (+ 1 count)) length)
3682               (when (wl-summary-jump-to-msg (car mlist))
3683                 (wl-summary-unmark)
3684                 (when new-mark
3685                   (wl-summary-persistent-mark) ; move
3686                   (delete-backward-char 1)
3687                   (insert new-mark)
3688                   (if wl-summary-highlight
3689                       (wl-highlight-summary-current-line))
3690                   (save-excursion
3691                     (goto-char pos)
3692                     (sit-for 0)))))
3693           (setq skipped (cons (car mlist) skipped)))
3694         (setq mlist (cdr mlist)))
3695       (setq wl-summary-buffer-target-mark-list skipped)
3696       (message "Prefetching... %d/%d message(s)." count length)
3697       (set-buffer-modified-p nil))))
3698
3699 (defun wl-summary-target-mark-refile-subr (copy-or-refile)
3700   (let ((variable
3701          (intern (format "wl-summary-buffer-%s-list" copy-or-refile)))
3702         (function
3703          (intern (format "wl-summary-%s" copy-or-refile)))
3704         (numlist wl-summary-buffer-number-list)
3705         regexp number msgid entity folder mlist)
3706     (save-excursion
3707       ;; guess by first mark
3708       (while numlist
3709         (if (memq (car numlist) wl-summary-buffer-target-mark-list)
3710             (setq number (car numlist)
3711                   numlist nil))
3712         (setq numlist (cdr numlist)))
3713       (when number
3714         (setq msgid (elmo-message-field wl-summary-buffer-elmo-folder
3715                                         number 'message-id)
3716               entity (elmo-msgdb-overview-get-entity
3717                       number (wl-summary-buffer-msgdb)))
3718         (if (null entity)
3719             (error "Cannot %s" copy-or-refile))
3720         (setq folder (wl-summary-read-folder
3721                       (wl-refile-guess entity)
3722                       (format "for %s" copy-or-refile)))
3723         (goto-char (point-min))
3724         (while (not (eobp))
3725           (when (string= (wl-summary-temp-mark) "*")
3726             (let (wl-summary-buffer-disp-msg)
3727               (when (setq number (wl-summary-message-number))
3728                 (funcall function folder number)
3729                 (setq wl-summary-buffer-target-mark-list
3730                       (delq number wl-summary-buffer-target-mark-list)))))
3731           (forward-line 1))
3732         ;; process invisible messages.
3733         (setq mlist wl-summary-buffer-target-mark-list)
3734         (while mlist
3735           (set variable
3736                (append (symbol-value variable)
3737                        (list (cons (car mlist) folder))))
3738           (setq wl-summary-buffer-target-mark-list
3739                 (delq (car mlist) wl-summary-buffer-target-mark-list))
3740           (setq mlist (cdr mlist)))))))
3741
3742 (defun wl-summary-next-buffer ()
3743   "Switch to next summary buffer."
3744   (interactive)
3745   (let ((buffers (sort (wl-collect-summary)
3746                        (lambda (buffer1 buffer2)
3747                          (string-lessp (buffer-name buffer1)
3748                                        (buffer-name buffer2))))))
3749     (switch-to-buffer
3750      (or (cadr (memq (current-buffer) buffers))
3751          (car buffers)))))
3752
3753 (defun wl-summary-previous-buffer ()
3754   "Switch to previous summary buffer."
3755   (interactive)
3756   (let ((buffers (sort (wl-collect-summary)
3757                        (lambda (buffer1 buffer2)
3758                          (not (string-lessp (buffer-name buffer1)
3759                                             (buffer-name buffer2)))))))
3760     (switch-to-buffer
3761      (or (cadr (memq (current-buffer) buffers))
3762          (car buffers)))))
3763
3764 (defun wl-summary-target-mark-copy ()
3765   (interactive)
3766   (wl-summary-target-mark-refile-subr "copy"))
3767
3768 (defun wl-summary-target-mark-refile ()
3769   (interactive)
3770   (wl-summary-target-mark-refile-subr "refile"))
3771
3772 (defun wl-summary-target-mark-mark-as-read ()
3773   (interactive)
3774   (save-excursion
3775     (goto-char (point-min))
3776     (let ((inhibit-read-only t)
3777           (buffer-read-only nil)
3778           wl-summary-buffer-disp-msg
3779           number mlist)
3780       (while (not (eobp))
3781         (when (string= (wl-summary-temp-mark) "*")
3782           ;; delete target-mark from buffer.
3783           (delete-backward-char 1)
3784           (insert " ")
3785           (setq number (wl-summary-message-number))
3786           (wl-summary-mark-as-read number)
3787           (if wl-summary-highlight
3788               (wl-highlight-summary-current-line))
3789           (if number
3790               (setq wl-summary-buffer-target-mark-list
3791                     (delq number wl-summary-buffer-target-mark-list))))
3792         (forward-line 1))
3793       (setq mlist wl-summary-buffer-target-mark-list)
3794       (while mlist
3795         (wl-summary-mark-as-read (car mlist))
3796         (setq wl-summary-buffer-target-mark-list
3797               (delq (car mlist) wl-summary-buffer-target-mark-list))
3798         (setq mlist (cdr mlist)))
3799       (wl-summary-count-unread)
3800       (wl-summary-update-modeline))))
3801
3802 (defun wl-summary-target-mark-mark-as-unread ()
3803   (interactive)
3804   (save-excursion
3805     (goto-char (point-min))
3806     (let ((inhibit-read-only t)
3807           (buffer-read-only nil)
3808           wl-summary-buffer-disp-msg
3809           number mlist)
3810       (while (not (eobp))
3811         (when (string= (wl-summary-temp-mark) "*")
3812           (delete-backward-char 1)
3813           (insert " ")
3814           (setq number (wl-summary-mark-as-unread))
3815           (if wl-summary-highlight
3816               (wl-highlight-summary-current-line))
3817           (if number
3818               (setq wl-summary-buffer-target-mark-list
3819                     (delq number wl-summary-buffer-target-mark-list))))
3820         (forward-line 1))
3821       (setq mlist wl-summary-buffer-target-mark-list)
3822       (while mlist
3823         (wl-summary-mark-as-unread (car mlist))
3824 ;;;     (wl-thread-msg-mark-as-unread (car mlist))
3825         (setq wl-summary-buffer-target-mark-list
3826               (delq (car mlist) wl-summary-buffer-target-mark-list))
3827         (setq mlist (cdr mlist)))
3828       (wl-summary-count-unread)
3829       (wl-summary-update-modeline))))
3830
3831 (defun wl-summary-target-mark-mark-as-important ()
3832   (interactive)
3833   (save-excursion
3834     (goto-char (point-min))
3835     (let ((inhibit-read-only t)
3836           (buffer-read-only nil)
3837           wl-summary-buffer-disp-msg
3838           number mlist)
3839       (while (not (eobp))
3840         (when (string= (wl-summary-temp-mark) "*")
3841           ;; delete target-mark from buffer.
3842           (delete-backward-char 1)
3843           (insert " ")
3844           (setq number (wl-summary-mark-as-important))
3845           (if wl-summary-highlight
3846               (wl-highlight-summary-current-line))
3847           (if number
3848               (setq wl-summary-buffer-target-mark-list
3849                     (delq number wl-summary-buffer-target-mark-list))))
3850         (forward-line 1))
3851       (setq mlist wl-summary-buffer-target-mark-list)
3852       (while mlist
3853         (wl-summary-mark-as-important (car mlist))
3854         (wl-thread-msg-mark-as-important (car mlist))
3855         (setq wl-summary-buffer-target-mark-list
3856               (delq (car mlist) wl-summary-buffer-target-mark-list))
3857         (setq mlist (cdr mlist)))
3858       (wl-summary-count-unread)
3859       (wl-summary-update-modeline))))
3860
3861 (defun wl-summary-target-mark-save ()
3862   (interactive)
3863   (let ((wl-save-dir
3864          (wl-read-directory-name "Save to directory: "
3865                                  wl-temporary-file-directory))
3866         number)
3867     (if (null (file-exists-p wl-save-dir))
3868         (make-directory wl-save-dir))
3869     (while (setq number (car wl-summary-buffer-target-mark-list))
3870       (wl-thread-jump-to-msg number)
3871       (wl-summary-save t wl-save-dir)
3872       (wl-summary-unmark number))))
3873
3874 (defun wl-summary-target-mark-pick ()
3875   (interactive)
3876   (wl-summary-pick wl-summary-buffer-target-mark-list 'delete))
3877
3878 (defun wl-summary-mark-as-read (&optional number no-folder-mark)
3879   (interactive)
3880   (save-excursion
3881     (let ((buffer-read-only nil)
3882           (folder wl-summary-buffer-elmo-folder)
3883           (msgdb (wl-summary-buffer-msgdb))
3884           (case-fold-search nil)
3885           cur-mark mark stat visible uncached new-mark marked)
3886       (setq number (or number (wl-summary-message-number))
3887             visible (if number
3888                         (wl-summary-jump-to-msg number)
3889                       ;; interactive
3890                       t)
3891             mark (elmo-msgdb-get-mark msgdb number))
3892       (cond
3893        ((string= mark wl-summary-new-mark) ; N
3894         (setq stat 'new))
3895        ((string= mark wl-summary-unread-uncached-mark) ; U
3896         (setq stat 'unread))
3897        ((string= mark wl-summary-unread-cached-mark)  ; !
3898         (setq stat 'unread))
3899        ((string= mark wl-summary-read-uncached-mark)  ; u
3900         (setq stat 'read))
3901        (t
3902         ;; no need to mark server.
3903         (setq no-folder-mark t)))
3904       (setq new-mark
3905             (if (and (if (elmo-message-use-cache-p folder number)
3906                          (not (elmo-folder-local-p folder)))
3907                      (not (elmo-file-cache-exists-p
3908                            (elmo-message-field wl-summary-buffer-elmo-folder
3909                                                number 'message-id))))
3910                 wl-summary-read-uncached-mark
3911               nil))
3912       ;; folder mark.
3913       (unless no-folder-mark
3914         (setq marked (elmo-folder-mark-as-read folder (list number))))
3915       (when (or no-folder-mark marked)
3916         (cond ((eq stat 'unread)
3917                (setq wl-summary-buffer-unread-count
3918                      (1- wl-summary-buffer-unread-count)))
3919               ((eq stat 'new)
3920                (setq wl-summary-buffer-new-count
3921                      (1- wl-summary-buffer-new-count))))
3922         (wl-summary-update-modeline)
3923         (wl-folder-update-unread
3924          (wl-summary-buffer-folder-name)
3925          (+ wl-summary-buffer-unread-count
3926             wl-summary-buffer-new-count))
3927         (when stat
3928           ;; set mark on buffer
3929           (when visible
3930             (unless (string= (wl-summary-persistent-mark) new-mark)
3931               (delete-backward-char 1)
3932               (insert (or new-mark " "))))
3933           ;; set msgdb mark.
3934           (unless (string= mark new-mark)
3935             (elmo-msgdb-set-mark msgdb number new-mark))
3936           (wl-summary-set-mark-modified))
3937         (if (and visible wl-summary-highlight)
3938             (wl-highlight-summary-current-line nil nil t)))
3939       (set-buffer-modified-p nil)
3940       (if stat
3941           (run-hooks 'wl-summary-unread-message-hook))
3942       number ;return value
3943       )))
3944
3945 (defun wl-summary-mark-as-important (&optional number
3946                                                mark
3947                                                no-server-update)
3948   (interactive)
3949   (if (eq (elmo-folder-type-internal wl-summary-buffer-elmo-folder)
3950           'internal)
3951       (error "Cannot process mark in this folder"))
3952   (save-excursion
3953     (let* (eol
3954           (inhibit-read-only t)
3955           (buffer-read-only nil)
3956           (folder wl-summary-buffer-elmo-folder)
3957           (msgdb (wl-summary-buffer-msgdb))
3958           (number-alist (elmo-msgdb-get-number-alist msgdb))
3959           message-id visible cur-mark)
3960       (if number
3961           (progn
3962             (setq visible (wl-summary-jump-to-msg number))
3963             (setq mark (or mark (elmo-msgdb-get-mark msgdb number))))
3964         (setq visible t))
3965       (when visible
3966         (if (null (setq number (wl-summary-message-number)))
3967             (progn
3968               (message "No message.")
3969               (setq visible nil))
3970           (end-of-line)
3971           (setq eol (point))
3972           (wl-summary-goto-previous-message-beginning)))
3973       (if (or (and (not visible)
3974                    ;; already exists in msgdb.
3975                    (elmo-msgdb-overview-get-entity number msgdb))
3976               (setq cur-mark (wl-summary-persistent-mark)))
3977           (progn
3978             (setq number (or number (wl-summary-message-number)))
3979             (setq mark (or mark cur-mark))
3980             (setq message-id (elmo-message-field
3981                               wl-summary-buffer-elmo-folder
3982                               number
3983                               'message-id))
3984             (if (string= mark wl-summary-important-mark)
3985                 (progn
3986                   ;; server side mark
3987                   (save-match-data
3988                     (unless no-server-update
3989                       (elmo-folder-unmark-important folder (list number))
3990                       (elmo-msgdb-global-mark-delete message-id))
3991                     ;; Remove cache if local folder.
3992                     (if (and (elmo-folder-local-p folder)
3993                              (not (eq 'mark
3994                                       (elmo-folder-type-internal folder))))
3995                         (elmo-file-cache-delete
3996                          (elmo-file-cache-get-path message-id))))
3997                   (when visible
3998                     (delete-backward-char 1)
3999                     (insert " "))
4000                   (elmo-msgdb-set-mark msgdb number nil))
4001               ;; server side mark
4002               (save-match-data
4003                 (unless no-server-update
4004                   (elmo-folder-mark-as-important folder (list number))))
4005               (when visible
4006                 (delete-backward-char 1)
4007                 (insert wl-summary-important-mark))
4008               (elmo-msgdb-set-mark msgdb number
4009                                    wl-summary-important-mark)
4010               (if (eq (elmo-file-cache-exists-p message-id) 'entire)
4011                   (elmo-folder-mark-as-read folder (list number))
4012                 ;; Force cache message.
4013                 (elmo-message-encache folder number 'read))
4014               (unless no-server-update
4015                 (elmo-msgdb-global-mark-set message-id
4016                                             wl-summary-important-mark)))
4017             (wl-summary-set-mark-modified)))
4018       (if (and visible wl-summary-highlight)
4019           (wl-highlight-summary-current-line nil nil t))))
4020   (set-buffer-modified-p nil)
4021   number)
4022
4023 ;;; Summary line.
4024 (defvar wl-summary-line-formatter nil)
4025
4026 (defun wl-summary-view-old-p ()
4027   "Return non-nil when summary view cache has old format."
4028   (save-excursion
4029     (goto-char (point-min))
4030     (and wl-summary-buffer-number-list
4031          (not (re-search-forward "\r-?[0-9]+" (point-at-eol) t)))))
4032
4033 (defun wl-summary-line-format-changed-p ()
4034   "Return non-nil when summary line format is changed."
4035   (not (string=
4036         wl-summary-buffer-line-format
4037         (or (elmo-object-load (expand-file-name 
4038                                wl-summary-line-format-file
4039                                (elmo-folder-msgdb-path
4040                                 wl-summary-buffer-elmo-folder))
4041                               wl-summary-buffer-mime-charset)
4042             wl-summary-buffer-line-format))))
4043
4044 (defun wl-summary-line-format-save ()
4045   "Save current summary line format."
4046   (elmo-object-save
4047    (expand-file-name wl-summary-line-format-file
4048                      (elmo-folder-msgdb-path
4049                       wl-summary-buffer-elmo-folder))
4050    wl-summary-buffer-line-format
4051    wl-summary-buffer-mime-charset))
4052
4053 (defun wl-summary-line-number ()
4054   (wl-set-string-width
4055    (- wl-summary-buffer-number-column)
4056    (number-to-string
4057     (elmo-msgdb-overview-entity-get-number wl-message-entity))))
4058
4059 (defun wl-summary-line-year ()
4060   (aref wl-datevec 0))
4061 (defun wl-summary-line-month ()
4062   (format "%02d" (aref wl-datevec 1)))
4063 (defun wl-summary-line-day ()
4064   (format "%02d" (aref wl-datevec 2)))
4065 (defun wl-summary-line-day-of-week ()
4066   (condition-case nil
4067       (elmo-date-get-week (aref wl-datevec 0)
4068                           (aref wl-datevec 1)
4069                           (aref wl-datevec 2))
4070     (error "??")))
4071 (defun wl-summary-line-hour ()
4072   (format "%02d" (aref wl-datevec 3)))
4073 (defun wl-summary-line-minute ()
4074   (format "%02d" (aref wl-datevec 4)))
4075
4076 (defun wl-summary-line-size ()
4077   (let ((size (elmo-msgdb-overview-entity-get-size wl-message-entity)))
4078     (if size
4079         (cond
4080          ((<= 1 (/ size 1048576))
4081           (format "%.0fM" (/ size 1048576.0)))
4082          ((<= 1 (/ size 1024))
4083           (format "%.0fK" (/ size 1024.0)))
4084          (t (format "%dB" size)))
4085       "")))
4086
4087 (defvar wl-summary-line-subject-minimum-length nil)
4088 (defun wl-summary-line-subject ()
4089   (let (no-parent subject parent-raw-subject parent-subject)
4090     (if (string= wl-thr-indent-string "")
4091         (setq no-parent t)) ; no parent
4092     (setq subject
4093           (elmo-delete-char ?\n
4094                             (or (elmo-msgdb-overview-entity-get-subject
4095                                  wl-message-entity)
4096                                 wl-summary-no-subject-message)))
4097     (setq parent-raw-subject
4098           (elmo-msgdb-overview-entity-get-subject wl-parent-message-entity))
4099     (setq parent-subject
4100           (if parent-raw-subject
4101               (elmo-delete-char ?\n parent-raw-subject)))
4102     (setq subject
4103           (if (or no-parent
4104                   (null parent-subject)
4105                   (not (wl-summary-subject-equal
4106                         subject parent-subject)))
4107               (funcall wl-summary-subject-function subject)
4108             ""))
4109     (when (and wl-summary-line-subject-minimum-length
4110                (< (string-width subject)
4111                   wl-summary-line-subject-minimum-length))
4112       (while (< (string-width subject)
4113                 wl-summary-line-subject-minimum-length)
4114         (setq subject (concat subject " "))))
4115     (if (and (not wl-summary-width)
4116              wl-summary-subject-length-limit)
4117         (truncate-string subject
4118                          wl-summary-subject-length-limit)
4119       subject)))
4120
4121 (defun wl-summary-line-from ()
4122   (elmo-delete-char ?\n
4123                     (funcall wl-summary-from-function
4124                              (elmo-msgdb-overview-entity-get-from
4125                               wl-message-entity))))
4126
4127 (defun wl-summary-line-list-info ()
4128   (let (sequence ml-name ml-count subject return-path)
4129     (setq sequence (elmo-msgdb-overview-entity-get-extra-field
4130                     wl-message-entity "x-sequence")
4131           ml-name (or (elmo-msgdb-overview-entity-get-extra-field
4132                        wl-message-entity "x-ml-name")
4133                       (and sequence
4134                            (car (split-string sequence " "))))
4135           ml-count (or (elmo-msgdb-overview-entity-get-extra-field
4136                         wl-message-entity "x-mail-count")
4137                        (elmo-msgdb-overview-entity-get-extra-field
4138                         wl-message-entity "x-ml-count")
4139                        (and sequence
4140                             (cadr (split-string sequence " ")))))
4141     (and (setq subject (elmo-msgdb-overview-entity-get-subject
4142                         wl-message-entity))
4143          (setq subject (elmo-delete-char ?\n subject))
4144          (string-match "^\\s(\\(\\S)+\\)[ :]\\([0-9]+\\)\\s)[ \t]*" subject)
4145          (progn
4146            (or ml-name (setq ml-name (match-string 1 subject)))
4147            (or ml-count (setq ml-count (match-string 2 subject)))))
4148     (and (setq return-path
4149                (elmo-msgdb-overview-entity-get-extra-field
4150                 wl-message-entity "return-path"))
4151          (string-match "^<\\([^@>]+\\)-return-\\([0-9]+\\)-" return-path)
4152          (progn
4153            (or ml-name (setq ml-name (match-string 1 return-path)))
4154            (or ml-count (setq ml-count (match-string 2 return-path)))))
4155     (condition-case nil
4156         (if (and ml-name ml-count)
4157             (format "(%s %05d)"
4158                     (car (split-string ml-name " "))
4159                     (string-to-int ml-count))
4160           "")
4161       (error ""))))
4162
4163 (defun wl-summary-line-list-count ()
4164   (let (sequence ml-count subject-string return-path)
4165     (setq ml-count
4166           (or (elmo-msgdb-overview-entity-get-extra-field
4167                wl-message-entity "x-mail-count")
4168               (elmo-msgdb-overview-entity-get-extra-field
4169                wl-message-entity "x-ml-count")
4170               (and (setq sequence (elmo-msgdb-overview-entity-get-extra-field
4171                                    wl-message-entity "x-sequence"))
4172                    (cadr (split-string sequence " ")))
4173               (and (setq subject-string
4174                          (elmo-msgdb-overview-entity-get-subject
4175                           wl-message-entity))
4176                    (setq subject-string
4177                          (elmo-delete-char ?\n subject-string))
4178                    (string-match "^\\s(\\(\\S)+\\)[ :]\\([0-9]+\\)\\s)[ \t]*"
4179                                  subject-string)
4180                    (match-string 2 subject-string))
4181               (and (setq return-path
4182                          (elmo-msgdb-overview-entity-get-extra-field
4183                           wl-message-entity "return-path"))
4184                    (string-match "^<[^@>]+-return-\\([0-9]+\\)-"
4185                                  return-path)
4186                    (match-string 1 return-path))))
4187     (if ml-count
4188         (format "%.0f" (string-to-number ml-count))
4189       "")))
4190
4191 (defun wl-summary-line-attached ()
4192   (let ((content-type (elmo-msgdb-overview-entity-get-extra-field
4193                        wl-message-entity "content-type")))
4194     (if (and content-type
4195              (string-match "multipart/mixed" content-type))
4196         "@"
4197       "")))
4198
4199 (defun wl-summary-create-line (wl-message-entity
4200                                wl-parent-message-entity
4201                                wl-temp-mark
4202                                wl-persistent-mark
4203                                &optional
4204                                wl-thr-children-number
4205                                wl-thr-indent-string
4206                                wl-thr-linked)
4207   "Create a summary line."
4208   (let ((wl-mime-charset wl-summary-buffer-mime-charset)
4209         (elmo-mime-charset wl-summary-buffer-mime-charset)
4210         (elmo-lang wl-summary-buffer-weekday-name-lang)
4211         (wl-datevec (or (ignore-errors (timezone-fix-time
4212                                         (elmo-msgdb-overview-entity-get-date 
4213                                          wl-message-entity)
4214                                         nil
4215                                         wl-summary-fix-timezone))
4216                         (make-vector 5 0)))
4217         (entity wl-message-entity) ; backward compatibility.
4218         line mark)
4219     (if (and wl-thr-indent-string
4220              wl-summary-indent-length-limit
4221              (< wl-summary-indent-length-limit
4222                 (string-width wl-thr-indent-string)))
4223         (setq wl-thr-indent-string (wl-set-string-width
4224                                     wl-summary-indent-length-limit
4225                                     wl-thr-indent-string)))
4226     (setq line (funcall wl-summary-buffer-line-formatter))
4227     (if wl-summary-width (setq line
4228                                (wl-set-string-width
4229                                 (- wl-summary-width 1) line nil
4230                                 'ignore-invalid)))
4231     (setq line (concat line
4232                        "\r"
4233                        (number-to-string
4234                         (elmo-msgdb-overview-entity-get-number 
4235                          wl-message-entity))))
4236     (if wl-summary-highlight
4237         (wl-highlight-summary-line-string line
4238                                           wl-persistent-mark
4239                                           wl-temp-mark
4240                                           wl-thr-indent-string))
4241     line))
4242
4243 (defsubst wl-summary-proc-wday (wday-str year month mday)
4244   (save-match-data
4245     (if (string-match "\\([A-Z][a-z][a-z]\\).*" wday-str)
4246         (wl-match-string 1 wday-str)
4247       (elmo-date-get-week year month mday))))
4248
4249 (defvar wl-summary-move-spec-plugged-alist
4250   (` ((new . ((t . nil)
4251               (p . (, wl-summary-new-mark))
4252               (p . (, (wl-regexp-opt
4253                        (list wl-summary-unread-uncached-mark
4254                              wl-summary-unread-cached-mark))))
4255               (p . (, (regexp-quote wl-summary-important-mark)))))
4256       (unread . ((t . nil)
4257                  (p . (, (wl-regexp-opt
4258                           (list wl-summary-new-mark
4259                                 wl-summary-unread-uncached-mark
4260                                 wl-summary-unread-cached-mark))))
4261                  (p . (, (regexp-quote wl-summary-important-mark))))))))
4262
4263 (defvar wl-summary-move-spec-unplugged-alist
4264   (` ((new . ((t . nil)
4265               (p . (, wl-summary-unread-cached-mark))
4266               (p . (, (regexp-quote wl-summary-important-mark)))))
4267       (unread . ((t . nil)
4268                  (p . (, wl-summary-unread-cached-mark))
4269                  (p . (, (regexp-quote wl-summary-important-mark))))))))
4270
4271 (defsubst wl-summary-next-message (num direction hereto)
4272   (if wl-summary-buffer-next-message-function
4273       (funcall wl-summary-buffer-next-message-function num direction hereto)
4274     (let ((cur-spec (cdr (assq wl-summary-move-order
4275                                (if (elmo-folder-plugged-p
4276                                     wl-summary-buffer-elmo-folder)
4277                                    wl-summary-move-spec-plugged-alist
4278                                  wl-summary-move-spec-unplugged-alist))))
4279           (nums (memq num (if (eq direction 'up)
4280                               (reverse wl-summary-buffer-number-list)
4281                             wl-summary-buffer-number-list)))
4282           marked-list nums2)
4283       (unless hereto (setq nums (cdr nums)))
4284       (setq nums2 nums)
4285       (if cur-spec
4286           (catch 'done
4287             (while cur-spec
4288               (setq nums nums2)
4289               (cond ((eq (car (car cur-spec)) 'p)
4290                      (if (setq marked-list
4291                                (elmo-folder-list-messages-mark-match
4292                                 wl-summary-buffer-elmo-folder
4293                                 (cdr (car cur-spec))))
4294                          (while nums
4295                            (if (memq (car nums) marked-list)
4296                                (throw 'done (car nums)))
4297                            (setq nums (cdr nums)))))
4298                     ((eq (car (car cur-spec)) 't)
4299                      (if wl-summary-buffer-target-mark-list
4300                          (while nums
4301                            (if (memq (car nums)
4302                                      wl-summary-buffer-target-mark-list)
4303                                (throw 'done (car nums)))
4304                            (setq nums (cdr nums))))))
4305               (setq cur-spec (cdr cur-spec))))
4306         (car nums)))))
4307
4308 (defsubst wl-summary-cursor-move (direction hereto)
4309   (when (and (eq direction 'up)
4310              (eobp))
4311     (forward-line -1)
4312     (setq hereto t))
4313   (let (num)
4314     (when (setq num (wl-summary-next-message (wl-summary-message-number)
4315                                              direction hereto))
4316       (if (numberp num)
4317           (wl-thread-jump-to-msg num))
4318       t)))
4319 ;;
4320 ;; Goto unread or important
4321 ;; returns t if next message exists in this folder.
4322 (defun wl-summary-cursor-down (&optional hereto)
4323   (interactive "P")
4324   (wl-summary-cursor-move 'down hereto))
4325
4326 (defun wl-summary-cursor-up (&optional hereto)
4327   (interactive "P")
4328   (wl-summary-cursor-move 'up hereto))
4329
4330 (defun wl-summary-save-view-cache ()
4331   (save-excursion
4332     (let* ((dir (elmo-folder-msgdb-path wl-summary-buffer-elmo-folder))
4333            (cache (expand-file-name wl-summary-cache-file dir))
4334            (view (expand-file-name wl-summary-view-file dir))
4335            (save-view wl-summary-buffer-view)
4336            (mark-list (copy-sequence wl-summary-buffer-target-mark-list))
4337            (refile-list (copy-sequence wl-summary-buffer-refile-list))
4338            (copy-list (copy-sequence wl-summary-buffer-copy-list))
4339            (delete-list (copy-sequence wl-summary-buffer-delete-list))
4340            (tmp-buffer (get-buffer-create " *wl-summary-save-view-cache*"))
4341            (temp-column wl-summary-buffer-temp-mark-column)
4342            (charset wl-summary-buffer-mime-charset))
4343       (if (file-directory-p dir)
4344           (); ok.
4345         (if (file-exists-p dir)
4346             (error "File %s already exists" dir)
4347           (elmo-make-directory dir)))
4348       (if (eq save-view 'thread)
4349           (wl-thread-save-entity dir))
4350       (when wl-summary-check-line-format
4351         (wl-summary-line-format-save))
4352       (unwind-protect
4353           (progn
4354             (when (file-writable-p cache)
4355               (copy-to-buffer tmp-buffer (point-min) (point-max))
4356               (with-current-buffer tmp-buffer
4357                 (widen)
4358                 (make-local-variable 'wl-summary-highlight)
4359                 (setq wl-summary-highlight nil
4360                       wl-summary-buffer-target-mark-list mark-list
4361                       wl-summary-buffer-refile-list refile-list
4362                       wl-summary-buffer-copy-list copy-list
4363                       wl-summary-buffer-delete-list delete-list
4364                       wl-summary-buffer-temp-mark-column temp-column)
4365                 (wl-summary-delete-all-temp-marks)
4366                 (encode-coding-region
4367                  (point-min) (point-max)
4368                  (or (mime-charset-to-coding-system charset 'LF)
4369                      ;; Mule 2 doesn't have `*ctext*unix'.
4370                      (mime-charset-to-coding-system charset)))
4371                 (write-region-as-binary (point-min)(point-max)
4372                                         cache nil 'no-msg)))
4373             (when (file-writable-p view) ; 'thread or 'sequence
4374               (save-excursion
4375                 (set-buffer tmp-buffer)
4376                 (erase-buffer)
4377                 (prin1 save-view tmp-buffer)
4378                 (princ "\n" tmp-buffer)
4379                 (write-region (point-min) (point-max) view nil 'no-msg))))
4380         ;; kill tmp buffer.
4381         (kill-buffer tmp-buffer)))))
4382
4383 (defsubst wl-summary-get-sync-range (folder)
4384   (intern (or (and
4385                (elmo-folder-plugged-p folder)
4386                (wl-get-assoc-list-value
4387                 wl-folder-sync-range-alist
4388                 (elmo-folder-name-internal folder)))
4389               wl-default-sync-range)))
4390
4391 ;; redefined for wl-summary-sync-update
4392 (defun wl-summary-input-range (folder)
4393   "returns update or all or rescan."
4394   ;; for the case when parts are expanded in the bottom of the folder
4395   (let ((input-range-list '("update" "all" "rescan" "first:" "last:"
4396                             "cache-status"
4397                             "no-sync" "rescan-noscore" "all-visible"))
4398         (default (or (wl-get-assoc-list-value
4399                       wl-folder-sync-range-alist
4400                       folder)
4401                      wl-default-sync-range))
4402         range)
4403     (setq range
4404           (completing-read (format "Range (%s): " default)
4405                            (mapcar
4406                             (function (lambda (x) (cons x x)))
4407                             input-range-list)))
4408     (if (string= range "")
4409         default
4410       range)))
4411
4412 (defun wl-summary-toggle-disp-folder (&optional arg)
4413   (interactive)
4414   (let ((cur-buf (current-buffer))
4415         (summary-win (get-buffer-window (current-buffer)))
4416         fld-buf fld-win)
4417     (cond
4418      ((eq arg 'on)
4419       (setq wl-summary-buffer-disp-folder t)
4420       ;; hide your folder window
4421       (if (setq fld-buf (get-buffer wl-folder-buffer-name))
4422           (if (setq fld-win (get-buffer-window fld-buf))
4423               (delete-window fld-win))))
4424      ((eq arg 'off)
4425       (setq wl-summary-buffer-disp-folder nil)
4426       ;; hide your wl-message window!
4427       (when (buffer-live-p wl-message-buffer)
4428         (wl-message-select-buffer wl-message-buffer)
4429         (delete-window))
4430       (select-window (get-buffer-window cur-buf))
4431       ;; display wl-folder window!!
4432       (if (setq fld-buf (get-buffer wl-folder-buffer-name))
4433           (if (setq fld-win (get-buffer-window fld-buf))
4434               ;; folder win is already displayed.
4435               (select-window fld-win)
4436             ;; folder win is not displayed.
4437             (switch-to-buffer fld-buf))
4438         ;; no folder buf
4439         (wl-folder))
4440       ;; temporarily delete summary-win.
4441       (if summary-win
4442           (delete-window summary-win))
4443       (split-window-horizontally wl-folder-window-width)
4444       (other-window 1)
4445       (switch-to-buffer cur-buf))
4446      (t
4447       (if (setq fld-buf (get-buffer wl-folder-buffer-name))
4448           (if (setq fld-win (get-buffer-window fld-buf))
4449               (setq wl-summary-buffer-disp-folder nil)
4450             (setq wl-summary-buffer-disp-folder t)))
4451       (if (not wl-summary-buffer-disp-folder)
4452           ;; hide message window
4453           (let ((mes-win (and wl-message-buffer
4454                               (get-buffer-window wl-message-buffer)))
4455                 (wl-stay-folder-window t))
4456             (if mes-win (delete-window mes-win))
4457             ;; hide your folder window
4458             (if (setq fld-buf (get-buffer wl-folder-buffer-name))
4459                 (if (setq fld-win (get-buffer-window fld-buf))
4460                     (progn
4461                       (delete-window (get-buffer-window cur-buf))
4462                       (select-window fld-win)
4463                       (switch-to-buffer cur-buf))))
4464             (run-hooks 'wl-summary-toggle-disp-folder-off-hook)
4465             ;; resume message window.
4466             (when mes-win
4467               (wl-message-select-buffer wl-message-buffer)
4468               (run-hooks 'wl-summary-toggle-disp-folder-message-resumed-hook)
4469               (select-window (get-buffer-window cur-buf))))
4470         ;; hide message window
4471         (let ((wl-stay-folder-window t)
4472               (mes-win (and wl-message-buffer
4473                             (get-buffer-window wl-message-buffer))))
4474           (if mes-win (delete-window mes-win))
4475           (select-window (get-buffer-window cur-buf))
4476           ;; display wl-folder window!!
4477           (if (setq fld-buf (get-buffer wl-folder-buffer-name))
4478               (if (setq fld-win (get-buffer-window fld-buf))
4479                   ;; folder win is already displayed.
4480                   (select-window fld-win)
4481                 ;; folder win is not displayed...occupy all.
4482                 (switch-to-buffer fld-buf))
4483             ;; no folder buf
4484             (wl-folder))
4485           (split-window-horizontally wl-folder-window-width)
4486           (other-window 1)
4487           (switch-to-buffer cur-buf)
4488           ;; resume message window.
4489           (run-hooks 'wl-summary-toggle-disp-folder-on-hook)
4490           (when mes-win
4491             (wl-message-select-buffer wl-message-buffer)
4492             (run-hooks 'wl-summary-toggle-disp-folder-message-resumed-hook)
4493             (select-window (get-buffer-window cur-buf))))))))
4494   (run-hooks 'wl-summary-toggle-disp-folder-hook))
4495
4496 (defun wl-summary-toggle-disp-msg (&optional arg)
4497   (interactive)
4498   (let ((cur-buf (current-buffer))
4499         fld-buf fld-win
4500         summary-win)
4501     (cond
4502      ((eq arg 'on)
4503       (setq wl-summary-buffer-disp-msg t)
4504       (save-excursion
4505         ;; hide your folder window
4506         (if (and (not wl-stay-folder-window)
4507                  (setq fld-buf (get-buffer wl-folder-buffer-name)))
4508             (if (setq fld-win (get-buffer-window fld-buf))
4509                 (unless (one-window-p fld-win)
4510                   (delete-window fld-win))))))
4511      ((eq arg 'off)
4512       (wl-delete-all-overlays)
4513       (setq wl-summary-buffer-disp-msg nil)
4514       (save-excursion
4515         (when (buffer-live-p wl-message-buffer)
4516           (wl-message-select-buffer wl-message-buffer)
4517           (delete-window)
4518           (and (get-buffer-window cur-buf)
4519                (select-window (get-buffer-window cur-buf))))
4520         (run-hooks 'wl-summary-toggle-disp-off-hook)))
4521      (t
4522       (if (and wl-message-buffer
4523                (get-buffer-window wl-message-buffer)) ; already displayed
4524           (setq wl-summary-buffer-disp-msg nil)
4525         (setq wl-summary-buffer-disp-msg t))
4526       (if wl-summary-buffer-disp-msg
4527           (progn
4528             (wl-summary-redisplay)
4529 ;;; hide your folder window
4530 ;;;         (setq fld-buf (get-buffer wl-folder-buffer-name))
4531 ;;;         (if (setq fld-win (get-buffer-window fld-buf))
4532 ;;;             (delete-window fld-win)))
4533             (run-hooks 'wl-summary-toggle-disp-on-hook))
4534         (wl-delete-all-overlays)
4535         (save-excursion
4536           (wl-message-select-buffer wl-message-buffer)
4537           (delete-window)
4538           (select-window (get-buffer-window cur-buf))
4539           (run-hooks 'wl-summary-toggle-disp-off-hook))
4540 ;;;     (switch-to-buffer cur-buf)
4541         )))))
4542
4543 (defun wl-summary-next-line-content ()
4544   "Show next line of the message."
4545   (interactive)
4546   (let ((cur-buf (current-buffer)))
4547     (wl-summary-toggle-disp-msg 'on)
4548     (when (wl-summary-set-message-buffer-or-redisplay 'ignore-original)
4549       (set-buffer cur-buf)
4550       (wl-message-next-page 1))))
4551
4552 (defun wl-summary-prev-line-content ()
4553   (interactive)
4554   (let ((cur-buf (current-buffer)))
4555     (wl-summary-toggle-disp-msg 'on)
4556     (when (wl-summary-set-message-buffer-or-redisplay 'ignore-original)
4557       (set-buffer cur-buf)
4558       (wl-message-prev-page 1))))
4559
4560 (defun wl-summary-next-page ()
4561   (interactive)
4562   (let ((cur-buf (current-buffer)))
4563     (wl-summary-toggle-disp-msg 'on)
4564     (when (wl-summary-set-message-buffer-or-redisplay 'ignore-original)
4565       (set-buffer cur-buf)
4566       (wl-message-next-page))))
4567
4568 (defun wl-summary-prev-page ()
4569   (interactive)
4570   (let ((cur-buf (current-buffer)))
4571     (wl-summary-toggle-disp-msg 'on)
4572     (when (wl-summary-set-message-buffer-or-redisplay 'ignore-original)
4573       (set-buffer cur-buf)
4574       (wl-message-prev-page))))
4575
4576 (defsubst wl-summary-no-mime-p (folder)
4577   (wl-string-match-member (elmo-folder-name-internal folder)
4578                           wl-summary-no-mime-folder-list))
4579
4580 (defun wl-summary-set-message-buffer-or-redisplay (&rest args)
4581   "Set message buffer.
4582 If message is not displayed yet, display it.
4583 Return t if message exists."
4584   (let ((folder wl-summary-buffer-elmo-folder)
4585         (number (wl-summary-message-number))
4586         cur-folder cur-number message-last-pos)
4587     (when (buffer-live-p wl-message-buffer)
4588       (save-window-excursion
4589         (wl-message-select-buffer wl-message-buffer)
4590         (setq cur-folder wl-message-buffer-cur-folder)
4591         (setq cur-number wl-message-buffer-cur-number)))
4592     (if (and (string= (elmo-folder-name-internal folder) (or cur-folder ""))
4593              (eq number (or cur-number 0)))
4594         (progn
4595           (set-buffer wl-message-buffer)
4596           t)
4597       (if (wl-summary-no-mime-p folder)
4598           (wl-summary-redisplay-no-mime-internal folder number)
4599         (wl-summary-redisplay-internal folder number))
4600       (when (buffer-live-p wl-message-buffer)
4601         (set-buffer wl-message-buffer))
4602       nil)))
4603
4604 (defun wl-summary-target-mark-forward (&optional arg)
4605   (interactive "P")
4606   (let ((mlist (nreverse wl-summary-buffer-target-mark-list))
4607         (summary-buf (current-buffer))
4608         (wl-draft-forward t)
4609         start-point
4610         draft-buf)
4611     (wl-summary-jump-to-msg (car mlist))
4612     (wl-summary-forward t)
4613     (setq start-point (point))
4614     (setq draft-buf (current-buffer))
4615     (setq mlist (cdr mlist))
4616     (save-window-excursion
4617       (when mlist
4618         (while mlist
4619           (set-buffer summary-buf)
4620           (wl-summary-jump-to-msg (car mlist))
4621           (wl-summary-redisplay)
4622           (set-buffer draft-buf)
4623           (goto-char (point-max))
4624           (wl-draft-insert-message)
4625           (setq mlist (cdr mlist)))
4626         (wl-draft-body-goto-top)
4627         (wl-draft-enclose-digest-region (point) (point-max)))
4628       (goto-char start-point)
4629       (save-excursion
4630         (set-buffer summary-buf)
4631         (wl-summary-delete-all-temp-marks)))
4632     (run-hooks 'wl-mail-setup-hook)))
4633
4634 (defun wl-summary-target-mark-reply-with-citation (&optional arg)
4635   (interactive "P")
4636   (let ((mlist (nreverse wl-summary-buffer-target-mark-list))
4637         (summary-buf (current-buffer))
4638         change-major-mode-hook
4639         start-point
4640         draft-buf)
4641     (wl-summary-jump-to-msg (car mlist))
4642     (wl-summary-reply arg t)
4643     (goto-char (point-max))
4644     (setq start-point (point-marker))
4645     (setq draft-buf (current-buffer))
4646     (save-window-excursion
4647       (while mlist
4648         (set-buffer summary-buf)
4649         (delete-other-windows)
4650         (wl-summary-jump-to-msg (car mlist))
4651         (wl-summary-redisplay)
4652         (set-buffer draft-buf)
4653         (goto-char (point-max))
4654         (wl-draft-yank-original)
4655         (setq mlist (cdr mlist)))
4656       (goto-char start-point)
4657       (save-excursion
4658         (set-buffer summary-buf)
4659         (wl-summary-delete-all-temp-marks)))
4660     (run-hooks 'wl-mail-setup-hook)))
4661
4662 (defun wl-summary-reply-with-citation (&optional arg)
4663   (interactive "P")
4664   (when (wl-summary-reply arg t)
4665     (goto-char (point-max))
4666     (wl-draft-yank-original)
4667     (run-hooks 'wl-mail-setup-hook)))
4668
4669 (defun wl-summary-jump-to-msg-by-message-id (&optional id)
4670   (interactive)
4671   (let* ((original (wl-summary-message-number))
4672          (msgid (elmo-string (or id (read-from-minibuffer "Message-ID: "))))
4673          (number-alist (elmo-msgdb-get-number-alist (wl-summary-buffer-msgdb)))
4674          msg otherfld schar
4675          (errmsg
4676           (format "No message with id \"%s\" in the folder." msgid)))
4677     (if (setq msg (car (rassoc msgid number-alist)))
4678 ;;;     (wl-summary-jump-to-msg-internal
4679 ;;;      (wl-summary-buffer-folder-name) msg 'no-sync)
4680         (progn
4681           (wl-thread-jump-to-msg msg)
4682           t)
4683       ;; for XEmacs!
4684       (if (and elmo-use-database
4685                (setq errmsg
4686                      (format
4687                       "No message with id \"%s\" in the database." msgid))
4688                (setq otherfld (elmo-database-msgid-get msgid)))
4689           (if (cdr (wl-summary-jump-to-msg-internal
4690                     (car otherfld) (nth 1 otherfld) 'no-sync))
4691               t ; succeed.
4692             ;; Back to original.
4693             (wl-summary-jump-to-msg-internal
4694              (wl-summary-buffer-folder-name) original 'no-sync))
4695         (cond ((eq wl-summary-search-via-nntp 'confirm)
4696                (require 'elmo-nntp)
4697                (message "Search message in nntp server \"%s\" <y/n/s(elect)>?"
4698                         elmo-nntp-default-server)
4699                (setq schar (read-char))
4700                (cond ((eq schar ?y)
4701                       (wl-summary-jump-to-msg-by-message-id-via-nntp msgid))
4702                      ((eq schar ?s)
4703                       (wl-summary-jump-to-msg-by-message-id-via-nntp
4704                        msgid
4705                        (read-from-minibuffer "NNTP Server: ")))
4706                      (t
4707                       (message errmsg)
4708                       nil)))
4709               (wl-summary-search-via-nntp
4710                (wl-summary-jump-to-msg-by-message-id-via-nntp msgid))
4711               (t
4712                (message errmsg)
4713                nil))))))
4714
4715 (defun wl-summary-jump-to-msg-by-message-id-via-nntp (&optional id server-spec)
4716   (interactive)
4717   (let* ((msgid (elmo-string (or id (read-from-minibuffer "Message-ID: "))))
4718          newsgroups folder ret
4719          user server port type spec)
4720     (if server-spec
4721         (if (string-match "^-" server-spec)
4722             (setq spec (wl-folder-get-elmo-folder server-spec)
4723                   user (elmo-net-folder-user-internal spec)
4724                   server (elmo-net-folder-server-internal spec)
4725                   port (elmo-net-folder-port-internal spec)
4726                   type (elmo-net-folder-stream-type-internal spec))
4727           (setq server server-spec)))
4728     (when (setq ret (elmo-nntp-get-newsgroup-by-msgid
4729                      msgid
4730                      (or server elmo-nntp-default-server)
4731                      (or user elmo-nntp-default-user)
4732                      (or port elmo-nntp-default-port)
4733                      (or type elmo-nntp-default-stream-type)))
4734       (setq newsgroups (elmo-nntp-parse-newsgroups ret))
4735       (setq folder (concat "-" (car newsgroups)
4736                            (elmo-nntp-folder-postfix user server port type)))
4737       (catch 'found
4738         (while newsgroups
4739           (if (wl-folder-entity-exists-p (car newsgroups)
4740                                          wl-folder-newsgroups-hashtb)
4741               (throw 'found
4742                      (setq folder (concat "-" (car newsgroups)
4743                                           (elmo-nntp-folder-postfix
4744                                            user server port type)))))
4745           (setq newsgroups (cdr newsgroups)))))
4746     (if ret
4747         (wl-summary-jump-to-msg-internal folder nil 'update msgid)
4748       (message "No message id \"%s\" in nntp server \"%s\"."
4749                msgid (or server elmo-nntp-default-server))
4750       nil)))
4751
4752 (defun wl-summary-jump-to-msg-internal (folder msg scan-type &optional msgid)
4753   (let (wl-auto-select-first entity)
4754     (if (or (string= folder (wl-summary-buffer-folder-name))
4755             (y-or-n-p
4756              (format
4757               "Message was found in the folder \"%s\". Jump to it? "
4758               folder)))
4759         (progn
4760           (unwind-protect
4761               (wl-summary-goto-folder-subr
4762                folder scan-type nil nil t)
4763             (if msgid
4764                 (setq msg
4765                       (car (rassoc msgid
4766                                    (elmo-msgdb-get-number-alist
4767                                     (wl-summary-buffer-msgdb))))))
4768             (setq entity (wl-folder-search-entity-by-name folder
4769                                                           wl-folder-entity
4770                                                           'folder))
4771             (if entity
4772                 (wl-folder-set-current-entity-id
4773                  (wl-folder-get-entity-id entity))))
4774           (if (null msg)
4775               (message "Message was not found currently in this folder.")
4776             (setq msg (and (wl-thread-jump-to-msg msg) msg)))
4777           (cons folder msg)))))
4778
4779 (defun wl-summary-jump-to-parent-message (arg)
4780   (interactive "P")
4781   (let ((cur-buf (current-buffer))
4782         (number (wl-summary-message-number))
4783         (regexp "\\(<[^<>]*>\\)[ \t]*$")
4784         (i -1) ;; xxx
4785         msg-id msg-num ref-list ref irt)
4786     (if (null number)
4787         (message "No message.")
4788       (when (eq wl-summary-buffer-view 'thread)
4789         (cond ((and arg (not (numberp arg)))
4790                (setq msg-num
4791                      (wl-thread-entity-get-number
4792                       (wl-thread-entity-get-top-entity
4793                        (wl-thread-get-entity number)))))
4794               ((and arg (numberp arg))
4795                (setq i 0)
4796                (setq msg-num number)
4797                (while (< i arg)
4798                  (setq msg-num
4799                        (wl-thread-entity-get-number
4800                         (wl-thread-entity-get-parent-entity
4801                          (wl-thread-get-entity msg-num))))
4802                  (setq i (1+ i))))
4803               (t (setq msg-num
4804                        (wl-thread-entity-get-number
4805                         (wl-thread-entity-get-parent-entity
4806                          (wl-thread-get-entity number)))))))
4807       (when (null msg-num)
4808         (wl-summary-set-message-buffer-or-redisplay)
4809         (set-buffer (wl-message-get-original-buffer))
4810         (message "Searching parent message...")
4811         (setq ref (std11-field-body "References")
4812               irt (std11-field-body "In-Reply-To"))
4813         (cond
4814          ((and arg (not (numberp arg)) ref (not (string= ref ""))
4815                (string-match regexp ref))
4816           ;; The first message of the thread.
4817           (setq msg-id (wl-match-string 1 ref)))
4818          ;; "In-Reply-To:" has only one msg-id.
4819          ((and (null arg) irt (not (string= irt ""))
4820                (string-match regexp irt))
4821           (setq msg-id (wl-match-string 1 irt)))
4822          ((and (or (null arg) (numberp arg)) ref (not (string= ref ""))
4823                (string-match regexp ref))
4824           ;; "^" searching parent, "C-u 2 ^" looking for grandparent.
4825           (while (string-match regexp ref)
4826             (setq ref-list
4827                   (append (list
4828                            (wl-match-string 1 ref))
4829                           ref-list))
4830             (setq ref (substring ref (match-end 0)))
4831             (setq i (1+ i)))
4832           (setq msg-id
4833                 (if (null arg) (nth 0 ref-list) ;; previous
4834                   (if (<= arg i) (nth (1- arg) ref-list)
4835                     (nth i ref-list)))))))
4836       (set-buffer cur-buf)
4837       (cond ((and (null msg-id) (null msg-num))
4838              (message "No parent message!")
4839              nil)
4840             ((and msg-id (wl-summary-jump-to-msg-by-message-id msg-id))
4841              (wl-summary-redisplay)
4842              (message "Searching parent message...done")
4843              t)
4844             ((and msg-num (wl-summary-jump-to-msg msg-num))
4845              (wl-summary-redisplay)
4846              (message "Searching parent message...done")
4847              t)
4848             (t ; failed.
4849              (message "Parent message was not found.")
4850              nil)))))
4851
4852 (defun wl-summary-reply (&optional arg without-setup-hook)
4853   "Reply to current message. Default is \"wide\" reply.
4854 Reply to author if invoked with ARG."
4855   (interactive "P")
4856   (let ((folder wl-summary-buffer-elmo-folder)
4857         (number (wl-summary-message-number))
4858         (summary-buf (current-buffer))
4859         mes-buf)
4860     (when number
4861       (save-excursion
4862         (wl-summary-redisplay-internal folder number))
4863       (setq mes-buf wl-message-buffer)
4864       (wl-message-select-buffer wl-message-buffer)
4865       (set-buffer mes-buf)
4866       (goto-char (point-min))
4867       (unless wl-draft-use-frame
4868         (split-window-vertically)
4869         (other-window 1))
4870       (when (setq mes-buf (wl-message-get-original-buffer))
4871         (wl-draft-reply mes-buf arg summary-buf)
4872         (unless without-setup-hook
4873           (run-hooks 'wl-mail-setup-hook)))
4874       t)))
4875
4876 (defun wl-summary-write ()
4877   "Write a new draft from Summary."
4878   (interactive)
4879   (wl-draft (list (cons 'To ""))
4880             nil nil nil nil (wl-summary-buffer-folder-name))
4881   (run-hooks 'wl-mail-setup-hook)
4882   (mail-position-on-field "To"))
4883
4884 (defvar wl-summary-write-current-folder-functions
4885   '(wl-folder-get-newsgroups
4886     wl-folder-guess-mailing-list-by-refile-rule
4887     wl-folder-guess-mailing-list-by-folder-name)
4888   "Newsgroups or Mailing List address guess functions list.
4889 Call from `wl-summary-write-current-folder'.
4890 When guess function return nil, challenge next guess-function.")
4891
4892 (defun wl-summary-write-current-folder (&optional folder)
4893   "Write message to current FOLDER's newsgroup or mailing-list.
4894 Use function list is `wl-summary-write-current-folder-functions'."
4895   (interactive)
4896   ;; default FOLDER is current buffer folder
4897   (setq folder (or folder (wl-summary-buffer-folder-name)))
4898   (let ((func-list wl-summary-write-current-folder-functions)
4899         guess-list guess-func)
4900     (while func-list
4901       (setq guess-list (funcall (car func-list) folder))
4902       (if (null guess-list)
4903           (setq func-list (cdr func-list))
4904         (setq guess-func (car func-list))
4905         (setq func-list nil)))
4906     (if (null guess-func)
4907         (wl-summary-write)
4908       (unless (or (stringp (nth 0 guess-list))
4909                   (stringp (nth 1 guess-list))
4910                   (stringp (nth 2 guess-list)))
4911         (error "Invalid value return guess function `%s'"
4912                (symbol-name guess-func)))
4913       (wl-draft (list (cons 'To (nth 0 guess-list))
4914                       (cons 'Cc (nth 1 guess-list))
4915                       (cons 'Newsgroups (nth 2 guess-list)))
4916                 nil nil nil nil folder)
4917       (run-hooks 'wl-mail-setup-hook)
4918       (mail-position-on-field "Subject"))))
4919
4920 (defun wl-summary-forward (&optional without-setup-hook)
4921   ""
4922   (interactive)
4923   (let ((folder wl-summary-buffer-elmo-folder)
4924         (number (wl-summary-message-number))
4925         (summary-buf (current-buffer))
4926         (wl-draft-forward t)
4927         mes-buf
4928         entity subject num)
4929     (if (null number)
4930         (message "No message.")
4931       (if (and (elmo-message-use-cache-p folder number)
4932                (eq (elmo-file-cache-status
4933                     (elmo-file-cache-get
4934                      (elmo-message-field folder number 'message-id)))
4935                    'section))
4936           ;; Reload.
4937           (wl-summary-redisplay-internal nil nil 'force-reload)
4938         (wl-summary-redisplay-internal folder number))
4939       (setq mes-buf wl-message-buffer)
4940       (wl-message-select-buffer mes-buf)
4941       (unless wl-draft-use-frame
4942         (split-window-vertically)
4943         (other-window 1))
4944       ;; get original subject.
4945       (if summary-buf
4946           (save-excursion
4947             (set-buffer summary-buf)
4948             (setq subject
4949                   (or (elmo-message-field folder number 'subject) ""))))
4950       (set-buffer mes-buf)
4951       (wl-draft-forward subject summary-buf)
4952       (unless without-setup-hook
4953         (run-hooks 'wl-mail-setup-hook)))))
4954
4955 (defun wl-summary-click (e)
4956   (interactive "e")
4957   (mouse-set-point e)
4958   (wl-summary-read))
4959
4960 (defun wl-summary-read ()
4961   "Proceed reading message in the summary buffer."
4962   (interactive)
4963   (let ((cur-buf (current-buffer)))
4964     (wl-summary-toggle-disp-msg 'on)
4965     (when (wl-summary-set-message-buffer-or-redisplay 'ignore-original)
4966       (set-buffer cur-buf)
4967       (if (wl-message-next-page)
4968           (wl-summary-down t)))))
4969
4970 (defsubst wl-summary-cursor-move-surface (downward interactive)
4971   (if wl-summary-move-direction-toggle
4972       (setq wl-summary-move-direction-downward downward))
4973   (let ((start (point))
4974         (skip-tmark-regexp (wl-regexp-opt wl-summary-skip-mark-list))
4975         (skip t)
4976         skip-pmark-regexp goto-next next-entity finfo)
4977     (if (elmo-folder-plugged-p wl-summary-buffer-elmo-folder)
4978         ()
4979       (setq skip-pmark-regexp
4980             (wl-regexp-opt (list " "
4981                                  wl-summary-unread-cached-mark
4982                                  wl-summary-important-mark))))
4983     (while (and skip
4984                 (not (if downward (eobp) (bobp))))
4985       (if downward
4986           (forward-line 1)
4987         (forward-line -1))
4988       (setq skip (or (string-match skip-tmark-regexp 
4989                                    (save-excursion
4990                                      (wl-summary-temp-mark)))
4991                      (and skip-pmark-regexp
4992                           (not (string-match
4993                                 skip-pmark-regexp
4994                                 (save-excursion
4995                                   (wl-summary-persistent-mark))))))))
4996
4997     (if (if downward (eobp) (and (bobp) skip)) (setq goto-next t))
4998     (if (or (eobp) (and (bobp) skip))
4999         (goto-char start))
5000
5001     (beginning-of-line)
5002
5003     (if (not goto-next)
5004         (if wl-summary-buffer-disp-msg
5005             (wl-summary-redisplay))
5006       (if interactive
5007           (if wl-summary-buffer-next-folder-function
5008               (funcall wl-summary-buffer-next-folder-function)
5009             (when wl-auto-select-next
5010               (setq next-entity
5011                     (if downward
5012                         (wl-summary-get-next-folder)
5013                       (wl-summary-get-prev-folder)))
5014               (if next-entity
5015                   (setq finfo (wl-folder-get-entity-info next-entity))))
5016             (wl-ask-folder
5017              '(lambda () (wl-summary-next-folder-or-exit next-entity))
5018              (format
5019               "No more messages. Type SPC to go to %s."
5020               (wl-summary-entity-info-msg next-entity finfo))))))))
5021
5022 (defun wl-summary-prev (&optional interactive)
5023   (interactive)
5024   (wl-summary-cursor-move-surface nil (or interactive (interactive-p))))
5025
5026 (defun wl-summary-next (&optional interactive)
5027   (interactive)
5028   (wl-summary-cursor-move-surface t (or interactive (interactive-p))))
5029
5030 (defun wl-summary-up (&optional interactive skip-no-unread)
5031   ""
5032   (interactive)
5033   (if wl-summary-move-direction-toggle
5034       (setq wl-summary-move-direction-downward nil))
5035   (if (wl-summary-cursor-up)
5036       (if wl-summary-buffer-disp-msg
5037           (wl-summary-redisplay))
5038     (if (or interactive
5039             (interactive-p))
5040         (if wl-summary-buffer-prev-folder-function
5041             (funcall wl-summary-buffer-prev-folder-function)
5042           (let (next-entity finfo)
5043             (when wl-auto-select-next
5044               (progn
5045                 (setq next-entity (wl-summary-get-prev-unread-folder))
5046                 (if next-entity
5047                     (setq finfo (wl-folder-get-entity-info next-entity)))))
5048             (if (and skip-no-unread
5049                      (eq wl-auto-select-next 'skip-no-unread))
5050                 (wl-summary-next-folder-or-exit next-entity t)
5051               (wl-ask-folder
5052                '(lambda () (wl-summary-next-folder-or-exit next-entity t))
5053                (format
5054                 "No more unread messages. Type SPC to go to %s."
5055                 (wl-summary-entity-info-msg next-entity finfo)))))))))
5056
5057 (defun wl-summary-get-prev-folder ()
5058   (let ((folder-buf (get-buffer wl-folder-buffer-name))
5059         last-entity cur-id)
5060     (when folder-buf
5061       (setq cur-id (save-excursion (set-buffer folder-buf)
5062                                    wl-folder-buffer-cur-entity-id))
5063       (wl-folder-get-prev-folder cur-id))))
5064
5065 (defun wl-summary-get-next-folder ()
5066   (let ((folder-buf (get-buffer wl-folder-buffer-name))
5067         cur-id)
5068     (when folder-buf
5069       (setq cur-id (save-excursion (set-buffer folder-buf)
5070                                    wl-folder-buffer-cur-entity-id))
5071       (wl-folder-get-next-folder cur-id))))
5072
5073 (defun wl-summary-get-next-unread-folder ()
5074   (let ((folder-buf (get-buffer wl-folder-buffer-name))
5075         cur-id)
5076     (when folder-buf
5077       (setq cur-id (save-excursion (set-buffer folder-buf)
5078                                    wl-folder-buffer-cur-entity-id))
5079       (wl-folder-get-next-folder cur-id 'unread))))
5080
5081 (defun wl-summary-get-prev-unread-folder ()
5082   (let ((folder-buf (get-buffer wl-folder-buffer-name))
5083         cur-id)
5084     (when folder-buf
5085       (setq cur-id (save-excursion (set-buffer folder-buf)
5086                                    wl-folder-buffer-cur-entity-id))
5087       (wl-folder-get-prev-folder cur-id 'unread))))
5088
5089 (defun wl-summary-down (&optional interactive skip-no-unread)
5090   (interactive)
5091   (if wl-summary-move-direction-toggle
5092       (setq wl-summary-move-direction-downward t))
5093   (if (wl-summary-cursor-down)
5094       (if wl-summary-buffer-disp-msg
5095           (wl-summary-redisplay))
5096     (if (or interactive
5097             (interactive-p))
5098         (if wl-summary-buffer-next-folder-function
5099             (funcall wl-summary-buffer-next-folder-function)
5100           (let (next-entity finfo)
5101             (when wl-auto-select-next
5102               (setq next-entity (wl-summary-get-next-unread-folder)))
5103             (if next-entity
5104                 (setq finfo (wl-folder-get-entity-info next-entity)))
5105             (if (and skip-no-unread
5106                      (eq wl-auto-select-next 'skip-no-unread))
5107                 (wl-summary-next-folder-or-exit next-entity)
5108               (wl-ask-folder
5109                '(lambda () (wl-summary-next-folder-or-exit next-entity))
5110                (format
5111                 "No more unread messages. Type SPC to go to %s."
5112                 (wl-summary-entity-info-msg next-entity finfo)))))))))
5113
5114 (defun wl-summary-goto-last-displayed-msg ()
5115   (interactive)
5116   (unless wl-summary-buffer-last-displayed-msg
5117     (setq wl-summary-buffer-last-displayed-msg
5118           wl-summary-buffer-current-msg))
5119   (if wl-summary-buffer-last-displayed-msg
5120       (progn
5121         (wl-summary-jump-to-msg wl-summary-buffer-last-displayed-msg)
5122         (if wl-summary-buffer-disp-msg
5123             (wl-summary-redisplay)))
5124     (message "No last message.")))
5125
5126 (defun wl-summary-redisplay (&optional arg)
5127   (interactive "P")
5128   (if (and (not arg)
5129            (wl-summary-no-mime-p wl-summary-buffer-elmo-folder))
5130       (wl-summary-redisplay-no-mime)
5131     (wl-summary-redisplay-internal nil nil arg)))
5132
5133 (defsubst wl-summary-redisplay-internal (&optional folder number force-reload)
5134   (interactive)
5135   (let* ((msgdb (wl-summary-buffer-msgdb))
5136          (folder (or folder wl-summary-buffer-elmo-folder))
5137          (num (or number (wl-summary-message-number)))
5138          (wl-mime-charset      wl-summary-buffer-mime-charset)
5139          (default-mime-charset wl-summary-buffer-mime-charset)
5140          fld-buf fld-win thr-entity)
5141     (if (and wl-thread-open-reading-thread
5142              (eq wl-summary-buffer-view 'thread)
5143              (not (wl-thread-entity-get-opened
5144                    (setq thr-entity (wl-thread-get-entity
5145                                      num))))
5146              (wl-thread-entity-get-children thr-entity))
5147         (wl-thread-force-open))
5148     (if num
5149         (progn
5150           (setq wl-summary-buffer-disp-msg t)
5151           (setq wl-summary-buffer-last-displayed-msg
5152                 wl-summary-buffer-current-msg)
5153           ;; hide folder window
5154           (if (and (not wl-stay-folder-window)
5155                    (setq fld-buf (get-buffer wl-folder-buffer-name)))
5156               (if (setq fld-win (get-buffer-window fld-buf))
5157                   (delete-window fld-win)))
5158           (setq wl-current-summary-buffer (current-buffer))
5159           (wl-summary-mark-as-read
5160            num
5161            ;; not fetched, then change server-mark.
5162            (if (wl-message-redisplay folder num 'mime
5163                                      (or force-reload
5164                                          (string= (elmo-folder-name-internal
5165                                                    folder)
5166                                                   wl-draft-folder)))
5167                nil
5168              ;; plugged, then leave server-mark.
5169              (if (and
5170                   (not
5171                    (elmo-folder-local-p
5172                     wl-summary-buffer-elmo-folder))
5173                   (elmo-folder-plugged-p
5174                    wl-summary-buffer-elmo-folder))
5175                  'leave)))
5176           (setq wl-summary-buffer-current-msg num)
5177           (when wl-summary-recenter
5178             (recenter (/ (- (window-height) 2) 2))
5179             (if (not wl-summary-indent-length-limit)
5180                 (wl-horizontal-recenter)))
5181           (wl-highlight-summary-displaying)
5182           (wl-message-buffer-prefetch-next folder num
5183                                            wl-message-buffer-prefetch-depth
5184                                            (current-buffer)
5185                                            wl-summary-buffer-mime-charset)
5186           (run-hooks 'wl-summary-redisplay-hook))
5187       (message "No message to display."))))
5188
5189 (defun wl-summary-redisplay-no-mime (&optional ask-coding)
5190   "Display message without MIME decoding.
5191 If ASK-CODING is non-nil, coding-system for the message is asked."
5192   (interactive "P")
5193   (let ((elmo-mime-display-as-is-coding-system
5194          (if ask-coding
5195              (or (read-coding-system "Coding system: ")
5196                  elmo-mime-display-as-is-coding-system)
5197            elmo-mime-display-as-is-coding-system)))
5198     (wl-summary-redisplay-no-mime-internal)))
5199
5200 (defun wl-summary-redisplay-no-mime-internal (&optional folder number)
5201   (let* ((fld (or folder wl-summary-buffer-elmo-folder))
5202          (num (or number (wl-summary-message-number)))
5203          wl-break-pages)
5204     (if num
5205         (progn
5206           (setq wl-summary-buffer-disp-msg t)
5207           (setq wl-summary-buffer-last-displayed-msg
5208                 wl-summary-buffer-current-msg)
5209           (setq wl-current-summary-buffer (current-buffer))
5210           (wl-message-redisplay fld num 'as-is
5211                                 (string= (elmo-folder-name-internal fld)
5212                                          wl-draft-folder))
5213           (wl-summary-mark-as-read num)
5214           (setq wl-summary-buffer-current-msg num)
5215           (when wl-summary-recenter
5216             (recenter (/ (- (window-height) 2) 2))
5217             (if (not wl-summary-indent-length-limit)
5218                 (wl-horizontal-recenter)))
5219           (wl-highlight-summary-displaying)
5220           (run-hooks 'wl-summary-redisplay-hook))
5221       (message "No message to display.")
5222       (wl-ask-folder 'wl-summary-exit
5223                      "No more messages. Type SPC to go to folder mode."))))
5224
5225 (defun wl-summary-redisplay-all-header (&optional folder number)
5226   (interactive)
5227   (let* ((fld (or folder wl-summary-buffer-elmo-folder))
5228          (num (or number (wl-summary-message-number)))
5229          (wl-mime-charset      wl-summary-buffer-mime-charset)
5230          (default-mime-charset wl-summary-buffer-mime-charset))
5231     (if num
5232         (progn
5233           (setq wl-summary-buffer-disp-msg t)
5234           (setq wl-summary-buffer-last-displayed-msg
5235                 wl-summary-buffer-current-msg)
5236           (setq wl-current-summary-buffer (current-buffer))
5237           (if (wl-message-redisplay fld num 'all-header
5238                                     (string= (elmo-folder-name-internal fld)
5239                                              wl-draft-folder))
5240               (wl-summary-mark-as-read num))
5241           (setq wl-summary-buffer-current-msg num)
5242           (when wl-summary-recenter
5243             (recenter (/ (- (window-height) 2) 2))
5244             (if (not wl-summary-indent-length-limit)
5245                 (wl-horizontal-recenter)))
5246           (wl-highlight-summary-displaying)
5247           (run-hooks 'wl-summary-redisplay-hook))
5248       (message "No message to display."))))
5249
5250 (defun wl-summary-jump-to-current-message ()
5251   "Jump into Message buffer."
5252   (interactive)
5253   (let (message-buf message-win)
5254     (if (setq message-buf wl-message-buffer)
5255         (if (setq message-win (get-buffer-window message-buf))
5256             (select-window message-win)
5257           (wl-message-select-buffer wl-message-buffer))
5258       (wl-summary-redisplay)
5259       (wl-message-select-buffer wl-message-buffer))))
5260
5261 (defun wl-summary-cancel-message ()
5262   "Cancel an article on news."
5263   (interactive)
5264   (if (null (wl-summary-message-number))
5265       (message "No message.")
5266     (let ((summary-buf (current-buffer))
5267           message-buf)
5268       (wl-summary-set-message-buffer-or-redisplay)
5269       (if (setq message-buf (wl-message-get-original-buffer))
5270           (set-buffer message-buf))
5271       (unless (wl-message-news-p)
5272         (set-buffer summary-buf)
5273         (if (and (eq (elmo-folder-type-internal wl-summary-buffer-elmo-folder)
5274                      'nntp)
5275                  (y-or-n-p "Cannot get Newsgroups. Fetch again? "))
5276             (progn
5277               (wl-summary-redisplay t)
5278               (wl-summary-supersedes-message))
5279           (error "This is not a news article; supersedes is impossible")))
5280       (when (yes-or-no-p "Do you really want to cancel this article? ")
5281         (let (from newsgroups message-id distribution buf)
5282           (save-excursion
5283             (setq from (std11-field-body "from")
5284                   newsgroups (std11-field-body "newsgroups")
5285                   message-id (std11-field-body "message-id")
5286                   distribution (std11-field-body "distribution"))
5287             ;; Make sure that this article was written by the user.
5288             (unless (wl-address-user-mail-address-p
5289                      (wl-address-header-extract-address
5290                       (car (wl-parse-addresses from))))
5291               (error "This article is not yours"))
5292             ;; Make control message.
5293             (setq buf (set-buffer (get-buffer-create " *message cancel*")))
5294             (setq wl-draft-buffer-cur-summary-buffer summary-buf)
5295             (buffer-disable-undo (current-buffer))
5296             (erase-buffer)
5297             (insert "Newsgroups: " newsgroups "\n"
5298                     "From: " (wl-address-header-extract-address
5299                               wl-from) "\n"
5300                               "Subject: cmsg cancel " message-id "\n"
5301                               "Control: cancel " message-id "\n"
5302                               (if distribution
5303                                   (concat "Distribution: " distribution "\n")
5304                                 "")
5305                               mail-header-separator "\n"
5306                               wl-summary-cancel-message)
5307             (message "Canceling your message...")
5308             (wl-draft-raw-send t t) ; kill when done, force-pre-hooks.
5309             (message "Canceling your message...done")))))))
5310
5311 (defun wl-summary-supersedes-message ()
5312   "Supersede current message."
5313   (interactive)
5314   (let ((summary-buf (current-buffer))
5315         message-buf from)
5316     (wl-summary-set-message-buffer-or-redisplay)
5317     (if (setq message-buf (wl-message-get-original-buffer))
5318         (set-buffer message-buf))
5319     (unless (wl-message-news-p)
5320       (set-buffer summary-buf)
5321       (if (and (eq (elmo-folder-type-internal wl-summary-buffer-elmo-folder)
5322                    'nntp)
5323                (y-or-n-p "Cannot get Newsgroups. Fetch again? "))
5324           (progn
5325             (wl-summary-redisplay t)
5326             (wl-summary-supersedes-message))
5327         (error "This is not a news article; supersedes is impossible")))
5328     (save-excursion
5329       (setq from (std11-field-body "from"))
5330       ;; Make sure that this article was written by the user.
5331       (unless (wl-address-user-mail-address-p
5332                (wl-address-header-extract-address
5333                 (car (wl-parse-addresses from))))
5334         (error "This article is not yours"))
5335       (let* ((message-id (std11-field-body "message-id"))
5336              (followup-to (std11-field-body "followup-to"))
5337              (mail-default-headers
5338               (concat mail-default-headers
5339                       "Supersedes: " message-id "\n"
5340                       (and followup-to
5341                            (concat "Followup-To: " followup-to "\n")))))
5342         (if message-buf (set-buffer message-buf))
5343         (wl-draft-edit-string (buffer-substring (point-min) (point-max)))))))
5344
5345 (defun wl-summary-save (&optional arg wl-save-dir)
5346   "Save current message to disk."
5347   (interactive)
5348   (let ((filename)
5349         (num (wl-summary-message-number)))
5350     (if (null wl-save-dir)
5351         (setq wl-save-dir wl-temporary-file-directory))
5352     (if num
5353         (save-excursion
5354           (setq filename (expand-file-name
5355                           (int-to-string num)
5356                           wl-save-dir))
5357           (if (null (and arg
5358                          (null (file-exists-p filename))))
5359               (setq filename
5360                     (read-file-name "Save to file: " filename)))
5361
5362           (wl-summary-set-message-buffer-or-redisplay)
5363           (set-buffer (wl-message-get-original-buffer))
5364           (if (and (null arg) (file-exists-p filename))
5365               (if (y-or-n-p "File already exists.  override it? ")
5366                   (write-region (point-min) (point-max) filename))
5367             (write-region (point-min) (point-max) filename)))
5368       (message "No message to save."))
5369     num))
5370
5371 (defun wl-summary-save-region (beg end)
5372   (interactive "r")
5373   (save-excursion
5374     (save-restriction
5375       (narrow-to-region beg end)
5376       (goto-char (point-min))
5377       (let ((wl-save-dir
5378              (wl-read-directory-name "Save to directory: "
5379                                      wl-temporary-file-directory)))
5380         (if (null (file-exists-p wl-save-dir))
5381             (make-directory wl-save-dir))
5382         (if (eq wl-summary-buffer-view 'thread)
5383             (progn
5384               (while (not (eobp))
5385                 (let* ((number (wl-summary-message-number))
5386                        (entity (wl-thread-get-entity number)))
5387                   (if (wl-thread-entity-get-opened entity)
5388                       (wl-summary-save t wl-save-dir)
5389                     ;; closed
5390                     (wl-summary-save t wl-save-dir))
5391                   (forward-line 1))))
5392           (while (not (eobp))
5393             (wl-summary-save t wl-save-dir)
5394             (forward-line 1)))))))
5395
5396 ;; mew-summary-pipe-message()
5397 (defun wl-summary-pipe-message (prefix command)
5398   "Send this message via pipe."
5399   (interactive (list current-prefix-arg nil))
5400   (if (null (wl-summary-message-number))
5401       (message "No message.")
5402     (setq command (read-string "Shell command on message: "
5403                                wl-summary-shell-command-last))
5404     (if (y-or-n-p "Send this message to pipe? ")
5405         (wl-summary-pipe-message-subr prefix command))))
5406
5407 (defun wl-summary-target-mark-pipe (prefix command)
5408   "Send each marked messages via pipe."
5409   (interactive (list current-prefix-arg nil))
5410   (if (null wl-summary-buffer-target-mark-list)
5411       (message "No marked message.")
5412     (setq command (read-string "Shell command on each marked message: "
5413                                wl-summary-shell-command-last))
5414     (when (y-or-n-p "Send each marked message to pipe? ")
5415       (while (car wl-summary-buffer-target-mark-list)
5416         (let ((num (car wl-summary-buffer-target-mark-list)))
5417           (wl-thread-jump-to-msg num)
5418           (wl-summary-pipe-message-subr prefix command)
5419           (wl-summary-unmark num))))))
5420
5421 (defun wl-summary-pipe-message-subr (prefix command)
5422   (save-excursion
5423     (wl-summary-set-message-buffer-or-redisplay)
5424     (set-buffer (wl-message-get-original-buffer))
5425     (if (string= command "")
5426         (setq command wl-summary-shell-command-last))
5427     (goto-char (point-min)) ; perhaps this line won't be necessary
5428     (if prefix
5429         (search-forward "\n\n"))
5430     (shell-command-on-region (point) (point-max) command nil)
5431     (setq wl-summary-shell-command-last command)))
5432
5433 (defun wl-summary-print-message (&optional arg)
5434   (interactive "P")
5435   (if (null (wl-summary-message-number))
5436       (message "No message.")
5437     (save-excursion
5438       (wl-summary-set-message-buffer-or-redisplay)
5439       (if (or (not (interactive-p))
5440               (y-or-n-p "Print ok? "))
5441           (progn
5442             (let ((buffer (generate-new-buffer " *print*")))
5443               (copy-to-buffer buffer (point-min) (point-max))
5444               (set-buffer buffer)
5445               (funcall wl-print-buffer-function)
5446               (kill-buffer buffer)))
5447         (message "")))))
5448
5449 (defun wl-summary-print-message-with-ps-print (&optional filename)
5450   "Print message via ps-print."
5451   (interactive)
5452   (if (null (wl-summary-message-number))
5453       (message "No message.")
5454     (setq filename (ps-print-preprint current-prefix-arg))
5455     (if (or (not (interactive-p))
5456             (y-or-n-p "Print ok? "))
5457         (let ((summary-buffer (current-buffer))
5458               wl-break-pages)
5459           (save-excursion
5460             (wl-summary-set-message-buffer-or-redisplay)
5461             ;; (wl-summary-redisplay-internal)
5462             (let* ((buffer (generate-new-buffer " *print*"))
5463                    (entity (progn
5464                              (set-buffer summary-buffer)
5465                              (assoc (cdr (assq
5466                                           (wl-summary-message-number)
5467                                           (elmo-msgdb-get-number-alist
5468                                            (wl-summary-buffer-msgdb))))
5469                                     (elmo-msgdb-get-overview
5470                                      (wl-summary-buffer-msgdb)))))
5471                    (wl-ps-subject
5472                     (and entity
5473                          (or (elmo-msgdb-overview-entity-get-subject entity)
5474                              "")))
5475                    (wl-ps-from
5476                     (and entity
5477                          (or (elmo-msgdb-overview-entity-get-from entity) "")))
5478                    (wl-ps-date
5479                     (and entity
5480                          (or (elmo-msgdb-overview-entity-get-date entity) ""))))
5481               (run-hooks 'wl-ps-preprint-hook)
5482               (set-buffer wl-message-buffer)
5483               (copy-to-buffer buffer (point-min) (point-max))
5484               (set-buffer buffer)
5485               (unwind-protect
5486                   (let ((ps-left-header
5487                          (list (concat "(" wl-ps-subject ")")
5488                                (concat "(" wl-ps-from ")")))
5489                         (ps-right-header
5490                          (list "/pagenumberstring load"
5491                                (concat "(" wl-ps-date ")"))))
5492                     (run-hooks 'wl-ps-print-hook)
5493                     (funcall wl-ps-print-buffer-function filename))
5494                 (kill-buffer buffer)))))
5495       (message ""))))
5496
5497 (if (featurep 'ps-print) ; ps-print is available.
5498     (fset 'wl-summary-print-message 'wl-summary-print-message-with-ps-print))
5499
5500 (defun wl-summary-target-mark-print ()
5501   (interactive)
5502   (if (null wl-summary-buffer-target-mark-list)
5503       (message "No marked message.")
5504     (when (y-or-n-p "Print all marked messages. OK? ")
5505       (while (car wl-summary-buffer-target-mark-list)
5506         (let ((num (car wl-summary-buffer-target-mark-list)))
5507           (wl-thread-jump-to-msg num)
5508           (wl-summary-print-message)
5509           (wl-summary-unmark num))))))
5510
5511 (defun wl-summary-folder-info-update ()
5512   (let ((folder (elmo-string (wl-summary-buffer-folder-name)))
5513         (num-db (elmo-msgdb-get-number-alist
5514                  (wl-summary-buffer-msgdb))))
5515     (wl-folder-set-folder-updated folder
5516                                   (list 0
5517                                         (+ wl-summary-buffer-unread-count
5518                                            wl-summary-buffer-new-count)
5519                                         (length num-db)))))
5520
5521 (defun wl-summary-get-original-buffer ()
5522   "Get original buffer for the current summary."
5523   (save-excursion
5524     (wl-summary-set-message-buffer-or-redisplay)
5525     (wl-message-get-original-buffer)))
5526
5527 (defun wl-summary-pack-number (&optional arg)
5528   (interactive "P")
5529   (elmo-folder-pack-numbers wl-summary-buffer-elmo-folder)
5530   (let (wl-use-scoring)
5531     (wl-summary-rescan)))
5532
5533 (defun wl-summary-target-mark-uudecode ()
5534   (interactive)
5535   (let ((mlist (reverse wl-summary-buffer-target-mark-list))
5536         (summary-buf (current-buffer))
5537         (tmp-buf (get-buffer-create "*WL UUENCODE*"))
5538         orig-buf i k filename rc errmsg)
5539     (setq i 1)
5540     (setq k (length mlist))
5541     (set-buffer tmp-buf)
5542     (erase-buffer)
5543     (save-window-excursion
5544       (while mlist
5545         (set-buffer summary-buf)
5546         (wl-summary-jump-to-msg (car mlist))
5547         (wl-summary-redisplay)
5548         (set-buffer (setq orig-buf (wl-summary-get-original-buffer)))
5549         (goto-char (point-min))
5550         (cond ((= i 1) ; first
5551                (if (setq filename (wl-message-uu-substring
5552                                    orig-buf tmp-buf t
5553                                    (= i k)))
5554                    nil
5555                  (error "Can't find begin line")))
5556               ((< i k)
5557                (wl-message-uu-substring orig-buf tmp-buf))
5558               (t ; last
5559                (wl-message-uu-substring orig-buf tmp-buf nil t)))
5560         (setq i (1+ i))
5561         (setq mlist (cdr mlist)))
5562       (set-buffer tmp-buf)
5563       (message "Exec %s..." wl-prog-uudecode)
5564       (unwind-protect
5565           (let ((decode-dir wl-temporary-file-directory))
5566             (if (not wl-prog-uudecode-no-stdout-option)
5567                 (setq filename (read-file-name "Save to file: "
5568                                                (expand-file-name
5569                                                 (elmo-safe-filename filename)
5570                                                 wl-temporary-file-directory)))
5571               (setq decode-dir
5572                     (wl-read-directory-name "Save to directory: "
5573                                             wl-temporary-file-directory))
5574               (setq filename (expand-file-name filename decode-dir)))
5575             (if (file-exists-p filename)
5576                 (or (yes-or-no-p (format "File %s exists. Save anyway? "
5577                                          filename))
5578                     (error "")))
5579             (elmo-bind-directory
5580              decode-dir
5581              (setq rc
5582                    (as-binary-process
5583                     (apply 'call-process-region (point-min) (point-max)
5584                            wl-prog-uudecode t (current-buffer) nil
5585                            wl-prog-uudecode-arg))))
5586             (when (not (= 0 rc))
5587               (setq errmsg (buffer-substring (point-min)(point-max)))
5588               (error "Uudecode error: %s" errmsg))
5589             (if (not wl-prog-uudecode-no-stdout-option)
5590                 (let (file-name-handler-alist) ;; void jka-compr
5591                   (as-binary-output-file
5592                    (write-region (point-min) (point-max)
5593                                  filename nil 'no-msg))))
5594             (save-excursion
5595               (set-buffer summary-buf)
5596               (wl-summary-delete-all-temp-marks))
5597             (if (file-exists-p filename)
5598                 (message "Saved as %s" filename)))
5599         (kill-buffer tmp-buf)))))
5600
5601 ;; Someday
5602 ;; (defun wl-summary-drop-unsync ()
5603 ;;   "Drop all unsync messages."
5604 ;;   (interactive)
5605 ;;   (if (elmo-folder-pipe-p (wl-summary-buffer-folder-name))
5606 ;;       (error "You cannot drop unsync messages in this folder"))
5607 ;;   (if (or (not (interactive-p))
5608 ;;        (y-or-n-p "Drop all unsync messages? "))
5609 ;;       (let* ((folder-list (elmo-folder-get-primitive-folder-list
5610 ;;                         (wl-summary-buffer-folder-name)))
5611 ;;           (is-multi (elmo-multi-p (wl-summary-buffer-folder-name)))
5612 ;;           (sum 0)
5613 ;;           (multi-num 0)
5614 ;;           pair)
5615 ;;      (message "Dropping...")
5616 ;;      (while folder-list
5617 ;;        (setq pair (elmo-folder-message-numbers (car folder-list)))
5618 ;;        (when is-multi ;; dirty hack...
5619 ;;          (incf multi-num)
5620 ;;          (setcar pair (+ (* multi-num elmo-multi-divide-number)
5621 ;;                          (car pair))))
5622 ;;        (elmo-msgdb-set-number-alist
5623 ;;         (wl-summary-buffer-msgdb)
5624 ;;         (nconc
5625 ;;          (elmo-msgdb-get-number-alist (wl-summary-buffer-msgdb))
5626 ;;          (list (cons (car pair) nil))))
5627 ;;        (setq sum (+ sum (cdr pair)))
5628 ;;        (setq folder-list (cdr folder-list)))
5629 ;;      (wl-summary-set-message-modified)
5630 ;;      (wl-folder-set-folder-updated (wl-summary-buffer-folder-name)
5631 ;;                                    (list 0
5632 ;;                                          (+ wl-summary-buffer-unread-count
5633 ;;                                             wl-summary-buffer-new-count)
5634 ;;                                          sum))
5635 ;;      (message "Dropping...done"))))
5636
5637 (defun wl-summary-default-get-next-msg (msg)
5638   (or (wl-summary-next-message msg
5639                                (if wl-summary-move-direction-downward 'down
5640                                  'up)
5641                                nil)
5642       (cadr (memq msg (if wl-summary-move-direction-downward
5643                           wl-summary-buffer-number-list
5644                         (reverse wl-summary-buffer-number-list))))))
5645
5646 (defun wl-summary-save-current-message ()
5647   "Save current message for `wl-summary-yank-saved-message'."
5648   (interactive)
5649   (let ((number (wl-summary-message-number)))
5650     (setq wl-summary-buffer-saved-message number)
5651     (and number (message "No: %s is saved." number))))
5652
5653 (defun wl-summary-yank-saved-message ()
5654   "Set current message as a parent of the saved message."
5655   (interactive)
5656   (if wl-summary-buffer-saved-message
5657       (let ((number (wl-summary-message-number)))
5658         (if (eq wl-summary-buffer-saved-message number)
5659             (message "Cannot set itself as a parent.")
5660           (save-excursion
5661             (wl-thread-jump-to-msg wl-summary-buffer-saved-message)
5662             (wl-thread-set-parent number)
5663             (wl-summary-set-thread-modified))
5664           (setq  wl-summary-buffer-saved-message nil)))
5665     (message "There's no saved message.")))
5666
5667 (require 'product)
5668 (product-provide (provide 'wl-summary) (require 'wl-version))
5669
5670 ;;; wl-summary.el ends here