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