(wl-summary-jump-to-msg): Don't interactive input
[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 Message (No.): ")
2142   (when number
2143     (let ((pos (point))
2144           regexp)
2145       (setq regexp (concat "\r" (int-to-string number) "[^0-9]"))
2146       (if (and beg end (or (< pos beg) (< end pos)))
2147           (progn
2148             (goto-char beg)
2149             (if (re-search-forward regexp end t)
2150                 (progn (backward-char 1) (beginning-of-line) t)
2151               (goto-char pos)
2152               nil))
2153         (beginning-of-line)
2154         (if (or (and (re-search-forward regexp end t)
2155                      (progn (backward-char 1) t))
2156                 (re-search-backward regexp beg t))
2157             (progn (beginning-of-line) t)
2158           nil)))))
2159
2160 (defun wl-summary-highlight-msgs (msgs)
2161   (save-excursion
2162     (let ((len (length msgs))
2163           i)
2164       (message "Hilighting...")
2165       (setq i 0)
2166       (while msgs
2167         (if (wl-summary-jump-to-msg (car msgs))
2168             (wl-highlight-summary-current-line))
2169         (setq msgs (cdr msgs))
2170         (when (> len elmo-display-progress-threshold)
2171           (setq i (+ i 1))
2172           (if (or (zerop (% i 5)) (= i len))
2173               (elmo-display-progress
2174                'wl-summary-highlight-msgs "Highlighting..."
2175                (/ (* i 100) len)))))
2176       (message "Highlighting...done"))))
2177
2178 (defun wl-summary-message-number ()
2179   (save-excursion
2180     (beginning-of-line)
2181     (if (or (re-search-forward "\r\\(-?[0-9]+\\)" (point-at-eol) t)
2182             (re-search-forward "^ *\\(-?[0-9]+\\)" (point-at-eol) t))
2183         (string-to-int (wl-match-buffer 1))
2184       nil)))
2185
2186 (defun wl-summary-delete-all-msgs ()
2187   (interactive)
2188   (let ((cur-buf (current-buffer))
2189         (dels (elmo-folder-list-messages wl-summary-buffer-elmo-folder)))
2190     (set-buffer cur-buf)
2191     (if (null dels)
2192         (message "No message to delete.")
2193       (if (y-or-n-p (format "%s has %d message(s).  Delete all? "
2194                             (wl-summary-buffer-folder-name)
2195                             (length dels)))
2196           (progn
2197             (message "Deleting...")
2198             (elmo-folder-move-messages wl-summary-buffer-elmo-folder dels
2199                                        'null)
2200             (wl-summary-set-message-modified)
2201             (wl-folder-set-folder-updated (wl-summary-buffer-folder-name)
2202                                           (list 0 0 0))
2203 ;;; for thread.
2204 ;;;         (setq wl-thread-top-entity '(nil t nil nil))
2205             (setq wl-summary-buffer-unread-count 0)
2206             (setq wl-summary-buffer-new-count    0)
2207             (wl-summary-update-modeline)
2208             (set-buffer cur-buf)
2209             (let ((inhibit-read-only t)
2210                   (buffer-read-only nil))
2211               (erase-buffer))
2212 ;;;         (if wl-summary-cache-use (wl-summary-save-view-cache))
2213             (message "Deleting...done")
2214             t)
2215         nil))))
2216
2217 (defun wl-summary-toggle-thread (&optional arg)
2218   "Toggle thread status (T)hread and (S)equential.
2219 If ARG, without confirm."
2220   (interactive "P")
2221   (when (or arg
2222             (y-or-n-p (format "Toggle threading? (y=%s): "
2223                               (if (eq wl-summary-buffer-view 'thread)
2224                                   "\"off\"" "\"on\""))))
2225     (if (eq wl-summary-buffer-view 'thread)
2226         (setq wl-summary-buffer-view 'sequence)
2227       (setq wl-summary-buffer-view 'thread))
2228     (wl-summary-update-modeline)
2229     (force-mode-line-update)
2230     (wl-summary-rescan nil nil nil t)))
2231
2232 (defun wl-summary-load-file-object (filename)
2233   "Load lisp object from dir."
2234   (with-temp-buffer
2235     (let (insert-file-contents-pre-hook ; To avoid autoconv-xmas...
2236           insert-file-contents-post-hook
2237           ret-val)
2238       (if (not (file-readable-p filename))
2239           ()
2240         (as-binary-input-file (insert-file-contents filename))
2241         (condition-case nil
2242             (read (current-buffer))
2243           (error (error "Reading failed")))))))
2244
2245 (defun wl-summary-goto-folder (&optional arg)
2246   (interactive "P")
2247   (wl-summary-goto-folder-subr nil nil nil nil t nil arg))
2248
2249 (defun wl-summary-goto-folder-sticky ()
2250   (interactive)
2251   (wl-summary-goto-folder-subr nil nil nil t t))
2252
2253 (defun wl-summary-goto-last-visited-folder ()
2254   (interactive)
2255   (let ((entity
2256          (wl-folder-search-entity-by-name wl-summary-last-visited-folder
2257                                           wl-folder-entity
2258                                           'folder)))
2259     (if entity (wl-folder-set-current-entity-id
2260                 (wl-folder-get-entity-id entity))))
2261   (wl-summary-goto-folder-subr wl-summary-last-visited-folder nil nil nil t))
2262
2263 (defun wl-summary-sticky-p (&optional folder)
2264   (if folder
2265       (get-buffer (wl-summary-sticky-buffer-name
2266                    (elmo-folder-name-internal folder)))
2267     (not (string= wl-summary-buffer-name (buffer-name)))))
2268
2269 (defun wl-summary-always-sticky-folder-p (folder)
2270   (or (eq t wl-summary-always-sticky-folder-list)
2271       (wl-string-match-member
2272        (elmo-folder-name-internal folder)
2273        wl-summary-always-sticky-folder-list)))
2274
2275 (defun wl-summary-stick (&optional force)
2276   "Make current summary buffer sticky."
2277   (interactive "P")
2278   (if (wl-summary-sticky-p)
2279       (message "Current summary buffer is already sticky.")
2280     (when (or force (y-or-n-p "Stick current summary buffer? "))
2281       (wl-summary-toggle-disp-msg 'off)
2282       (wl-summary-switch-to-clone-buffer
2283        (wl-summary-sticky-buffer-name
2284         (wl-summary-buffer-folder-name)))
2285 ;;; ???hang up
2286 ;;;   (rename-buffer (wl-summary-sticky-buffer-name
2287 ;;;                   (wl-summary-buffer-folder-name))))
2288       (message "Folder `%s' is now sticky." (wl-summary-buffer-folder-name)))))
2289
2290 (defun wl-summary-switch-to-clone-buffer (buffer-name)
2291   (let ((cur-buf (current-buffer))
2292         (msg (wl-summary-message-number))
2293         (buf (get-buffer-create buffer-name))
2294         (folder wl-summary-buffer-elmo-folder)
2295         (copy-variables
2296          (append '(wl-summary-buffer-view
2297                    wl-summary-buffer-temp-mark-list
2298                    wl-summary-buffer-target-mark-list
2299                    wl-summary-buffer-elmo-folder
2300                    wl-summary-buffer-number-column
2301                    wl-summary-buffer-temp-mark-column
2302                    wl-summary-buffer-persistent-mark-column
2303                    wl-summary-buffer-message-modified
2304                    wl-summary-buffer-thread-modified
2305                    wl-summary-buffer-number-list
2306                    wl-summary-buffer-persistent-mark-version
2307                    wl-summary-buffer-folder-name
2308                    wl-summary-buffer-line-formatter)
2309                  (and (eq wl-summary-buffer-view 'thread)
2310                       '(wl-thread-entity-hashtb
2311                         wl-thread-entities
2312                         wl-thread-entity-list))
2313                  (and wl-use-scoring
2314                       '(wl-summary-scored
2315                         wl-summary-default-score
2316                         wl-summary-important-above
2317                         wl-summary-target-above
2318                         wl-summary-mark-below
2319                         wl-summary-expunge-below))
2320                  (and (featurep 'wl-score)
2321                       '(wl-current-score-file
2322                         wl-score-alist)))))
2323     (set-buffer buf)
2324     (wl-summary-mode)
2325     (wl-summary-buffer-set-folder folder)
2326     (let ((buffer-read-only nil))
2327       (insert-buffer cur-buf))
2328     (set-buffer-modified-p nil)
2329     (while copy-variables
2330       (set (car copy-variables)
2331            (save-excursion
2332              (set-buffer cur-buf)
2333              (symbol-value (car copy-variables))))
2334       (setq copy-variables (cdr copy-variables)))
2335     (switch-to-buffer buf)
2336     (kill-buffer cur-buf)
2337     (wl-summary-count-unread)
2338     (wl-summary-update-modeline)
2339     (if msg
2340         (if (eq wl-summary-buffer-view 'thread)
2341             (wl-thread-jump-to-msg msg)
2342           (wl-summary-jump-to-msg msg))
2343       (goto-char (point-max))
2344       (beginning-of-line))))
2345
2346 (defun wl-summary-get-buffer (folder)
2347   (or (and folder
2348            (get-buffer (wl-summary-sticky-buffer-name folder)))
2349       (get-buffer wl-summary-buffer-name)))
2350
2351 (defun wl-summary-get-buffer-create (name &optional force-sticky)
2352   (if force-sticky
2353       (get-buffer-create
2354        (wl-summary-sticky-buffer-name name))
2355     (or (get-buffer (wl-summary-sticky-buffer-name name))
2356         (get-buffer-create wl-summary-buffer-name))))
2357
2358 (defun wl-summary-make-number-list ()
2359   (save-excursion
2360     (goto-char (point-min))
2361     (setq wl-summary-buffer-number-list nil)
2362     (while (not (eobp))
2363       (setq wl-summary-buffer-number-list
2364             (cons (wl-summary-message-number)
2365                   wl-summary-buffer-number-list))
2366       (forward-line 1))
2367     (setq wl-summary-buffer-number-list
2368           (nreverse wl-summary-buffer-number-list))))
2369
2370 (defun wl-summary-auto-select-msg-p (unread-msg)
2371   (and unread-msg
2372        (not (elmo-message-has-global-flag-p
2373              wl-summary-buffer-elmo-folder unread-msg))))
2374
2375 (defsubst wl-summary-open-folder (folder)
2376   ;; Select folder
2377   (let ((elmo-mime-charset wl-summary-buffer-mime-charset))
2378     (unwind-protect
2379         (elmo-folder-open folder 'load-msgdb)
2380       ;; For compatibility
2381       (setq wl-summary-buffer-folder-name (elmo-folder-name-internal
2382                                            folder)))))
2383
2384 (defun wl-summary-goto-folder-subr (&optional name scan-type other-window
2385                                               sticky interactive scoring
2386                                               force-exit)
2387   "Display target folder on summary."
2388   (interactive)
2389   (let* ((keep-cursor (memq this-command
2390                             wl-summary-keep-cursor-command))
2391          (name (or name (wl-summary-read-folder wl-default-folder)))
2392          (cur-fld wl-summary-buffer-elmo-folder)
2393          folder buf mes hilit reuse-buf
2394          retval entity)
2395     (if (string= name "")
2396         (setq name wl-default-folder))
2397     (setq folder (wl-folder-get-elmo-folder name))
2398     (when (and (not (string=
2399                      (and cur-fld (elmo-folder-name-internal cur-fld))
2400                      (elmo-folder-name-internal folder))) ; folder is moved.
2401                (eq major-mode 'wl-summary-mode)) ; called in summary.
2402       (setq wl-summary-last-visited-folder (wl-summary-buffer-folder-name))
2403       (run-hooks 'wl-summary-exit-pre-hook)
2404       (if (or force-exit (not (wl-summary-sticky-p)))
2405           (wl-summary-cleanup-temp-marks))
2406       (wl-summary-save-view)
2407       (elmo-folder-commit wl-summary-buffer-elmo-folder)
2408       (if (and (wl-summary-sticky-p) force-exit)
2409           (kill-buffer (current-buffer))))
2410     (setq buf (wl-summary-get-buffer-create (elmo-folder-name-internal folder)
2411                                             sticky))
2412     (setq reuse-buf
2413           (save-excursion
2414             (set-buffer buf)
2415             (string= (elmo-folder-name-internal folder)
2416                      (wl-summary-buffer-folder-name))))
2417     (unwind-protect
2418         (if reuse-buf
2419             (if interactive
2420                 (switch-to-buffer buf)
2421               (set-buffer buf))
2422           (if other-window
2423               (delete-other-windows))
2424           (set-buffer buf)
2425           (unless (eq major-mode 'wl-summary-mode)
2426             (wl-summary-mode))
2427           (wl-summary-buffer-set-folder folder)
2428           (setq wl-summary-buffer-display-mime-mode
2429                 (if (wl-summary-no-mime-p wl-summary-buffer-elmo-folder)
2430                     'as-is
2431                   'mime))
2432           (setq wl-summary-buffer-disp-msg nil)
2433           (setq wl-summary-buffer-last-displayed-msg nil)
2434           (setq wl-summary-buffer-current-msg nil)
2435           (setq wl-summary-buffer-persistent-mark-version 0)
2436           (let ((inhibit-read-only t)
2437                 (buffer-read-only nil))
2438             (erase-buffer)
2439             ;; Resume summary view
2440             (if wl-summary-cache-use
2441                 (let* ((dir (elmo-folder-msgdb-path folder))
2442                        (cache (expand-file-name wl-summary-cache-file dir))
2443                        (view (expand-file-name wl-summary-view-file dir)))
2444                   (when (file-exists-p cache)
2445                     (insert-file-contents-as-binary cache)
2446                     (set-buffer-multibyte
2447                      default-enable-multibyte-characters)
2448                     (decode-mime-charset-region
2449                      (point-min)(point-max)
2450                      wl-summary-buffer-mime-charset 'LF))
2451                   (if (file-exists-p view)
2452                       (setq wl-summary-buffer-view
2453                             (wl-summary-load-file-object view))
2454                     (setq wl-summary-buffer-view
2455                           (or (wl-get-assoc-list-value
2456                                wl-summary-default-view-alist
2457                                (elmo-folder-name-internal folder))
2458                               wl-summary-default-view)))
2459                   (wl-thread-resume-entity folder)
2460                   (wl-summary-open-folder folder)
2461                   (wl-summary-detect-mark-position))
2462               (setq wl-summary-buffer-view
2463                     (wl-summary-load-file-object
2464                      (expand-file-name wl-summary-view-file
2465                                        (elmo-folder-msgdb-path folder))))
2466               (wl-summary-open-folder folder)
2467               (wl-summary-detect-mark-position)
2468               (wl-summary-rescan))
2469             (wl-summary-count-unread)
2470             (wl-summary-update-modeline)))
2471       (unless (eq wl-summary-buffer-view 'thread)
2472         (wl-summary-make-number-list))
2473       (when (and wl-summary-cache-use
2474                  (or (and wl-summary-check-line-format
2475                           (wl-summary-line-format-changed-p))
2476                      (wl-summary-view-old-p)))
2477         (wl-summary-rescan))
2478       (wl-summary-toggle-disp-msg (if wl-summary-buffer-disp-msg 'on 'off))
2479       (unless (and reuse-buf keep-cursor)
2480         (unwind-protect
2481             (let ((wl-use-scoring
2482                    (if (or scoring interactive) wl-use-scoring)))
2483               (if (and (not scan-type)
2484                        interactive
2485                        (not wl-ask-range))
2486                   (setq scan-type (wl-summary-get-sync-range folder)))
2487               (cond
2488                ((eq scan-type nil)
2489                 (wl-summary-sync 'unset-cursor))
2490                ((eq scan-type 'all)
2491                 (wl-summary-sync 'unset-cursor "all"))
2492                ((eq scan-type 'no-sync))
2493                ((eq scan-type 'rescan)
2494                 (wl-summary-rescan))
2495                ((or (eq scan-type 'force-update)
2496                     (eq scan-type 'update))
2497                 (setq mes (wl-summary-sync-force-update
2498                            'unset-cursor)))))
2499           (if interactive
2500               (switch-to-buffer buf)
2501             (set-buffer buf))
2502           ;; stick always-sticky-folder
2503           (when (wl-summary-always-sticky-folder-p folder)
2504             (or (wl-summary-sticky-p) (wl-summary-stick t)))
2505           (run-hooks 'wl-summary-prepared-pre-hook)
2506           (set-buffer-modified-p nil)
2507           (goto-char (point-min))
2508           (if (wl-summary-cursor-down t)
2509               (let ((unreadp (wl-summary-next-message
2510                               (wl-summary-message-number)
2511                               'down t)))
2512                 (cond ((and wl-auto-select-first
2513                             (wl-summary-auto-select-msg-p unreadp))
2514                        ;; wl-auto-select-first is non-nil and
2515                        ;; unreadp is non-nil but not flagged
2516                        (setq retval 'disp-msg))
2517                       ((and wl-auto-prefetch-first
2518                             (wl-summary-auto-select-msg-p unreadp))
2519                        ;; wl-auto-select-first is non-nil and
2520                        ;; unreadp is non-nil but not flagged
2521                        (setq retval 'prefetch-msg))
2522                       ((not (wl-summary-auto-select-msg-p unreadp))
2523                        ;; unreadp is nil or flagged
2524                        (setq retval 'more-next))))
2525             (goto-char (point-max))
2526             (if (elmo-folder-plugged-p folder)
2527                 (forward-line -1)
2528               (wl-summary-prev))
2529             (setq retval 'more-next))
2530           (if (and wl-summary-highlight
2531                    (not wl-summary-lazy-highlight)
2532                    (not reuse-buf))
2533               (if (and wl-summary-highlight-partial-threshold
2534                        (> (count-lines (point-min) (point-max))
2535                           wl-summary-highlight-partial-threshold))
2536                   (save-excursion
2537                     (forward-line (-
2538                                    0
2539                                    (or
2540                                     wl-summary-partial-highlight-above-lines
2541                                     wl-summary-highlight-partial-threshold)))
2542                     (wl-highlight-summary (point) (point-max)))
2543                 (wl-highlight-summary (point-min) (point-max))))
2544           (if (eq retval 'disp-msg)
2545               (wl-summary-redisplay))
2546           (if (eq retval 'prefetch-msg)
2547               (wl-message-buffer-prefetch
2548                folder
2549                (wl-summary-message-number)
2550                (min (or wl-message-buffer-prefetch-depth 0)
2551                     (1- wl-message-buffer-cache-size))
2552                (current-buffer)
2553                wl-summary-buffer-mime-charset))
2554           (if mes (message "%s" mes))
2555           (if (and interactive wl-summary-recenter)
2556               (recenter (/ (- (window-height) 2) 2))))))
2557     ;; set current entity-id
2558     (when (and folder
2559                (setq entity
2560                      (wl-folder-search-entity-by-name
2561                       (elmo-folder-name-internal folder)
2562                       wl-folder-entity
2563                       'folder)))
2564       ;; entity-id is unknown.
2565       (wl-folder-set-current-entity-id
2566        (wl-folder-get-entity-id entity)))
2567     (when (and wl-summary-buffer-window-scroll-functions
2568                wl-on-xemacs)
2569       (sit-for 0))
2570     (when (or (eq t wl-summary-force-prefetch-folder-list)
2571               (wl-string-match-member
2572                (elmo-folder-name-internal wl-summary-buffer-elmo-folder)
2573                wl-summary-force-prefetch-folder-list))
2574       (wl-summary-force-prefetch))
2575     (unwind-protect
2576         (run-hooks 'wl-summary-prepared-hook)
2577       (set-buffer-modified-p nil))
2578     retval))
2579
2580 (defun wl-summary-goto-previous-message-beginning ()
2581   (end-of-line)
2582   (re-search-backward "\r\\(-?[0-9]+\\)" nil t)
2583   (beginning-of-line))
2584
2585 (defun wl-summary-goto-top-of-current-thread ()
2586   (wl-summary-jump-to-msg
2587    (wl-thread-entity-get-number
2588     (wl-thread-entity-get-top-entity (wl-thread-get-entity
2589                                       (wl-summary-message-number))))))
2590
2591 (defun wl-summary-goto-bottom-of-sub-thread (&optional depth)
2592   (interactive)
2593   (let ((depth (or depth
2594                    (wl-thread-get-depth-of-current-line))))
2595     (forward-line 1)
2596     (while (and (not (eobp))
2597                 (>= (wl-thread-get-depth-of-current-line)
2598                     depth))
2599       (forward-line 1))
2600     (beginning-of-line)))
2601
2602 (defun wl-summary-insert-line (line)
2603   "Insert LINE in the Summary."
2604   (if wl-use-highlight-mouse-line
2605       ;; remove 'mouse-face of current line.
2606       (put-text-property
2607        (save-excursion (beginning-of-line)(point))
2608        (save-excursion (end-of-line)(point))
2609        'mouse-face nil))
2610   (insert line "\n")
2611   (save-excursion
2612     (forward-line -1)
2613     (let* ((number (wl-summary-message-number))
2614            (mark-info (wl-summary-registered-temp-mark number)))
2615       (when (and mark-info (nth 2 mark-info))
2616         (wl-summary-print-argument number (nth 2 mark-info)))))
2617   (if wl-use-highlight-mouse-line
2618       ;; remove 'mouse-face of current line.
2619       (put-text-property
2620        (save-excursion (beginning-of-line)(point))
2621        (save-excursion (end-of-line)(point))
2622        'mouse-face nil))
2623   (ignore-errors
2624     (run-hooks 'wl-summary-line-inserted-hook)))
2625
2626 (defun wl-summary-insert-sequential (entity folder &rest args)
2627   (when entity
2628     (let ((inhibit-read-only t)
2629           (number (elmo-message-entity-number entity))
2630           buffer-read-only)
2631       (goto-char (point-max))
2632       (wl-summary-insert-line
2633        (wl-summary-create-line entity nil nil
2634                                (elmo-message-flags
2635                                 wl-summary-buffer-elmo-folder
2636                                 number)
2637                                (elmo-message-cached-p
2638                                 wl-summary-buffer-elmo-folder
2639                                 number)))
2640       (setq wl-summary-buffer-number-list
2641             (wl-append wl-summary-buffer-number-list
2642                        (list (elmo-message-entity-number entity))))
2643       nil)))
2644
2645 (defun wl-summary-default-subject-filter (subject)
2646   (setq subject (elmo-replace-in-string subject "[ \t]*\\(re\\|was\\)[:>]" ""))
2647   (setq subject (elmo-replace-in-string subject "[ \t]" ""))
2648   (elmo-replace-in-string subject "^\\[[^]]*\\]" ""))
2649
2650 (defun wl-summary-subject-equal (subject1 subject2)
2651   (string= (funcall wl-summary-subject-filter-function subject1)
2652            (funcall wl-summary-subject-filter-function subject2)))
2653
2654 (defmacro wl-summary-put-alike (alike)
2655   (` (elmo-set-hash-val (format "#%d" (wl-count-lines))
2656                         (, alike)
2657                         wl-summary-alike-hashtb)))
2658
2659 (defmacro wl-summary-get-alike ()
2660   (` (elmo-get-hash-val (format "#%d" (wl-count-lines))
2661                         wl-summary-alike-hashtb)))
2662
2663 (defun wl-summary-insert-headers (folder func mime-decode)
2664   (let ((numbers (elmo-folder-list-messages folder 'visible t))
2665         ov this last alike)
2666     (buffer-disable-undo (current-buffer))
2667     (make-local-variable 'wl-summary-alike-hashtb)
2668     (setq wl-summary-alike-hashtb (elmo-make-hash (* (length numbers) 2)))
2669     (when mime-decode
2670       (set-buffer-multibyte default-enable-multibyte-characters))
2671     (while (setq ov (elmo-message-entity folder (pop numbers)))
2672       (setq this (funcall func ov))
2673       (and this (setq this (std11-unfold-string this)))
2674       (if (equal last this)
2675           (setq alike (cons ov alike))
2676         (when last
2677           (wl-summary-put-alike alike)
2678           (insert last ?\n))
2679         (setq alike (list ov)
2680               last this)))
2681     (when last
2682       (wl-summary-put-alike alike)
2683       (insert last ?\n))
2684     (when mime-decode
2685       (decode-mime-charset-region (point-min) (point-max)
2686                                   elmo-mime-charset)
2687       (when (eq mime-decode 'mime)
2688         (eword-decode-region (point-min) (point-max))))
2689     (run-hooks 'wl-summary-insert-headers-hook)))
2690
2691 (defun wl-summary-search-by-subject (entity folder)
2692   (let ((summary-buf (current-buffer))
2693         (buf (get-buffer-create wl-summary-search-buf-name))
2694         (folder-name (wl-summary-buffer-folder-name))
2695         match founds result)
2696     (with-current-buffer buf
2697       (let ((case-fold-search t))
2698         (when (or (not (string= wl-summary-search-buf-folder-name folder-name))
2699                   (zerop (buffer-size)))
2700           (setq wl-summary-search-buf-folder-name folder-name)
2701           (message "Creating subject cache...")
2702           (wl-summary-insert-headers
2703            folder
2704            (function
2705             (lambda (x)
2706               (funcall wl-summary-subject-filter-function
2707                        (elmo-message-entity-field x 'subject))))
2708            t)
2709           (message "Creating subject cache...done"))
2710         (setq match (funcall wl-summary-subject-filter-function
2711                              (elmo-message-entity-field entity 'subject
2712                                                         'decode)))
2713         (if (string= match "")
2714             (setq match "\n"))
2715         (goto-char (point-max))
2716         (while (and (null result)
2717                     (not (= (point) (point-min)))
2718                     (search-backward match nil t))
2719           ;; check exactly match
2720           (when (and (bolp) (= (point-at-eol)(match-end 0)))
2721             (setq founds (wl-summary-get-alike))
2722             (with-current-buffer summary-buf
2723               (while founds
2724                 (when (and
2725                        ;; the first element of found-entity list exists on
2726                        ;; thread tree.
2727                        (wl-thread-get-entity
2728                         (elmo-message-entity-number (car founds)))
2729                        ;; message id is not same as myself.
2730                        (not (string=
2731                              (elmo-message-entity-field entity 'message-id)
2732                              (elmo-message-entity-field (car founds)
2733                                                         'message-id)))
2734                        ;; not a descendant.
2735                        (not (wl-thread-descendant-p
2736                              (elmo-message-entity-number entity)
2737                              (elmo-message-entity-number (car founds)))))
2738                   (setq result (car founds)
2739                         founds nil))
2740                 (setq founds (cdr founds))))))
2741         result))))
2742
2743 (defun wl-summary-insert-thread (entity folder update
2744                                         &optional force-insert)
2745   (let ((depth 0)
2746         this-id parent-entity parent-number
2747         number cur-entity linked retval delayed-entity
2748         update-list entity-stack thread-entity)
2749     (while entity
2750       (setq this-id (elmo-message-entity-field entity 'message-id)
2751             number (elmo-message-entity-number entity))
2752       (if (and wl-thread-saved-entity-hashtb-internal
2753                (setq thread-entity
2754                      (elmo-get-hash-val
2755                       (format "#%d" (elmo-message-entity-number entity))
2756                       wl-thread-saved-entity-hashtb-internal)))
2757           (setq parent-entity
2758                 (elmo-message-entity
2759                  folder
2760                  (wl-thread-entity-get-parent thread-entity))
2761                 linked (wl-thread-entity-get-linked thread-entity))
2762         (setq parent-entity (elmo-message-entity-parent folder entity)
2763               linked nil))
2764       (setq parent-number (and parent-entity
2765                                (elmo-message-entity-number parent-entity)))
2766       ;; If thread loop detected, set parent as nil.
2767       (let ((cur entity)
2768             anumber relatives)
2769         (while cur
2770           (when (setq anumber
2771                       (elmo-message-entity-number
2772                        (setq cur (elmo-message-entity-parent folder cur))))
2773             (if (memq anumber relatives)
2774                 (setq parent-number nil
2775                       cur nil))
2776             (setq relatives (cons anumber relatives)))))
2777       (if (and parent-number
2778                (not (wl-thread-get-entity parent-number))
2779                (not force-insert))
2780           ;; parent exists in overview, but not in wl-thread-entities
2781           (progn
2782             (wl-append wl-summary-delayed-update
2783                        (list (cons parent-number entity)))
2784             (setq entity nil)) ;; exit loop
2785         ;; Search parent by subject.
2786         (when (and (null parent-number)
2787                    wl-summary-search-parent-by-subject-regexp
2788                    (string-match
2789                     wl-summary-search-parent-by-subject-regexp
2790                     (elmo-message-entity-field entity 'subject)))
2791           (let ((found (wl-summary-search-by-subject entity folder)))
2792             (when (and found
2793                        (not (member found wl-summary-delayed-update)))
2794               (setq parent-entity found)
2795               (setq parent-number
2796                     (elmo-message-entity-number parent-entity))
2797               (setq linked t))))
2798         ;; If subject is change, divide thread.
2799         (if (and parent-number
2800                  wl-summary-divide-thread-when-subject-changed
2801                  (not (wl-summary-subject-equal
2802                        (or (elmo-message-entity-field entity
2803                                                       'subject t) "")
2804                        (or (elmo-message-entity-field parent-entity
2805                                                       'subject t) ""))))
2806             (setq parent-number nil))
2807         (setq retval
2808               (wl-thread-insert-message entity
2809                                         number parent-number update linked))
2810         (and retval
2811              (wl-append update-list (list retval)))
2812         (setq entity nil) ; exit loop
2813         (while (setq delayed-entity (assq number wl-summary-delayed-update))
2814           (setq wl-summary-delayed-update
2815                 (delq delayed-entity wl-summary-delayed-update))
2816           ;; update delayed message
2817           (wl-append entity-stack (list (cdr delayed-entity)))))
2818       (if (and (not entity)
2819                entity-stack)
2820           (setq entity (pop entity-stack))))
2821     update-list))
2822
2823 (defun wl-summary-update-thread (entity
2824                                  thr-entity
2825                                  parent-entity)
2826   (let* ((this-id (elmo-message-entity-field entity 'message-id))
2827          (overview-entity entity)
2828          (parent-id (elmo-message-entity-field parent-entity 'message-id))
2829          (number (elmo-message-entity-number entity))
2830          (parent-number (elmo-message-entity-number parent-entity))
2831          insert-line)
2832     (cond
2833      ((or (not parent-id)
2834           (string= this-id parent-id))
2835       (goto-char (point-max))
2836       (beginning-of-line)
2837       (setq insert-line t))
2838      ;; parent already exists in buffer.
2839      ((wl-summary-jump-to-msg parent-number)
2840       (wl-thread-goto-bottom-of-sub-thread)
2841       (setq insert-line t)))
2842     (when insert-line
2843       (let (buffer-read-only)
2844         (wl-summary-insert-line
2845          (wl-summary-create-line
2846           entity
2847           parent-entity
2848           nil
2849           (elmo-message-flags wl-summary-buffer-elmo-folder number)
2850           (elmo-message-cached-p wl-summary-buffer-elmo-folder number)
2851           (wl-thread-maybe-get-children-num number)
2852           (wl-thread-make-indent-string thr-entity)
2853           (wl-thread-entity-get-linked thr-entity)))))))
2854
2855 (defun wl-summary-target-mark-msgs (msgs)
2856   "Return the number of marked messages."
2857   (let ((i 0))
2858     (dolist (number msgs)
2859       (when (wl-summary-target-mark number)
2860         (setq i (1+ i))))
2861     i))
2862
2863 (defun wl-summary-pick (&optional from-list delete-marks)
2864   (interactive "i\nP")
2865   (save-excursion
2866     (let* ((messages (or from-list
2867                          (elmo-folder-list-messages
2868                           wl-summary-buffer-elmo-folder
2869                           'visible
2870                           'in-msgdb)
2871                          (error "No messages")))
2872            (condition (car (elmo-parse-search-condition
2873                             (wl-read-search-condition
2874                              wl-summary-pick-field-default))))
2875            (result (elmo-folder-search wl-summary-buffer-elmo-folder
2876                                        condition
2877                                        messages))
2878            num)
2879       (if delete-marks
2880           (let ((mlist wl-summary-buffer-target-mark-list))
2881             (while mlist
2882               (when (wl-summary-jump-to-msg (car mlist))
2883                 (wl-summary-unmark))
2884               (setq mlist (cdr mlist)))
2885             (setq wl-summary-buffer-target-mark-list nil)))
2886       (if (and result
2887                (setq num (wl-summary-target-mark-msgs result))
2888                (> num 0))
2889           (if (= num (length result))
2890               (message "%d message(s) are picked." num)
2891             (message "%d(%d) message(s) are picked." num
2892                      (- (length result) num)))
2893         (message "No message was picked.")))))
2894
2895 (defun wl-summary-unvirtual ()
2896   "Exit from current virtual folder."
2897   (interactive)
2898   (if (eq 'filter
2899           (elmo-folder-type-internal wl-summary-buffer-elmo-folder))
2900       (wl-summary-goto-folder-subr
2901        (elmo-folder-name-internal
2902         (elmo-filter-folder-target-internal
2903          wl-summary-buffer-elmo-folder))
2904        'update nil nil t)
2905     (error "This folder is not filtered")))
2906
2907 (defun wl-summary-virtual (&optional arg)
2908   "Goto virtual folder.
2909 If ARG, exit virtual folder."
2910   (interactive "P")
2911   (if arg
2912       (wl-summary-unvirtual)
2913     (wl-summary-goto-folder-subr (concat "/"
2914                                          (wl-read-search-condition
2915                                           wl-summary-pick-field-default)
2916                                          "/"
2917                                          (wl-summary-buffer-folder-name))
2918                                  'update nil nil t)
2919     (run-hooks 'wl-summary-virtual-hook)))
2920
2921 (defun wl-summary-delete-all-temp-marks (&optional no-msg force)
2922   "Erase all temp marks from buffer."
2923   (interactive)
2924   (when (or wl-summary-buffer-target-mark-list
2925             wl-summary-buffer-temp-mark-list
2926             wl-summary-scored)
2927     (save-excursion
2928       (goto-char (point-min))
2929       (unless no-msg
2930         (message "Unmarking..."))
2931       (while (not (eobp))
2932         (wl-summary-unset-mark nil nil force)
2933         (forward-line 1))
2934       (unless no-msg
2935         (message "Unmarking...done"))
2936       (setq wl-summary-buffer-target-mark-list nil)
2937       (setq wl-summary-buffer-temp-mark-list nil))))
2938
2939 (defsubst wl-summary-temp-mark (&optional number)
2940   "Return temp-mark string of current line."
2941   (let ((number (or number (wl-summary-message-number)))
2942         info)
2943     (or (and (wl-summary-have-target-mark-p number)
2944              "*")
2945         (and (setq info (wl-summary-registered-temp-mark number))
2946              (nth 1 info))
2947         (wl-summary-get-score-mark number)
2948         " ")))
2949
2950 (defun wl-summary-persistent-mark-invalid-p ()
2951   (not
2952    (equal
2953     ;; mey be nil.
2954     (get-text-property (point) 'wl-summary-persistent-mark-version)
2955     wl-summary-buffer-persistent-mark-version)))
2956
2957 (defun wl-summary-validate-persistent-mark (beg end)
2958   (let ((inhibit-read-only t)
2959         (buffer-read-only nil))
2960     (put-text-property beg end
2961                        'wl-summary-persistent-mark-version
2962                        wl-summary-buffer-persistent-mark-version)
2963     (set-buffer-modified-p nil)))
2964
2965 (defun wl-summary-validate-persistent-mark-string (string)
2966   (put-text-property 0 (length string)
2967                      'wl-summary-persistent-mark-version
2968                      wl-summary-buffer-persistent-mark-version
2969                      string))
2970
2971 (defun wl-summary-invalidate-persistent-mark ()
2972   (setq wl-summary-buffer-persistent-mark-version
2973         (1+ wl-summary-buffer-persistent-mark-version)))
2974
2975 (defsubst wl-summary-persistent-mark-string (folder flags cached)
2976   "Return the persistent mark string.
2977 The mark is decided according to the FOLDER, FLAGS and CACHED."
2978   (let ((priorities wl-summary-persistent-mark-priority-list)
2979         mark)
2980     (while (and (null mark) priorities)
2981       (if (and (eq (car priorities) 'flag)
2982                (elmo-get-global-flags flags 'ignore-preserved))
2983           (let ((specs wl-summary-flag-alist)
2984                 spec)
2985             (while (setq spec (car specs))
2986               (if (memq (car spec) flags)
2987                   (setq mark (or (nth 2 spec) wl-summary-flag-mark)
2988                         specs nil)
2989                 (setq specs (cdr specs))))
2990             (unless mark
2991               (setq mark wl-summary-flag-mark)))
2992         (when (memq (car priorities) flags)
2993           (setq mark
2994                 (let ((var
2995                        (intern
2996                         (if cached
2997                             (format
2998                              "wl-summary-%s-cached-mark" (car priorities))
2999                           (format
3000                            "wl-summary-%s-uncached-mark" (car priorities))))))
3001                   (if (and (boundp var)
3002                            (symbol-value var))
3003                       (symbol-value var)
3004                     (if cached
3005                         (downcase (substring (symbol-name (car priorities))
3006                                              0 1))
3007                       (upcase (substring (symbol-name (car priorities))
3008                                          0 1))))))))
3009       (setq priorities (cdr priorities)))
3010     (or mark
3011         (if (or cached (elmo-folder-local-p folder))
3012             nil
3013           wl-summary-uncached-mark))))
3014
3015 (defsubst wl-summary-message-mark (folder number &optional flags)
3016   "Return mark of the message."
3017   (ignore-errors
3018     (wl-summary-persistent-mark-string
3019      folder
3020      (or flags (setq flags (elmo-message-flags folder number)))
3021      (memq 'cached flags) ; XXX for speed-up.
3022      )))
3023
3024 (defsubst wl-summary-persistent-mark (&optional number flags)
3025   "Return persistent-mark string of current line."
3026   (or (wl-summary-message-mark wl-summary-buffer-elmo-folder
3027                                (or number (wl-summary-message-number))
3028                                flags)
3029       " "))
3030
3031 (defun wl-summary-put-temp-mark (mark)
3032   "Put temp MARK on current line."
3033   (when wl-summary-buffer-temp-mark-column
3034     (save-excursion
3035       (beginning-of-line)
3036       (let ((inhibit-read-only t)
3037             (buffer-read-only nil))
3038         (move-to-column wl-summary-buffer-temp-mark-column)
3039         (delete-backward-char 1)
3040         (insert mark)))))
3041
3042 (defun wl-summary-next-buffer ()
3043   "Switch to next summary buffer."
3044   (interactive)
3045   (let ((buffers (sort (wl-collect-summary)
3046                        (lambda (buffer1 buffer2)
3047                          (string-lessp (buffer-name buffer1)
3048                                        (buffer-name buffer2))))))
3049     (switch-to-buffer
3050      (or (cadr (memq (current-buffer) buffers))
3051          (car buffers)))))
3052
3053 (defun wl-summary-previous-buffer ()
3054   "Switch to previous summary buffer."
3055   (interactive)
3056   (let ((buffers (sort (wl-collect-summary)
3057                        (lambda (buffer1 buffer2)
3058                          (not (string-lessp (buffer-name buffer1)
3059                                             (buffer-name buffer2)))))))
3060     (switch-to-buffer
3061      (or (cadr (memq (current-buffer) buffers))
3062          (car buffers)))))
3063
3064 (defun wl-summary-check-target-mark ()
3065   (when (null wl-summary-buffer-target-mark-list)
3066     (error "No marked message")))
3067
3068 (defun wl-summary-target-mark-mark-as-read ()
3069   (interactive)
3070   (wl-summary-check-target-mark)
3071   (save-excursion
3072     (goto-char (point-min))
3073     (let ((inhibit-read-only t)
3074           (buffer-read-only nil)
3075           wl-summary-buffer-disp-msg)
3076       (wl-summary-mark-as-read wl-summary-buffer-target-mark-list)
3077       (dolist (number wl-summary-buffer-target-mark-list)
3078         (wl-summary-unset-mark number)))))
3079
3080 (defun wl-summary-target-mark-mark-as-unread ()
3081   (interactive)
3082   (wl-summary-check-target-mark)
3083   (save-excursion
3084     (goto-char (point-min))
3085     (let ((inhibit-read-only t)
3086           (buffer-read-only nil)
3087           wl-summary-buffer-disp-msg)
3088       (wl-summary-mark-as-unread wl-summary-buffer-target-mark-list)
3089       (dolist (number wl-summary-buffer-target-mark-list)
3090         (wl-summary-unset-mark number)))))
3091
3092 (defun wl-summary-target-mark-operation (flag &optional inverse)
3093   (wl-summary-check-target-mark)
3094   (save-excursion
3095     (let ((inhibit-read-only t)
3096           (buffer-read-only nil)
3097           wl-summary-buffer-disp-msg)
3098       (funcall
3099        (intern (format "wl-summary-mark-as-%s-internal" flag))
3100        inverse
3101        wl-summary-buffer-target-mark-list)
3102       (wl-summary-delete-all-target-marks))))
3103
3104 (defun wl-summary-target-mark-mark-as-important (&optional remove)
3105   (interactive "P")
3106   (wl-summary-target-mark-operation 'important remove))
3107
3108 (defun wl-summary-target-mark-mark-as-answered (&optional remove)
3109   (interactive "P")
3110   (wl-summary-target-mark-operation 'answered remove))
3111
3112 (defun wl-summary-target-mark-set-flags (&optional remove)
3113   (interactive "P")
3114   (wl-summary-check-target-mark)
3115   (save-excursion
3116     (let ((inhibit-read-only t)
3117           (buffer-read-only nil)
3118           wl-summary-buffer-disp-msg)
3119       (wl-summary-set-flags-internal wl-summary-buffer-target-mark-list
3120                                      nil nil remove)
3121       (wl-summary-delete-all-target-marks)
3122       (wl-summary-count-unread)
3123       (wl-summary-update-modeline))))
3124
3125 (defun wl-summary-target-mark-save ()
3126   (interactive)
3127   (wl-summary-check-target-mark)
3128   (let ((wl-save-dir
3129          (wl-read-directory-name "Save to directory: "
3130                                  wl-temporary-file-directory))
3131         number)
3132     (if (null (file-exists-p wl-save-dir))
3133         (make-directory wl-save-dir))
3134     (while (setq number (car wl-summary-buffer-target-mark-list))
3135       (wl-thread-jump-to-msg number)
3136       (wl-summary-save t wl-save-dir)
3137       (wl-summary-unmark))))
3138
3139 (defun wl-summary-target-mark-pick ()
3140   (interactive)
3141   (wl-summary-check-target-mark)
3142   (wl-summary-pick wl-summary-buffer-target-mark-list 'delete))
3143
3144 (defun wl-summary-update-persistent-mark (&optional number flags)
3145   "Synch up persistent mark of current line with msgdb's.
3146 Return non-nil if the mark is updated"
3147   (interactive)
3148   (prog1
3149       (when wl-summary-buffer-persistent-mark-column
3150         (save-excursion
3151           (move-to-column wl-summary-buffer-persistent-mark-column)
3152           (let ((inhibit-read-only t)
3153                 (buffer-read-only nil)
3154                 (mark (buffer-substring (- (point) 1) (point)))
3155                 (new-mark (wl-summary-persistent-mark number flags)))
3156             (prog1
3157                 (unless (string= new-mark mark)
3158                   (delete-backward-char 1)
3159                   (insert new-mark)
3160                   (wl-summary-set-message-modified)
3161                   t)
3162               (wl-summary-validate-persistent-mark (point-at-bol)
3163                                                    (point-at-eol))))))
3164     (when wl-summary-highlight
3165       (wl-highlight-summary-current-line))
3166     (set-buffer-modified-p nil)))
3167
3168 (defsubst wl-summary-mark-as-read-internal (inverse
3169                                             number-or-numbers
3170                                             no-folder-mark
3171                                             no-modeline-update)
3172   (save-excursion
3173     (let ((folder wl-summary-buffer-elmo-folder)
3174           unread-message number
3175           number-list)
3176       (setq number-list (cond ((numberp number-or-numbers)
3177                                (setq unread-message
3178                                      (elmo-message-flagged-p
3179                                       folder
3180                                       number-or-numbers
3181                                       'unread))
3182                                (list number-or-numbers))
3183                               ((and (not (null number-or-numbers))
3184                                     (listp number-or-numbers))
3185                                number-or-numbers)
3186                               ((setq number (wl-summary-message-number))
3187                                ;; interactive
3188                                (setq unread-message
3189                                      (elmo-message-flagged-p
3190                                       folder
3191                                       number
3192                                       'unread))
3193                                (list number))))
3194       (if (null number-list)
3195           (message "No message.")
3196         (if inverse
3197             (elmo-folder-set-flag folder number-list 'unread no-folder-mark)
3198           (elmo-folder-unset-flag folder number-list 'unread no-folder-mark))
3199         (when (and unread-message
3200                    (not inverse))
3201           (dolist (number number-list)
3202             (wl-summary-jump-to-msg number)
3203             (run-hooks 'wl-summary-unread-message-hook)))
3204         (unless no-modeline-update
3205           ;; Update unread numbers.
3206           (wl-summary-count-unread)
3207           (wl-summary-update-modeline)
3208           (wl-folder-update-unread
3209            (wl-summary-buffer-folder-name)
3210            wl-summary-buffer-unread-count))))))
3211
3212 (defun wl-summary-mark-as-read (&optional number-or-numbers
3213                                           no-folder-mark
3214                                           no-modeline-update)
3215   (interactive)
3216   (wl-summary-mark-as-read-internal nil
3217                                     number-or-numbers
3218                                     no-folder-mark
3219                                     no-modeline-update))
3220
3221 (defun wl-summary-mark-as-unread (&optional number-or-numbers
3222                                             no-folder-mark
3223                                             no-modeline-update)
3224   (interactive)
3225   (wl-summary-mark-as-read-internal 'inverse
3226                                     number-or-numbers
3227                                     no-folder-mark
3228                                     no-modeline-update))
3229
3230 (defsubst wl-summary-set-persistent-mark-internal (inverse
3231                                                    flag
3232                                                    &optional number-or-numbers
3233                                                    no-modeline-update
3234                                                    no-server
3235                                                    interactive)
3236   "Set persistent mark."
3237   (save-excursion
3238     (let ((folder wl-summary-buffer-elmo-folder)
3239           number number-list)
3240       (setq number-list (cond ((numberp number-or-numbers)
3241                                (list number-or-numbers))
3242                               ((and (not (null number-or-numbers))
3243                                     (listp number-or-numbers))
3244                                number-or-numbers)
3245                               ((setq number (wl-summary-message-number))
3246                                ;; interactive
3247                                (list number))))
3248       (if (null number-list)
3249           (message "No message.")
3250         ;; XXX Only the first element of the list is checked.
3251         (if (elmo-message-flag-available-p folder (car number-list) flag)
3252             (progn
3253               (if inverse
3254                   (elmo-folder-unset-flag folder number-list flag no-server)
3255                 (elmo-folder-set-flag folder number-list flag no-server))
3256               (unless no-modeline-update
3257                 ;; Update unread numbers.
3258                 ;; should elmo-flag-mark-as-read return unread numbers?
3259                 (wl-summary-count-unread)
3260                 (wl-summary-update-modeline)
3261                 (wl-folder-update-unread
3262                  (wl-summary-buffer-folder-name)
3263                  wl-summary-buffer-unread-count)))
3264           (if interactive
3265               (error "Flag `%s' is not available in this folder" flag)))))))
3266
3267 (defun wl-summary-unset-persistent-mark (&optional flag
3268                                                    number-or-numbers
3269                                                    no-modeline-update
3270                                                    no-server)
3271   "Unset persistent mark."
3272   (interactive)
3273   (when (interactive-p)
3274     (let ((completion-ignore-case t))
3275       (setq flag (intern (downcase
3276                           (completing-read
3277                            "Mark name: "
3278                            (mapcar (lambda (flag)
3279                                      (list (capitalize (symbol-name flag))))
3280                                    (wl-summary-get-available-flags))
3281                            nil
3282                            'require-match))))))
3283   (wl-summary-set-persistent-mark-internal 'inverse
3284                                            flag
3285                                            number-or-numbers
3286                                            no-modeline-update
3287                                            no-server
3288                                            (interactive-p)))
3289
3290 (defun wl-summary-set-persistent-mark (&optional flag
3291                                                  number-or-numbers
3292                                                  no-modeline-update
3293                                                  no-server)
3294   "Set persistent mark."
3295   (interactive)
3296   (when (interactive-p)
3297     (let ((completion-ignore-case t))
3298       (setq flag (intern (downcase
3299                           (completing-read
3300                            "Mark name: "
3301                            (mapcar (lambda (flag)
3302                                      (list (capitalize (symbol-name flag))))
3303                                    (wl-summary-get-available-flags))
3304                            nil
3305                            'require-match))))))
3306   (wl-summary-set-persistent-mark-internal nil
3307                                            flag
3308                                            number-or-numbers
3309                                            no-modeline-update
3310                                            no-server
3311                                            (interactive-p)))
3312
3313 (defun wl-summary-toggle-persistent-mark (&optional force)
3314   "Toggle persistent mark."
3315   (interactive "P")
3316   (let ((completion-ignore-case t)
3317         flag)
3318     (setq flag (intern (downcase
3319                         (completing-read
3320                          "Mark name: "
3321                          (mapcar (lambda (flag)
3322                                    (list (capitalize (symbol-name flag))))
3323                                  (wl-summary-get-available-flags))
3324                          nil
3325                          'require-match))))
3326     (if (and (elmo-message-flagged-p wl-summary-buffer-elmo-folder
3327                                      (wl-summary-message-number)
3328                                      flag)
3329              (not force))
3330         (wl-summary-unset-persistent-mark flag)
3331       (wl-summary-set-persistent-mark flag))))
3332
3333 (defun wl-summary-mark-as-answered (&optional number-or-numbers
3334                                               no-modeline-update)
3335   (interactive)
3336   (wl-summary-set-persistent-mark-internal
3337    (and (interactive-p)
3338         (elmo-message-flagged-p wl-summary-buffer-elmo-folder
3339                                 (wl-summary-message-number)
3340                                 'answered))
3341    'answered
3342    number-or-numbers
3343    no-modeline-update
3344    nil
3345    (interactive-p)))
3346
3347 (defun wl-summary-mark-as-unanswered (&optional number-or-numbers
3348                                                 no-modeline-update)
3349   (wl-summary-set-persistent-mark-internal
3350    'inverse
3351    'answered
3352    number-or-numbers
3353    no-modeline-update))
3354
3355 (defun wl-summary-decide-flag (folder number)
3356   (let ((flags (elmo-get-global-flags (elmo-message-flags
3357                                        folder number)))
3358         (completion-ignore-case t)
3359         new-flags)
3360     (setq new-flags
3361           (delq nil
3362                 (mapcar
3363                  (lambda (flag)
3364                    (and (> (length flag) 0)
3365                         (intern (downcase flag))))
3366                  (wl-completing-read-multiple
3367                   "Flags: "
3368                   (mapcar (lambda (flag)
3369                             (list (capitalize (symbol-name flag))))
3370                           elmo-global-flags)
3371                   nil nil (mapconcat (lambda (flag)
3372                                        (capitalize (symbol-name flag)))
3373                                      flags
3374                                      ",")))))
3375     (dolist (flag new-flags)
3376       (unless (memq flag elmo-global-flags)
3377         (when (elmo-local-flag-p flag)
3378           (error "Cannot treat `%s'." flag))
3379         (unless (elmo-flag-valid-p flag)
3380           (error "Invalid char in `%s'" flag))
3381         (if (y-or-n-p (format "Flag `%s' is not registered yet. Register?"
3382                               (capitalize (symbol-name flag))))
3383             (setq elmo-global-flags (append
3384                                      elmo-global-flags
3385                                      (list flag)))
3386           (error "Stopped"))))
3387     new-flags))
3388
3389 (defsubst wl-summary-set-flags-internal (&optional
3390                                         number-or-numbers
3391                                         flags
3392                                         local
3393                                         remove-all)
3394   (save-excursion
3395     (let ((folder wl-summary-buffer-elmo-folder)
3396           number number-list)
3397       (setq number-list (cond ((numberp number-or-numbers)
3398                                (list number-or-numbers))
3399                               ((and (not (null number-or-numbers))
3400                                     (listp number-or-numbers))
3401                                number-or-numbers)
3402                               ((setq number (wl-summary-message-number))
3403                                ;; interactive
3404                                (list number))))
3405       (if remove-all
3406           (setq flags nil)
3407         (unless flags
3408           (setq flags (wl-summary-decide-flag folder (car number-list)))))
3409       (if (null number-list)
3410           (message "No message.")
3411         (dolist (number number-list)
3412           (elmo-message-set-global-flags folder number flags local)))
3413       flags)))
3414
3415 (defun wl-summary-set-flags (&optional remove)
3416   (interactive "P")
3417   (wl-summary-set-flags-internal nil nil nil remove))
3418
3419 (defun wl-summary-mark-as-important (&optional prompt)
3420   (interactive "P")
3421   (if prompt
3422       (wl-summary-set-flags-internal)
3423     (wl-summary-set-persistent-mark-internal
3424      (and (interactive-p)
3425           (elmo-message-flagged-p wl-summary-buffer-elmo-folder
3426                                   (wl-summary-message-number)
3427                                   'important))
3428      'important
3429      nil nil nil (interactive-p))))
3430
3431 ;;; Summary line.
3432 (defvar wl-summary-line-formatter nil)
3433
3434 (defun wl-summary-view-old-p ()
3435   "Return non-nil when summary view cache has old format."
3436   (save-excursion
3437     (goto-char (point-min))
3438     (and wl-summary-buffer-number-list
3439          (not (re-search-forward "\r-?[0-9]+" (point-at-eol) t)))))
3440
3441 (defun wl-summary-line-format-changed-p ()
3442   "Return non-nil when summary line format is changed."
3443   (not (string=
3444         wl-summary-buffer-line-format
3445         (or (elmo-object-load (expand-file-name
3446                                wl-summary-line-format-file
3447                                (elmo-folder-msgdb-path
3448                                 wl-summary-buffer-elmo-folder))
3449                               wl-summary-buffer-mime-charset)
3450             wl-summary-buffer-line-format))))
3451
3452 (defun wl-summary-line-format-save ()
3453   "Save current summary line format."
3454   (elmo-object-save
3455    (expand-file-name wl-summary-line-format-file
3456                      (elmo-folder-msgdb-path
3457                       wl-summary-buffer-elmo-folder))
3458    wl-summary-buffer-line-format
3459    wl-summary-buffer-mime-charset))
3460
3461 (defun wl-summary-line-number ()
3462   (wl-set-string-width
3463    (- wl-summary-buffer-number-column)
3464    (number-to-string
3465     (elmo-message-entity-number wl-message-entity))))
3466
3467 (defun wl-summary-line-year ()
3468   (aref wl-datevec 0))
3469 (defun wl-summary-line-month ()
3470   (format "%02d" (aref wl-datevec 1)))
3471 (defun wl-summary-line-day ()
3472   (format "%02d" (aref wl-datevec 2)))
3473 (defun wl-summary-line-day-of-week ()
3474   (condition-case nil
3475       (elmo-date-get-week (aref wl-datevec 0)
3476                           (aref wl-datevec 1)
3477                           (aref wl-datevec 2))
3478     (error "??")))
3479 (defun wl-summary-line-hour ()
3480   (format "%02d" (aref wl-datevec 3)))
3481 (defun wl-summary-line-minute ()
3482   (format "%02d" (aref wl-datevec 4)))
3483
3484 (defun wl-summary-line-size ()
3485   (let ((size (elmo-message-entity-field wl-message-entity 'size)))
3486     (if size
3487         (cond
3488          ((<= 1 (/ size 1048576))
3489           (format "%.0fM" (/ size 1048576.0)))
3490          ((<= 1 (/ size 1024))
3491           (format "%.0fK" (/ size 1024.0)))
3492          (t (format "%dB" size)))
3493       "")))
3494
3495 (defun wl-summary-line-subject ()
3496   (let (no-parent subject parent-raw-subject parent-subject)
3497     (if (string= wl-thr-indent-string "")
3498         (setq no-parent t)) ; no parent
3499     (setq subject
3500           (elmo-delete-char ?\n
3501                             (or (elmo-message-entity-field
3502                                  wl-message-entity
3503                                  'subject t)
3504                                 wl-summary-no-subject-message)))
3505     (setq parent-raw-subject
3506           (elmo-message-entity-field wl-parent-message-entity
3507                                      'subject t))
3508     (setq parent-subject
3509           (if parent-raw-subject
3510               (elmo-delete-char ?\n parent-raw-subject)))
3511     (if (or no-parent
3512             (null parent-subject)
3513             (not (wl-summary-subject-equal
3514                   subject parent-subject)))
3515         (funcall wl-summary-subject-function subject)
3516       "")))
3517
3518 (defun wl-summary-line-from ()
3519   (elmo-delete-char ?\n
3520                     (funcall wl-summary-from-function
3521                              (elmo-message-entity-field
3522                               wl-message-entity
3523                               'from t))))
3524
3525 (defun wl-summary-line-list-info ()
3526   (let ((list-info (wl-summary-get-list-info wl-message-entity)))
3527     (if (car list-info)
3528         (format (if (cdr list-info) "(%s %05.0f)" "(%s)")
3529                 (car list-info) (cdr list-info))
3530       "")))
3531
3532 (defun wl-summary-line-list-count ()
3533   (let ((ml-count (cdr (wl-summary-get-list-info wl-message-entity))))
3534     (if ml-count
3535         (format "%.0f" ml-count)
3536       "")))
3537
3538 (defun wl-summary-line-attached ()
3539   (let ((content-type (elmo-message-entity-field
3540                        wl-message-entity 'content-type))
3541         (case-fold-search t))
3542     (if (and content-type
3543              (string-match "multipart/mixed" content-type))
3544         "@"
3545       "")))
3546
3547 ;;; For future use.
3548 ;;(defun wl-summary-line-cached ()
3549 ;;  (if (elmo-message-cached-p wl-summary-buffer-elmo-folder
3550 ;;                           (elmo-message-entity-number wl-message-entity))
3551 ;;      " "
3552 ;;    "u"))
3553
3554 (defun wl-summary-create-line (wl-message-entity
3555                                wl-parent-message-entity
3556                                wl-temp-mark
3557                                wl-flags
3558                                wl-cached
3559                                &optional
3560                                wl-thr-children-number
3561                                wl-thr-indent-string
3562                                wl-thr-linked)
3563   "Create a summary line."
3564   (let ((wl-mime-charset wl-summary-buffer-mime-charset)
3565         (wl-persistent-mark (wl-summary-persistent-mark-string
3566                              wl-summary-buffer-elmo-folder
3567                              wl-flags
3568                              wl-cached))
3569         (elmo-mime-charset wl-summary-buffer-mime-charset)
3570         (elmo-lang wl-summary-buffer-weekday-name-lang)
3571         (wl-datevec (or (ignore-errors (timezone-fix-time
3572                                         (elmo-message-entity-field
3573                                          wl-message-entity
3574                                          'date)
3575                                         nil
3576                                         wl-summary-fix-timezone))
3577                         (make-vector 5 0)))
3578         (entity wl-message-entity) ; backward compatibility.
3579         line mark)
3580     (if (and wl-thr-indent-string
3581              wl-summary-indent-length-limit
3582              (< wl-summary-indent-length-limit
3583                 (string-width wl-thr-indent-string)))
3584         (setq wl-thr-indent-string (wl-set-string-width
3585                                     wl-summary-indent-length-limit
3586                                     wl-thr-indent-string)))
3587     (setq line (funcall wl-summary-buffer-line-formatter))
3588     (if wl-summary-width (setq line
3589                                (wl-set-string-width
3590                                 (- wl-summary-width 1) line nil
3591                                 'ignore-invalid)))
3592     (setq line (concat line
3593                        "\r"
3594                        (number-to-string
3595                         (elmo-message-entity-number
3596                          wl-message-entity))))
3597     (wl-summary-validate-persistent-mark-string line)
3598     (if wl-summary-highlight
3599         (wl-highlight-summary-line-string
3600          (elmo-message-entity-number wl-message-entity)
3601          line
3602          wl-flags
3603          wl-temp-mark
3604          wl-thr-indent-string))
3605     line))
3606
3607 (defsubst wl-summary-proc-wday (wday-str year month mday)
3608   (save-match-data
3609     (if (string-match "\\([A-Z][a-z][a-z]\\).*" wday-str)
3610         (wl-match-string 1 wday-str)
3611       (elmo-date-get-week year month mday))))
3612
3613 (defvar wl-summary-move-spec-alist
3614   '((new . ((t . nil)
3615             (p . new)
3616             (p . unread)
3617             (p . digest)))
3618     (unread . ((t . nil)
3619                (p . unread)
3620                (p . digest)))))
3621
3622 (defsubst wl-summary-next-message (num direction hereto)
3623   (if wl-summary-buffer-next-message-function
3624       (funcall wl-summary-buffer-next-message-function num direction hereto)
3625     (let ((cur-spec (cdr (assq wl-summary-move-order
3626                                wl-summary-move-spec-alist)))
3627           (nums (memq num (if (eq direction 'up)
3628                               (reverse wl-summary-buffer-number-list)
3629                             wl-summary-buffer-number-list)))
3630           flagged-list nums2)
3631       (unless hereto (setq nums (cdr nums)))
3632       (setq nums2 nums)
3633       (if cur-spec
3634           (catch 'done
3635             (while cur-spec
3636               (setq nums nums2)
3637               (cond ((eq (car (car cur-spec)) 'p)
3638                      (if (setq flagged-list
3639                                (elmo-folder-list-flagged
3640                                 wl-summary-buffer-elmo-folder
3641                                 (cdr (car cur-spec)) t))
3642                          (while nums
3643                            (if (and (memq (car nums) flagged-list)
3644                                     (elmo-message-accessible-p
3645                                      wl-summary-buffer-elmo-folder
3646                                      (car nums)))
3647                                (throw 'done (car nums)))
3648                            (setq nums (cdr nums)))))
3649                     ((eq (car (car cur-spec)) 't)
3650                      (if wl-summary-buffer-target-mark-list
3651                          (while nums
3652                            (if (memq (car nums)
3653                                      wl-summary-buffer-target-mark-list)
3654                                (throw 'done (car nums)))
3655                            (setq nums (cdr nums))))))
3656               (setq cur-spec (cdr cur-spec))))
3657         (car nums)))))
3658
3659 (defsubst wl-summary-cursor-move (direction hereto)
3660   (when (and (eq direction 'up)
3661              (eobp))
3662     (forward-line -1)
3663     (setq hereto t))
3664   (let (num)
3665     (when (setq num (wl-summary-next-message (wl-summary-message-number)
3666                                              direction hereto))
3667       (if (numberp num)
3668           (wl-thread-jump-to-msg num))
3669       t)))
3670 ;;
3671 ;; Goto unread or global flag message
3672 ;; returns t if next message exists in this folder.
3673 (defun wl-summary-cursor-down (&optional hereto)
3674   (interactive "P")
3675   (wl-summary-cursor-move 'down hereto))
3676
3677 (defun wl-summary-cursor-up (&optional hereto)
3678   (interactive "P")
3679   (wl-summary-cursor-move 'up hereto))
3680
3681 (defun wl-summary-save-view-cache ()
3682   (save-excursion
3683     (let* ((dir (elmo-folder-msgdb-path wl-summary-buffer-elmo-folder))
3684            (cache (expand-file-name wl-summary-cache-file dir))
3685            (view (expand-file-name wl-summary-view-file dir))
3686            (save-view wl-summary-buffer-view)
3687            (mark-list (copy-sequence wl-summary-buffer-target-mark-list))
3688            (temp-list (copy-sequence wl-summary-buffer-temp-mark-list))
3689            (tmp-buffer (get-buffer-create " *wl-summary-save-view-cache*"))
3690            (temp-column wl-summary-buffer-temp-mark-column)
3691            (charset wl-summary-buffer-mime-charset))
3692       (when dir
3693         (if (file-directory-p dir)
3694             (); ok.
3695           (if (file-exists-p dir)
3696               (error "File %s already exists" dir)
3697             (elmo-make-directory dir)))
3698         (if (eq save-view 'thread)
3699             (wl-thread-save-entity dir))
3700         (when wl-summary-check-line-format
3701           (wl-summary-line-format-save))
3702         (unwind-protect
3703             (progn
3704               (when (file-writable-p cache)
3705                 (copy-to-buffer tmp-buffer (point-min) (point-max))
3706                 (with-current-buffer tmp-buffer
3707                   (widen)
3708                   (make-local-variable 'wl-summary-highlight)
3709                   (setq wl-summary-highlight nil
3710                         wl-summary-buffer-target-mark-list mark-list
3711                         wl-summary-buffer-temp-mark-list temp-list
3712                         wl-summary-buffer-temp-mark-column temp-column)
3713                   (wl-summary-delete-all-temp-marks 'no-msg 'force)
3714                   (encode-coding-region
3715                    (point-min) (point-max)
3716                    (or (and wl-on-mule
3717                             ;; one in mcs-ltn1(apel<10.4) cannot take 2 arg.
3718                             (mime-charset-to-coding-system charset 'LF))
3719                        ;; Mule 2 doesn't have `*ctext*unix'.
3720                        (mime-charset-to-coding-system charset)))
3721                   (write-region-as-binary (point-min)(point-max)
3722                                           cache nil 'no-msg)))
3723               (when (file-writable-p view) ; 'thread or 'sequence
3724                 (with-temp-buffer
3725                   (prin1 save-view (current-buffer))
3726                   (princ "\n" (current-buffer))
3727                   (write-region (point-min) (point-max) view nil 'no-msg))))
3728           ;; kill tmp buffer.
3729           (kill-buffer tmp-buffer))))))
3730
3731 (defsubst wl-summary-get-sync-range (folder)
3732   (intern (or (and
3733                (elmo-folder-plugged-p folder)
3734                (wl-get-assoc-list-value
3735                 wl-folder-sync-range-alist
3736                 (elmo-folder-name-internal folder)
3737                 'function))
3738               wl-default-sync-range)))
3739
3740 ;; redefined for wl-summary-sync-update
3741 (defun wl-summary-input-range (folder)
3742   "returns update or all or rescan."
3743   ;; for the case when parts are expanded in the bottom of the folder
3744   (let ((input-range-list '("no-sync"
3745                             "first:"
3746                             "last:"
3747                             "cache-status"
3748                             "mark"
3749                             "rescan"
3750                             "rescan-noscore"
3751                             "rescan-thread"
3752                             "update"
3753                             "update-entirely"
3754                             "all"
3755                             "all-entirely"))
3756         (default (or (wl-get-assoc-list-value
3757                       wl-folder-sync-range-alist
3758                       folder
3759                       'function)
3760                      wl-default-sync-range))
3761         range)
3762     (setq range
3763           (completing-read (format "Range (%s): " default)
3764                            (mapcar
3765                             (function (lambda (x) (cons x x)))
3766                             input-range-list)))
3767     (if (string= range "")
3768         default
3769       range)))
3770
3771 (defun wl-summary-toggle-disp-folder (&optional arg)
3772   (interactive)
3773   (let ((cur-buf (current-buffer))
3774         (summary-win (get-buffer-window (current-buffer)))
3775         fld-buf fld-win)
3776     (cond
3777      ((eq arg 'on)
3778       (setq wl-summary-buffer-disp-folder t)
3779       ;; hide your folder window
3780       (if (setq fld-buf (get-buffer wl-folder-buffer-name))
3781           (if (setq fld-win (get-buffer-window fld-buf))
3782               (delete-window fld-win))))
3783      ((eq arg 'off)
3784       (setq wl-summary-buffer-disp-folder nil)
3785       ;; hide your wl-message window!
3786       (when (buffer-live-p wl-message-buffer)
3787         (wl-message-select-buffer wl-message-buffer)
3788         (delete-window))
3789       (select-window (get-buffer-window cur-buf))
3790       ;; display wl-folder window!!
3791       (if (setq fld-buf (get-buffer wl-folder-buffer-name))
3792           (if (setq fld-win (get-buffer-window fld-buf))
3793               ;; folder win is already displayed.
3794               (select-window fld-win)
3795             ;; folder win is not displayed.
3796             (switch-to-buffer fld-buf))
3797         ;; no folder buf
3798         (wl-folder))
3799       ;; temporarily delete summary-win.
3800       (if summary-win
3801           (delete-window summary-win))
3802       (split-window-horizontally wl-folder-window-width)
3803       (other-window 1)
3804       (switch-to-buffer cur-buf))
3805      (t
3806       (if (setq fld-buf (get-buffer wl-folder-buffer-name))
3807           (if (setq fld-win (get-buffer-window fld-buf))
3808               (setq wl-summary-buffer-disp-folder nil)
3809             (setq wl-summary-buffer-disp-folder t)))
3810       (if (not wl-summary-buffer-disp-folder)
3811           ;; hide message window
3812           (let ((mes-win (and wl-message-buffer
3813                               (get-buffer-window wl-message-buffer)))
3814                 (wl-stay-folder-window t))
3815             (if mes-win (delete-window mes-win))
3816             ;; hide your folder window
3817             (if (setq fld-buf (get-buffer wl-folder-buffer-name))
3818                 (if (setq fld-win (get-buffer-window fld-buf))
3819                     (progn
3820                       (delete-window (get-buffer-window cur-buf))
3821                       (select-window fld-win)
3822                       (switch-to-buffer cur-buf))))
3823             (run-hooks 'wl-summary-toggle-disp-folder-off-hook)
3824             ;; resume message window.
3825             (when mes-win
3826               (wl-message-select-buffer wl-message-buffer)
3827               (run-hooks 'wl-summary-toggle-disp-folder-message-resumed-hook)
3828               (select-window (get-buffer-window cur-buf))))
3829         ;; hide message window
3830         (let ((wl-stay-folder-window t)
3831               (mes-win (and wl-message-buffer
3832                             (get-buffer-window wl-message-buffer))))
3833           (if mes-win (delete-window mes-win))
3834           (select-window (get-buffer-window cur-buf))
3835           ;; display wl-folder window!!
3836           (if (setq fld-buf (get-buffer wl-folder-buffer-name))
3837               (if (setq fld-win (get-buffer-window fld-buf))
3838                   ;; folder win is already displayed.
3839                   (select-window fld-win)
3840                 ;; folder win is not displayed...occupy all.
3841                 (switch-to-buffer fld-buf))
3842             ;; no folder buf
3843             (wl-folder))
3844           (split-window-horizontally wl-folder-window-width)
3845           (other-window 1)
3846           (switch-to-buffer cur-buf)
3847           ;; resume message window.
3848           (run-hooks 'wl-summary-toggle-disp-folder-on-hook)
3849           (when mes-win
3850             (wl-message-select-buffer wl-message-buffer)
3851             (run-hooks 'wl-summary-toggle-disp-folder-message-resumed-hook)
3852             (select-window (get-buffer-window cur-buf))))))))
3853   (run-hooks 'wl-summary-toggle-disp-folder-hook))
3854
3855 (defun wl-summary-toggle-disp-msg (&optional arg)
3856   (interactive)
3857   (let ((cur-buf (current-buffer))
3858         fld-buf fld-win
3859         summary-win)
3860     (cond
3861      ((eq arg 'on)
3862       (setq wl-summary-buffer-disp-msg t)
3863       (save-excursion
3864         ;; hide your folder window
3865         (if (and (not wl-stay-folder-window)
3866                  (setq fld-buf (get-buffer wl-folder-buffer-name)))
3867             (if (setq fld-win (get-buffer-window fld-buf))
3868                 (unless (one-window-p fld-win)
3869                   (delete-window fld-win))))))
3870      ((eq arg 'off)
3871       (wl-delete-all-overlays)
3872       (setq wl-summary-buffer-disp-msg nil)
3873       (save-excursion
3874         (when (buffer-live-p wl-message-buffer)
3875           (wl-message-select-buffer wl-message-buffer)
3876           (delete-window)
3877           (and (get-buffer-window cur-buf)
3878                (select-window (get-buffer-window cur-buf))))
3879         (run-hooks 'wl-summary-toggle-disp-off-hook)))
3880      (t
3881       (if (and wl-message-buffer
3882                (get-buffer-window wl-message-buffer)) ; already displayed
3883           (setq wl-summary-buffer-disp-msg nil)
3884         (setq wl-summary-buffer-disp-msg t))
3885       (if wl-summary-buffer-disp-msg
3886           (progn
3887             (wl-summary-redisplay)
3888 ;;; hide your folder window
3889 ;;;         (setq fld-buf (get-buffer wl-folder-buffer-name))
3890 ;;;         (if (setq fld-win (get-buffer-window fld-buf))
3891 ;;;             (delete-window fld-win)))
3892             (run-hooks 'wl-summary-toggle-disp-on-hook))
3893         (wl-delete-all-overlays)
3894         (save-excursion
3895           (wl-message-select-buffer wl-message-buffer)
3896           (delete-window)
3897           (select-window (get-buffer-window cur-buf))
3898           (setq wl-message-buffer nil)
3899           (run-hooks 'wl-summary-toggle-disp-off-hook))
3900 ;;;     (switch-to-buffer cur-buf)
3901         )))
3902     (run-hooks 'wl-summary-buffer-window-scroll-functions)))
3903
3904 (defun wl-summary-enter-handler (&optional arg)
3905   "A command for `enter' key in the summary.
3906 Basically, it shows next line of the message.
3907 If optional argument ARG is specified, behave as followed.
3908 If ARG is number, jump to the message.
3909 Otherwise it shows previous line of the message."
3910   (interactive "P")
3911   (cond ((numberp arg)
3912          (unless (wl-thread-jump-to-msg arg)
3913            (message "Message (#%d) was not found." arg)))
3914         (arg
3915          (wl-summary-prev-line-content))
3916         (t
3917          (wl-summary-next-line-content))))
3918
3919 (defun wl-summary-next-line-content ()
3920   "Show next line of the message."
3921   (interactive)
3922   (let ((cur-buf (current-buffer)))
3923     (wl-summary-toggle-disp-msg 'on)
3924     (when (wl-summary-set-message-buffer-or-redisplay 'ignore-original)
3925       (set-buffer cur-buf)
3926       (wl-message-next-page 1))))
3927
3928 (defun wl-summary-prev-line-content ()
3929   (interactive)
3930   (let ((cur-buf (current-buffer)))
3931     (wl-summary-toggle-disp-msg 'on)
3932     (when (wl-summary-set-message-buffer-or-redisplay 'ignore-original)
3933       (set-buffer cur-buf)
3934       (wl-message-prev-page 1))))
3935
3936 (defun wl-summary-next-page ()
3937   (interactive)
3938   (let ((cur-buf (current-buffer)))
3939     (wl-summary-toggle-disp-msg 'on)
3940     (when (wl-summary-set-message-buffer-or-redisplay 'ignore-original)
3941       (set-buffer cur-buf)
3942       (wl-message-next-page))))
3943
3944 (defun wl-summary-prev-page ()
3945   (interactive)
3946   (let ((cur-buf (current-buffer)))
3947     (wl-summary-toggle-disp-msg 'on)
3948     (when (wl-summary-set-message-buffer-or-redisplay 'ignore-original)
3949       (set-buffer cur-buf)
3950       (wl-message-prev-page))))
3951
3952 (defsubst wl-summary-no-mime-p (folder)
3953   (wl-string-match-member (elmo-folder-name-internal folder)
3954                           wl-summary-no-mime-folder-list))
3955
3956 (defun wl-summary-set-message-buffer-or-redisplay (&rest args)
3957   "Set message buffer.
3958 If message is not displayed yet, display it.
3959 Return t if message exists."
3960   (let ((folder wl-summary-buffer-elmo-folder)
3961         (number (wl-summary-message-number))
3962         cur-folder cur-number message-last-pos)
3963     (when (buffer-live-p wl-message-buffer)
3964       (save-window-excursion
3965         (setq wl-current-summary-buffer (current-buffer))
3966         (wl-message-select-buffer wl-message-buffer)
3967         (setq cur-folder wl-message-buffer-cur-folder)
3968         (setq cur-number wl-message-buffer-cur-number)))
3969     (if (and (string= (elmo-folder-name-internal folder) (or cur-folder ""))
3970              (eq number (or cur-number 0)))
3971         (progn
3972           (set-buffer wl-message-buffer)
3973           t)
3974       (wl-summary-redisplay-internal folder number)
3975       (when (buffer-live-p wl-message-buffer)
3976         (set-buffer wl-message-buffer))
3977       nil)))
3978
3979 (defun wl-summary-target-mark-forward (&optional arg)
3980   (interactive "P")
3981   (wl-summary-check-target-mark)
3982   (let ((mlist (nreverse (copy-sequence wl-summary-buffer-target-mark-list)))
3983         (summary-buf (current-buffer))
3984         (wl-draft-forward t)
3985         start-point
3986         draft-buf)
3987     (wl-summary-jump-to-msg (car mlist))
3988     (wl-summary-forward t)
3989     (setq start-point (point))
3990     (setq draft-buf (current-buffer))
3991     (setq mlist (cdr mlist))
3992     (save-window-excursion
3993       (when mlist
3994         (while mlist
3995           (set-buffer summary-buf)
3996           (wl-summary-jump-to-msg (car mlist))
3997           (wl-summary-redisplay)
3998           (set-buffer draft-buf)
3999           (goto-char (point-max))
4000           (wl-draft-insert-message)
4001           (setq mlist (cdr mlist)))
4002         (wl-draft-body-goto-top)
4003         (wl-draft-enclose-digest-region (point) (point-max)))
4004       (goto-char start-point)
4005       (save-excursion
4006         (set-buffer summary-buf)
4007         (wl-summary-delete-all-target-marks)))
4008     (run-hooks 'wl-mail-setup-hook)))
4009
4010 (defun wl-summary-target-mark-reply-with-citation (&optional arg)
4011   (interactive "P")
4012   (wl-summary-check-target-mark)
4013   (let ((mlist (nreverse (copy-sequence wl-summary-buffer-target-mark-list)))
4014         (summary-buf (current-buffer))
4015         change-major-mode-hook
4016         start-point
4017         draft-buf)
4018     (wl-summary-jump-to-msg (car mlist))
4019     (when (wl-summary-reply arg t)
4020       (goto-char (point-max))
4021       (setq start-point (point-marker))
4022       (setq draft-buf (current-buffer))
4023       (save-window-excursion
4024         (while mlist
4025           (set-buffer summary-buf)
4026           (delete-other-windows)
4027           (wl-summary-jump-to-msg (car mlist))
4028           (wl-summary-redisplay)
4029           (set-buffer draft-buf)
4030           (goto-char (point-max))
4031           (wl-draft-yank-original)
4032           (setq mlist (cdr mlist)))
4033         (goto-char start-point)
4034         (save-excursion
4035           (set-buffer summary-buf)
4036           (wl-summary-delete-all-target-marks)))
4037       (wl-draft-reply-position wl-draft-reply-default-position)
4038       (run-hooks 'wl-mail-setup-hook))))
4039
4040 (defun wl-summary-reply-with-citation (&optional arg)
4041   (interactive "P")
4042   (when (wl-summary-reply arg t)
4043     (goto-char (point-max))
4044     (wl-draft-yank-original)
4045     (wl-draft-reply-position wl-draft-reply-default-position)
4046     (run-hooks 'wl-mail-setup-hook)))
4047
4048 (defun wl-summary-jump-to-msg-by-message-id (&optional id)
4049   (interactive)
4050   (let* ((original (wl-summary-message-number))
4051          (msgid (elmo-string (or id (read-from-minibuffer "Message-ID: "))))
4052          (entity (elmo-message-entity wl-summary-buffer-elmo-folder msgid))
4053          msg otherfld schar
4054          (errmsg (format "No message with id \"%s\" in the folder." msgid)))
4055     (if (setq msg (elmo-message-entity-number entity))
4056         (progn
4057           (wl-thread-jump-to-msg msg)
4058           t)
4059       ;; for XEmacs!
4060       (if (and elmo-use-database
4061                (setq errmsg
4062                      (format
4063                       "No message with id \"%s\" in the database." msgid))
4064                (setq otherfld (elmo-database-msgid-get msgid)))
4065           (if (cdr (wl-summary-jump-to-msg-internal
4066                     (car otherfld) (nth 1 otherfld) 'no-sync))
4067               t ; succeed.
4068             ;; Back to original.
4069             (wl-summary-jump-to-msg-internal
4070              (wl-summary-buffer-folder-name) original 'no-sync))
4071         (cond ((eq wl-summary-search-via-nntp 'confirm)
4072                (require 'elmo-nntp)
4073                (message "Search message in nntp server \"%s\" <y/n/s(elect)>? "
4074                         elmo-nntp-default-server)
4075                (setq schar (let ((cursor-in-echo-area t)) (read-char)))
4076                (cond ((eq schar ?y)
4077                       (wl-summary-jump-to-msg-by-message-id-via-nntp msgid))
4078                      ((eq schar ?s)
4079                       (wl-summary-jump-to-msg-by-message-id-via-nntp
4080                        msgid
4081                        (read-from-minibuffer "NNTP Server: ")))
4082                      (t
4083                       (message "%s" errmsg)
4084                       nil)))
4085               ((or (eq wl-summary-search-via-nntp 'force)
4086                    (and
4087                     (eq (elmo-folder-type-internal wl-summary-buffer-elmo-folder)
4088                         'nntp)
4089                     wl-summary-search-via-nntp))
4090                (wl-summary-jump-to-msg-by-message-id-via-nntp msgid))
4091               (t
4092                (message "%s" errmsg)
4093                nil))))))
4094
4095 (defun wl-summary-jump-to-msg-by-message-id-via-nntp (&optional id server-spec)
4096   (interactive)
4097   (let* ((msgid (elmo-string (or id (read-from-minibuffer "Message-ID: "))))
4098          newsgroups folder ret
4099          user server port type spec)
4100     (if server-spec
4101         (if (string-match "^-" server-spec)
4102             (setq spec (wl-folder-get-elmo-folder server-spec)
4103                   user (elmo-net-folder-user-internal spec)
4104                   server (elmo-net-folder-server-internal spec)
4105                   port (elmo-net-folder-port-internal spec)
4106                   type (elmo-net-folder-stream-type-internal spec))
4107           (setq server server-spec)))
4108     (when (setq ret (elmo-nntp-get-newsgroup-by-msgid
4109                      msgid
4110                      (or server elmo-nntp-default-server)
4111                      (or user elmo-nntp-default-user)
4112                      (or port elmo-nntp-default-port)
4113                      (or type elmo-nntp-default-stream-type)))
4114       (setq newsgroups (elmo-nntp-parse-newsgroups ret))
4115       (setq folder (concat "-" (car newsgroups)
4116                            (elmo-nntp-folder-postfix user server port type)))
4117       (catch 'found
4118         (while newsgroups
4119           (if (wl-folder-entity-exists-p (car newsgroups)
4120                                          wl-folder-newsgroups-hashtb)
4121               (throw 'found
4122                      (setq folder (concat "-" (car newsgroups)
4123                                           (elmo-nntp-folder-postfix
4124                                            user server port type)))))
4125           (setq newsgroups (cdr newsgroups)))))
4126     (if ret
4127         (wl-summary-jump-to-msg-internal folder nil 'update msgid)
4128       (message "No message id \"%s\" in nntp server \"%s\"."
4129                msgid (or server elmo-nntp-default-server))
4130       nil)))
4131
4132 (defun wl-summary-jump-to-msg-internal (folder msg scan-type &optional msgid)
4133   (let (wl-auto-select-first entity)
4134     (if (or (string= folder (wl-summary-buffer-folder-name))
4135             (y-or-n-p
4136              (format
4137               "Message was found in the folder \"%s\". Jump to it? "
4138               folder)))
4139         (progn
4140           (unwind-protect
4141               (wl-summary-goto-folder-subr
4142                folder scan-type nil nil t)
4143             (if msgid
4144                 (setq msg
4145                       (elmo-message-entity-number
4146                        (elmo-message-entity
4147                         wl-summary-buffer-elmo-folder
4148                         msgid))))
4149             (setq entity (wl-folder-search-entity-by-name folder
4150                                                           wl-folder-entity
4151                                                           'folder))
4152             (if entity
4153                 (wl-folder-set-current-entity-id
4154                  (wl-folder-get-entity-id entity))))
4155           (if (null msg)
4156               (message "Message was not found currently in this folder.")
4157             (setq msg (and (wl-thread-jump-to-msg msg) msg)))
4158           (cons folder msg)))))
4159
4160 (defun wl-summary-jump-to-parent-message (arg)
4161   (interactive "P")
4162   (let ((cur-buf (current-buffer))
4163         (disp-msg wl-summary-buffer-disp-msg)
4164         (number (wl-summary-message-number))
4165         (regexp "\\(<[^<>]*>\\)[ \t]*$")
4166         (i -1) ;; xxx
4167         msg-id msg-num ref-list ref irt)
4168     (if (null number)
4169         (message "No message.")
4170       (when (eq wl-summary-buffer-view 'thread)
4171         (cond ((and arg (not (numberp arg)))
4172                (setq msg-num
4173                      (wl-thread-entity-get-number
4174                       (wl-thread-entity-get-top-entity
4175                        (wl-thread-get-entity number)))))
4176               ((and arg (numberp arg))
4177                (setq i 0)
4178                (setq msg-num number)
4179                (while (< i arg)
4180                  (setq msg-num
4181                        (wl-thread-entity-get-number
4182                         (wl-thread-entity-get-parent-entity
4183                          (wl-thread-get-entity msg-num))))
4184                  (setq i (1+ i))))
4185               (t (setq msg-num
4186                        (wl-thread-entity-get-number
4187                         (wl-thread-entity-get-parent-entity
4188                          (wl-thread-get-entity number)))))))
4189       (when (null msg-num)
4190         (wl-summary-set-message-buffer-or-redisplay)
4191         (set-buffer (wl-message-get-original-buffer))
4192         (message "Searching parent message...")
4193         (setq ref (std11-field-body "References")
4194               irt (std11-field-body "In-Reply-To"))
4195         (cond
4196          ((and arg (not (numberp arg)) ref (not (string= ref ""))
4197                (string-match regexp ref))
4198           ;; The first message of the thread.
4199           (setq msg-id (wl-match-string 1 ref)))
4200          ;; "In-Reply-To:" has only one msg-id.
4201          ((and (null arg) irt (not (string= irt ""))
4202                (string-match regexp irt))
4203           (setq msg-id (wl-match-string 1 irt)))
4204          ((and (or (null arg) (numberp arg)) ref (not (string= ref ""))
4205                (string-match regexp ref))
4206           ;; "^" searching parent, "C-u 2 ^" looking for grandparent.
4207           (while (string-match regexp ref)
4208             (setq ref-list
4209                   (append (list
4210                            (wl-match-string 1 ref))
4211                           ref-list))
4212             (setq ref (substring ref (match-end 0)))
4213             (setq i (1+ i)))
4214           (setq msg-id
4215                 (if (null arg) (nth 0 ref-list) ;; previous
4216                   (if (<= arg i) (nth (1- arg) ref-list)
4217                     (nth i ref-list))))))
4218         (set-buffer cur-buf)
4219         (or disp-msg (wl-summary-toggle-disp-msg 'off)))
4220       (cond ((and (null msg-id) (null msg-num))
4221              (message "No parent message!")
4222              nil)
4223             ((and msg-id (wl-summary-jump-to-msg-by-message-id msg-id))
4224              (if wl-summary-buffer-disp-msg (wl-summary-redisplay))
4225              (message "Searching parent message...done")
4226              t)
4227             ((and msg-num (wl-summary-jump-to-msg msg-num))
4228              (if wl-summary-buffer-disp-msg (wl-summary-redisplay))
4229              (message "Searching parent message...done")
4230              t)
4231             (t ; failed.
4232              (message "Parent message was not found.")
4233              nil)))))
4234
4235 (defun wl-summary-reply (&optional arg without-setup-hook)
4236   "Reply to current message. Default is \"wide\" reply.
4237 Reply to author if invoked with ARG."
4238   (interactive "P")
4239   (let ((folder wl-summary-buffer-elmo-folder)
4240         (number (wl-summary-message-number))
4241         (summary-buf (current-buffer))
4242         (winconf (current-window-configuration))
4243         mes-buf)
4244     (when number
4245       (save-excursion
4246         (wl-summary-set-message-buffer-or-redisplay))
4247       (wl-message-select-buffer wl-message-buffer)
4248       (condition-case err
4249           (when (setq mes-buf (wl-message-get-original-buffer))
4250             (wl-draft-reply mes-buf arg summary-buf number)
4251             (wl-draft-reply-position wl-draft-reply-default-position)
4252             (unless without-setup-hook
4253               (run-hooks 'wl-mail-setup-hook)))
4254         (error (set-window-configuration winconf)
4255                (signal (car err)(cdr err))))
4256       (with-current-buffer summary-buf (run-hooks 'wl-summary-reply-hook))
4257       t)))
4258
4259 (defun wl-summary-write ()
4260   "Write a new draft from Summary."
4261   (interactive)
4262   (wl-draft (list (cons 'To ""))
4263             nil nil nil nil (wl-summary-buffer-folder-name))
4264   (run-hooks 'wl-mail-setup-hook)
4265   (mail-position-on-field "To"))
4266
4267 (defvar wl-summary-write-current-folder-functions
4268   '(wl-folder-get-newsgroups
4269     wl-folder-guess-mailing-list-by-refile-rule
4270     wl-folder-guess-mailing-list-by-folder-name)
4271   "Newsgroups or Mailing List address guess functions list.
4272 Call from `wl-summary-write-current-folder'.
4273 When guess function return nil, challenge next guess-function.")
4274
4275 (defun wl-summary-write-current-folder (&optional folder)
4276   "Write message to current FOLDER's newsgroup or mailing-list.
4277 Use function list is `wl-summary-write-current-folder-functions'."
4278   (interactive)
4279   ;; default FOLDER is current buffer folder
4280   (setq folder (or folder (wl-summary-buffer-folder-name)))
4281   (let ((func-list wl-summary-write-current-folder-functions)
4282         guess-list guess-func)
4283     (while func-list
4284       (setq guess-list (funcall (car func-list) folder))
4285       (if (null guess-list)
4286           (setq func-list (cdr func-list))
4287         (setq guess-func (car func-list))
4288         (setq func-list nil)))
4289     (if (null guess-func)
4290         (wl-summary-write)
4291       (unless (or (stringp (nth 0 guess-list))
4292                   (stringp (nth 1 guess-list))
4293                   (stringp (nth 2 guess-list)))
4294         (error "Invalid value return guess function `%s'"
4295                (symbol-name guess-func)))
4296       (wl-draft (list (cons 'To (nth 0 guess-list))
4297                       (cons 'Cc (nth 1 guess-list))
4298                       (cons 'Newsgroups (nth 2 guess-list)))
4299                 nil nil nil nil folder)
4300       (run-hooks 'wl-mail-setup-hook)
4301       (mail-position-on-field "Subject"))))
4302
4303 (defun wl-summary-forward (&optional without-setup-hook)
4304   ""
4305   (interactive)
4306   (let ((folder wl-summary-buffer-elmo-folder)
4307         (number (wl-summary-message-number))
4308         (summary-buf (current-buffer))
4309         (wl-draft-forward t)
4310         entity subject num)
4311     (if (null number)
4312         (message "No message.")
4313       (if (and (elmo-message-use-cache-p folder number)
4314                (eq (elmo-file-cache-status
4315                     (elmo-file-cache-get
4316                      (elmo-message-field folder number 'message-id)))
4317                    'section))
4318           ;; Reload.
4319           (wl-summary-redisplay-internal nil nil 'force-reload)
4320         (wl-summary-redisplay-internal folder number))
4321       (wl-message-select-buffer wl-message-buffer)
4322       (setq subject (with-current-buffer
4323                         wl-message-buffer-original-buffer
4324                       (std11-field-body "Subject")))
4325       (wl-draft-forward subject summary-buf number)
4326       (with-current-buffer summary-buf (run-hooks 'wl-summary-forward-hook))
4327       (unless without-setup-hook
4328         (run-hooks 'wl-mail-setup-hook)))))
4329
4330 (defun wl-summary-click (e)
4331   (interactive "e")
4332   (mouse-set-point e)
4333   (wl-summary-read))
4334
4335 (defun wl-summary-read ()
4336   "Proceed reading message in the summary buffer."
4337   (interactive)
4338   (let ((cur-buf (current-buffer)))
4339     (wl-summary-toggle-disp-msg 'on)
4340     (when (wl-summary-set-message-buffer-or-redisplay 'ignore-original)
4341       (set-buffer cur-buf)
4342       (if (wl-message-next-page)
4343           (wl-summary-down t)))))
4344
4345 (defsubst wl-summary-cursor-move-surface (downward interactive)
4346   (if wl-summary-move-direction-toggle
4347       (setq wl-summary-move-direction-downward downward))
4348   (let ((start (point))
4349         (skip-tmark-regexp (wl-regexp-opt wl-summary-skip-mark-list))
4350         (skip t)
4351         (column (current-column))
4352         goto-next next-entity finfo)
4353     (beginning-of-line)
4354     (while (and skip
4355                 (not (if downward (eobp) (bobp))))
4356       (if downward
4357           (forward-line 1)
4358         (forward-line -1))
4359       (setq skip (or (string-match skip-tmark-regexp
4360                                    (wl-summary-temp-mark))
4361                      (not (and (wl-summary-message-number)
4362                                (elmo-message-accessible-p
4363                                 wl-summary-buffer-elmo-folder
4364                                 (wl-summary-message-number)))))))
4365     (if (if downward (eobp) (and (bobp) skip)) (setq goto-next t))
4366     (if (or (eobp) (and (bobp) skip))
4367         (goto-char start))
4368     (move-to-column column)
4369
4370     (if (not goto-next)
4371         (if wl-summary-buffer-disp-msg
4372             (wl-summary-redisplay))
4373       (if interactive
4374           (cond
4375            ((and (not downward) wl-summary-buffer-prev-folder-function)
4376             (funcall wl-summary-buffer-prev-folder-function))
4377            ((and downward wl-summary-buffer-next-folder-function)
4378             (funcall wl-summary-buffer-next-folder-function))
4379            (t
4380             (when wl-auto-select-next
4381               (setq next-entity
4382                     (if downward
4383                         (wl-summary-get-next-folder)
4384                       (wl-summary-get-prev-folder)))
4385               (if next-entity
4386                   (setq finfo (wl-folder-get-entity-info next-entity))))
4387             (wl-ask-folder
4388              '(lambda () (wl-summary-next-folder-or-exit next-entity))
4389              (format
4390               "No more messages. Type SPC to go to %s."
4391               (wl-summary-entity-info-msg next-entity finfo)))))))))
4392
4393 (defun wl-summary-prev (&optional interactive)
4394   (interactive)
4395   (wl-summary-cursor-move-surface nil (or interactive (interactive-p))))
4396
4397 (defun wl-summary-next (&optional interactive)
4398   (interactive)
4399   (wl-summary-cursor-move-surface t (or interactive (interactive-p))))
4400
4401 (defun wl-summary-up (&optional interactive skip-no-unread)
4402   ""
4403   (interactive)
4404   (if wl-summary-move-direction-toggle
4405       (setq wl-summary-move-direction-downward nil))
4406   (if (wl-summary-cursor-up)
4407       (if wl-summary-buffer-disp-msg
4408           (wl-summary-redisplay))
4409     (if (or interactive
4410             (interactive-p))
4411         (if wl-summary-buffer-prev-folder-function
4412             (funcall wl-summary-buffer-prev-folder-function)
4413           (let (next-entity finfo)
4414             (when wl-auto-select-next
4415               (progn
4416                 (setq next-entity (wl-summary-get-prev-unread-folder))
4417                 (if next-entity
4418                     (setq finfo (wl-folder-get-entity-info next-entity)))))
4419             (if (and skip-no-unread
4420                      (eq wl-auto-select-next 'skip-no-unread))
4421                 (wl-summary-next-folder-or-exit next-entity t)
4422               (wl-ask-folder
4423                '(lambda () (wl-summary-next-folder-or-exit next-entity t))
4424                (format
4425                 "No more unread messages. Type SPC to go to %s."
4426                 (wl-summary-entity-info-msg next-entity finfo)))))))))
4427
4428 (defun wl-summary-get-prev-folder ()
4429   (let ((folder-buf (get-buffer wl-folder-buffer-name))
4430         last-entity cur-id)
4431     (when folder-buf
4432       (setq cur-id (save-excursion (set-buffer folder-buf)
4433                                    wl-folder-buffer-cur-entity-id))
4434       (wl-folder-get-prev-folder cur-id))))
4435
4436 (defun wl-summary-get-next-folder ()
4437   (let ((folder-buf (get-buffer wl-folder-buffer-name))
4438         cur-id)
4439     (when folder-buf
4440       (setq cur-id (save-excursion (set-buffer folder-buf)
4441                                    wl-folder-buffer-cur-entity-id))
4442       (wl-folder-get-next-folder cur-id))))
4443
4444 (defun wl-summary-get-next-unread-folder ()
4445   (let ((folder-buf (get-buffer wl-folder-buffer-name))
4446         cur-id)
4447     (when folder-buf
4448       (setq cur-id (save-excursion (set-buffer folder-buf)
4449                                    wl-folder-buffer-cur-entity-id))
4450       (wl-folder-get-next-folder cur-id 'unread))))
4451
4452 (defun wl-summary-get-prev-unread-folder ()
4453   (let ((folder-buf (get-buffer wl-folder-buffer-name))
4454         cur-id)
4455     (when folder-buf
4456       (setq cur-id (save-excursion (set-buffer folder-buf)
4457                                    wl-folder-buffer-cur-entity-id))
4458       (wl-folder-get-prev-folder cur-id 'unread))))
4459
4460 (defun wl-summary-down (&optional interactive skip-no-unread)
4461   (interactive)
4462   (if wl-summary-move-direction-toggle
4463       (setq wl-summary-move-direction-downward t))
4464   (if (wl-summary-cursor-down)
4465       (if wl-summary-buffer-disp-msg
4466           (wl-summary-redisplay))
4467     (if (or interactive
4468             (interactive-p))
4469         (if wl-summary-buffer-next-folder-function
4470             (funcall wl-summary-buffer-next-folder-function)
4471           (let (next-entity finfo)
4472             (when wl-auto-select-next
4473               (setq next-entity (wl-summary-get-next-unread-folder)))
4474             (if next-entity
4475                 (setq finfo (wl-folder-get-entity-info next-entity)))
4476             (if (and skip-no-unread
4477                      (eq wl-auto-select-next 'skip-no-unread))
4478                 (wl-summary-next-folder-or-exit next-entity)
4479               (wl-ask-folder
4480                '(lambda () (wl-summary-next-folder-or-exit next-entity))
4481                (format
4482                 "No more unread messages. Type SPC to go to %s."
4483                 (wl-summary-entity-info-msg next-entity finfo)))))))))
4484
4485 (defun wl-summary-goto-last-displayed-msg ()
4486   (interactive)
4487   (unless wl-summary-buffer-last-displayed-msg
4488     (setq wl-summary-buffer-last-displayed-msg
4489           wl-summary-buffer-current-msg))
4490   (if wl-summary-buffer-last-displayed-msg
4491       (progn
4492         (wl-summary-jump-to-msg wl-summary-buffer-last-displayed-msg)
4493         (if wl-summary-buffer-disp-msg
4494             (wl-summary-redisplay)))
4495     (message "No last message.")))
4496
4497 (defun wl-summary-message-display-type ()
4498   (when (and wl-summary-buffer-disp-msg
4499              (buffer-live-p wl-message-buffer)
4500              wl-summary-buffer-current-msg
4501              (wl-summary-message-number)
4502              (= (wl-summary-message-number) wl-summary-buffer-current-msg))
4503     (wl-message-buffer-display-type wl-message-buffer)))
4504
4505 (defun wl-summary-buffer-display-mime-mode ()
4506   (or (wl-message-display-type-property (wl-summary-message-display-type)
4507                                         :mime)
4508       wl-summary-buffer-display-mime-mode))
4509
4510 (defun wl-summary-buffer-display-header-mode ()
4511   (or (wl-message-display-type-property (wl-summary-message-display-type)
4512                                         :header)
4513       wl-summary-buffer-display-header-mode))
4514
4515 (defun wl-summary-toggle-mime (&optional arg)
4516   "Toggle MIME decoding.
4517 If ARG is non-nil, ask coding-system to display the message in the current
4518 MIME analysis mode.
4519
4520 If ARG is numeric number, decode message as following:
4521 1: Enable MIME analysis.
4522 2: Enable MIME analysis only for headers.
4523 3: Disable MIME analysis."
4524   (interactive "P")
4525   (let ((mime-mode (wl-summary-buffer-display-mime-mode))
4526         (elmo-mime-display-as-is-coding-system
4527          elmo-mime-display-as-is-coding-system))
4528     (if (and (consp arg) (> (prefix-numeric-value arg) 4))
4529         (progn
4530           (setq wl-summary-buffer-display-mime-mode mime-mode)
4531           (wl-summary-update-modeline))
4532       (cond
4533        ((numberp arg)
4534         (setq mime-mode (case arg
4535                           (1 'mime)
4536                           (2 'header-only)
4537                           (3 'as-is)
4538 ;;;                       (4 'decode-only)
4539                           (5 'no-merge))))
4540        (arg
4541         ;; Specify coding-system (doesn't change the MIME mode).
4542         (setq elmo-mime-display-as-is-coding-system
4543               (if (and arg
4544                        (not (wl-message-mime-analysis-p
4545                              (wl-summary-message-display-type))))
4546                   (or (read-coding-system "Coding system: ")
4547                       elmo-mime-display-as-is-coding-system)
4548                 elmo-mime-display-as-is-coding-system)))
4549        (t
4550         ;; Change the MIME mode.
4551         (setq mime-mode (or (cadr (memq mime-mode
4552                                         wl-summary-display-mime-mode-list))
4553                             (car wl-summary-display-mime-mode-list)))))
4554       (wl-summary-redisplay-internal nil nil arg mime-mode))
4555     (message "MIME decoding: %s%s"
4556              (upcase (symbol-name mime-mode))
4557              (if (and (not (eq mime-mode 'mime))
4558                       (not (eq elmo-mime-display-as-is-coding-system
4559                                wl-cs-autoconv)))
4560                  (concat " ("
4561                          (symbol-name elmo-mime-display-as-is-coding-system)
4562                          ")")
4563                ""))))
4564
4565 (defun wl-summary-redisplay (&optional arg)
4566   "Redisplay message."
4567   (interactive "P")
4568   (apply #'wl-summary-redisplay-internal nil nil arg
4569          (unless (and (consp arg) (> (prefix-numeric-value arg) 4))
4570            (list wl-summary-buffer-display-mime-mode
4571                  wl-summary-buffer-display-header-mode))))
4572
4573 (defun wl-summary-toggle-all-header (&optional arg)
4574   "Toggle displaying message with all header."
4575   (interactive "P")
4576   (let ((header-mode (wl-summary-buffer-display-header-mode)))
4577     (if (and (consp arg) (> (prefix-numeric-value arg) 4))
4578         (setq wl-summary-buffer-display-header-mode header-mode)
4579       (wl-summary-redisplay-internal
4580        nil nil arg nil
4581        (if (eq header-mode 'all) 'partial 'all)))))
4582
4583 (defun wl-summary-redisplay-internal (&optional folder number force-reload
4584                                                 mime-mode header-mode)
4585   (let* ((folder (or folder wl-summary-buffer-elmo-folder))
4586          (num (or number (wl-summary-message-number)))
4587          (wl-mime-charset      wl-summary-buffer-mime-charset)
4588          (default-mime-charset wl-summary-buffer-mime-charset)
4589          fld-buf fld-win thr-entity
4590          (elmo-message-fetch-confirm (or elmo-message-fetch-confirm
4591                                          (and force-reload
4592                                               elmo-message-fetch-threshold))))
4593     (if (and wl-thread-open-reading-thread
4594              (eq wl-summary-buffer-view 'thread)
4595              (not (wl-thread-entity-get-opened
4596                    (setq thr-entity (wl-thread-get-entity
4597                                      num))))
4598              (wl-thread-entity-get-children thr-entity))
4599         (wl-thread-force-open))
4600     (if num
4601         (progn
4602           (setq wl-summary-buffer-disp-msg t)
4603           (setq wl-summary-buffer-last-displayed-msg
4604                 wl-summary-buffer-current-msg)
4605           ;; hide folder window
4606           (if (and (not wl-stay-folder-window)
4607                    (setq fld-buf (get-buffer wl-folder-buffer-name)))
4608               (if (setq fld-win (get-buffer-window fld-buf))
4609                   (delete-window fld-win)))
4610           (setq wl-current-summary-buffer (current-buffer))
4611           (wl-message-redisplay folder num
4612                                 (wl-message-make-display-type
4613                                  (or mime-mode
4614                                      (wl-summary-buffer-display-mime-mode))
4615                                  (or header-mode
4616                                      (wl-summary-buffer-display-header-mode)))
4617                                 (or force-reload
4618                                     (string= (elmo-folder-name-internal folder)
4619                                              wl-draft-folder)))
4620           (when (elmo-message-use-cache-p folder num)
4621             (elmo-message-set-cached folder num t))
4622           (ignore-errors
4623             (if (elmo-message-flagged-p wl-summary-buffer-elmo-folder
4624                                         num
4625                                         'unread)
4626                 (wl-summary-mark-as-read num)
4627               (wl-summary-count-unread)
4628               (wl-summary-update-modeline)
4629               (wl-folder-update-unread
4630                (wl-summary-buffer-folder-name)
4631                wl-summary-buffer-unread-count)))
4632           (setq wl-summary-buffer-current-msg num)
4633           (when wl-summary-recenter
4634             (recenter (/ (- (window-height) 2) 2))
4635             (if (not wl-summary-indent-length-limit)
4636                 (wl-horizontal-recenter)))
4637           (wl-highlight-summary-displaying)
4638           (wl-message-buffer-prefetch-next
4639            folder num
4640            (min (or wl-message-buffer-prefetch-depth 0)
4641                 (1- wl-message-buffer-cache-size))
4642            (current-buffer)
4643            wl-summary-buffer-mime-charset)
4644           (run-hooks 'wl-summary-redisplay-hook))
4645       (message "No message to display."))))
4646
4647 (defun wl-summary-jump-to-current-message ()
4648   "Jump into Message buffer."
4649   (interactive)
4650   (let (message-buf message-win)
4651     (if (setq message-buf wl-message-buffer)
4652         (if (setq message-win (get-buffer-window message-buf))
4653             (select-window message-win)
4654           (wl-message-select-buffer wl-message-buffer))
4655       (wl-summary-redisplay)
4656       (wl-message-select-buffer wl-message-buffer))))
4657
4658 (defun wl-summary-cancel-message ()
4659   "Cancel an article on news."
4660   (interactive)
4661   (if (null (wl-summary-message-number))
4662       (message "No message.")
4663     (let ((summary-buf (current-buffer))
4664           message-buf)
4665       (wl-summary-set-message-buffer-or-redisplay)
4666       (if (setq message-buf (wl-message-get-original-buffer))
4667           (set-buffer message-buf))
4668       (unless (wl-message-news-p)
4669         (set-buffer summary-buf)
4670         (if (and (eq (elmo-folder-type-internal wl-summary-buffer-elmo-folder)
4671                      'nntp)
4672                  (y-or-n-p "Cannot get Newsgroups. Fetch again? "))
4673             (progn
4674               (wl-summary-redisplay t)
4675               (wl-summary-supersedes-message))
4676           (error "This is not a news article; supersedes is impossible")))
4677       (when (yes-or-no-p "Do you really want to cancel this article? ")
4678         (let (from newsgroups message-id distribution buf)
4679           (save-excursion
4680             (setq from (std11-field-body "from")
4681                   newsgroups (std11-field-body "newsgroups")
4682                   message-id (std11-field-body "message-id")
4683                   distribution (std11-field-body "distribution"))
4684             ;; Make sure that this article was written by the user.
4685             (unless (wl-address-user-mail-address-p
4686                      (wl-address-header-extract-address
4687                       (car (wl-parse-addresses from))))
4688               (error "This article is not yours"))
4689             ;; Make control message.
4690             (setq buf (set-buffer (get-buffer-create " *message cancel*")))
4691             (setq wl-draft-buffer-cur-summary-buffer summary-buf)
4692             (buffer-disable-undo (current-buffer))
4693             (erase-buffer)
4694             (insert "Newsgroups: " newsgroups "\n"
4695                     "From: " (wl-address-header-extract-address
4696                               wl-from) "\n"
4697                               "Subject: cmsg cancel " message-id "\n"
4698                               "Control: cancel " message-id "\n"
4699                               (if distribution
4700                                   (concat "Distribution: " distribution "\n")
4701                                 "")
4702                               mail-header-separator "\n"
4703                               wl-summary-cancel-message)
4704             (message "Canceling your message...")
4705             (wl-draft-raw-send t t) ; kill when done, force-pre-hooks.
4706             (message "Canceling your message...done")))))))
4707
4708 (defun wl-summary-supersedes-message ()
4709   "Supersede current message."
4710   (interactive)
4711   (wl-summary-toggle-disp-msg 'off)
4712   (let ((summary-buf (current-buffer))
4713         message-buf from)
4714     (wl-summary-set-message-buffer-or-redisplay)
4715     (if (setq message-buf (wl-message-get-original-buffer))
4716         (set-buffer message-buf))
4717     (unless (wl-message-news-p)
4718       (set-buffer summary-buf)
4719       (if (and (eq (elmo-folder-type-internal wl-summary-buffer-elmo-folder)
4720                    'nntp)
4721                (y-or-n-p "Cannot get Newsgroups. Fetch again? "))
4722           (progn
4723             (wl-summary-redisplay t)
4724             (wl-summary-supersedes-message))
4725         (error "This is not a news article; supersedes is impossible")))
4726     (save-excursion
4727       (setq from (std11-field-body "from"))
4728       ;; Make sure that this article was written by the user.
4729       (unless (wl-address-user-mail-address-p
4730                (wl-address-header-extract-address
4731                 (car (wl-parse-addresses from))))
4732         (error "This article is not yours"))
4733       (let* ((message-id (std11-field-body "message-id"))
4734              (followup-to (std11-field-body "followup-to"))
4735              (mail-default-headers
4736               (concat mail-default-headers
4737                       "Supersedes: " message-id "\n"
4738                       (and followup-to
4739                            (concat "Followup-To: " followup-to "\n")))))
4740         (if message-buf (set-buffer message-buf))
4741         (wl-draft-edit-string (buffer-substring (point-min) (point-max)))))))
4742
4743 (defun wl-summary-save (&optional arg wl-save-dir)
4744   "Save current message to disk."
4745   (interactive)
4746   (let ((filename)
4747         (num (wl-summary-message-number)))
4748     (unless wl-save-dir
4749       (setq wl-save-dir wl-temporary-file-directory))
4750     (if num
4751         (save-excursion
4752           (setq filename (expand-file-name
4753                           (concat (int-to-string num)
4754                                   wl-summary-save-file-suffix)
4755                           wl-save-dir))
4756           (when (or (null arg)
4757                     (file-exists-p filename))
4758             (setq filename (read-file-name "Save to file: " filename)))
4759           (wl-summary-set-message-buffer-or-redisplay)
4760           (set-buffer (wl-message-get-original-buffer))
4761           (when (or arg
4762                     (not (file-exists-p filename))
4763                     (y-or-n-p "File already exists.  override it? "))
4764             (write-region-as-binary (point-min) (point-max) filename)))
4765       (message "No message to save."))
4766     num))
4767
4768 (defun wl-summary-save-region (beg end)
4769   (interactive "r")
4770   (save-excursion
4771     (save-restriction
4772       (wl-summary-narrow-to-region beg end)
4773       (goto-char (point-min))
4774       (let ((wl-save-dir
4775              (wl-read-directory-name "Save to directory: "
4776                                      wl-temporary-file-directory)))
4777         (if (null (file-exists-p wl-save-dir))
4778             (make-directory wl-save-dir))
4779         (if (eq wl-summary-buffer-view 'thread)
4780             (progn
4781               (while (not (eobp))
4782                 (let* ((number (wl-summary-message-number))
4783                        (entity (wl-thread-get-entity number)))
4784                   (if (wl-thread-entity-get-opened entity)
4785                       (wl-summary-save t wl-save-dir)
4786                     ;; closed
4787                     (wl-summary-save t wl-save-dir))
4788                   (forward-line 1))))
4789           (while (not (eobp))
4790             (wl-summary-save t wl-save-dir)
4791             (forward-line 1)))))))
4792
4793 ;; mew-summary-pipe-message()
4794 (defun wl-summary-pipe-message (prefix command)
4795   "Send this message via pipe."
4796   (interactive (list current-prefix-arg nil))
4797   (if (null (wl-summary-message-number))
4798       (message "No message.")
4799     (setq command (read-string "Shell command on message: "
4800                                wl-summary-shell-command-last))
4801     (if (y-or-n-p "Send this message to pipe? ")
4802         (wl-summary-pipe-message-subr prefix command))))
4803
4804 (defun wl-summary-target-mark-pipe (prefix command)
4805   "Send each marked messages via pipe."
4806   (interactive (list current-prefix-arg nil))
4807   (if (null wl-summary-buffer-target-mark-list)
4808       (message "No marked message.")
4809     (setq command (read-string "Shell command on each marked message: "
4810                                wl-summary-shell-command-last))
4811     (when (y-or-n-p "Send each marked message to pipe? ")
4812       (while (car wl-summary-buffer-target-mark-list)
4813         (let ((num (car wl-summary-buffer-target-mark-list)))
4814           (wl-thread-jump-to-msg num)
4815           (wl-summary-pipe-message-subr prefix command)
4816           (wl-summary-unmark))))))
4817
4818 (defun wl-summary-pipe-message-subr (prefix command)
4819   (save-excursion
4820     (wl-summary-set-message-buffer-or-redisplay)
4821     (set-buffer (wl-message-get-original-buffer))
4822     (if (string= command "")
4823         (setq command wl-summary-shell-command-last))
4824     (goto-char (point-min)) ; perhaps this line won't be necessary
4825     (if prefix
4826         (search-forward "\n\n"))
4827     (shell-command-on-region (point) (point-max) command nil)
4828     (setq wl-summary-shell-command-last command)))
4829
4830 (defun wl-summary-print-message (&optional arg)
4831   (interactive "P")
4832   (if (null (wl-summary-message-number))
4833       (message "No message.")
4834     (save-excursion
4835       (wl-summary-set-message-buffer-or-redisplay)
4836       (if (or (not (interactive-p))
4837               (y-or-n-p "Print ok? "))
4838           (progn
4839             (let ((buffer (generate-new-buffer " *print*")))
4840               (copy-to-buffer buffer (point-min) (point-max))
4841               (set-buffer buffer)
4842               (funcall wl-print-buffer-function)
4843               (kill-buffer buffer)))
4844         (message "")))))
4845
4846 (defun wl-summary-print-message-with-ps-print (&optional filename)
4847   "Print message via ps-print."
4848   (interactive)
4849   (if (null (wl-summary-message-number))
4850       (message "No message.")
4851     (setq filename (ps-print-preprint current-prefix-arg))
4852     (if (or (not (interactive-p))
4853             (y-or-n-p "Print ok? "))
4854         (let ((summary-buffer (current-buffer))
4855               wl-break-pages)
4856           (save-excursion
4857             (wl-summary-set-message-buffer-or-redisplay)
4858             (let* ((buffer (generate-new-buffer " *print*"))
4859                    (entity (progn
4860                              (set-buffer summary-buffer)
4861                              (elmo-message-entity
4862                               wl-summary-buffer-elmo-folder
4863                               (wl-summary-message-number))))
4864                    (wl-ps-subject
4865                     (and entity
4866                          (or (elmo-message-entity-field entity 'subject t)
4867                              "")))
4868                    (wl-ps-from
4869                     (and entity
4870                          (or (elmo-message-entity-field entity 'from t) "")))
4871                    (wl-ps-date
4872                     (and entity
4873                          (or (elmo-message-entity-field entity 'date) ""))))
4874               (run-hooks 'wl-ps-preprint-hook)
4875               (set-buffer wl-message-buffer)
4876               (copy-to-buffer buffer (point-min) (point-max))
4877               (set-buffer buffer)
4878               (unwind-protect
4879                   (let ((ps-left-header
4880                          (list (concat "(" wl-ps-subject ")")
4881                                (concat "(" wl-ps-from ")")))
4882                         (ps-right-header
4883                          (list "/pagenumberstring load"
4884                                (concat "(" wl-ps-date ")"))))
4885                     (run-hooks 'wl-ps-print-hook)
4886                     (funcall wl-ps-print-buffer-function filename))
4887                 (kill-buffer buffer)))))
4888       (message ""))))
4889
4890 (if (featurep 'ps-print) ; ps-print is available.
4891     (fset 'wl-summary-print-message 'wl-summary-print-message-with-ps-print))
4892
4893 (defun wl-summary-target-mark-print ()
4894   (interactive)
4895   (wl-summary-check-target-mark)
4896   (when (y-or-n-p "Print all marked messages. OK? ")
4897     (while (car wl-summary-buffer-target-mark-list)
4898       (let ((num (car wl-summary-buffer-target-mark-list)))
4899         (wl-thread-jump-to-msg num)
4900         (wl-summary-print-message)
4901         (wl-summary-unmark)))))
4902
4903 (defun wl-summary-folder-info-update ()
4904   (wl-folder-set-folder-updated
4905    (elmo-string (wl-summary-buffer-folder-name))
4906    (list 0
4907          wl-summary-buffer-unread-count
4908          (elmo-folder-length
4909           wl-summary-buffer-elmo-folder))))
4910
4911 (defun wl-summary-get-original-buffer ()
4912   "Get original buffer for the current summary."
4913   (save-excursion
4914     (wl-summary-set-message-buffer-or-redisplay)
4915     (wl-message-get-original-buffer)))
4916
4917 (defun wl-summary-pack-number (&optional arg)
4918   (interactive "P")
4919   (elmo-folder-pack-numbers wl-summary-buffer-elmo-folder)
4920   (let (wl-use-scoring)
4921     (wl-summary-rescan nil nil nil t)))
4922
4923 (defun wl-summary-target-mark-uudecode ()
4924   (interactive)
4925   (wl-summary-check-target-mark)
4926   (let ((mlist (reverse wl-summary-buffer-target-mark-list))
4927         (summary-buf (current-buffer))
4928         (tmp-buf (get-buffer-create "*WL UUENCODE*"))
4929         orig-buf i k filename rc errmsg)
4930     (setq i 1)
4931     (setq k (length mlist))
4932     (set-buffer tmp-buf)
4933     (erase-buffer)
4934     (save-window-excursion
4935       (while mlist
4936         (set-buffer summary-buf)
4937         (wl-summary-jump-to-msg (car mlist))
4938         (wl-summary-redisplay)
4939         (set-buffer (setq orig-buf (wl-summary-get-original-buffer)))
4940         (goto-char (point-min))
4941         (cond ((= i 1) ; first
4942                (if (setq filename (wl-message-uu-substring
4943                                    orig-buf tmp-buf t
4944                                    (= i k)))
4945                    nil
4946                  (error "Can't find begin line")))
4947               ((< i k)
4948                (wl-message-uu-substring orig-buf tmp-buf))
4949               (t ; last
4950                (wl-message-uu-substring orig-buf tmp-buf nil t)))
4951         (setq i (1+ i))
4952         (setq mlist (cdr mlist)))
4953       (set-buffer tmp-buf)
4954       (message "Exec %s..." wl-prog-uudecode)
4955       (unwind-protect
4956           (let ((decode-dir wl-temporary-file-directory))
4957             (if (not wl-prog-uudecode-no-stdout-option)
4958                 (setq filename (read-file-name "Save to file: "
4959                                                (expand-file-name
4960                                                 (elmo-safe-filename filename)
4961                                                 wl-temporary-file-directory)))
4962               (setq decode-dir
4963                     (wl-read-directory-name "Save to directory: "
4964                                             wl-temporary-file-directory))
4965               (setq filename (expand-file-name filename decode-dir)))
4966             (if (file-exists-p filename)
4967                 (or (yes-or-no-p (format "File %s exists. Save anyway? "
4968                                          filename))
4969                     (error "")))
4970             (elmo-bind-directory
4971              decode-dir
4972              (setq rc
4973                    (as-binary-process
4974                     (apply 'call-process-region (point-min) (point-max)
4975                            wl-prog-uudecode t (current-buffer) nil
4976                            wl-prog-uudecode-arg))))
4977             (when (not (= 0 rc))
4978               (setq errmsg (buffer-substring (point-min)(point-max)))
4979               (error "Uudecode error: %s" errmsg))
4980             (if (not wl-prog-uudecode-no-stdout-option)
4981                 (let (file-name-handler-alist) ;; void jka-compr
4982                   (as-binary-output-file
4983                    (write-region (point-min) (point-max)
4984                                  filename nil 'no-msg))))
4985             (save-excursion
4986               (set-buffer summary-buf)
4987               (wl-summary-delete-all-target-marks))
4988             (if (file-exists-p filename)
4989                 (message "Saved as %s" filename)))
4990         (kill-buffer tmp-buf)))))
4991
4992 ;; Someday
4993 ;; (defun wl-summary-drop-unsync ()
4994 ;;   "Drop all unsync messages."
4995 ;;   (interactive)
4996 ;;   (if (elmo-folder-pipe-p (wl-summary-buffer-folder-name))
4997 ;;       (error "You cannot drop unsync messages in this folder"))
4998 ;;   (if (or (not (interactive-p))
4999 ;;        (y-or-n-p "Drop all unsync messages? "))
5000 ;;       (let* ((folder-list (elmo-folder-get-primitive-folder-list
5001 ;;                         (wl-summary-buffer-folder-name)))
5002 ;;           (is-multi (elmo-multi-p (wl-summary-buffer-folder-name)))
5003 ;;           (sum 0)
5004 ;;           (multi-num 0)
5005 ;;           pair)
5006 ;;      (message "Dropping...")
5007 ;;      (while folder-list
5008 ;;        (setq pair (elmo-folder-message-numbers (car folder-list)))
5009 ;;        (when is-multi ;; dirty hack...
5010 ;;          (incf multi-num)
5011 ;;          (setcar pair (+ (* multi-num elmo-multi-divide-number)
5012 ;;                          (car pair))))
5013 ;;        (elmo-msgdb-set-number-alist
5014 ;;         (wl-summary-buffer-msgdb)
5015 ;;         (nconc
5016 ;;          (elmo-msgdb-get-number-alist (wl-summary-buffer-msgdb))
5017 ;;          (list (cons (car pair) nil))))
5018 ;;        (setq sum (+ sum (cdr pair)))
5019 ;;        (setq folder-list (cdr folder-list)))
5020 ;;      (wl-summary-set-message-modified)
5021 ;;      (wl-folder-set-folder-updated (wl-summary-buffer-folder-name)
5022 ;;                                    (list 0
5023 ;;                                          (+ wl-summary-buffer-unread-count
5024 ;;                                             wl-summary-buffer-new-count)
5025 ;;                                          sum))
5026 ;;      (message "Dropping...done"))))
5027
5028 (defun wl-summary-default-get-next-msg (msg)
5029   (or (wl-summary-next-message msg
5030                                (if wl-summary-move-direction-downward 'down
5031                                  'up)
5032                                nil)
5033       (cadr (memq msg (if wl-summary-move-direction-downward
5034                           wl-summary-buffer-number-list
5035                         (reverse wl-summary-buffer-number-list))))))
5036
5037 (defun wl-summary-save-current-message ()
5038   "Save current message for `wl-summary-yank-saved-message'."
5039   (interactive)
5040   (let ((number (wl-summary-message-number)))
5041     (setq wl-summary-buffer-saved-message number)
5042     (and number (message "No: %s is saved." number))))
5043
5044 (defun wl-summary-yank-saved-message ()
5045   "Set current message as a parent of the saved message."
5046   (interactive)
5047   (if wl-summary-buffer-saved-message
5048       (let ((number (wl-summary-message-number)))
5049         (if (eq wl-summary-buffer-saved-message number)
5050             (message "Cannot set itself as a parent.")
5051           (save-excursion
5052             (wl-thread-jump-to-msg wl-summary-buffer-saved-message)
5053             (wl-thread-set-parent number)
5054             (wl-summary-set-thread-modified))
5055           (setq  wl-summary-buffer-saved-message nil)))
5056     (message "There's no saved message.")))
5057
5058 (defun wl-summary-toggle-header-narrowing ()
5059   "Toggle message header narrowing."
5060   (interactive)
5061   (when wl-message-use-header-narrowing
5062     (save-selected-window
5063       (let* ((mbuf wl-message-buffer)
5064              (mwin (when mbuf (get-buffer-window mbuf)))
5065              (wpos (when mwin (window-start mwin))))
5066         (when mbuf
5067           (set-buffer mbuf)
5068           (wl-message-header-narrowing-toggle)
5069           (and wpos (set-window-start mwin wpos)))))))
5070
5071 (require 'product)
5072 (product-provide (provide 'wl-summary) (require 'wl-version))
5073
5074 ;;; wl-summary.el ends here