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