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