(x_make_frame_visible): Call signal handler directly.
[bpt/emacs.git] / lisp / mail / rmailsum.el
CommitLineData
76550a57 1;;; rmailsum.el --- make summary buffers for the mail reader
aae56ea7 2
d733c5ec 3;; Copyright (C) 1985, 1993, 1994 Free Software Foundation, Inc.
9750e079 4
e5167999 5;; Maintainer: FSF
d7b4d18f 6;; Keywords: mail
e5167999 7
4d4d11cc
JB
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
e5167999 12;; the Free Software Foundation; either version 2, or (at your option)
4d4d11cc
JB
13;; any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs; see the file COPYING. If not, write to
22;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23
aae56ea7
ER
24;;; Commentary:
25
d41d75fb
RS
26;; Extended by Bob Weiner of Motorola
27;; Provided all commands from rmail-mode in rmail-summary-mode and made key
28;; bindings in both modes wholly compatible.
29
aae56ea7
ER
30;;; Code:
31
d41d75fb 32;; Entry points for making a summary buffer.
4d4d11cc 33
d41d75fb
RS
34;; Regenerate the contents of the summary
35;; using the same selection criterion as last time.
36;; M-x revert-buffer in a summary buffer calls this function.
37(defun rmail-update-summary (&rest ignore)
38 (apply (car rmail-summary-redo) (cdr rmail-summary-redo)))
4d4d11cc
JB
39
40(defun rmail-summary ()
41 "Display a summary of all messages, one line per message."
42 (interactive)
d41d75fb 43 (rmail-new-summary "All" '(rmail-summary) nil))
4d4d11cc
JB
44
45(defun rmail-summary-by-labels (labels)
46 "Display a summary of all messages with one or more LABELS.
47LABELS should be a string containing the desired labels, separated by commas."
48 (interactive "sLabels to summarize by: ")
49 (if (string= labels "")
50 (setq labels (or rmail-last-multi-labels
51 (error "No label specified"))))
52 (setq rmail-last-multi-labels labels)
53 (rmail-new-summary (concat "labels " labels)
d41d75fb 54 (list 'rmail-summary-by-labels labels)
4d4d11cc
JB
55 'rmail-message-labels-p
56 (concat ", \\(" (mail-comma-list-regexp labels) "\\),")))
57
58(defun rmail-summary-by-recipients (recipients &optional primary-only)
59 "Display a summary of all messages with the given RECIPIENTS.
60Normally checks the To, From and Cc fields of headers;
61but if PRIMARY-ONLY is non-nil (prefix arg given),
62 only look in the To and From fields.
d41d75fb 63RECIPIENTS is a string of regexps separated by commas."
4d4d11cc
JB
64 (interactive "sRecipients to summarize by: \nP")
65 (rmail-new-summary
66 (concat "recipients " recipients)
d41d75fb 67 (list 'rmail-summary-by-recipients recipients primary-only)
4d4d11cc
JB
68 'rmail-message-recipients-p
69 (mail-comma-list-regexp recipients) primary-only))
70
4d4d11cc
JB
71(defun rmail-summary-by-regexp (regexp)
72 "Display a summary of all messages according to regexp REGEXP.
73If the regular expression is found in the header of the message
74\(including in the date and other lines, as well as the subject line),
75Emacs will list the header line in the RMAIL-summary."
76 (interactive "sRegexp to summarize by: ")
77 (if (string= regexp "")
78 (setq regexp (or rmail-last-regexp
d41d75fb 79 (error "No regexp specified."))))
4d4d11cc
JB
80 (setq rmail-last-regexp regexp)
81 (rmail-new-summary (concat "regexp " regexp)
d41d75fb 82 (list 'rmail-summary-by-regexp regexp)
4d4d11cc
JB
83 'rmail-message-regexp-p
84 regexp))
85
d41d75fb
RS
86;; rmail-summary-by-topic
87;; 1989 R.A. Schnitzler
88
89(defun rmail-summary-by-topic (subject &optional whole-message)
90 "Display a summary of all messages with the given SUBJECT.
91Normally checks the Subject field of headers;
92but if WHOLE-MESSAGE is non-nil (prefix arg given),
93 look in the whole message.
94SUBJECT is a string of regexps separated by commas."
95 (interactive "sTopics to summarize by: \nP")
96 (rmail-new-summary
97 (concat "about " subject)
98 (list 'rmail-summary-by-topic subject whole-message)
99 'rmail-message-subject-p
100 (mail-comma-list-regexp subject) whole-message))
101
102(defun rmail-message-subject-p (msg subject &optional whole-message)
103 (save-restriction
104 (goto-char (rmail-msgbeg msg))
105 (search-forward "\n*** EOOH ***\n")
106 (narrow-to-region
107 (point)
e90b6d92 108 (progn (search-forward (if whole-message "\^_" "\n\n")) (point)))
d41d75fb
RS
109 (goto-char (point-min))
110 (if whole-message (re-search-forward subject nil t)
111 (string-match subject (or (mail-fetch-field "Subject") "")) )))
cad1e93b
RS
112
113(defun rmail-summary-by-senders (senders)
114 "Display a summary of all messages with the given SENDERS.
115SENDERS is a string of names separated by commas."
116 (interactive "sSenders to summarize by: ")
117 (rmail-new-summary
118 (concat "senders " senders)
84fa8eb5 119 (list 'rmail-summary-by-senders senders)
cad1e93b
RS
120 'rmail-message-senders-p
121 (mail-comma-list-regexp senders)))
122
123(defun rmail-message-senders-p (msg senders)
124 (save-restriction
125 (goto-char (rmail-msgbeg msg))
126 (search-forward "\n*** EOOH ***\n")
127 (narrow-to-region (point) (progn (search-forward "\n\n") (point)))
128 (string-match senders (or (mail-fetch-field "From") ""))))
4d4d11cc 129\f
d41d75fb
RS
130;; General making of a summary buffer.
131
132(defvar rmail-summary-symbol-number 0)
133
134(defun rmail-new-summary (description redo-form function &rest args)
4d4d11cc
JB
135 "Create a summary of selected messages.
136DESCRIPTION makes part of the mode line of the summary buffer.
137For each message, FUNCTION is applied to the message number and ARGS...
138and if the result is non-nil, that message is included.
139nil for FUNCTION means all messages."
140 (message "Computing summary lines...")
d41d75fb
RS
141 (let (sumbuf mesg was-in-summary)
142 (save-excursion
143 ;; Go to the Rmail buffer.
144 (if (eq major-mode 'rmail-summary-mode)
145 (progn
146 (setq was-in-summary t)
147 (set-buffer rmail-buffer)))
148 ;; Find its summary buffer, or make one.
deb5848d
RS
149 (setq sumbuf
150 (if (and rmail-summary-buffer
151 (buffer-name rmail-summary-buffer))
152 rmail-summary-buffer
153 (generate-new-buffer (concat (buffer-name) "-summary"))))
d41d75fb 154 (setq mesg rmail-current-message)
d41d75fb
RS
155 ;; Filter the messages; make or get their summary lines.
156 (let ((summary-msgs ())
157 (new-summary-line-count 0))
158 (let ((msgnum 1)
36f41915
KH
159 (buffer-read-only nil)
160 (old-min (point-min-marker))
161 (old-max (point-max-marker)))
162 ;; Can't use save-restriction here; that doesn't work if we
163 ;; plan to modify text outside the original restriction.
164 (save-excursion
165 (widen)
166 (goto-char (point-min))
167 (while (>= rmail-total-messages msgnum)
168 (if (or (null function)
169 (apply function (cons msgnum args)))
170 (setq summary-msgs
171 (cons (cons msgnum (rmail-make-summary-line msgnum))
172 summary-msgs)))
173 (setq msgnum (1+ msgnum)))
174 (setq summary-msgs (nreverse summary-msgs)))
175 (narrow-to-region old-min old-max))
deb5848d
RS
176 ;; Temporarily, while summary buffer is unfinished,
177 ;; we "don't have" a summary.
178 (setq rmail-summary-buffer nil)
179 (save-excursion
180 (let ((rbuf (current-buffer))
181 (total rmail-total-messages))
182 (set-buffer sumbuf)
183 ;; Set up the summary buffer's contents.
184 (let ((buffer-read-only nil))
185 (erase-buffer)
186 (while summary-msgs
187 (princ (cdr (car summary-msgs)) sumbuf)
188 (setq summary-msgs (cdr summary-msgs)))
189 (goto-char (point-min)))
190 ;; Set up the rest of its state and local variables.
191 (setq buffer-read-only t)
192 (rmail-summary-mode)
193 (make-local-variable 'minor-mode-alist)
b37767e7 194 (setq minor-mode-alist (list '(t (concat ": " description))))
deb5848d
RS
195 (setq rmail-buffer rbuf
196 rmail-summary-redo redo-form
197 rmail-total-messages total))))
198 (setq rmail-summary-buffer sumbuf))
d41d75fb
RS
199 ;; Now display the summary buffer and go to the right place in it.
200 (or was-in-summary
3f4e31a2
RS
201 (if (one-window-p)
202 ;; If there is just one window, put the summary on the top.
203 (progn
204 (split-window)
205 (select-window (next-window (frame-first-window)))
206 (pop-to-buffer sumbuf)
207 ;; If pop-to-buffer did not use that window, delete that
208 ;; window. (This can happen if it uses another frame.)
209 (if (not (eq sumbuf (window-buffer (frame-first-window))))
210 (delete-other-windows)))
211 (pop-to-buffer sumbuf)))
d41d75fb
RS
212 (rmail-summary-goto-msg mesg t t)
213 (message "Computing summary lines...done")))
214\f
215;; Low levels of generating a summary.
4d4d11cc
JB
216
217(defun rmail-make-summary-line (msg)
218 (let ((line (or (aref rmail-summary-vector (1- msg))
219 (progn
220 (setq new-summary-line-count
221 (1+ new-summary-line-count))
222 (if (zerop (% new-summary-line-count 10))
223 (message "Computing summary lines...%d"
224 new-summary-line-count))
225 (rmail-make-summary-line-1 msg)))))
226 ;; Fix up the part of the summary that says "deleted" or "unseen".
227 (aset line 4
228 (if (rmail-message-deleted-p msg) ?\D
229 (if (= ?0 (char-after (+ 3 (rmail-msgbeg msg))))
230 ?\- ?\ )))
231 line))
232
233(defun rmail-make-summary-line-1 (msg)
234 (goto-char (rmail-msgbeg msg))
235 (let* ((lim (save-excursion (forward-line 2) (point)))
236 pos
237 (labels
238 (progn
239 (forward-char 3)
240 (concat
241; (if (save-excursion (re-search-forward ",answered," lim t))
242; "*" "")
243; (if (save-excursion (re-search-forward ",filed," lim t))
244; "!" "")
245 (if (progn (search-forward ",,") (eolp))
246 ""
247 (concat "{"
248 (buffer-substring (point)
249 (progn (end-of-line) (point)))
250 "} ")))))
251 (line
252 (progn
253 (forward-line 1)
254 (if (looking-at "Summary-line: ")
255 (progn
256 (goto-char (match-end 0))
257 (setq line
258 (buffer-substring (point)
259 (progn (forward-line 1) (point)))))))))
260 ;; Obsolete status lines lacking a # should be flushed.
261 (and line
262 (not (string-match "#" line))
263 (progn
264 (delete-region (point)
265 (progn (forward-line -1) (point)))
266 (setq line nil)))
267 ;; If we didn't get a valid status line from the message,
268 ;; make a new one and put it in the message.
269 (or line
270 (let* ((case-fold-search t)
271 (next (rmail-msgend msg))
272 (beg (if (progn (goto-char (rmail-msgbeg msg))
273 (search-forward "\n*** EOOH ***\n" next t))
274 (point)
275 (forward-line 1)
276 (point)))
277 (end (progn (search-forward "\n\n" nil t) (point))))
278 (save-restriction
279 (narrow-to-region beg end)
280 (goto-char beg)
281 (setq line (rmail-make-basic-summary-line)))
282 (goto-char (rmail-msgbeg msg))
283 (forward-line 2)
284 (insert "Summary-line: " line)))
285 (setq pos (string-match "#" line))
286 (aset rmail-summary-vector (1- msg)
287 (concat (format "%4d " msg)
288 (substring line 0 pos)
289 labels
290 (substring line (1+ pos))))))
291
292(defun rmail-make-basic-summary-line ()
293 (goto-char (point-min))
294 (concat (save-excursion
295 (if (not (re-search-forward "^Date:" nil t))
296 " "
297 (cond ((re-search-forward "\\([^0-9:]\\)\\([0-3]?[0-9]\\)\\([- \t_]+\\)\\([adfjmnos][aceopu][bcglnprtvy]\\)"
298 (save-excursion (end-of-line) (point)) t)
299 (format "%2d-%3s"
300 (string-to-int (buffer-substring
301 (match-beginning 2)
302 (match-end 2)))
303 (buffer-substring
304 (match-beginning 4) (match-end 4))))
305 ((re-search-forward "\\([^a-z]\\)\\([adfjmnos][acepou][bcglnprtvy]\\)\\([-a-z \t_]*\\)\\([0-9][0-9]?\\)"
306 (save-excursion (end-of-line) (point)) t)
307 (format "%2d-%3s"
308 (string-to-int (buffer-substring
309 (match-beginning 4)
310 (match-end 4)))
311 (buffer-substring
312 (match-beginning 2) (match-end 2))))
313 (t "??????"))))
314 " "
315 (save-excursion
316 (if (not (re-search-forward "^From:[ \t]*" nil t))
317 " "
318 (let* ((from (mail-strip-quoted-names
319 (buffer-substring
320 (1- (point))
4f5d303b
RS
321 ;; Get all the lines of the From field
322 ;; so that we get a whole comment if there is one,
323 ;; so that mail-strip-quoted-names can discard it.
324 (let ((opoint (point)))
325 (while (progn (forward-line 1)
326 (looking-at "[ \t]")))
327 ;; Back up over newline, then trailing spaces or tabs
328 (forward-char -1)
329 (skip-chars-backward " \t")
330 (point)))))
331 len mch lo)
4d4d11cc
JB
332 (if (string-match (concat "^"
333 (regexp-quote (user-login-name))
334 "\\($\\|@\\)")
335 from)
336 (save-excursion
337 (goto-char (point-min))
338 (if (not (re-search-forward "^To:[ \t]*" nil t))
339 nil
340 (setq from
341 (concat "to: "
342 (mail-strip-quoted-names
343 (buffer-substring
344 (point)
345 (progn (end-of-line)
346 (skip-chars-backward " \t")
347 (point)))))))))
348 (setq len (length from))
349 (setq mch (string-match "[@%]" from))
350 (format "%25s"
351 (if (or (not mch) (<= len 25))
352 (substring from (max 0 (- len 25)))
353 (substring from
95412165
RS
354 (setq lo (cond ((< (- mch 14) 0) 0)
355 ((< len (+ mch 11))
4d4d11cc 356 (- len 25))
95412165 357 (t (- mch 14))))
4d4d11cc
JB
358 (min len (+ lo 25))))))))
359 " #"
360 (if (re-search-forward "^Subject:" nil t)
361 (progn (skip-chars-forward " \t")
362 (buffer-substring (point)
363 (progn (end-of-line)
364 (point))))
365 (re-search-forward "[\n][\n]+" nil t)
366 (buffer-substring (point) (progn (end-of-line) (point))))
367 "\n"))
d41d75fb
RS
368\f
369;; Simple motion in a summary buffer.
4d4d11cc
JB
370
371(defun rmail-summary-next-all (&optional number)
372 (interactive "p")
bb694792
RS
373 (forward-line (if number number 1))
374 (display-buffer rmail-buffer))
4d4d11cc
JB
375
376(defun rmail-summary-previous-all (&optional number)
377 (interactive "p")
bb694792
RS
378 (forward-line (- (if number number 1)))
379 (display-buffer rmail-buffer))
4d4d11cc
JB
380
381(defun rmail-summary-next-msg (&optional number)
d41d75fb
RS
382 "Display next non-deleted msg from rmail file.
383With optional prefix argument NUMBER, moves forward this number of non-deleted
384messages, or backward if NUMBER is negative."
4d4d11cc
JB
385 (interactive "p")
386 (forward-line 0)
b37767e7 387 (and (> number 0) (end-of-line))
4d4d11cc
JB
388 (let ((count (if (< number 0) (- number) number))
389 (search (if (> number 0) 're-search-forward 're-search-backward))
d41d75fb
RS
390 (non-del-msg-found nil))
391 (while (and (> count 0) (setq non-del-msg-found
682ac5eb 392 (or (funcall search "^....[^D]" nil t)
d41d75fb 393 non-del-msg-found)))
bb694792 394 (setq count (1- count))))
b37767e7 395 (beginning-of-line)
bb694792 396 (display-buffer rmail-buffer))
4d4d11cc
JB
397
398(defun rmail-summary-previous-msg (&optional number)
399 (interactive "p")
400 (rmail-summary-next-msg (- (if number number 1))))
401
d41d75fb
RS
402(defun rmail-summary-next-labeled-message (n labels)
403 "Show next message with LABEL. Defaults to last labels used.
404With prefix argument N moves forward N messages with these labels."
405 (interactive "p\nsMove to next msg with labels: ")
406 (save-excursion
407 (set-buffer rmail-buffer)
408 (rmail-next-labeled-message n labels)))
409
410(defun rmail-summary-previous-labeled-message (n labels)
411 "Show previous message with LABEL. Defaults to last labels used.
412With prefix argument N moves backward N messages with these labels."
413 (interactive "p\nsMove to previous msg with labels: ")
414 (save-excursion
415 (set-buffer rmail-buffer)
416 (rmail-previous-labeled-message n labels)))
417\f
418;; Delete and undelete summary commands.
419
420(defun rmail-summary-delete-forward (&optional backward)
421 "Delete this message and move to next nondeleted one.
422Deleted messages stay in the file until the \\[rmail-expunge] command is given.
423With prefix argument, delete and move backward."
424 (interactive "P")
4d4d11cc
JB
425 (let (end)
426 (rmail-summary-goto-msg)
427 (pop-to-buffer rmail-buffer)
92a38267
RS
428 (rmail-delete-message)
429 (let ((del-msg rmail-current-message))
430 (pop-to-buffer rmail-summary-buffer)
431 (rmail-summary-mark-deleted del-msg)
432 (while (and (not (if backward (bobp) (eobp)))
94eeb96a
RS
433 (save-excursion (beginning-of-line)
434 (looking-at " +[0-9]+D")))
92a38267 435 (forward-line (if backward -1 1))))))
4d4d11cc
JB
436
437(defun rmail-summary-delete-backward ()
d41d75fb
RS
438 "Delete this message and move to previous nondeleted one.
439Deleted messages stay in the file until the \\[rmail-expunge] command is given."
4d4d11cc 440 (interactive)
d41d75fb 441 (rmail-summary-delete-forward t))
4d4d11cc 442
d41d75fb 443(defun rmail-summary-mark-deleted (&optional n undel)
fedc33f7
RS
444 (and n (rmail-summary-goto-msg n t t))
445 (or (eobp)
446 (let ((buffer-read-only nil))
447 (skip-chars-forward " ")
448 (skip-chars-forward "[0-9]")
449 (if undel
450 (if (looking-at "D")
451 (progn (delete-char 1) (insert " ")))
452 (delete-char 1)
453 (insert "D"))))
d41d75fb
RS
454 (beginning-of-line))
455
456(defun rmail-summary-mark-undeleted (n)
457 (rmail-summary-mark-deleted n t))
458
459(defun rmail-summary-deleted-p (&optional n)
460 (save-excursion
461 (and n (rmail-summary-goto-msg n nil t))
462 (skip-chars-forward " ")
463 (skip-chars-forward "[0-9]")
464 (looking-at "D")))
4d4d11cc 465
d41d75fb
RS
466(defun rmail-summary-undelete (&optional arg)
467 "Undelete current message.
468Optional prefix ARG means undelete ARG previous messages."
469 (interactive "p")
470 (if (/= arg 1)
471 (rmail-summary-undelete-many arg)
5ed1243c
RS
472 (let ((buffer-read-only nil)
473 (opoint (point)))
d41d75fb
RS
474 (end-of-line)
475 (cond ((re-search-backward "\\(^ *[0-9]*\\)\\(D\\)" nil t)
476 (replace-match "\\1 ")
477 (rmail-summary-goto-msg)
478 (pop-to-buffer rmail-buffer)
479 (and (rmail-message-deleted-p rmail-current-message)
480 (rmail-undelete-previous-message))
5ed1243c
RS
481 (pop-to-buffer rmail-summary-buffer))
482 (t (goto-char opoint))))))
d41d75fb
RS
483
484(defun rmail-summary-undelete-many (&optional n)
485 "Undelete all deleted msgs, optional prefix arg N means undelete N prev msgs."
486 (interactive "P")
487 (save-excursion
488 (set-buffer rmail-buffer)
489 (let* ((init-msg (if n rmail-current-message rmail-total-messages))
490 (rmail-current-message init-msg)
491 (n (or n rmail-total-messages))
492 (msgs-undeled 0))
493 (while (and (> rmail-current-message 0)
494 (< msgs-undeled n))
495 (if (rmail-message-deleted-p rmail-current-message)
496 (progn (rmail-set-attribute "deleted" nil)
497 (setq msgs-undeled (1+ msgs-undeled))))
498 (setq rmail-current-message (1- rmail-current-message)))
499 (set-buffer rmail-summary-buffer)
500 (setq rmail-current-message init-msg msgs-undeled 0)
501 (while (and (> rmail-current-message 0)
502 (< msgs-undeled n))
503 (if (rmail-summary-deleted-p rmail-current-message)
504 (progn (rmail-summary-mark-undeleted rmail-current-message)
505 (setq msgs-undeled (1+ msgs-undeled))))
506 (setq rmail-current-message (1- rmail-current-message))))
507 (rmail-summary-goto-msg)))
508\f
4d4d11cc
JB
509;; Rmail Summary mode is suitable only for specially formatted data.
510(put 'rmail-summary-mode 'mode-class 'special)
511
512(defun rmail-summary-mode ()
d41d75fb
RS
513 "Rmail Summary Mode is invoked from Rmail Mode by using \\<rmail-mode-map>\\[rmail-summary].
514As commands are issued in the summary buffer, they are applied to the
515corresponding mail messages in the rmail buffer.
516
517All normal editing commands are turned off.
9cd78473
RS
518Instead, nearly all the Rmail mode commands are available,
519though many of them move only among the messages in the summary.
d41d75fb 520
9cd78473
RS
521These additional commands exist:
522
523\\[rmail-summary-undelete-many] Undelete all or prefix arg deleted messages.
524\\[rmail-summary-wipe] Delete the summary and go to the Rmail buffer.
525
526Commands for sorting the summary:
527
528\\[rmail-summary-sort-by-date] Sort by date.
529\\[rmail-summary-sort-by-subject] Sort by subject.
530\\[rmail-summary-sort-by-author] Sort by author.
531\\[rmail-summary-sort-by-recipient] Sort by recipient.
532\\[rmail-summary-sort-by-correspondent] Sort by correspondent.
ebdf372b
KH
533\\[rmail-summary-sort-by-lines] Sort by lines.
534\\[rmail-summary-sort-by-keywords] Sort by keywords."
4d4d11cc
JB
535 (interactive)
536 (kill-all-local-variables)
4d4d11cc
JB
537 (setq major-mode 'rmail-summary-mode)
538 (setq mode-name "RMAIL Summary")
4d4d11cc
JB
539 (setq truncate-lines t)
540 (setq buffer-read-only t)
541 (set-syntax-table text-mode-syntax-table)
d41d75fb
RS
542 (make-local-variable 'rmail-buffer)
543 (make-local-variable 'rmail-total-messages)
544 (make-local-variable 'rmail-current-message)
545 (setq rmail-current-message nil)
546 (make-local-variable 'rmail-summary-redo)
547 (setq rmail-summary-redo nil)
548 (make-local-variable 'revert-buffer-function)
d41d75fb 549 (make-local-variable 'post-command-hook)
0732dfa5 550 (rmail-summary-enable)
4d4d11cc
JB
551 (run-hooks 'rmail-summary-mode-hook))
552
0732dfa5
KH
553;; Summary features need to be disabled during edit mode.
554(defun rmail-summary-disable ()
56b25713
KH
555 (use-local-map text-mode-map)
556 (remove-hook 'post-command-hook 'rmail-summary-rmail-update)
557 (setq revert-buffer-function nil))
0732dfa5
KH
558
559(defun rmail-summary-enable ()
56b25713
KH
560 (use-local-map rmail-summary-mode-map)
561 (add-hook 'post-command-hook 'rmail-summary-rmail-update)
562 (setq revert-buffer-function 'rmail-update-summary))
0732dfa5 563
bb694792
RS
564;; Show in Rmail the message described by the summary line that point is on,
565;; but only if the Rmail buffer is already visible.
d41d75fb
RS
566;; This is a post-command-hook in summary buffers.
567(defun rmail-summary-rmail-update ()
10e09db4
KH
568 (let (buffer-read-only)
569 (save-excursion
570 ;; If at end of buffer, pretend we are on the last text line.
571 (if (eobp)
572 (forward-line -1))
573 (beginning-of-line)
574 (skip-chars-forward " ")
575 (let ((msg-num (string-to-int (buffer-substring
576 (point)
577 (progn (skip-chars-forward "0-9")
578 (point))))))
579 (or (eq rmail-current-message msg-num)
580 (let ((window (get-buffer-window rmail-buffer))
581 (owin (selected-window)))
582 (setq rmail-current-message msg-num)
583 (if (= (following-char) ?-)
584 (progn
585 (delete-char 1)
586 (insert " ")))
587 (if window
588 ;; Using save-window-excursion would cause the new value
980d43b6
RS
589 ;; of point to get lost.
590 (unwind-protect
591 (progn
592 (select-window window)
593 (rmail-show-message msg-num))
10e09db4
KH
594 (select-window owin))
595 (save-excursion
596 (set-buffer rmail-buffer)
597 (rmail-show-message msg-num)))))))))
d41d75fb
RS
598\f
599(defvar rmail-summary-mode-map nil)
600
601(if rmail-summary-mode-map
602 nil
603 (setq rmail-summary-mode-map (make-keymap))
604 (suppress-keymap rmail-summary-mode-map)
605 (define-key rmail-summary-mode-map "a" 'rmail-summary-add-label)
606 (define-key rmail-summary-mode-map "c" 'rmail-summary-continue)
607 (define-key rmail-summary-mode-map "d" 'rmail-summary-delete-forward)
608 (define-key rmail-summary-mode-map "\C-d" 'rmail-summary-delete-backward)
609 (define-key rmail-summary-mode-map "e" 'rmail-summary-edit-current-message)
610 (define-key rmail-summary-mode-map "f" 'rmail-summary-forward)
611 (define-key rmail-summary-mode-map "g" 'rmail-summary-get-new-mail)
612 (define-key rmail-summary-mode-map "h" 'rmail-summary)
613 (define-key rmail-summary-mode-map "i" 'rmail-summary-input)
614 (define-key rmail-summary-mode-map "j" 'rmail-summary-goto-msg)
615 (define-key rmail-summary-mode-map "k" 'rmail-summary-kill-label)
616 (define-key rmail-summary-mode-map "l" 'rmail-summary-by-labels)
617 (define-key rmail-summary-mode-map "\e\C-h" 'rmail-summary)
618 (define-key rmail-summary-mode-map "\e\C-l" 'rmail-summary-by-labels)
619 (define-key rmail-summary-mode-map "\e\C-r" 'rmail-summary-by-recipients)
620 (define-key rmail-summary-mode-map "\e\C-s" 'rmail-summary-by-regexp)
621 (define-key rmail-summary-mode-map "\e\C-t" 'rmail-summary-by-topic)
622 (define-key rmail-summary-mode-map "m" 'rmail-summary-mail)
623 (define-key rmail-summary-mode-map "\M-m" 'rmail-summary-retry-failure)
624 (define-key rmail-summary-mode-map "n" 'rmail-summary-next-msg)
d41d75fb
RS
625 (define-key rmail-summary-mode-map "\en" 'rmail-summary-next-all)
626 (define-key rmail-summary-mode-map "\e\C-n" 'rmail-summary-next-labeled-message)
627 (define-key rmail-summary-mode-map "o" 'rmail-summary-output-to-rmail-file)
628 (define-key rmail-summary-mode-map "\C-o" 'rmail-summary-output)
629 (define-key rmail-summary-mode-map "p" 'rmail-summary-previous-msg)
d41d75fb
RS
630 (define-key rmail-summary-mode-map "\ep" 'rmail-summary-previous-all)
631 (define-key rmail-summary-mode-map "\e\C-p" 'rmail-summary-previous-labeled-message)
632 (define-key rmail-summary-mode-map "q" 'rmail-summary-quit)
633 (define-key rmail-summary-mode-map "r" 'rmail-summary-reply)
634 (define-key rmail-summary-mode-map "s" 'rmail-summary-expunge-and-save)
635 (define-key rmail-summary-mode-map "\es" 'rmail-summary-search)
636 (define-key rmail-summary-mode-map "t" 'rmail-summary-toggle-header)
637 (define-key rmail-summary-mode-map "u" 'rmail-summary-undelete)
638 (define-key rmail-summary-mode-map "\M-u" 'rmail-summary-undelete-many)
639 (define-key rmail-summary-mode-map "w" 'rmail-summary-wipe)
640 (define-key rmail-summary-mode-map "x" 'rmail-summary-expunge)
641 (define-key rmail-summary-mode-map "." 'rmail-summary-beginning-of-message)
642 (define-key rmail-summary-mode-map "<" 'rmail-summary-first-message)
643 (define-key rmail-summary-mode-map ">" 'rmail-summary-last-message)
644 (define-key rmail-summary-mode-map " " 'rmail-summary-scroll-msg-up)
645 (define-key rmail-summary-mode-map "\177" 'rmail-summary-scroll-msg-down)
646 (define-key rmail-summary-mode-map "?" 'describe-mode)
e45fce03
RS
647 (define-key rmail-summary-mode-map "\C-c\C-s\C-d"
648 'rmail-summary-sort-by-date)
649 (define-key rmail-summary-mode-map "\C-c\C-s\C-s"
650 'rmail-summary-sort-by-subject)
651 (define-key rmail-summary-mode-map "\C-c\C-s\C-a"
652 'rmail-summary-sort-by-author)
653 (define-key rmail-summary-mode-map "\C-c\C-s\C-r"
654 'rmail-summary-sort-by-recipient)
655 (define-key rmail-summary-mode-map "\C-c\C-s\C-c"
656 'rmail-summary-sort-by-correspondent)
657 (define-key rmail-summary-mode-map "\C-c\C-s\C-l"
658 'rmail-summary-sort-by-lines)
ebdf372b
KH
659 (define-key rmail-summary-mode-map "\C-c\C-s\C-k"
660 'rmail-summary-sort-by-keywords)
d41d75fb
RS
661 )
662\f
e7a00c25
RS
663;;; Menu bar bindings.
664
665(define-key rmail-summary-mode-map [menu-bar] (make-sparse-keymap))
666
667(define-key rmail-summary-mode-map [menu-bar classify]
668 (cons "Classify" (make-sparse-keymap "Classify")))
669
670(define-key rmail-summary-mode-map [menu-bar classify output-inbox]
29e6129e 671 '("Output (inbox)..." . rmail-summary-output))
e7a00c25
RS
672
673(define-key rmail-summary-mode-map [menu-bar classify output]
29e6129e 674 '("Output (Rmail)..." . rmail-summary-output-to-rmail-file))
e7a00c25
RS
675
676(define-key rmail-summary-mode-map [menu-bar classify kill-label]
29e6129e 677 '("Kill Label..." . rmail-summary-kill-label))
e7a00c25
RS
678
679(define-key rmail-summary-mode-map [menu-bar classify add-label]
29e6129e 680 '("Add Label..." . rmail-summary-add-label))
e7a00c25
RS
681
682(define-key rmail-summary-mode-map [menu-bar summary]
683 (cons "Summary" (make-sparse-keymap "Summary")))
684
685(define-key rmail-summary-mode-map [menu-bar summary labels]
29e6129e 686 '("By Labels..." . rmail-summary-by-labels))
e7a00c25
RS
687
688(define-key rmail-summary-mode-map [menu-bar summary recipients]
29e6129e 689 '("By Recipients..." . rmail-summary-by-recipients))
e7a00c25
RS
690
691(define-key rmail-summary-mode-map [menu-bar summary topic]
29e6129e 692 '("By Topic..." . rmail-summary-by-topic))
e7a00c25
RS
693
694(define-key rmail-summary-mode-map [menu-bar summary regexp]
29e6129e 695 '("By Regexp..." . rmail-summary-by-regexp))
e7a00c25
RS
696
697(define-key rmail-summary-mode-map [menu-bar summary all]
698 '("All" . rmail-summary))
699
700(define-key rmail-summary-mode-map [menu-bar mail]
701 (cons "Mail" (make-sparse-keymap "Mail")))
702
e76bca6c 703(define-key rmail-summary-mode-map [menu-bar mail rmail-summary-get-new-mail]
b0d3522a
RS
704 '("Get New Mail" . rmail-summary-get-new-mail))
705
c0d133a6 706(define-key rmail-summary-mode-map [menu-bar mail lambda]
b0d3522a 707 '("----"))
aba6cc35 708
e7a00c25
RS
709(define-key rmail-summary-mode-map [menu-bar mail continue]
710 '("Continue" . rmail-summary-continue))
711
b0d3522a 712(define-key rmail-summary-mode-map [menu-bar mail resend]
29e6129e 713 '("Re-send..." . rmail-resend))
b0d3522a 714
e7a00c25
RS
715(define-key rmail-summary-mode-map [menu-bar mail forward]
716 '("Forward" . rmail-summary-forward))
717
718(define-key rmail-summary-mode-map [menu-bar mail retry]
719 '("Retry" . rmail-summary-retry-failure))
720
721(define-key rmail-summary-mode-map [menu-bar mail reply]
722 '("Reply" . rmail-summary-reply))
723
724(define-key rmail-summary-mode-map [menu-bar mail mail]
725 '("Mail" . rmail-summary-mail))
726
727(define-key rmail-summary-mode-map [menu-bar delete]
728 (cons "Delete" (make-sparse-keymap "Delete")))
729
730(define-key rmail-summary-mode-map [menu-bar delete expunge/save]
731 '("Expunge/Save" . rmail-summary-expunge-and-save))
732
733(define-key rmail-summary-mode-map [menu-bar delete expunge]
734 '("Expunge" . rmail-summary-expunge))
735
736(define-key rmail-summary-mode-map [menu-bar delete undelete]
737 '("Undelete" . rmail-summary-undelete))
738
739(define-key rmail-summary-mode-map [menu-bar delete delete]
740 '("Delete" . rmail-summary-delete-forward))
741
742(define-key rmail-summary-mode-map [menu-bar move]
743 (cons "Move" (make-sparse-keymap "Move")))
744
745(define-key rmail-summary-mode-map [menu-bar move search-back]
29e6129e 746 '("Search Back..." . rmail-summary-search-backward))
e7a00c25
RS
747
748(define-key rmail-summary-mode-map [menu-bar move search]
29e6129e 749 '("Search..." . rmail-summary-search))
e7a00c25
RS
750
751(define-key rmail-summary-mode-map [menu-bar move previous]
752 '("Previous Nondeleted" . rmail-summary-previous-msg))
753
754(define-key rmail-summary-mode-map [menu-bar move next]
755 '("Next Nondeleted" . rmail-summary-next-msg))
756
757(define-key rmail-summary-mode-map [menu-bar move last]
758 '("Last" . rmail-summary-last-message))
759
760(define-key rmail-summary-mode-map [menu-bar move first]
761 '("First" . rmail-summary-first-message))
762
763(define-key rmail-summary-mode-map [menu-bar move previous]
764 '("Previous" . rmail-summary-previous-all))
765
766(define-key rmail-summary-mode-map [menu-bar move next]
767 '("Next" . rmail-summary-next-all))
768\f
4197af8a
RS
769(defvar rmail-summary-overlay nil)
770
d41d75fb 771(defun rmail-summary-goto-msg (&optional n nowarn skip-rmail)
4d4d11cc
JB
772 (interactive "P")
773 (if (consp n) (setq n (prefix-numeric-value n)))
774 (if (eobp) (forward-line -1))
775 (beginning-of-line)
776 (let ((buf rmail-buffer)
777 (cur (point))
4197af8a 778 message-not-found
4d4d11cc
JB
779 (curmsg (string-to-int
780 (buffer-substring (point)
781 (min (point-max) (+ 5 (point)))))))
4197af8a
RS
782 ;; If message number N was specified, find that message's line
783 ;; or set message-not-found.
784 ;; If N wasn't specified or that message can't be found.
785 ;; set N by default.
4d4d11cc
JB
786 (if (not n)
787 (setq n curmsg)
788 (if (< n 1)
789 (progn (message "No preceding message")
790 (setq n 1)))
791 (if (> n rmail-total-messages)
792 (progn (message "No following message")
793 (goto-char (point-max))
794 (rmail-summary-goto-msg)))
795 (goto-char (point-min))
796 (if (not (re-search-forward (concat "^ *" (int-to-string n)) nil t))
797 (progn (or nowarn (message "Message %d not found" n))
798 (setq n curmsg)
4197af8a 799 (setq message-not-found t)
4d4d11cc
JB
800 (goto-char cur))))
801 (beginning-of-line)
802 (skip-chars-forward " ")
803 (skip-chars-forward "0-9")
804 (save-excursion (if (= (following-char) ?-)
805 (let ((buffer-read-only nil))
806 (delete-char 1)
807 (insert " "))))
4197af8a
RS
808 ;; Make sure we have an overlay to use.
809 (or rmail-summary-overlay
810 (progn
811 (make-local-variable 'rmail-summary-overlay)
812 (setq rmail-summary-overlay (make-overlay (point) (point)))))
813 ;; If this message is in the summary, use the overlay to highlight it.
814 ;; Otherwise, don't highlight anything.
815 (if message-not-found
816 (overlay-put rmail-summary-overlay 'face nil)
817 (move-overlay rmail-summary-overlay
818 (save-excursion (beginning-of-line) (1+ (point)))
754942d8 819 (save-excursion (end-of-line) (point)))
4197af8a 820 (overlay-put rmail-summary-overlay 'face 'highlight))
4d4d11cc 821 (beginning-of-line)
d41d75fb
RS
822 (if skip-rmail
823 nil
857ff384
RS
824 (let ((selwin (selected-window)))
825 (unwind-protect
826 (progn (pop-to-buffer buf)
827 (rmail-show-message n))
828 (select-window selwin))))))
d41d75fb 829\f
4d4d11cc 830(defun rmail-summary-scroll-msg-up (&optional dist)
431e100f 831 "Scroll the Rmail window forward."
4d4d11cc 832 (interactive "P")
431e100f 833 (let ((other-window-scroll-buffer rmail-buffer))
3d71f4b0
RS
834 (if (get-buffer-window rmail-buffer)
835 (scroll-other-window dist)
836 ;; This forces rmail-buffer to be sized correctly later.
837 (display-buffer rmail-buffer)
838 (setq rmail-current-message nil))))
4d4d11cc
JB
839
840(defun rmail-summary-scroll-msg-down (&optional dist)
431e100f 841 "Scroll the Rmail window backward."
4d4d11cc 842 (interactive "P")
431e100f 843 (rmail-summary-scroll-msg-up
d41d75fb
RS
844 (cond ((eq dist '-) nil)
845 ((null dist) '-)
846 (t (- (prefix-numeric-value dist))))))
847
848(defun rmail-summary-beginning-of-message ()
849 "Show current message from the beginning."
850 (interactive)
851 (pop-to-buffer rmail-buffer)
852 (beginning-of-buffer)
853 (pop-to-buffer rmail-summary-buffer))
4d4d11cc
JB
854
855(defun rmail-summary-quit ()
d41d75fb 856 "Quit out of Rmail and Rmail summary."
4d4d11cc 857 (interactive)
d41d75fb 858 (rmail-summary-wipe)
4d4d11cc
JB
859 (rmail-quit))
860
d41d75fb
RS
861(defun rmail-summary-wipe ()
862 "Kill and wipe away Rmail summary, remaining within Rmail."
4d4d11cc 863 (interactive)
d41d75fb 864 (save-excursion (set-buffer rmail-buffer) (setq rmail-summary-buffer nil))
9cd78473 865 (let ((local-rmail-buffer rmail-buffer))
d41d75fb
RS
866 (kill-buffer (current-buffer))
867 ;; Delete window if not only one.
868 (if (not (eq (selected-window) (next-window nil 'no-minibuf)))
869 (delete-window))
9cd78473
RS
870 ;; Switch windows to the rmail buffer, or switch to it in this window.
871 (pop-to-buffer local-rmail-buffer)))
d41d75fb
RS
872
873(defun rmail-summary-expunge ()
874 "Actually erase all deleted messages and recompute summary headers."
875 (interactive)
876 (save-excursion
877 (set-buffer rmail-buffer)
878 (rmail-only-expunge))
879 (rmail-update-summary))
880
881(defun rmail-summary-expunge-and-save ()
882 "Expunge and save RMAIL file."
883 (interactive)
884 (save-excursion
885 (set-buffer rmail-buffer)
b37767e7
RS
886 (rmail-only-expunge))
887 (rmail-update-summary)
888 (save-excursion
980d43b6 889 (set-buffer rmail-buffer)
ccc341de
KH
890 (save-buffer))
891 (set-buffer-modified-p nil))
d41d75fb
RS
892
893(defun rmail-summary-get-new-mail ()
894 "Get new mail and recompute summary headers."
895 (interactive)
b37767e7
RS
896 (let (msg)
897 (save-excursion
898 (set-buffer rmail-buffer)
899 (rmail-get-new-mail)
900 ;; Get the proper new message number.
901 (setq msg rmail-current-message))
902 ;; Make sure that message is displayed.
903 (rmail-summary-goto-msg msg)))
d41d75fb
RS
904
905(defun rmail-summary-input (filename)
906 "Run Rmail on file FILENAME."
907 (interactive "FRun rmail on RMAIL file: ")
b37767e7
RS
908 ;; We switch windows here, then display the other Rmail file there.
909 (pop-to-buffer rmail-buffer)
910 (rmail filename))
d41d75fb
RS
911
912(defun rmail-summary-first-message ()
913 "Show first message in Rmail file from summary buffer."
914 (interactive)
915 (beginning-of-buffer))
916
917(defun rmail-summary-last-message ()
918 "Show last message in Rmail file from summary buffer."
919 (interactive)
920 (end-of-buffer)
921 (forward-line -1))
922
923(defvar rmail-summary-edit-map nil)
924(if rmail-summary-edit-map
925 nil
926 (setq rmail-summary-edit-map
ae06ea79 927 (nconc (make-sparse-keymap) text-mode-map))
d41d75fb
RS
928 (define-key rmail-summary-edit-map "\C-c\C-c" 'rmail-cease-edit)
929 (define-key rmail-summary-edit-map "\C-c\C-]" 'rmail-abort-edit))
930
931(defun rmail-summary-edit-current-message ()
932 "Edit the contents of this message."
933 (interactive)
934 (pop-to-buffer rmail-buffer)
935 (rmail-edit-current-message)
936 (use-local-map rmail-summary-edit-map))
937
938(defun rmail-summary-cease-edit ()
939 "Finish editing message, then go back to Rmail summary buffer."
940 (interactive)
941 (rmail-cease-edit)
942 (pop-to-buffer rmail-summary-buffer))
943
944(defun rmail-summary-abort-edit ()
945 "Abort edit of current message; restore original contents.
946Go back to summary buffer."
947 (interactive)
948 (rmail-abort-edit)
949 (pop-to-buffer rmail-summary-buffer))
950
e7a00c25
RS
951(defun rmail-summary-search-backward (regexp &optional n)
952 "Show message containing next match for REGEXP.
953Prefix argument gives repeat count; negative argument means search
954backwards (through earlier messages).
955Interactively, empty argument means use same regexp used last time."
956 (interactive
957 (let* ((reversep (>= (prefix-numeric-value current-prefix-arg) 0))
958 (prompt
959 (concat (if reversep "Reverse " "") "Rmail search (regexp): "))
960 regexp)
961 (if rmail-search-last-regexp
962 (setq prompt (concat prompt
963 "(default "
964 rmail-search-last-regexp
965 ") ")))
966 (setq regexp (read-string prompt))
967 (cond ((not (equal regexp ""))
968 (setq rmail-search-last-regexp regexp))
969 ((not rmail-search-last-regexp)
970 (error "No previous Rmail search string")))
971 (list rmail-search-last-regexp
972 (prefix-numeric-value current-prefix-arg))))
973 ;; Don't use save-excursion because that prevents point from moving
974 ;; properly in the summary buffer.
975 (let ((buffer (current-buffer)))
976 (unwind-protect
977 (progn
978 (set-buffer rmail-buffer)
979 (rmail-search regexp (- n)))
980 (set-buffer buffer))))
981
d41d75fb
RS
982(defun rmail-summary-search (regexp &optional n)
983 "Show message containing next match for REGEXP.
984Prefix argument gives repeat count; negative argument means search
985backwards (through earlier messages).
986Interactively, empty argument means use same regexp used last time."
987 (interactive
988 (let* ((reversep (< (prefix-numeric-value current-prefix-arg) 0))
989 (prompt
990 (concat (if reversep "Reverse " "") "Rmail search (regexp): "))
991 regexp)
992 (if rmail-search-last-regexp
993 (setq prompt (concat prompt
994 "(default "
995 rmail-search-last-regexp
996 ") ")))
997 (setq regexp (read-string prompt))
998 (cond ((not (equal regexp ""))
999 (setq rmail-search-last-regexp regexp))
1000 ((not rmail-search-last-regexp)
1001 (error "No previous Rmail search string")))
1002 (list rmail-search-last-regexp
1003 (prefix-numeric-value current-prefix-arg))))
e7a00c25
RS
1004 ;; Don't use save-excursion because that prevents point from moving
1005 ;; properly in the summary buffer.
1006 (let ((buffer (current-buffer)))
1007 (unwind-protect
1008 (progn
1009 (set-buffer rmail-buffer)
1010 (rmail-search regexp n))
1011 (set-buffer buffer))))
d41d75fb
RS
1012
1013(defun rmail-summary-toggle-header ()
1014 "Show original message header if pruned header currently shown, or vice versa."
1015 (interactive)
1016 (save-excursion
1017 (set-buffer rmail-buffer)
1018 (rmail-toggle-header)))
1019
1020(defun rmail-summary-add-label (label)
1021 "Add LABEL to labels associated with current Rmail message.
1022Completion is performed over known labels when reading."
980d43b6
RS
1023 (interactive (list (save-excursion
1024 (set-buffer rmail-buffer)
1025 (rmail-read-label "Add label"))))
d41d75fb
RS
1026 (save-excursion
1027 (set-buffer rmail-buffer)
1028 (rmail-add-label label)))
1029
1030(defun rmail-summary-kill-label (label)
1031 "Remove LABEL from labels associated with current Rmail message.
1032Completion is performed over known labels when reading."
980d43b6
RS
1033 (interactive (list (save-excursion
1034 (set-buffer rmail-buffer)
1035 (rmail-read-label "Kill label"))))
d41d75fb
RS
1036 (save-excursion
1037 (set-buffer rmail-buffer)
1038 (rmail-set-label label nil)))
1039\f
1040;;;; *** Rmail Summary Mailing Commands ***
1041
1042(defun rmail-summary-mail ()
1043 "Send mail in another window.
1044While composing the message, use \\[mail-yank-original] to yank the
1045original message into it."
1046 (interactive)
db1d3cf7 1047 (rmail-start-mail nil nil nil nil nil rmail-buffer)
d41d75fb
RS
1048 (use-local-map (copy-keymap (current-local-map)))
1049 (define-key (current-local-map)
1050 "\C-c\C-c" 'rmail-summary-send-and-exit))
1051
1052(defun rmail-summary-continue ()
1053 "Continue composing outgoing message previously being composed."
1054 (interactive)
db1d3cf7 1055 (rmail-start-mail t))
d41d75fb
RS
1056
1057(defun rmail-summary-reply (just-sender)
1058 "Reply to the current message.
1059Normally include CC: to all other recipients of original message;
db1d3cf7
KH
1060prefix argument means ignore them. While composing the reply,
1061use \\[mail-yank-original] to yank the original message into it."
d41d75fb 1062 (interactive "P")
db1d3cf7
KH
1063 (set-buffer rmail-buffer)
1064 (rmail-reply just-sender)
1065 (use-local-map (copy-keymap (current-local-map)))
1066 (define-key (current-local-map)
1067 "\C-c\C-c" 'rmail-summary-send-and-exit))
d41d75fb
RS
1068
1069(defun rmail-summary-retry-failure ()
1070 "Edit a mail message which is based on the contents of the current message.
1071For a message rejected by the mail system, extract the interesting headers and
1072the body of the original message; otherwise copy the current message."
1073 (interactive)
db1d3cf7
KH
1074 (set-buffer rmail-buffer)
1075 (rmail-retry-failure)
1076 (use-local-map (copy-keymap (current-local-map)))
1077 (define-key (current-local-map)
1078 "\C-c\C-c" 'rmail-summary-send-and-exit))
d41d75fb
RS
1079
1080(defun rmail-summary-send-and-exit ()
1081 "Send mail reply and return to summary buffer."
1082 (interactive)
1083 (mail-send-and-exit t))
1084
18e90c58
RS
1085(defun rmail-summary-forward (resend)
1086 "Forward the current message to another user.
1087With prefix argument, \"resend\" the message instead of forwarding it;
1088see the documentation of `rmail-resend'."
1089 (interactive "P")
d41d75fb
RS
1090 (save-excursion
1091 (set-buffer rmail-buffer)
18e90c58 1092 (rmail-forward resend)
d41d75fb
RS
1093 (use-local-map (copy-keymap (current-local-map)))
1094 (define-key (current-local-map)
1095 "\C-c\C-c" 'rmail-summary-send-and-exit)))
1096\f
1097;; Summary output commands.
1098
1099(defun rmail-summary-output-to-rmail-file ()
1100 "Append the current message to an Rmail file named FILE-NAME.
1101If the file does not exist, ask if it should be created.
1102If file is being visited, the message is appended to the Emacs
1103buffer visiting that file."
1104 (interactive)
1105 (save-excursion
1106 (set-buffer rmail-buffer)
84fa8eb5
RS
1107 (let ((rmail-delete-after-output nil))
1108 (call-interactively 'rmail-output-to-rmail-file)))
1109 (if rmail-delete-after-output
94eeb96a 1110 (rmail-summary-delete-forward nil)))
d41d75fb
RS
1111
1112(defun rmail-summary-output ()
1113 "Append this message to Unix mail file named FILE-NAME."
1114 (interactive)
1115 (save-excursion
1116 (set-buffer rmail-buffer)
84fa8eb5
RS
1117 (let ((rmail-delete-after-output nil))
1118 (call-interactively 'rmail-output)))
1119 (if rmail-delete-after-output
94eeb96a 1120 (rmail-summary-delete-forward nil)))
e45fce03
RS
1121\f
1122;; Sorting messages in Rmail Summary buffer.
1123
1124(defun rmail-summary-sort-by-date (reverse)
1125 "Sort messages of current Rmail summary by date.
1126If prefix argument REVERSE is non-nil, sort them in reverse order."
1127 (interactive "P")
1128 (rmail-sort-from-summary (function rmail-sort-by-date) reverse))
1129
1130(defun rmail-summary-sort-by-subject (reverse)
1131 "Sort messages of current Rmail summary by subject.
1132If prefix argument REVERSE is non-nil, sort them in reverse order."
1133 (interactive "P")
1134 (rmail-sort-from-summary (function rmail-sort-by-subject) reverse))
1135
1136(defun rmail-summary-sort-by-author (reverse)
1137 "Sort messages of current Rmail summary by author.
1138If prefix argument REVERSE is non-nil, sort them in reverse order."
1139 (interactive "P")
1140 (rmail-sort-from-summary (function rmail-sort-by-author) reverse))
1141
1142(defun rmail-summary-sort-by-recipient (reverse)
1143 "Sort messages of current Rmail summary by recipient.
1144If prefix argument REVERSE is non-nil, sort them in reverse order."
1145 (interactive "P")
1146 (rmail-sort-from-summary (function rmail-sort-by-recipient) reverse))
1147
1148(defun rmail-summary-sort-by-correspondent (reverse)
1149 "Sort messages of current Rmail summary by other correspondent.
1150If prefix argument REVERSE is non-nil, sort them in reverse order."
1151 (interactive "P")
1152 (rmail-sort-from-summary (function rmail-sort-by-correspondent) reverse))
1153
1154(defun rmail-summary-sort-by-lines (reverse)
1155 "Sort messages of current Rmail summary by lines of the message.
1156If prefix argument REVERSE is non-nil, sort them in reverse order."
1157 (interactive "P")
1158 (rmail-sort-from-summary (function rmail-sort-by-lines) reverse))
1159
ebdf372b
KH
1160(defun rmail-summary-sort-by-keywords (reverse labels)
1161 "Sort messages of current Rmail summary by keywords.
1162If prefix argument REVERSE is non-nil, sort them in reverse order.
1163KEYWORDS is a comma-separated list of labels."
1164 (interactive "P\nsSort by labels: ")
1165 (rmail-sort-from-summary
1166 (function (lambda (reverse)
1167 (rmail-sort-by-keywords reverse labels)))
1168 reverse))
1169
e45fce03
RS
1170(defun rmail-sort-from-summary (sortfun reverse)
1171 "Sort Rmail messages from Summary buffer and update it after sorting."
1172 (require 'rmailsort)
2a527e48
KH
1173 (let ((selwin (selected-window)))
1174 (unwind-protect
1175 (progn (pop-to-buffer rmail-buffer)
1176 (funcall sortfun reverse))
1177 (select-window selwin))))
c88ab9ce
ER
1178
1179;;; rmailsum.el ends here