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