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