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