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