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