diff lisp/mh-e/mh-e.el @ 89966:d8411455de48

Revision: miles@gnu.org--gnu-2004/emacs--unicode--0--patch-32 Merge from emacs--cvs-trunk--0 Patches applied: * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-486 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-487 Tweak permissions * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-488 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-489 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-490 Update from CVS: man/fixit.texi (Spelling): Fix typo. * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-491 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-494 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-495 Update from CVS: Add missing lisp/mh-e files * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-496 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-499 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-500 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-513 Update from CVS
author Miles Bader <miles@gnu.org>
date Fri, 27 Aug 2004 07:00:34 +0000
parents 97905c4f1a42 25da1d331c99
children 4da4a09e8b1b
line wrap: on
line diff
--- a/lisp/mh-e/mh-e.el	Wed Aug 18 06:38:14 2004 +0000
+++ b/lisp/mh-e/mh-e.el	Fri Aug 27 07:00:34 2004 +0000
@@ -5,7 +5,7 @@
 
 ;; Author: Bill Wohler <wohler@newt.com>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
-;; Version: 7.4.4
+;; Version: 7.82
 ;; Keywords: mail
 
 ;; This file is part of GNU Emacs.
@@ -75,25 +75,21 @@
 
 ;; Original version for Gosling emacs by Brian Reid, Stanford, 1982.
 ;; Modified by James Larus, BBN, July 1984 and UCB, 1984 & 1985.
