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