emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to pmailsum.el


From: Paul Michael Reilly
Subject: [Emacs-diffs] Changes to pmailsum.el
Date: Mon, 18 Aug 2008 04:51:31 +0000

CVSROOT:        /cvsroot/emacs
Module name:    emacs
Changes by:     Paul Michael Reilly <pmr>       08/08/18 04:51:29

Index: pmailsum.el
===================================================================
RCS file: pmailsum.el
diff -N pmailsum.el
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ pmailsum.el 18 Aug 2008 04:51:28 -0000      1.1
@@ -0,0 +1,1497 @@
+;;; pmailsum.el --- make summary buffers for the mail reader
+
+;; Copyright (C) 1985, 1993, 1994, 1995, 1996, 2000, 2001, 2002, 2003,
+;;   2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+;; Maintainer: FSF
+;; Keywords: mail
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; All commands run from the summary buffer update the buffer local
+;; variable `pmail-current-message'.  As part of the post command
+;; processing point is moved to the beginning of the line describing
+;; the current message.
+
+;;; History:
+
+;; Extended by Bob Weiner of Motorola
+;;   Provided all commands from pmail-mode in pmail-summary-mode and made key
+;;   bindings in both modes wholly compatible.
+
+;; Overhauled by Paul Reilly to support mbox format.
+
+;;; Code:
+
+(defvar msgnum)
+
+;; For pmail-select-summary
+(require 'pmail)
+
+;;;###autoload
+(defcustom pmail-summary-scroll-between-messages t
+  "*Non-nil means Pmail summary scroll commands move between messages."
+  :type 'boolean
+  :group 'pmail-summary)
+
+;;;###autoload
+(defcustom pmail-summary-line-count-flag t
+  "*Non-nil if Pmail summary should show the number of lines in each message."
+  :type 'boolean
+  :group 'pmail-summary)
+
+(defvar pmail-summary-font-lock-keywords
+  '(("^.....D.*" . font-lock-string-face)                      ; Deleted.
+    ("^.....-.*" . font-lock-type-face)                                ; 
Unread.
+    ;; Neither of the below will be highlighted if either of the above are:
+    ("^.....[^D-]....\\(......\\)" 1 font-lock-keyword-face)   ; Date.
+    ("{ \\([^\n}]+\\) }" 1 font-lock-comment-face))            ; Labels.
+  "Additional expressions to highlight in Pmail Summary mode.")
+
+(defvar pmail-summary-redo nil
+  "Private storage for Pmail summary history.")
+
+(defvar pmail-summary-overlay nil
+  "Private storage for an Pmail summary overlay cache")
+(put 'pmail-summary-overlay 'permanent-local t)
+
+(defvar pmail-summary-mode-map
+  (let ((map (make-keymap)))
+    (suppress-keymap map)
+    (define-key map [mouse-2] 'pmail-summary-mouse-goto-message)
+    (define-key map "a"      'pmail-summary-add-label)
+    (define-key map "b"      'pmail-summary-bury)
+    (define-key map "B"      'pmail-summary-browse-body)
+    (define-key map "c"      'pmail-summary-continue)
+    (define-key map "d"      'pmail-summary-delete-forward)
+    (define-key map "\C-d"   'pmail-summary-delete-backward)
+    (define-key map "e"      'pmail-summary-edit-current-message)
+    (define-key map "f"      'pmail-summary-forward)
+    (define-key map "g"      'pmail-summary-get-new-mail)
+    (define-key map "h"      'pmail-summary)
+    (define-key map "i"      'pmail-summary-input)
+    (define-key map "j"      'pmail-summary-goto-msg)
+    (define-key map "\C-m"   'pmail-summary-goto-msg)
+    (define-key map "k"      'pmail-summary-kill-label)
+    (define-key map "l"      'pmail-summary-by-labels)
+    (define-key map "\e\C-h" 'pmail-summary)
+    (define-key map "\e\C-l" 'pmail-summary-by-labels)
+    (define-key map "\e\C-r" 'pmail-summary-by-recipients)
+    (define-key map "\e\C-f" 'pmail-summary-by-senders)
+    (define-key map "\e\C-s" 'pmail-summary-by-regexp)
+    (define-key map "\e\C-t" 'pmail-summary-by-topic)
+    (define-key map "m"      'pmail-summary-mail)
+    (define-key map "\M-m"   'pmail-summary-retry-failure)
+    (define-key map "n"      'pmail-summary-next-msg)
+    (define-key map "\en"    'pmail-summary-next-all)
+    (define-key map "\e\C-n" 'pmail-summary-next-labeled-message)
+    (define-key map "o"      'pmail-summary-output)
+    (define-key map "\C-o"   'pmail-summary-output)
+    (define-key map "p"      'pmail-summary-previous-msg)
+    (define-key map "\ep"    'pmail-summary-previous-all)
+    (define-key map "\e\C-p" 'pmail-summary-previous-labeled-message)
+    (define-key map "q"      'pmail-summary-quit)
+    (define-key map "Q"      'pmail-summary-wipe)
+    (define-key map "r"      'pmail-summary-reply)
+    (define-key map "s"      'pmail-summary-expunge-and-save)
+    (define-key map "\es"    'pmail-summary-search)
+    (define-key map "t"      'pmail-summary-toggle-header)
+    (define-key map "u"      'pmail-summary-undelete)
+    (define-key map "\M-u"   'pmail-summary-undelete-many)
+    (define-key map "x"      'pmail-summary-expunge)
+    (define-key map "w"      'pmail-summary-output-body)
+    (define-key map "."      'pmail-summary-beginning-of-message)
+    (define-key map "/"      'pmail-summary-end-of-message)
+    (define-key map "<"      'pmail-summary-first-message)
+    (define-key map ">"      'pmail-summary-last-message)
+    (define-key map " "      'pmail-summary-scroll-msg-up)
+    (define-key map "\177"   'pmail-summary-scroll-msg-down)
+    (define-key map "?"      'describe-mode)
+    (define-key map "\C-c\C-n" 'pmail-summary-next-same-subject)
+    (define-key map "\C-c\C-p" 'pmail-summary-previous-same-subject)
+    (define-key map "\C-c\C-s\C-d" 'pmail-summary-sort-by-date)
+    (define-key map "\C-c\C-s\C-s" 'pmail-summary-sort-by-subject)
+    (define-key map "\C-c\C-s\C-a" 'pmail-summary-sort-by-author)
+    (define-key map "\C-c\C-s\C-r" 'pmail-summary-sort-by-recipient)
+    (define-key map "\C-c\C-s\C-c" 'pmail-summary-sort-by-correspondent)
+    (define-key map "\C-c\C-s\C-l" 'pmail-summary-sort-by-lines)
+    (define-key map "\C-c\C-s\C-k" 'pmail-summary-sort-by-labels)
+    (define-key map [menu-bar] (make-sparse-keymap))
+    (define-key map [menu-bar classify]
+      (cons "Classify" (make-sparse-keymap "Classify")))
+    (define-key map [menu-bar classify output-menu]
+      '("Output (Pmail Menu)..." . pmail-summary-output-menu))
+    (define-key map [menu-bar classify input-menu]
+      '("Input Pmail File (menu)..." . pmail-input-menu))
+    (define-key map [menu-bar classify input-menu] '(nil))
+    (define-key map [menu-bar classify output-menu] '(nil))
+    (define-key map [menu-bar classify output-body]
+      '("Output (body)..." . pmail-summary-output-body))
+    (define-key map [menu-bar classify output-inbox]
+      '("Output (inbox)..." . pmail-summary-output))
+    (define-key map [menu-bar classify output]
+      '("Output (Pmail)..." . pmail-summary-output))
+    (define-key map [menu-bar classify kill-label]
+      '("Kill Label..." . pmail-summary-kill-label))
+    (define-key map [menu-bar classify add-label]
+      '("Add Label..." . pmail-summary-add-label))
+    (define-key map [menu-bar summary]
+      (cons "Summary" (make-sparse-keymap "Summary")))
+    (define-key map [menu-bar summary senders]
+      '("By Senders..." . pmail-summary-by-senders))
+    (define-key map [menu-bar summary labels]
+      '("By Labels..." . pmail-summary-by-labels))
+    (define-key map [menu-bar summary recipients]
+      '("By Recipients..." . pmail-summary-by-recipients))
+    (define-key map [menu-bar summary topic]
+      '("By Topic..." . pmail-summary-by-topic))
+    (define-key map [menu-bar summary regexp]
+      '("By Regexp..." . pmail-summary-by-regexp))
+    (define-key map [menu-bar summary all]
+      '("All" . pmail-summary))
+    (define-key map [menu-bar mail]
+      (cons "Mail" (make-sparse-keymap "Mail")))
+    (define-key map [menu-bar mail pmail-summary-get-new-mail]
+      '("Get New Mail" . pmail-summary-get-new-mail))
+    (define-key map [menu-bar mail lambda]
+      '("----"))
+    (define-key map [menu-bar mail continue]
+      '("Continue" . pmail-summary-continue))
+    (define-key map [menu-bar mail resend]
+      '("Re-send..." . pmail-summary-resend))
+    (define-key map [menu-bar mail forward]
+      '("Forward" . pmail-summary-forward))
+    (define-key map [menu-bar mail retry]
+      '("Retry" . pmail-summary-retry-failure))
+    (define-key map [menu-bar mail reply]
+      '("Reply" . pmail-summary-reply))
+    (define-key map [menu-bar mail mail]
+      '("Mail" . pmail-summary-mail))
+    (define-key map [menu-bar delete]
+      (cons "Delete" (make-sparse-keymap "Delete")))
+    (define-key map [menu-bar delete expunge/save]
+      '("Expunge/Save" . pmail-summary-expunge-and-save))
+    (define-key map [menu-bar delete expunge]
+      '("Expunge" . pmail-summary-expunge))
+    (define-key map [menu-bar delete undelete]
+      '("Undelete" . pmail-summary-undelete))
+    (define-key map [menu-bar delete delete]
+      '("Delete" . pmail-summary-delete-forward))
+    (define-key map [menu-bar move]
+      (cons "Move" (make-sparse-keymap "Move")))
+    (define-key map [menu-bar move search-back]
+      '("Search Back..." . pmail-summary-search-backward))
+    (define-key map [menu-bar move search]
+      '("Search..." . pmail-summary-search))
+    (define-key map [menu-bar move previous]
+      '("Previous Nondeleted" . pmail-summary-previous-msg))
+    (define-key map [menu-bar move next]
+      '("Next Nondeleted" . pmail-summary-next-msg))
+    (define-key map [menu-bar move last]
+      '("Last" . pmail-summary-last-message))
+    (define-key map [menu-bar move first]
+      '("First" . pmail-summary-first-message))
+    (define-key map [menu-bar move previous]
+      '("Previous" . pmail-summary-previous-all))
+    (define-key map [menu-bar move next]
+      '("Next" . pmail-summary-next-all))
+    map)
+  "Keymap for `pmail-summary-mode'.")
+
+;; Entry points for making a summary buffer.
+
+;; Regenerate the contents of the summary
+;; using the same selection criterion as last time.
+;; M-x revert-buffer in a summary buffer calls this function.
+(defun pmail-update-summary (&rest ignore)
+  (apply (car pmail-summary-redo) (cdr pmail-summary-redo)))
+
+;;;###autoload
+(defun pmail-summary ()
+  "Display a summary of all messages, one line per message."
+  (interactive)
+  (pmail-new-summary "All" '(pmail-summary) nil))
+
+;;;###autoload
+(defun pmail-summary-by-labels (labels)
+  "Display a summary of all messages with one or more LABELS.
+LABELS should be a string containing the desired labels, separated by commas."
+  (interactive "sLabels to summarize by: ")
+  (if (string= labels "")
+      (setq labels (or pmail-last-multi-labels
+                      (error "No label specified"))))
+  (setq pmail-last-multi-labels labels)
+  (pmail-new-summary (concat "labels " labels)
+                    (list 'pmail-summary-by-labels labels)
+                    'pmail-message-labels-p
+                    (mail-comma-list-regexp labels)))
+
+;;;###autoload
+(defun pmail-summary-by-recipients (recipients &optional primary-only)
+  "Display a summary of all messages with the given RECIPIENTS.
+Normally checks the To, From and Cc fields of headers;
+but if PRIMARY-ONLY is non-nil (prefix arg given),
+ only look in the To and From fields.
+RECIPIENTS is a string of regexps separated by commas."
+  (interactive "sRecipients to summarize by: \nP")
+  (pmail-new-summary
+   (concat "recipients " recipients)
+   (list 'pmail-summary-by-recipients recipients primary-only)
+   'pmail-message-recipients-p
+   (mail-comma-list-regexp recipients) primary-only))
+
+;;;###autoload
+(defun pmail-summary-by-regexp (regexp)
+  "Display a summary of all messages according to regexp REGEXP.
+If the regular expression is found in the header of the message
+\(including in the date and other lines, as well as the subject line),
+Emacs will list the header line in the PMAIL-summary."
+  (interactive "sRegexp to summarize by: ")
+  (if (string= regexp "")
+      (setq regexp (or pmail-last-regexp
+                        (error "No regexp specified"))))
+  (setq pmail-last-regexp regexp)
+  (pmail-new-summary (concat "regexp " regexp)
+                    (list 'pmail-summary-by-regexp regexp)
+                    'pmail-message-regexp-p
+                     regexp))
+
+;;;###autoload
+(defun pmail-summary-by-topic (subject &optional whole-message)
+  "Display a summary of all messages with the given SUBJECT.
+Normally checks the Subject field of headers;
+but if WHOLE-MESSAGE is non-nil (prefix arg given),
+ look in the whole message.
+SUBJECT is a string of regexps separated by commas."
+  (interactive
+   (let* ((subject (with-current-buffer pmail-buffer
+                    (pmail-current-subject)))
+         (prompt (concat "Topics to summarize by (regexp"
+                         (if subject ", default current subject" "")
+                         "): ")))
+     (list (read-string prompt nil nil subject) current-prefix-arg)))
+  (pmail-new-summary
+   (concat "about " subject)
+   (list 'pmail-summary-by-topic subject whole-message)
+   'pmail-message-subject-p
+   (mail-comma-list-regexp subject) whole-message))
+
+(defun pmail-message-subject-p (msg subject &optional whole-message)
+  "Return non-nil if SUBJECT is found in MSG.
+If WHOLE-MESSAGE is nil only the subject header will be searched,
+otherwise the whole message will be searched for text matching
+SUBJECT.  Return nil to indicate that SUBJECT is not found,
+non-nil otherwise."
+  (save-restriction
+    (narrow-to-region
+     (pmail-desc-get-start msg)
+     (pmail-desc-get-end msg))
+    (goto-char (point-min))
+    (if whole-message
+       (re-search-forward subject nil t))
+    (string-match subject
+                 (let ((subj (pmail-header-get-header "subject")))
+                   (if subj
+                       (funcall pmail-summary-line-decoder subj)
+                     "")))))
+
+;;;###autoload
+(defun pmail-summary-by-senders (senders)
+  "Display a summary of all messages with the given SENDERS.
+SENDERS is a string of names separated by commas."
+  (interactive
+   (let* ((sender (when pmail-current-message
+                   (pmail-desc-get-sender pmail-current-message)))
+         (sender-re (with-current-buffer pmail-buffer
+                      (regexp-quote sender)))
+         (prompt (concat "Senders to summarize by (regexp"
+                         (if sender ", default current sender" "")
+                         "): ")))
+     (list (read-string prompt nil nil sender))))
+  (pmail-new-summary
+   (concat "senders " senders)
+   (list 'pmail-summary-by-senders senders)
+   'pmail-message-senders-p
+   (mail-comma-list-regexp senders)))
+
+(defun pmail-message-senders-p (msg sender)
+  "Return non-nil if SENDER is found in MSG.
+The From header is tested."
+  (save-restriction
+    (narrow-to-region
+     (pmail-desc-get-start msg)
+     (pmail-desc-get-end msg))
+    (goto-char (point-min))
+    (string-match sender (or (mail-fetch-field "From") ""))))
+
+;;;; General making of a summary buffer.
+
+(defvar pmail-summary-symbol-number 0)
+
+(defun pmail-new-summary (description redo-form function &rest args)
+  "Create a summary of selected messages.
+DESCRIPTION makes part of the mode line of the summary buffer.
+For each message, FUNCTION is applied to the message number and ARGS...
+and if the result is non-nil, that message is included.
+nil for FUNCTION means all messages."
+  (message "Computing summary lines...")
+  (let ((summary-msgs ())
+        (new-summary-line-count 0)
+        (msgnum 1)
+        current-message sumbuf was-in-summary)
+    (save-excursion
+      ;; Go to the Pmail buffer.
+      (if (eq major-mode 'pmail-summary-mode)
+         (setq was-in-summary t))
+      (set-buffer pmail-buffer)
+      ;; Find its summary buffer, or make one.
+      (setq current-message pmail-current-message
+           sumbuf
+           (if (and pmail-summary-buffer
+                    (buffer-name pmail-summary-buffer))
+               pmail-summary-buffer
+             (generate-new-buffer (concat (buffer-name) "-summary"))))
+      ;; Collect the message summaries based on the filtering
+      ;; argument (FUNCTION).
+      (while (>= pmail-total-messages msgnum)
+       (if (or (null function)
+               (apply function (cons msgnum args)))
+           (setq summary-msgs
+                 (cons (cons msgnum (pmail-summary-get-summary-line msgnum))
+                       summary-msgs)))
+       (setq msgnum (1+ msgnum)))
+      (setq summary-msgs (nreverse summary-msgs))
+      ;; Place the collected summaries into the summary buffer.
+      (setq pmail-summary-buffer nil)
+      (save-excursion
+       (let ((rbuf (current-buffer))
+             (vbuf pmail-view-buffer)
+             (total pmail-total-messages))
+         (set-buffer sumbuf)
+         ;; Set up the summary buffer's contents.
+         (let ((buffer-read-only nil))
+           (erase-buffer)
+           (while summary-msgs
+             (princ (cdr (car summary-msgs)) sumbuf)
+             (setq summary-msgs (cdr summary-msgs)))
+           (goto-char (point-min)))
+         ;; Set up the rest of its state and local variables.
+         (setq buffer-read-only t)
+         (pmail-summary-mode)
+         (make-local-variable 'minor-mode-alist)
+         (setq minor-mode-alist (list (list t (concat ": " description))))
+         (setq pmail-buffer rbuf
+               pmail-view-buffer vbuf
+               pmail-summary-redo redo-form
+               pmail-total-messages total
+               pmail-current-message current-message)))
+      (setq pmail-summary-buffer sumbuf))
+    ;; Now display the summary buffer and go to the right place in it.
+    (or was-in-summary
+       (progn
+         (if (and (one-window-p)
+                  pop-up-windows (not pop-up-frames))
+             ;; If there is just one window, put the summary on the top.
+             (progn
+               (split-window (selected-window) pmail-summary-window-size)
+               (select-window (next-window (frame-first-window)))
+               (pop-to-buffer sumbuf)
+               ;; If pop-to-buffer did not use that window, delete that
+               ;; window.  (This can happen if it uses another frame.)
+               (if (not (eq sumbuf (window-buffer (frame-first-window))))
+                   (delete-other-windows)))
+           (pop-to-buffer sumbuf))
+         (set-buffer pmail-buffer)
+         ;; This is how pmail makes the summary buffer reappear.
+         ;; We do this here to make the window the proper size.
+         (pmail-select-summary nil)
+         (set-buffer pmail-summary-buffer)))
+    (pmail-summary-goto-msg current-message nil t)
+    (pmail-summary-construct-io-menu)
+    (message "Computing summary lines...done")))
+
+;;;; Low levels of generating a summary.
+
+;;;###autoload
+(defcustom pmail-summary-line-decoder (function identity)
+  "*Function to decode summary-line.
+
+By default, `identity' is set."
+  :type 'function
+  :group 'pmail-summary)
+
+;;;###autoload
+(defcustom pmail-user-mail-address-regexp
+  (concat "^\\("
+         (regexp-quote (user-login-name))
+         "\\($\\|@\\)\\|"
+         (regexp-quote
+          (or user-mail-address
+              (concat (user-login-name) "@"
+                      (or mail-host-address
+                          (system-name)))))
+         "\\>\\)")
+  "*Regexp matching user mail addresses.
+If non-nil, this variable is used to identify the correspondent
+when receiving new mail.  If it matches the address of the
+sender, the recipient is taken as correspondent of a mail.  It is
+initialized based on your `user-login-name' and
+`user-mail-address'.
+
+Usually you don't have to set this variable, except if you
+collect mails sent by you under different user names.  Then it
+should be a regexp matching your mail addresses.
+
+Setting this variable has an effect only before reading a mail."
+  :type '(choice (const :tag "None" nil) regexp)
+  :group 'pmail-retrieve
+  :version "21.1")
+
+
+;;;; Simple motion in a summary buffer.
+
+(defun pmail-summary-next-all (&optional number)
+  "Move to an nearby message.
+If NUMBER is positive then move forward NUMBER messages.  If NUMBER is
+negative then move backwards NUMBER messages.  If NUMBER is nil then
+move forward one message."
+  (interactive "p")
+  (forward-line (if number number 1))
+  ;; It doesn't look nice to move forward past the last message line.
+  (and (eobp) (> number 0)
+       (forward-line -1))
+  (display-buffer pmail-buffer))
+
+(defun pmail-summary-previous-all (&optional number)
+  (interactive "p")
+  (forward-line (- (if number number 1)))
+  ;; It doesn't look nice to move forward past the last message line.
+  (and (eobp) (< number 0)
+       (forward-line -1))
+  (display-buffer pmail-buffer))
+
+(defun pmail-summary-next-msg (&optional number)
+  "Display next non-deleted msg from pmail file.
+With optional prefix argument NUMBER, moves forward this number of
+non-deleted messages, or backward if NUMBER is negative."
+  (interactive "p")
+  (let (msg)
+    (with-current-buffer pmail-buffer
+      (pmail-next-undeleted-message number)
+      (setq msg pmail-current-message))
+    (pmail-summary-goto-msg msg)))
+
+(defun pmail-summary-previous-msg (&optional number)
+  "Display previous non-deleted msg from pmail file.
+With optional prefix argument NUMBER, moves backward this number of
+non-deleted messages."
+  (interactive "p")
+  (pmail-summary-next-msg (- (if number number 1))))
+
+(defun pmail-summary-next-labeled-message (n labels)
+  "Show next message with LABEL.  Defaults to last labels used.
+With prefix argument N moves forward N messages with these labels."
+  (interactive "p\nsMove to next msg with labels: ")
+  (let (msg)
+    (save-excursion
+      (set-buffer pmail-buffer)
+      (pmail-next-labeled-message n labels)
+      (setq msg pmail-current-message))
+    (setq pmail-current-message msg)))
+
+(defun pmail-summary-previous-labeled-message (n labels)
+  "Show previous message with LABEL.  Defaults to last labels used.
+With prefix argument N moves backward N messages with these labels."
+  (interactive "p\nsMove to previous msg with labels: ")
+  (let (msg)
+    (save-excursion
+      (set-buffer pmail-buffer)
+      (pmail-previous-labeled-message n labels)
+      (setq msg pmail-current-message))
+    (setq pmail-current-message msg)))
+
+(defun pmail-summary-next-same-subject (n)
+  "Go to the next message in the summary having the same subject.
+With prefix argument N, do this N times.
+If N is negative, go backwards."
+  (interactive "p")
+  (with-current-buffer pmail-buffer
+    (pmail-next-same-subject n)))
+
+(defun pmail-summary-previous-same-subject (n)
+  "Go to the previous message in the summary having the same subject.
+With prefix argument N, do this N times.
+If N is negative, go forwards instead."
+  (interactive "p")
+  (pmail-summary-next-same-subject (- n)))
+
+
+;; Delete and undelete summary commands.
+
+(defun pmail-summary-delete-forward (&optional count)
+  "Delete this message and move to next nondeleted one.
+Deleted messages stay in the file until the \\[pmail-expunge] command is given.
+A prefix argument serves as a repeat count;
+a negative argument means to delete and move backward."
+  (interactive "p")
+  (unless (numberp count) (setq count 1))
+  (let (end del-msg
+           (backward (< count 0)))
+    (while (/= count 0)
+      (pmail-summary-goto-msg)
+      (with-current-buffer pmail-buffer
+       (pmail-delete-message)
+       (setq del-msg pmail-current-message))
+      (pmail-summary-mark-deleted del-msg)
+      (while (and (not (if backward (bobp) (eobp)))
+                 (save-excursion (beginning-of-line)
+                                 (looking-at " *[0-9]+D")))
+       (forward-line (if backward -1 1)))
+      (setq count
+           (if (> count 0) (1- count) (1+ count))))
+    ;; Update the summary buffer current message counter and show the
+    ;; message in the Pmail buffer.
+    (pmail-summary-goto-msg (pmail-summary-get-message-at-point))))
+
+(defun pmail-summary-delete-backward (&optional count)
+  "Delete this message and move to previous nondeleted one.
+Deleted messages stay in the file until the \\[pmail-expunge] command is given.
+A prefix argument serves as a repeat count;
+a negative argument means to delete and move forward."
+  (interactive "p")
+  (pmail-summary-delete-forward (- count)))
+
+(defun pmail-summary-mark-deleted (&optional n undel)
+  ;; Since third arg is t, this only alters the summary, not the Pmail buf.
+  (and n (pmail-summary-goto-msg n t))
+  (or (eobp)
+      (not (overlay-get pmail-summary-overlay 'face))
+      (let ((buffer-read-only nil))
+       (skip-chars-forward " ")
+       (skip-chars-forward "[0-9]")
+       (if undel
+           (if (looking-at "D")
+               (progn (delete-char 1) (insert " ")))
+         (delete-char 1)
+         (insert "D"))))
+  (beginning-of-line))
+
+(defun pmail-summary-mark-undeleted (n)
+  (pmail-summary-mark-deleted n t))
+
+(defun pmail-summary-deleted-p (&optional n)
+  (unless n (setq n pmail-current-message))
+  (with-current-buffer pmail-buffer
+    (pmail-desc-deleted-p n)))
+
+(defun pmail-summary-undelete (&optional arg)
+  "Undelete current message.
+Optional prefix ARG means undelete ARG previous messages."
+  (interactive "p")
+  (if (/= arg 1)
+      (pmail-summary-undelete-many arg)
+    (let ((buffer-read-only nil)
+         (opoint (point)))
+      (goto-char (line-end-position))
+      (if (not (re-search-backward "\\(^ *[0-9]*\\)\\(D\\)" nil t))
+         (goto-char opoint)
+       (replace-match "\\1 ")
+       (pmail-summary-goto-msg)
+       (if pmail-enable-mime
+           (set-buffer pmail-buffer)
+         (pop-to-buffer pmail-buffer))
+       (when (pmail-message-deleted-p pmail-current-message)
+         (pmail-undelete-previous-message))
+       (when pmail-enable-mime
+         (pop-to-buffer pmail-view-buffer))
+       (pop-to-buffer pmail-summary-buffer)))))
+
+(defun pmail-summary-undelete-many (&optional n)
+  "Undelete all deleted msgs, optional prefix arg N means undelete N prev 
msgs."
+  (interactive "P")
+  (with-current-buffer pmail-buffer
+    (let* ((init-msg (if n pmail-current-message pmail-total-messages))
+          (pmail-current-message init-msg)
+          (n (or n pmail-total-messages))
+          (msgs-undeled 0))
+      (while (and (> pmail-current-message 0) (< msgs-undeled n))
+       (when (pmail-message-deleted-p pmail-current-message)
+         (pmail-set-attribute "deleted" nil)
+         (setq msgs-undeled (1+ msgs-undeled)))
+       (setq pmail-current-message (1- pmail-current-message)))
+      (with-current-buffer pmail-summary-buffer
+       (setq pmail-current-message init-msg msgs-undeled 0)
+       (while (and (> pmail-current-message 0) (< msgs-undeled n))
+         (when (pmail-summary-deleted-p pmail-current-message)
+           (pmail-summary-mark-undeleted pmail-current-message)
+           (setq msgs-undeled (1+ msgs-undeled)))
+         (setq pmail-current-message (1- pmail-current-message)))))))
+
+;; Pmail Summary mode is suitable only for specially formatted data.
+(put 'pmail-summary-mode 'mode-class 'special)
+
+(defun pmail-summary-mode ()
+  "Pmail Summary Mode is invoked from Pmail Mode by using 
\\<pmail-mode-map>\\[pmail-summary].
+As commands are issued in the summary buffer, they are applied to the
+corresponding mail messages in the pmail buffer.
+
+All normal editing commands are turned off.
+Instead, nearly all the Pmail mode commands are available,
+though many of them move only among the messages in the summary.
+
+These additional commands exist:
+
+\\[pmail-summary-undelete-many]        Undelete all or prefix arg deleted 
messages.
+\\[pmail-summary-wipe] Delete the summary and go to the Pmail buffer.
+
+Commands for filtering the summary:
+
+\\[pmail-summary-by-labels] Filter by label.
+\\[pmail-summary-by-topic] Filter by Subject.
+      Filter by the entire message (header and body) if given a
+      prefix argument.
+\\[pmail-summary-by-senders] Filter by From field.
+\\[pmail-summary-by-recipients] Filter by To, From, and Cc fields.
+      Filter by To and From only if given a prefix argument.
+
+The commands listed above take comma-separated lists of regular
+expressions.
+
+\\[pmail-summary-by-regexp] Filter by any header line.
+\\[pmail-summary] Restore the default summary.
+
+Commands for sorting the summary:
+
+\\[pmail-summary-sort-by-date] Sort by date.
+\\[pmail-summary-sort-by-subject] Sort by subject.
+\\[pmail-summary-sort-by-author] Sort by author.
+\\[pmail-summary-sort-by-recipient] Sort by recipient.
+\\[pmail-summary-sort-by-correspondent] Sort by correspondent.
+\\[pmail-summary-sort-by-lines] Sort by lines.
+\\[pmail-summary-sort-by-labels] Sort by labels."
+  (interactive)
+  (kill-all-local-variables)
+  (setq major-mode 'pmail-summary-mode)
+  (setq mode-name "PMAIL Summary")
+  (setq truncate-lines t)
+  (setq buffer-read-only t)
+  (set-syntax-table text-mode-syntax-table)
+  (make-local-variable 'pmail-buffer)
+  (make-local-variable 'pmail-view-buffer)
+  (make-local-variable 'pmail-total-messages)
+  (make-local-variable 'pmail-current-message)
+  (setq pmail-current-message nil)
+  (make-local-variable 'pmail-summary-redo)
+  (setq pmail-summary-redo nil)
+  (make-local-variable 'revert-buffer-function)
+  (make-local-variable 'font-lock-defaults)
+  (setq font-lock-defaults '(pmail-summary-font-lock-keywords t))
+  (pmail-summary-enable)
+  (run-mode-hooks 'pmail-summary-mode-hook))
+
+;; Summary features need to be disabled during edit mode.
+(defun pmail-summary-disable ()
+  (use-local-map text-mode-map)
+  (remove-hook 'post-command-hook 'pmail-summary-pmail-update t)
+  (setq revert-buffer-function nil))
+
+(defun pmail-summary-enable ()
+  (use-local-map pmail-summary-mode-map)
+  (add-hook 'post-command-hook 'pmail-summary-pmail-update nil t)
+  (setq revert-buffer-function 'pmail-update-summary))
+
+(defvar pmail-summary-put-back-unseen nil
+  "Used for communicating between calls to `pmail-summary-pmail-update'.
+If it moves to a message within an Incremental Search, and removes
+the `unseen' attribute from that message, it sets this flag
+so that if the next motion between messages is in the same Incremental
+Search, the `unseen' attribute is restored.")
+
+(defun pmail-summary-pmail-update ()
+  "Update the Pmail summary buffer.
+Put the cursor on the beginning of the line containing the
+current message and highlight the buffer.  Show in Pmail the
+message described by the summary line that point is on, but only
+if the Pmail buffer is already visible.  This is on
+`post-command-hook' in summary buffers."
+  (let (buffer-read-only)
+    (save-excursion
+      ;; If at end of buffer, pretend we are on the last text line.
+      (when (eobp)
+       (forward-line -1))
+      ;; Determine the message number corresponding to line point is on.
+      (beginning-of-line)
+      (skip-chars-forward " ")
+      (let ((msg-num (string-to-number (buffer-substring
+                                       (point)
+                                       (progn (skip-chars-forward "0-9")
+                                              (point))))))
+       ;; Always leave `unseen' removed if we get out of isearch mode.
+       ;; Don't let a subsequent isearch restore `unseen'.
+       (when (not isearch-mode)
+         (setq pmail-summary-put-back-unseen nil))
+       (or (eq pmail-current-message msg-num)
+           (let ((window (get-buffer-window pmail-view-buffer t))
+                 (owin (selected-window)))
+             (if isearch-mode
+                 (save-excursion
+                   (set-buffer pmail-buffer)
+                   ;; If we first saw the previous message in this
+                   ;; search, and we have gone to a different message
+                   ;; while searching, put back `unseen' on the former
+                   ;; one.
+                   (if pmail-summary-put-back-unseen
+                       (pmail-set-attribute "unseen" t
+                                            pmail-current-message))
+                   ;; Arrange to do that later, for the new current message,
+                   ;; if it still has `unseen'.
+                   (setq pmail-summary-put-back-unseen
+                         (member "unseen" (pmail-desc-get-keywords msg-num))))
+               (setq pmail-summary-put-back-unseen nil))
+             ;; Go to the desired message.
+             (setq pmail-current-message msg-num)
+             ;; Update the summary to show the message has been seen.
+             (when (= (following-char) ?-)
+               (delete-char 1)
+               (insert " "))
+             (if window
+                 ;; Using save-window-excursion would cause the new value
+                 ;; of point to get lost.
+                 (unwind-protect
+                     (progn
+                       (select-window window)
+                       (pmail-show-message msg-num t))
+                   (select-window owin))
+               (when (buffer-name pmail-buffer)
+                 (save-excursion
+                     (set-buffer pmail-buffer)
+                     (pmail-show-message msg-num t))))))
+       (pmail-summary-update-highlight nil)))))
+
+(defun pmail-summary-mouse-goto-message (event)
+  "Select the message whose summary line you click on."
+  (interactive "@e")
+  (goto-char (posn-point (event-end event)))
+  (setq pmail-current-message (pmail-summary-get-message-at-point))
+  (pmail-summary-pmail-update))
+
+(defun pmail-summary-get-message-at-point ()
+  "Return the message number corresponding to the line containing point.
+If the summary buffer contains no messages, nil is returned."
+  (save-excursion
+    ;; Position point at the beginning of a line.
+    (if (eobp)
+        (forward-line -1)
+      (forward-line 0))
+    ;; Parse the message number.
+    (string-to-number
+     (buffer-substring (point) (min (point-max) (+ 6 (point)))))))
+
+(defun pmail-summary-goto-msg (&optional n nowarn skip-pmail)
+  "Go to message N in the summary buffer and the Pmail buffer.
+If N is nil, use the message corresponding to point in the summary
+buffer and move to that message in the Pmail buffer.
+
+If NOWARN, don't say anything if N is out of range.
+If SKIP-PMAIL, don't do anything to the Pmail buffer."
+  (interactive "P")
+  (if (consp n) (setq n (prefix-numeric-value n)))
+  ;; Do the end of buffer adjustment.
+  (if (eobp) (forward-line -1))
+  (beginning-of-line)
+  ;; Set N to the current message unless it was already set by the
+  ;; caller.
+  (unless n (setq n (pmail-summary-get-message-at-point)))
+  (let* ((obuf (current-buffer))
+        (buf pmail-buffer)
+        (cur (point))
+        message-not-found
+        (curmsg (string-to-number
+                 (buffer-substring (point)
+                                   (min (point-max) (+ 6 (point))))))
+        (total (with-current-buffer buf
+                 pmail-total-messages)))
+    ;; Do a validity check on N.  If it is valid then set the current
+    ;; summary message to N.  `pmail-summary-pmail-update' will then
+    ;; actually move point to the selected message.
+    (if (< n 1)
+       (progn (message "No preceding message")
+              (setq n 1)))
+    (if (and (> n total)
+            (> total 0))
+       (progn (message "No following message")
+              (goto-char (point-max))
+              (pmail-summary-goto-msg nil nowarn skip-pmail)))
+    (goto-char (point-min))
+    (if (not (re-search-forward (format "^%5d[^0-9]" n) nil t))
+       (progn (or nowarn (message "Message %d not found" n))
+              (setq n curmsg)
+              (setq message-not-found t)
+              (goto-char cur)))
+    (beginning-of-line)
+    (skip-chars-forward " ")
+    (skip-chars-forward "0-9")
+    (save-excursion (if (= (following-char) ?-)
+                       (let ((buffer-read-only nil))
+                         (delete-char 1)
+                         (insert " "))))
+    (pmail-summary-update-highlight message-not-found)
+    (beginning-of-line)
+    ;; Determine if the Pmail buffer needs to be processed.
+    (if skip-pmail
+       nil
+      ;; It does.
+      (let ((selwin (selected-window)))
+       (unwind-protect
+           (progn (pop-to-buffer buf)
+                  (pmail-show-message n))
+         (select-window selwin)
+         ;; The actions above can alter the current buffer.  Preserve it.
+         (set-buffer obuf))))))
+
+;; Update the highlighted line in an pmail summary buffer.
+;; That should be current.  We highlight the line point is on.
+;; If NOT-FOUND is non-nil, we turn off highlighting.
+(defun pmail-summary-update-highlight (not-found)
+  ;; Make sure we have an overlay to use.
+  (or pmail-summary-overlay
+      (progn
+       (make-local-variable 'pmail-summary-overlay)
+       (setq pmail-summary-overlay (make-overlay (point) (point)))))
+  ;; If this message is in the summary, use the overlay to highlight it.
+  ;; Otherwise, don't highlight anything.
+  (if not-found
+      (overlay-put pmail-summary-overlay 'face nil)
+    (move-overlay pmail-summary-overlay
+                 (save-excursion (beginning-of-line)
+                                 (skip-chars-forward " ")
+                                 (point))
+                 (save-excursion (end-of-line) (point)))
+    (overlay-put pmail-summary-overlay 'face 'highlight)))
+
+(defun pmail-summary-scroll-msg-up (&optional dist)
+  "Scroll the Pmail window forward.
+If the Pmail window is displaying the end of a message,
+advance to the next message."
+  (interactive "P")
+  (if (eq dist '-)
+      (pmail-summary-scroll-msg-down nil)
+    (let ((pmail-buffer-window (get-buffer-window pmail-view-buffer)))
+      (if pmail-buffer-window
+         (if (let ((pmail-summary-window (selected-window)))
+               (select-window pmail-buffer-window)
+               (prog1
+                   ;; Is EOB visible in the buffer?
+                   (save-excursion
+                     (let ((ht (window-height (selected-window))))
+                       (move-to-window-line (- ht 2))
+                       (end-of-line)
+                       (eobp)))
+                 (select-window pmail-summary-window)))
+             (if (not pmail-summary-scroll-between-messages)
+                 (error "End of buffer")
+               (pmail-summary-next-msg (or dist 1)))
+           (let ((other-window-scroll-buffer pmail-view-buffer))
+             (scroll-other-window dist)))
+       ;; If it isn't visible at all, show the beginning.
+       (pmail-summary-beginning-of-message)))))
+
+(defun pmail-summary-scroll-msg-down (&optional dist)
+  "Scroll the Pmail window backward.
+If the Pmail window is now displaying the beginning of a message,
+move to the previous message."
+  (interactive "P")
+  (if (eq dist '-)
+      (pmail-summary-scroll-msg-up nil)
+    (let ((pmail-buffer-window (get-buffer-window pmail-view-buffer)))
+      (if pmail-buffer-window
+         (if (let ((pmail-summary-window (selected-window)))
+               (select-window pmail-buffer-window)
+               (prog1
+                   ;; Is BOB visible in the buffer?
+                   (save-excursion
+                     (move-to-window-line 0)
+                     (beginning-of-line)
+                     (bobp))
+                 (select-window pmail-summary-window)))
+             (if (not pmail-summary-scroll-between-messages)
+                 (error "Beginning of buffer")
+               (pmail-summary-previous-msg (or dist 1)))
+           (let ((other-window-scroll-buffer pmail-view-buffer))
+             (scroll-other-window-down dist)))
+       ;; If it isn't visible at all, show the beginning.
+       (pmail-summary-beginning-of-message)))))
+
+(defun pmail-summary-beginning-of-message ()
+  "Show current message from the beginning."
+  (interactive)
+  (pmail-summary-show-message 'BEG))
+
+(defun pmail-summary-end-of-message ()
+  "Show bottom of current message."
+  (interactive)
+  (pmail-summary-show-message 'END))
+
+(defun pmail-summary-show-message (where)
+  "Show current mail message.
+Position it according to WHERE which can be BEG or END"
+  (if (and (one-window-p) (not pop-up-frames))
+      ;; If there is just one window, put the summary on the top.
+      (let ((buffer pmail-view-buffer))
+       (split-window (selected-window) pmail-summary-window-size)
+       (select-window (frame-first-window))
+       (pop-to-buffer pmail-view-buffer)
+       ;; If pop-to-buffer did not use that window, delete that
+       ;; window.  (This can happen if it uses another frame.)
+       (or (eq buffer (window-buffer (next-window (frame-first-window))))
+           (delete-other-windows)))
+    (pop-to-buffer pmail-view-buffer))
+  (cond ((eq where 'BEG)
+        (goto-char (point-min))
+        (search-forward "\n\n"))
+       ((eq where 'END)
+        (goto-char (point-max))
+        (recenter (1- (window-height)))))
+  (pop-to-buffer pmail-summary-buffer))
+
+(defun pmail-summary-bury ()
+  "Bury the Pmail buffer and the Pmail summary buffer."
+  (interactive)
+  (let ((buffer-to-bury (current-buffer)))
+    (let (window)
+      (while (setq window (get-buffer-window pmail-buffer))
+       (set-window-buffer window (other-buffer pmail-buffer)))
+      (bury-buffer pmail-buffer))
+    (switch-to-buffer (other-buffer buffer-to-bury))
+    (bury-buffer buffer-to-bury)))
+
+(defun pmail-summary-quit ()
+  "Quit out of Pmail and Pmail summary."
+  (interactive)
+  (pmail-summary-wipe)
+  (pmail-quit))
+
+(defun pmail-summary-wipe ()
+  "Kill and wipe away Pmail summary, remaining within Pmail."
+  (interactive)
+  (save-excursion (set-buffer pmail-buffer) (setq pmail-summary-buffer nil))
+  (let ((local-pmail-buffer pmail-view-buffer))
+    (kill-buffer (current-buffer))
+    ;; Delete window if not only one.
+    (if (not (eq (selected-window) (next-window nil 'no-minibuf)))
+       (delete-window))
+    ;; Switch windows to the pmail buffer, or switch to it in this window.
+    (pop-to-buffer local-pmail-buffer)))
+
+(defun pmail-summary-expunge ()
+  "Actually erase all deleted messages and recompute summary headers."
+  (interactive)
+  (set-buffer pmail-buffer)
+  (pmail-expunge)
+  (set-buffer pmail-summary-buffer))
+
+(defun pmail-summary-expunge-and-save ()
+  "Expunge and save PMAIL file."
+  (interactive)
+  (set-buffer pmail-buffer)
+  (pmail-expunge)
+  (save-buffer)
+  (set-buffer pmail-summary-buffer)
+  (set-buffer-modified-p nil))
+
+(defun pmail-summary-get-new-mail (&optional file-name)
+  "Get new mail and recompute summary headers.
+
+Optionally you can specify the file to get new mail from.  In this case,
+the file of new mail is not changed or deleted.  Noninteractively, you can
+pass the inbox file name as an argument.  Interactively, a prefix
+argument says to read a file name and use that file as the inbox."
+  (interactive
+   (list (if current-prefix-arg
+            (read-file-name "Get new mail from file: "))))
+  (let (current-message new-mail)
+    (with-current-buffer pmail-buffer
+      (setq new-mail (pmail-get-new-mail file-name)
+           current-message pmail-current-message))
+    ;; If new mail was found, display of the correct message was
+    ;; done elsewhere.
+    (unless new-mail
+      (pmail-summary-goto-msg current-message nil t))))
+
+(defun pmail-summary-input (filename)
+  "Run Pmail on file FILENAME."
+  (interactive "FRun pmail on PMAIL file: ")
+  ;; We switch windows here, then display the other Pmail file there.
+  (pop-to-buffer pmail-buffer)
+  (pmail filename))
+
+(defun pmail-summary-first-message ()
+  "Show first message in Pmail file from summary buffer."
+  (interactive)
+  (with-no-warnings
+    (beginning-of-buffer)))
+
+(defun pmail-summary-last-message ()
+  "Show last message in Pmail file from summary buffer."
+  (interactive)
+  (with-no-warnings
+    (end-of-buffer))
+  (forward-line -1))
+
+(declare-function pmail-abort-edit "pmailedit" ())
+(declare-function pmail-cease-edit "pmailedit"())
+(declare-function pmail-set-label "pmailkwd" (l state &optional n))
+(declare-function pmail-output-read-file-name "pmailout" ())
+(declare-function pmail-output-read-pmail-file-name  "pmailout" ())
+(declare-function mail-send-and-exit "sendmail" (&optional arg))
+
+(defvar pmail-summary-edit-map
+  (let ((map (nconc (make-sparse-keymap) text-mode-map)))
+    (define-key map "\C-c\C-c" 'pmail-cease-edit)
+    (define-key map "\C-c\C-]" 'pmail-abort-edit)
+    map)
+  "Mode map to use when editing the pmail summary.")
+
+(defun pmail-summary-edit-current-message ()
+  "Edit the contents of this message."
+  (interactive)
+  (pop-to-buffer pmail-buffer)
+  (pmail-edit-current-message)
+  (use-local-map pmail-summary-edit-map))
+
+(defun pmail-summary-cease-edit ()
+  "Finish editing message, then go back to Pmail summary buffer."
+  (interactive)
+  (pmail-cease-edit)
+  (pop-to-buffer pmail-summary-buffer))
+
+(defun pmail-summary-abort-edit ()
+  "Abort edit of current message; restore original contents.
+Go back to summary buffer."
+  (interactive)
+  (pmail-abort-edit)
+  (pop-to-buffer pmail-summary-buffer))
+
+(defun pmail-summary-search-backward (regexp &optional n)
+  "Show message containing next match for REGEXP.
+Prefix argument gives repeat count; negative argument means search
+backwards (through earlier messages).
+Interactively, empty argument means use same regexp used last time."
+  (interactive
+    (let* ((reversep (>= (prefix-numeric-value current-prefix-arg) 0))
+          (prompt
+           (concat (if reversep "Reverse " "") "Pmail search (regexp"))
+          regexp)
+      (setq prompt
+           (concat prompt
+                   (if pmail-search-last-regexp
+                       (concat ", default "
+                               pmail-search-last-regexp "): ")
+                     "): ")))
+      (setq regexp (read-string prompt))
+      (cond ((not (equal regexp ""))
+            (setq pmail-search-last-regexp regexp))
+           ((not pmail-search-last-regexp)
+            (error "No previous Pmail search string")))
+      (list pmail-search-last-regexp
+           (prefix-numeric-value current-prefix-arg))))
+  ;; Don't use save-excursion because that prevents point from moving
+  ;; properly in the summary buffer.
+  (let ((buffer (current-buffer)))
+    (unwind-protect
+       (progn
+         (set-buffer pmail-buffer)
+         (pmail-search regexp (- n)))
+      (set-buffer buffer))))
+
+(defun pmail-summary-search (regexp &optional n)
+  "Show message containing next match for REGEXP.
+Prefix argument gives repeat count; negative argument means search
+backwards (through earlier messages).
+Interactively, empty argument means use same regexp used last time."
+  (interactive
+    (let* ((reversep (< (prefix-numeric-value current-prefix-arg) 0))
+          (prompt
+           (concat (if reversep "Reverse " "") "Pmail search (regexp"))
+          regexp)
+      (setq prompt
+           (concat prompt
+                   (if pmail-search-last-regexp
+                       (concat ", default "
+                               pmail-search-last-regexp "): ")
+                     "): ")))
+      (setq regexp (read-string prompt))
+      (cond ((not (equal regexp ""))
+            (setq pmail-search-last-regexp regexp))
+           ((not pmail-search-last-regexp)
+            (error "No previous Pmail search string")))
+      (list pmail-search-last-regexp
+           (prefix-numeric-value current-prefix-arg))))
+  ;; Don't use save-excursion because that prevents point from moving
+  ;; properly in the summary buffer.
+  (let ((buffer (current-buffer)))
+    (unwind-protect
+       (progn
+         (set-buffer pmail-buffer)
+         (pmail-search regexp n))
+      (set-buffer buffer))))
+
+(defun pmail-summary-toggle-header ()
+  "Show original message header if pruned header currently shown, or vice 
versa."
+  (interactive)
+  (with-current-buffer pmail-buffer
+    (pmail-toggle-header)))
+
+(defun pmail-summary-add-label (label)
+  "Add LABEL to labels associated with current Pmail message.
+Completion is performed over known labels when reading."
+  (interactive (list (with-current-buffer pmail-buffer
+                      (pmail-read-label "Add label"))))
+  (with-current-buffer pmail-buffer
+    (pmail-add-label label)))
+
+(defun pmail-summary-kill-label (label)
+  "Remove LABEL from labels associated with current Pmail message.
+Completion is performed over known labels when reading."
+  (interactive (list (with-current-buffer pmail-buffer
+                      (pmail-read-label "Kill label" t))))
+  (with-current-buffer pmail-buffer
+    (pmail-kill-label label)))
+
+;;;; *** Pmail Summary Mailing Commands ***
+
+(defun pmail-summary-override-mail-send-and-exit ()
+  "Replace bindings to 'mail-send-and-exit with 'pmail-summary-send-and-exit"
+  (use-local-map (copy-keymap (current-local-map)))
+  (dolist (key (where-is-internal 'mail-send-and-exit))
+    (define-key (current-local-map) key 'pmail-summary-send-and-exit)))
+
+(defun pmail-summary-mail ()
+  "Send mail in another window.
+While composing the message, use \\[mail-yank-original] to yank the
+original message into it."
+  (interactive)
+  (let ((window (get-buffer-window pmail-buffer)))
+    (if window
+       (select-window window)
+      (set-buffer pmail-buffer)))
+  (pmail-start-mail nil nil nil nil nil (current-buffer))
+  (pmail-summary-override-mail-send-and-exit))
+
+(defun pmail-summary-continue ()
+  "Continue composing outgoing message previously being composed."
+  (interactive)
+  (let ((window (get-buffer-window pmail-buffer)))
+    (if window
+       (select-window window)
+      (set-buffer pmail-buffer)))
+  (pmail-start-mail t))
+
+(defun pmail-summary-reply (just-sender)
+  "Reply to the current message.
+Normally include CC: to all other recipients of original message;
+prefix argument means ignore them.  While composing the reply,
+use \\[mail-yank-original] to yank the original message into it."
+  (interactive "P")
+  (let ((window (get-buffer-window pmail-view-buffer)))
+    (if window
+       (select-window window)
+      (set-buffer pmail-view-buffer)))
+  (pmail-reply just-sender)
+  (pmail-summary-override-mail-send-and-exit))
+
+(defun pmail-summary-retry-failure ()
+  "Edit a mail message which is based on the contents of the current message.
+For a message rejected by the mail system, extract the interesting headers and
+the body of the original message; otherwise copy the current message."
+  (interactive)
+  (let ((window (get-buffer-window pmail-buffer)))
+    (if window
+       (select-window window)
+      (set-buffer pmail-buffer)))
+  (pmail-retry-failure)
+  (pmail-summary-override-mail-send-and-exit))
+
+(defun pmail-summary-send-and-exit ()
+  "Send mail reply and return to summary buffer."
+  (interactive)
+  (mail-send-and-exit t))
+
+(defun pmail-summary-forward (resend)
+  "Forward the current message to another user.
+With prefix argument, \"resend\" the message instead of forwarding it;
+see the documentation of `pmail-resend'."
+  (interactive "P")
+  (save-excursion
+    (let ((window (get-buffer-window pmail-buffer)))
+      (if window
+         (select-window window)
+       (set-buffer pmail-buffer)))
+    (pmail-forward resend)
+    (pmail-summary-override-mail-send-and-exit)))
+
+(defun pmail-summary-resend ()
+  "Resend current message using `pmail-resend'."
+  (interactive)
+  (save-excursion
+    (let ((window (get-buffer-window pmail-buffer)))
+      (if window
+         (select-window window)
+       (set-buffer pmail-buffer)))
+    (call-interactively 'pmail-resend)))
+
+;;;; Summary output commands.
+
+(defun pmail-summary-output-to-pmail-file (&optional file-name n)
+  "Append the current message to an Pmail file named FILE-NAME.
+If the file does not exist, ask if it should be created.
+If file is being visited, the message is appended to the Emacs
+buffer visiting that file.
+
+A prefix argument N says to output N consecutive messages
+starting with the current one.  Deleted messages are skipped and don't count."
+  (interactive
+   (progn (require 'pmailout)
+         (list (pmail-output-read-file-name)
+               (prefix-numeric-value current-prefix-arg))))
+  (let ((i 0) prev-msg)
+    (while
+       (and (< i n)
+            (progn (pmail-summary-goto-msg)
+                   (not (eq prev-msg
+                            (setq prev-msg
+                                  (with-current-buffer pmail-buffer
+                                    pmail-current-message))))))
+      (setq i (1+ i))
+      (with-current-buffer pmail-buffer
+       (let ((pmail-delete-after-output nil))
+         (pmail-output-to-pmail-file file-name 1)))
+      (if pmail-delete-after-output
+         (pmail-summary-delete-forward nil)
+       (if (< i n)
+           (pmail-summary-next-msg 1))))))
+
+(defun pmail-summary-output (&optional file-name n)
+  "Append this message to Unix mail file named FILE-NAME.
+
+A prefix argument N says to output N consecutive messages
+starting with the current one.  Deleted messages are skipped and don't count."
+  (interactive
+   (progn (require 'pmailout)
+         (list (pmail-output-read-file-name)
+               (prefix-numeric-value current-prefix-arg))))
+  (let ((i 0) prev-msg)
+    (while
+       (and (< i n)
+            (progn (pmail-summary-goto-msg)
+                   (not (eq prev-msg
+                            (setq prev-msg
+                                  (with-current-buffer pmail-buffer
+                                    pmail-current-message))))))
+      (setq i (1+ i))
+      (with-current-buffer pmail-buffer
+       (let ((pmail-delete-after-output nil))
+         (pmail-output file-name 1)))
+      (if pmail-delete-after-output
+         (pmail-summary-delete-forward nil)
+       (if (< i n)
+           (pmail-summary-next-msg 1))))))
+
+(defun pmail-summary-output-menu ()
+  "Output current message to another Pmail file, chosen with a menu.
+Also set the default for subsequent \\[pmail-output-to-pmail-file] commands.
+The variables `pmail-secondary-file-directory' and
+`pmail-secondary-file-regexp' control which files are offered in the menu."
+  (interactive)
+  (save-excursion
+    (set-buffer pmail-buffer)
+    (let ((pmail-delete-after-output nil))
+      (call-interactively 'pmail-output-menu)))
+  (if pmail-delete-after-output
+      (pmail-summary-delete-forward nil)))
+
+(defun pmail-summary-construct-io-menu ()
+  (let ((files (pmail-find-all-files pmail-secondary-file-directory)))
+    (if files
+       (progn
+         (define-key pmail-summary-mode-map [menu-bar classify input-menu]
+           (cons "Input Pmail File"
+                 (pmail-list-to-menu "Input Pmail File"
+                                     files
+                                     'pmail-summary-input)))
+         (define-key pmail-summary-mode-map [menu-bar classify output-menu]
+           (cons "Output Pmail File"
+                 (pmail-list-to-menu "Output Pmail File"
+                                     files
+                                     'pmail-summary-output-to-pmail-file))))
+      (define-key pmail-summary-mode-map [menu-bar classify input-menu]
+       '("Input Pmail File" . pmail-disable-menu))
+      (define-key pmail-summary-mode-map [menu-bar classify output-menu]
+       '("Output Pmail File" . pmail-disable-menu)))))
+
+(defun pmail-summary-output-body (&optional file-name)
+  "Write this message body to the file FILE-NAME.
+FILE-NAME defaults, interactively, from the Subject field of the message."
+  (interactive)
+  (save-excursion
+    (set-buffer pmail-buffer)
+    (let ((pmail-delete-after-output nil))
+      (if file-name
+         (pmail-output-body-to-file file-name)
+       (call-interactively 'pmail-output-body-to-file))))
+  (if pmail-delete-after-output
+      (pmail-summary-delete-forward nil)))
+
+;; Sorting messages in Pmail Summary buffer.
+
+(defun pmail-summary-sort-by-date (reverse)
+  "Sort messages of current Pmail summary by date.
+If prefix argument REVERSE is non-nil, sort them in reverse order."
+  (interactive "P")
+  (pmail-sort-from-summary (function pmail-sort-by-date) reverse))
+
+(defun pmail-summary-sort-by-subject (reverse)
+  "Sort messages of current Pmail summary by subject.
+If prefix argument REVERSE is non-nil, sort them in reverse order."
+  (interactive "P")
+  (pmail-sort-from-summary (function pmail-sort-by-subject) reverse))
+
+(defun pmail-summary-sort-by-author (reverse)
+  "Sort messages of current Pmail summary by author.
+If prefix argument REVERSE is non-nil, sort them in reverse order."
+  (interactive "P")
+  (pmail-sort-from-summary (function pmail-sort-by-author) reverse))
+
+(defun pmail-summary-sort-by-recipient (reverse)
+  "Sort messages of current Pmail summary by recipient.
+If prefix argument REVERSE is non-nil, sort them in reverse order."
+  (interactive "P")
+  (pmail-sort-from-summary (function pmail-sort-by-recipient) reverse))
+
+(defun pmail-summary-sort-by-correspondent (reverse)
+  "Sort messages of current Pmail summary by other correspondent.
+If prefix argument REVERSE is non-nil, sort them in reverse order."
+  (interactive "P")
+  (pmail-sort-from-summary (function pmail-sort-by-correspondent) reverse))
+
+(defun pmail-summary-sort-by-lines (reverse)
+  "Sort messages of current Pmail summary by lines of the message.
+If prefix argument REVERSE is non-nil, sort them in reverse order."
+  (interactive "P")
+  (pmail-sort-from-summary (function pmail-sort-by-lines) reverse))
+
+(defun pmail-summary-sort-by-labels (reverse labels)
+  "Sort messages of current Pmail summary by labels.
+If prefix argument REVERSE is non-nil, sort them in reverse order.
+KEYWORDS is a comma-separated list of labels."
+  (interactive "P\nsSort by labels: ")
+  (pmail-sort-from-summary
+   (function (lambda (reverse)
+              (pmail-sort-by-labels reverse labels)))
+   reverse))
+
+(defun pmail-sort-from-summary (sortfun reverse)
+  "Sort Pmail messages from Summary buffer and update it after sorting."
+  (require 'pmailsort)
+  (let ((selwin (selected-window)))
+    (unwind-protect
+       (progn (pop-to-buffer pmail-buffer)
+              (funcall sortfun reverse))
+      (select-window selwin))))
+
+(defun pmail-summary-get-sender (n)
+  "Return the sender for message N.
+If sender matches `pmail-user-mail-address-regexp' or
+`user-mail-address', return the to-address instead."
+  (let ((sender (pmail-desc-get-sender n)))
+    (if (or (null sender)
+           (and pmail-user-mail-address-regexp
+                (string-match pmail-user-mail-address-regexp sender)))
+       ;; Either no sender known, or it's this user.
+       (save-restriction
+         (narrow-to-region (pmail-desc-get-start n)
+                           (pmail-desc-get-end n))
+         (concat "to: " (mail-strip-quoted-names
+                         (pmail-header-get-header "to"))))
+      sender)))
+
+(defun pmail-summary-get-line-count (n)
+  "Return a string containing the number of lines in message N.
+If `pmail-summary-line-count-flag' is nil, return the empty string."
+  (if pmail-summary-line-count-flag
+      (let ((lines (pmail-desc-get-line-count n)))
+       (format (cond ((<= lines     9) "   [%d]")
+                     ((<= lines    99) "  [%d]")
+                     ((<= lines   999) " [%3d]")
+                     (t "[%d]"))
+               lines))
+    ""))
+
+(defun pmail-summary-get-summary-attributes (n)
+  "Return the attribute character codes for message N.
+`-' means an unseen message, `D' means marked for deletion."
+  (format "%s%s%s%s%s"
+          (cond ((pmail-desc-attr-p pmail-desc-unseen-index n) "-")
+                ((pmail-desc-attr-p pmail-desc-deleted-index n) "D")
+                (t " "))
+          (or (pmail-desc-get-attr-code pmail-desc-answered-index n) " ")
+          (or (pmail-desc-get-attr-code pmail-desc-filed-index n) " ")
+          (or (pmail-desc-get-attr-code pmail-desc-edited-index n) " ")
+          (or (pmail-desc-get-attr-code pmail-desc-stored-index n) " ")))
+
+(defun pmail-summary-get-summary-line (n)
+  "Return a summary line for message N."
+  (let (keywords str subj)
+    (dolist (keyword (pmail-desc-get-keywords n))
+      (when (and (pmail-keyword-p keyword)
+                (not (pmail-attribute-p keyword)))
+       (setq keywords (cons keyword keywords))))
+    (setq keywords (nreverse keywords)
+         str (if keywords
+                 (concat "{ " (mapconcat 'identity keywords " ") " } ")
+               "")
+         subj (replace-regexp-in-string "\\s-+" " "
+                                        (pmail-desc-get-subject n)))
+    (funcall pmail-summary-line-decoder
+            (format "%5s%s%6s %25.25s%s %s\n"
+                    n
+                    (pmail-summary-get-summary-attributes n)
+                    (concat (pmail-desc-get-day-number n) "-"
+                            (pmail-desc-get-month n))
+                    (pmail-summary-get-sender n)
+                    (pmail-summary-get-line-count n)
+                    (concat str subj)))))
+
+(defun pmail-summary-update (n)
+  "Rewrite the summary line for message N."
+  (with-current-buffer pmail-buffer
+    ;; we need to do this in the pmail-buffer lest the keywords are
+    ;; not recognized
+    (let ((summary (pmail-summary-get-summary-line n)))
+      (with-current-buffer pmail-summary-buffer
+       (save-excursion
+         (let ((buffer-read-only nil))
+           (pmail-summary-goto-msg n)
+           ;; summary line includes newline at the end
+           (delete-region (point) (1+ (line-end-position)))
+           (insert summary)))))))
+
+(provide 'pmailsum)
+
+;; arch-tag: 556079ee-75c1-47f5-9884-2e0a0bc6c5a1
+;;; pmailsum.el ends here




reply via email to

[Prev in Thread] Current Thread [Next in Thread]