-;; Rewritten for GNU Emacs, James Larus 1985.  larus@ginger.berkeley.edu
-;; Modified by Stephen Gildea 1988.  gildea@lcs.mit.edu
-;; Maintenance picked up by Bill Wohler <wohler@newt.com> and the
-;; SourceForge Crew <http://mh-e.sourceforge.net/>. 2001.
+;; Rewritten for GNU Emacs, James Larus, 1985.
+;; Modified by Stephen Gildea, 1988.
+;; Maintenance picked up by Bill Wohler and the
+;; SourceForge Crew <http://mh-e.sourceforge.net/>, 2001.
 
 ;;; Code:
 
 (provide 'mh-e)
-(require 'mh-utils)
+
+(eval-when-compile (require 'mh-acros))
 (mh-require-cl)
-
-(defvar recursive-load-depth-limit)
-(eval-when (compile load eval)
-  (if (and (boundp 'recursive-load-depth-limit)
-           (integerp recursive-load-depth-limit)
-           (> 50 recursive-load-depth-limit))
-      (setq recursive-load-depth-limit 50)))
-
+(require 'mh-utils)
+(require 'mh-init)
 (require 'mh-inc)
+(require 'mh-seq)
 (require 'gnus-util)
 (require 'easymenu)
 
@@ -101,35 +97,27 @@
 (defvar font-lock-auto-fontify)
 (defvar font-lock-defaults)
 
-(defconst mh-version "7.4.4" "Version number of MH-E.")
+(defconst mh-version "7.82" "Version number of MH-E.")
 
 ;;; Autoloads
 (autoload 'Info-goto-node "info")
 
-
-
-(defvar mh-note-deleted "D"
-  "String whose first character is used to notate deleted messages.")
-
-(defvar mh-note-refiled "^"
-  "String whose first character is used to notate refiled messages.")
-
-(defvar mh-note-cur "+"
-  "String whose first character is used to notate the current message.")
-
 (defvar mh-partial-folder-mode-line-annotation "select"
   "Annotation when displaying part of a folder.
 The string is displayed after the folder's name.  nil for no annotation.")
 
+
+;;; Scan Line Formats
+
 ;;; Parameterize MH-E to work with different scan formats.  The defaults work
 ;;; with the standard MH scan listings, in which the first 4 characters on
 ;;; the line are the message number, followed by two places for notations.
 
-;; The following scan formats are passed to the scan program if the
-;; setting of `mh-scan-format-file' above is nil.  They are identical
-;; except the later one makes use of the nmh `decode' function to
-;; decode RFC 2047 encodings. If you just want to change the width of
-;; the msg number, use the `mh-set-cmd-note' function.
+;; The following scan formats are passed to the scan program if the setting of
+;; `mh-scan-format-file' is t. They are identical except the later one makes
+;; use of the nmh `decode' function to decode RFC 2047 encodings. If you just
+;; want to change the width of the msg number, use the `mh-set-cmd-note'
+;; function.
 
 (defvar mh-scan-format-mh
   (concat
@@ -150,11 +138,10 @@
 fontification have been added to the fifth column (remember that in Emacs, the
 first column is 0).
 
-The values of the fifth column, in priority order, are: `-' if the
-message has been replied to, t if an address on the To: line matches
-one of the mailboxes of the current user, `c' if the Cc: line matches,
-`b' if the Bcc: line matches, and `n' if a non-empty Newsgroups: header
-is present.")
+The values of the fifth column, in priority order, are: `-' if the message has
+been replied to, t if an address on the To: line matches one of the
+mailboxes of the current user, `c' if the Cc: line matches, `b' if the Bcc:
+line matches, and `n' if a non-empty Newsgroups: header is present.")
 
 (defvar mh-scan-format-nmh
   (concat
@@ -176,78 +163,94 @@
 fontification have been added to the fifth column (remember that in Emacs, the
 first column is 0).
 
-The values of the fifth column, in priority order, are: `-' if the
-message has been replied to, t if an address on the To: line matches
-one of the mailboxes of the current user, `c' if the Cc: line matches,
-`b' if the Bcc: line matches, and `n' if a non-empty Newsgroups: header
-is present.")
+The values of the fifth column, in priority order, are: `-' if the message has
+been replied to, t if an address on the To: field matches one of the
+mailboxes of the current user, `c' if the Cc: field matches, `b' if the Bcc:
+field matches, and `n' if a non-empty Newsgroups: field is present.")
+
+(defvar mh-note-deleted ?D
+  "Deleted messages are marked by this character.
+See also `mh-scan-deleted-msg-regexp'.")
+
+(defvar mh-note-refiled ?^
+  "Refiled messages are marked by this character.
+See also `mh-scan-refiled-msg-regexp'.")
+
+(defvar mh-note-cur ?+
+  "The current message (in MH) is marked by this character.
+See also `mh-scan-cur-msg-number-regexp'.")
 
 (defvar mh-scan-good-msg-regexp  "^\\( *[0-9]+\\)[^D^0-9]"
-  "Regexp specifying the scan lines that are 'good' messages.
-The default `mh-folder-font-lock-keywords' expects this expression to contain
-at least one parenthesized expression which matches the message number.")
+  "This regexp specifies the scan lines that are 'good' messages.
+Note that the default setting of `mh-folder-font-lock-keywords' expects this
+expression to contain at least one parenthesized expression which matches the
+message number as in the default of \"^\\\\( *[0-9]+\\\\)[^D^0-9]\".")
 
 (defvar mh-scan-deleted-msg-regexp "^\\( *[0-9]+\\)D"
-  "Regexp matching scan lines of deleted messages.
-The default `mh-folder-font-lock-keywords' expects this expression to contain
-at least one parenthesized expression which matches the message number.")
+  "This regexp matches deleted messages.
+Note that the default setting of `mh-folder-font-lock-keywords' expects this
+expression to contain at least one parenthesized expression which matches the
+message number as in the default of \"^\\\\( *[0-9]+\\\\)D\".
+See also `mh-note-deleted'.")
 
 (defvar mh-scan-refiled-msg-regexp  "^\\( *[0-9]+\\)\\^"
-  "Regexp matching scan lines of refiled messages.
-The default `mh-folder-font-lock-keywords' expects this expression to contain
-at least one parenthesized expression which matches the message number.")
+  "This regexp matches refiled messages.
+Note that the default setting of `mh-folder-font-lock-keywords' expects this
+expression to contain at least one parenthesized expression which matches the
+message number as in the default of \"^\\\\( *[0-9]+\\\\)\\\\^\".
+See also `mh-note-refiled'.")
 
 (defvar mh-scan-valid-regexp "^ *[0-9]"
-  "Regexp matching scan lines for messages (not error messages).")
+  "This regexp matches scan lines for messages (not error messages).")
 
 (defvar mh-scan-cur-msg-number-regexp "^\\( *[0-9]+\\+\\).*"
-  "Regexp matching scan line for the current message.
-The default `mh-folder-font-lock-keywords' expects this expression to contain
-at least one parenthesized expression which matches the message number.
-Don't disable this regexp as it's needed by non fontifying functions.")
-
-(defvar mh-scan-cur-msg-regexp "^\\( *[0-9]+\\+DISABLED.*\\)"
-  "Regexp matching scan line for the current message.
-The default `mh-folder-font-lock-keywords' expects this expression to contain
-at least one parenthesized expression which matches the whole line.
-To enable this feature, remove the string DISABLED from the regexp.")
+  "This regexp matches the current message.
+Note that the default setting of `mh-folder-font-lock-keywords' expects this
+expression to contain at least one parenthesized expression which matches the
+message number as in the default of \"^\\\\( *[0-9]+\\\\+\\\\).*\". Don't
+disable this regexp as it's needed by non-fontifying functions.
+See also `mh-note-cur'.")
 
 (defvar mh-scan-date-regexp "\\([0-9][0-9]/[0-9][0-9]\\)"
-  "Regexp matching a valid date in scan lines.
-The default `mh-folder-font-lock-keywords' expects this expression to contain
-only one parenthesized expression which matches the date field
-\(see `mh-scan-format-regexp').")
+  "This regexp matches a valid date.
+Note that the default setting of `mh-folder-font-lock-keywords' expects this
+expression to contain only one parenthesized expression which matches the date
+field as in the default of \"\\\\([0-9][0-9]/[0-9][0-9]\\\\)\"}.
+See also `mh-scan-format-regexp'.")
 
 (defvar mh-scan-rcpt-regexp  "\\(To:\\)\\(..............\\)"
-  "Regexp specifying the recipient in scan lines for messages we sent.
-The default `mh-folder-font-lock-keywords' expects this expression to contain
-two parenthesized expressions.  The first is expected to match the To:
-that the default scan format file generates.  The second is expected to match
-the recipient's name.")
+  "This regexp specifies the recipient in messages you sent.
+Note that the default setting of `mh-folder-font-lock-keywords'
+expects this expression to contain two parenthesized expressions. The
+first is expected to match the `To:' that the default scan format
+file generates. The second is expected to match the recipient's name
+as in the default of \"\\\\(To:\\\\)\\\\(..............\\\\)\".")
 
 (defvar mh-scan-body-regexp "\\(<<\\([^\n]+\\)?\\)"
-  "Regexp matching the message body beginning displayed in scan lines.
-The default `mh-folder-font-lock-keywords' expects this expression to contain
-at least one parenthesized expression which matches the body text.")
+  "This regexp matches the message body fragment displayed in scan lines.
+Note that the default setting of `mh-folder-font-lock-keywords' expects this
+expression to contain at least one parenthesized expression which matches the
+body text as in the default of \"\\\\(<<\\\\([^\\n]+\\\\)?\\\\)\".")
 
 (defvar mh-scan-subject-regexp
-  ;;"^ *[0-9]+........[ ]*...................\\([Rr][Ee]:\\s-*\\)*\\([^<\n]*\\)"
   "^ *[0-9]+........[ ]*...................\\([Rr][Ee]\\(\\[[0-9]+\\]\\)?:\\s-*\\)*\\([^<\n]*\\)"
-  "*Regexp matching the subject string in MH folder mode.
-The default `mh-folder-font-lock-keywords' expects this expression to contain
-at least tree parenthesized expressions. The first is expected to match the Re:
-string, if any. The second matches an optional bracketed number after Re,
-such as in Re[2]: and the third is expected to match the subject line itself.")
+  "This regexp matches the subject.
+Note that the default setting of `mh-folder-font-lock-keywords' expects this
+expression to contain at least three parenthesized expressions. The first is
+expected to match the `Re:' string, if any. The second matches an optional
+bracketed number after `Re:', such as in `Re[2]:' (and is thus a
+sub-expression of the first expression) and the third is expected to match
+the subject line itself as in the default of \"^ *[0-9]+........[ ]*...................\\\\([Rr][Ee]\\\\(\\\\\\=[[0-9]+\\\\]\\\\)?:\\\\s-*\\\\)*\\\\([^<\\n]*\\\\)\".")
 
 (defvar mh-scan-format-regexp
   (concat "\\([bct]\\)" mh-scan-date-regexp " *\\(..................\\)")
-  "Regexp matching the output of scan.
-The default value is based upon the default values of either
-`mh-scan-format-mh' or `mh-scan-format-nmh'.
-The default `mh-folder-font-lock-keywords' expects this expression to contain
-at least three parenthesized expressions. The first should match the
-fontification hint, the second is found in `mh-scan-date-regexp', and the
-third should match the user name.")
+  "This regexp matches the output of scan.
+Note that the default setting of `mh-folder-font-lock-keywords' expects this
+expression to contain at least three parenthesized expressions. The first
+should match the fontification hint, the second is found in
+`mh-scan-date-regexp', and the third should match the user name as in the
+default of \"(concat \"\\\\([bct]\\\\)\" mh-scan-date-regexp
+                     \"*\\\\(..................\\\\)\")\".")
 
 
 
@@ -279,10 +282,7 @@
    ;; scan font-lock name
    (list mh-scan-format-regexp
          '(1 mh-folder-date-face)
-         '(3 mh-folder-scan-format-face))
-   ;; Current message line
-   (list mh-scan-cur-msg-regexp
-         '(1 mh-folder-cur-msg-face prepend t)))
+         '(3 mh-folder-scan-format-face)))
   "Regexp keywords used to fontify the MH-Folder buffer.")
 
 (defvar mh-scan-cmd-note-width 1
@@ -356,46 +356,6 @@
 
 ;; Fontifify unseen mesages in bold.
 
-(defvar mh-folder-unseen-seq-name nil
-  "Name of unseen sequence.
-The default for this is provided by the function `mh-folder-unseen-seq-name'
-On nmh systems.")
-
-(defun mh-folder-unseen-seq-name ()
-  "Provide name of unseen sequence from mhparam."
-  (or mh-progs (mh-find-path))
-  (save-excursion
-    (let ((unseen-seq-name "unseen"))
-      (with-temp-buffer
-        (unwind-protect
-            (progn
-              (call-process (expand-file-name "mhparam" mh-progs)
-                            nil '(t t) nil "-component" "Unseen-Sequence")
-              (goto-char (point-min))
-              (if (re-search-forward "Unseen-Sequence: \\(.*\\)$" nil t)
-                  (setq unseen-seq-name (match-string 1))))))
-      unseen-seq-name)))
-
-(defun mh-folder-unseen-seq-list ()
-  "Return a list of unseen message numbers for current folder."
-  (if (not mh-folder-unseen-seq-name)
-      (setq mh-folder-unseen-seq-name (mh-folder-unseen-seq-name)))
-  (cond
-   ((not mh-folder-unseen-seq-name)
-    nil)
-   (t
-    (let ((folder mh-current-folder))
-      (save-excursion
-        (with-temp-buffer
-          (unwind-protect
-              (progn
-                (call-process (expand-file-name "mark" mh-progs)
-                              nil '(t t) nil
-                              folder "-seq" mh-folder-unseen-seq-name
-                              "-list")
-                (goto-char (point-min))
-                (sort (mh-read-msg-list) '<)))))))))
-
 (defmacro mh-generate-sequence-font-lock (seq prefix face)
   "Generate the appropriate code to fontify messages in SEQ.
 PREFIX is used to generate unique names for the variables and functions
@@ -492,6 +452,8 @@
                                         ;Rememeber original notation that
                                         ;is overwritten by `mh-note-seq'.
 
+(defvar mh-colors-available-flag nil)   ;Are colors available?
+
 ;;; Macros and generic functions:
 
 (defun mh-mapc (function list)
@@ -503,7 +465,7 @@
 (defun mh-scan-format ()
   "Return the output format argument for the scan program."
   (if (equal mh-scan-format-file t)
-      (list "-format" (if mh-nmh-flag
+      (list "-format" (if (mh-variant-p 'nmh 'mu-mh)
                           (list (mh-update-scan-format
                                  mh-scan-format-nmh mh-cmd-note))
                         (list (mh-update-scan-format
@@ -519,7 +481,7 @@
 (defun mh-rmail (&optional arg)
   "Inc(orporate) new mail with MH.
 Scan an MH folder if ARG is non-nil. This function is an entry point to MH-E,
-the Emacs front end to the MH mail system."
+the Emacs interface to the MH mail system."
   (interactive "P")
   (mh-find-path)
   (if arg
@@ -532,7 +494,7 @@
 (defun mh-nmail (&optional arg)
   "Check for new mail in inbox folder.
 Scan an MH folder if ARG is non-nil. This function is an entry point to MH-E,
-the Emacs front end to the MH mail system."
+the Emacs interface to the MH mail system."
   (interactive "P")
   (mh-find-path)                        ; init mh-inbox
   (if arg
@@ -616,6 +578,7 @@
       (setq folder mh-inbox))
   (let ((threading-needed-flag nil))
     (let ((config (current-window-configuration)))
+      (delete-other-windows)
       (cond ((not (get-buffer folder))
              (mh-make-folder folder)
              (setq threading-needed-flag mh-show-threads-flag)
@@ -659,25 +622,26 @@
            (if wait-after-complaining-flag (sit-for 1)))))
 
 (defun mh-folder-from-address ()
-  "Determine folder name from address in From field.
-Takes the address in the From: header field, and returns one of:
+  "Derive folder name from sender.
+
+The name of the folder is derived as follows:
 
-  a) The folder name associated with the address in the alist
-     `mh-default-folder-list'.  If the `Check Recipient' boolean
-      is set, then the `mh-default-folder-list' addresses are
-      checked against the recipient instead of the originator
-      (making possible to use this feature for mailing lists).
-      The first match found in `mh-default-folder-list' is used.
+  a) The folder name associated with the first address found in the list
+     `mh-default-folder-list' is used. Each element in this list contains a
+     `Check Recipient' item. If this item is turned on, then the address is
+     checked against the recipient instead of the sender. This is useful for
+     mailing lists.
 
-  b) The address' corresponding alias from the user's personal
-     aliases file prefixed by `mh-default-folder-prefix'.
+  b) An alias prefixed by `mh-default-folder-prefix' corresponding to the
+     address is used. The prefix is used to prevent clutter in your mail
+     directory.
 
-Returns nil if the address was not found in either place or if the variable
-`mh-default-folder-must-exist-flag' is nil and the folder does not exist."
+Return nil if a folder name was not derived, or if the variable
+`mh-default-folder-must-exist-flag' is t and the folder does not exist."
   ;; Loop for all entries in mh-default-folder-list
   (save-restriction
     (goto-char (point-min))
-    (re-search-forward "\n\n" nil t)
+    (re-search-forward "\n\n" nil 'limit)
     (narrow-to-region (point-min) (point))
     (let ((to/cc (concat (or (message-fetch-field "to") "") ", "
                          (or (message-fetch-field "cc") "")))
@@ -715,25 +679,24 @@
   "Prompt the user for a folder in which the message should be filed.
 The folder is returned as a string.
 
-If `mh-default-folder-for-message-function' is a function then the message
-being refiled is yanked into a temporary buffer and the function is called to
-intelligently guess where the message is to be refiled.
-
-Otherwise, a default folder name is generated by `mh-folder-from-address'."
+The default folder name is generated by the option
+`mh-default-folder-for-message-function' if it is non-nil or
+`mh-folder-from-address'."
   (mh-prompt-for-folder
    "Destination"
-   (let ((refile-file (mh-msg-filename (mh-get-msg-num t))))
-     (save-excursion
-       (set-buffer (get-buffer-create mh-temp-buffer))
-       (erase-buffer)
-       (insert-file-contents refile-file)
-       (or (and mh-default-folder-for-message-function
-                (let ((buffer-file-name refile-file))
-                  (funcall mh-default-folder-for-message-function)))
-           (mh-folder-from-address)
-           (and (eq 'refile (car mh-last-destination-folder))
-                (symbol-name (cdr mh-last-destination-folder)))
-           "")))
+   (let ((refile-file (ignore-errors (mh-msg-filename (mh-get-msg-num t)))))
+     (if (null refile-file) ""
+       (save-excursion
+         (set-buffer (get-buffer-create mh-temp-buffer))
+         (erase-buffer)
+         (insert-file-contents refile-file)
+         (or (and mh-default-folder-for-message-function
+                  (let ((buffer-file-name refile-file))
+                    (funcall mh-default-folder-for-message-function)))
+             (mh-folder-from-address)
+             (and (eq 'refile (car mh-last-destination-folder))
+                  (symbol-name (cdr mh-last-destination-folder)))
+             ""))))
    t))
 
 (defun mh-refile-msg (range folder &optional dont-update-last-destination-flag)
@@ -872,7 +835,9 @@
                (setq count (1- count)))
              (not (car unread-sequence)))
            (message "No more unread messages"))
-          (t (mh-goto-msg (car unread-sequence))))))
+          (t (loop for msg in unread-sequence
+                   when (mh-goto-msg msg t) return nil
+                   finally (message "No more unread messages"))))))
 
 (defun mh-goto-next-button (backward-flag &optional criterion)
   "Search for next button satisfying criterion.
@@ -1090,7 +1055,7 @@
   (if (not (mh-outstanding-commands-p))
       (mh-set-folder-modified-p nil)))
 
-;;;###mh-autoload
+
 (defun mh-folder-line-matches-show-buffer-p ()
   "Return t if the message under point in folder-mode is in the show buffer.
 Return nil in any other circumstance (no message under point, no show buffer,
@@ -1123,7 +1088,6 @@
 (defun mh-version ()
   "Display version information about MH-E and the MH mail handling system."
   (interactive)
-  (mh-find-progs)
   (set-buffer (get-buffer-create mh-info-buffer))
   (erase-buffer)
   ;; MH-E version.
@@ -1140,19 +1104,12 @@
   ;; Emacs version.
   (insert (emacs-version) "\n\n")
   ;; MH version.
-  (let ((help-start (point)))
-    (condition-case err-data
-        (mh-exec-cmd-output "inc" nil (if mh-nmh-flag "-version" "-help"))
-      (file-error (insert (mapconcat 'concat (cdr err-data) ": ") "\n")))
-    (goto-char help-start)
-    (if mh-nmh-flag
-        (search-forward "inc -- " nil t)
-      (search-forward "version: " nil t))
-    (delete-region help-start (point)))
-  (goto-char (point-max))
-  (insert " mh-progs:\t" mh-progs "\n"
-          " mh-lib:\t" mh-lib "\n"
-          " mh-lib-progs:\t" mh-lib-progs "\n\n")
+  (if mh-variant-in-use
+      (insert mh-variant-in-use "\n"
+              " mh-progs:\t" mh-progs "\n"
+              " mh-lib:\t" mh-lib "\n"
+              " mh-lib-progs:\t" mh-lib-progs "\n\n")
+    (insert "No MH variant detected\n"))
   ;; Linux version.
   (condition-case ()
       (call-process "uname" nil t nil "-a")
@@ -1202,7 +1159,7 @@
 (defun mh-folder-size-flist (folder)
   "Find size of FOLDER using `flist'."
   (with-temp-buffer
-    (call-process (expand-file-name "flist" mh-progs) nil t nil
+    (call-process (expand-file-name "flist" mh-progs) nil t nil "-showzero"
                   "-norecurse" folder "-sequence" (symbol-name mh-unseen-seq))
     (goto-char (point-min))
     (multiple-value-bind (folder unseen total)
@@ -1236,6 +1193,7 @@
   (let ((config (current-window-configuration))
         (current-buffer (current-buffer))
         (threaded-view-flag mh-show-threads-flag))
+    (delete-other-windows)
     (save-excursion
       (when (get-buffer folder)
         (set-buffer folder)
@@ -1258,12 +1216,11 @@
            (mh-toggle-threads))
           (mh-index-data
            (mh-index-insert-folder-headers)))
-    (unless mh-showing-mode (delete-other-windows))
     (unless (eq current-buffer (current-buffer))
       (setq mh-previous-window-config config)))
   nil)
 
-;;;###mh-autoload
+
 (defun mh-update-sequences ()
   "Update MH's Unseen-Sequence and current folder and message.
 Flush MH-E's state out to MH. The message at the cursor becomes current."
@@ -1334,7 +1291,7 @@
                (mh-exec-cmd "refile" (mh-get-msg-num t) "-link"
                             "-src" mh-current-folder
                             (symbol-name folder))
-             (message "Message not copied.")))
+             (message "Message not copied")))
           (t
            (mh-set-folder-modified-p t)
            (cond ((null (assoc folder mh-refile-list))
@@ -1381,7 +1338,9 @@
                (setq count (1- count)))
              (not (car unread-sequence)))
            (message "No more unread messages"))
-          (t (mh-goto-msg (car unread-sequence))))))
+          (t (loop for msg in unread-sequence
+                   when (mh-goto-msg msg t) return nil
+                   finally (message "No more unread messages"))))))
 
 (defun mh-set-scan-mode ()
   "Display the scan listing buffer, but do not show a message."
@@ -1472,12 +1431,12 @@
     ["Go to First Message"              mh-first-msg t]
     ["Go to Last Message"               mh-last-msg t]
     ["Go to Message by Number..."       mh-goto-msg t]
-    ["Modify Message"                   mh-modify]
+    ["Modify Message"                   mh-modify t]
     ["Delete Message"                   mh-delete-msg (mh-get-msg-num nil)]
     ["Refile Message"                   mh-refile-msg (mh-get-msg-num nil)]
-    ["Undo Delete/Refile"               mh-undo t]
-    ["Process Delete/Refile"            mh-execute-commands
-     (or mh-refile-list mh-delete-list)]
+    ["Undo Delete/Refile"               mh-undo (mh-outstanding-commands-p)]
+    ["Execute Delete/Refile"            mh-execute-commands
+     (mh-outstanding-commands-p)]
     "--"
     ["Compose a New Message"            mh-send t]
     ["Reply to Message..."              mh-reply (mh-get-msg-num nil)]
@@ -1501,7 +1460,7 @@
     ["Incorporate New Mail"             mh-inc-folder t]
     ["Toggle Show/Folder"               mh-toggle-showing t]
     ["Execute Delete/Refile"            mh-execute-commands
-     (or mh-refile-list mh-delete-list)]
+     (mh-outstanding-commands-p)]
     ["Rescan Folder"                    mh-rescan-folder t]
     ["Thread Folder"                    mh-toggle-threads
      (not (memq 'unthread mh-view-ops))]
@@ -1541,6 +1500,12 @@
   (defvar tool-bar-map)
   (defvar desktop-save-buffer))         ;Emacs 21.4
 
+;; Register mh-folder-mode as supporting which-function-mode...
+(load "which-func" t t)
+(when (and (boundp 'which-func-modes)
+           (not (member 'mh-folder-mode which-func-modes)))
+  (push 'mh-folder-mode which-func-modes))
+
 (define-derived-mode mh-folder-mode fundamental-mode "MH-Folder"
   "Major MH-E mode for \"editing\" an MH folder scan listing.\\<mh-folder-mode-map>
 
@@ -1548,16 +1513,49 @@
 messages.  Messages can be marked for deletion or refiling into another
 folder; these commands are executed all at once with a separate command.
 
-A prefix argument (\\[universal-argument]) to delete, refile, list, or undo
-applies the action to a message sequence. If `transient-mark-mode',
-is non-nil, the action is applied to the region.
-
 Options that control this mode can be changed with \\[customize-group];
 specify the \"mh\" group. In particular, please see the `mh-scan-format-file'
 option if you wish to modify scan's format.
 
 When a folder is visited, the hook `mh-folder-mode-hook' is run.
 
+Ranges
+======
+Many commands that operate on individual messages, such as `mh-forward' or
+`mh-refile-msg' take a RANGE argument. This argument can be used in several
+ways.
+
+If you provide the prefix argument (\\[universal-argument]) to these commands,
+then you will be prompted for the message range. This can be any legal MH
+range which can include messages, sequences, and the abbreviations (described
+in the mh(1) man page):
+
+<num1>-<num2>
+    Indicates all messages in the range <num1> to <num2>, inclusive. The range
+    must be nonempty.
+
+`<num>:N'
+`<num>:+N'
+`<num>:-N'
+    Up to N messages beginning with (or ending with) message num. Num may be
+    any of the pre-defined symbols: first, prev, cur, next or last.
+
+`first:N'
+`prev:N'
+`next:N'
+`last:N'
+    The first, previous, next or last messages, if they exist.
+
+`all'
+    All of the messages.
+
+For example, a range that shows all of these things is `1 2 3 5-10 last:5
+unseen'.
+
+If the option `transient-mark-mode' is set to t and you set a region in the
+MH-Folder buffer, then the MH-E command will perform the operation on all
+messages in that region.
+
 \\{mh-folder-mode-map}"
 
   (make-local-variable 'font-lock-defaults)
@@ -1565,10 +1563,15 @@
   (make-local-variable 'desktop-save-buffer)
   (setq desktop-save-buffer t)
   (mh-make-local-vars
+   'mh-colors-available-flag (mh-colors-available-p)
+                                        ; Do we have colors available
    'mh-current-folder (buffer-name)     ; Name of folder, a string
    'mh-show-buffer (format "show-%s" (buffer-name)) ; Buffer that displays msgs
    'mh-folder-filename                  ; e.g. "/usr/foobar/Mail/inbox/"
    (file-name-as-directory (mh-expand-file-name (buffer-name)))
+   'mh-display-buttons-for-inline-parts-flag
+   mh-display-buttons-for-inline-parts-flag ; Allow for display of buttons to
+                                        ; be  toggled.
    'mh-arrow-marker (make-marker)       ; Marker where arrow is displayed
    'overlay-arrow-position nil          ; Allow for simultaneous display in
    'overlay-arrow-string ">"            ;  different MH-E buffers.
@@ -1597,6 +1600,8 @@
    'mh-sequence-notation-history (make-hash-table)
                                         ; Remember what is overwritten by
                                         ; mh-note-seq.
+   'imenu-create-index-function 'mh-index-create-imenu-index
+                                        ; Setup imenu support
    'mh-previous-window-config nil)      ; Previous window configuration
   (mh-remove-xemacs-horizontal-scrollbar)
   (setq truncate-lines t)
@@ -1620,6 +1625,26 @@
            font-lock-auto-fontify)
       (turn-on-font-lock)))             ; Force font-lock in XEmacs.
 
+(defun mh-toggle-mime-buttons ()
+  "Toggle display of buttons for inline MIME parts."
+  (interactive)
+  (setq mh-display-buttons-for-inline-parts-flag
+        (not mh-display-buttons-for-inline-parts-flag))
+  (mh-show nil t))
+
+(defun mh-colors-available-p ()
+  "Check if colors are available in the Emacs being used."
+  (or mh-xemacs-flag
+      (let ((color-cells
+             (or (ignore-errors (mh-funcall-if-exists display-color-cells))
+                 (ignore-errors (mh-funcall-if-exists
+                                 x-display-color-cells)))))
+        (and (numberp color-cells) (>= color-cells 8)))))
+
+(defun mh-colors-in-use-p ()
+  "Check if colors are being used in the folder buffer."
+  (and mh-colors-available-flag font-lock-mode))
+
 (defun mh-make-local-vars (&rest pairs)
   "Initialize local variables according to the variable-value PAIRS."
 
@@ -1631,7 +1656,11 @@
 (defun mh-restore-desktop-buffer (desktop-buffer-file-name
                                   desktop-buffer-name
                                   desktop-buffer-misc)
-  "Restore an MH folder buffer specified in a desktop file."
+  "Restore an MH folder buffer specified in a desktop file.
+When desktop creates a buffer, DESKTOP-BUFFER-FILE-NAME holds the file name to
+visit, DESKTOP-BUFFER-NAME holds the desired buffer name, and
+DESKTOP-BUFFER-MISC holds a list of miscellaneous info used by the
+`desktop-buffer-handlers' functions."
   (mh-find-path)
   (mh-visit-folder desktop-buffer-name)
   (current-buffer))
@@ -1641,6 +1670,8 @@
 If the optional argument DONT-EXEC-PENDING is non-nil then pending deletes and
 refiles aren't carried out.
 Return in the folder's buffer."
+  (when (stringp range)
+    (setq range (delete "" (split-string range "[ \t\n]"))))
   (cond ((null (get-buffer folder))
          (mh-make-folder folder))
         (t
@@ -1693,7 +1724,9 @@
       (goto-char scan-start)
       (cond ((looking-at "scan: no messages in")
              (keep-lines mh-scan-valid-regexp)) ; Flush random scan lines
-            ((looking-at "scan: bad message list ")
+            ((looking-at (if (mh-variant-p 'mu-mh)
+                             "scan: message set .* does not exist"
+                           "scan: bad message list "))
              (keep-lines mh-scan-valid-regexp))
             ((looking-at "scan: "))     ; Keep error messages
             (t
@@ -1869,46 +1902,21 @@
                                   (""))))))
       (mh-logo-display))))
 
-;;; XXX: Remove this function, if no one uses it any more...
-(defun mh-unmark-all-headers (remove-all-flags)
-  "Remove all '+' flags from the folder listing.
-With non-nil argument REMOVE-ALL-FLAGS, remove all 'D', '^' and '%' flags too.
-Optimized for speed (i.e., no regular expressions).
-
-This function is deprecated. Use `mh-remove-all-notation' instead."
-  (save-excursion
-    (let ((case-fold-search nil)
-          (last-line (1- (point-max)))
-          char)
-      (mh-first-msg)
-      (while (<= (point) last-line)
-        (forward-char mh-cmd-note)
-        (setq char (following-char))
-        (if (or (and remove-all-flags
-                     (or (= char (aref mh-note-deleted 0))
-                         (= char (aref mh-note-refiled 0))))
-                (= char (aref mh-note-cur 0)))
-            (progn
-              (delete-char 1)
-              (insert " ")))
-        (if remove-all-flags
-            (progn
-              (forward-char 1)
-              (if (= (following-char) (aref mh-note-seq 0))
-                  (progn
-                    (delete-char 1)
-                    (insert " ")))))
-        (forward-line)))))
-
 (defun mh-add-sequence-notation (msg internal-seq-flag)
   "Add sequence notation to the MSG on the current line.
-If INTERNAL-SEQ-FLAG is non-nil, then just remove text properties from the
-current line, so that font-lock would automatically refontify it."
+If INTERNAL-SEQ-FLAG is non-nil, then refontify the scan line if font-lock is
+turned on."
   (with-mh-folder-updating (t)
     (save-excursion
       (beginning-of-line)
       (if internal-seq-flag
-          (mh-notate nil nil mh-cmd-note)
+          (progn
+            ;; Change the buffer so that if transient-mark-mode is active
+            ;; and there is an active region it will get deactivated as in
+            ;; the case of user sequences.
+            (mh-notate nil nil mh-cmd-note)
+            (when font-lock-mode
+              (font-lock-fontify-region (point) (line-end-position))))
         (forward-char (1+ mh-cmd-note))
         (let ((stack (gethash msg mh-sequence-notation-history)))
           (setf (gethash msg mh-sequence-notation-history)
@@ -1930,7 +1938,11 @@
         (while (and all (cdr stack))
           (setq stack (cdr stack)))
         (when stack
-          (mh-notate nil (car stack) (1+ mh-cmd-note)))
+          (save-excursion
+            (beginning-of-line)
+            (forward-char (1+ mh-cmd-note))
+            (delete-char 1)
+            (insert (car stack))))
         (setf (gethash msg mh-sequence-notation-history) (cdr stack))))))
 
 (defun mh-remove-cur-notation ()
@@ -1953,7 +1965,7 @@
       (mh-remove-sequence-notation msg nil t))
     (clrhash mh-sequence-notation-history)))
 
-;;;###mh-autoload
+
 (defun mh-goto-cur-msg (&optional minimal-changes-flag)
   "Position the cursor at the current message.
 When optional argument MINIMAL-CHANGES-FLAG is non-nil, the function doesn't
@@ -2102,7 +2114,10 @@
 
 (defun mh-outstanding-commands-p ()
   "Return non-nil if there are outstanding deletes or refiles."
-  (or mh-delete-list mh-refile-list))
+  (save-excursion
+    (when (eq major-mode 'mh-show-mode)
+      (set-buffer mh-show-folder-buffer))
+    (or mh-delete-list mh-refile-list)))
 
 (defun mh-coalesce-msg-list (messages)
   "Given a list of MESSAGES, return a list of message number ranges.
@@ -2223,7 +2238,7 @@
   "Return non-nil if NAME is the name of an internal MH-E sequence."
   (or (memq name mh-internal-seqs)
       (eq name mh-unseen-seq)
-      (and mh-tick-seq (eq name mh-tick-seq))
+      (and (mh-colors-in-use-p) mh-tick-seq (eq name mh-tick-seq))
       (eq name mh-previous-seq)
       (mh-folder-name-p name)))
 
@@ -2264,6 +2279,15 @@
       (when (and (eq sequence mh-unseen-seq) (mh-speed-flists-active-p))
         (apply #'mh-speed-flists t folders-changed)))))
 
+(defun mh-catchup (range)
+  "Delete RANGE from the `mh-unseen-seq' sequence.
+
+Check the document of `mh-interactive-range' to see how RANGE is read in
+interactive use."
+  (interactive (list (mh-interactive-range "Catchup"
+                                           (cons (point-min) (point-max)))))
+  (mh-delete-msg-from-seq range mh-unseen-seq))
+
 (defun mh-delete-a-msg-from-seq (msg sequence internal-flag)
   "Delete MSG from SEQUENCE.
 If INTERNAL-FLAG is non-nil, then do not inform MH of the change."
@@ -2291,23 +2315,6 @@
                            "-sequence" (symbol-name seq)
                            (mh-coalesce-msg-list msgs)))))
 
-(defun mh-map-over-seqs (function seq-list)
-  "Apply FUNCTION to each sequence in SEQ-LIST.
-The sequence name and the list of messages are passed as arguments."
-  (while seq-list
-    (funcall function
-             (mh-seq-name (car seq-list))
-             (mh-seq-msgs (car seq-list)))
-    (setq seq-list (cdr seq-list))))
-
-(defun mh-notate-if-in-one-seq (msg character offset seq)
-  "Notate MSG.
-The CHARACTER is placed at the given OFFSET from the beginning of the listing.
-The notation is performed if the MSG is only in SEQ."
-  (let ((in-seqs (mh-seq-containing-msg msg nil)))
-    (if (and (eq seq (car in-seqs)) (null (cdr in-seqs)))
-        (mh-notate msg character offset))))
-
 (defun mh-seq-containing-msg (msg &optional include-internal-flag)
   "Return a list of the sequences containing MSG.
 If INCLUDE-INTERNAL-FLAG non-nil, include MH-E internal sequences in list."
@@ -2341,6 +2348,7 @@
   "'"           mh-toggle-tick
   ","           mh-header-display
   "."           mh-alt-show
+  ";"           mh-toggle-mh-decode-mime-flag
   ">"           mh-write-msg-to-file
   "?"           mh-help
   "E"           mh-extract-rejected-mail
@@ -2362,7 +2370,6 @@
   "g"           mh-goto-msg
   "i"           mh-inc-folder
   "k"           mh-delete-subject-or-thread
-  "l"           mh-print-msg
   "m"           mh-alt-send
   "n"           mh-next-undeleted-msg
   "\M-n"        mh-next-unread-msg
@@ -2382,6 +2389,7 @@
   "?"           mh-prefix-help
   "'"           mh-index-ticked-messages
   "S"           mh-sort-folder
+  "c"           mh-catchup
   "f"           mh-alt-visit-folder
   "i"           mh-index-search
   "k"           mh-kill-folder
@@ -2402,6 +2410,17 @@
   "b"           mh-junk-blacklist
   "w"           mh-junk-whitelist)
 
+(gnus-define-keys (mh-ps-print-map "P" mh-folder-mode-map)
+  "?"           mh-prefix-help
+  "A"           mh-ps-print-toggle-mime
+  "C"           mh-ps-print-toggle-color
+  "F"           mh-ps-print-toggle-faces
+  "M"           mh-ps-print-toggle-mime
+  "f"           mh-ps-print-msg-file
+  "l"		mh-print-msg
+  "p"           mh-ps-print-msg
+  "s"           mh-ps-print-msg-show)
+
 (gnus-define-keys (mh-sequence-map "S" mh-folder-mode-map)
   "'"           mh-narrow-to-tick
   "?"           mh-prefix-help
@@ -2446,8 +2465,10 @@
 (gnus-define-keys (mh-mime-map "K" mh-folder-mode-map)
   "?"           mh-prefix-help
   "a"           mh-mime-save-parts
+  "e"           mh-display-with-external-viewer
   "i"           mh-folder-inline-mime-part
   "o"           mh-folder-save-mime-part
+  "t"           mh-toggle-mime-buttons
   "v"           mh-folder-toggle-mime-part
   "\t"          mh-next-button
   [backtab]     mh-prev-button
@@ -2477,13 +2498,17 @@
 (defvar mh-help-messages
   '((nil "[i]nc, [.]show, [,]show all, [n]ext, [p]revious,\n"
          "[d]elete, [o]refile, e[x]ecute,\n"
-         "[s]end, [r]eply.\n"
+         "[s]end, [r]eply,\n"
+         "[;]toggle MIME decoding.\n"
          "Prefix characters:\n [F]older, [S]equence, [J]unk, MIME [K]eys,"
          "\n [T]hread, [/]limit, e[X]tract, [D]igest, [I]nc spools.")
 
     (?F "[l]ist; [v]isit folder;\n"
         "[n]ew messages; [']ticked messages; [s]earch; [i]ndexed search;\n"
         "[p]ack; [S]ort; [r]escan; [k]ill")
+    (?P "PS [p]rint message; [l]non-PS print;\n"
+        "PS Print [s]how window, message to [f]ile;\n"
+        "Toggle printing of [M]IME parts, [C]olor, [F]aces")
     (?S "[p]ut message in sequence, [n]arrow, [']narrow to ticked, [w]iden,\n"
         "[s]equences, [l]ist,\n"
         "[d]elete message from sequence, [k]ill sequence")