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