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