Upgraded to MH-E version 7.4.80.
authorBill Wohler <wohler@newt.com>
Sun, 15 Aug 2004 22:00:06 +0000 (22:00 +0000)
committerBill Wohler <wohler@newt.com>
Sun, 15 Aug 2004 22:00:06 +0000 (22:00 +0000)
See etc/MH-E-NEWS and lisp/mh-e/ChangeLog for details.

20 files changed:
etc/ChangeLog
etc/MH-E-NEWS
etc/NEWS
lisp/mh-e/ChangeLog
lisp/mh-e/mh-alias.el
lisp/mh-e/mh-comp.el
lisp/mh-e/mh-customize.el
lisp/mh-e/mh-e.el
lisp/mh-e/mh-funcs.el
lisp/mh-e/mh-gnus.el
lisp/mh-e/mh-identity.el
lisp/mh-e/mh-inc.el
lisp/mh-e/mh-index.el
lisp/mh-e/mh-junk.el
lisp/mh-e/mh-loaddefs.el
lisp/mh-e/mh-mime.el
lisp/mh-e/mh-pick.el
lisp/mh-e/mh-seq.el
lisp/mh-e/mh-speed.el
lisp/mh-e/mh-utils.el

index 33d187a..3c6ac1e 100644 (file)
@@ -1,3 +1,7 @@
+2004-08-15  Bill Wohler  <wohler@newt.com>
+
+       * NEWS, MH-E-NEWS: Upgraded to MH-E version 7.4.80.
+
 2004-08-14  Romain Francoise  <romain@orebokech.com>
 
        * NEWS: Mention the thumbs.el package.
index 5bea16d..264acf8 100644 (file)
@@ -6,6 +6,372 @@ Copying and distribution of this file, with or without modification,
 are permitted in any medium without royalty provided the copyright
 notice and this notice are preserved.
 
+* Changes in MH-E 7.4.80
+
+Version 7.4.80 now supports GNU mailutils, S/MIME, picons,
+which-func-mode, has an improved interface for hiding header fields,
+improves upon the MH variant detection, and contains many bug fixes.
+Those of you familiar with the GNU version numbering schemes will
+recognize this as an alpha release. This does not reflect on the
+quality of this release which is as high as it has always been.
+Although we are not ready to release 8.0, we want you to have access
+to the work that has been hiding in CVS. At the same time we want to
+make it clear that there are incompatible changes with previous
+versions.
+
+We are planning to release the long-awaited manual update synchronized
+with version 8.0. We are using documentation from the manual in the
+docstrings which is hoped to make "C-h f (describe-function)" really
+useful and create a seamless experience when switching back and forth
+between the manual and the docstrings. This has been done in about
+half of the variables and functions in this version.
+
+The writing of the manual has revealed a few inconsistencies in the
+software whose fixes have resulted in incompatible changes, and there
+may well be more. So, unlike version 7 which was chock full of new
+features, version 8's strengths will include complete documentation
+and higher quality.
+
+** New Features in MH-E 7.4.80
+
+*** GNU mailutils Support
+
+MH-E now supports GNU mailutils 0.4 and higher versions.
+
+*** S/MIME Support
+
+MH-E now supports S/MIME using Gnus 5.10.6 or higher.
+
+*** Picon Support
+
+In addition to the other methods of displaying an icon for the sender
+of a message, MH-E can now display images from a picon directory. The
+directory search path is found in the `mh-picon-directory-list'
+variable. More documentation is found in the "facedb" sections in the
+xfaces man page. [NOTE: need to make mh-picon-directory-list an option
+and add xfaces facedb documentation to it.]
+
+*** X-Image-URL Updates
+
+Now support the use of `curl' and `fetch' as alternatives to `wget' to
+obtain the image. The display of images are controlled with the
+`mh-show-use-xface-flag' option while the `mh-fetch-x-image-url'
+option controls how the images are fetched.
+
+WARNING: There are security concerns with this feature. Please read
+the documentation for these options carefully before changing the
+default.
+
+*** Updates to mh-identity-list
+
+Note that the field names found in `mh-identity-list' that refer to
+the fields in `mh-identity-handlers' have changed in an incompatible
+way from 7.4.4. In general, the symbolic names now have a ":" prefix
+to avoid collisions with header fields. Before starting Emacs, edit
+your .emacs and insert ":" before "signature" if you have defined it.
+
+You can change your attribution in replies with the new "Attribution
+Verb" field, and you can set your default GPG user ID with the "GPG
+key ID" field.
+
+Signatures can now be read from the `mh-signature-file-name' variable,
+or come from a function, in addition to a named file. If you write
+your own function, variables that you can use include
+`mh-signature-separator-regexp', `mh-signature-separator',
+and `mh-signature-separator-p'.
+
+The handling of these fields has been moved into a new
+`mh-identity-handlers' option, an alist of fields (strings) and
+handlers (functions). Strings are lowercase. Use ":signature" for
+Signature and ":pgg-default-user-id" for GPG Key ID. The function
+associated with the string "default" is used if no other functions are
+appropriate. For this reason, don't name a header field "Default".
+
+If you point your signature at a vCard file with a vcf suffix, then it
+will be incorporated as a vCard body part (closes SF #802723).
+
+*** Catchup Command
+
+There is a new "F c (mh-catchup)" command that marks all unread
+messages in the current folder as read.
+
+*** Change Content-Type Renderer on the Fly in MH-Show Buffer
+
+This has been implemented by adding the key binding "K e
+(mh-display-with-external-viewer)". For inline text/html parts,
+buttons aren't displayed by default. In that case use "K t
+(mh-toggle-mime-buttons)" to display the button before viewing it with
+an external browser (closes SF #839318).
+
+*** Use which-func-mode to Display Folder in Index Mode
+
+Turning on `which-func-mode' displays the folder name of the message
+under the cursor in index folders (closes SF #855520).
+
+*** Render Signature and vCard in Italics
+
+This has been implemented.  Use `mh-show-signature-face' to customize
+the face used (closes SF #802722).
+
+*** New Print Map
+
+There is now a keymap for the printing functions whose prefix is "P".
+The command "l (mh-print-msg)" has been replaced with "P l". Other new
+functions in this keymap include:
+
+    P A         mh-ps-print-toggle-mime
+    P C         mh-ps-print-toggle-color
+    P F         mh-ps-print-toggle-faces
+    P M         mh-ps-print-toggle-mime
+    P f         mh-ps-print-msg-file
+    P l         mh-print-msg
+    P p         mh-ps-print-msg
+    P s         mh-ps-print-msg-show
+
+*** Draft Buffer Keymap Changes
+
+The keymap in the draft buffer has been modified slightly. The old
+anonymous ftp and tar composition commands have been reinstated and
+letter signing and encrypting keymaps have been added.
+
+The type of signing or encryption has been generalized so the method
+is now an option rather than a part of the function's name. The option
+is `mh-mml-method-default' and choices include PGP (MIME), PGP,
+S/MIME, or none.
+
+Key            7.4.4                   7.4.80
+
+C-c RET C-e    mh-mml-secure-message-encrypt-pgpmime
+                                       mh-mml-secure-message-encrypt
+C-c RET C-s    mh-mml-secure-message-sign-pgpmime
+                                       -
+C-c RET C-g    -                       mh-mhn-compose-anon-ftp
+C-c RET C-n    -                       mh-mml-unsecure-message
+C-c RET C-s    -                       mh-mml-secure-message-sign
+C-c RET C-t    -                       mh-mhn-compose-external-compressed-tar
+C-c RET C-s    mh-mml-secure-message-sign-pgpmime
+                                       mh-mml-secure-message-sign
+C-c RET C-x    -                       mh-mhn-compose-external-type
+C-c RET e      mh-mml-secure-message-encrypt-pgpmime
+                                       Prefix Command
+C-c RET e e    -                       mh-mml-secure-message-encrypt
+C-c RET e s    -                       mh-mml-secure-message-signencrypt
+C-c RET g      -                       mh-mhn-compose-anon-ftp
+C-c RET n      -                       mh-mml-unsecure-message
+C-c RET s      mh-mml-secure-message-sign-pgpmime
+                                       Prefix Command
+C-c RET s e    -                       mh-mml-secure-message-signencrypt
+C-c RET s s    -                       mh-mml-secure-message-sign
+C-c RET t      -                       mh-mhn-compose-external-compressed-tar
+C-c RET x      -                       mh-mhn-compose-external-type
+
+*** Speedbar: Highlight Folders With Unseen
+
+The speedbar now renders the folders with unseen messages in boldface
+which makes them easier to identify (closes SF #623369).
+
+*** Quick Key Help
+
+The "? (mh-help)" function now displays the help in its own buffer
+called *MH-E Help* (closes SF #493740 and SF #656631).
+
+*** New Startup File mh-e-autoloads.el
+
+If you are installing MH-E yourself, then you can replace any
+autoloads you may have with "(require 'mh-e-autoloads.el)". See the
+README for details.
+
+*** Glimpse Support Removed
+
+Since glimpse isn't free, we cannot mention it. Glimpse has been
+removed from the option `mh-indexer-choices' (closes SF #831276).
+
+*** mh-msg-is-in-seq Update
+
+Can now specify an alternate message number to "S s
+(mh-msg-is-in-seq)" with a prefix argument.
+
+** New Variables in MH-E 7.4.80
+
+Variables that have been added to MH-E that have not been discussed
+elsewhere are listed here.
+
+*** mail-citation-hook
+
+Hook for modifying a citation just inserted in the mail buffer.
+
+*** mh-alias-reloaded-hook
+
+Invoked by `mh-alias-reload' after reloading aliases.
+
+*** mh-auto-fields-prompt-flag
+
+Non-nil means to prompt before sending if fields in
+`mh-auto-fields-list' are inserted.
+
+*** mh-default-folder-for-message-function
+
+Function to select a default folder for refiling or `Fcc'.
+
+*** mh-forward-hook
+
+Invoked on the forwarded letter by "f (mh-forward)".
+
+*** mh-invisible-header-fields-default
+
+List of hidden header fields. The header fields listed in this option
+are hidden, although you can check off any field that you would like
+to see. Header fields that you would like to hide that aren't listed
+can be added to the `mh-invisible-header-fields' option (closes SF
+#752045).
+
+The option `mh-visible-header-fields' has been deleted.
+
+*** mh-junk-background
+
+If on, spam programs are run in background. This used to be the
+default behavior but this could overwhelm a system if many messages
+were black- or whitelisted at once. The spam programs are now run in
+the foreground, but this option can be used to put them back in the
+background.
+
+*** mh-signature-separator-flag
+
+Non-nil means a signature separator should be inserted. It is not
+recommended that you change this option since various mail user
+agents, including MH-E, use the separator to present the signature
+differently, and to suppress the signature when replying or yanking a
+letter into a draft.
+
+*** mh-variant
+
+Specifies the variant used by MH-E. The default setting of this option
+is `Auto-detect' which means that MH-E will automatically choose the
+first of nmh, MH, or GNU mailutils that it finds in the directories
+listed in `mh-path', `mh-sys-path', and `exec-path'. If, for example,
+you have both nmh and mailutils installed and `mh-variant-in-use' was
+initialized to nmh but you want to use mailutils, then you can set
+this option to `mailutils'.
+
+When this variable is changed, MH-E resets `mh-progs', `mh-lib',
+`mh-lib-progs', `mh-flists-present-flag', and `mh-variant-in-use'
+accordingly.
+
+If you've set these variables in your .emacs, it is strongly suggested
+that you comment them out. The MH detection code has been completely
+rewritten and it is very likely that you no longer to set them and
+their setting may confuse other MH-E settings.
+
+** Variables Deleted in MH-E
+
+Variables that have been removed from MH-E that have not been
+discussed elsewhere are listed here.
+
+*** mh-alias-system-aliases
+
+System definitions should not be a user option.
+
+*** mh-junk-mail-folder
+
+Since this variable can accept values other than folder names, it was
+renamed to `mh-junk-disposition' to more accurately reflect the content.
+
+** Bug Fixes in MH-E 7.4.80
+
+Many bugs were fixed in this version that aren't listed below.
+
+*** mh-extract-rejected-mail Can't Do MIME (and Other Formats)
+
+Now handles qmail and exim bounces (addresses SF #404965).
+
+*** mh-rmail Hangs in XEmacs
+
+We've determined that MH-E is incompatible with some versions of
+XEmacs (21.5.9-21.5.16). More recent versions work fine. If you think
+our list is too broad, please let us know which version of XEmacs you
+are using (closes SF #644321).
+
+*** Inconsistent Prompts
+
+Prompt formats are now consistent throughout the application (closes
+SF #730470).
+
+*** Empty Shell Comments Confuse mh-mhn-directive-present-p
+
+If you had a string that matched the regexp "^# $" in your draft, it
+would cause an error. This has been fixed (closes SF #762458).
+
+*** Quote Hashes When mhbuild Directives Used
+
+A related bug, if you had empty shell comments but inserted your own
+directives, you'd get another error from mhbuild. This has been fixed
+by quoting the hash ("^# $") like this "##" before submitting to
+mhbuild (closes SF #762464).
+
+*** Inconsistent Usage in Scan Formatting Variables
+
+The variables:
+
+    mh-note-cur
+    mh-note-deleted
+    mh-note-dist
+    mh-note-forw
+    mh-note-refiled
+    mh-note-repl
+    mh-note-seq
+
+used to contain strings. Although only the first character was read,
+the entire string would be inserted which may have caused problems.
+These variables have been converted to character constants so that
+only a single character can be inserted into the scan line (closes SF
+#770772).
+
+*** Bad Handling of Aliases That Conflict With Local User Names
+
+If a user name existed both locally and in the aliases file, the local
+user would be flashed, but the alias would be used when sending. This
+has been fixed so that the user name that is flashed is the same as
+the name that is sent (closes SF #772595).
+
+*** Args out of range
+
+In rare and non-reproducible circumstances, compilation sometimes
+threw an "Args out of range" error. Nonetheless, this has been fixed
+(closes SF #806577).
+
+*** mh-forward hard-codes '-mime' Switch on nmh
+
+Added new option `mh-compose-forward-as-mime-flag' that controls whether
+messages are forwarded as MIME attachments (closes SF #827203).
+
+*** Not Re-prompted to Sign After Pass Phrase Typo
+
+If there were errors when sending a signed message (like getting the
+pass phrase wrong), the MML markup remained in the draft buffer. The
+draft buffer is now restored if there is an error (closes SF #839303).
+
+*** Font-lock Gets Confused in MH-Letter Buffer
+
+If a user manually moved the cursor to the end of the header field
+separator line (by mouse click or keyboard navigation) and hit Enter
+to start typing their message, any line in the body with a colon would
+be fontified with a gray background. This has been fixed (closes SF
+#855479).
+
+*** mh-refile-msg Fails to Suggest Folder for Empty Message
+
+If you received a message with an empty body from someone who is
+listed in your aliases file, "o (mh-refile-msg)" failed to suggest the
+correct folder. This has been fixed (closes SF #917096).
+
+*** Error Visiting Folder With no Unseen Messages
+
+If you visited a folder without unseen messages and the option "flist:
+-noshowzero" is present in your ~/.mh_profile, you'd get an error. This
+has been fixed (closes SF #933954).
+
+\f
+
 * Changes in MH-E 7.4.4
 
 Version 7.4.4 addresses programmatic issues from the FSF and prepares
@@ -18,7 +384,7 @@ code moved here from desktop.el.
 
 * Changes in MH-E 7.4.3
 
-Version 7.4.3 fixes the problem where mh-identity-list was not getting
+Version 7.4.3 fixes the problem where `mh-identity-list' was not getting
 set from .emacs.
 
 * Changes in MH-E 7.4.2
index c25c07e..43af2c9 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -658,7 +658,7 @@ You can now put the init files .emacs and .emacs_SHELL under
 
 ** MH-E changes.
 
-Upgraded to MH-E version 7.4.4. There have been major changes since
+Upgraded to MH-E version 7.4.80. There have been major changes since
 version 5.0.2; see MH-E-NEWS for details.
 
 +++
index 3d19028..645e9a1 100644 (file)
@@ -1,3 +1,239 @@
+2004-08-15  Bill Wohler  <wohler@newt.com>
+
+       * Released MH-E version 7.4.80.
+     
+       * MH-E-NEWS, README: Updated for release 7.4.80.
+     
+       * mh-e.el (Version, mh-version): Updated for release 7.4.80.
+       
+2004-08-15  Bill Wohler  <wohler@newt.com>
+
+       * mh-funcs.el, mh-gnus.el, mh-inc.el, mh-init.el, mh-junk.el,
+       mh-pick.el, mh-print.el, mh-xemacs.el: Added 2004 to Copyright.
+
+       * mh-acros.el, mh-alias.el: Checkdoc fixes.
+       
+2004-08-12  Satyaki Das  <satyaki@theforce.stanford.edu>
+
+       * mh-acros.el (cl): Load cl in this file. That is all right, since
+       this file is only used at compile time, and so cl doesn't get
+       loaded at run time. This avoids problems with stale *.elc files
+       present in the Emacs source tree during compilation.
+       (mh-defstruct): Modify it to make it more CL like and in the
+       process simplify it a bit. This makes the argument list of the
+       constructor compatible with the previous version, thereby avoiding
+       a compilation error when an old version of mh-seq.elc is present.
+
+       * mh-seq.el (mh-thread-id-container, mh-thread-get-message)
+       (mh-thread-get-message-container): Revert back to the CL style
+       of using keyword arguments, since the mh-defstruct now produces
+       code compatible to such usage.
+
+2004-08-11  Satyaki Das  <satyaki@theforce.stanford.edu>
+
+       * mh-acros.el (mh-defstruct, mh-require-cl): Checkdoc fixes.
+
+       * mh-utils.el (message-tokenize-header, message-fetch-field): Add
+       autoloads.
+       (mh-folder-completing-read): Make the folder completion look
+       better with CVS Emacs.
+
+       * mh-init.el (mh-variant-set): Remove dead code.
+
+2004-08-11  Bill Wohler  <wohler@newt.com>
+
+       * *.el: Use the following at the top of each file which seems to
+       do a good job of suppressing compilation warnings in 21.3 and CVS
+       Emacs (21.4). This replaces (require 'cl) or (require
+       'utils) (mh-require-cl) calls:
+       
+         (eval-when-compile (require 'mh-acros))
+          (mh-require-cl)
+
+2004-08-10  Bill Wohler  <wohler@newt.com>
+
+       * release-utils (DESCRIPTION): Added one.
+       (FILES, SEE ALSO, VERSION): Deleted empty and incorrect sections.
+
+       * mh-e.el (mh-colors-available-p): Call x-display-color-cells with
+       mh-funcall-if-exists since it no longer seems to be defined in
+       GNU Emacs 21.4.
+
+2004-08-10  Satyaki Das  <satyaki@theforce.stanford.edu>
+
+       * mh-speed.el (mh-process-kill-without-query, mh-speed-flists):
+       Avoid a compiler warning in versions of Emacs where
+       process-kill-without-query is a deprecated function.
+
+       * mh-seq.el (mh-thread-message, mh-thread-container): Use
+       mh-defstruct instead of defstruct.
+       (mh-thread-id-container, mh-thread-get-message-container) 
+       (mh-thread-get-message): Use the slightly different structure
+       constructor function.
+
+       * mh-acros.el (mh-defstruct): New macro which is a partial
+       replacement of the defstruct in CL.
+       (no-byte-compile): Don't compile the file since it isn't loaded at
+       run time, so efficiency isn't an issue.
+
+       * mh-utils.el (mh-buffer-data): Use mh-defstruct instead of
+       defstruct.
+
+2004-08-09  Satyaki Das  <satyaki@theforce.stanford.edu>
+
+       * mh-funcs.el, mh-junk.el, mh-print.el: Use mh-require-cl to avoid
+       compilation warnings in Emacs-21.3.
+
+       * mh-acros.el (mh-require-cl): Add autoloads of CL functions used.
+
+2004-08-09  Bill Wohler  <wohler@newt.com>
+
+       * mh-customize.el (mh-show-use-xface-flag): Mention that `fetch' and
+       `curl' are supported as well.
+
+2004-08-08  Bill Wohler  <wohler@newt.com>
+
+       * mh-xemacs.el (mh-xemacs-has-toolbar-flag): Checkdoc fixes.
+
+       * mh-mime.el (mh-display-with-external-viewer): Checkdoc fixes.
+
+       * mh-identity.el: (mh-identity-attribution-verb-end): Stripped
+       trailing space; checkdoc fixes.
+
+       * mh-e.el (mh-restore-desktop-buffer): Checkdoc fixes.
+
+       * mh-customize.el: (mh-inc-spool-list,
+       mh-compose-forward-as-mime-flag, defcustom): Stripped trailing
+       space; checkdoc fixes.
+
+       * mh-comp.el (mh-reply): Stripped trailing space.
+
+       * mh-unit.el (mh-unit-files): Added mh-acros.el and mh-gnus.el.
+       (mh-unit): Don't lm-verify pre-21.4. Save buffers before killing
+       since we might have done some editing.
+
+       * import-emacs: Deleted. Functionality subsumed by release-utils.
+
+       * release-utils: New script. Performs import-emacs functionality
+       and displays new and deleted options.
+
+       * Makefile (import-emacs): Call release-utils instead of
+       import-emacs.
+
+       * mh-funcs.el (mh-undo-folder): Removed deprecated `ignore'
+       argument.
+
+       * mh-e.el (mh-scan-date-regexp): Deleted as Peter claims it is
+       obsolete.
+       (mh-folder-font-lock-keywords): Removed reference to deleted
+       variable `mh-scan-date-regexp'.
+
+       * mh-customize.el (mh-auto-fields-prompt-flag): Made reference to
+       `mh-auto-fileds-lists'.
+       (mh-forward-hook): Fixed docstring typo.
+
+2004-08-07  Bill Wohler  <wohler@newt.com>
+
+       * mh-acros.el: New file. Currently holds macros needed by
+       mh-customize.el but is planned to hold all macros to avoid
+       dependency problems when compiling.
+
+       * mh-utils.el (mh-xemacs-flag): Defined in mh-customize.el now.
+       (mh-require-cl, mh-do-in-gnu-emacs, mh-do-in-xemacs)
+       (mh-funcall-if-exists, mh-make-local-hook, mh-mark-active-p):
+       Moved to new file mh-acros.el.
+
+       * mh-customize.el: Require mh-acros and cl only when compiling and
+       mh-loaddefs at runtime instead of mh-utils.
+       (mh-xemacs-flag): Define it here instead of mh-utils.el.
+
+       * Makefile (MH-E-SRC): Added mh-acros.el.
+
+       * mh-gnus.el (default-enable-multibyte-characters): Don't define
+       any more. It doesn't seem to be needed.
+
+       * mh-customize.el (mh-junk-background): New variable. If on, spam
+       programs are run in background. Running in foreground can be slow.
+       Defaults to nil to spare machines with little memory.
+
+       * mh-junk.el (mh-spamassassin-blacklist, mh-bogofilter-blacklist) 
+       (mh-bogofilter-whitelist, mh-spamprobe-blacklist) 
+       (mh-spamprobe-whitelist): Use new option mh-junk-background.
+
+2004-07-25  Satyaki Das  <satyaki@theforce.stanford.edu>
+
+       * mh-utils.el (mh-folder-completing-read): In recent CVS Emacs,
+       the first letter of the possible choices in the completion buffer
+       is highlighted. The change is needed for this feature to work
+       during folder name completion. This is not entirely sufficient,
+       since the leading "+" in folder names is still mishandled. A patch
+       is required in Emacs itself to address that.
+
+2004-07-22  Mark D. Baushke  <mdb@gnu.org>
+
+       * mh-e.el (recursive-load-depth-limit): Move
+       recursive-load-depth-limit code to ...
+       * mh-utils.el (recursive-load-depth-limit): ... here to avoid
+       problems compiling mh-utils.el and mh-alias.el with gnus-5.10.6
+       under emacs-21.1. Use eval-and-compile instead of eval-when.
+
+2004-07-20  Bill Wohler  <wohler@newt.com>
+
+       * mh-customize.el (mh-invisible-header-fields-internal): Added
+       header fields emitted by T-Mobile picture phones (X-Mms-*, and
+       commented out X-Operator field saying it's like X-Mailer).
+       
+2004-07-12  Bill Wohler  <wohler@newt.com>
+
+       * mh-gnus.el: Set local variables indent-tabs-mode and
+       sentence-end-double-space to nil.
+
+       * mh-customize.el: Checkpoint from option docstring updates and
+       manual synchronization from last summer. For the options listed
+       below, docstring was usually completely rewritten. Use "on"
+       instead of "t" in docstring to match what is seen in customization
+       buffer. Use headline capitalization. Standardize on "Auto-detect"
+       text when option has that capibility.
+       (mh): Since we work on more than one type of Emacs, use Emacs
+       instead of GNU Emacs. Prefer GNU mailutils over GNU Mailutils.
+       (mh-variant): s/Autodetect at startup/Auto-detect/.
+       (mh-alias-insertion-location): s/Sorted
+       alphabetically/Alphabetical/. s/At the top of file/Top/. s/At the
+       bottom of file/Bottom/.
+       (mh-alias-local-users-prefix): s/Use login instead of real
+       name/Use Login/.
+       (mh-identity-list): Sorted values by fields, attribution,
+       signature, GPG key.
+       (mh-auto-fields-list): Missing quote.
+       (mh-compose-insertion): s/Use Gnus/Gnus/. s/Use mhn/mhn/.
+       (mh-compose-space-does-completion-flag): s/SPACE/<SPC>/.
+       (mh-extract-from-attribution-verb): Since we have French, added
+       German too ;-).
+       (mh-letter-complete-function): Mention default in docstring.
+       (mh-invisible-header-fields-internal): Added X-ELNK-Trace from
+       Earthlink.
+       (mh-alias-flash-on-comma, mh-alias-insert-file)
+       (mh-alias-passwd-gecos-comma-separator-flag)
+       (mh-recenter-summary-flag, mh-default-folder-for-message-function)
+       (mh-default-folder-must-exist-flag, mh-index-program)
+       (mh-index-ticked-messages-folders, mh-ins-buf-prefix)
+       (mh-delete-yanked-msg-window-flag, mh-identity-default): See
+       summary above.
+
+       * mh-init.el (mh-variant-set, mh-sys-path, mh-variant-mu-mh-info):
+       Prefer GNU mailutils over GNU Mailutils MH.
+       
+       * mh-comp.el (sc-cite-original, mh-smail, mh-smail-batch)
+       (mh-edit-again, mh-extract-rejected-mail, mh-forward)
+       (mh-smail-other-window, mh-reply, mh-send, mh-send-other-window):
+       Use `mh-send' instead of \\[mh-send]] since links in the docstring
+       are more useful than a key sequence in these cases. Use "See also"
+       instead of "See also documentation for".
+
+       * Merged in 7.4.4 changes, described below.
+
+       * mh-e.el (Version, mh-version):  Set to 7.4.4+cvs.
+
 2004-07-10  Bill Wohler  <wohler@newt.com>
 
        * Released MH-E version 7.4.4.
        require that the cl package not be required at runtime. However,
        the cl package in versions of Emacs prior to 21.4 left cl routines
        in their macro expansions. Use mh-require-cl to provide the cl
-       routines in the best way possible.
+       routines in the best way possible (closes SF #930012).
        (require 'mouse): To shush compiler.
 
        * Use new function mh-require-cl throughout.
        4. Run xbmtopbm < file.xbm > file.pbm.
        Thanks to jan.h.d@swipnet.se for the help.
 
+2004-07-07  Stephen Gildea
+
+       * mh-customize.el (mh-invisible-header-fields-internal): 
+       Add X-Greylist, X-Source*, and X-WebTV-Signature.
+       Replace specific X-Spam-* headers with general pattern.
+       
+2004-06-15  Bill Wohler  <wohler@newt.com>
+
+       * README: Vladimir Ivanovic reports that mh-rmail works with
+       XEmacs 21.5.17, so updated requirements text accordingly (closes
+       SF #644321).
+
+2004-05-12  Satyaki Das  <satyaki@theforce.stanford.edu>
+
+       * mh-utils.el (mh-mail-header-end): Replace call to
+       rfc822-goto-eoh with something that allows From_ lines in the mail
+       header.
+
+2004-04-14  Bill Wohler  <wohler@newt.com>
+
+       * mh-utils.el (mh-show-mouse): s/EVENT/event/. Thanks to John Paul
+       Wallington <jpw@gnu.org> for pointing this out.
+
+2004-04-12  Satyaki Das  <satyaki@theforce.stanford.edu>
+
+       * mh-e.el (mh-folder-size-flist): Add -showzero option so that the
+       parsing code doesn't get confused by the presence of -noshowzero
+       in the user's .mh_profile (closes SF #933954).
+
+2004-04-07  Satyaki Das  <satyaki@theforce.stanford.edu>
+
+       * mh-mime.el (mh-insert-mime-button) 
+       (mh-insert-mime-security-button): Add evaporate property to
+       overlays used in MIME part buttons.  This avoids problems with
+       CVS Emacs.
+
+2004-03-16  Satyaki Das  <satyaki@theforce.stanford.edu>
+
+       * mh-e.el (mh-folder-from-address): Go to the end of buffer if the
+       re-search-forward fails (closes SF #917096).
+
+2004-02-02  Satyaki Das  <satyaki@theforce.stanford.edu>
+
+       * mh-customize.el (mh-compose-forward-as-mime-flag): New user
+       customizable variable that controls whether messages are forwarded
+       as MIME attachments (closes SF #827203).
+
+       * mh-comp.el (mh-forward): Call forw with -mime option only if
+       mh-compose-forward-as-mime-flag is non-nil.
+
+2003-12-26  Jeffrey C Honig  <jch@honig.net>
+
+       * mh-junk.el (mh-junk-blacklist, mh-junk-whitelist) 
+       (mh-spamassassin-blacklist, mh-spamassassin-blacklist) 
+       (mh-spamassassin-blacklist, mh-spamassassin-whitelist) 
+       (mh-spamassassin-whitelist, mh-bogofilter-blacklist) 
+       (mh-spamprobe-blacklist): Add progress messages.  Change "Couldn't"
+       to "Unable" in error messages.  Run bogofilter and spamprobe in
+       the foreground to prevent a large number of processes from
+       swamping the system.
+
+2003-12-25  Satyaki Das  <satyaki@theforce.stanford.edu>
+
+       * mh-e.el (mh-prompt-for-refile-folder): Marking the whole folder
+       and then refiling all messages throws an error, since this
+       function expects point to be on a valid scan line. The change
+       relaxes this requirement, thereby avoiding the above problem.
+
+2003-12-14  Satyaki Das  <satyaki@theforce.stanford.edu>
+
+       * mh-comp.el (mh-ascii-buffer-p): New function that checks if a
+       buffer is entirely composed of ASCII.
+       (mh-send-letter): Encode the draft if it contains non-ASCII
+       characters.
+
+2003-12-12  Satyaki Das  <satyaki@theforce.stanford.edu>
+
+       * mh-customize.el (mh-invisible-headers): Keep only unique fields
+       in list of header fields to hide. This avoids problems in XEmacs.
+
+2003-12-10  Satyaki Das  <satyaki@theforce.stanford.edu>
+
+       * mh-seq.el (mh-thread-print-scan-lines): The imenu index was not
+       getting created for threaded index buffers. The change fixes this.
+
+       * mh-index.el (mh-index-insert-folder-headers): Always create the
+       imenu index.
+       (mh-index-create-imenu-index): Set which-func-mode to t. If
+       which-function-mode is turned on after the folder buffer has been
+       prepared, display of the folder info was being inhibited. The
+       change fixes that.
+
+2003-12-09  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-comp.el (mh-letter-mode): Setup mh-mail-header-separator
+       based on draft contents.
+       (mh-letter-mode, mh-letter-mail-header-end-marker)
+       (mh-letter-header-end): Remove use of the variable
+       mh-letter-mail-header-end-marker. Instead use
+       mh-mail-header-separator. This avoids problems in font locking
+       draft buffers (closes SF #855479).
+
+2003-12-09  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-index.el (mh-index-insert-folder-headers): Modified so that
+       imenu--index-alist is updated.
+       (mh-index-create-imenu-index): New function that generates an
+       index usable by imenu. This adds which-func-mode support to index
+       folders (closes SF #855520).
+
+       * mh-e.el (which-func, which-func-modes): Tell which-func that
+       mh-folder-mode supports it.
+       (mh-folder-mode): Add support for imenu.
+
+2003-11-22  Peter S Galbraith  <psg@debian.org>
+
+       * Makefile: renamed mh-startup.el to mh-e-autoloads.el
+
+       * README: renamed mh-startup.el to mh-e-autoloads.el
+
+       * .cvsignore: Added mh-e-autoloads.el
+
 2003-11-18  Bill Wohler  <wohler@newt.com>
 
        * Released MH-E version 7.4.3.
 
        * mh-e.el (Version, mh-version): Updated for release 7.4.3.
        
+       * This patch release contains the following two patches:
+       
        * mh-identity.el (mh-identity-make-menu): Removed condition on
        mh-auto-fields-list. Use it to enable or disable menu item
        instead.
        defcustom before mh-auto-fields-list so that defvar wouldn't
        clobber user's customization settings.
 
+2003-11-17  Jeffrey C Honig  <jch@honig.net>
+
+       * mh-print.el (mh-print-msg): Do not print a message on deprecated
+       usage, the bindings have been removed.
+
+       * mh-e.el (mh-folder-mode-map): Remove "l" binding for
+       mh-print-msg.
+
+       * mh-utils.el (mh-show-mode-map): Remove "l" binding for
+       mh-print-msg.
+
+2003-11-16  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-comp.el (mh-beginning-of-word): Use the function
+       mh-mail-abbrev-make-syntax-table instead of the function
+       mail-abbrev-make-syntax-table.
+
+       * mh-gnus.el (mh-mail-abbrev-make-syntax-table): Add a wrapper
+       function that calls mail-abbrev-make-syntax-table if available.
+       This is needed so that MH-E built with CVS Emacs will work with
+       released versions of Emacs21 and vice versa.
+
+2003-11-14  Peter S Galbraith  <psg@debian.org>
+
+       * mh-customize.el (mh-invisible-header-fields-internal): Add
+       "X-NAI-Spam-" and "X-Spam-Report:".
+
+2003-11-14  Mark D. Baushke  <mdb@gnu.org>
+
+       * mh-customize.el (mh-invisible-header-fields-internal): 
+       Add X-AntiAbuse and X-MailScanner.
+       (Patch from Stephen Gildea.)
+       
+2003-11-13  Peter S Galbraith  <psg@debian.org>
+
+       * mh-identity.el (mh-identity-handler-attribution-verb): New
+       function. A new Identity handler for the attribution verb (e.g.
+       "wrote:") to allow for different identities to use different
+       languages.
+       (mh-identity-insert-attribution-verb): New function. Insert the
+       attribution verb, placing special markers so it can be deleted and
+       replaced later.
+       (mh-identity-attribution-verb-start): New variable. Holds the
+       marker for the start of the attribution verb.
+       (mh-identity-attribution-verb-end): New variable. Holds the
+       marker for the end of the attribution verb.
+
+       * mh-customize.el (mh-identity-handlers): Add new
+       ":attribution-verb" tag for the attribution-verb handler.
+       (mh-identity-list): Idem.
+
+       * mh-comp.el (mh-yank-cur-msg): Insert attribution verb using
+       mh-identity-insert-attribution-verb.
+       (mh-extract-from-attribution): Extract only the name from the From
+       line, without appending `mh-extract-from-attribution-verb' since
+       markers need to be inserted around that now.
+
+2003-11-12  Bill Wohler  <wohler@newt.com>
+
+       * mh-e.el (mh-rmail, mh-nmail): Well, actually, we run in both GNU
+       Emacs and XEmacs, so removed the "GNU" in the docstrings unless
+       one is strictly talking about GNU Emacs.
+
+       * mh-comp.el (mh-smail, mh-smail-batch, mh-smail-other-window):
+       Ditto.
+
+2003-11-11  Bill Wohler  <wohler@newt.com>
+
+       * mh-customize.el (mh-customize): Minor docstring change.
+       (mh, mh-e): The short description for MH-E is: The GNU Emacs
+       Interface to the MH Mail System. Therefore, updated docstrings
+       accordingly.
+
+       * mh-comp.el (mh-smail, mh-smail-batch, mh-smail-other-window):
+       Ditto.
+
+       * mh-e.el (mh-rmail, mh-nmail): Ditto.
+
+2003-11-10  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-mime.el (mh-mml-to-mime): In case errors happen in
+       mml-to-mime, restore contents of the draft buffer (closes SF
+       #839303).
+
+2003-11-07  Bill Wohler  <wohler@newt.com>
+
+       * mh-customize.el (mh-letter-mode-hook): Moved to mh-sending-mail
+       group (where it is now documented in the manual).
+       (mh-pick-mode-hook): Moved to mh-index group (where it is now
+       documented in the manual).
+
+       * mh-loaddefs.el: Deleted per our discussion on mh-e-devel. No
+       more conflicts! No more check-ins! Anyone pulling CVS MH-E is
+       expected to compile. This file shall be added to the tarball so
+       that users of the distribution are not.
+
+2003-11-07  Mark D. Baushke  <mdb@gnu.org>
+
+       * mh-loaddefs.el: Regenerated.
+
+       * mh-customize.el (mh-forward-hook): Define new hook.
+       * mh-comp.el (mh-forward): Use it.
+
+2003-11-07  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-loaddefs.el: Regenerated.
+
+       * mh-utils.el (mh-show-toggle-mime-buttons)
+       (mh-show-display-with-external-viewer): New interactive functions
+       callable from the show buffer.
+       (mh-show-mime-map): Add bindings for "K t" and "K e".
+       (mh-show-msg): Propagate change to
+       mh-display-buttons-for-inline-parts-flag to the show buffer.
+
+       * mh-mime.el (mh-display-with-external-viewer): New interactive
+       function to display MIME parts with external viewer (closes SF
+       #839318).
+
+       * mh-e.el (mh-folder-mode): Make the variable
+       mh-display-buttons-for-inline-parts-flag buffer-local so that
+       display of MIME buttons can be toggled.
+       (mh-toggle-mime-buttons): New interactive function to toggle
+       display of MIME buttons.
+       (mh-mime-map): Modified to add bindings for "K t" and "K e".
+
+2003-11-04  Steve Youngs  <sryoungs@bigpond.net.au>
+
+       * Makefile (XEMACS_LOADDEFS_FILE): New.  Used to generate mh-loaddefs.el
+       in XEmacs.
+       (XEMACS_LOADDEFS_COOKIE): Ditto.
+       (XEMACS_LOADDEFS_PKG_NAME): Ditto.
+       (xemacs): Add target to build mh-loaddefs.el in XEmacs
+       (clean-xemacs): Remove `mh-loaddefs.el*'
+       (loaddefs-xemacs): New rule to build mh-loaddefs.el in XEmacs.
+
+2003-11-02  Peter S Galbraith  <psg@debian.org>
+
+       * mh-init.el (mh-variant-set-variant): Reset `mh-x-mailer-string'
+       when we select an MH variant.
+
+2003-11-02  Jeffrey C Honig  <jch@honig.net>
+
+       * mh-loaddefs.el: Regenerated.  
+
+       * mh-funcs.el (mh-print-msg): Move to mh-print.el.
+
+       * mh-e.el (mh-folder-mode-map): Add mh-print-msg ("l") back, it
+       will print a message that this usage is deprecated.
+
+       * mh-print.el (require, mh-ps-print-msg, mh-ps-print-msg-file): 
+       Require mh-funcs for mh-note-printed.  PS print functions were not
+       setting the printed notation.  Move mh-print-msg here for
+       consistency.  Print message if mh-print-msg invoked via deprecated
+       key binding.
+
+2003-11-01  Peter S Galbraith  <psg@debian.org>
+
+       * Makefile: Add target to make `mh-startup.el', a file containg
+       usual entry commands into MH-E to be used for users installing
+       MH-E separately from Emacs.
+
+       * README: Document the above for users.
+
+2003-10-29  Jeffrey C Honig  <jch@honig.net>
+
+       * mh-utils.el (mh-show-ps-print-map): Add "?" and "l" to
+       mh-show-ps-print-map.
+
+       * mh-e.el (mh-ps-print-map, mh-help-messages): Add "?" and "l" to
+       mh-ps-print-map.  Add "l" to help message.
+
+2003-10-27  Bill Wohler  <wohler@newt.com>
+
+       * Makefile (MH-E-SRC): Moved mh-xemacs.el to new variable
+       MH-E-XEMACS-SRC.
+       (MH-E-XEMACS-SRC): New variable to hold XEmacs source files.
+       (MH-E-XEMACS-OBJ): New variable to hold XEmacs object files.
+       (clean): Moved XEmacs-specific code to clean-xemacs.
+       (xemacs): Added clean-xemacs prerequisite. Moved down to
+       XEmacs section of file.
+       (clean-xemacs): New target to remove XEmacs-specific files.
+       (compile-xemacs): Added $(MH-E-XEMACS-SRC) prerequisite.
+       (dist): Added $(MH-E-XEMACS-SRC) to tarball.
+
+2003-10-27  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-loaddefs.el: Regenerated.
+
+       * mh-index.el (mh-indexer-choices): Remove option for the non-free
+       glimpse indexer (closes SF #831276).
+       (mh-glimpse-binary, mh-glimpse-directory)
+       (mh-glimpse-execute-search, mh-glimpse-next-result): Functions
+       and variables to implement glimpse support are removed.
+
+       * mh-customize.el (mh-index-program): Remove option for glimpse.
+
+2003-10-24  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-customize.el: Remove top-level test for toolbar enabled
+       XEmacs since it is not needed.
+       (mh-tool-bar-define): Add test for XEmacs toolbar in the functions
+       mh-toolbar-init, mh-tool-bar-letter-buttons-set and
+       mh-tool-bar-folder-buttons-set. This enables proper compilation
+       irrespective of whether the XEmacs was built with toolbar support
+       or not.
+
+       * mh-comp.el (mh-letter-mode): Remove conditional since it is not
+       needed.
+
+       * mh-e.el (mh-folder-mode): Same as above.
+
+       * mh-utils.el (mh-show-mode): Same as above.
+
+       * mh-xemacs.el (mh-xemacs-icon-map): Remove condition on toolbar
+       presence since we want the build to work if XEmacs without
+       toolbars is used during compilation.
+
+2003-10-23  Bill Wohler  <wohler@newt.com>
+
+       * mh-customize.el: The Great Reorganization. Sorted groups
+       alphabetically. Aligned variables in customization groups with
+       manual sections. Group docstrings changed to match manual chapter
+       titles.
+
+2003-10-22  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-speed.el (timer): Avoid compiler warning in XEmacs.
+
+2003-10-22  Steve Youngs  <sryoungs@bigpond.net.au>
+
+       * Makefile (XEMACS_OPTIONS): Add '-no-autoloads' to give a cleaner
+       build environment.
+       (AUTO_PRELOADS): Removed, in favour of 'AUTOLOAD_PACKAGE_NAME' and
+       'AUTOLOAD_FILE'.
+       (AUTOLOAD_PACKAGE_NAME): New.
+       (AUTOLOAD_FILE): New.
+       (all): Don't set $EMACS_HOME if building with XEmacs.
+       (xemacs): Use 'compile-xemacs' instead of 'compile'.
+       (auto-autoloads.elc): Use new $AUTOLOAD_* vars and allow for
+       '-no-autoloads'.
+       (custom-load.elc): Allow for '-no-autoloads'.
+       (compile-xemacs): New.  It allows for the '-no-autoloads' option
+       and byte-compiles all the source files with a single instance of
+       XEmacs. 
+
+       * mh-e.el (mh-folder-mode): Only load the toolbar in XEmacs if
+       toolbar support is available.
+
+       * mh-comp.el (mh-letter-mode): Only load the toolbar in XEmacs if
+       toolbar support is available.
+
+       * mh-customize.el: Require 'mh-xemacs' at toplevel when
+       'mh-xemacs-flag' is non-nil.
+       Wrap all the toolbar code in a test that is true if using
+       GNU/Emacs or a toolbar-enabled XEmacs.
+
+       * mh-print.el (mh-ps-spool-a-msg): Comment out
+       `clean-message-header-flag' because it isn't used anywhere.
+
+       * mh-utils.el (mh-show-mode): Only load the toolbar in XEmacs if
+       toolbar support is available.
+
+       * mh-xemacs.el: Autoload `regexp-opt', `customize-group',
+       `view-mode', `with-electric-help', `pp', `sort-numeric-fields',
+       `reverse-region', and `goto-address' at compile time.
+       (mh-xemacs-has-toolbar-flag): New.  This is non-nil when XEmacs
+       has toolbar support.
+       (mh-xemacs-toolbar-*-icon): Use it.
+
+2003-10-21  Mark D. Baushke  <mdb@gnu.org>
+
+       * mh-identity.el (mh-identity-field-handler): Fields that begin
+       with ":" must have an mh-identity-handler defined or the user
+       gets an error.
+
+2003-10-17  Peter S Galbraith  <psg@debian.org>
+
+       * mh-customize.el (mh-identity-list): This change affects users!
+       The keyword "signature" becomes ":signature".  The recently added
+       keyword "pgg-default-user-id" becomes ":pgg-default-user-id".
+       (mh-auto-fields-list): The keyword "Identity" becomes ":identity".
+       (mh-identity-handlers): Idem for signature and pgg-default-user-id.
+
+       * mh-comp.el (mh-insert-auto-fields): Idem for Identity.
+
+2003-10-17  Peter S Galbraith  <psg@debian.org>
+
+       * mh-xemacs.el: Add eval-and-compile call to (load "toolbar" t t) to
+       make sure `toolbar-make-button-list' is defined.  We can't use
+       require because Emacs doesn't have this library.
+
+2003-10-16  Bill Wohler  <wohler@newt.com>
+
+       * mh-customize.el (mh-signature-file-name)
+       (mh-letter-insert-signature-hook): Merge docstring with manual.
+
+       * mh-comp.el (mh-file-is-vcard-p): Checkdoc fix.
+       (mh-insert-signature): Merge docstring with manual.
+
+       * mh-customize.el (mh-junk): Changed manual link in defgroup from
+       Customizing mh-e to Junk.
+       (mh-junk-function-alist): Moved SpamAssassin to first in list on
+       the hunch that it is the most popular and should be chosen if
+       other anti-spam programs exist.
+       (mh-junk-mail-folder): Since the variable can accept values other
+       than folder names, renamed to mh-junk-disposition to more
+       accurately reflect the content. Merge docstring with manual.
+       (mh-junk-program): Moved SpamAssassin to the top of the menu for
+       the same reason presented in mh-junk-function-alist. Also, fixed
+       case of spam programs to match official usage. Merge docstring
+       with manual.
+
+       * mh-junk.el (mh-junk-blacklist):
+       s/mh-junk-mail-folder/mh-junk-disposition/. Merge docstring with
+       manual.
+       (mh-junk-whitelist): Merge docstring with manual.
+       (mh-bogofilter-blacklist): No longer suggest using automatic
+       classification so use -s instead of -Ns.
+       (mh-bogofilter-whitelist): No longer suggest using automatic
+       classification so use -n instead of -Sn.
+       (mh-spamassassin-blacklist, mh-spamassassin-whitelist): Merge
+       docstring with manual. Moved spamassassin functions to top of file
+       so functions appear in same order that they are presented in menu.
+
+2003-10-09  Peter S Galbraith  <psg@debian.org>
+
+       * mh-customize.el (mail-citation-hook): Moved from mh-comp.el and
+       made into a defcustom. 
+
+2003-10-09  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-loaddefs.el: Regenerated.
+
+       * mh-comp.el (mh-get-header-field): Add autoload cookie.
+
+       * mh-utils.el (mh-show-ps-print-toggle-mime)
+       (mh-show-ps-print-toggle-color, mh-show-ps-print-toggle-faces)
+       (mh-show-ps-print-msg-file, mh-show-ps-print-msg)
+       (mh-show-ps-print-msg-show): New interactive functions callable
+       from the show buffer.
+       (mh-show-ps-print-map): New key map for printing.
+
+       * mh-e.el (mh-folder-mode-map): Remove key binding for
+       mh-print-msg.
+       (mh-ps-print-map): Add new key map for printing.
+
+       * Makefile (MH-E-SRC): Add mh-print.el.
+
+2003-10-07  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-utils.el (mh-x-image-url-fetch-image): In XEmacs,
+       make-temp-file is not present. So to avoid security problems, use
+       a temporary file in the user's home directory. This avoids issues
+       in creating files in a world-writable directory.
+
+       * mh-mime.el (mh-signature-highlight): In Emacs, arrange for the
+       overlay to be freed when it is no longer needed. Also, implement
+       signature highlighting in XEmacs.
+
+2003-10-05  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-mime.el (mh-mime-display, mh-mm-inline-message): Respect the
+       value of `mm-verify-option' and `mm-decrypt-option'.
+       (mh-mime-display-security): Rearrange code a bit to avoid too many
+       new lines being inserted when message verification/decryption is
+       carried out while the message is being read. Also use the
+       point-m{in|ax}-marker functions to make the function easier to read.
+       (mh-mime-security-press-button): Extend the function so that the
+       user can verify/decrypt messages while reading them.
+
+       * mh-gnus.el (mm-possibly-verify-or-decrypt): Added to avoid
+       compiler warning with old Gnus.
+
+       * mh-utils.el (mh-x-image-url-sane-p): New function which checks
+       if the URL in X-Image-URL is something we can handle.
+       (mh-x-image-url-display): Don't display image if the URL looks
+       malformed.
+
+2003-10-04  Mark D Baushke  <mdb@gnu.org>
+
+       * mh-comp.el (mh-letter-menu): Simplify menu heading.
+
+2003-10-03  Mark D Baushke  <mdb@gnu.org>
+
+       * mh-mime.el (mh-mml-query-cryptographic-method): Avoid
+       revisionist history and still provide a good default.
+
+       * mh-comp.el (mh-letter-menu): Remove the Disable Security
+       parenthetical comment.
+
+       * mh-loaddefs.el: Regenerated.
+       
+       * mh-customize.el (mh-mml-method-default): What method should be
+       used in secure directives.
+       
+       * mh-mime.el (mh-secure-message): New function used to generate
+       the mml security tags.
+       (mh-mml-unsecure-message): New wrapper function around
+       mml-unsecure-messages.
+       (mh-mml-secure-message-sign-pgpmime): Remove function.
+       (mh-mml-secure-message-encrypt-pgpmime): Ditto.
+       (mh-mml-cryptographic-method-history): New variable.
+       (mh-mml-query-cryptographic-method): New function.
+       (mh-mml-secure-message-encrypt): Ditto.
+       (mh-mml-secure-message-signencrypt): Ditto.
+       (mh-mml-secure-message-sign): Ditto.
+
+       * mh-comp.el (mh-letter-menu, mh-letter-mode-help-messages,
+       (mh-letter-mode-map): Update to use new functions.
+
+2003-09-26  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-seq.el (mh-interactive-range): The function has been
+       extended so that it now takes a default result to return if no
+       interactive prefix arg is given and no region is active.
+
+       * mh-e.el (mh-add-sequence-notation): If transient-mark-mode is
+       on, then the active region is deactivated based on whether a user
+       sequence or a internal sequence is being notated. The change
+       removes this inconsistency.
+       (mh-catchup, mh-folder-map): A new interactive function to mark
+       messages as read has been added and bound to "F c" in the folder
+       mode.
+
+       * mh-utils.el (mh-show-catchup, mh-show-folder-map): New
+       interactive function callable from show mode buffers has been
+       bound to "F c".
+
+2003-09-24  Bill Wohler  <wohler@newt.com>
+
+       * mh-customize.el (mh-clean-message-header-flag)
+       (mh-invisible-header-fields-default, mh-invisible-header-fields):
+       Merge docstring with manual.
+
+2003-09-24  Mark D. Baushke  <mdb@gnu.org>
+
+       * mh-junk.el (mh-junk-blacklist): Junked messages should be put
+       into the mh-seen-list to avoid propagating the unseen sequence
+       into the spam folder.
+
+       * mh-loaddefs.el: Regenerated.
+
+       * mh-mime.el (mh-mml-secure-message-sign-pgpmime): Add an optional
+       dontsign argument to remove an existing secure message directive.
+       Update the docstring -- this fuction does not allow for
+       encrypt/sign, just sign directives.
+
+       * mh-mime.el (mh-mml-secure-message-sign-pgpmime): Use
+       mml-insert-tag directly to provide a sender if
+       mh-identity-pgg-default-user-id is set.
+       (mh-mml-secure-message-encrypt-pgpmime): Use mml-insert-tag
+       directly to provide a sender if this message is to be both signed
+       and encrypted and mh-identity-pgg-default-user-id is set.
+
+2003-09-23  Bill Wohler  <wohler@newt.com>
+
+       * mh-alias.el (Commentary): Removed as it is now in the manual.
+       (mh-alias-system-aliases): Moved here from mh-customize.el. By
+       definition, "system" definitions are not user-visible, and user
+       filenames are in the the Aliasfile: profile component, so this
+       variable really shouldn't be a defcustom
+       (mh-alias-tstamp, mh-alias-filenames, mh-alias-reload)
+       (mh-alias-add-alias, mh-alias-grab-from-field)
+       (mh-alias-add-address-under-point, mh-alias-apropos): Merge
+       docstring with manual.
+       (mh-alias-reload-maybe): Minor comment update.
+       (mh-alias-insert-file): Merge docstring with manual. Removed
+       "[press TAB]" from prompt since users should know about completion
+       and space can be used as well.
+       (mh-alias-for-from-p): No longer returns a surprising result (t if
+       there was **not** an alias for the From field) if the From header
+       field is missing. This function now returns what you would expect
+       a function of this name to return. Renamed from
+       mh-alias-from-has-no-alias-p since negatives in the function name
+       make logic harder to follow.
+       (mh-alias-add-alias-to-file): Merge docstring with manual.
+       Improved verbiage of prompt. Aliases are now inserted "[b]efore"
+       or "[a]fter" the existing alias instead of "[i]nsert" or
+       "[a]ppend." Note how the new usage flows better.
+
+       * mh-customize.el (mh-alias): Changed manual link in defgroup from
+       Customizing mh-e to Aliases.
+       (mh-alias-grab-from-field button): mh-alias-from-has-no-alias-p
+       renamed to mh-alias-for-from-p and no longer returns surprising
+       value if there isn't a From field. Therefore, enable button if
+       there is a From header field and mh-alias-for-from-p returns nil.
+       (mh-letter-complete-function)
+       (mh-alias-completion-ignore-case-flag, mh-alias-flash-on-comma)
+       (mh-alias-insert-file, mh-alias-insertion-location)
+       (mh-alias-local-users, mh-alias-local-users-prefix)
+       (mh-alias-passwd-gecos-comma-separator-flag): Merge docstring with
+       manual.
+       (mh-alias-system-aliases): Moved to mh-alias.el.
+
+       * mh-comp.el (mh-letter-complete-function-alist): Removed comment
+       about making this customizable since I didn't think it seemed
+       appropriate in the manual.
+       (mh-letter-complete): Merge docstring with manual.
+
+2003-09-23  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-speed.el (mh-speed-flists): When exiting emacs, don't ask if
+       the flists process should be killed.
+
+       * mh-e.el (mh-folder-message-menu): Enable undo menu entry only
+       if something can be undone.
+
+       * mh-customize.el (undo): Enable undo button only if something
+       can be undone.
+
+2003-09-22  Peter S Galbraith  <psg@debian.org>
+
+       * mh-customize.el (mh-identity-handlers): New defcustom.  Alist of
+       Handler functions for mh-identity (downcased) fields.
+       (mh-identity-list): Add support for pgg-default-user-id.        
+
+       * mh-identity.el (mh-insert-identity): Modified to use
+       `mh-identity-handlers', adding hacking flexibility for those who
+       might need it.
+       (mh-identity-field-handler): New function. Return the handler for
+       a FIELD or nil if none set. The field name is downcased.
+       (mh-identity-handler-gpg-identity): New function; handler for pgg
+       pgp identities.  It sets a buffer-local value for
+       `mh-pgg-default-user-id' which must be handled by mh-send-letter.
+       (mh-identity-pgg-default-user-id): New buffer-local variable to
+       hold the requested key ID.
+       (mh-identity-handler-signature): New function; handler t insert
+       and remove signature files.
+       (mh-identity-handler-default): New function; the default handler
+       to insert or remove generic field.
+       (mh-identity-handler-top): Insert a field at the top of the
+       header.
+       (mh-identity-handler-bottom): Insert a field at the bottom of the
+       header.
+       (mh-header-field-delete): Make more robust wrt the field having a
+       trailing colon or not.
+       (mh-identity-make-menu): Add a "Customize Identities" menu entry.
+       
+       * mh-loaddefs.el: Regenerated.
+
+2003-09-21  Peter S Galbraith  <psg@debian.org>
+
+       * mh-init.el (mh-variant-set): Bug fix for mh-variant long names
+       with version numbers.
+
+       * mh-e.el (mh-scan-format): patch from Sergey Poznyakoff.
+       GNU mailutils now supports the %(decode) format 
+
+2003-09-20  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-gnus.el (mh-mm-text-html-renderer): New function to query
+       which HTML renderer is being used by Gnus.
+
+       * mh-mime.el (mh-signature-highlight): Renderers used to display
+       HTML parts garble the signature separator in various ways. The
+       function has been modified to take that into account.
+       (mh-mime-display-single, mh-mm-display-part): Pass the new
+       optional argument to `mh-signature-highlight'.
+
+2003-09-19  Mark D. Baushke  <mdb@gnu.org>
+
+       * mh-mime.el (mh-have-file-command, mh-file-mime-type): Made an
+       mh-autoload as they are used in mh-comp.el.
+
+       * mh-loaddefs.el: Regenerated.
+
+2003-09-18  Peter S Galbraith  <psg@debian.org>
+
+       * mh-comp.el (mh-insert-fields): Make sure field has a colon.
+
+2003-09-18  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-seq.el (mh-toggle-tick): Don't hardcode the name of the tick
+       sequencence in the function. This would have caused improper
+       highlighting of the tick sequence if the user had changed its
+       name.
+
+2003-09-15  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-e.el (mh-folder-message-menu): Fix a little bug which shows
+       up as a problem during compilation (closes SF #806577).
+
+2003-09-15  Mark D. Baushke  <mdb@gnu.org>
+
+       * mh-customize.el (mh-invisible-header-fields-internal): Added
+       a new field for GNU mailutils per Sergey Poznyakoff.
+
+2003-09-09  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-utils.el (vcard): Unconditionally load vcard.el, if
+       available, so that vcards are always inlined.
+
+2003-09-09  Peter S Galbraith  <psg@debian.org>
+
+       * mh-mime.el (mh-file-mime-type-substitutions): Add entry to
+       convert text/plain .vcf files to text/x-vcard.
+       (mh-mime-content-types): Add text/x-vcard.
+
+2003-09-09  Bill Wohler  <wohler@newt.com>
+
+       * mh-comp.el (mh-rejected-letter-start): Added strings for qmail
+       and exim (addresses SF #404965).
+
+2003-09-09  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-gnus.el (mm-inline-text-vcard): Make vcard display work with
+       Gnus-5.9. The extra file vcard.el is still needed.
+
+       * mh-mime.el (mh-signature-highlight): New function that
+       highlights message signatures.
+       (mh-mm-display-part, mh-mime-display-single): Highlight signatures
+       using `mh-signature-highlight' (closes SF #802722). More work is
+       needed for XEmacs.
+       (mh-mime-display): Highlight signature in non-MIME email too.
+
+       * mh-customize.el (mh-show-signature-face): New face used to
+       display message signature.
+
+2003-09-08  Peter S Galbraith  <psg@debian.org>
+
+       * mh-e.el (mh-version): Do something sensible when
+       mh-variant-in-use is undefined.
+       * mh-junk.el (mh-spamassassin-blacklist)
+       (mh-spamassassin-whitelist): Change options to be compatoble with
+       old version of spamassassin (V2.20).
+
+2003-09-07  Mark D. Baushke  <mdb@gnu.org>
+
+       * mh-mime.el (mh-access-types): Per RFC 2049, the "afs"
+       access-type for message/external-body has been removed.
+       Update the comments to reference the current MIME RFCs
+       2045, 2046 and 2049 rather than the obsolete RFC 1521.
+
+2003-09-05  Peter S Galbraith  <psg@debian.org>
+
+       * mh-e.el (mh-version): Bumped version number to 7.4.2+cvs.
+
+2003-09-04  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-utils.el (mh-picon-directory-list, mh-picon-directory): The
+       mh-picon-directory-list variable supersedes mh-picon-directory.
+       (mh-picon-existing-directory-list): New variable that contains
+       the list of picon directories that actually exist.
+       (mh-picon-set-directory-list): New function to update
+       mh-picon-existing-directory-list from mh-picon-directory-list.
+       (mh-picon-get-image): The function has been modified to search a
+       list of possible picon source directories. The regexp to extract
+       the username from the email address has been made smarter so that
+       it can recognize email addresses of the form user+random@foo.net
+       and extract "user" from there.
+       (mh-picon-file-contents): The file type recognition code has been
+       moved from mh-picon-get-image into this function.
+       (mh-picon-generate-path): The function has been generalized so
+       that searching multiple paths is now feasible.
+
+       * mh-pick.el, mh-e.el: Checkdoc fixes.
+
+2003-09-02  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-identity.el (eval-when): It seems that the mh-comp-loaded
+       code isn't required any more.
+
+2003-08-30  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-init.el (mh-variant-set): Replace `error' with `message' so
+       that Emacs CVS will compile without errors if no MH variant is
+       present.
+
+2003-08-29  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-init.el (mh-variant-set): Add interactive spec to the
+       function.
+
+       * mh-mime.el (mh-mhn-compose-external-type): Optional arguments
+       are prompted for only if prefix arg is given.
+
+2003-08-29  Mark D. Baushke  <mdb@gnu.org>
+
+       * mh-mime.el (mh-mhn-compose-external-type): Modified to be
+       interactive and prompts for many of the fields. Made an
+       mh-autoload.
+       (mh-access-types): New table derived from RFC2017, RFC1521 and
+       RFC1738, used in a completing-read in
+       mh-mhn-compose-external-type.
+
+       * mh-loaddefs.el: Regenerated.
+
+2003-08-26  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-utils.el (mh-picon-image-types, mh-picon-get-image): Avoid
+       compiler warnings.
+       (mh-sub-folders-actual): Parsing of the output from folders has
+       been modified, so that it also works for MH (closes SF #792300).
+
+       * mh-junk.el (mh-spamassassin-whitelist): Avoid calling
+       ietf-drums-parse-address if it isn't present.
+       (mh-spamassassin-identify-spammers): Avoid use of puthash so that
+       Emacs20 doesn't complain.
+
+       * mh-e.el (mh-colors-available-p): Wrap call to
+       display-color-cells in a mh-funcall-if-exists to avoid compiler
+       warning in Emacs20.
+
+2003-08-25  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-e.el (mh-colors-available-flag, mh-folder-mode): New
+       variable to track if colors are available and it is set
+       appropriately in mh-folder-mode.
+       (mh-colors-available-p, mh-colors-in-use-p): Two functions to
+       check whether colors are available and if they are actually being
+       used.
+       (mh-add-sequence-notation): Just changing a scan line doesn't
+       make font-lock refontify the line in Emacs20. So explicitly
+       refontify the scan line in such a situation.
+       (mh-internal-seq): If colors aren't being used then treat the
+       tick sequence like a normal user sequence.
+
+       * mh-seq.el (mh-put-msg-in-seq): Do font-lock highlighting after
+       the messages have been added to the sequence.
+       (mh-toggle-tick): Modified so that highlighting of the ticked
+       messages will be properly done. If font-lock isn't being used or
+       if colors aren't supported by the Emacs where MH-E is running,
+       then the `%' character is used to annotate ticked messages.
+
+       * mh-utils.el (mh-picon-image-types): Since Emacs20 doesn't have
+       image-type-available-p, wrap calls to that function in
+       ignore-errors.
+       (mh-add-msgs-to-seq): Do the font-lock highlighting after the
+       messages have been added.
+
+2003-08-24  Bill Wohler  <wohler@newt.com>
+
+       * Makefile (MH-E-SRC): Replaced mh-xemacs-compat.el and
+       mh-xemacs-icons.el with mh-xemacs.el.
+
+       * mh-e.el: Don't require mh-xemacs-compat which no longer exists.
+       The XEmacs stuff gets required by mh-customize.el which is
+       required by mh-utils.el which is required by mh-e.el. This all
+       happens before mh-xemacs-compat was required, so all should be
+       well.
+
+       * mh-unit.el (mh-unit-files): Replaced mh-xemacs-compat.el and
+       mh-xemacs-icons.el with mh-xemacs.el.
+
+       * mh-xemacs.el: New file from concatenation of mh-xemacs-compat.el
+       and mh-xemacs-icons.el which were removed since their names
+       exceeded DOS 8+3 limits.
+
+       * mh-customize.el (mh-compose-skipped-header-fields): Use
+       uppercase for field names.
+
+2003-08-21  Bill Wohler  <wohler@newt.com>
+
+       * mh-customize.el (mh-sequences): Introduced new customization
+       group for sequences.
+       (mh-refile-preserves-sequences-flag, mh-tick-seq)
+       (mh-update-sequences-after-mh-show-flag): Moved option from
+       mh-folder to mh-sequences group. Synced docstring with manual.
+       (mh-index-ticked-messages-folders): Since mh-tick-seq is
+       customizable, use it instead of tick in the docstring.
+
+       * mh-index.el (mh-index-ticked-messages): Since mh-tick-seq is
+       customizable, use it instead of tick in the docstring.
+
+       * mh-seq.el (mh-msg-is-in-seq): Can now specify an alternate
+       message number with a prefix argument.
+       (mh-narrow-to-tick): Since mh-tick-seq is customizable, use it
+       instead of tick in the docstring. Also, use mh-tick-seq instead of
+       tick in warning message.
+
+2003-08-20  Peter S Galbraith  <psg@debian.org>
+
+       * mh-customize.el: setq mh-variant to 'none when byte-compiling,
+       since we don't care what MH variant (if any) is on the system at
+       that point.
+
+       * mh-init.el (mh-variant-set): Don't probe for MH variant when
+       mh-variant is set to'none (during byte-compilation).
+
+2003-08-19  Peter S Galbraith  <psg@debian.org>
+
+       * mh-pick.el (mh-pick-single-dash): New defconst.  Search
+       components that are supported by single-dash option in
+       pick.
+       (mh-pick-regexp-builder): Use `mh-pick-single-dash' and adapt
+       patch from Sergey Poznyakoff.
+
+       * mh-comp.el (mh-reply): mu-mh supports `repl -group', thanks to
+       Sergey Poznyakof.
+
+       * mh-init.el: checkdoc fixes.
+
+2003-08-19  Bill Wohler  <wohler@newt.com>
+
+       * mh-seq.el: (mh-edit-pick-expr): Renamed from mh-read-pick-regexp
+       since the new name is more indicative of what the function does.
+       Prompt now says "Pick expression" instead of "Pick regexp".
+       (mh-narrow-to-subject): Rewrote function to behave like other
+       similar functions.
+       (mh-narrow-to-header-field, mh-narrow-to-range)
+       (mh-narrow-to-tick): s/regexp/pick-expr/.
+       (mh-widen, mh-narrow-to-from, mh-narrow-to-cc, mh-narrow-to-to):
+       Synced docstrings with manual
+
 2003-08-19  Bill Wohler  <wohler@newt.com>
 
        * Released MH-E version 7.4.2.
        (patches from 1.307 and 1.309 and branched for 7.4.2, closes SF
        #791021).
 
+2003-08-18  Bill Wohler  <wohler@newt.com>
+
+       * mh-index.el (mh-index-sequenced-messages)
+       (mh-index-new-messages, mh-index-ticked-messages): Updated
+       docstrings from manual (closes SF #718833).
+
+       * mh-customize.el (mh-variant): Checkdoc fix.
+       (mh-index-new-messages-folders): Don't mention defvar in
+       docstring, use `+inbox' instead.
+       (mh-index-ticked-messages-folders): Don't mention defvar in
+       docstring, use `tick' instead.
+
+       * mh-comp.el (mh-repl-group-formfile): Checkdoc fix.
+
+2003-08-18  Peter S Galbraith  <psg@debian.org>
+
+       * mh-init.el (mh-variant-set, mh-sys-path, mh-variant-info): Add
+       support for GNU mailutils.
+       (mh-variant-mu-mh-info): New function to detect mu-mh and return
+       info about it for `mh-variants'.
+
+       * mh-e.el (mh-regenerate-headers): mu-mh has different error
+       message for a invalid mesage list.
+
+2003-08-18  Peter S Galbraith  <psg@debian.org>
+
+       * mh-customize.el (mh-e): New defgroup.  Sort of an alias for the
+       'mh group that a user might be more likely to find.
+
+2003-08-18  Bill Wohler  <wohler@newt.com>
+
+       * mh-comp.el (mh-insert-auto-fields-done-local): Docstring tweak.
+       (mh-compose-and-send-mail): Do not call mh-insert-auto-fields.
+       This should be done only once in mh-send-letter.
+
+2003-08-18  Peter S Galbraith  <psg@debian.org>
+
+       * mh-comp.el (mh-letter-mode): Call `mh-find-path unconditionally,
+       like elsewehere in MH-E.
+
+       * mh-utils.el (mh-find-path): Run setup code only if
+       `mh-find-path-run' is nil such that this is only done once.
+       Also remove the `setq' for `read-mail-command' and `mail-user-agent'.
+       
+2003-08-18  Peter S Galbraith  <psg@debian.org>
+
+       * mh-e.el: require 'mh-utils first
+
+       * mh-customize.el (mh-variant): defcustom moved here.
+
+       * mh-init.el (mh-variants): Made an mh-autoload.
+
+2003-08-18  Peter S Galbraith  <psg@debian.org>
+
+       * Makefile (MH-E-SRC): Added mh-init.el to MH-E-SRC.
+
+       * mh-utils.el (mh-find-progs): Deleted.  Make obsolete by mh-init.el.
+       (mh-find-path): Call `mh-variants' instead of now obsolete
+       `mh-find-progs'.
+       (mh-path-search): Deleted.  Was only used by `mh-find-progs'.
+
+       * mh-e.el: require mh-init.el.
+       (mh-version): Use simpler `mh-variant-in-use'.  
+       (mh-scan-format): Use (mh-variant-p 'nmh) instead of mh-nmh-flag.
+
+       * mh-comp.el (mh-insert-x-mailer): Use simpler `mh-variant-in-use'.
+
+       * mh-utils.el (mh-progs, mh-lib, mh-lib-progs) 
+       (mh-flists-present-flag): Moved to mh-init.el.
+       (mh-nmh-flag): Deleted.  Use (mh-variant-p 'nmh) instead.
+
+       * mh-comp.el (mh-repl-group-formfile, mh-forward, mh-reply) 
+       (mh-send-letter): Use (mh-variant-p 'nmh) instead of mh-nmh-flag.
+
+       * mh-mime.el (mh-edit-mhn, mh-mime-save-parts): Use (mh-variant-p
+       'nmh) instead of mh-nmh-flag.
+
+2003-08-16  Bill Wohler  <wohler@newt.com>
+
+       * mh-customize.el (mh-folder-selection): New group to hold
+       variables described in Folder Selection section in manual.
+       (mh-default-folder-list, mh-default-folder-must-exist-flag,
+       mh-default-folder-prefix): Moved to mh-folder-selection group.
+       Updated docstrings per manual update.
+       (mh-default-folder-for-message-function): New defcustom. Was a
+       defvar in mh-utils.el. Updated docstring per manual update.
+
+       * mh-utils.el (mh-default-folder-for-message-function): Moved to
+       mh-customize.el.
+
+       * mh-e.el (mh-folder-from-address, mh-prompt-for-refile-folder):
+       Updated docstrings per manual update.
+
+       * mh-unit.el (mh-unit-files): Added mh-init.el.
+
+2003-08-16  Peter S Galbraith  <psg@debian.org>
+
+       * mh-init.el: New file.  Code to initialize the MH-E back-end.
+       Highlights:
+       (mh-variant): New defcustom. Users may customize `mh-variant' to
+       switch between available variants.
+       (mh-variants): Available MH variants are described in this variable.
+       (mh-variant-in-use, mh-variant-p): Developers may check which
+        variant is currently in use with the variable `mh-variant-in-use'
+        or the function `mh-variant-p'.
+       
+2003-08-15  Bill Wohler  <wohler@newt.com>
+
+       * mh-customize.el (mh-auto-fields-list): The manual uses Fcc
+       instead of fcc, so I've changed the user-visible text
+       accordingly. I've left the const alone for backwards
+       compatibility.
+
+2003-08-14  Bill Wohler  <wohler@newt.com>
+
+       * mh-identity.el (mh-insert-identity): Changed signature deletion
+       test to test for both markers, rather than testing to see if the
+       start marker is bound. Since the start marker is defined in this
+       file, it should always be bound. Suggestion by Satyaki.
+
+       * mh-comp.el (mh-send-letter): Go to the top of the draft so that
+       the user can see which header fields have been inserted. I think
+       this is more important than leaving point alone or going to the
+       end to see the signature since Mail-Followup-To or Bcc or cc could
+       have some deleterious effects.
+
+       * mh-customize.el (mh-auto-fields-prompt-flag): New variable.
+       Non-nil means to prompt before sending if fields inserted.
+
+       * mh-comp.el (mh-insert-auto-fields): Now return t if fields
+       inserted; otherwise nil.
+       (mh-send-letter): Deleted obsolete documentation about adding
+       X-Mailer and X-Face. Prompt before sending if auto fields added
+       and mh-auto-fields-prompt-flag is t.
+
+       * mh-customize.el (mh-identity-list): Allow signature to come from
+       mh-signature-file-name. In this case, the "signature" value is set
+       to nil. This might not be the best implementation. Suggestions
+       welcome.
+
+       * mh-identity.el (mh-insert-identity): Now that the signature can
+       be a nil value, moved test higher up in cond so that the test for
+       a nil value would not be executed first prevening signature
+       handling. Handle nil signature value by calling
+       mh-insert-signature with no arguments which means to use
+       mh-signature-file-name.
+
+       * mh-comp.el (mh-insert-signature): Changed text of message if no
+       signature inserted.
+
+       * mh-customize.el (mh-identity-list): Changed "Signature" constant
+       back to "signature" so it *won't* be backwards-incompatible any
+       more. I discovered one could use the :tag keyword to get headline
+       captalization in the menu.
+
+       * mh-identity.el (mh-insert-identity): Ditto.
+
+       * mh-identity.el (mh-identity-make-menu): Always build menu.
+       Always create Insert Auto Fields menu item. Just don't enable it
+       if mh-auto-fields-list is nil. Enable radio buttons always. Make
+       None a radio button choice with the other identities.
+
+       * mh-comp.el (mh-letter-menu): Removed cond on fboundp
+       'easy-menu-define. We don't do this elsewhere.
+
+2003-08-13  Bill Wohler  <wohler@newt.com>
+
+       * mh-identity.el (mh-identity-make-menu, mh-insert-identity): Use
+       headline capitalization in menu items. Even the internal names are
+       exposed in the customize interface, so they need to be uppercase
+       too.
+       (mh-insert-identity): Rather than goto-char to
+       mh-identity-signature-start before deleting, simply pass it to
+       delete-region. When setting markers, use point-min-marker and
+       point-max-marker instead of moving point. Set marker type of
+       mh-identity-signature-start to t to fix a bug where changing
+       identity deleted user's text.
+
+       * mh-customize.el (mh-identity-list, mh-auto-fields-list):
+       Reworked docstring. Use headline capitalization. Commented out
+       implementation details for later deletion or resurrection upon
+       popular demand. N.B. If your mh-identity-list contains "signature"
+       then you will need to either edit your .emacs file manually, or
+       delete your existing "signature" which will become a regular field
+       with this change and create a new signature. I figured I could get
+       away with this since 8.0 is a major release, and coinciding with
+       the manual update will be a MAJOR release. I apologize profusely
+       that I didn't catch this before it was released.
+       (mh-identity-default): Use headline capitalization in example.
+
+2003-08-12  Jeffrey C Honig  <jch@honig.net>
+
+       * mh-customize.el (mh-alias-reloaded-hook): Define
+       `mh-alias-reloaded-hook'.
+
+       * mh-alias.el (mh-alias-reload): Run `mh-alias-reloaded-hook'
+       after reloading the aliases.
+
+2003-08-12  Mark D. Baushke  <mdb@gnu.org>
+
+       * mh-comp.el (mh-insert-signature): Use functionp to avoid
+       the possibility of doing a funcall on a void function.
+
+2003-08-12  Bill Wohler  <wohler@newt.com>
+
+       * mh-customize.el (mh-identity): Point group manual link to new
+       Identities section.
+       (mh-signature-separator-flag): New variable which can be used to
+       suppress the output of the signature separator.
+
+       * mh-comp.el (mh-insert-signature): Use
+       mh-signature-separator-flag.
+
+       * mh-identity.el (mh-insert-identity): If the identity's signature
+       file didn't exist, an fboundp error was thrown. This was fixed by
+       removing signature tests that were redundant and out of date with
+       the tests in mh-insert-signature. Removed second signature
+       condition as it is now handled in the first signature condition.
+
+2003-08-12  Peter S Galbraith  <psg@debian.org>
+
+       * mh-identity.el (mh-insert-identity): Don't insert new lines on
+       signatures anymore.
+
+       * mh-comp.el (mh-insert-signature): Make sure signature file is
+       readable before trying to insert it.
+
+2003-08-11  Bill Wohler  <wohler@newt.com>
+
+       * mh-comp.el (mh-insert-signature): Unconditionally insert a
+       newline so that signatures are inserted consistently, and so that
+       there isn't any text after the cursor so that the user can start
+       typing his message immediately. Use new variable and function
+       mh-signature-separator and mh-signature-separator-p.
+
+       * mh-customize.el (mh-delete-yanked-msg-window-flag): Checkdoc
+       fix.
+       (mh-signature-file-name): Updated docstring now that this variable
+       can be a function. Added cross-references to
+       mh-signature-separator, mh-signature-separator-regexp, and
+       mh-signature-separator-p which might be used in such functions.
+
+       * mh-identity.el (mh-insert-identity): Don't include signature if
+       signature separator already present. Useful when running
+       mh-edit-again.
+
+       * mh-mime.el (mh-inline-vcard-p): Use mh-signature-separator-p.
+
+       * mh-utils.el (mh-signature-separator-regexp): New variable
+       containing "^-- $" which should be used when looking for the
+       signature separator.
+       (mh-signature-separator): New variable containing "-- \n" which
+       should be used when inserting the signature separator.
+       (mh-signature-separator-p): New function that returns non-nil if
+       mh-signature-separator-regexp is found in the buffer.
+
+2003-08-09  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-utils.el (mh-x-image-scaling-function): Variable that
+       contains function used to scale images. Possible choices are
+       mh-x-image-scale-with-convert and mh-x-image-scale-with-pnm.
+       (mh-convert-executable): Removed.
+       (mh-x-image-scale-with-pnm, mh-x-image-scale-with-convert): New
+       functions that scale images using pnm tools or ImageMagick.
+       (mh-x-image-scale-and-display, mh-x-image-url-display): Use
+       mh-x-image-scaling-function instead of mh-convert-executable.
+
+2003-08-08  Peter S Galbraith  <psg@debian.org>
+
+       * mh-comp.el (mh-insert-signature): Bug fix.  Handle case of nil
+       `mh-signature-file-name' and hooks correctly.
+
+       * mh-identity.el (mh-insert-identity): Refactor to use
+       mh-insert-signature
+       
+       * mh-comp.el (mh-signature-separator-p): Removed.
+
+       * mh-comp.el (mh-insert-signature): Merge MIME awareness from
+       mh-insert-identity into this command. Allow
+       `mh-signature-file-name' to be a function to call.  See if "-- "
+       needs to be inserted only after hooks have run.
+
+2003-08-07  Bill Wohler  <wohler@newt.com>
+
+       * mh-customize.el (mh-compose-skipped-header-fields): Added
+       X-Image-URL.
+       (mh-autoload): Removed cookies. They aren't necessary in
+       mh-e.el, mh-utils.el, or mh-customize.el.
+
+       * mh-e.el (mh-autoload): Removed cookies. They aren't necessary in
+       mh-e.el, mh-utils.el, or mh-customize.el.
+
+       * mh-identity.el (mh-insert-identity): Made regexp for signature
+       separator more explicit. Hmmm, maybe we should create
+       mh-signature-separator-regexp...
+
+       * mh-index.el (mh-replace-string): Moved to mh-utils.el.
+
+       * mh-utils.el (mh-replace-string): Moved here from mh-index.el.
+       (mh-autoload): Removed cookies. They aren't necessary in mh-e.el,
+       mh-utils.el, or mh-customize.el.
+
+       * mh-comp.el (mh-insert-signature): Added file argument to insert
+       a file other than mh-signature-file-name. Insert signature
+       separator, unless file already contains one.
+
+2003-08-06  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-e.el (mh-folder-size, mh-folder-size-folder)
+       (mh-folder-size-flist): If flist is not present use folder to
+       find the number of messages in the folder. Also the .mh_sequences
+       file is read to find the number of unseen messages.
+
+       * mh-utils.el (mh-flists-present-flag, mh-find-progs): Introduce
+       a new variable to test for the presence of the flists program and
+       set it in mh-find-progs.
+
+2003-08-06  Peter S Galbraith  <psg@debian.org>
+
+       * mh-customize.el: Change the order of `mh-identity-list' and
+       `mh-auto-fields-list' and remove byte-compilation defvar for
+       `mh-identity-list'.  This fixes a customization bug for
+       `mh-identity-list', where it wasn't set correctly.
+
+       * mh-identity.el (mh-identity-make-menu): mh-auto-fields-list may
+       not be bound yet when initially loaded.
+
+2003-08-06  Bill Wohler  <wohler@newt.com>
+
+       * mh-alias.el (mh-alias-add-address-under-point): Removed trailing
+       period from messages. The conventions say that errors should not
+       end with a period and that "Foo...done" messages should not end in
+       a period, but they aren't explicit about messages in general.
+       Given what the conventions *do* say, and because most of our
+       messages don't end with a period, let's just say that messages in
+       general don't end in a period, just like error messages.
+
+       * mh-comp.el (mh-extract-rejected-mail, mh-letter-mode-message):
+       Ditto.
+
+       * mh-e.el (mh-refile-a-msg):  Ditto.
+
+       * mh-funcs.el (mh-undo-folder): Ditto.
+
+       * mh-mime.el (mh-mime-save-parts): Ditto.
+       
+       * mh-seq.el (mh-subject-to-sequence-unthreaded) 
+       (mh-narrow-to-subject, mh-delete-subject): Ditto.
+
+       * mh-index.el (mh-index-sequenced-messages)
+       (mh-index-new-messages, mh-index-ticked-messages): Discovered that
+       in general we should only use question marks in yes-or-no-p or
+       y-or-n-p prompts, but not in other prompts that use
+       completing-read and offer defaults. In these cases, use colons
+       instead (closes SF #730470).
+
+       * mh-mime.el (mh-mime-save-parts): Ditto.
+
+       * mh-utils.el (mh-prompt-for-folder): Ditto.
+
+       * mh-alias.el (mh-alias-apropos): Multiple messages are usually
+       shown one at a time rather than appended. Send output to
+       mh-aliases-buffer instead of *Help*.
+       (mh-alias-local-users): Checkdoc fix.
+
+       * mh-funcs.el (mh-undo-folder): Removed commented-out code since
+       its deadline had expired.
+
+       * mh-utils.el (mh-aliases-buffer): New buffer name, used in
+       mh-aliases.el.
+
+2003-08-06  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-utils.el (mh-x-image-url-cache-canonicalize): Make this
+       function work for XEmacs too.
+       (mh-collect-folder-names): Use folders instead of flists. One
+       advantage is that folders is available on MH while flists is not.
+       Another is that if an explicit -sequence argument isn't given and
+       Unseen-Sequence profile is not present then flists croaks while
+       folders doesn't.
+       (mh-collect-folder-names-filter): Don't consider folder names that
+       start with a `.' character. This is needed since the folders
+       command doesn't filter them out like flists does.
+
+       * mh-index.el (mh-replace-string): Add autoload for it.
+
+2003-08-05  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-mime.el (mh-compose-forward, mh-mhn-compose-forw)
+       (mh-mml-forward-message): The variable mh-sent-from-msg can be a
+       list. So check that the value is really a number before using it
+       like one.
+
+       * mh-comp.el (mh-insert-letter): Same as above.
+
+       * mh-utils.el (mh-picon-get-image): Make the code that finds the
+       address of the sender more robust.
+       (mh-face-display-function): Make it work with XEmacs.
+       (mh-picon-image-types): A new variable that stores what image
+       types can be used.
+
+2003-08-05  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-customize.el (mh-tool-bar-define): Make the save button such
+       that is activated only if the buffer needs to saved.
+
+       * mh-utils.el (mh-face-display-function, mh-picon-get-image): Some
+       domains, for instance cs.cmu.edu, don't have xpm files. So we need
+       to search for all three files. The change does that.
+       (mh-picon-file-contents): A utility function to return the
+       contents of a file as a string.
+       (mh-picon-get-image): Write it as a loop to make it simpler.
+       (mh-x-image-set-download-state): Make the link simpler.
+
+2003-08-04  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-utils.el (mh-x-image-url-display): Don't bother to try to
+       download image if we don't have the necessary tools to display
+       it.
+       (mh-face-display-function): Add preliminary support for "domain"
+       picons.
+       (mh-picon-get-image, mh-picon-generate-path): Functions to find
+       best match for domain in the From header field.
+
+       * mh-e.el (mh-previous-unread-msg): If some of the messages in the
+       unseen sequence are not present in the folder buffer then calling
+       this function gets stuck and can't skip over them. The change
+       fixes this.
+       (mh-next-unread-msg): Same as above.
+
+2003-08-04  Bill Wohler  <wohler@newt.com>
+
+       * mh-utils.el (mh-show-mode): Added cross reference to
+       mh-folder-mode in docstring (closes SF #728638). Added
+       \\{mh-show-mode-map} to show keymap.
+
+       * mh-e.el (mh-folder-mode): Added information about ranges to
+       docstring (closes SF #728638).
+
+       * mh-speed.el (mh-speed-refresh): New function that calls
+       mh-speed-flists and mh-invalidate-map.
+       (mh-folder-speedbar-key-map): Replaced keybindings for
+       mh-speed-invalidate-map and mh-speed-flists with a single binding
+       for mh-speed-refresh.
+       (mh-folder-speedbar-menu-items): Replaced menu items for Run
+       Flists and Invalidate Cached Folders with the single menu item
+       Refresh Speedbar in order to simplify the UI.
+
+       * mh-customize.el (mh-fetch-x-image-url): Added DOS as another
+       reason not to set this to t.
+
+2003-08-04  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-e.el (mh-scan-folder): Handle ranges from user input properly.
+
+2003-08-03  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-utils.el (mh-find-msg-get-num): Removed. If threading isn't
+       present, the messages are sorted by index. So `mh-goto-msg' was
+       implemented as a binary search and this function was used in that
+       implementation. So this isn't needed any more.
+       (mh-msg-search-pat): Removed. Before the advent of message
+       threading, this function was used to generate a regexp used to
+       search for a particular message. It isn't used anymore. The
+       variable `mh-scan-msg-number-regexp' should be updated and used in
+       `mh-goto-msg' instead of hardcoding the regexp in the code. Then
+       we might be able to better support other scan line formats in the
+       future.
+
+       * mh-seq.el (mh-map-to-seq-msgs, mh-notate-seq): Removed. These
+       functions were used to notate user sequences. But calling
+       `mh-goto-msg' inside of a loop is inefficient. So the sequence
+       notation code was rewritten thereby making these functions
+       redundant.
+       (mh-copy-line-to-point): Removed. This function was used in the
+       implementation the now removed function `mh-copy-seq-to-point'.
+       That function was problematic and was replaced by the less general
+       `mh-copy-seq-to-eob'. This makes `mh-copy-line-to-point'
+       redundant.
+       (mh-region-to-msg-list): Removed since this is a special case of
+       the more general `mh-range-to-msg-list'.
+
+       * mh-loaddefs.el: Regenerated.
+
+2003-08-03  Jeffrey C Honig  <jch@honig.net>
+
+       * mh-customize.el (mh-invisible-header-fields-default): Added
+       several new fields to hide.  Sorted the list with sort-lines.
+
+2003-08-03  Peter S Galbraith  <psg@debian.org>
+
+       * mh-customize.el (mh-invisible-headers): Variable renamed to
+       `mh-invisible-header-fields-compiled'.
+       (mh-invisible-headers): Implement above change.
+
+       * mh-utils.el (mh-display-msg): Idem.
+
+       * mh-mime.el (mh-mm-inline-message): Idem.
+
+       * mh-comp.el (mh-insert-letter): Idem.
+
+2003-08-03  Bill Wohler  <wohler@newt.com>
+
+       * mh-speed.el (mh-folder-speedbar-menu-items): Added separator
+       between standard and MH-E menu items. Use headline capitalization
+       in menu items.
+
+       * mh-utils.el (mh-temp-fetch-buffer): New constant to hold
+       buffer name for wget output.
+       (mh-x-image-url-fetch-image): Use mh-temp-fetch-buffer instead
+       of hard-coded buffer name. Use make-temp-file to avoid race
+       conditions and subsequent security issues raised in make-temp-name
+       docstring.
+
+2003-08-03  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-utils.el (mh-wget-executable, mh-wget-choice, mh-wget-option)
+       (mh-x-image-url-fetch-image): Support the use of `curl' and
+       `fetch' as alternatives to `wget'.
+       (mh-wget-choice): Change order of search.
+       (mh-x-image-url-fetch-image): Rename buffer.
+
+2003-08-03  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-utils.el (mh-x-image-set-download-state)
+       (mh-x-image-get-download-state): Specially named symbolic links
+       are used to keep track of whether a X-Image-URL header field needs
+       to downloaded the next time it is seen. These functions get and
+       set the symlinks appropriately.
+       (mh-x-image-url-fetch-image): Simplified since the query has been
+       moved to `mh-x-image-url-display'. Also if wget isn't present then
+       try again next time since the user might install wget before
+       trying once more.
+       (mh-x-image-scale-and-display): Handle absence of the `convert'
+       program better. If it isn't present then we will try to display
+       the image the next time it is encountered. Also use the -geometry
+       option to convert since the -resize option isn't present in older
+       versions.
+       (mh-x-image-url-display): Move all the code that decides whether
+       an X-Image-URL header field will be fetched in this function. Also
+       remember the user's decision so that if the image couldn't be
+       fetched the first time, we will try to fetch it later on without
+       asking again.
+
+2003-08-02  Peter S Galbraith  <psg@debian.org>
+
+       * mh-alias.el (mh-alias-local-users): Exclude all aliases already
+       in mh-alias-alist from `ali' (closes SF #772595).
+
+2003-08-01  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-utils.el (mh-x-image-display, mh-x-image-url-display): Avoid
+       a race. The X-Image-URL is displayed asynchronously. Suppose a
+       message with a image is shown with `mh-show'. If a different
+       message is displayed before the image can be fetched, then the new
+       message will have the image displayed. With this change the race
+       is less likely to happen.
+
+2003-08-01  Peter S Galbraith  <psg@debian.org>
+
+       * mh-inc.el (mh-inc-spool-map): Fix what `mh-inc-spool-map-help'
+       must look like as a fake `mh-help-messages' in order to work
+       correctly in mh-help.
+
+2003-07-31  Bill Wohler  <wohler@newt.com>
+
+       * mh-inc.el (mh-inc-spool-map): Use mh-help instead of
+       mh-ephem-message in order to display help in its own buffer
+       instead of minibuffer.
+
+       * mh-utils.el (mh-help-buffer): New variable to hold the name of
+       the MH-E help buffer name.
+
+       * mh-funcs.el (mh-help, mh-prefix-help): Use with-electric-help to
+       display help messages. I observed a friend with a vision
+       disability and the 5 seconds the help appeared on the screen was
+       not long enough for him to lock on it. I've therefore changed the
+       help function to display the help in its own buffer called *MH-E
+       Help* (closes SF #493740 and SF #656631).
+
+       * mh-customize.el (mh-fetch-x-image-url): Changed default from nil
+       to 'ask. Updated docstring from manual.
+       (mh-invisible-header-fields-internal): Added X-Image-URL.
+       (mh-show-use-xface-flag): Updated docstring from manual.
+       (mh-x-face-file): Ditto.
+
+       * mh-mime.el (mh-mhn-compose-external-type): Don't insert the
+       directory parameter if it's nil. The mhbuild man page indicates
+       that this parameter is optional, so this should be fine.
+
+       * mh-comp.el (mh-letter-mode-map): Added keybindings for
+       mh-mhn-compose-anon-ftp and
+       mh-mhn-compose-external-compressed-tar.
+       (mh-letter-menu): Uncommented menu items for same.
+
+2003-07-30  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-loaddefs.el: Regenerated.
+
+       * mh-pick.el (mh-do-pick-search): Removed since the function
+       `mh-pick-do-search' performs the same action as this function.
+
+       * mh-index.el (mh-index-update-unseen): Removed since the
+       generalized sequence synchronization code that keeps sequences in
+       index folders in sync with the sequences in the source folders
+       makes this function redundant.
+
+       * mh-e.el (mh-folder-unseen-seq-name, mh-folder-unseen-seq-list):
+       Removed. These two functions were used in the unseen sequence
+       highlighting before the sequence highlighting code was
+       generalized. In any event calls to the function
+       `mh-folder-unseen-seq-name' can be replaced by the variable
+       `mh-unseen-seq' and calls to `mh-folder-unseen-seq-list' can be
+       replaced with (cdr (assoc mh-unseen-seq mh-seq-list)).
+       (mh-unmark-all-headers): Removed since this function has been
+       superseded by mh-remove-all-notation.
+       (mh-map-over-seqs): Removed since we now have the generalized
+       iteration over message ranges (the `mh-iterate-on-range' macro)
+       that can be used instead.
+       (mh-notate-if-in-one-seq): Removed. This function was used for
+       changing the `%' notation for user sequences. It can't be used for
+       that purpose any more, since we have a different scheme now.
+
+       * mh-unit.el (mh-unit-tests): Removed since it isn't needed any
+       more.
+       (mh-unit): Run all function that start with the string
+       "mh-unit-test-".
+
+2003-07-30  Bill Wohler  <wohler@newt.com>
+
+       * mh-customize.el (mh-invisible-header-fields): Checkdoc fix.
+
+       * mh-utils.el (mh-x-image-url-cache-canonicalize): Shortened using
+       example in files.el:make-backup-file-name-1.
+       (mh-face-display-function): Added X-Image-URL to docstring.
+
+       * mh-unit.el (mh-unit-x-image-url-cache-canonicalize): New
+       function to test mh-x-image-url-cache-canonicalize since it lent
+       itself well to unit testing. Had to start somewhere!
+       (mh-unit-equal): New function that throws an error if RESULT
+       doesn't equal EXPECTED.
+       (mh-unit): Call mh-unit-x-image-url-cache-canonicalize.
+       
+2003-07-29  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-unit.el (mh-unit-update-call-graph): Make the function work
+       better with dotted lists, that is lists of the form (a b c . d)
+       where `d' isn't nil. With this we are able to avoid marking some
+       functions as unused even though they are actually used in alists.
+
+2003-07-28  Peter S Galbraith  <psg@debian.org>
+
+       * mh-comp.el (mh-insert-letter):  Remove `mh-visible-headers'
+       operation.
+
+       * mh-mime.el (mh-mm-inline-message): Same.
+
+       * mh-utils.el (mh-display-msg): Same.
+       (mh-clean-msg-header): Make a note of above change.
+
+       * mh-customize.el (mh-invisible-header-fields-internal): Renamed
+       from prior `mh-invisible-header-fields-default'.
+       (mh-invisible-header-fields-default): Renamed from prior
+       `mh-invisible-header-fields-default-override'.
+       (mh-invisible-header-fields): Renamed from prior
+       `mh-invisible-header-fields-user'.
+       (mh-visible-headers): Removed!  We use invisible fields only now.
+       (mh-visible-header-fields): Removed!
+
+2003-07-28  Peter S Galbraith  <psg@debian.org>
+
+       * mh-customize.el (mh-invisible-header-fields-default): Added 3
+       new fields to hide.
+
+2003-07-28  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-utils.el (mh-show): Add an extra argument to the function so
+       that interactive use will always force redisplay of the message.
+
+       * mh-mime.el (mh-mime-display, mh-mm-inline-message): Bind the
+       variables `mm-verify-option' and `mm-decrypt-option' so that
+       verification and decryption of mail can happen without any
+       additional tinkering.
+
+2003-07-25  Peter S Galbraith  <psg@debian.org>
+
+       * mh-customize.el (mh-invisible-header-fields-default): New defvar
+       holding default fields to hide.  This replaces the old
+       `mh-invisible-header-fields' defcustom.
+       (mh-invisible-header-fields-user): New defcustom.  Users add
+       fields to suppress that we didn't include in
+       `mh-invisible-header-fields-default'.  This could be named simply
+       `mh-invisible-header-fields' and it wouldn't really break anything
+       for users who have customized it to a long list now redundant with
+       `mh-invisible-header-fields-default'.
+       (mh-invisible-header-fields-default-override): New defcustom.
+       Users check off the fields they want displyed from what we
+       included in `mh-invisible-header-fields-default'.
+       (mh-invisible-headers): Function adapted to new variables.
+
+2003-07-25  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-e.el (mh-inc-folder): If the user is in a different folder
+       displaying a message and runs mh-inc-folder, then the folder
+       changes to +inbox but the show window continues to display the
+       message in the old folder. The change fixes this.
+       (mh-visit-folder): Make the handling of the show window similar to
+       that of mh-inc-folder.
+
+2003-07-24  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-e.el (mh-folder-message-menu, mh-folder-folder-menu): Use the
+       predicate mh-outstanding-commands-p instead of its exapansion.
+       Also use the same label in both menus.
+       (mh-outstanding-commands-p): Generalized so that it will work in
+       mh-show-mode buffers as well.
+
+       * mh-customize.el (mh-tool-bar-define): Enable tool-bar button for
+       mh-execute-commands only if there are pending deletes or refiles.
+
+2003-07-19  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-utils.el (mh-show-msg): If a unseen message is first marked
+       for deletion/refiling and then displayed, the bold highlighting
+       does not go away. This change fixes that.
+
+       * mh-seq.el (mh-msg-is-in-seq): Fix a bug in the function. If any
+       message was marked for refiling, then the function would have you
+       believe that every message in the folder is being refiled.
+
+2003-07-17  Bill Wohler  <wohler@newt.com>
+
+       * mh-e.el: Removed email address for Stephen Gildea's in Change
+       Log at his request (damn spammers). Removed other email addresses
+       while I was at it since the SourceForge URL should be sufficient
+       contact information.
+
+       (mh-scan-format-*mh): Fixed typo in comment above these variables.
+       These variables are used if mh-scan-format-file is t, not nil.
+       Also mh-scan-format-file is no longer "above" (courtesy Stephen
+       Gildea).
+
+2003-07-17  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-mime.el (mh-mhn-quote-unescaped-sharp): New function that
+       quotes `#' characters in the first column that aren't part of a
+       MHN directive.
+       (mh-mhn-directive-present-p): Generalized to allow the function
+       to search for MHN directives in a part of the buffer.
+       (mh-edit-mhn): Quote unescaped `#' characters in the draft (closes
+       SF #762464).
+
+2003-07-16  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-alias.el (mh-alias-read-address-map): If
+       mh-alias-flash-on-comma is nil when mh-alias is loaded, then
+       setting mh-alias-flash-on-comma to t later on doesn't turn on
+       address completion display till Emacs is restarted. The change
+       fixes this.
+
+2003-07-15  Bill Wohler  <wohler@newt.com>
+
+       * mh-utils.el (mh-cmd-note): Cleaned up docstring (changed phrase
+       to sentences). Moved to Scan Line Formats section.
+       (mh-scan-msg-number-regexp)
+       (mh-scan-msg-overflow-regexp, mh-scan-msg-format-regexp)
+       (mh-scan-msg-format-string, mh-scan-msg-search-regexp): Cleaned up
+       docstrings (changed phrases to sentences).
+       (mh-note-seq): Cleaned up docstring (changed phrase to sentences).
+       Also, this variable is now a character and not a string. Moved to
+       Scan Line Formats section.
+
+       * mh-funcs.el (mh-note-copied, mh-note-printed): Cleaned up
+       docstrings (changed phrases to sentences). Also, these variables
+       are now characters and not strings.
+
+       * mh-e.el (mh-scan-format-mh, mh-scan-format-nmh): Filled. I was
+       hoping to quote the hint `t' but checkdoc wouldn't let me.
+       (mh-note-deleted, mh-note-refiled, mh-note-cur): Moved to Scan
+       Line Formats section.
+       (mh-scan-good-msg-regexp, mh-scan-deleted-msg-regexp) 
+       (mh-scan-refiled-msg-regexp, mh-scan-valid-regexp) 
+       (mh-scan-cur-msg-number-regexp, mh-scan-date-regexp) 
+       (mh-scan-rcpt-regexp, mh-scan-body-regexp) 
+       (mh-scan-subject-regexp, mh-scan-format-regexp): Cleaned
+       up docstrings (changed phrases to sentences).
+       (mh-scan-cur-msg-regexp): Marked this variable as obsolete; it
+       should be removed for 8.0.
+
+       * mh-comp.el (mh-note-repl, mh-note-forw, mh-note-dist): Cleaned
+       up docstrings (changed phrases to sentences). Also, these
+       variables are now characters and not strings.
+
+2003-07-15  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-index.el (mh-index-update-single-msg)
+       (mh-index-create-sequences): Handle the situation where there are
+       copies of the exact same message correctly.
+
+2003-07-15  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-seq.el (mh-thread-update-scan-line-map): Modified since
+       notation is already a character.
+
+       * mh-utils.el (mh-note-seq): Convert from string to character.
+       (mh-notate): Modified since characters are used to notate instead
+       of strings of length one.
+
+       * mh-comp.el (mh-note-repl, mh-note-forw, mh-note-dist): Convert
+       from string to characters.
+
+       * mh-e.el (mh-note-deleted, mh-note-refiled, mh-note-cur): Same as
+       above (closes SF #770772).
+       (mh-unmark-all-headers): Modified since mh-note-* variables are
+       now characters.
+       (mh-remove-sequence-notation): The mh-notate function remembers
+       the previous notation. Before the change to the mh-note-*
+       variables, mh-notate would only remember the change if a string
+       was used to notate the message. Now mh-notate is always called
+       with a character notation. So the deletion has to take place
+       explicitly.
+
+2003-06-28  Bill Wohler  <wohler@newt.com>
+
+       * mh-mime.el (mh-mhn-directive-present-p): If shell comments are
+       present that have a space after the # but no content, then this
+       function would throw an error. This has been fixed (closes SF
+       #762458).
+
+2003-06-27  Satyaki Das  <satyakid@stanford.edu>
+
+       * mh-index.el (mh-index-search): Use the new and improved
+       mh-index-new-folder.
+       (mh-index-new-folder): Improved so that redoing the same search
+       will reuse the old index folder.
+       (mh-index-folder-search-regexp): New function which that extracts
+       out the search expression that produced the index folder.
+
+2003-06-24  Bill Wohler  <wohler@newt.com>
+
+       * mh-e.el (Version, mh-version):  Set to 7.4.1+cvs.
+
 2003-06-25  Bill Wohler  <wohler@newt.com>
 
        * Released MH-E version 7.4.1.
index bd20b91..1356e2c 100644 (file)
 
 ;;; Commentary:
 
-;;  [To be deleted when documented in MH-E manual.]
-;;
-;;  This module provides mail alias completion when entering addresses.
-;;
-;;  Use the TAB key to complete aliases (and optionally local usernames) when
-;;  initially composing a message in the To: and Cc: minibuffer prompts. You
-;;  may enter multiple addressees separated with a comma (but do *not* add any
-;;  space after the comma).
-;;
-;;  In the header of a message draft, use "M-TAB (mh-letter-complete)" to
-;;  complete aliases. This is useful when you want to add an addressee as an
-;;  afterthought when creating a message, or when adding an additional
-;;  addressee to a reply.
-;;
-;;  By default, completion is case-insensitive. This can be changed by
-;;  customizing the variable `mh-alias-completion-ignore-case-flag'. This is
-;;  useful, for example, to differentiate between people aliases in lowercase
-;;  such as:
-;;
-;;    p.galbraith: Peter Galbraith <GalbraithP@dfo-mpo.gc.ca>
-;;
-;;  and lists in uppercase such as:
-;;
-;;    MH-E: MH-E mailing list <mh-e-devel@lists.sourceforge.net>
-;;
-;;  Note that this variable affects minibuffer completion only. If you have an
-;;  alias for P.Galbraith and type in p.galbraith at the prompt, it will still
-;;  be expanded in the letter buffer because MH is case-insensitive.
-;;
-;;  When you press ", (mh-alias-minibuffer-confirm-address)" after an alias in
-;;  the minibuffer, the expansion for the previous mail alias appears briefly.
-;;  To inhibit this, customize the variable `mh-alias-flash-on-comma'.
-;;
-;;  The addresses and aliases entered in the minibuffer are added to the
-;;  message draft. To expand the aliases before they are added to the draft,
-;;  customize the variable `mh-alias-expand-aliases-flag'.
-;;
-;;  Completion is also performed on usernames extracted from the /etc/passwd
-;;  file. This can be a handy tool on a machine where you and co-workers
-;;  exchange messages, but should probably be disabled on a system with
-;;  thousands of users you don't know. This is done by customizing the
-;;  variable `mh-alias-local-users'. This variable also takes a string which
-;;  is executed to generate the password file. For example, you'd use "ypcat
-;;  passwd" for NIS.
-;;
-;;  Aliases are loaded the first time you send mail and get the "To:" prompt
-;;  and whenever a source of aliases changes. Sources of system aliases are
-;;  defined in the customization variable `mh-alias-system-aliases' and
-;;  include:
-;;
-;;    /etc/nmh/MailAliases
-;;    /usr/lib/mh/MailAliases
-;;    /etc/passwd
-;;
-;;  Sources of personal aliases are read from the files listed in your MH
-;;  profile component Aliasfile. Multiple files are separated by white space
-;;  and are relative to your mail directory.
-;;
-;;  Alias Insertions
-;;  ~~~~~~~~~~~~~~~~
-;;  There are commands to insert new aliases into your alias file(s) (defined
-;;  by the `Aliasfile' component in the .mh_profile file or by the variable
-;;  `mh-alias-insert-file').  In particular, there is a tool-bar icon to grab
-;;  an alias from the From line of the current message.
-
 ;;; Change Log:
 
 ;;; Code:
 
+(eval-when-compile (require 'mh-acros))
+(mh-require-cl)
 (require 'mh-e)
 (load "cmr" t t)                        ; Non-fatal dependency for
                                        ; completing-read-multiple.
 (defvar mh-alias-tstamp nil
   "Time aliases were last loaded.")
 (defvar mh-alias-read-address-map nil)
-(if mh-alias-read-address-map
-    ()
+(unless mh-alias-read-address-map
   (setq mh-alias-read-address-map
        (copy-keymap minibuffer-local-completion-map))
-  (if mh-alias-flash-on-comma
-      (define-key mh-alias-read-address-map
-       "," 'mh-alias-minibuffer-confirm-address))
+  (define-key mh-alias-read-address-map
+    "," 'mh-alias-minibuffer-confirm-address)
   (define-key mh-alias-read-address-map " " 'self-insert-command))
 
+(defvar mh-alias-system-aliases
+  '("/etc/nmh/MailAliases" "/etc/mh/MailAliases"
+    "/usr/lib/mh/MailAliases" "/usr/share/mailutils/mh/MailAliases"
+    "/etc/passwd")
+  "*A list of system files which are a source of aliases.
+If these files are modified, they are automatically reread. This list need
+include only system aliases and the passwd file, since personal alias files
+listed in your `Aliasfile:' MH profile component are automatically included.
+You can update the alias list manually using \\[mh-alias-reload].")
+
 \f
 ;;; Alias Loading
 
@@ -138,7 +83,7 @@ This is a wrapper around `assoc-string' or `assoc-ignore-case'. Avoid
 
 (defun mh-alias-tstamp (arg)
   "Check whether alias files have been modified.
-Return t if any file listed in the MH profile component Aliasfile has been
+Return t if any file listed in the Aliasfile MH profile component has been
 modified since the timestamp.
 If ARG is non-nil, set timestamp with the current time."
   (if arg
@@ -157,7 +102,7 @@ If ARG is non-nil, set timestamp with the current time."
 
 (defun mh-alias-filenames (arg)
   "Return list of filenames that contain aliases.
-The filenames come from the MH profile component Aliasfile and are expanded.
+The filenames come from the Aliasfile profile component and are expanded.
 If ARG is non-nil, filenames listed in `mh-alias-system-aliases' are appended."
   (or mh-progs (mh-find-path))
   (save-excursion
@@ -201,7 +146,8 @@ non-nil."
     res))
 
 (defun mh-alias-local-users ()
-  "Return an alist of local users from /etc/passwd."
+  "Return an alist of local users from /etc/passwd.
+Exclude all aliases already in `mh-alias-alist' from `ali'"
   (let (passwd-alist)
     (save-excursion
       (set-buffer (get-buffer-create mh-temp-buffer))
@@ -222,23 +168,33 @@ non-nil."
                    (gecos-name (match-string 3))
                    (realname (mh-alias-gecos-name
                               gecos-name username
-                              mh-alias-passwd-gecos-comma-separator-flag)))
-              (setq passwd-alist
-                    (cons
-                     (list (if mh-alias-local-users-prefix
-                               (concat mh-alias-local-users-prefix
-                                       (mh-alias-suggest-alias realname t))
-                             username)
-                           (if (string-equal username realname)
-                               (concat "<" username ">")
-                             (concat realname " <" username ">")))
-                     passwd-alist))))))
+                              mh-alias-passwd-gecos-comma-separator-flag))
+                   (alias-name (if mh-alias-local-users-prefix
+                                  (concat mh-alias-local-users-prefix
+                                          (mh-alias-suggest-alias realname t))
+                                username))
+                   (alias-translation
+                    (if (string-equal username realname)
+                        (concat "<" username ">")
+                      (concat realname " <" username ">"))))
+              (when (not (mh-assoc-ignore-case alias-name mh-alias-alist))
+                (setq passwd-alist (cons (list alias-name alias-translation)
+                                         passwd-alist)))))))
         (forward-line 1)))
     passwd-alist))
 
 ;;;###mh-autoload
 (defun mh-alias-reload ()
-  "Load MH aliases into `mh-alias-alist'."
+  "Reload MH aliases.
+
+Since aliases are updated frequently, MH-E will reload aliases automatically
+whenever an alias lookup occurs if an alias source (a file listed in your
+`Aliasfile:' profile component and your password file if variable
+`mh-alias-local-users' is non-nil) has changed. However, you can reload your
+aliases manually by calling this command directly.
+
+The value of `mh-alias-reloaded-hook' is a list of functions to be called,
+with no arguments, after the aliases have been loaded."
   (interactive)
   (save-excursion
     (message "Loading MH aliases...")
@@ -269,13 +225,14 @@ non-nil."
         (if (not (mh-assoc-ignore-case (car user) mh-alias-alist))
             (setq mh-alias-alist (append mh-alias-alist (list user))))
         (setq local-users (cdr local-users)))))
+  (run-hooks 'mh-alias-reloaded-hook)
   (message "Loading MH aliases...done"))
 
 ;;;###mh-autoload
 (defun mh-alias-reload-maybe ()
   "Load new MH aliases."
-  (if (or (eq mh-alias-alist 'not-read) ; Doesn't exist, so create it.
-          (mh-alias-tstamp nil))        ; Out of date, so recreate it.
+  (if (or (eq mh-alias-alist 'not-read) ; Doesn't exist?
+          (mh-alias-tstamp nil))        ; Out of date?
       (mh-alias-reload)))
 
 \f
@@ -461,21 +418,21 @@ is converted to lower case."
       found)))
 
 (defun mh-alias-insert-file (&optional alias)
-  "Return the alias file to write a new entry for ALIAS in.
-Use variable `mh-alias-insert-file' if non-nil, else use AliasFile component
-value.
-If ALIAS is specified and it already exists, try to return the file that
-contains it."
+  "Return filename which should be used to add ALIAS.
+The value of the option `mh-alias-insert-file' is used if non-nil\; otherwise
+the value of the `Aliasfile:' profile component is used.
+If the alias already exists, try to return the name of the file that contains
+it."
   (cond
    ((and mh-alias-insert-file (listp mh-alias-insert-file))
     (if (not (elt mh-alias-insert-file 1))        ; Only one entry, use it
         (car mh-alias-insert-file)
       (if (or (not alias)
               (string-equal alias (mh-alias-ali alias))) ;alias doesn't exist
-          (completing-read "Alias file [press Tab]: "
+          (completing-read "Alias file: "
                            (mapcar 'list mh-alias-insert-file) nil t)
         (or (mh-alias-which-file-has-alias alias mh-alias-insert-file)
-            (completing-read "Alias file [press Tab]: "
+            (completing-read "Alias file: "
                              (mapcar 'list mh-alias-insert-file) nil t)))))
    ((and mh-alias-insert-file (stringp mh-alias-insert-file))
     mh-alias-insert-file)
@@ -490,16 +447,15 @@ contains it."
       (cond
        ((not autolist)
         (error "No writable alias file.
-Set `mh-alias-insert-file' or set AliasFile in your .mh_profile file"))
+Set `mh-alias-insert-file' or the Aliasfile profile component"))
        ((not (elt autolist 1))        ; Only one entry, use it
         (car autolist))
        ((or (not alias)
             (string-equal alias (mh-alias-ali alias))) ;alias doesn't exist
-        (completing-read "Alias file [press Tab]: "
-                         (mapcar 'list autolist) nil t))
+        (completing-read "Alias file: " (mapcar 'list autolist) nil t))
        (t
         (or (mh-alias-which-file-has-alias alias autolist)
-            (completing-read "Alias file [press Tab]: "
+            (completing-read "Alias file: "
                              (mapcar 'list autolist) nil t))))))))
 
 ;;;###mh-autoload
@@ -520,10 +476,8 @@ Set `mh-alias-insert-file' or set AliasFile in your .mh_profile file"))
                       (split-string aliases ", +")))))))
 
 ;;;###mh-autoload
-(defun mh-alias-from-has-no-alias-p ()
-  "Return t is From has no current alias set.
-In the exceptional situation where there isn't a From header in the message the
-function returns nil."
+(defun mh-alias-for-from-p ()
+  "Return t if sender's address has a corresponding alias."
   (mh-alias-reload-maybe)
   (save-excursion
     (if (not (mh-folder-line-matches-show-buffer-p))
@@ -532,13 +486,16 @@ function returns nil."
           (set-buffer mh-show-buffer))
       (let ((from-header (mh-extract-from-header-value)))
         (and from-header
-             (not (mh-alias-address-to-alias from-header)))))))
+             (mh-alias-address-to-alias from-header))))))
 
 (defun mh-alias-add-alias-to-file (alias address &optional file)
   "Add ALIAS for ADDRESS in alias FILE without alias check or prompts.
 Prompt for alias file if not provided and there is more than one candidate.
-If ALIAS matches exactly, prompt to [i]nsert before old value or [a]ppend
-after it."
+
+If the alias exists already, you will have the choice of inserting the new
+alias before or after the old alias. In the former case, this alias will be
+used when sending mail to this alias. In the latter case, the alias serves as
+an additional folder name hint when filing messages."
   (if (not file)
       (setq file (mh-alias-insert-file alias)))
   (save-excursion
@@ -552,14 +509,15 @@ after it."
        ((re-search-forward
          (concat "^" (regexp-quote alias-search) " *\\(.*\\)") nil t)
         (let ((answer (read-string
-                       (format "Exists for %s; [i]nsert, [a]ppend: "
+                       (format (concat "Alias %s exists; insert new address "
+                                       "[b]efore or [a]fter: ")
                                (match-string 1))))
               (case-fold-search t))
-          (cond ((string-match "^i" answer))
+          (cond ((string-match "^b" answer))
                 ((string-match "^a" answer)
                  (forward-line 1))
                 (t
-                 (error "Quitting")))))
+                 (error "Unrecognized response")))))
        ;; No, so sort-in at the right place
        ;; search for "^alias", then "^alia", etc.
        ((eq mh-alias-insertion-location 'sorted)
@@ -587,8 +545,11 @@ after it."
 ;;;###mh-autoload
 (defun mh-alias-add-alias (alias address)
   "*Add ALIAS for ADDRESS in personal alias file.
-Prompts for confirmation if the address already has an alias.
-If the alias is already is use, `mh-alias-add-alias-to-file' will prompt."
+This function prompts you for an alias and address. If the alias exists
+already, you will have the choice of inserting the new alias before or after
+the old alias. In the former case, this alias will be used when sending mail
+to this alias. In the latter case, the alias serves as an additional folder
+name hint when filing messages."
   (interactive "P\nP")
   (mh-alias-reload-maybe)
   (setq alias (completing-read "Alias: " mh-alias-alist nil nil alias))
@@ -614,9 +575,7 @@ If the alias is already is use, `mh-alias-add-alias-to-file' will prompt."
 
 ;;;###mh-autoload
 (defun mh-alias-grab-from-field ()
-  "*Add ALIAS for ADDRESS in personal alias file.
-Prompts for confirmation if the alias is already in use or if the address
-already has an alias."
+  "*Add alias for the sender of the current message."
   (interactive)
   (mh-alias-reload-maybe)
   (save-excursion
@@ -636,24 +595,26 @@ already has an alias."
 
 ;;;###mh-autoload
 (defun mh-alias-add-address-under-point ()
-  "Insert an alias for email address under point."
+  "Insert an alias for address under point."
   (interactive)
   (let ((address (mh-goto-address-find-address-at-point)))
     (if address
         (mh-alias-add-alias nil address)
-      (message "No email address found under point."))))
+      (message "No email address found under point"))))
 
 ;;;###mh-autoload
 (defun mh-alias-apropos (regexp)
-  "Show all aliases that match REGEXP either in name or content."
+  "Show all aliases or addresses that match REGEXP."
   (interactive "sAlias regexp: ")
   (if mh-alias-local-users
       (mh-alias-reload-maybe))
-  (let ((matches "")(group-matches "")(passwd-matches))
+  (let ((matches "")
+        (group-matches "")
+        (passwd-matches))
     (save-excursion
       (message "Reading MH aliases...")
       (mh-exec-cmd-quiet t "ali" "-nolist" "-nouser")
-      (message "Reading MH aliases...done.  Parsing...")
+      (message "Parsing MH aliases...")
       (while (re-search-forward regexp nil t)
         (beginning-of-line)
         (cond
@@ -673,10 +634,9 @@ already has an alias."
                 (concat matches
                         (buffer-substring (point)(progn (end-of-line)(point)))
                         "\n")))))
-      (message "Reading MH aliases...done.  Parsing...done.")
+      (message "Parsing MH aliases...done")
       (when mh-alias-local-users
-        (message
-         "Reading MH aliases...done.  Parsing...done.  Passwd aliases...")
+        (message "Making passwd aliases...")
         (setq passwd-matches
               (mapconcat
                '(lambda (elem)
@@ -684,13 +644,12 @@ already has an alias."
                           (string-match regexp (cadr elem)))
                       (format "%s: %s\n" (car elem) (cadr elem))))
                mh-alias-passwd-alist ""))
-        (message
-         "Reading MH aliases...done.  Parsing...done.  Passwd aliases...done.")))
+        (message "Making passwd aliases...done")))
     (if (and (string-equal "" matches)
              (string-equal "" group-matches)
              (string-equal "" passwd-matches))
         (message "No matches")
-      (with-output-to-temp-buffer "*Help*"
+      (with-output-to-temp-buffer mh-aliases-buffer
         (if (not (string-equal "" matches))
             (princ matches))
         (when (not (string-equal group-matches ""))
index 489b669..cde52c6 100644 (file)
 
 ;;; Code:
 
+(eval-when-compile (require 'mh-acros))
+(mh-require-cl)
 (require 'mh-e)
 (require 'gnus-util)
 (require 'easymenu)
-(require 'mh-utils)
-(mh-require-cl)
+(require 'mh-gnus)
 (eval-when (compile load eval)
   (ignore-errors (require 'mailabbrev)))
 
@@ -48,6 +49,7 @@
 (defvar sendmail-coding-system)
 (defvar mh-identity-list)
 (defvar mh-identity-default)
+(defvar mh-mml-mode-default)
 (defvar mh-identity-menu)
 
 ;;; Autoloads
@@ -58,7 +60,7 @@
 (autoload 'sc-cite-original "sc"
   "Workhorse citing function which performs the initial citation.
 This is callable from the various mail and news readers' reply
-function according to the agreed upon standard.  See `\\[sc-describe]'
+function according to the agreed upon standard.  See `sc-describe'
 for more details.  `sc-cite-original' does not do any yanking of the
 original message but it does require a few things:
 
@@ -95,14 +97,16 @@ If MH will not allow you to redist a previously redist'd msg, set to nil.")
 This allows transaction log to be visible if -watch, -verbose or -snoop are
 used.")
 
-(defvar mh-note-repl "-"
-  "String whose first character is used to notate replied to messages.")
+;;; Scan Line Formats
+
+(defvar mh-note-repl ?-
+  "Messages that have been replied to are marked by this character.")
 
-(defvar mh-note-forw "F"
-  "String whose first character is used to notate forwarded messages.")
+(defvar mh-note-forw ?F
+  "Messages that have been forwarded are marked by this character.")
 
-(defvar mh-note-dist "R"
-  "String whose first character is used to notate redistributed messages.")
+(defvar mh-note-dist ?R
+  "Messages that have been redistributed are marked by this character.")
 
 (defvar mh-yank-hooks nil
   "Obsolete hook for modifying a citation just inserted in the mail buffer.
@@ -113,23 +117,6 @@ text as modified.
 This is a normal hook, misnamed for historical reasons.
 It is semi-obsolete and is only used if `mail-citation-hook' is nil.")
 
-(defvar mail-citation-hook nil
-  "*Hook for modifying a citation just inserted in the mail buffer.
-Each hook function can find the citation between point and mark.
-And each hook function should leave point and mark around the citation
-text as modified.
-
-If this hook is entirely empty (nil), the text of the message is inserted
-with `mh-ins-buf-prefix' prefixed to each line.
-
-See also the variable `mh-yank-from-start-of-msg', which controls how
-much of the message passed to the hook.
-
-This hook was historically provided to set up supercite.  You may now leave
-this nil and set up supercite by setting the variable
-`mh-yank-from-start-of-msg' to 'supercite or, for more automatic insertion,
-to 'autosupercite.")
-
 (defvar mh-comp-formfile "components"
   "Name of file to be used as a skeleton for composing messages.
 Default is \"components\".  If not an absolute file name, the file
@@ -145,7 +132,8 @@ system MH lib directory.")
 (defvar mh-repl-group-formfile "replgroupcomps"
   "Name of file to be used as a skeleton for replying to messages.
 This file is used to form replies to the sender and all recipients of a
-message. Only used if `mh-nmh-flag' is non-nil. Default is \"replgroupcomps\".
+message. Only used if `(mh-variant-p 'nmh)' is non-nil.
+Default is \"replgroupcomps\".
 If not an absolute file name, the file is searched for first in the user's MH
 directory, then in the system MH lib directory.")
 
@@ -153,6 +141,8 @@ directory, then in the system MH lib directory.")
   (format "^%s$"
           (regexp-opt
            '("Content-Type: message/rfc822" ;MIME MDN
+             "------ This is a copy of the message, including all the headers. ------";from exim
+            "--- Below this line is a copy of the message."; from qmail
              "   ----- Unsent message follows -----" ;from sendmail V5
              " --------Unsent Message below:" ; from sendmail at BU
              "   ----- Original message follows -----" ;from sendmail V8
@@ -201,16 +191,16 @@ Used by the \\<mh-folder-mode-map>`\\[mh-edit-again]' and `\\[mh-extract-rejecte
   "Field name for message annotation.")
 
 (defvar mh-insert-auto-fields-done-local nil
-  "Buffer-local variable set when `mh-insert-auto-fields' successfully called.")
+  "Buffer-local variable set when `mh-insert-auto-fields' called successfully.")
 (make-variable-buffer-local 'mh-insert-auto-fields-done-local)
 
 ;;;###autoload
 (defun mh-smail ()
   "Compose and send mail with the MH mail system.
-This function is an entry point to MH-E, the Emacs front end
-to the MH mail system.
+This function is an entry point to MH-E, the Emacs interface to the MH mail
+system.
 
-See documentation of `\\[mh-send]' for more details on composing mail."
+See `mh-send' for more details on composing mail."
   (interactive)
   (mh-find-path)
   (call-interactively 'mh-send))
@@ -220,11 +210,11 @@ See documentation of `\\[mh-send]' for more details on composing mail."
 ;;;###autoload
 (defun mh-smail-batch (&optional to subject other-headers &rest ignored)
   "Set up a mail composition draft with the MH mail system.
-This function is an entry point to MH-E, the Emacs front end
-to the MH mail system.  This function does not prompt the user
-for any header fields, and thus is suitable for use by programs
-that want to create a mail buffer.
-Users should use `\\[mh-smail]' to compose mail.
+This function is an entry point to MH-E, the Emacs interface to the MH mail
+system. This function does not prompt the user for any header fields, and thus
+is suitable for use by programs that want to create a mail buffer. Users
+should use `mh-smail' to compose mail.
+
 Optional arguments for setting certain fields include TO, SUBJECT, and
 OTHER-HEADERS. Additional arguments are IGNORED."
   (mh-find-path)
@@ -260,7 +250,8 @@ CONTINUE, SWITCH-FUNCTION, YANK-ACTION and SEND-ACTIONS are ignored."
   "Clean up a draft or a message MSG previously sent and make it resendable.
 Default is the current message.
 The variable `mh-new-draft-cleaned-headers' specifies the headers to remove.
-See also documentation for `\\[mh-send]' function."
+
+See also `mh-send'."
   (interactive (list (mh-get-msg-num t)))
   (let* ((from-folder mh-current-folder)
          (config (current-window-configuration))
@@ -292,7 +283,8 @@ See also documentation for `\\[mh-send]' function."
   "Extract message MSG returned by the mail system and make it resendable.
 Default is the current message.  The variable `mh-new-draft-cleaned-headers'
 gives the headers to clean out of the original message.
-See also documentation for `\\[mh-send]' function."
+
+See also `mh-send'."
   (interactive (list (mh-get-msg-num t)))
   (let ((from-folder mh-current-folder)
         (config (current-window-configuration))
@@ -303,7 +295,7 @@ See also documentation for `\\[mh-send]' function."
            (delete-region (point-min) (point))
            (mh-clean-msg-header (point-min) mh-new-draft-cleaned-headers nil))
           (t
-           (message "Does not appear to be a rejected letter.")))
+           (message "Does not appear to be a rejected letter")))
     (mh-insert-header-separator)
     (goto-char (point-min))
     (save-buffer)
@@ -323,7 +315,7 @@ Default is the displayed message.
 Check the documentation of `mh-interactive-range' to see how RANGE is read in
 interactive use.
 
-See also documentation for `\\[mh-send]' function."
+See also `mh-send'."
   (interactive (list (mh-interactive-read-address "To: ")
                      (mh-interactive-read-address "Cc: ")
                      (mh-interactive-range "Forward")))
@@ -335,7 +327,10 @@ See also documentation for `\\[mh-send]' function."
          (draft-name (expand-file-name "draft" mh-user-path))
          (draft (cond ((or (not (file-exists-p draft-name))
                            (y-or-n-p "The file 'draft' exists.  Discard it? "))
-                       (mh-exec-cmd "forw" "-build" (if mh-nmh-flag "-mime")
+                       (mh-exec-cmd "forw" "-build"
+                                    (if (and (mh-variant-p 'nmh)
+                                             mh-compose-forward-as-mime-flag)
+                                        "-mime")
                                     mh-current-folder
                                     (mh-coalesce-msg-list msgs))
                        (prog1
@@ -388,7 +383,8 @@ See also documentation for `\\[mh-send]' function."
                                   mh-note-forw "Forwarded:"
                                   config)
         (mh-letter-mode-message)
-        (mh-letter-adjust-point)))))
+        (mh-letter-adjust-point)
+        (run-hooks 'mh-forward-hook)))))
 
 (defun mh-forwarded-letter-subject (from subject)
   "Return a Subject suitable for a forwarded message.
@@ -406,10 +402,10 @@ Original message has headers FROM and SUBJECT."
 ;;;###autoload
 (defun mh-smail-other-window ()
   "Compose and send mail in other window with the MH mail system.
-This function is an entry point to MH-E, the Emacs front end
-to the MH mail system.
+This function is an entry point to MH-E, the Emacs interface to the MH mail
+system.
 
-See documentation of `\\[mh-send]' for more details on composing mail."
+See `mh-send' for more details on composing mail."
   (interactive)
   (mh-find-path)
   (call-interactively 'mh-send-other-window))
@@ -496,13 +492,15 @@ to reply to:
 If optional prefix argument INCLUDEP provided, then include the message
 in the reply using filter `mhl.reply' in your MH directory.
 If the file named by `mh-repl-formfile' exists, it is used as a skeleton
-for the reply.  See also documentation for `\\[mh-send]' function."
+for the reply.
+
+See also `mh-send'."
   (interactive (list
                 (mh-get-msg-num t)
                 (let ((minibuffer-help-form
                        "from => Sender only\nto => Sender and primary recipients\ncc or all => Sender and all recipients"))
                   (or mh-reply-default-reply-to
-                      (completing-read "Reply to whom? (from, to, all) [from]: "
+                      (completing-read "Reply to whom: [from] "
                                        '(("from") ("to") ("cc") ("all"))
                                        nil
                                        t)))
@@ -511,7 +509,7 @@ for the reply.  See also documentation for `\\[mh-send]' function."
          (show-buffer mh-show-buffer)
          (config (current-window-configuration))
          (group-reply (or (equal reply-to "cc") (equal reply-to "all")))
-         (form-file (cond ((and mh-nmh-flag group-reply
+         (form-file (cond ((and (mh-variant-p 'nmh 'mu-mh) group-reply
                                 (stringp mh-repl-group-formfile))
                            mh-repl-group-formfile)
                           ((stringp mh-repl-formfile) mh-repl-formfile)
@@ -525,7 +523,7 @@ for the reply.  See also documentation for `\\[mh-send]' function."
                         '("-nocc" "all"))
                        ((equal reply-to "to")
                         '("-cc" "to"))
-                       (group-reply (if mh-nmh-flag
+                       (group-reply (if (mh-variant-p 'nmh 'mu-mh)
                                         '("-group" "-nocc" "me")
                                       '("-cc" "all" "-nocc" "me"))))
                  (cond ((or (eq mh-yank-from-start-of-msg 'autosupercite)
@@ -562,7 +560,6 @@ for the reply.  See also documentation for `\\[mh-send]' function."
 ;;;###mh-autoload
 (defun mh-send (to cc subject)
   "Compose and send a letter.
-
 Do not call this function from outside MH-E; use \\[mh-smail] instead.
 
 The file named by `mh-comp-formfile' will be used as the form.
@@ -581,7 +578,6 @@ passed three arguments: TO, CC, and SUBJECT."
 ;;;###mh-autoload
 (defun mh-send-other-window (to cc subject)
   "Compose and send a letter in another window.
-
 Do not call this function from outside MH-E; use \\[mh-smail-other-window]
 instead.
 
@@ -711,6 +707,8 @@ Do not insert any pairs whose value is the empty string."
     (while name-values
       (let ((field-name (car name-values))
             (value (car (cdr name-values))))
+        (if (not (string-match "^.*:$" field-name))
+            (setq field-name (concat field-name ":")))
         (cond ((equal value "")
                nil)
               ((mh-position-on-field field-name)
@@ -730,6 +728,7 @@ The optional second arg is for pre-version 4 compatibility and is IGNORED."
         ((mh-goto-header-end 0)
          nil)))
 
+;;;###mh-autoload
 (defun mh-get-header-field (field)
   "Find and return the body of FIELD in the mail header.
 Returns the empty string if the field is not in the header of the
@@ -777,35 +776,53 @@ Returns t if found, nil if not."
 
 ;;; Menu extracted from mh-menubar.el V1.1 (31 July 2001)
 (eval-when-compile (defvar mh-letter-menu nil))
-(cond
- ((fboundp 'easy-menu-define)
-  (easy-menu-define
-    mh-letter-menu mh-letter-mode-map "Menu for MH-E letter mode."
-    '("Letter"
-      ["Send This Draft"          mh-send-letter t]
-      ["Split Current Line"       mh-open-line t]
-      ["Check Recipient"          mh-check-whom t]
-      ["Yank Current Message"     mh-yank-cur-msg t]
-      ["Insert a Message..."      mh-insert-letter t]
-      ["Insert Signature"         mh-insert-signature t]
-      ["GPG Sign message"
-       mh-mml-secure-message-sign-pgpmime mh-gnus-pgp-support-flag]
-      ["GPG Encrypt message"
-       mh-mml-secure-message-encrypt-pgpmime mh-gnus-pgp-support-flag]
-      ["Compose Insertion (MIME)..."      mh-compose-insertion t]
-      ;;    ["Compose Compressed tar (MIME)..."
-      ;;mh-mhn-compose-external-compressed-tar t]
-      ;;    ["Compose Anon FTP (MIME)..."       mh-mhn-compose-anon-ftp t]
-      ["Compose Forward (MIME)..."        mh-compose-forward t]
-      ;; The next two will have to be merged. But I also need to make sure the
-      ;; user can't mix directives of both types.
-      ["Pull in All Compositions (mhn)"
-       mh-edit-mhn (mh-mhn-directive-present-p)]
-      ["Pull in All Compositions (gnus)"
-       mh-mml-to-mime (mh-mml-directive-present-p)]
-      ["Revert to Non-MIME Edit (mhn)"
-       mh-revert-mhn-edit (equal mh-compose-insertion 'mhn)]
-      ["Kill This Draft"          mh-fully-kill-draft t]))))
+(easy-menu-define
+  mh-letter-menu mh-letter-mode-map "Menu for MH-E letter mode."
+  '("Letter"
+    ["Send This Draft"          mh-send-letter t]
+    ["Split Current Line"       mh-open-line t]
+    ["Check Recipient"          mh-check-whom t]
+    ["Yank Current Message"     mh-yank-cur-msg t]
+    ["Insert a Message..."      mh-insert-letter t]
+    ["Insert Signature"         mh-insert-signature t]
+    ("Encrypt/Sign Message"
+     ["Sign Message"
+      mh-mml-secure-message-sign mh-gnus-pgp-support-flag]
+     ["Encrypt Message"
+      mh-mml-secure-message-encrypt mh-gnus-pgp-support-flag]
+     ["Sign+Encrypt Message"
+      mh-mml-secure-message-signencrypt mh-gnus-pgp-support-flag]
+     ["Disable Security"
+      mh-mml-unsecure-message mh-gnus-pgp-support-flag]
+     "--"
+     "Security Method"
+     ["PGP (MIME)" (setq mh-mml-method-default "pgpmime")
+      :style radio
+      :selected (equal mh-mml-method-default "pgpmime")]
+     ["PGP" (setq mh-mml-method-default "pgp")
+      :style radio
+      :selected (equal mh-mml-method-default "pgp")]
+     ["S/MIME" (setq mh-mml-method-default "smime")
+      :style radio
+      :selected (equal mh-mml-method-default "smime")]
+     "--"
+     ["Save Method as Default"
+      (customize-save-variable 'mh-mml-method-default mh-mml-method-default) t]
+     )
+    ["Compose Insertion (MIME)..."      mh-compose-insertion t]
+    ["Compose Compressed tar (MIME)..."
+     mh-mhn-compose-external-compressed-tar t]
+    ["Compose Get File (MIME)..."       mh-mhn-compose-anon-ftp t]
+    ["Compose Forward (MIME)..."        mh-compose-forward t]
+    ;; The next two will have to be merged. But I also need to make sure the
+    ;; user can't mix directives of both types.
+    ["Pull in All Compositions (mhn)"
+     mh-edit-mhn (mh-mhn-directive-present-p)]
+    ["Pull in All Compositions (gnus)"
+     mh-mml-to-mime (mh-mml-directive-present-p)]
+    ["Revert to Non-MIME Edit (mhn)"
+     mh-revert-mhn-edit (equal mh-compose-insertion 'mhn)]
+    ["Kill This Draft"          mh-fully-kill-draft t]))
 
 ;;; Help Messages
 ;;; Group messages logically, more or less.
@@ -817,12 +834,15 @@ Returns t if found, nil if not."
      "\t\tInsert:\n"
      "Check recipients:     \\[mh-check-whom]"
      "\t\t  Current message:    \\[mh-yank-cur-msg]\n"
-     "Encrypt message:      \\[mh-mml-secure-message-encrypt-pgpmime]"
-     "\t\t  Attachment:         \\[mh-compose-insertion]\n"
-     "Sign message:         \\[mh-mml-secure-message-sign-pgpmime]"
-     "\t\t  Message to forward: \\[mh-compose-forward]\n"
+     "\t\t  Attachment:             \\[mh-compose-insertion]\n"
+     "\t\t  Message to forward:     \\[mh-compose-forward]\n"
+     "                          "
+     "Security:"
+     "\t\t  Encrypt message:          \\[mh-mml-secure-message-encrypt]"
+     "\t\t  Sign+Encrypt message:     \\[mh-mml-secure-message-signencrypt]"
+     "\t\t  Sign message:             \\[mh-mml-secure-message-sign]\n"
      "                          "
-     "\t\t  Signature:          \\[mh-insert-signature]"))
+     "\t\t  Signature:              \\[mh-insert-signature]"))
   "Key binding cheat sheet.
 
 This is an associative array which is used to show the most common commands.
@@ -872,13 +892,19 @@ When a message is composed, the hooks `text-mode-hook' and
 `mh-letter-mode-hook' are run.
 
 \\{mh-letter-mode-map}"
-  (or mh-user-path (mh-find-path))
+  (mh-find-path)
   (make-local-variable 'mh-send-args)
   (make-local-variable 'mh-annotate-char)
   (make-local-variable 'mh-annotate-field)
   (make-local-variable 'mh-previous-window-config)
   (make-local-variable 'mh-sent-from-folder)
   (make-local-variable 'mh-sent-from-msg)
+  ;; Set the local value of mh-mail-header-separator according to what is
+  ;; present in the buffer...
+  (set (make-local-variable 'mh-mail-header-separator)
+       (save-excursion
+         (goto-char (mh-mail-header-end))
+         (buffer-substring-no-properties (point) (line-end-position))))
   (make-local-variable 'mail-header-separator)
   (setq mail-header-separator mh-mail-header-separator) ;override sendmail.el
   (make-local-variable 'mh-help-messages)
@@ -886,12 +912,6 @@ When a message is composed, the hooks `text-mode-hook' and
   (setq buffer-invisibility-spec '((vanish . t) t))
   (set (make-local-variable 'line-move-ignore-invisible) t)
 
-  ;; Set mh-mail-header-end-marker to remember end of message header.
-  (set (make-local-variable 'mh-letter-mail-header-end-marker)
-       (set-marker (make-marker) (save-excursion
-                                   (goto-char (mh-mail-header-end))
-                                   (line-beginning-position 2))))
-
   ;; From sendmail.el for proper paragraph fill
   ;; sendmail.el also sets a normal-auto-fill-function (not done here)
   (make-local-variable 'paragraph-separate)
@@ -965,11 +985,15 @@ When a message is composed, the hooks `text-mode-hook' and
          t)))
 
 (defun mh-letter-header-end ()
-  "Find the end of header from `mh-letter-mail-header-end-marker'."
+  "Find the end of the message header.
+This function is to be used only for font locking. It works by searching for
+`mh-mail-header-separator' in the buffer."
   (save-excursion
-    (goto-char (marker-position mh-letter-mail-header-end-marker))
-    (forward-line -1)
-    (point)))
+    (goto-char (point-min))
+    (cond ((equal mh-mail-header-separator "") (point-min))
+          ((search-forward (format "\n%s\n" mh-mail-header-separator) nil t)
+           (line-beginning-position 0))
+          (t (point-min)))))
 
 (defun mh-auto-fill-for-letter ()
   "Perform auto-fill for message.
@@ -1041,16 +1065,69 @@ Prompt for the field name with a completion list of the current folders."
                   (substring folder 1)
                 folder)))))
 
+(defun mh-file-is-vcard-p (file)
+  "Return t if FILE is a .vcf vcard."
+  (let ((case-fold-search t))
+    (and (stringp file)
+         (file-exists-p file)
+         (or (and (not (mh-have-file-command))
+                  (not (null (string-match "\.vcf$" file))))
+             (and (mh-have-file-command)
+                  (string-equal "text/x-vcard" (mh-file-mime-type file)))))))
+
 ;;;###mh-autoload
-(defun mh-insert-signature ()
-  "Insert the file named by `mh-signature-file-name' at point.
+(defun mh-insert-signature (&optional file)
+  "Insert the signature specified by `mh-signature-file-name' or FILE at point.
+A signature separator (`-- ') will be added if the signature block does not
+contain one and `mh-signature-separator-flag' is on.
 The value of `mh-letter-insert-signature-hook' is a list of functions to be
-called, with no arguments, before the signature is actually inserted."
-  (interactive)
-  (let ((mh-signature-file-name mh-signature-file-name))
-    (run-hooks 'mh-letter-insert-signature-hook)
-    (if mh-signature-file-name
-        (insert-file-contents mh-signature-file-name)))
+called, with no arguments, after the signature is inserted.
+The signature can also be inserted with `mh-identity-list'."
+(interactive)
+  (save-excursion
+    (insert "\n")
+    (let ((mh-signature-file-name (or file mh-signature-file-name))
+          (mh-mhn-p (mh-mhn-directive-present-p))
+          (mh-mml-p (mh-mml-directive-present-p)))
+      (save-restriction
+        (narrow-to-region (point) (point))
+        (cond
+         ((mh-file-is-vcard-p mh-signature-file-name)
+          (if (equal mh-compose-insertion 'gnus)
+              (insert "<#part type=\"text/x-vcard\" filename=\""
+                      mh-signature-file-name
+                      "\" disposition=inline description=VCard>\n<#/part>")
+            (insert "#text/x-vcard; name=\""
+                    (file-name-nondirectory mh-signature-file-name)
+                    "\" [VCard] " (expand-file-name mh-signature-file-name))))
+         (t
+          (cond
+           (mh-mhn-p
+            (insert "#\n" "Content-Description: Signature\n"))
+           (mh-mml-p
+            (mml-insert-tag 'part 'type "text/plain" 'disposition "inline"
+                            'description "Signature")))
+          (cond ((null mh-signature-file-name))
+                ((and (stringp mh-signature-file-name)
+                      (file-readable-p mh-signature-file-name))
+                 (insert-file-contents mh-signature-file-name))
+                ((functionp mh-signature-file-name)
+                 (funcall mh-signature-file-name)))))
+        (save-restriction
+          (widen)
+          (run-hooks 'mh-letter-insert-signature-hook))
+        (goto-char (point-min))
+        (when (and (not (mh-file-is-vcard-p mh-signature-file-name))
+                   mh-signature-separator-flag
+                   (> (point-max) (point-min))
+                   (not (mh-signature-separator-p)))
+          (cond (mh-mhn-p
+                 (forward-line 2))
+                (mh-mml-p
+                 (forward-line 1)))
+          (insert mh-signature-separator))
+        (if (not (> (point-max) (point-min)))
+            (message "No signature found")))))
   (force-mode-line-update))
 
 ;;;###mh-autoload
@@ -1100,33 +1177,18 @@ MH the first time a message is composed.")
 (defun mh-insert-x-mailer ()
   "Append an X-Mailer field to the header.
 The versions of MH-E, Emacs, and MH are shown."
-
   ;; Lazily initialize mh-x-mailer-string.
   (when (and mh-insert-x-mailer-flag (null mh-x-mailer-string))
-    (save-window-excursion
-      ;; User would be confused if version info buffer disappeared magically,
-      ;; so don't delete buffer if it already existed.
-      (let ((info-buffer-exists-p (get-buffer mh-info-buffer)))
-        (mh-version)
-        (set-buffer mh-info-buffer)
-        (if mh-nmh-flag
-            (search-forward-regexp "^nmh-\\(\\S +\\)")
-          (search-forward-regexp "^MH \\(\\S +\\)" nil t))
-        (let ((x-mailer-mh (buffer-substring (match-beginning 1)
-                                             (match-end 1))))
-          (setq mh-x-mailer-string
-                (format "MH-E %s; %s %s; %sEmacs %s"
-                        mh-version (if mh-nmh-flag "nmh" "MH") x-mailer-mh
-                        (if mh-xemacs-flag "X" "GNU ")
-                        (cond ((not mh-xemacs-flag) emacs-version)
-                              ((string-match "[0-9.]*\\( +\([ a-z]+[0-9]+\)\\)?"
-                                             emacs-version)
-                               (match-string 0 emacs-version))
-                              (t (format "%s.%s"
-                                         emacs-major-version
-                                         emacs-minor-version))))))
-        (if (not info-buffer-exists-p)
-            (kill-buffer mh-info-buffer)))))
+    (setq mh-x-mailer-string
+          (format "MH-E %s; %s; %sEmacs %s"
+                  mh-version mh-variant-in-use
+                  (if mh-xemacs-flag "X" "GNU ")
+                  (cond ((not mh-xemacs-flag) emacs-version)
+                        ((string-match "[0-9.]*\\( +\([ a-z]+[0-9]+\)\\)?"
+                                       emacs-version)
+                         (match-string 0 emacs-version))
+                        (t (format "%s.%s" emacs-major-version
+                                   emacs-minor-version))))))
   ;; Insert X-Mailer, but only if it doesn't already exist.
   (save-excursion
     (when (and mh-insert-x-mailer-flag
@@ -1155,25 +1217,31 @@ Sets buffer-local `mh-insert-auto-fields-done-local' when done and inserted
 something.  If NON-INTERACTIVE is non-nil, do not be verbose and only
 attempt matches if `mh-insert-auto-fields-done-local' is nil.
 
-An `identity' entry is skipped if one was already entered manually."
+An `identity' entry is skipped if one was already entered manually.
+
+Return t if fields added; otherwise return nil."
   (interactive)
-  (when (or (not non-interactive) (not mh-insert-auto-fields-done-local))
+  (when (or (not non-interactive)
+            (not mh-insert-auto-fields-done-local))
     (save-excursion
-      (when (and (or (mh-goto-header-field "To:")(mh-goto-header-field "cc:")))
-        (let ((list mh-auto-fields-list))
+      (when (and (or (mh-goto-header-field "To:")
+                     (mh-goto-header-field "cc:")))
+        (let ((list mh-auto-fields-list)
+              (fields-inserted nil))
           (while list
             (let ((regexp (nth 0 (car list)))
                   (entries (nth 1 (car list))))
               (when (mh-regexp-in-field-p regexp "To:" "cc:")
                 (setq mh-insert-auto-fields-done-local t)
+                (setq fields-inserted t)
                 (if (not non-interactive)
-                    (message "Matched for regexp %s" regexp))
+                    (message "Fields for %s added" regexp))
                 (let ((entry-list entries))
                   (while entry-list
                     (let ((field (caar entry-list))
                           (value (cdar entry-list)))
                       (cond
-                       ((equal "identity" field)
+                       ((equal ":identity" field)
                         (when (and (not mh-identity-local)
                                    (assoc value mh-identity-list))
                           (mh-insert-identity value)))
@@ -1181,7 +1249,8 @@ An `identity' entry is skipped if one was already entered manually."
                         (mh-modify-header-field field value
                                                 (equal field "From")))))
                     (setq entry-list (cdr entry-list))))))
-            (setq list (cdr list))))))))
+            (setq list (cdr list)))
+          fields-inserted)))))
 
 (defun mh-modify-header-field (field value &optional overwrite-flag)
   "To header FIELD add VALUE.
@@ -1201,8 +1270,6 @@ If OVERWRITE-FLAG is non-nil then the old value, if present, is discarded."
          (mh-goto-header-end 0)
          (insert field ": " value "\n"))))
 
-(defvar mh-letter-mail-header-end-marker nil)
-
 (defun mh-compose-and-send-mail (draft send-args
                                        sent-from-folder sent-from-msg
                                        to subject cc
@@ -1221,22 +1288,19 @@ for `mh-annotate-msg'.
 CONFIG is the window configuration to restore after sending the letter."
   (pop-to-buffer draft)
   (mh-letter-mode)
-  (mh-insert-auto-fields t)
 
-  ;; mh-identity support
+  ;; Insert identity.
   (if (and (boundp 'mh-identity-default)
            mh-identity-default
            (not mh-identity-local))
       (mh-insert-identity mh-identity-default))
-  (when (and (boundp 'mh-identity-list)
-             mh-identity-list)
-    (mh-identity-make-menu)
-    (easy-menu-add mh-identity-menu))
+  (mh-identity-make-menu)
+  (easy-menu-add mh-identity-menu)
 
-  ;; Extra fields
+  ;; Insert extra fields.
   (mh-insert-x-mailer)
   (mh-insert-x-face)
-  ;; Hide skipped fields
+
   (mh-letter-hide-all-skipped-fields)
 
   (setq mh-sent-from-folder sent-from-folder)
@@ -1264,7 +1328,16 @@ CONFIG is the window configuration to restore after sending the letter."
 This should be the last function called when composing the draft."
   (message "%s" (substitute-command-keys
                  (concat "Type \\[mh-send-letter] to send message, "
-                         "\\[mh-help] for help."))))
+                         "\\[mh-help] for help"))))
+
+(defun mh-ascii-buffer-p ()
+  "Check if current buffer is entirely composed of ASCII.
+The function doesn't work for XEmacs since `find-charset-region' doesn't exist
+there."
+  (loop for charset in (mh-funcall-if-exists
+                        find-charset-region (point-min) (point-max))
+        unless (eq charset 'ascii) return nil
+        finally return t))
 
 ;;;###mh-autoload
 (defun mh-send-letter (&optional arg)
@@ -1273,15 +1346,17 @@ If optional prefix argument ARG is provided, monitor delivery.
 The value of `mh-before-send-letter-hook' is a list of functions to be called,
 with no arguments, before doing anything.
 Run `\\[mh-edit-mhn]' if mhn directives are present; otherwise
-run `\\[mh-mml-to-mime]' if mml directives are present.
-Insert X-Mailer field if variable `mh-insert-x-mailer-flag' is set.
-Insert X-Face field if the file specified by `mh-x-face-file' exists."
+run `\\[mh-mml-to-mime]' if mml directives are present."
   (interactive "P")
   (run-hooks 'mh-before-send-letter-hook)
-  (mh-insert-auto-fields t)
+  (if (and (mh-insert-auto-fields t)
+           mh-auto-fields-prompt-flag
+           (goto-char (point-min)))
+      (if (not (y-or-n-p "Auto fields inserted, send? "))
+          (error "Send aborted")))
   (cond ((mh-mhn-directive-present-p)
          (mh-edit-mhn))
-        ((mh-mml-directive-present-p)
+        ((or (mh-mml-directive-present-p) (not (mh-ascii-buffer-p)))
          (mh-mml-to-mime)))
   (save-buffer)
   (message "Sending...")
@@ -1302,7 +1377,7 @@ Insert X-Face field if the file specified by `mh-x-face-file' exists."
                'iso-latin-1))))
     ;; The default BCC encapsulation will make a MIME message unreadable.
     ;; With nmh use the -mime arg to prevent this.
-    (if (and mh-nmh-flag
+    (if (and (mh-variant-p 'nmh)
              (mh-goto-header-field "Bcc:")
              (mh-goto-header-field "Content-Type:"))
         (setq mh-send-args (format "-mime %s" mh-send-args)))
@@ -1338,7 +1413,8 @@ Insert X-Face field if the file specified by `mh-x-face-file' exists."
 ;;;###mh-autoload
 (defun mh-insert-letter (folder message verbatim)
   "Insert a message into the current letter.
-Removes the header fields according to the variable `mh-invisible-headers'.
+Removes the header fields according to the variable
+`mh-invisible-header-fields-compiled'.
 Prefixes each non-blank line with `mh-ins-buf-prefix', unless
 `mh-yank-from-start-of-msg' is set for supercite in which case supercite is
 used to format the message.
@@ -1355,11 +1431,12 @@ and point after it."
   (save-restriction
     (narrow-to-region (point) (point))
     (let ((start (point-min)))
-      (if (equal message "") (setq message (int-to-string mh-sent-from-msg)))
+      (if (and (equal message "") (numberp mh-sent-from-msg))
+          (setq message (int-to-string mh-sent-from-msg)))
       (insert-file-contents
        (expand-file-name message (mh-expand-file-name folder)))
       (when (not verbatim)
-        (mh-clean-msg-header start mh-invisible-headers mh-visible-headers)
+        (mh-clean-msg-header start mh-invisible-header-fields-compiled nil)
         (goto-char (point-max))         ;Needed for sc-cite-original
         (push-mark)                     ;Needed for sc-cite-original
         (goto-char (point-min))         ;Needed for sc-cite-original
@@ -1373,15 +1450,13 @@ and point after it."
       (skip-chars-forward " ")
       (cond
        ((looking-at "\"\\([^\"\n]+\\)\" \\(<.+>\\)")
-        (format "%s %s %s" (match-string 1)(match-string 2)
-                mh-extract-from-attribution-verb))
+        (format "%s %s " (match-string 1)(match-string 2)))
        ((looking-at "\\([^<\n]+<.+>\\)$")
-        (format "%s %s" (match-string 1) mh-extract-from-attribution-verb))
+        (format "%s " (match-string 1)))
        ((looking-at "\\([^ ]+@[^ ]+\\) +(\\(.+\\))$")
-        (format "%s <%s> %s" (match-string 2)(match-string 1)
-                mh-extract-from-attribution-verb))
+        (format "%s <%s> " (match-string 2)(match-string 1)))
        ((looking-at " *\\(.+\\)$")
-        (format "%s %s" (match-string 1) mh-extract-from-attribution-verb))))))
+        (format "%s " (match-string 1)))))))
 
 ;;;###mh-autoload
 (defun mh-yank-cur-msg ()
@@ -1444,9 +1519,11 @@ yanked message will be deleted."
             (push-mark)                 ;Needed for sc-cite-original
             (goto-char (point-min))     ;Needed for sc-cite-original
             (mh-insert-prefix-string mh-ins-buf-prefix)
-            (if (or (eq 'attribution mh-yank-from-start-of-msg)
-                    (eq 'autoattrib mh-yank-from-start-of-msg))
-                (insert from-attr "\n\n"))
+            (when (or (eq 'attribution mh-yank-from-start-of-msg)
+                      (eq 'autoattrib mh-yank-from-start-of-msg))
+              (insert from-attr)
+              (mh-identity-insert-attribution-verb nil)
+              (insert "\n\n"))
             ;; If the user has selected a region, he has already "edited" the
             ;; text, so leave the cursor at the end of the yanked text. In
             ;; either case, leave a mark at the opposite end of the included
@@ -1572,7 +1649,7 @@ Any match found replaces the text from BEGIN to END."
   (let ((syntax-table (syntax-table)))
     (unwind-protect
         (save-excursion
-          (mh-funcall-if-exists mail-abbrev-make-syntax-table)
+          (mh-mail-abbrev-make-syntax-table)
           (set-syntax-table mail-abbrev-syntax-table)
           (backward-word n)
           (point))
@@ -1593,7 +1670,6 @@ Any match found replaces the text from BEGIN to END."
                           (mh-folder-completion-function folder nil t))))
     (mh-complete-word folder choices beg end)))
 
-;; XXX: This should probably be customizable
 (defvar mh-letter-complete-function-alist
   '((cc . mh-alias-letter-expand-alias)
     (bcc . mh-alias-letter-expand-alias)
@@ -1607,10 +1683,10 @@ Any match found replaces the text from BEGIN to END."
 
 (defun mh-letter-complete (arg)
   "Perform completion on header field or word preceding point.
-Alias completion is done within the mail header on selected fields based on
-the matches in `mh-letter-complete-function-alist'. Elsewhere the function
-designated by `mh-letter-complete-function' is used and given the prefix ARG,
-if present."
+If the field contains addresses (for example, `To:' or `Cc:') or folders (for
+example, `Fcc:') then this function will provide alias completion. Elsewhere,
+this function runs `mh-letter-complete-function' instead and passes the prefix
+ARG, if present."
   (interactive "P")
   (let ((func nil))
     (cond ((not (mh-in-header-p))
@@ -1832,10 +1908,13 @@ Otherwise return the empty string."
 ;;; Build the letter-mode keymap:
 ;;; If this changes, modify mh-letter-mode-help-messages accordingly, above.
 (gnus-define-keys  mh-letter-mode-map
+  " "                   mh-letter-complete-or-space
+  ","                   mh-letter-confirm-address
   "\C-c?"               mh-help
+  "\C-c\C-\\"           mh-fully-kill-draft ;if no C-q
+  "\C-c\C-^"            mh-insert-signature ;if no C-s
   "\C-c\C-c"            mh-send-letter
   "\C-c\C-d"            mh-insert-identity
-  "\C-c\M-d"            mh-insert-auto-fields
   "\C-c\C-e"            mh-edit-mhn
   "\C-c\C-f\C-b"        mh-to-field
   "\C-c\C-f\C-c"        mh-to-field
@@ -1852,31 +1931,38 @@ Otherwise return the empty string."
   "\C-c\C-fs"           mh-to-field
   "\C-c\C-ft"           mh-to-field
   "\C-c\C-i"            mh-insert-letter
-  "\C-c\C-m\C-e"        mh-mml-secure-message-encrypt-pgpmime
+  "\C-c\C-m\C-e"        mh-mml-secure-message-encrypt
   "\C-c\C-m\C-f"        mh-compose-forward
+  "\C-c\C-m\C-g"        mh-mhn-compose-anon-ftp
   "\C-c\C-m\C-i"        mh-compose-insertion
   "\C-c\C-m\C-m"        mh-mml-to-mime
-  "\C-c\C-m\C-s"        mh-mml-secure-message-sign-pgpmime
+  "\C-c\C-m\C-n"        mh-mml-unsecure-message
+  "\C-c\C-m\C-s"        mh-mml-secure-message-sign
+  "\C-c\C-m\C-t"        mh-mhn-compose-external-compressed-tar
   "\C-c\C-m\C-u"        mh-revert-mhn-edit
-  "\C-c\C-me"           mh-mml-secure-message-encrypt-pgpmime
+  "\C-c\C-m\C-x"        mh-mhn-compose-external-type
+  "\C-c\C-mee"          mh-mml-secure-message-encrypt
+  "\C-c\C-mes"          mh-mml-secure-message-signencrypt
   "\C-c\C-mf"           mh-compose-forward
+  "\C-c\C-mg"           mh-mhn-compose-anon-ftp
   "\C-c\C-mi"           mh-compose-insertion
   "\C-c\C-mm"           mh-mml-to-mime
-  "\C-c\C-ms"           mh-mml-secure-message-sign-pgpmime
+  "\C-c\C-mn"           mh-mml-unsecure-message
+  "\C-c\C-mse"          mh-mml-secure-message-signencrypt
+  "\C-c\C-mss"          mh-mml-secure-message-sign
+  "\C-c\C-mt"           mh-mhn-compose-external-compressed-tar
   "\C-c\C-mu"           mh-revert-mhn-edit
+  "\C-c\C-mx"           mh-mhn-compose-external-type
   "\C-c\C-o"            mh-open-line
   "\C-c\C-q"            mh-fully-kill-draft
-  "\C-c\C-\\"           mh-fully-kill-draft ;if no C-q
   "\C-c\C-s"            mh-insert-signature
-  "\C-c\C-^"            mh-insert-signature ;if no C-s
+  "\C-c\C-t"            mh-letter-toggle-header-field-display
   "\C-c\C-w"            mh-check-whom
   "\C-c\C-y"            mh-yank-cur-msg
-  "\C-c\C-t"            mh-letter-toggle-header-field-display
-  " "                   mh-letter-complete-or-space
+  "\C-c\M-d"            mh-insert-auto-fields
   "\M-\t"               mh-letter-complete
   "\t"                  mh-letter-next-header-field-or-indent
-  [backtab]             mh-letter-previous-header-field
-  ","                   mh-letter-confirm-address)
+  [backtab]             mh-letter-previous-header-field)
 
 ;; "C-c /" prefix is used in mh-letter-mode by pgp.el and mailcrypt.el.
 
index 2ce36c8..0cf35b3 100644 (file)
 ;;
 ;; 1. MH-E Customization Groups
 ;;
-;;    These are the customization group definitions. These are organized in a
-;;    logical order. High-level, windows and toolbar, folder, message,
-;;    composing and hooks.
+;;    These are the customization group definitions. Every group has a
+;;    associated manual node. The ordering is alphabetical, except for the
+;;    groups mh-faces and mh-hooks which are last .
 ;;
 ;; 2. MH-E Customization
 ;;
-;;    Here are the actual customization variables. There is a sub-section for
-;;    each group in the MH-E Customization Groups section. Within each
-;;    section, variables are sorted alphabetically. The manual section
-;;    dictates which group a variable should be placed. New variables should
-;;    be placed in the section where they would most likely be defined.
+;;    These are the actual customization variables. There is a sub-section for
+;;    each group in the MH-E Customization Groups section, in the same order,
+;;    separated by page breaks. Within each section, variables are sorted
+;;    alphabetically.
 ;;
-;;    All hooks should be placed in the 'mh-hook group; in addition, add the
-;;    group in which the hook is defined in the manual (or, if it is new,
-;;    where it would be defined). These two actions insures that the hooks
-;;    appear last in each group.
+;; 3. Hooks
+;;
+;;    All hooks must be placed in the mh-hook group; in addition, add the
+;;    group associated with the manual node in which the hook is described.
+;;    Since the mh-hook group appears near the end of this file, the hooks
+;;    will appear at the end of these other groups.
+;;
+;; 4. Faces
+;;
+;;    Create a new face group if necessary; in this case, add the group
+;;    associated with the manual node in which the faces are described to the
+;;    faces' group definition. Since the face groups appear last, the face
+;;    groups will appear at the end of these other groups.
 ;;
-;; 3. Faces
-
 ;;; Change Log:
 
 ;;; Code:
+
 (provide 'mh-customize)
-(require 'mh-utils)
+
+(eval-when-compile (require 'mh-acros))
+(mh-require-cl)
+(require 'mh-loaddefs)
+
+(autoload 'Info-goto-node "info")
+
+(eval-and-compile
+  (defvar mh-xemacs-flag (featurep 'xemacs)
+    "Non-nil means the current Emacs is XEmacs."))
 
 (when mh-xemacs-flag
   (require 'mh-xemacs))
 
-;;;###mh-autoload
 (defun mh-customize (&optional delete-other-windows-flag)
   "Customize MH-E variables.
-With optional argument DELETE-OTHER-WINDOWS-FLAG, other windows in the frame
-are removed."
+If optional argument DELETE-OTHER-WINDOWS-FLAG is non-nil, other windows in
+the frame are removed."
   (interactive "P")
   (customize-group 'mh)
   (when delete-other-windows-flag
     (delete-other-windows)))
 
+\f
+
+;;; For compiler warnings...
+(defvar mh-show-buffer)
+(defvar mh-show-folder-buffer)
+
 ;;; MH-E Customization Groups
 
 (defgroup mh nil
-  "GNU Emacs interface to the MH mail system."
+  "Emacs interface to the MH mail system.
+MH is the Rand Mail Handler. Other implementations include nmh and GNU
+mailutils."
   :link '(custom-manual "(mh-e)Top")
   :group 'mail)
 
-(defgroup mh-toolbar nil
-  "Toolbar configuration."
-  :prefix "mh-"
+(defgroup mh-e '((mh custom-group))     ; Sort of an alias for 'mh group
+  "Emacs interface to the MH mail system.
+MH is the Rand Mail Handler. Other implementations include nmh and GNU
+mailutils."
+  :link '(custom-manual "(mh-e)Top"))
+
+(defgroup mh-alias nil
+  "Aliases."
+  :link '(custom-manual "(mh-e)Aliases")
+  :prefix "mh-alias-"
   :group 'mh)
 
-(defgroup mh-speed nil
-  "Speedbar and folder configuration."
+(defgroup mh-folder nil
+  "Organizing your mail with folders."
   :prefix "mh-"
-  :link '(custom-manual "(mh-e)Customizing Moving Mail")
+  :link '(custom-manual "(mh-e)Organizing")
   :group 'mh)
 
-(defgroup mh-folder nil
-  "Options for controlling scan listing."
+(defgroup mh-folder-selection nil
+  "Folder selection."
   :prefix "mh-"
-  :link '(custom-manual "(mh-e)Customizing Moving Mail")
+  :link '(custom-manual "(mh-e)Folder Selection")
+  :group 'mh)
+
+(defgroup mh-identity nil
+  "Identities."
+  :link '(custom-manual "(mh-e)Identities")
+  :prefix "mh-identity-"
+  :group 'mh)
+
+(defgroup mh-inc nil
+  "Incorporating your mail."
+  :prefix "mh-inc-"
+  :link '(custom-manual "(mh-e)Incorporating Mail")
   :group 'mh)
 
 (defgroup mh-index nil
-  "Indexed searching."
-  :link '(custom-manual "(mh-e)Customizing mh-e")
-  :prefix "mh-"
+  "Searching."
+  :link '(custom-manual "(mh-e)Searching")
+  :prefix "mh-index-"
   :group 'mh)
 
 (defgroup mh-junk nil
-  "Spam handling."
-  :link '(custom-manual "(mh-e)Customizing mh-e")
+  "Dealing with junk mail."
+  :link '(custom-manual "(mh-e)Junk")
   :prefix "mh-junk-"
   :group 'mh)
 
-(defgroup mh-show nil
-  "Message display."
+(defgroup mh-letter nil
+  "Editing a draft."
   :prefix "mh-"
-  :link '(custom-manual "(mh-e)Customizing Reading")
+  :link '(custom-manual "(mh-e)Editing Drafts")
   :group 'mh)
 
-(defgroup mh-faces nil
-  "Faces used in MH-E."
-  :link '(custom-manual "(mh-e)Customizing mh-e")
+(defgroup mh-ranges nil
+  "Ranges."
   :prefix "mh-"
-  :group 'faces
+  :link '(custom-manual "(mh-e)Ranges")
   :group 'mh)
 
-(defgroup mh-letter nil
-  "Composing messages."
+(defgroup mh-scan-line-formats nil
+  "Scan line formats."
+  :link '(custom-manual "(mh-e)Scan Line Formats")
   :prefix "mh-"
-  :link '(custom-manual "(mh-e)Customizing Sending")
   :group 'mh)
 
-(defgroup mh-alias nil
-  "Alias handling."
-  :link '(custom-manual "(mh-e)Customizing mh-e")
-  :prefix "mh-alias-"
+(defgroup mh-sending-mail nil
+  "Sending mail."
+  :prefix "mh-"
+  :link '(custom-manual "(mh-e)Sending Mail")
   :group 'mh)
 
-(defgroup mh-identity nil
-  "Multiple personalities."
-  :link '(custom-manual "(mh-e)Customizing mh-e")
+(defgroup mh-sequences nil
+  "Sequences."
+  :prefix "mh-"
+  :link '(custom-manual "(mh-e)Sequences")
+  :group 'mh)
+
+(defgroup mh-show nil
+  "Reading your mail."
+  :prefix "mh-"
+  :link '(custom-manual "(mh-e)Reading Mail")
+  :group 'mh)
+
+(defgroup mh-speed nil
+  "The speedbar."
+  :prefix "mh-speed-"
+  :link '(custom-manual "(mh-e)Speedbar")
+  :group 'mh)
+
+(defgroup mh-toolbar nil
+  "The toolbar"
+  :link '(custom-manual "(mh-e)Toolbar")
+  :prefix "mh-"
+  :group 'mh)
+
+(defgroup mh-faces nil
+  "Faces used in MH-E."
+  :link '(custom-manual "(mh-e)Top")
   :prefix "mh-"
+  :group 'faces
   :group 'mh)
 
 (defgroup mh-hooks nil
   "MH-E hooks."
-  :link '(custom-manual "(mh-e)Customizing mh-e")
+  :link '(custom-manual "(mh-e)Top")
   :prefix "mh-"
   :group 'mh)
 
 ;;; Faces
 
-(defgroup mh-speed-faces nil
-  "Faces used in speedbar."
-  :link '(custom-manual "(mh-e)Customizing mh-e")
-  :prefix "mh-"
-  :group 'mh-faces
-  :group 'mh-speed)
-
 (defgroup mh-folder-faces nil
   "Faces used in scan listing."
-  :link '(custom-manual "(mh-e)Customizing mh-e")
+  :link '(custom-manual "(mh-e)Organizing")
   :prefix "mh-"
   :group 'mh-faces
-  :group 'mh-folder)
+  :group 'mh-show)
 
 (defgroup mh-index-faces nil
-  "Faces used in indexed searches."
-  :link '(custom-manual "(mh-e)Customizing mh-e")
+  "Faces used in searching."
+  :link '(custom-manual "(mh-e)Searching")
   :prefix "mh-"
   :group 'mh-faces
   :group 'mh-index)
 
+(defgroup mh-letter-faces nil
+  "Faces used in message drafts."
+  :link '(custom-manual "(mh-e)Sending Mail")
+  :prefix "mh-"
+  :group 'mh-faces
+  :group 'mh-letter)
+
 (defgroup mh-show-faces nil
   "Faces used in message display."
-  :link '(custom-manual "(mh-e)Customizing mh-e")
+  :link '(custom-manual "(mh-e)Reading Mail")
   :prefix "mh-"
   :group 'mh-faces
   :group 'mh-show)
 
-(defgroup mh-letter-faces nil
-  "Faces used when composing messages."
-  :link '(custom-manual "(mh-e)Customizing mh-e")
+(defgroup mh-speed-faces nil
+  "Faces used in speedbar."
+  :link '(custom-manual "(mh-e)Speedbar")
   :prefix "mh-"
   :group 'mh-faces
-  :group 'mh-letter)
+  :group 'mh-speed)
 
 \f
 
-;;; MH-E Customization (:group mh)
+;;; Emacs interface to the MH mail system (:group mh)
+(eval-when (compile)
+  (setq mh-variant 'none))
+
+(defcustom mh-variant 'autodetect
+  "*Specifies the variant used by MH-E.
+
+The default setting of this option is `Auto-detect' which means that MH-E will
+automatically choose the first of nmh, MH, or GNU mailutils that it finds in
+the directories listed in `mh-path', `mh-sys-path', and `exec-path'. If, for
+example, you have both nmh and mailutils installed and `mh-variant-in-use' was
+initialized to nmh but you want to use mailutils, then you can set this option
+to `mailutils'.
+
+When this variable is changed, MH-E resets `mh-progs', `mh-lib',
+`mh-lib-progs', `mh-flists-present-flag', and `mh-variant-in-use'
+accordingly."
+  :type `(radio
+          (const :tag "Auto-detect" autodetect)
+          ,@(mapcar (lambda (x) `(const ,(car x))) (mh-variants)))
+  :set (lambda (symbol value)
+         (set-default symbol value)     ;Done in mh-variant-set-variant!
+         (mh-variant-set value))
+  :group 'mh)
 
-;;; Toolbar configuration (:group 'mh-toolbar)
+\f
 
-(defcustom mh-tool-bar-search-function 'mh-search-folder
-  "*Function called by the tool-bar search button.
-See `mh-search-folder' and `mh-index-search' for details."
-  :type '(choice (const mh-search-folder)
-                 (const mh-index-search)
-                 (function :tag "Other function"))
-  :group 'mh-toolbar)
+;;; Aliases (:group 'mh-alias)
 
-;; Functions called from the tool bar
-(defun mh-tool-bar-search (&optional arg)
-  "Interactively call `mh-tool-bar-search-function'.
-Optional argument ARG is not used."
-  (interactive "P")
-  (call-interactively mh-tool-bar-search-function))
+(defcustom mh-alias-completion-ignore-case-flag t
+  "*Non-nil means don't consider case significant in MH alias completion.
+As MH ignores case in the aliases, so too does MH-E. However, you may turn
+this option off to make case significant which can be used to segregate
+completion of your aliases. You might use lowercase for mailing lists and
+uppercase for people."
+  :type 'boolean
+  :group 'mh-alias)
 
-(defun mh-tool-bar-customize ()
-  "Call `mh-customize' from the toolbar."
-  (interactive)
-  (mh-customize t))
+(defcustom mh-alias-expand-aliases-flag nil
+  "*Non-nil means to expand aliases entered in the minibuffer.
+In other words, aliases entered in the minibuffer will be expanded to the full
+address in the message draft. By default, this expansion is not performed."
+  :type 'boolean
+  :group 'mh-alias)
 
-(defun mh-tool-bar-folder-help ()
-  "Visit \"(mh-e)Top\"."
-  (interactive)
-  (Info-goto-node "(mh-e)Top")
-  (delete-other-windows))
+(defcustom mh-alias-flash-on-comma t
+  "*Specify whether to flash address or warn on translation.
+This option controls the behavior when a [comma] is pressed while entering
+aliases or addresses. The default setting flashes the address associated with
+an address in the minibuffer briefly, but does not display a warning if the
+alias is not found."
+  :type '(choice (const :tag "Flash but Don't Warn If No Alias" t)
+                (const :tag "Flash and Warn If No Alias" 1)
+                (const :tag "Don't Flash Nor Warn If No Alias" nil))
+  :group 'mh-alias)
 
-(defun mh-tool-bar-letter-help ()
-  "Visit \"(mh-e)Draft Editing\"."
-  (interactive)
-  (Info-goto-node "(mh-e)Draft Editing")
-  (delete-other-windows))
+(defcustom mh-alias-insert-file nil
+  "*Filename used to store a new MH-E alias.
+The default setting of this option is `Use Aliasfile Profile Component'. This
+option can also hold the name of a file or a list a file names. If this option
+is set to a list of file names, or the `Aliasfile:' profile component contains
+more than one file name, MH-E will prompt for one of them when MH-E adds an
+alias."
+  :type '(choice (const :tag "Use Aliasfile Profile Component" nil)
+                 (file :tag "Alias File")
+                 (repeat :tag "List of Alias Files" file))
+  :group 'mh-alias)
 
-(defmacro mh-tool-bar-reply-generator (function recipient folder-buffer-flag)
-  "Generate FUNCTION that replies to RECIPIENT.
-If FOLDER-BUFFER-FLAG is nil then the function generated
-When INCLUDE-FLAG is non-nil, include message body being replied to."
-  `(defun ,function (&optional arg)
-     ,(format "Reply to \"%s\".\nWhen ARG is non-nil include message in reply."
-              recipient)
-     (interactive "P")
-     ,(if folder-buffer-flag nil '(set-buffer mh-show-folder-buffer))
-     (mh-reply (mh-get-msg-num nil) ,recipient arg)))
+(defcustom mh-alias-insertion-location 'sorted
+  "Specifies where new aliases are entered in alias files.
+This option is set to `Alphabetical' by default. If you organize your alias
+file in other ways, then adding aliases to the `Top' or `Bottom' of your alias
+file might be more appropriate."
+  :type '(choice (const :tag "Alphabetical" sorted)
+                 (const :tag "Top" top)
+                 (const :tag "Bottom" bottom))
+  :group 'mh-alias)
 
-(mh-tool-bar-reply-generator mh-tool-bar-reply-from "from" t)
-(mh-tool-bar-reply-generator mh-show-tool-bar-reply-from "from" nil)
-(mh-tool-bar-reply-generator mh-tool-bar-reply-to "to" t)
-(mh-tool-bar-reply-generator mh-show-tool-bar-reply-to "to" nil)
-(mh-tool-bar-reply-generator mh-tool-bar-reply-all "all" t)
-(mh-tool-bar-reply-generator mh-show-tool-bar-reply-all "all" nil)
+(defcustom mh-alias-local-users t
+  "*If on, local users are added to alias completion.
 
-;; XEmacs has a couple of extra customizations...
-(mh-do-in-xemacs
-  (defcustom mh-xemacs-use-toolbar-flag (if (and (featurep 'toolbar)
-                                                 (featurep 'xpm)
-                                                 (device-on-window-system-p))
-                                            t
-                                          nil)
-    "*If non-nil, use toolbar.
+Aliases are created from `/etc/passwd' entries with a user ID larger than
+a magical number, typically 200. This can be a handy tool on a machine where
+you and co-workers exchange messages. These aliases have the form
+`local.first.last' if a real name is present in the password file.
+Otherwise, the alias will have the form `local.login'.
 
-This will default to t if you are in an environment that supports
-toolbars and xpm."
-    :type 'boolean
-    :group 'mh-toolbar)
+If you're on a system with thousands of users you don't know, and the loading
+of local aliases slows MH-E down noticeably, then turn this option off.
 
-  (defcustom mh-xemacs-toolbar-position (if mh-xemacs-use-toolbar-flag
-                                            'default
-                                          nil)
-    "*Where to put the toolbar.
+This option also takes a string which is executed to generate the password
+file. For example, use \"ypcat passwd\" to obtain the NIS password file."
+  :type '(choice (boolean) (string))
+  :group 'mh-alias)
 
-Valid non-nil values are \"default\", \"top\", \"bottom\", \"left\",
-\"right\".  These match the four edges of the frame, with \"default\"
-meaning \"use the same position as the default-toolbar\".
+(defcustom mh-alias-local-users-prefix "local."
+  "*String prepended to the real names of users from the password file.
+This option can also be set to `Use Login'.
 
-A nil value means do not use a toolbar.
+For example, consider the following password file entry:
 
-If this variable is set to anything other than \"default\" and the
-default-toolbar has a different positional setting from the value of
-this variable, then two toolbars will be displayed.  The MH-E toolbar
-and the default-toolbar."
-    :type '(radio (const :tag "Same position as the \"default-toolbar\""
-                         :value default)
-                  (const :tag "Along the top edge of the frame"
-                         :value top)
-                  (const :tag "Along the bottom edge of the frame"
-                         :value bottom)
-                  (const :tag "Along the left edge of the frame"
-                         :value left)
-                  (const :tag "Along the right edge of the frame"
-                         :value right)
-                  (const :tag "Don't use a toolbar" nil))
-    :group 'mh-toolbar))
+    psg:x:1000:1000:Peter S Galbraith,,,:/home/psg:/bin/tcsh
 
-(defmacro mh-tool-bar-define (defaults &rest buttons)
-  "Define a tool bar for MH-E.
-DEFAULTS is the list of buttons that are present by default. It is a list of
-lists where the sublists are of the following form:
+The following settings of this option will produce the associated aliases:
 
-  (:KEYWORD FUNC1 FUNC2 FUNC3 ...)
+    \"local.\"                  local.peter.galbraith
+    \"\"                        peter.galbraith
+    Use Login                   psg
 
-Here :KEYWORD is one of :folder or :letter. If it is :folder then the default
-buttons in the folder and show mode buffers are being specified. If it is
-:letter then the default buttons in the letter mode are listed. FUNC1, FUNC2,
-FUNC3, ... are the names of the functions that the buttons would execute.
+This option has no effect if variable `mh-alias-local-users' is turned off."
+  :type '(choice (const :tag "Use Login" nil)
+                 (string))
+  :group 'mh-alias)
 
-Each element of BUTTONS is a list consisting of four mandatory items and one
-optional item as follows:
+(defcustom mh-alias-passwd-gecos-comma-separator-flag t
+  "*Non-nil means the gecos field in the password file uses a comma separator.
+In the example in `mh-alias-local-users-prefix', commas are used to separate
+different values within the so-called gecos field. This is a fairly common
+usage. However, in the rare case that the gecos field in your password file is
+not separated by commas and whose contents may contain commas, you can turn
+this option off."
+  :type 'boolean
+  :group 'mh-alias)
 
-  (FUNCTION MODES ICON DOC &optional ENABLE-EXPR)
+\f
 
-where,
+;;; Organizing Your Mail with Folders (:group 'mh-folder)
 
-  FUNCTION is the name of the function that will be executed when the button
-  is clicked.
+(defcustom mh-recenter-summary-flag nil
+  "*Non-nil means to recenter the summary window.
+If this option is turned on, recenter the summary window when the show window
+is toggled off."
+  :type 'boolean
+  :group 'mh-folder)
 
-  MODES is a list of symbols. List elements must be from `folder', `letter' and
-  `sequence'. If `folder' is present then the button is available in the
-  folder and show buffer. If the name of FUNCTION is of the form \"mh-foo\",
-  where foo is some arbitrary string, then we check if the function
-  `mh-show-foo' exists. If it exists then that function is used in the show
-  buffer. Otherwise the original function `mh-foo' is used in the show buffer
-  as well. Presence of `sequence' is handled similar to the above. The only
-  difference is that the button is shown only when the folder is narrowed to a
-  sequence. If `letter' is present in MODES, then the button is available
-  during draft editing and runs FUNCTION when clicked.
+\f
 
-  ICON is the icon that is drawn in the button.
+;;; Folder Selection (:group 'mh-folder-selection)
 
-  DOC is the documentation for the button. It is used in tool-tips and in
-  providing other help to the user. GNU Emacs uses only the first line of the
-  string. So the DOC should be formatted such that the first line is useful and
-  complete without the rest of the string.
-
-  Optional item ENABLE-EXPR is an arbitrary lisp expression. If it evaluates
-  to nil, then the button is deactivated, otherwise it is active. If is in't
-  present then the button is always active."
-  ;; The following variable names have been carefully chosen to make code
-  ;; generation easier. Modifying the names should be done carefully.
-  (let (folder-buttons folder-docs folder-button-setter sequence-button-setter
-        show-buttons show-button-setter show-seq-button-setter
-        letter-buttons letter-docs letter-button-setter
-        folder-defaults letter-defaults
-        folder-vectors show-vectors letter-vectors)
-    (dolist (x defaults)
-      (cond ((eq (car x) :folder) (setq folder-defaults (cdr x)))
-            ((eq (car x) :letter) (setq letter-defaults (cdr x)))))
-    (dolist (button buttons)
-      (unless (and (listp button)
-                   (or (equal (length button) 4) (equal (length button) 5)))
-        (error "Incorrect MH-E tool-bar button specification: %s" button))
-      (let* ((name (nth 0 button))
-             (name-str (symbol-name name))
-             (icon (nth 2 button))
-             (xemacs-icon (mh-do-in-xemacs
-                           (cdr (assoc (intern icon) mh-xemacs-icon-map))))
-             (full-doc (nth 3 button))
-             (doc (if (string-match "\\(.*\\)\n" full-doc)
-                      (match-string 1 full-doc)
-                    full-doc))
-             (enable-expr (or (nth 4 button) t))
-             (modes (nth 1 button))
-             functions show-sym)
-        (when (memq 'letter modes) (setq functions `(:letter ,name)))
-        (when (or (memq 'folder modes) (memq 'sequence modes))
-          (setq functions
-                (append `(,(if (memq 'folder modes) :folder :sequence) ,name)
-                        functions))
-          (setq show-sym
-                (if (string-match "^mh-\\(.*\\)$" name-str)
-                    (intern (concat "mh-show-" (match-string 1 name-str)))
-                  name))
-          (setq functions
-                (append `(,(if (memq 'folder modes) :show :show-seq)
-                          ,(if (fboundp show-sym) show-sym name))
-                        functions)))
-        (do ((functions functions (cddr functions)))
-            ((null functions))
-          (let* ((type (car functions))
-                 (function (cadr functions))
-                 (type1 (substring (symbol-name type) 1))
-                 (vector-list (cond ((eq type :show) 'show-vectors)
-                                    ((eq type :show-seq) 'show-vectors)
-                                    ((eq type :letter) 'letter-vectors)
-                                    (t 'folder-vectors)))
-                 (list (cond ((eq type :letter) 'mh-tool-bar-letter-buttons)
-                             (t 'mh-tool-bar-folder-buttons)))
-                 (key (intern (concat "mh-" type1 "toolbar-" name-str)))
-                 (setter (intern (concat type1 "-button-setter")))
-                 (mbuttons (cond ((eq type :letter) 'letter-buttons)
-                                 ((eq type :show) 'show-buttons)
-                                 ((eq type :show-seq) 'show-buttons)
-                                 (t 'folder-buttons)))
-                 (docs (cond ((eq mbuttons 'letter-buttons) 'letter-docs)
-                             ((eq mbuttons 'folder-buttons) 'folder-docs))))
-            (add-to-list vector-list `[,xemacs-icon ,function t ,full-doc])
-            (add-to-list
-             setter `(when (member ',name ,list)
-                       (mh-funcall-if-exists
-                        tool-bar-add-item ,icon ',function ',key
-                                          :help ,doc :enable ',enable-expr)))
-            (add-to-list mbuttons name)
-            (if docs (add-to-list docs doc))))))
-    (setq folder-buttons (nreverse folder-buttons)
-          letter-buttons (nreverse letter-buttons)
-          show-buttons (nreverse show-buttons)
-          letter-docs (nreverse letter-docs)
-          folder-docs (nreverse folder-docs)
-          folder-vectors (nreverse folder-vectors)
-          show-vectors (nreverse show-vectors)
-          letter-vectors (nreverse letter-vectors))
-    (dolist (x folder-defaults)
-      (unless (memq x folder-buttons)
-        (error "Folder defaults contains unknown button '%s'" x)))
-    (dolist (x letter-defaults)
-      (unless (memq x letter-buttons)
-        (error "Letter defaults contains unknown button '%s'" x)))
-    `(eval-when (compile load eval)
-       (defvar mh-folder-tool-bar-map nil)
-       (defvar mh-folder-seq-tool-bar-map nil)
-       (defvar mh-show-tool-bar-map nil)
-       (defvar mh-show-seq-tool-bar-map nil)
-       (defvar mh-letter-tool-bar-map nil)
-       ;; GNU Emacs tool bar specific code
-       (mh-do-in-gnu-emacs
-         ;; Custom setter functions
-         (defun mh-tool-bar-folder-buttons-set (symbol value)
-           "Construct toolbar for `mh-folder-mode' and `mh-show-mode'."
-           (set-default symbol value)
-           (setq mh-folder-tool-bar-map
-                 (let ((tool-bar-map (make-sparse-keymap)))
-                   ,@(nreverse folder-button-setter)
-                   tool-bar-map))
-           (setq mh-show-tool-bar-map
-                 (let ((tool-bar-map (make-sparse-keymap)))
-                   ,@(nreverse show-button-setter)
-                   tool-bar-map))
-           (setq mh-show-seq-tool-bar-map
-                 (let ((tool-bar-map (copy-keymap mh-show-tool-bar-map)))
-                   ,@(nreverse show-seq-button-setter)
-                   tool-bar-map))
-           (setq mh-folder-seq-tool-bar-map
-                 (let ((tool-bar-map (copy-keymap mh-folder-tool-bar-map)))
-                   ,@(nreverse sequence-button-setter)
-                   tool-bar-map)))
-         (defun mh-tool-bar-letter-buttons-set (symbol value)
-           "Construct toolbar for `mh-letter-mode'."
-           (set-default symbol value)
-           (setq mh-letter-tool-bar-map
-                 (let ((tool-bar-map (make-sparse-keymap)))
-                   ,@(nreverse letter-button-setter)
-                   tool-bar-map))))
-       ;; XEmacs specific code
-       (mh-do-in-xemacs
-         (defvar mh-toolbar-folder-vector-map
-           ',(loop for button in folder-buttons
-                   for vector in folder-vectors
-                   collect (cons button vector)))
-         (defvar mh-toolbar-show-vector-map
-           ',(loop for button in show-buttons
-                   for vector in show-vectors
-                   collect (cons button vector)))
-         (defvar mh-toolbar-letter-vector-map
-           ',(loop for button in letter-buttons
-                   for vector in letter-vectors
-                   collect (cons button vector)))
-         (defvar mh-toolbar-folder-buttons nil)
-         (defvar mh-toolbar-show-buttons nil)
-         (defvar mh-toolbar-letter-buttons nil)
-         ;; Custom setter functions
-         (defun mh-tool-bar-letter-buttons-set (symbol value)
-           (set-default symbol value)
-           (setq mh-toolbar-letter-buttons
-                 (loop for b in value
-                       collect (cdr (assoc b mh-toolbar-letter-vector-map)))))
-         (defun mh-tool-bar-folder-buttons-set (symbol value)
-           (set-default symbol value)
-           (setq mh-toolbar-folder-buttons
-                 (loop for b in value
-                       collect (cdr (assoc b mh-toolbar-folder-vector-map))))
-           (setq mh-toolbar-show-buttons
-                 (loop for b in value
-                       collect (cdr (assoc b mh-toolbar-show-vector-map)))))
-         ;; Initialize toolbar
-         (defun mh-toolbar-init (mode)
-           "Install toolbar in MODE."
-           (let ((toolbar (cond ((eq mode :folder) mh-toolbar-folder-buttons)
-                                ((eq mode :letter) mh-toolbar-letter-buttons)
-                                ((eq mode :show) mh-toolbar-show-buttons)))
-                 (height 37)
-                 (width 40)
-                 (buffer (current-buffer)))
-             (when (and mh-xemacs-toolbar-position mh-xemacs-use-toolbar-flag)
-               (cond
-                ((eq mh-xemacs-toolbar-position 'top)
-                 (set-specifier top-toolbar toolbar buffer)
-                 (set-specifier top-toolbar-visible-p t)
-                 (set-specifier top-toolbar-height height))
-                ((eq mh-xemacs-toolbar-position 'bottom)
-                 (set-specifier bottom-toolbar toolbar buffer)
-                 (set-specifier bottom-toolbar-visible-p t)
-                 (set-specifier bottom-toolbar-height height))
-                ((eq mh-xemacs-toolbar-position 'left)
-                 (set-specifier left-toolbar toolbar buffer)
-                 (set-specifier left-toolbar-visible-p t)
-                 (set-specifier left-toolbar-width width))
-                ((eq mh-xemacs-toolbar-position 'right)
-                 (set-specifier right-toolbar toolbar buffer)
-                 (set-specifier right-toolbar-visible-p t)
-                 (set-specifier right-toolbar-width width))
-                (t (set-specifier default-toolbar toolbar buffer)))))))
-       ;; Declare customizable toolbars
-       (custom-declare-variable
-        'mh-tool-bar-folder-buttons
-        '(list ,@(mapcar (lambda (x) `(quote ,x)) folder-defaults))
-        "Choose buttons to include in MH-E folder/show toolbar."
-        :group 'mh-toolbar :set 'mh-tool-bar-folder-buttons-set
-        :type '(set ,@(loop for x in folder-buttons
-                            for y in folder-docs
-                            collect `(const :tag ,y ,x))))
-       (custom-declare-variable
-        'mh-tool-bar-letter-buttons
-        '(list ,@(mapcar (lambda (x) `(quote ,x)) letter-defaults))
-        "Choose buttons to include in MH-E letter toolbar."
-        :group 'mh-toolbar :set 'mh-tool-bar-letter-buttons-set
-        :type '(set ,@(loop for x in letter-buttons
-                            for y in letter-docs
-                            collect `(const :tag ,y ,x)))))))
-
-(mh-tool-bar-define
-    ((:folder mh-inc-folder mh-mime-save-parts mh-previous-undeleted-msg
-              mh-page-msg  mh-next-undeleted-msg mh-delete-msg mh-refile-msg
-              mh-undo mh-execute-commands mh-toggle-tick mh-reply
-              mh-alias-grab-from-field mh-send mh-rescan-folder
-              mh-tool-bar-search mh-visit-folder
-              mh-tool-bar-customize mh-tool-bar-folder-help mh-widen)
-     (:letter mh-send-letter mh-compose-insertion ispell-message save-buffer
-              undo kill-region menu-bar-kill-ring-save yank mh-fully-kill-draft
-              mh-tool-bar-customize mh-tool-bar-letter-help))
-  ;; Folder/Show buffer buttons
-  (mh-inc-folder (folder) "mail"
-    "Incorporate new mail in Inbox
-This button runs `mh-inc-folder' which drags any
-new mail into your Inbox folder.")
-  (mh-mime-save-parts (folder) "attach"
-    "Save MIME parts from this message
-This button runs `mh-mime-save-parts' which saves a message's
-different parts into separate files.")
-  (mh-previous-undeleted-msg (folder) "left_arrow"
-    "Go to the previous undeleted message
-This button runs `mh-previous-undeleted-msg'")
-  (mh-page-msg (folder) "page-down"
-    "Page the current message forwards\nThis button runs `mh-page-msg'")
-  (mh-next-undeleted-msg (folder) "right_arrow"
-    "Go to the next undeleted message\nThe button runs `mh-next-undeleted-msg'")
-  (mh-delete-msg (folder) "close"
-    "Mark this message for deletion\nThis button runs `mh-delete-msg'")
-  (mh-refile-msg (folder) "refile"
-    "Refile this message\nThis button runs `mh-refile-msg'")
-  (mh-undo (folder) "undo" "Undo last operation\nThis button runs `undo'")
-  (mh-execute-commands (folder) "execute"
-    "Perform moves and deletes\nThis button runs `mh-execute-commands'")
-  (mh-toggle-tick (folder) "highlight"
-    "Toggle tick mark\nThis button runs `mh-toggle-tick'")
-  (mh-toggle-showing (folder) "show"
-    "Toggle showing message\nThis button runs `mh-toggle-showing'")
-  (mh-tool-bar-reply-from (folder) "reply-from" "Reply to \"from\"")
-  (mh-tool-bar-reply-to (folder) "reply-to" "Reply to \"to\"")
-  (mh-tool-bar-reply-all (folder) "reply-all" "Reply to \"all\"")
-  (mh-reply (folder) "mail/reply2"
-    "Reply to this message\nThis button runs `mh-reply'")
-  (mh-alias-grab-from-field (folder) "alias"
-    "Grab From alias\nThis button runs `mh-alias-grab-from-field'"
-    (mh-alias-from-has-no-alias-p))
-  (mh-send (folder) "mail_compose"
-    "Compose new message\nThis button runs `mh-send'")
-  (mh-rescan-folder (folder) "rescan"
-    "Rescan this folder\nThis button runs `mh-rescan-folder'")
-  (mh-pack-folder (folder) "repack"
-    "Repack this folder\nThis button runs `mh-pack-folder'")
-  (mh-tool-bar-search (folder) "search"
-    "Search\nThis button runs `mh-tool-bar-search-function'")
-  (mh-visit-folder (folder) "fld_open"
-    "Visit other folder\nThis button runs `mh-visit-folder'")
-  ;; Letter buffer buttons
-  (mh-send-letter (letter) "mail_send" "Send this letter")
-  (mh-compose-insertion (letter) "attach" "Insert attachment")
-  (ispell-message (letter) "spell" "Check spelling")
-  (save-buffer (letter) "save" "Save current buffer to its file")
-  (undo (letter) "undo" "Undo last operation")
-  (kill-region (letter) "cut"
-    "Cut (kill) text in region between mark and current position")
-  (menu-bar-kill-ring-save (letter) "copy"
-    "Copy text in region between mark and current position")
-  (yank (letter) "paste" "Paste (yank) text cut or copied earlier")
-  (mh-fully-kill-draft (letter) "close" "Kill this draft")
-  ;; Common buttons
-  (mh-tool-bar-customize (folder letter) "preferences" "MH-E Preferences")
-  (mh-tool-bar-folder-help (folder) "help"
-    "Help! (general help)\nThis button runs `Info-goto-node'")
-  (mh-tool-bar-letter-help (letter) "help"
-    "Help! (general help)\nThis button runs `Info-goto-node'")
-  ;; Folder narrowed to sequence buttons
-  (mh-widen (sequence) "widen"
-    "Widen from the sequence\nThis button runs `mh-widen'"))
-
-\f
-
-;;; Speedbar and folder configuration (:group 'mh-speed)
-
-(defcustom mh-large-folder 200
-  "The number of messages that indicates a large folder.
-If a folder is deemed to be large, that is the number of messages in it exceed
-this value, then confirmation is needed when it is visited. Even when
-`mh-show-threads-flag' is non-nil, the folder is not automatically threaded, if
-it is large. If set to nil all folders are treated as if they are small."
-  :type '(choice (const :tag "No limit") integer)
-  :group 'mh-speed)
-
-(defcustom mh-speed-flists-interval 60
-  "Time between calls to flists in seconds.
-If 0, flists is not called repeatedly."
-  :type 'integer
-  :group 'mh-speed)
-
-(defcustom mh-speed-run-flists-flag t
-  "Non-nil means flists is used.
-If non-nil, flists is executed every `mh-speed-flists-interval' seconds to
-update the display of the number of unseen and total messages in each folder.
-If resources are limited, this can be set to nil and the speedbar display can
-be updated manually with the \\[mh-speed-flists] command."
-  :type 'boolean
-  :group 'mh-speed)
-
-\f
-
-;;; Options for controlling scan listing (:group 'mh-folder)
-
-(defcustom mh-adaptive-cmd-note-flag t
-  "*Non-nil means that the message number width is determined dynamically.
-This is done once when a folder is first opened by running scan on the last
-message of the folder. The message number for the last message is extracted
-and its width calculated. This width is used when calling `mh-set-cmd-note'.
-
-If you prefer fixed-width message numbers, set this variable to nil and call
-`mh-set-cmd-note' with the width specified by the scan format in
-`mh-scan-format-file'. For example, the default width is 4, so you would use
-\"(mh-set-cmd-note 4)\" if `mh-scan-format-file' were nil."
-  :type 'boolean
-  :group 'mh-folder)
+(defcustom mh-default-folder-for-message-function nil
+  "Function to select a default folder for refiling or `Fcc'.
+The current buffer is set to the message being refiled with point at the start
+of the message. This function should return the default folder as a string
+with a leading `+' sign. It can also return nil so that the last folder name
+is used as the default, or an empty string to suppress the default entirely."
+  :type 'function
+  :group 'mh-folder-selection)
 
 (defcustom mh-default-folder-list nil
-  "*Alist of addresses and folders.
-When refiling messages, these folders are the default that is provided if the
-sender (or recipient if the Check Recipient checkbox has been selected) has
-the associated address, a regexp. The first entry to match will be used, so
-order them according to the wanted priority. You do not need to list your
-aliases here as that lookup is already performed.
+  "*List of addresses and folders.
+The folder name associated with the first address found in this list is used
+as the default for `mh-refile-msg' and similar functions. 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.
 
 See `mh-prompt-for-refile-folder' and `mh-folder-from-address' for more
 information."
   :type '(repeat (list (regexp :tag "Address")
                        (string :tag "Folder")
                        (boolean :tag "Check Recipient")))
-  :group 'mh-folder)
+  :group 'mh-folder-selection)
 
 (defcustom mh-default-folder-must-exist-flag t
   "*Non-nil means guessed folder name must exist to be used.
-If this variable is t, then the guessed name is only used if the folder
-already exists\; if the folder doesn't exist, then the last folder name used
-is suggested. This is useful if you get mail from various people for whom you
-have an alias, but file them all in the same project folder.
+If the derived folder does not exist, and this option is on, then the last
+folder name used is suggested. This is useful if you get mail from various
+people for whom you have an alias, but file them all in the same project
+folder.
+
 See `mh-prompt-for-refile-folder' and `mh-folder-from-address' for more
 information."
   :type 'boolean
-  :group 'mh-folder)
+  :group 'mh-folder-selection)
 
 (defcustom mh-default-folder-prefix ""
-  "*Prefix used for guessed folder names.
-This can be used to put folders associated with your aliases in a sub-folder
-so as to not clutter your mail directory.
+  "*Prefix used for folder names generated from aliases.
+The prefix is used to prevent clutter in your mail directory.
+
 See `mh-prompt-for-refile-folder' and `mh-folder-from-address' for more
 information."
   :type 'string
-  :group 'mh-folder)
+  :group 'mh-folder-selection)
 
-(defcustom mh-inc-prog "inc"
-  "*Program to run to incorporate new mail into a folder.
-Normally \"inc\".  This file is searched for relative to
-the `mh-progs' directory unless it is an absolute pathname."
-  :type 'string
-  :group 'mh-folder)
-
-(defcustom mh-inc-spool-list nil
-  "*Alist of alternate spool files, corresponding folders and keybindings.
-Here's an example. Suppose you have subscribed to the MH-E devel mailing
-list. You could filter its mail into a separate spool file named
-~/mail/mh-e using Procmail and a .procmailrc entry like:
-
-MAILDIR=$HOME/mail      #you'd better make sure it exists
-:0:
-* ^From mh-e-devel-admin@lists.sourceforge.net
-mh-e
-
-If you wanted to incorporate that spool file into an MH folder called
-mh-e by pressing \"I m\" in folder-mode or by `M-x mh-inc-spool-mh-e',
-you would setup  `mh-inc-spool-list' with an entry:
-
- Spool file:  ~/mail/mh-e
- Folder:      mh-e
- Key binding: m
-
-Then, you could also install `xbuffy' and configure an extra mailbox like so:
-
-box ~/mail/mh-e
- title mh-e
- origMode
- polltime 10
- headertime 0
- command gnudoit -q '(mh-inc-spool-mh-e)'
-
-Note that the entry above uses the gnuserv package to communicate the
-command `mh-inc-spool-mh-e' to Emacs. It will incorporate the spool file
-when clicking the xbuffy box with the middle mouse button."
-  :type '(repeat (list (file :tag "Spool file")
-                       (string :tag "Folder")
-                       (character :tag "Key binding")))
-  :set 'mh-inc-spool-list-set
-  :group 'mh-folder)
-
-(defcustom mh-interpret-number-as-range-flag t
-  "Non-nil means interpret a number as a range.
-If the variable is non-nil, and you use an integer, N, when asked for a
-range to scan, then MH-E uses the range \"last:N\"."
-  :type 'boolean
-  :group 'mh-folder)
-
-(defcustom mh-lpr-command-format "lpr -J '%s'"
-  "*Format for Unix command that prints a message.
-The string should be a Unix command line, with the string '%s' where
-the job's name (folder and message number) should appear.  The formatted
-message text is piped to this command when you type \\<mh-folder-mode-map>`\\[mh-print-msg]'."
-  :type 'string
-  :group 'mh-folder)
-
-(defcustom mh-mime-save-parts-default-directory t
-  "Default directory to use for `mh-mime-save-parts'.
-If nil, prompt and set for next time the command is used during same session.
-If t, prompt always"
-  :type '(choice (const :tag "Prompt the first time" nil)
-                 (const :tag "Prompt always" t)
-                 directory)
-  :group 'mh-folder)
-
-(defcustom mh-print-background-flag nil
-  "*Non-nil means messages should be printed in the background.
-WARNING: do not delete the messages until printing is finished;
-otherwise, your output may be truncated."
-  :type 'boolean
-  :group 'mh-folder)
+\f
 
-(defcustom mh-recenter-summary-flag nil
-  "*Non-nil means to recenter the summary window.
-Recenter the summary window when the show window is toggled off if non-nil."
-  :type 'boolean
-  :group 'mh-folder)
+;;; Identities (:group 'mh-identity)
 
-(defcustom mh-recursive-folders-flag nil
-  "*Non-nil means that commands which operate on folders do so recursively."
-  :type 'boolean
-  :group 'mh-folder)
+(defcustom mh-identity-list nil
+  "*List of identities.
+
+Each element consists of an identity label, and a collection of header fields
+and a signature to insert if the identity is selected (see
+`mh-identity-default', `mh-insert-identity' and the `Identity' menu in a
+MH-Letter buffer). The `Value Menu' contains the common header fields `From'
+and `Organization'. Other header fields may be added using the `Other Field'
+menu item. The `Signature' menu item is used to insert a signature with
+`mh-insert-signature'. The `GPG Key ID' menu item is used to specify a
+different key to sign or encrypt messages."
+  :type '(repeat (list :tag ""
+                       (string :tag "Label")
+                       (repeat :tag "Add at least one item below"
+                               (choice
+                                (cons :tag "From Field"
+                                      (const "From")
+                                      (string :tag "Value"))
+                                (cons :tag "Organization Field"
+                                      (const "Organization")
+                                      (string :tag "Value"))
+                                (cons :tag "Other Field"
+                                      (string :tag "Field")
+                                      (string :tag "Value"))
+                                (cons :tag "Attribution Verb"
+                                      (const ":attribution-verb")
+                                      (string :tag "Value"))
+                                (cons :tag "Signature"
+                                      (const :tag "Signature"
+                                             ":signature")
+                                      (choice
+                                       (const :tag "mh-signature-file-name"
+                                              nil)
+                                       (file)
+                                       (function)))
+                                (cons :tag "GPG Key ID"
+                                      (const :tag "GPG Key ID"
+                                             ":pgg-default-user-id")
+                                      (string :tag "Value"))))))
+  :set 'mh-identity-list-set
+  :group 'mh-identity)
 
-;;; If `mh-unpropagated-sequences' becomes a defcustom, add the following tot
-;;; he docstring: "Additional sequences that should not to be preserved can be
-;;; specified by setting `mh-unpropagated-sequences' appropriately." XXX
+(defcustom mh-auto-fields-list nil
+  "List of recipients for which header lines are automatically inserted.
+Each element consists of the recipient, which is a regular expression, and a
+collection of header fields and identities to insert if the message is sent to
+this recipient. The `Value Menu' contains the common header fields `Fcc' and
+`Mail-Followup-To'. Other header fields may be added using the `Other Field'
+menu item. The `Identity' menu item is used to insert entire identities with
+`mh-insert-identity'."
+  :type `(repeat
+          (list :tag ""
+                (string :tag "Recipient")
+                (repeat :tag "Add at least one item below"
+                        (choice
+                         (cons :tag "Identity"
+                               (const ":identity")
+                               ,(append
+                                 '(radio)
+                                 (mapcar
+                                  (function (lambda (arg) `(const ,arg)))
+                                  (mapcar 'car mh-identity-list))))
+                         (cons :tag "Fcc Field"
+                               (const "fcc")
+                               (string :tag "Value"))
+                         (cons :tag "Mail-Followup-To Field"
+                               (const "Mail-Followup-To")
+                               (string :tag "Value"))
+                         (cons :tag "Other Field"
+                                 (string :tag "Field")
+                                 (string :tag "Value"))))))
+  :group 'mh-identity)
 
-(defcustom mh-refile-preserves-sequences-flag t
-  "*Non-nil means that sequences are preserved when messages are refiled.
-If this variable is non-nil and a message belonging to a sequence other than
-cur or Previous-Sequence (see mh-profile 5) is refiled then it is put in the
-same sequence in the destination folder."
+(defcustom mh-auto-fields-prompt-flag t
+  "*Non-nil means to prompt before sending if fields inserted.
+See `mh-auto-fields-list'."
   :type 'boolean
-  :group 'mh-folder)
-
-(defcustom mh-scan-format-file t
-  "Specifies the format file to pass to the scan program.
-If t, the format string will be taken from the either `mh-scan-format-mh'
-or `mh-scan-format-nmh' depending on whether MH or nmh is in use.
-If nil, the default scan output will be used.
+  :group 'mh-identity)
 
-If you customize the scan format, you may need to modify a few variables
-containing regexps that MH-E uses to identify specific portions of the output.
-Use `M-x apropos RET mh-scan.*regexp' to obtain a list of these variables. You
-may also have to call `mh-set-cmd-note' with the width of your message
-numbers. See also `mh-adaptive-cmd-note-flag'."
-  :type '(choice (const :tag "Use MH-E scan format" t)
-                 (const :tag "Use default scan format" nil)
-                 (file  :tag "Specify a scan format file"))
-  :group 'mh-folder)
+(defcustom mh-identity-default nil
+  "Default identity to use when `mh-letter-mode' is called."
+  :type (append
+         '(radio)
+         (cons '(const :tag "None" nil)
+               (mapcar (function (lambda (arg) `(const ,arg)))
+                       (mapcar 'car mh-identity-list))))
+  :group 'mh-identity)
 
-(defcustom mh-scan-prog "scan"
-  "*Program to run to generate one-line-per-message listing of a folder.
-Normally \"scan\" or a file name linked to scan.  This file is searched
-for relative to the `mh-progs' directory unless it is an absolute pathname."
-  :type 'string
-  :group 'mh-folder)
-(make-variable-buffer-local 'mh-scan-prog)
+(defcustom mh-identity-handlers
+  '(("default" . mh-identity-handler-bottom)
+    ("from" . mh-identity-handler-top)
+    (":attribution-verb" . mh-identity-handler-attribution-verb)
+    (":signature" . mh-identity-handler-signature)
+    (":pgg-default-user-id" . mh-identity-handler-gpg-identity))
+  "Handler functions for fields in `mh-identity-list'.
+This is an alist of fields (strings) and handlers (functions). Strings are
+lowercase. Use \":signature\" for Signature and \":pgg-default-user-id\" for
+GPG Key ID. The function associated with the string \"default\" is used if no
+other functions are appropriate. For this reason, don't name a header field
+\"Default\"."
+  :type '(repeat (cons (string :tag "Field") function))
+  :group 'mh-identity)
 
-(defcustom mh-show-threads-flag nil
-  "Non-nil means new folders start in threaded mode.
-Threading large number of messages can be time consuming. So if the flag is
-non-nil then threading will be done only if the number of messages being
-threaded is less than `mh-large-folder'."
-  :type 'boolean
-  :group 'mh-folder)
+\f
 
-(defcustom mh-store-default-directory nil
-  "*Last directory used by \\[mh-store-msg]; default for next store.
-A directory name string, or nil to use current directory."
-  :type '(choice (const :tag "Current" nil)
-                 directory)
-  :group 'mh-folder)
+;;; Incorporating Your Mail (:group 'mh-inc)
 
-(defcustom mh-tick-seq 'tick
-  "The name of the MH tick sequence."
-  :type '(choice (const :tag "Disable ticking" nil)
-                 symbol)
-  :group 'mh-folder)
+(defcustom mh-inc-prog "inc"
+  "*Program to run to incorporate new mail into a folder.
+Normally \"inc\". This program is relative to the `mh-progs' directory unless
+it is an absolute pathname."
+  :type 'string
+  :group 'mh-inc)
 
-(defcustom mh-update-sequences-after-mh-show-flag t
-  "*Non-nil means `mh-update-sequence' is called from `mh-show-mode'.
-If set, `mh-update-sequence' is run every time a message is shown, telling
-MH or nmh that this is your current message.  It's useful, for example, to
-display MIME content using \"M-! mhshow RET\""
-  :type 'boolean
-  :group 'mh-folder)
+(defcustom mh-inc-spool-list nil
+  "*Alist of alternate spool files, corresponding folders and keybindings.
+This option will be described by example.
+
+Suppose you have subscribed to the mh-e-devel mailing list and you use
+procmail to filter its mail into `~/mail/mh-e' with the following
+`.procmailrc' recipe:
+
+    MAILDIR=$HOME/mail
+    :0:
+    * ^From mh-e-devel-admin@lists.sourceforge.net
+    mh-e
+
+If you wanted to incorporate that spool file into an MH folder called mh-e
+with the \"I m\" or \\[mh-inc-spool-mh-e] commands, you would use the
+following:
+
+    Spool File:  ~/mail/mh-e
+    Folder:      mh-e
+    Key Binding: m
+
+Then, you could also install `xbuffy' and configure an extra mailbox using the
+gnuserv package to run the `mh-inc-spool-mh-e' command in Emacs:
+
+    box ~/mail/mh-e
+        title mh-e
+        origMode
+        polltime 10
+        headertime 0
+        command gnudoit -q '(mh-inc-spool-mh-e)'
+
+To incorporate the spool file, click the xbuffy box with the middle mouse
+button."
+  :type '(repeat (list (file :tag "Spool File")
+                       (string :tag "Folder")
+                       (character :tag "Key Binding")))
+  :set 'mh-inc-spool-list-set
+  :group 'mh-inc)
 
 \f
 
-;;; Indexed searching (:group 'mh-index)
+;;; Searching (:group 'mh-index)
 
 (defcustom mh-index-new-messages-folders t
-  "Folders searched for `mh-unseen-seq'.
-If t, then `mh-inbox' is searched. If nil, all the top level folders are
-searched. Otherwise the list of folders specified as strings are searched.
+  "Folders searched for the `unseen' sequence.
+This option can be set to `Inbox' to search the `+inbox' folder or `All' to
+search all of the top level folders. Otherwise, list the folders that should
+be searched with the `Choose Folders' menu item.
+
 See also `mh-recursive-folders-flag'."
   :group 'mh-index
   :type '(choice (const :tag "Inbox" t)
                  (const :tag "All" nil)
-                 (repeat :tag "Choose folders" (string :tag "Folder"))))
+                 (repeat :tag "Choose Folders" (string :tag "Folder"))))
 
 (defcustom mh-index-program nil
   "Indexing program that MH-E shall use.
-The possible choices are swish++, swish-e, mairix, namazu, glimpse, pick and
-grep. By default this variable is nil which means that the programs are tried
-in order and the first one found is used.
+The default setting of this option is `Auto-detect' which means that MH-E will
+automatically choose one of swish++, swish-e, mairix, namazu, pick and grep in
+that order. If, for example, you have both swish++ and mairix installed and
+you want to use mairix, then you can set this option to `mairix'.
 
 More information about setting up an indexing program to use with MH-E can be
 found in the documentation of `mh-index-search'."
@@ -850,33 +621,34 @@ found in the documentation of `mh-index-search'."
                  (const :tag "swish-e" swish)
                  (const :tag "mairix" mairix)
                  (const :tag "namazu" namazu)
-                 (const :tag "glimpse" glimpse)
                  (const :tag "pick" pick)
                  (const :tag "grep" grep))
   :group 'mh-index)
 
 (defcustom mh-index-ticked-messages-folders t
   "Folders searched for `mh-tick-seq'.
-If t, then `mh-inbox' is searched. If nil, all the top level folders are
-searched. Otherwise the list of folders specified as strings are searched.
+This option can be set to `Inbox' to search the `+inbox' folder or `All' to
+search all of the top level folders. Otherwise, list the folders that should
+be searched with the `Choose Folders' menu item.
+
 See also `mh-recursive-folders-flag'."
   :group 'mh-index
   :type '(choice (const :tag "Inbox" t)
                  (const :tag "All" nil)
-                 (repeat :tag "Choose folders" (string :tag "Folder"))))
+                 (repeat :tag "Choose Folders" (string :tag "Folder"))))
 
 \f
 
-;;; Spam Handling (:group 'mh-junk)
+;;; Dealing with Junk Mail (:group 'mh-junk)
 
 ;; Spam fighting program chosen
 (defvar mh-junk-choice nil)
 
 ;; Available spam filter interfaces
 (defvar mh-junk-function-alist
-  '((bogofilter mh-bogofilter-blacklist mh-bogofilter-whitelist)
-    (spamprobe mh-spamprobe-blacklist mh-spamprobe-whitelist)
-    (spamassassin mh-spamassassin-blacklist mh-spamassassin-whitelist))
+  '((spamassassin mh-spamassassin-blacklist mh-spamassassin-whitelist)
+    (bogofilter mh-bogofilter-blacklist mh-bogofilter-whitelist)
+    (spamprobe mh-spamprobe-blacklist mh-spamprobe-whitelist))
   "Available choices of spam programs to use.
 This is an alist. For each element there are functions that blacklist a message
 as spam and whitelist a message incorrectly classified as spam.")
@@ -894,28 +666,348 @@ bound to the new value of `mh-junk-program'. The function sets the variable
                   finally return (car element)))))
 
 ;; User customizable variables
-(defcustom mh-junk-mail-folder nil
-  "Folder to put spam mail in.
-If nil then the spam is deleted."
-  :type '(choice (const :tag "Delete spam" nil)
-                 (string :tag "Spam folder"))
+(defcustom mh-junk-disposition nil
+  "Disposition of junk mail."
+  :type '(choice (const :tag "Delete Spam" nil)
+                 (string :tag "Spam Folder"))
+  :group 'mh-junk)
+
+(defcustom mh-junk-program nil
+  "Spam program that MH-E should use.
+The default setting of this option is `Auto-detect' which means that MH-E will
+automatically choose one of SpamAssassin, Bogofilter, or SpamProbe in that
+order. If, for example, you have both SpamAssassin and Bogofilter installed
+and you want to use BogoFilter, then you can set this option to `Bogofilter'."
+  :type '(choice (const :tag "Auto-detect" nil)
+                 (const :tag "SpamAssassin" spamassassin)
+                 (const :tag "Bogofilter" bogofilter)
+                 (const :tag "SpamProbe" spamprobe))
+  :set 'mh-junk-choose
   :group 'mh-junk)
 
-(defcustom mh-junk-program nil
-  "Spam program that MH-E shall use.
-The possible choices are bogofilter, spamprobe, and spamassassin. By default
-this variable is nil which means that the programs are tried in order and the
-first one found is used."
-  :type '(choice (const :tag "auto-detect" nil)
-                 (const :tag "bogofilter" bogofilter)
-                 (const :tag "spamprobe" spamprobe)
-                 (const :tag "spamassassin" spamassassin))
-  :set 'mh-junk-choose
-  :group 'mh-junk)
+(defcustom mh-junk-background nil
+  "If on, spam programs are run in background.
+By default, the programs are run in the foreground, but this can be slow when
+junking large numbers of messages. If you have enough memory or don't junk
+that many messages at the same time, you might try turning on this option."
+  :type '(choice (const :tag "Off" nil)
+                 (const :tag "On" 0))
+  :group 'mh-junk)
+
+\f
+
+;;; Editing a Draft (:group 'mh-letter)
+
+(defcustom mh-mml-method-default (if mh-gnus-pgp-support-flag "pgpmime" "none")
+  "Default method to use in security directives."
+  :type '(choice (const :tag "PGP (MIME)" "pgpmime")
+                 (const :tag "PGP" "pgp")
+                 (const :tag "S/MIME" "smime")
+                 (const :tag "None" "none"))
+  :group 'mh-letter)
+
+(defcustom mh-compose-forward-as-mime-flag t
+  "Non-nil means that messages are forwarded as a MIME part."
+  :type 'boolean
+  :group 'mh-letter)
+
+(defcustom mh-compose-insertion (if (locate-library "mml") 'gnus 'mhn)
+  "Type of MIME message directives in messages.
+
+By default, this option is set to `Gnus' if it is supported. This option can
+also be set manually to `mhn' if mhn directives are preferred."
+  :type '(choice (const :tag "Gnus" gnus)
+                 (const :tag "mhn"  mhn))
+  :group 'mh-letter)
+
+(defcustom mh-compose-skipped-header-fields
+  '("From" "Organization" "References" "In-Reply-To"
+    "X-Face" "Face" "X-Image-URL" "X-Mailer")
+  "List of header fields to skip over when navigating in draft."
+  :type '(repeat (string :tag "Field"))
+  :group 'mh-letter)
+
+(defcustom mh-compose-space-does-completion-flag nil
+  "*Non-nil means that <SPC> does completion in message header."
+  :type 'boolean
+  :group 'mh-letter)
+
+(defcustom mh-delete-yanked-msg-window-flag nil
+  "*Non-nil means delete any window displaying the message.
+If this option is on, yanking the current message into a draft letter with
+\\<mh-letter-mode-map>\\[mh-yank-cur-msg] deletes any windows displaying the
+message."
+  :type 'boolean
+  :group 'mh-letter)
+
+(defcustom mh-extract-from-attribution-verb "wrote:"
+  "*Verb to use for attribution when a message is yanked by \\<mh-letter-mode-map>\\[mh-yank-cur-msg]."
+  :type '(choice (const "wrote:")
+                 (const "a Ã©crit:")
+                 (const "schrieb:")
+                 (string :tag "Custom String"))
+  :group 'mh-letter)
+
+(defcustom mh-ins-buf-prefix "> "
+  "*String to put before each non-blank line of a yanked or inserted message.
+Used when the message is inserted into an outgoing letter
+by \\<mh-letter-mode-map>\\[mh-insert-letter] or \\[mh-yank-cur-msg]."
+  :type 'string
+  :group 'mh-letter)
+
+(defcustom mh-insert-x-mailer-flag t
+  "*Non-nil means append an X-Mailer field to the header."
+  :type 'boolean
+  :group 'mh-letter)
+
+(defcustom mh-letter-complete-function 'ispell-complete-word
+  "*Function to call when completing outside of address or folder fields.
+By default, this is set to `ispell-complete-word'."
+  :type '(choice function (const nil))
+  :group 'mh-letter)
+
+(defcustom mh-letter-fill-column 72
+  "*Fill column to use in `mh-letter-mode'.
+This is usually less than in other text modes because email messages get
+quoted by some prefix (sometimes many times) when they are replied to,
+and it's best to avoid quoted lines that span more than 80 columns."
+  :type 'integer
+  :group 'mh-letter)
+
+(defcustom mh-reply-show-message-flag t
+  "*Non-nil means the show buffer is displayed using \\<mh-letter-mode-map>\\[mh-reply].
+
+The setting of this variable determines whether the MH `show-buffer' is
+displayed with the current message when using `mh-reply' without a prefix
+argument.  Set it to nil if you already include the message automatically
+in your draft using
+ repl: -filter repl.filter
+in your ~/.mh_profile file."
+  :type 'boolean
+  :group 'mh-letter)
+
+(defcustom mh-signature-file-name "~/.signature"
+  "*Source of user's signature.
+
+By default, the text of your signature is taken from the file `~/.signature'.
+You can read from other files by changing this option. This file may contain a
+vCard in which case an attachment is added with the vCard.
+
+This option may also be a symbol, in which case that function is called. You
+may not want a signature separator to be added for you; instead you may want
+to insert one yourself. Variables that you may find useful to do this include
+`mh-signature-separator' (when inserting a signature separator) and
+`mh-signature-separator-regexp' (for finding said separator). The function
+`mh-signature-separator-p', which reports t if the buffer contains a
+separator, may be useful as well.
+
+The signature is inserted into your message with the command
+\\<mh-letter-mode-map>\\[mh-insert-signature] or with the `mh-identity-list'
+option."
+  :type 'file
+  :group 'mh-letter)
+
+(defcustom mh-signature-separator-flag t
+  "*Non-nil means a signature separator should be inserted.
+It is not recommended that you change this option since various mail user
+agents, including MH-E, use the separator to present the signature
+differently, and to suppress the signature when replying or yanking a letter
+into a draft."
+  :type 'boolean
+  :group 'mh-letter)
+
+(defcustom mh-x-face-file "~/.face"
+  "*File containing face header field to insert in outgoing mail.
+
+If the file starts with either of the strings `X-Face:', `Face:' or
+`X-Image-URL:' then the contents are added to the message header verbatim.
+Otherwise it is assumed that the file contains the value of the `X-Face:'
+header field.
+
+The `X-Face:' header field, which is a low-resolution, black and white image,
+can be generated using the `compface' command, which can be obtained from
+ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.Z. The \"Online
+X-Face Convertor\" at http://www.dairiki.org/xface/ is a useful resource for
+quick conversion of images into `X-Face:' header fields.
+
+Use the `make-face' script (http://quimby.gnus.org/circus/face/make-face) to
+convert a JPEG image to the higher resolution, color, `Face:' header field.
+
+The URL of any image can be used for the `X-Image-URL:' field and no
+processing of the image is required.
+
+To prevent the setting of any of these header fields, either set
+`mh-x-face-file' to nil, or simply ensure that the file defined by this option
+doesn't exist."
+  :type 'file
+  :group 'mh-letter)
+
+(defcustom mh-yank-from-start-of-msg 'attribution
+  "*Controls which part of a message is yanked by \\<mh-letter-mode-map>\\[mh-yank-cur-msg].
+If t, include the entire message, with full headers.  This is historically
+here for use with supercite, but is now deprecated in favor of the setting
+`supercite' below.
+
+If the symbol `body', then yank the message minus the header.
+
+If the symbol `supercite', include the entire message, with full headers.
+This also causes the invocation of `sc-cite-original' without the setting
+of `mail-citation-hook', now deprecated practice.
+
+If the symbol `autosupercite', do as for `supercite' automatically when
+show buffer matches the message being replied-to.  When this option is used,
+the -noformat switch is passed to the repl program to override a -filter or
+-format switch.
+
+If the symbol `attribution', then yank the message minus the header and add
+a simple attribution line at the top.
+
+If the symbol `autoattrib', do as for `attribution' automatically when show
+buffer matches the message being replied-to.  You can make sure this is
+always the case by setting `mh-reply-show-message-flag' to t (which is the
+default) and optionally `mh-delete-yanked-msg-window-flag' to t as well such
+that the show window is never displayed.  When the `autoattrib' option is
+used, the -noformat switch is passed to the repl program to override a
+-filter or -format switch.
+
+If nil, yank only the portion of the message following the point.
+
+If the show buffer has a region, this variable is ignored unless its value is
+one of `attribution' or `autoattrib' in which case the attribution is added
+to the yanked region."
+  :type '(choice (const :tag "Below point" nil)
+                 (const :tag "Without header" body)
+                 (const :tag "Invoke supercite" supercite)
+                 (const :tag "Invoke supercite, automatically" autosupercite)
+                 (const :tag "Without header, with attribution" attribution)
+                 (const :tag "Without header, with attribution, automatically"
+                        autoattrib)
+                 (const :tag "Entire message with headers" t))
+  :group 'mh-letter)
+
+\f
+
+;;; Ranges (:group 'mh-ranges)
+
+(defcustom mh-interpret-number-as-range-flag t
+  "Non-nil means interpret a number as a range.
+If the variable is non-nil, and you use an integer, N, when asked for a
+range to scan, then MH-E uses the range \"last:N\"."
+  :type 'boolean
+  :group 'mh-ranges)
+
+\f
+
+;;; Scan Line Formats (:group 'mh-scan-line-formats)
+
+(defcustom mh-adaptive-cmd-note-flag t
+  "*Non-nil means that the message number width is determined dynamically.
+This is done once when a folder is first opened by running scan on the last
+message of the folder. The message number for the last message is extracted
+and its width calculated. This width is used when calling `mh-set-cmd-note'.
+
+If you prefer fixed-width message numbers, set this variable to nil and call
+`mh-set-cmd-note' with the width specified by the scan format in
+`mh-scan-format-file'. For example, the default width is 4, so you would use
+\"(mh-set-cmd-note 4)\" if `mh-scan-format-file' were nil."
+  :type 'boolean
+  :group 'mh-scan-line-formats)
+
+(defcustom mh-scan-format-file t
+  "Specifies the format file to pass to the scan program.
+If t, the format string will be taken from the either `mh-scan-format-mh'
+or `mh-scan-format-nmh' depending on whether MH or nmh is in use.
+If nil, the default scan output will be used.
+
+If you customize the scan format, you may need to modify a few variables
+containing regexps that MH-E uses to identify specific portions of the output.
+Use `M-x apropos RET mh-scan.*regexp' to obtain a list of these variables. You
+may also have to call `mh-set-cmd-note' with the width of your message
+numbers. See also `mh-adaptive-cmd-note-flag'."
+  :type '(choice (const :tag "Use MH-E scan Format" t)
+                 (const :tag "Use Default scan Format" nil)
+                 (file  :tag "Specify a scan Format File"))
+  :group 'mh-scan-line-formats)
+
+(defcustom mh-scan-prog "scan"
+  "*Program to run to generate one-line-per-message listing of a folder.
+Normally \"scan\" or a file name linked to scan.  This file is searched
+for relative to the `mh-progs' directory unless it is an absolute pathname."
+  :type 'string
+  :group 'mh-scan-line-formats)
+(make-variable-buffer-local 'mh-scan-prog)
+
+\f
+
+;;; Sending Mail (:group 'mh-sending-mail)
+
+(defcustom mh-compose-letter-function nil
+  "Invoked when setting up a letter draft.
+It is passed three arguments: TO recipients, SUBJECT, and CC recipients."
+  :type '(choice (const nil) function)
+  :group 'mh-sending-mail)
+
+(defcustom mh-compose-prompt-flag nil
+  "*Non-nil means prompt for header fields when composing a new draft."
+  :type 'boolean
+  :group 'mh-sending-mail)
+
+(defcustom mh-forward-subject-format "%s: %s"
+  "*Format to generate the Subject: line contents for a forwarded message.
+The two string arguments to the format are the sender of the original
+message and the original subject line."
+  :type 'string
+  :group 'mh-sending-mail)
+
+(defcustom mh-reply-default-reply-to nil
+  "*Sets the person or persons to whom a reply will be sent.
+If nil, prompt for recipient.  If non-nil, then \\<mh-folder-mode-map>`\\[mh-reply]' will use this
+value and it should be one of \"from\", \"to\", \"cc\", or \"all\".
+The values \"cc\" and \"all\" do the same thing."
+  :type '(choice (const :tag "Prompt" nil)
+                 (const "from") (const "to")
+                 (const "cc") (const "all"))
+  :group 'mh-sending-mail)
+
+\f
+
+;;; Sequences (:group 'mh-sequences)
+
+;;; If `mh-unpropagated-sequences' becomes a defcustom, add the following to
+;;; the docstring: "Additional sequences that should not to be preserved can be
+;;; specified by setting `mh-unpropagated-sequences' appropriately." XXX
+
+(defcustom mh-refile-preserves-sequences-flag t
+  "*Non-nil means that sequences are preserved when messages are refiled.
+If this variable is non-nil and a message belonging to a sequence other than
+cur or Previous-Sequence (see mh-profile 5) is refiled then it is put in the
+same sequence in the destination folder."
+  :type 'boolean
+  :group 'mh-sequences)
+
+(defcustom mh-tick-seq 'tick
+  "The name of the MH sequence for ticked messages.
+You would change this option if you already use the `tick' sequence for your
+own use. You can also disable all of the ticking functions by choosing the
+`Disable Ticking' item but there isn't much advantage to that."
+  :type '(choice (const :tag "Disable Ticking" nil)
+                 symbol)
+  :group 'mh-sequences)
+
+(defcustom mh-update-sequences-after-mh-show-flag t
+  "*Non-nil means flush MH sequences to disk after message is shown.
+Three sequences are maintained internally by MH-E and pushed out to MH when a
+message is shown. They include the sequence specified by your
+`Unseen-Sequence:' profile entry, `cur', and the sequence listed by
+the `mh-tick-seq' option which is `tick' by default.
+If you do not like this behavior, set this option to nil. You can then update
+the state manually with the \\<mh-folder-mode-map>`\\[mh-execute-commands]', `\\[mh-quit]', or `\\[mh-update-sequences]' commands."
+  :type 'boolean
+  :group 'mh-sequences)
 
 \f
 
-;;; Message display (:group 'mh-show)
+;;; Reading Your Mail (:group 'mh-show)
 
 (defcustom mh-bury-show-buffer-flag t
   "*Non-nil means that the displayed show buffer for a folder is buried."
@@ -923,10 +1015,11 @@ first one found is used."
   :group 'mh-show)
 
 (defcustom mh-clean-message-header-flag t
-  "*Non-nil means clean headers of messages that are displayed or inserted.
-The variable `mh-invisible-headers' if set determines the header fields that
-are displayed. If it isn't set, then the variable `mh-invisible-headers'
-determines the header fields that are removed."
+  "*Non-nil means remove extraneous header fields.
+The header fields listed in the `mh-invisible-header-fields-default' option
+are hidden, although you can check off any field that you would like to see.
+Header fields that you would like to hide that aren't listed can be added to
+the `mh-invisible-header-fields' option."
   :type 'boolean
   :group 'mh-show)
 
@@ -960,19 +1053,28 @@ question."
   :type 'boolean
   :group 'mh-show)
 
-(defcustom mh-fetch-x-image-url nil
-  "Control fetching of X-Image-URL header field image.
-This setting only has effect if `mh-show-use-xface-flag' is non-nil.
+(defcustom mh-fetch-x-image-url 'ask
+  "*Control fetching of `X-Image-URL:' header field image.
+If set to \"Always fetch\" (t), the image is always fetched. You probably want
+to avoid this setting for privacy and DOS (denial of service) reasons. For
+example, fetching a URL can tip off a spammer that you've read his email.
+Someone may also flood your network and fill your disk drive by sending a
+torrent of messages, each specifying a unique URL to a very large file.
+
+If set to \"Ask before fetching\" ('ask), you are prompted before the image is
+fetched. MH-E will remember your reply and will either use the already fetched
+image the next time the same URL is encountered or silently skip it if you
+didn't fetch it the first time. This is the default.
 
-If set to t, the image is fetched.
+If set to \"Never fetch\" (nil), images are never fetched and only displayed
+if they are already present in the cache.
 
-If set to 'ask, the user is prompted before the image is fetched. MH-E will
-remember your reply and will either use the already fetched image the next time
-the same URL is encountered or silently skip it if you didn't fetch it the
-first time.
+The cache of images is found in the directory `.mhe-x-image-cache' within your
+MH directory. To see how you can add your own face to the `From:' field, see
+`mh-x-face-file'.
+
+This setting only has effect if `mh-show-use-xface-flag' is non-nil."
 
-If set to nil, the default, images are not fetched and only displayed if they
-are already present in the cache."
   :type '(choice (const :tag "Always fetch" t)
                  (const :tag "Ask before fetching" ask)
                  (const :tag "Never fetch" nil))
@@ -1002,28 +1104,8 @@ The gnus method uses a different color for each indentation."
                  (const :tag "Don't fontify" nil))
   :group 'mh-show)
 
-(defvar mh-invisible-headers nil
-  "*Regexp matching lines in a message header that are not to be shown.
-Customize the variable `mh-invisible-header-fields' to generate this variable;
-It will in turn automatically use the function `mh-invisible-headers' to
-generate this variable.
-If the variable `mh-visible-headers' is non-nil, it is used instead to specify
-what to keep.")
-
-(defun mh-invisible-headers ()
-  "Make or remake the variable `mh-invisible-headers'.
-Done using `mh-invisible-header-fields' as input."
-  (if mh-invisible-header-fields
-      (setq mh-invisible-headers
-            (concat
-             "^"
-             (let ((max-specpdl-size 1000) ;workaround for insufficient default
-                   (fields mh-invisible-header-fields))
-               (regexp-opt fields t))))
-    (setq mh-invisible-headers nil)))
-
 ;; Keep fields alphabetized. Mention source, if known.
-(defcustom mh-invisible-header-fields
+(defvar mh-invisible-header-fields-internal
   '("Approved:"
     "Autoforwarded:"
     "Bestservhost:"
@@ -1053,12 +1135,13 @@ Done using `mh-invisible-header-fields' as input."
     "Old-Return-Path:"
     "Original-Encoded-Information-Types:"  ; X400
     "Original-Lines:"                   ; mail to news
-    "Original-Newsgroups:"              ; mail to news
     "Original-NNTP-"                    ; mail to news
+    "Original-Newsgroups:"              ; mail to news
     "Original-Path:"                    ; mail to news
     "Original-Received:"                ; mail to news
     "Original-To:"                      ; mail to news
     "Original-X-"                       ; mail to news
+    "Originator:"
     "P1-Content-Type:"                  ; X400
     "P1-Message-Id:"                    ; X400
     "P1-Recipient:"                     ; X400
@@ -1074,13 +1157,17 @@ Done using `mh-invisible-header-fields' as input."
     "Return-Path:"                      ; RFC 822
     "Sensitivity:"                      ; MS Outlook
     "Status:"                           ; sendmail
+    "Thread-"
     "Ua-Content-Id:"                    ; X400
 ;;  "User-Agent:"                       ; Similar to X-Mailer, so display it.
     "Via:"                              ; MH
     "X-Abuse-Info:"
+    "X-Abuse-and-DMCA-"
     "X-Accept-Language:"
     "X-Accept-Language:"                ; Netscape/Mozilla
     "X-Ack:"
+    "X-Administrivia-To:"
+    "X-AntiAbuse:"                      ; cPanel
     "X-Apparently-From:"                ; MS Outlook
     "X-Apparently-To:"           ; Egroups/yahoogroups mailing list manager
     "X-Authentication-Warning:"         ; sendmail
@@ -1088,13 +1175,18 @@ Done using `mh-invisible-header-fields' as input."
     "X-Bogosity:"                       ; bogofilter
     "X-Complaints-To:"
     "X-Cron-Env:"
+    "X-DMCA"
     "X-Delivered"
+    "X-ELNK-Trace:"                     ; Earthlink mailer
+    "X-Envelope-Date:"                  ; GNU mailutils
+    "X-Envelope-From:"
     "X-Envelope-Sender:"
     "X-Envelope-To:"
     "X-Face:"
     "X-Folder:"                         ; Spam
     "X-From-Line"
     "X-Gnus-Mail-Source:"               ; gnus
+    "X-Greylist:"                       ; milter-greylist-1.2.1
     "X-Habeas-SWE-1:"                   ; Spam
     "X-Habeas-SWE-2:"                   ; Spam
     "X-Habeas-SWE-3:"                   ; Spam
@@ -1104,27 +1196,35 @@ Done using `mh-invisible-header-fields' as input."
     "X-Habeas-SWE-7:"                   ; Spam
     "X-Habeas-SWE-8:"                   ; Spam
     "X-Habeas-SWE-9:"                   ; Spam
+    "X-Image-URL:"                      ; URL equivalent of X-Face and Face
     "X-Info:"                           ; NTMail
     "X-Juno-"                           ; Juno
     "X-List-Host:"                      ; Unknown mailing list managers
     "X-List-Subscribe:"                 ; Unknown mailing list managers
     "X-List-Unsubscribe:"               ; Unknown mailing list managers
+    "X-Listprocessor-"                  ; ListProc(tm) by CREN
     "X-Listserver:"                     ; Unknown mailing list managers
     "X-Loop:"                           ; Unknown mailing list managers
+    "X-MHE-Checksum"                    ; Checksum added during index search
     "X-MIME-Autoconverted:"             ; sendmail
     "X-MIMETrack:"
-    "X-MS-TNEF-Correlator:"             ; MS Outlook
+    "X-Mms-"                            ; T-Mobile pictures
+    "X-MS-"                            ; MS Outlook
+    "X-MailScanner"                     ; ListProc(tm) by CREN
     "X-Mailing-List:"                   ; Unknown mailing list managers
     "X-Mailman-Version:"                ; Mailman mailing list manager
     "X-Majordomo:"                      ; Majordomo mailing list manager
     "X-Message-Id"
-    "X-MHE-Checksum"                    ; Checksum added during index search
+    "X-MessageWall-Score:"              ; Unknown mailing list manager, AUC TeX
     "X-MimeOLE:"                        ; MS Outlook
     "X-Mozilla-Status:"                 ; Netscape/Mozilla
     "X-Msmail-"                         ; MS Outlook
+    "X-NAI-Spam-"                       ; Network Associates Inc. SpamKiller
     "X-News:"                           ; News
     "X-No-Archive:"
     "X-Notes-Item:"                     ; Lotus Notes Domino structured header
+    "X-OperatingSystem:"
+    ;;"X-Operator:"                     ; Similar to X-Mailer, so display it
     "X-Orcl-Content-Type:"
     "X-Original-Complaints-To:"
     "X-Original-Date:"                  ; SourceForge mailing list manager
@@ -1132,8 +1232,10 @@ Done using `mh-invisible-header-fields' as input."
     "X-Original-Trace:"
     "X-OriginalArrivalTime:"            ; Hotmail
     "X-Originating-IP:"                 ; Hotmail
+    "X-Postfilter:"
     "X-Priority:"                       ; MS Outlook
     "X-Qotd-"                           ; User added
+    "X-RM"
     "X-Received-Date:"
     "X-Received:"
     "X-Request-"
@@ -1141,38 +1243,108 @@ Done using `mh-invisible-header-fields' as input."
     "X-SBNote:"                         ; Spam
     "X-SBPass:"                         ; Spam
     "X-SBRule:"                         ; Spam
+    "X-SMTP-"
     "X-Scanned-By"
     "X-Sender:"
     "X-Server-Date:"
     "X-Server-Uuid:"
     "X-Sieve:"                          ; Sieve filtering
-    "X-Spam-Checker-Version:"           ; Spamassassin
-    "X-Spam-Level:"                     ; Spamassassin
-    "X-Spam-Score:"                     ; Spamassassin
-    "X-Spam-Status:"                    ; Spamassassin
+    "X-Source"
+    "X-Spam-"                           ; Spamassassin
     "X-SpamBouncer:"                    ; Spam
+    "X-Status"
+    "X-Submissions-To:"
+    "X-Telecom-Digest"
     "X-Trace:"
+    "X-UID"
     "X-UIDL:"
     "X-UserInfo1:"
     "X-VSMLoop:"                        ; NTMail
     "X-Vms-To:"
+    "X-WebTV-Signature:"
     "X-Wss-Id:"                         ; Worldtalk gateways
+    "X-Yahoo"
     "X-eGroups-"                 ; Egroups/yahoogroups mailing list manager
     "X-pgp:"
     "X-submission-address:"
     "X400-"                             ; X400
     "Xref:")
-"*List of header fields that are not to be shown.
-Regexps are not allowed. Unique fields should have a \":\" suffix; otherwise,
-the element can be used to render invisible an entire class of fields that
-start with the same prefix.
-This variable is ignored if the variable `mh-visible-headers' is set."
+  "List of default header fields that are not to be shown.
+Do not alter this variable directly.  Instead, add entries from here that you
+would like to be displayed in `mh-invisible-header-fields-default'
+and add entries to hide in `mh-invisible-header-fields'.")
+
+(defvar mh-invisible-header-fields-compiled nil
+  "*Regexp matching lines in a message header that are not to be shown.
+Do not alter this variable directly. Instead, customize
+`mh-invisible-header-fields-default' checking for fields normally
+hidden that you wish to display, and add extra entries to hide in
+`mh-invisible-header-fields'.")
+
+(defun mh-invisible-headers ()
+  "Make or remake the variable `mh-invisible-header-fields-compiled'.
+Done using `mh-invisible-header-fields-internal' as input, from which entries
+from `mh-invisible-header-fields-default' are removed and entries
+from `mh-invisible-header-fields' are added."
+  (let ((fields mh-invisible-header-fields-internal))
+    (when mh-invisible-header-fields-default
+      ;; Remove entries from `mh-invisible-header-fields-default'
+      (setq fields
+            (loop for x in fields
+                  unless (member x mh-invisible-header-fields-default)
+                  collect x)))
+    (when (and (boundp 'mh-invisible-header-fields)
+               mh-invisible-header-fields)
+      (dolist (x mh-invisible-header-fields)
+        (unless (member x fields) (setq fields (cons x fields)))))
+    (if fields
+        (setq mh-invisible-header-fields-compiled
+              (concat
+               "^"
+               ;; workaround for insufficient default
+               (let ((max-specpdl-size 1000))
+                 (regexp-opt fields t))))
+      (setq mh-invisible-header-fields-compiled nil))))
+
+(defcustom mh-invisible-header-fields-default nil
+  "*List of hidden header fields.
+The header fields listed in this option are hidden, although you can check off
+any field that you would like to see. Header fields that you would like to
+hide that aren't listed can be added to the `mh-invisible-header-fields'
+option.
+
+See also `mh-clean-message-header-flag'."
+  :type `(set ,@(mapcar (lambda (x) `(const ,x))
+                        mh-invisible-header-fields-internal))
+  :set (lambda (symbol value)
+         (set-default symbol value)
+         (mh-invisible-headers))
+  :group 'mh-show)
+
+(defcustom mh-invisible-header-fields nil
+  "*Additional header fields to hide.
+Header fields that you would like to hide that aren't listed in
+`mh-invisible-header-fields-default' can be added to this option with a couple
+of caveats. Regular expressions are not allowed. Unique fields should have a
+`:' suffix; otherwise, the element can be used to render invisible an entire
+class of fields that start with the same prefix.
+
+See also `mh-clean-message-header-flag'."
+
   :type '(repeat (string :tag "Header field"))
   :set (lambda (symbol value)
          (set-default symbol value)
          (mh-invisible-headers))
   :group 'mh-show)
 
+(defcustom mh-lpr-command-format "lpr -J '%s'"
+  "*Format for Unix command that prints a message.
+The string should be a Unix command line, with the string '%s' where
+the job's name (folder and message number) should appear.  The formatted
+message text is piped to this command when you type \\<mh-folder-mode-map>`\\[mh-print-msg]'."
+  :type 'string
+  :group 'mh-show)
+
 (defcustom mh-max-inline-image-height nil
   "*Maximum inline image height if Content-Disposition is not present.
 If nil, image will be displayed if its height is smaller than the height of
@@ -1187,6 +1359,27 @@ window."
   :type '(choice (const nil) integer)
   :group 'mh-show)
 
+(defcustom mh-mime-save-parts-default-directory t
+  "Default directory to use for `mh-mime-save-parts'.
+If nil, prompt and set for next time the command is used during same session.
+If t, prompt always"
+  :type '(choice (const :tag "Prompt the first time" nil)
+                 (const :tag "Prompt always" t)
+                 directory)
+  :group 'mh-show)
+
+(defcustom mh-print-background-flag nil
+  "*Non-nil means messages should be printed in the background.
+WARNING: do not delete the messages until printing is finished;
+otherwise, your output may be truncated."
+  :type 'boolean
+  :group 'mh-show)
+
+(defcustom mh-recursive-folders-flag nil
+  "*Non-nil means that commands which operate on folders do so recursively."
+  :type 'boolean
+  :group 'mh-show)
+
 (defcustom mh-show-maximum-size 0
   "*Maximum size of message (in bytes) to display automatically.
 Provides an opportunity to skip over large messages which may be slow to load.
@@ -1194,6 +1387,14 @@ Use a value of 0 to display all messages automatically regardless of size."
   :type 'integer
   :group 'mh-show)
 
+(defcustom mh-show-threads-flag nil
+  "Non-nil means new folders start in threaded mode.
+Threading large number of messages can be time consuming. So if the flag is
+non-nil then threading will be done only if the number of messages being
+threaded is less than `mh-large-folder'."
+  :type 'boolean
+  :group 'mh-show)
+
 ;; Use goto-addr if it was already loaded (which probably sets this
 ;; variable to t), or if this variable is otherwise set to t.
 (defcustom mh-show-use-goto-addr-flag (and (boundp 'goto-address-highlight-p)
@@ -1205,80 +1406,55 @@ The `goto-addr' module is used."
 
 (defcustom mh-show-use-xface-flag (>= emacs-major-version 21)
   "*Non-nil means display face images in `mh-show-mode'.
-This flag controls the display of three kinds of faces.
-
-The first is the traditional X-Face header field. For GNU Emacs 21
-and above, the `uncompface' binary is required to be in the execute
-PATH for the display of X-Face images. It can be obtained from
-ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.Z.
-
-If the XEmacs you are using has internal support for X-Face images, then MH-E
-will display X-Face images in XEmacs \"out of the box\". Even if you don't have
-X-Face support compiled into your XEmacs, you can still see the X-Face images
-in MH-E with the aid of an external x-face package and `uncompface'. It is
-available from ftp://ftp.jpl.org/pub/elisp/. Download it, put its files in the
-`load-path' and MH-E will invoke it automatically.
-
-Second, MH-E supports the display of the Gnus-specific Face
-header field in GNU Emacs >= 21 and XEmacs. No external packages
-are required. More information about the Face header can be found
-at: http://quimby.gnus.org/circus/face/.
-
-Finally, MH-E can also display images from the X-Image-URL header field. The
-display of the images requires the `wget' program, available from
-http://www.gnu.org/software/wget/wget.html, to fetch the image and the
-`convert' program from the ImageMagick suite, available from
+
+MH-E can display the content of `Face:', `X-Face:', and `X-Image-URL:' header
+fields. If any of these fields occur in the header of your message, the
+sender's face will appear in the `From:' header field. If more than one of
+these fields appear, then the first field found in the order `Face:',
+`X-Face:', and `X-Image-URL:' will be used. Note that versions of GNU Emacs
+prior to 21.1 don't support the display of inline images, so face images are
+not displayed in these versions.
+
+The option `mh-show-use-xface-flag' is used to turn this feature on and off.
+This feature will be turned on by default if your system supports it.
+
+The first header field used, if present, is the Gnus-specific `Face:' field.
+The `Face:' field appeared in GNU Emacs 21 and XEmacs. For more information,
+see http://quimby.gnus.org/circus/face/. Next is the traditional `X-Face:'
+header field. The display of this field requires the `uncompface' program
+which can be obtained from
+ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.Z. Recent versions of
+XEmacs have internal support for `X-Face:' images. If your version of XEmacs
+does not, then you'll need both `uncompface' and the x-face package which is
+available at ftp://ftp.jpl.org/pub/elisp/.
+
+Finally, MH-E will display images referenced by the `X-Image-URL:' header
+field if neither the `Face:' nor the `X-Face:' fields are present. The display
+of the images requires `wget' (available from
+http://www.gnu.org/software/wget/wget.html), `fetch', or `curl' to fetch the
+image and the `convert' program from the ImageMagick suite, available from
 http://www.imagemagick.org/. Of the three header fields this is the most
 efficient in terms of network usage since the image doesn't need to be
-transmitted with every single mail. However its display needs the recipient to
-fetch a URL and this can be misused. So it is disabled by default. It can be
-enabled by customizing `mh-fetch-x-image-url'. Setting that to ask for
-confirmation before fetching seems like a good choice.
+transmitted with every single mail.
 
-Versions of GNU Emacs prior to 21.1 don't support the display of
-inline images. So face images are not displayed in these versions."
+The option `mh-fetch-x-image-url' controls the fetching of the `X-Image-URL:'
+header field image."
   :type 'boolean
   :group 'mh-show)
 
+(defcustom mh-store-default-directory nil
+  "*Last directory used by \\[mh-store-msg]; default for next store.
+A directory name string, or nil to use current directory."
+  :type '(choice (const :tag "Current" nil)
+                 directory)
+  :group 'mh-show)
+
 (defcustom mh-summary-height nil
   "*Number of lines in MH-Folder window (including the mode line)."
   :type '(choice (const :tag "Automatic" nil)
                  (integer :tag "Fixed sized"))
   :group 'mh-show)
 
-(defvar mh-visible-headers nil
-  "*Regexp matching lines in a message header that are to be shown.
-Customize the variable `mh-visible-header-fields' to generate this variable;
-It will in turn automatically use the function `mh-visible-headers' to
-generate this variable.
-Only used if `mh-clean-message-header-flag' is non-nil. Setting it overrides
-the variable `mh-invisible-headers'.")
-
-(defun mh-visible-headers ()
-  "Make or remake the variable `mh-visible-headers'.
-Done using `mh-visible-header-fields' as input."
-  (if mh-visible-header-fields
-      (setq mh-visible-headers
-            (concat
-             "^"
-             (let ((max-specpdl-size 1000) ;workaround for insufficient default
-                   (fields mh-visible-header-fields))
-               (regexp-opt fields t))))
-    (setq mh-visible-headers nil)))
-
-(defcustom mh-visible-header-fields nil
-"*List of header fields that are to be shown.
-Regexps are not allowed. Unique fields should have a \":\" suffix; otherwise,
-the element can be used to render visible an entire class of fields that
-start with the same prefix.
-Only used if `mh-clean-message-header-flag' is non-nil.
-Setting it overrides the variable `mh-invisible-headers'."
-  :type '(repeat (string :tag "Header field"))
-  :set (lambda (symbol value)
-         (set-default symbol value)
-         (mh-visible-headers))
-  :group 'mh-show)
-
 (defcustom mhl-formfile nil
   "*Name of format file to be used by mhl to show and print messages.
 A value of t means use the default format file.
@@ -1292,387 +1468,489 @@ the message continues to conform to RFC 822 and MH-E can parse the headers."
 
 \f
 
-;;; Composing messages (:group 'mh-letter)
-
-(defcustom mh-compose-insertion (if (locate-library "mml") 'gnus 'mhn)
-  "Use either 'gnus or 'mhn to insert MIME message directives in messages."
-  :type '(choice (const :tag "Use Gnus" gnus)
-                 (const :tag "Use mhn"  mhn))
-  :group 'mh-letter)
-
-(defcustom mh-compose-letter-function nil
-  "Invoked when setting up a letter draft.
-It is passed three arguments: TO recipients, SUBJECT, and CC recipients."
-  :type '(choice (const nil) function)
-  :group 'mh-letter)
-
-(defcustom mh-compose-prompt-flag nil
-  "*Non-nil means prompt for header fields when composing a new draft."
-  :type 'boolean
-  :group 'mh-letter)
-
-(defcustom mh-compose-skipped-header-fields
-  '("from" "organization" "references" "in-reply-to" "x-face" "face"
-    "x-mailer")
-  "List of header fields to skip over when navigating in draft."
-  :type '(repeat (string :tag "Field"))
-  :group 'mh-letter)
-
-(defcustom mh-compose-space-does-completion-flag nil
-  "*Non-nil means that SPACE does completion in message header."
-  :type 'boolean
-  :group 'mh-letter)
-
-(defcustom mh-delete-yanked-msg-window-flag nil
-  "*Non-nil means delete any window displaying the message.
-Controls window display when a message is yanked by \\<mh-letter-mode-map>\\[mh-yank-cur-msg].
-If non-nil, yanking the current message into a draft letter deletes any
-windows displaying the message."
-  :type 'boolean
-  :group 'mh-letter)
-
-(defcustom mh-extract-from-attribution-verb "wrote:"
-  "*Verb to use for attribution when a message is yanked by \\<mh-letter-mode-map>\\[mh-yank-cur-msg]."
-  :type '(choice (const "wrote:")
-                 (const "a Ã©crit :")
-                 (string :tag "Custom string"))
-  :group 'mh-letter)
-
-(defcustom mh-forward-subject-format "%s: %s"
-  "*Format to generate the Subject: line contents for a forwarded message.
-The two string arguments to the format are the sender of the original
-message and the original subject line."
-  :type 'string
-  :group 'mh-letter)
-
-(defcustom mh-ins-buf-prefix "> "
-  "*String to put before each non-blank line of a yanked or inserted message.
-\\<mh-letter-mode-map>Used when the message is inserted into an outgoing letter
-by \\[mh-insert-letter] or \\[mh-yank-cur-msg]."
-  :type 'string
-  :group 'mh-letter)
-
-(defcustom mh-insert-x-mailer-flag t
-  "*Non-nil means append an X-Mailer field to the header."
-  :type 'boolean
-  :group 'mh-letter)
+;;; The Speedbar (:group 'mh-speed)
 
-(defcustom mh-letter-complete-function 'ispell-complete-word
-  "*Function to call when completing outside of fields specific to aliases."
-  :type '(choice function (const nil))
-  :group 'mh-letter)
+(defcustom mh-large-folder 200
+  "The number of messages that indicates a large folder.
+If a folder is deemed to be large, that is the number of messages in it exceed
+this value, then confirmation is needed when it is visited. Even when
+`mh-show-threads-flag' is non-nil, the folder is not automatically threaded, if
+it is large. If set to nil all folders are treated as if they are small."
+  :type '(choice (const :tag "No limit") integer)
+  :group 'mh-speed)
 
-(defcustom mh-letter-fill-column 72
-  "*Fill column to use in `mh-letter-mode'.
-This is usually less than in other text modes because email messages get
-quoted by some prefix (sometimes many times) when they are replied to,
-and it's best to avoid quoted lines that span more than 80 columns."
+(defcustom mh-speed-flists-interval 60
+  "Time between calls to flists in seconds.
+If 0, flists is not called repeatedly."
   :type 'integer
-  :group 'mh-letter)
-
-(defcustom mh-reply-default-reply-to nil
-  "*Sets the person or persons to whom a reply will be sent.
-If nil, prompt for recipient.  If non-nil, then \\<mh-folder-mode-map>`\\[mh-reply]' will use this
-value and it should be one of \"from\", \"to\", \"cc\", or \"all\".
-The values \"cc\" and \"all\" do the same thing."
-  :type '(choice (const :tag "Prompt" nil)
-                 (const "from") (const "to")
-                 (const "cc") (const "all"))
-  :group 'mh-letter)
-
-(defcustom mh-reply-show-message-flag t
-  "*Non-nil means the show buffer is displayed using \\<mh-letter-mode-map>\\[mh-reply].
+  :group 'mh-speed)
 
-The setting of this variable determines whether the MH `show-buffer' is
-displayed with the current message when using `mh-reply' without a prefix
-argument.  Set it to nil if you already include the message automatically
-in your draft using
- repl: -filter repl.filter
-in your ~/.mh_profile file."
+(defcustom mh-speed-run-flists-flag t
+  "Non-nil means flists is used.
+If non-nil, flists is executed every `mh-speed-flists-interval' seconds to
+update the display of the number of unseen and total messages in each folder.
+If resources are limited, this can be set to nil and the speedbar display can
+be updated manually with the \\[mh-speed-flists] command."
   :type 'boolean
-  :group 'mh-letter)
-
-(defcustom mh-signature-file-name "~/.signature"
-  "*Name of file containing the user's signature.
-Inserted into message by \\<mh-letter-mode-map>\\[mh-insert-signature]."
-  :type 'file
-  :group 'mh-letter)
-
-(defcustom mh-x-face-file "~/.face"
-  "*File containing X-Face or Face header field to insert in outgoing mail.
-
-If the file starts with either of the strings \"X-Face: \", \"Face: \" or
-\"X-Image-URL: \" then it is assumed to contain the whole field and is added to
-the message header verbatim. Otherwise it is assumed that the file contains the
-value of the X-Face header field.
-
-X-Face header fields can be generated using `compface', which can be obtained
-from ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.Z. The \"Online
-X-Face Convertor\" at http://www.dairiki.org/xface/ is a useful resource for
-quick conversion of images into X-Face header fields.
-
-There is a `make-face' script that converts a jpeg image to a Face header
-field at http://quimby.gnus.org/circus/face/make-face.
-
-The URL of any image can be used for the X-Image-URL field and no processing
-of the image is required.
-
-If nil, or the file does not exist, nothing is added to the message header."
-  :type 'file
-  :group 'mh-letter)
+  :group 'mh-speed)
 
-(defcustom mh-yank-from-start-of-msg 'attribution
-  "*Controls which part of a message is yanked by \\<mh-letter-mode-map>\\[mh-yank-cur-msg].
-If t, include the entire message, with full headers.  This is historically
-here for use with supercite, but is now deprecated in favor of the setting
-`supercite' below.
+\f
 
-If the symbol `body', then yank the message minus the header.
+;;; The Toolbar (:group 'mh-toolbar)
 
-If the symbol `supercite', include the entire message, with full headers.
-This also causes the invocation of `sc-cite-original' without the setting
-of `mail-citation-hook', now deprecated practice.
+(defcustom mh-tool-bar-search-function 'mh-search-folder
+  "*Function called by the tool-bar search button.
+See `mh-search-folder' and `mh-index-search' for details."
+  :type '(choice (const mh-search-folder)
+                 (const mh-index-search)
+                 (function :tag "Other function"))
+  :group 'mh-toolbar)
 
-If the symbol `autosupercite', do as for `supercite' automatically when
-show buffer matches the message being replied-to.  When this option is used,
-the -noformat switch is passed to the repl program to override a -filter or
--format switch.
+;; Functions called from the tool bar
+(defun mh-tool-bar-search (&optional arg)
+  "Interactively call `mh-tool-bar-search-function'.
+Optional argument ARG is not used."
+  (interactive "P")
+  (call-interactively mh-tool-bar-search-function))
 
-If the symbol `attribution', then yank the message minus the header and add
-a simple attribution line at the top.
+(defun mh-tool-bar-customize ()
+  "Call `mh-customize' from the toolbar."
+  (interactive)
+  (mh-customize t))
 
-If the symbol `autoattrib', do as for `attribution' automatically when show
-buffer matches the message being replied-to.  You can make sure this is
-always the case by setting `mh-reply-show-message-flag' to t (which is the
-default) and optionally `mh-delete-yanked-msg-window-flag' to t as well such
-that the show window is never displayed.  When the `autoattrib' option is
-used, the -noformat switch is passed to the repl program to override a
--filter or -format switch.
+(defun mh-tool-bar-folder-help ()
+  "Visit \"(mh-e)Top\"."
+  (interactive)
+  (Info-goto-node "(mh-e)Top")
+  (delete-other-windows))
 
-If nil, yank only the portion of the message following the point.
+(defun mh-tool-bar-letter-help ()
+  "Visit \"(mh-e)Draft Editing\"."
+  (interactive)
+  (Info-goto-node "(mh-e)Draft Editing")
+  (delete-other-windows))
 
-If the show buffer has a region, this variable is ignored unless its value is
-one of `attribution' or `autoattrib' in which case the attribution is added
-to the yanked region."
-  :type '(choice (const :tag "Below point" nil)
-                 (const :tag "Without header" body)
-                 (const :tag "Invoke supercite" supercite)
-                 (const :tag "Invoke supercite, automatically" autosupercite)
-                 (const :tag "Without header, with attribution" attribution)
-                 (const :tag "Without header, with attribution, automatically"
-                        autoattrib)
-                 (const :tag "Entire message with headers" t))
-  :group 'mh-letter)
+(defmacro mh-tool-bar-reply-generator (function recipient folder-buffer-flag)
+  "Generate FUNCTION that replies to RECIPIENT.
+If FOLDER-BUFFER-FLAG is nil then the function generated
+When INCLUDE-FLAG is non-nil, include message body being replied to."
+  `(defun ,function (&optional arg)
+     ,(format "Reply to \"%s\".\nWhen ARG is non-nil include message in reply."
+              recipient)
+     (interactive "P")
+     ,(if folder-buffer-flag nil '(set-buffer mh-show-folder-buffer))
+     (mh-reply (mh-get-msg-num nil) ,recipient arg)))
 
-\f
+(mh-tool-bar-reply-generator mh-tool-bar-reply-from "from" t)
+(mh-tool-bar-reply-generator mh-show-tool-bar-reply-from "from" nil)
+(mh-tool-bar-reply-generator mh-tool-bar-reply-to "to" t)
+(mh-tool-bar-reply-generator mh-show-tool-bar-reply-to "to" nil)
+(mh-tool-bar-reply-generator mh-tool-bar-reply-all "all" t)
+(mh-tool-bar-reply-generator mh-show-tool-bar-reply-all "all" nil)
 
-;;; Alias handling (:group 'mh-alias)
+;; XEmacs has a couple of extra customizations...
+(mh-do-in-xemacs
+  (defcustom mh-xemacs-use-toolbar-flag (if (and (featurep 'toolbar)
+                                                 (featurep 'xpm)
+                                                 (device-on-window-system-p))
+                                            t
+                                          nil)
+    "*If non-nil, use toolbar.
 
-(defcustom mh-alias-completion-ignore-case-flag t
-  "*Non-nil means don't consider case significant in MH alias completion.
-This is the default in plain MH, so it is the default here as well. It
-can be useful to set this to t if, for example, you use lowercase
-aliases for people and uppercase for mailing lists."
-  :type 'boolean
-  :group 'mh-alias)
+This will default to t if you are in an environment that supports
+toolbars and xpm."
+    :type 'boolean
+    :group 'mh-toolbar)
 
-(defcustom mh-alias-expand-aliases-flag nil
-  "*Non-nil means to expand aliases entered in the minibuffer.
-In other words, aliases entered in the minibuffer will be expanded to the full
-address in the message draft. By default, this expansion is not performed."
-  :type 'boolean
-  :group 'mh-alias)
+  (defcustom mh-xemacs-toolbar-position (if mh-xemacs-use-toolbar-flag
+                                            'default
+                                          nil)
+    "*Where to put the toolbar.
 
-(defcustom mh-alias-flash-on-comma t
-  "*Specify whether to flash or warn on translation.
-When a [comma] is pressed while entering aliases or addresses, setting this
-variable to the following values has the listed effects:
-t   Flash alias translation but don't warn if there is no translation.
-1   Flash alias translation and warn if there is no translation.
-nil Do not flash alias translation nor warn if there is no translation."
-  :type '(choice (const :tag "Flash but don't warn if no translation" t)
-                (const :tag "Flash and warn if no translation" 1)
-                (const :tag "Don't flash nor warn if no translation" nil))
-  :group 'mh-alias)
+Valid non-nil values are \"default\", \"top\", \"bottom\", \"left\",
+\"right\".  These match the four edges of the frame, with \"default\"
+meaning \"use the same position as the default-toolbar\".
 
-(defcustom mh-alias-insert-file nil
-  "*Filename to use to store new MH-E aliases.
-This variable can also be a list of filenames, in which case MH-E will prompt
-for one of them. If nil, the default, then MH-E will use the first file found
-in the \"AliasFile\" component of the MH profile."
-  :type '(choice (const :tag "Use AliasFile MH profile component" nil)
-                 (file :tag "Alias file")
-                 (repeat :tag "List of alias files" file))
-  :group 'mh-alias)
+A nil value means do not use a toolbar.
 
-(defcustom mh-alias-insertion-location 'sorted
-  "Specifies where new aliases are entered in alias files.
-Options are sorted alphabetically, at the top of the file or at the bottom."
-  :type '(choice (const :tag "Sorted alphabetically" sorted)
-                 (const :tag "At the top of file" top)
-                 (const :tag "At the bottom of file" bottom))
-  :group 'mh-alias)
+If this variable is set to anything other than \"default\" and the
+default-toolbar has a different positional setting from the value of
+this variable, then two toolbars will be displayed.  The MH-E toolbar
+and the default-toolbar."
+    :type '(radio (const :tag "Same position as the \"default-toolbar\""
+                         :value default)
+                  (const :tag "Along the top edge of the frame"
+                         :value top)
+                  (const :tag "Along the bottom edge of the frame"
+                         :value bottom)
+                  (const :tag "Along the left edge of the frame"
+                         :value left)
+                  (const :tag "Along the right edge of the frame"
+                         :value right)
+                  (const :tag "Don't use a toolbar" nil))
+    :group 'mh-toolbar))
 
-(defcustom mh-alias-local-users t
-  "*If t, local users are completed in MH-E To: and Cc: prompts.
+(defmacro mh-tool-bar-define (defaults &rest buttons)
+  "Define a tool bar for MH-E.
+DEFAULTS is the list of buttons that are present by default. It is a list of
+lists where the sublists are of the following form:
 
-Users with a userid greater than some magic number (usually 200) are available
-for completion.
+  (:KEYWORD FUNC1 FUNC2 FUNC3 ...)
 
-If you set this variable to a string, it will be executed to generate a
-password file. A value of \"ypcat passwd\" is helpful if NIS is in use."
-  :type '(choice (boolean) (string))
-  :group 'mh-alias)
+Here :KEYWORD is one of :folder or :letter. If it is :folder then the default
+buttons in the folder and show mode buffers are being specified. If it is
+:letter then the default buttons in the letter mode are listed. FUNC1, FUNC2,
+FUNC3, ... are the names of the functions that the buttons would execute.
 
-(defcustom mh-alias-local-users-prefix "local."
-  "*String prepended to the real names of users from the passwd file.
-If nil, use the username string unmodified instead of the real name from
-the gecos field of the passwd file.
+Each element of BUTTONS is a list consisting of four mandatory items and one
+optional item as follows:
 
-For example, given the following passwd file line:
+  (FUNCTION MODES ICON DOC &optional ENABLE-EXPR)
 
- psg:x:1000:1000:Peter S Galbraith,,,:/home/psg:/bin/tcsh
+where,
 
-here are the derived aliases for different values of this variable:
+  FUNCTION is the name of the function that will be executed when the button
+  is clicked.
 
- \"local.\"  -> local.peter.galbraith
- \"\"        -> peter.galbraith
- nii       -> psg
+  MODES is a list of symbols. List elements must be from `folder', `letter' and
+  `sequence'. If `folder' is present then the button is available in the
+  folder and show buffer. If the name of FUNCTION is of the form \"mh-foo\",
+  where foo is some arbitrary string, then we check if the function
+  `mh-show-foo' exists. If it exists then that function is used in the show
+  buffer. Otherwise the original function `mh-foo' is used in the show buffer
+  as well. Presence of `sequence' is handled similar to the above. The only
+  difference is that the button is shown only when the folder is narrowed to a
+  sequence. If `letter' is present in MODES, then the button is available
+  during draft editing and runs FUNCTION when clicked.
 
-This variable is only meaningful if the variable `mh-alias-local-users' is
-non-nil."
-  :type '(choice (const :tag "Use username instead of real name" nil)
-                 (string))
-  :group 'mh-alias)
+  ICON is the icon that is drawn in the button.
 
-(defcustom mh-alias-passwd-gecos-comma-separator-flag t
-  "*Non-nil means the gecos field in the passwd file uses comma as a separator.
-Used to construct aliases for users in the passwd file."
-  :type 'boolean
-  :group 'mh-alias)
+  DOC is the documentation for the button. It is used in tool-tips and in
+  providing other help to the user. GNU Emacs uses only the first line of the
+  string. So the DOC should be formatted such that the first line is useful and
+  complete without the rest of the string.
+
+  Optional item ENABLE-EXPR is an arbitrary lisp expression. If it evaluates
+  to nil, then the button is deactivated, otherwise it is active. If is in't
+  present then the button is always active."
+  ;; The following variable names have been carefully chosen to make code
+  ;; generation easier. Modifying the names should be done carefully.
+  (let (folder-buttons folder-docs folder-button-setter sequence-button-setter
+                       show-buttons show-button-setter show-seq-button-setter
+                       letter-buttons letter-docs letter-button-setter
+                       folder-defaults letter-defaults
+                       folder-vectors show-vectors letter-vectors)
+    (dolist (x defaults)
+      (cond ((eq (car x) :folder) (setq folder-defaults (cdr x)))
+            ((eq (car x) :letter) (setq letter-defaults (cdr x)))))
+    (dolist (button buttons)
+      (unless (and (listp button)
+                   (or (equal (length button) 4) (equal (length button) 5)))
+        (error "Incorrect MH-E tool-bar button specification: %s" button))
+      (let* ((name (nth 0 button))
+             (name-str (symbol-name name))
+             (icon (nth 2 button))
+             (xemacs-icon (mh-do-in-xemacs
+                            (cdr (assoc (intern icon) mh-xemacs-icon-map))))
+             (full-doc (nth 3 button))
+             (doc (if (string-match "\\(.*\\)\n" full-doc)
+                      (match-string 1 full-doc)
+                    full-doc))
+             (enable-expr (or (nth 4 button) t))
+             (modes (nth 1 button))
+             functions show-sym)
+        (when (memq 'letter modes) (setq functions `(:letter ,name)))
+        (when (or (memq 'folder modes) (memq 'sequence modes))
+          (setq functions
+                (append `(,(if (memq 'folder modes) :folder :sequence) ,name)
+                        functions))
+          (setq show-sym
+                (if (string-match "^mh-\\(.*\\)$" name-str)
+                    (intern (concat "mh-show-" (match-string 1 name-str)))
+                  name))
+          (setq functions
+                (append `(,(if (memq 'folder modes) :show :show-seq)
+                          ,(if (fboundp show-sym) show-sym name))
+                        functions)))
+        (do ((functions functions (cddr functions)))
+            ((null functions))
+          (let* ((type (car functions))
+                 (function (cadr functions))
+                 (type1 (substring (symbol-name type) 1))
+                 (vector-list (cond ((eq type :show) 'show-vectors)
+                                    ((eq type :show-seq) 'show-vectors)
+                                    ((eq type :letter) 'letter-vectors)
+                                    (t 'folder-vectors)))
+                 (list (cond ((eq type :letter) 'mh-tool-bar-letter-buttons)
+                             (t 'mh-tool-bar-folder-buttons)))
+                 (key (intern (concat "mh-" type1 "toolbar-" name-str)))
+                 (setter (intern (concat type1 "-button-setter")))
+                 (mbuttons (cond ((eq type :letter) 'letter-buttons)
+                                 ((eq type :show) 'show-buttons)
+                                 ((eq type :show-seq) 'show-buttons)
+                                 (t 'folder-buttons)))
+                 (docs (cond ((eq mbuttons 'letter-buttons) 'letter-docs)
+                             ((eq mbuttons 'folder-buttons) 'folder-docs))))
+            (add-to-list vector-list `[,xemacs-icon ,function t ,full-doc])
+            (add-to-list
+             setter `(when (member ',name ,list)
+                       (mh-funcall-if-exists
+                        tool-bar-add-item ,icon ',function ',key
+                        :help ,doc :enable ',enable-expr)))
+            (add-to-list mbuttons name)
+            (if docs (add-to-list docs doc))))))
+    (setq folder-buttons (nreverse folder-buttons)
+          letter-buttons (nreverse letter-buttons)
+          show-buttons (nreverse show-buttons)
+          letter-docs (nreverse letter-docs)
+          folder-docs (nreverse folder-docs)
+          folder-vectors (nreverse folder-vectors)
+          show-vectors (nreverse show-vectors)
+          letter-vectors (nreverse letter-vectors))
+    (dolist (x folder-defaults)
+      (unless (memq x folder-buttons)
+        (error "Folder defaults contains unknown button '%s'" x)))
+    (dolist (x letter-defaults)
+      (unless (memq x letter-buttons)
+        (error "Letter defaults contains unknown button '%s'" x)))
+    `(eval-when (compile load eval)
+       (defvar mh-folder-tool-bar-map nil)
+       (defvar mh-folder-seq-tool-bar-map nil)
+       (defvar mh-show-tool-bar-map nil)
+       (defvar mh-show-seq-tool-bar-map nil)
+       (defvar mh-letter-tool-bar-map nil)
+       ;; GNU Emacs tool bar specific code
+       (mh-do-in-gnu-emacs
+         ;; Custom setter functions
+         (defun mh-tool-bar-folder-buttons-set (symbol value)
+           "Construct toolbar for `mh-folder-mode' and `mh-show-mode'."
+           (set-default symbol value)
+           (setq mh-folder-tool-bar-map
+                 (let ((tool-bar-map (make-sparse-keymap)))
+                   ,@(nreverse folder-button-setter)
+                   tool-bar-map))
+           (setq mh-show-tool-bar-map
+                 (let ((tool-bar-map (make-sparse-keymap)))
+                   ,@(nreverse show-button-setter)
+                   tool-bar-map))
+           (setq mh-show-seq-tool-bar-map
+                 (let ((tool-bar-map (copy-keymap mh-show-tool-bar-map)))
+                   ,@(nreverse show-seq-button-setter)
+                   tool-bar-map))
+           (setq mh-folder-seq-tool-bar-map
+                 (let ((tool-bar-map (copy-keymap mh-folder-tool-bar-map)))
+                   ,@(nreverse sequence-button-setter)
+                   tool-bar-map)))
+         (defun mh-tool-bar-letter-buttons-set (symbol value)
+           "Construct toolbar for `mh-letter-mode'."
+           (set-default symbol value)
+           (setq mh-letter-tool-bar-map
+                 (let ((tool-bar-map (make-sparse-keymap)))
+                   ,@(nreverse letter-button-setter)
+                   tool-bar-map))))
+       ;; XEmacs specific code
+       (mh-do-in-xemacs
+         (defvar mh-toolbar-folder-vector-map
+           ',(loop for button in folder-buttons
+                   for vector in folder-vectors
+                   collect (cons button vector)))
+         (defvar mh-toolbar-show-vector-map
+           ',(loop for button in show-buttons
+                   for vector in show-vectors
+                   collect (cons button vector)))
+         (defvar mh-toolbar-letter-vector-map
+           ',(loop for button in letter-buttons
+                   for vector in letter-vectors
+                   collect (cons button vector)))
+         (defvar mh-toolbar-folder-buttons nil)
+         (defvar mh-toolbar-show-buttons nil)
+         (defvar mh-toolbar-letter-buttons nil)
+         ;; Custom setter functions
+         (defun mh-tool-bar-letter-buttons-set (symbol value)
+           (set-default symbol value)
+           (when mh-xemacs-has-toolbar-flag
+             (setq mh-toolbar-letter-buttons
+                   (loop for b in value
+                         collect (cdr (assoc b mh-toolbar-letter-vector-map))))))
+         (defun mh-tool-bar-folder-buttons-set (symbol value)
+           (set-default symbol value)
+           (when mh-xemacs-has-toolbar-flag
+             (setq mh-toolbar-folder-buttons
+                   (loop for b in value
+                         collect (cdr (assoc b mh-toolbar-folder-vector-map))))
+             (setq mh-toolbar-show-buttons
+                   (loop for b in value
+                         collect (cdr (assoc b mh-toolbar-show-vector-map))))))
+         ;; Initialize toolbar
+         (defun mh-toolbar-init (mode)
+           "Install toolbar in MODE."
+           (let ((toolbar (cond ((eq mode :folder) mh-toolbar-folder-buttons)
+                                ((eq mode :letter) mh-toolbar-letter-buttons)
+                                ((eq mode :show) mh-toolbar-show-buttons)))
+                 (height 37)
+                 (width 40)
+                 (buffer (current-buffer)))
+             (when (and mh-xemacs-toolbar-position mh-xemacs-use-toolbar-flag
+                        mh-xemacs-has-toolbar-flag)
+               (cond
+                ((eq mh-xemacs-toolbar-position 'top)
+                 (set-specifier top-toolbar toolbar buffer)
+                 (set-specifier top-toolbar-visible-p t)
+                 (set-specifier top-toolbar-height height))
+                ((eq mh-xemacs-toolbar-position 'bottom)
+                 (set-specifier bottom-toolbar toolbar buffer)
+                 (set-specifier bottom-toolbar-visible-p t)
+                 (set-specifier bottom-toolbar-height height))
+                ((eq mh-xemacs-toolbar-position 'left)
+                 (set-specifier left-toolbar toolbar buffer)
+                 (set-specifier left-toolbar-visible-p t)
+                 (set-specifier left-toolbar-width width))
+                ((eq mh-xemacs-toolbar-position 'right)
+                 (set-specifier right-toolbar toolbar buffer)
+                 (set-specifier right-toolbar-visible-p t)
+                 (set-specifier right-toolbar-width width))
+                (t (set-specifier default-toolbar toolbar buffer)))))))
+       ;; Declare customizable toolbars
+       (custom-declare-variable
+        'mh-tool-bar-folder-buttons
+        '(list ,@(mapcar (lambda (x) `(quote ,x)) folder-defaults))
+        "Choose buttons to include in MH-E folder/show toolbar."
+        :group 'mh-toolbar :set 'mh-tool-bar-folder-buttons-set
+        :type '(set ,@(loop for x in folder-buttons
+                            for y in folder-docs
+                            collect `(const :tag ,y ,x))))
+       (custom-declare-variable
+        'mh-tool-bar-letter-buttons
+        '(list ,@(mapcar (lambda (x) `(quote ,x)) letter-defaults))
+        "Choose buttons to include in MH-E letter toolbar."
+        :group 'mh-toolbar :set 'mh-tool-bar-letter-buttons-set
+        :type '(set ,@(loop for x in letter-buttons
+                            for y in letter-docs
+                            collect `(const :tag ,y ,x)))))))
 
-(defcustom mh-alias-system-aliases
-  '("/etc/nmh/MailAliases" "/usr/lib/mh/MailAliases" "/etc/passwd")
-  "*A list of system files from which to cull aliases.
-If these files are modified, they are automatically reread. This list need
-include only system aliases and the passwd file, since personal alias files
-listed in your \"AliasFile\" MH profile component are automatically included.
-You can update the alias list manually using \\[mh-alias-reload]."
-  :type '(choice (file) (repeat file))
-  :group 'mh-alias)
+(mh-tool-bar-define
+    ((:folder mh-inc-folder mh-mime-save-parts mh-previous-undeleted-msg
+              mh-page-msg  mh-next-undeleted-msg mh-delete-msg mh-refile-msg
+              mh-undo mh-execute-commands mh-toggle-tick mh-reply
+              mh-alias-grab-from-field mh-send mh-rescan-folder
+              mh-tool-bar-search mh-visit-folder
+              mh-tool-bar-customize mh-tool-bar-folder-help mh-widen)
+     (:letter mh-send-letter mh-compose-insertion ispell-message save-buffer
+              undo kill-region menu-bar-kill-ring-save yank mh-fully-kill-draft
+              mh-tool-bar-customize mh-tool-bar-letter-help))
+  ;; Folder/Show buffer buttons
+  (mh-inc-folder (folder) "mail"
+    "Incorporate new mail in Inbox
+This button runs `mh-inc-folder' which drags any
+new mail into your Inbox folder.")
+  (mh-mime-save-parts (folder) "attach"
+    "Save MIME parts from this message
+This button runs `mh-mime-save-parts' which saves a message's
+different parts into separate files.")
+  (mh-previous-undeleted-msg (folder) "left_arrow"
+    "Go to the previous undeleted message
+This button runs `mh-previous-undeleted-msg'")
+  (mh-page-msg (folder) "page-down"
+    "Page the current message forwards\nThis button runs `mh-page-msg'")
+  (mh-next-undeleted-msg (folder) "right_arrow"
+    "Go to the next undeleted message\nThe button runs `mh-next-undeleted-msg'")
+  (mh-delete-msg (folder) "close"
+    "Mark this message for deletion\nThis button runs `mh-delete-msg'")
+  (mh-refile-msg (folder) "refile"
+    "Refile this message\nThis button runs `mh-refile-msg'")
+  (mh-undo (folder) "undo" "Undo last operation\nThis button runs `undo'"
+    (mh-outstanding-commands-p))
+  (mh-execute-commands (folder) "execute"
+    "Perform moves and deletes\nThis button runs `mh-execute-commands'"
+    (mh-outstanding-commands-p))
+  (mh-toggle-tick (folder) "highlight"
+    "Toggle tick mark\nThis button runs `mh-toggle-tick'")
+  (mh-toggle-showing (folder) "show"
+    "Toggle showing message\nThis button runs `mh-toggle-showing'")
+  (mh-tool-bar-reply-from (folder) "reply-from" "Reply to \"from\"")
+  (mh-tool-bar-reply-to (folder) "reply-to" "Reply to \"to\"")
+  (mh-tool-bar-reply-all (folder) "reply-all" "Reply to \"all\"")
+  (mh-reply (folder) "mail/reply2"
+    "Reply to this message\nThis button runs `mh-reply'")
+  (mh-alias-grab-from-field (folder) "alias"
+    "Grab From alias\nThis button runs `mh-alias-grab-from-field'"
+    (and (mh-extract-from-header-value) (not (mh-alias-for-from-p))))
+  (mh-send (folder) "mail_compose"
+    "Compose new message\nThis button runs `mh-send'")
+  (mh-rescan-folder (folder) "rescan"
+    "Rescan this folder\nThis button runs `mh-rescan-folder'")
+  (mh-pack-folder (folder) "repack"
+    "Repack this folder\nThis button runs `mh-pack-folder'")
+  (mh-tool-bar-search (folder) "search"
+    "Search\nThis button runs `mh-tool-bar-search-function'")
+  (mh-visit-folder (folder) "fld_open"
+    "Visit other folder\nThis button runs `mh-visit-folder'")
+  ;; Letter buffer buttons
+  (mh-send-letter (letter) "mail_send" "Send this letter")
+  (mh-compose-insertion (letter) "attach" "Insert attachment")
+  (ispell-message (letter) "spell" "Check spelling")
+  (save-buffer (letter) "save" "Save current buffer to its file"
+    (buffer-modified-p))
+  (undo (letter) "undo" "Undo last operation")
+  (kill-region (letter) "cut"
+    "Cut (kill) text in region between mark and current position")
+  (menu-bar-kill-ring-save (letter) "copy"
+    "Copy text in region between mark and current position")
+  (yank (letter) "paste" "Paste (yank) text cut or copied earlier")
+  (mh-fully-kill-draft (letter) "close" "Kill this draft")
+  ;; Common buttons
+  (mh-tool-bar-customize (folder letter) "preferences" "MH-E Preferences")
+  (mh-tool-bar-folder-help (folder) "help"
+    "Help! (general help)\nThis button runs `Info-goto-node'")
+  (mh-tool-bar-letter-help (letter) "help"
+    "Help! (general help)\nThis button runs `Info-goto-node'")
+  ;; Folder narrowed to sequence buttons
+  (mh-widen (sequence) "widen"
+    "Widen from the sequence\nThis button runs `mh-widen'"))
 
 \f
 
-;;; Multiple personalities (:group 'mh-identity)
-
-(defcustom mh-identity-list nil
-  "*List holding MH-E identity.
-Omit the colon and trailing space from the field names.
-The keyword name \"none\" is reserved for internal use.
-Use the keyname name \"signature\" to specify either a signature file or a
-function to call to insert a signature at point.
-
-Providing an empty Value (\"\") will cause the field to be deleted.
-
-Example entries using the customize interface:
-   Keyword name: work
-            From
-            Value: John Doe <john@work.com>
-            Organization
-            Value: Acme Inc.
-   Keyword name: home
-            From
-            Value: John Doe <johndoe@home.net>
-            Organization
-            Value:
-
-This would produce the equivalent of:
- (setq mh-identity-list
-      '((\"work\"
-         ((\"From\" . \"John Doe <john@work.com>\")
-          (\"Organization\" . \"Acme Inc.\")))
-        (\"home\"
-         ((\"From\" . \"John Doe <johndoe@home.net>\")
-          (\"Organization\" . \"\")))))"
-  :type '(repeat (list :tag ""
-                       (string :tag "Keyword name")
-                       (repeat :tag "At least one pair from below"
-                               (choice (cons :tag "From field"
-                                             (const "From")
-                                             (string :tag "Value"))
-                                       (cons :tag "Organization field"
-                                             (const "Organization")
-                                             (string :tag "Value"))
-                                       (cons :tag "Signature"
-                                             (const "signature")
-                                             (choice (file) (function)))
-                                       (cons :tag "Other field & value pair"
-                                             (string :tag "Field")
-                                             (string :tag "Value"))))))
-  :set 'mh-identity-list-set
-  :group 'mh-identity)
-
-(defcustom mh-auto-fields-list nil
-  "Alist of addresses for which header lines are automatically inserted.
-Each element has the form (REGEXP ((KEYWORD VALUE) (KEYWORD VALUE)).
-When the REGEXP appears in the To or cc fields of a message, the corresponding
-KEYWORD header field is insert with its VALUE in the message header.
+;;; Hooks (:group 'mh-hooks + group where hook described)
 
-There is one special case for KEYWORD, that of \"identity\", which means to
-insert that identity using `mh-insert-identity'.
+(defcustom mail-citation-hook nil
+  "*Hook for modifying a citation just inserted in the mail buffer.
+Each hook function can find the citation between point and mark.
+And each hook function should leave point and mark around the citation
+text as modified.
 
-The common KEYWORD cases of \"Mail-Followup-To\" and \"fcc\" are also
-prompted for in the customization interface."
-  :type `(repeat
-          (list :tag ""
-                (string :tag "Regular expression to match")
-                (repeat :tag "At least one pair from below"
-                        (choice
-                         (cons :tag "Identity entry"
-                          (const "identity")
-                          ,(append
-                            '(radio)
-                            (mapcar (function (lambda (arg) `(const ,arg)))
-                                    (mapcar 'car mh-identity-list))))
-                         (cons :tag "fcc field"
-                               (const "fcc")
-                               (string :tag "Value"))
-                         (cons :tag "Mail-Followup-To field"
-                               (const "Mail-Followup-To")
-                               (string :tag "Value"))
-                         (cons :tag "Other field and value pair"
-                                 (string :tag "Field")
-                                 (string :tag "Value"))))))
-  :group 'mh-identity)
+If this hook is entirely empty (nil), the text of the message is inserted
+with `mh-ins-buf-prefix' prefixed to each line.
 
-(defcustom mh-identity-default nil
-  "Default identity to use when `mh-letter-mode' is called."
-  ;; Dynamically render :type corresponding to `mh-identity-list' entries,
-  ;; e.g.:
-  ;;  :type '(radio (const :tag "none" nil)
-  ;;                (const "home")
-  ;;                (const "work"))
-  :type (append
-         '(radio)
-         (cons '(const :tag "None" nil)
-               (mapcar (function (lambda (arg) `(const ,arg)))
-                       (mapcar 'car mh-identity-list))))
-  :group 'mh-identity)
+See also the variable `mh-yank-from-start-of-msg', which controls how
+much of the message passed to the hook.
 
-\f
+This hook was historically provided to set up supercite.  You may now leave
+this nil and set up supercite by setting the variable
+`mh-yank-from-start-of-msg' to 'supercite or, for more automatic insertion,
+to 'autosupercite.
 
-;;; Hooks (:group 'mh-hooks + group where hook defined)
+The hook 'trivial-cite is NOT part of Emacs.  It is provided from tc.el,
+available here:
+ http://shasta.cs.uiuc.edu/~lrclause/tc.html
+If you use it, customize `mh-yank-from-start-of-msg' to
+ \"Entire message with headers\"."
+  :type 'hook
+  :options '(trivial-cite)
+  :group 'mh-hooks
+  :group 'mh-letter)
 
-;;; These are alphabetized. All hooks should be placed in the 'mh-hook group;
-;;; in addition, add the group in which the hook is defined in the manual (or,
-;;; if it is new, where it would be defined).
+(defcustom mh-alias-reloaded-hook nil
+  "Invoked by `mh-alias-reload' after reloading aliases."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-alias)
 
 (defcustom mh-before-quit-hook nil
   "Invoked by \\<mh-folder-mode-map>`\\[mh-quit]' before quitting MH-E.
 See also `mh-quit-hook'."
   :type 'hook
   :group 'mh-hooks
-  :group 'mh-folder)
+  :group 'mh-show)
 
 (defcustom mh-before-send-letter-hook nil
   "Invoked at the beginning of the \\<mh-letter-mode-map>\\[mh-send-letter] command."
@@ -1684,7 +1962,7 @@ See also `mh-quit-hook'."
   "Invoked after marking each message for deletion."
   :type 'hook
   :group 'mh-hooks
-  :group 'mh-folder)
+  :group 'mh-show)
 
 (defcustom mh-edit-mhn-hook nil
   "Invoked on the formatted letter by \\<mh-letter-mode-map>\\[mh-edit-mhn]."
@@ -1696,13 +1974,13 @@ See also `mh-quit-hook'."
   "Invoked by `mh-find-path' after reading the user's MH profile."
   :type 'hook
   :group 'mh-hooks
-  :group 'mh-folder)
+  :group 'mh-show)
 
 (defcustom mh-folder-mode-hook nil
   "Invoked in `mh-folder-mode' on a new folder."
   :type 'hook
   :group 'mh-hooks
-  :group 'mh-folder)
+  :group 'mh-show)
 
 (defcustom mh-folder-updated-hook nil
   "Invoked when the folder actions (such as moves and deletes) are performed.
@@ -1712,11 +1990,17 @@ current folder, `mh-current-folder'."
   :type 'hook
   :group 'mh-hooks)
 
+(defcustom mh-forward-hook nil
+  "Invoked on the forwarded letter by \\<mh-folder-mode-map>\\[mh-forward]."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-folder)
+
 (defcustom mh-inc-folder-hook nil
   "Invoked by \\<mh-folder-mode-map>`\\[mh-inc-folder]' after incorporating mail into a folder."
   :type 'hook
   :group 'mh-hooks
-  :group 'mh-folder)
+  :group 'mh-inc)
 
 (defcustom mh-kill-folder-suppress-prompt-hook '(mh-index-p)
   "Invoked at the beginning of the  \\<mh-folder-mode-map>`\\[mh-kill-folder]' command.
@@ -1733,13 +2017,12 @@ t on +inbox and you hit \\<mh-folder-mode-map>`\\[mh-kill-folder]' by accident
 in the +inbox buffer, you will not be happy."
   :type 'hook
   :group 'mh-hooks
-  :group 'mh-folder)
+  :group 'mh-show)
 
 (defcustom mh-letter-insert-signature-hook nil
-  "Invoked at the beginning of the \\<mh-letter-mode-map>\\[mh-insert-signature] command.
-Can be used to determine which signature file to use based on message content.
-On return, if `mh-signature-file-name' is non-nil that file will be inserted at
-the current point in the buffer."
+  "Invoked after signature has been inserted.
+This hook may access the actual name of the file or the function used to
+insert the signature with `mh-signature-file-name'."
   :type 'hook
   :group 'mh-hooks
   :group 'mh-letter)
@@ -1748,26 +2031,26 @@ the current point in the buffer."
   "Invoked in `mh-letter-mode' on a new letter."
   :type 'hook
   :group 'mh-hooks
-  :group 'mh-letter)
+  :group 'mh-sending-mail)
 
 (defcustom mh-pick-mode-hook nil
   "Invoked upon entry to `mh-pick-mode'."
   :type 'hook
   :group 'mh-hooks
-  :group 'mh-folder)
+  :group 'mh-index)
 
 (defcustom mh-quit-hook nil
   "Invoked after \\<mh-folder-mode-map>`\\[mh-quit]' quits MH-E.
 See also `mh-before-quit-hook'."
   :type 'hook
   :group 'mh-hooks
-  :group 'mh-folder)
+  :group 'mh-show)
 
 (defcustom mh-refile-msg-hook nil
   "Invoked after marking each message for refiling."
   :type 'hook
   :group 'mh-hooks
-  :group 'mh-folder)
+  :group 'mh-show)
 
 (defcustom mh-show-hook nil
   "Invoked after \\<mh-folder-mode-map>`\\[mh-show]' shows a message."
@@ -1787,44 +2070,13 @@ The variable `mh-seen-list' can be used to obtain the list of messages which
 will be removed from the unseen sequence."
   :type 'hook
   :group 'mh-hooks
-  :group 'mh-folder)
+  :group 'mh-show)
 
 \f
 
-;;; Faces
-
-;;; Faces used in speedbar (:group mh-speed-faces)
-
-(defface mh-speedbar-folder-face
-  '((((class color) (background light))
-     (:foreground "blue4"))
-    (((class color) (background dark))
-     (:foreground "light blue")))
-  "Face used for folders in the speedbar buffer."
-  :group 'mh-speed-faces)
-
-(defface mh-speedbar-selected-folder-face
-  '((((class color) (background light))
-     (:foreground "red" :underline t))
-    (((class color) (background dark))
-     (:foreground "red" :underline t))
-    (t (:underline t)))
-  "Face used for the current folder."
-  :group 'mh-speed-faces)
+;;; Faces (:group 'mh-*-faces + group where faces described)
 
-(defface mh-speedbar-folder-with-unseen-messages-face
-  '((t (:inherit mh-speedbar-folder-face :bold t)))
-  "Face used for folders in the speedbar buffer which have unread messages."
-  :group 'mh-speed-faces)
-
-(defface mh-speedbar-selected-folder-with-unseen-messages-face
-  '((t (:inherit mh-speedbar-selected-folder-face :bold t)))
-  "Face used for the current folder when it has unread messages."
-  :group 'mh-speed-faces)
-
-\f
-
-;;; Faces used in scan listing (:group mh-folder-faces)
+;;; Faces Used in Scan Listing (:group 'mh-folder-faces)
 
 (defvar mh-folder-body-face 'mh-folder-body-face
   "Face for highlighting body text in MH-Folder buffers.")
@@ -1962,7 +2214,36 @@ will be removed from the unseen sequence."
 
 \f
 
-;;; Faces used in message display (:group mh-show-faces)
+;;; Faces Used in Searching (:group 'mh-index-faces)
+
+(defvar mh-index-folder-face 'mh-index-folder-face
+  "Face for highlighting folders in MH-Index buffers.")
+(defface mh-index-folder-face
+  '((((class color) (background light))
+     (:foreground "dark green" :bold t))
+    (((class color) (background dark))
+     (:foreground "indian red" :bold t))
+    (t
+     (:bold t)))
+  "Face for highlighting folders in MH-Index buffers."
+  :group 'mh-index-faces)
+
+\f
+
+;;; Faces Used in Message Drafts (:group 'mh-letter-faces)
+
+(defface mh-letter-header-field-face
+  '((((class color) (background light))
+     (:background "gray90"))
+    (((class color) (background dark))
+     (:background "gray10"))
+    (t (:bold t)))
+  "Face for displaying header fields in draft buffers."
+  :group 'mh-letter-faces)
+
+\f
+
+;;; Faces Used in Message Display (:group 'mh-show-faces)
 
 (defvar mh-show-cc-face 'mh-show-cc-face
   "Face for highlighting cc header fields.")
@@ -2002,6 +2283,11 @@ will be removed from the unseen sequence."
   "Face used to deemphasize unspecified header fields."
   :group 'mh-show-faces)
 
+(defface mh-show-signature-face
+  '((t (:italic t)))
+  "Face for highlighting message signature."
+  :group 'mh-show-faces)
+
 (defvar mh-show-to-face 'mh-show-to-face
   "Face for highlighting the To: header field.")
 (if (boundp 'facemenu-unlisted-faces)
@@ -2041,32 +2327,34 @@ The background and foreground is used in the image."
 
 \f
 
-;;; Faces used in indexed searches (:group mh-index-faces)
+;;; Faces Used in Speedbar (:group 'mh-speed-faces)
 
-(defvar mh-index-folder-face 'mh-index-folder-face
-  "Face for highlighting folders in MH-Index buffers.")
-(defface mh-index-folder-face
+(defface mh-speedbar-folder-face
   '((((class color) (background light))
-     (:foreground "dark green" :bold t))
+     (:foreground "blue4"))
     (((class color) (background dark))
-     (:foreground "indian red" :bold t))
-    (t
-     (:bold t)))
-  "Face for highlighting folders in MH-Index buffers."
-  :group 'mh-index-faces)
-
-\f
-
-;;; Faces used when composing messages.
+     (:foreground "light blue")))
+  "Face used for folders in the speedbar buffer."
+  :group 'mh-speed-faces)
 
-(defface mh-letter-header-field-face
+(defface mh-speedbar-selected-folder-face
   '((((class color) (background light))
-     (:background "gray90"))
+     (:foreground "red" :underline t))
     (((class color) (background dark))
-     (:background "gray10"))
-    (t (:bold t)))
-  "Face for displaying header fields in draft buffers."
-  :group 'mh-letter-faces)
+     (:foreground "red" :underline t))
+    (t (:underline t)))
+  "Face used for the current folder."
+  :group 'mh-speed-faces)
+
+(defface mh-speedbar-folder-with-unseen-messages-face
+  '((t (:inherit mh-speedbar-folder-face :bold t)))
+  "Face used for folders in the speedbar buffer which have unread messages."
+  :group 'mh-speed-faces)
+
+(defface mh-speedbar-selected-folder-with-unseen-messages-face
+  '((t (:inherit mh-speedbar-selected-folder-face :bold t)))
+  "Face used for the current folder when it has unread messages."
+  :group 'mh-speed-faces)
 
 ;;; Local Variables:
 ;;; indent-tabs-mode: nil
index e72304c..5cb7f90 100644 (file)
@@ -5,7 +5,7 @@
 
 ;; Author: Bill Wohler <wohler@newt.com>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
-;; Version: 7.4.4
+;; Version: 7.4.80
 ;; Keywords: mail
 
 ;; This file is part of GNU Emacs.
 
 ;; 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)
-(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)))
 
+(eval-when-compile (require 'mh-acros))
+(mh-require-cl)
+(require 'mh-utils)
+(require 'mh-init)
 (require 'mh-inc)
 (require 'gnus-util)
 (require 'easymenu)
 (defvar font-lock-auto-fontify)
 (defvar font-lock-defaults)
 
-(defconst mh-version "7.4.4" "Version number of MH-E.")
+(defconst mh-version "7.4.80" "Version number of MH-E.")
 
 ;;; Autoloads
 (autoload 'Info-goto-node "info")
 
-\f
-
-(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.")
 
+\f
+;;; 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 +137,10 @@ This format is identical to the default except that additional hints for
 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 +162,94 @@ This format is identical to the default except that additional hints for
 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
+                     \"*\\\\(..................\\\\)\")\".")
 
 \f
 
@@ -279,10 +281,7 @@ third should match the user name.")
    ;; 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 +355,6 @@ This column will only ever have spaces in it.")
 
 ;; 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 +451,8 @@ is done highlighting.")
                                         ;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 +464,7 @@ is done highlighting.")
 (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 +480,7 @@ is done highlighting.")
 (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 +493,7 @@ the Emacs front end to the MH mail system."
 (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 +577,7 @@ Do not call this function from outside MH-E; use \\[mh-rmail] instead."
       (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 +621,26 @@ last undeleted message then pause for a second after printing message."
            (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 +678,24 @@ Returns nil if the address was not found in either place or if the variable
   "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 +834,9 @@ are skipped."
                (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 +1054,7 @@ interactive use."
   (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 +1087,6 @@ compiled then macro expansion happens at compile time."
 (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 +1103,12 @@ compiled then macro expansion happens at compile time."
   ;; 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 +1158,7 @@ used to avoid problems in corner cases involving folders whose names end with a
 (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 +1192,7 @@ regardless of the size of the `mh-large-folder' variable."
   (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 +1215,11 @@ regardless of the size of the `mh-large-folder' variable."
            (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 +1290,7 @@ arguments, after the message has been refiled."
                (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 +1337,9 @@ With optional argument COUNT, COUNT-1 unread messages are skipped."
                (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 +1430,12 @@ Make it the current folder."
     ["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 +1459,7 @@ Make it the current folder."
     ["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 +1499,12 @@ is used in previous versions and XEmacs."
   (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 +1512,49 @@ You can show the message the cursor is pointing to, and step through the
 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 +1562,15 @@ When a folder is visited, the hook `mh-folder-mode-hook' is run.
   (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 +1599,8 @@ When a folder is visited, the hook `mh-folder-mode-hook' is run.
    '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 +1624,26 @@ When a folder is visited, the hook `mh-folder-mode-hook' is run.
            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 +1655,11 @@ When a folder is visited, the hook `mh-folder-mode-hook' is run.
 (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 +1669,8 @@ When a folder is visited, the hook `mh-folder-mode-hook' is run.
 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 +1723,9 @@ If UPDATE, append the scan lines, otherwise replace."
       (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 +1901,21 @@ in what is now stored in the buffer-local variable `mh-mode-line-annotation'."
                                   (""))))))
       (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 +1937,11 @@ If ALL is non-nil, then all sequence marks on the scan line are removed."
         (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 +1964,7 @@ If ALL is non-nil, then all sequence marks on the scan line are removed."
       (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 +2113,10 @@ with no arguments, after the unseen sequence is updated."
 
 (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 +2237,7 @@ numbers, a sequence, a region in a cons cell. If nil all messages are notated."
   "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 +2278,15 @@ change."
       (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 +2314,6 @@ Signals an error if SEQ is an illegal name."
                            "-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."
@@ -2362,7 +2368,6 @@ If INCLUDE-INTERNAL-FLAG non-nil, include MH-E internal sequences in list."
   "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 +2387,7 @@ If INCLUDE-INTERNAL-FLAG non-nil, include MH-E internal sequences in list."
   "?"           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 +2408,17 @@ If INCLUDE-INTERNAL-FLAG non-nil, include MH-E internal sequences in list."
   "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 +2463,10 @@ If INCLUDE-INTERNAL-FLAG non-nil, include MH-E internal sequences in list."
 (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
@@ -2484,6 +2503,9 @@ If INCLUDE-INTERNAL-FLAG non-nil, include MH-E internal sequences in list."
     (?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")
index 4620186..ef745f4 100644 (file)
@@ -1,6 +1,6 @@
 ;;; mh-funcs.el --- MH-E functions not everyone will use right away
 
-;; Copyright (C) 1993, 1995, 2001, 02, 2003 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1995, 2001, 02, 03, 2004 Free Software Foundation, Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
@@ -34,6 +34,8 @@
 
 ;;; Code:
 
+(eval-when-compile (require 'mh-acros))
+(mh-require-cl)
 (require 'mh-e)
 
 ;;; Customization
@@ -45,11 +47,13 @@ prefix argument.  Normally default arguments to sortm are specified in the
 MH profile.
 For example, '(\"-nolimit\" \"-textfield\" \"subject\") is a useful setting.")
 
+;;; Scan Line Formats
+
 (defvar mh-note-copied "C"
-  "String whose first character is used to notate copied messages.")
+  "Copied messages are marked by this character.")
 
 (defvar mh-note-printed "P"
-  "String whose first character is used to notate printed messages.")
+  "Messages that have been printed are marked by this character.")
 
 ;;; Functions
 
@@ -232,60 +236,6 @@ Otherwise just send the message's body without the headers."
         (forward-line 2))
     (mh-recenter 0)))
 
-;;;###mh-autoload
-(defun mh-print-msg (range)
-  "Print RANGE on printer.
-
-Check the documentation of `mh-interactive-range' to see how RANGE is read in
-interactive use.
-
-The variable `mh-lpr-command-format' is used to generate the print command.
-The messages are formatted by mhl. See the variable `mhl-formfile'."
-  (interactive (list (mh-interactive-range "Print")))
-  (message "Printing...")
-  (let (msgs)
-    ;; Gather message numbers and add them to "printed" sequence.
-    (mh-iterate-on-range msg range
-      (mh-add-msgs-to-seq msg 'printed t)
-      (mh-notate nil mh-note-printed mh-cmd-note)
-      (push msg msgs))
-    (setq msgs (nreverse msgs))
-    ;; Print scan listing if we have more than one message.
-    (if (> (length msgs) 1)
-        (let* ((msgs-string
-                (mapconcat 'identity (mh-list-to-string
-                                      (mh-coalesce-msg-list msgs)) " "))
-               (lpr-command
-                (format mh-lpr-command-format
-                        (cond ((listp range)
-                               (format "Folder: %s, Messages: %s"
-                                       mh-current-folder msgs-string))
-                              ((symbolp range)
-                               (format "Folder: %s, Sequence: %s"
-                                       mh-current-folder range)))))
-               (scan-command
-                (format "scan %s | %s" msgs-string lpr-command)))
-          (if mh-print-background-flag
-              (mh-exec-cmd-daemon shell-file-name nil "-c" scan-command)
-            (call-process shell-file-name nil nil nil "-c" scan-command))))
-    ;; Print the messages
-    (dolist (msg msgs)
-      (let* ((mhl-command (format "%s %s %s"
-                                  (expand-file-name "mhl" mh-lib-progs)
-                                  (if mhl-formfile
-                                      (format " -form %s" mhl-formfile)
-                                    "")
-                                  (mh-msg-filename msg)))
-             (lpr-command
-              (format mh-lpr-command-format
-                      (format "%s/%s" mh-current-folder msg)))
-             (print-command
-              (format "%s | %s" mhl-command lpr-command)))
-        (if mh-print-background-flag
-            (mh-exec-cmd-daemon shell-file-name nil "-c" print-command)
-          (call-process shell-file-name nil nil nil "-c" print-command)))))
-  (message "Printing...done"))
-
 ;;;###mh-autoload
 (defun mh-sort-folder (&optional extra-args)
   "Sort the messages in the current folder by date.
@@ -307,9 +257,8 @@ argument EXTRA-ARGS is given."
           (mh-index-data (mh-index-insert-folder-headers)))))
 
 ;;;###mh-autoload
-(defun mh-undo-folder (&rest ignore)
-  "Undo all pending deletes and refiles in current folder.
-Argument IGNORE is deprecated."
+(defun mh-undo-folder ()
+  "Undo all pending deletes and refiles in current folder."
   (interactive)
   (cond ((or mh-do-not-confirm-flag
              (yes-or-no-p "Undo all commands in folder? "))
@@ -320,10 +269,7 @@ Argument IGNORE is deprecated."
          (with-mh-folder-updating (nil)
            (mh-remove-all-notation)))
         (t
-         (message "Commands not undone.")
-         ;; Remove by 2003-06-30 if nothing seems amiss. XXX
-         ;; (sit-for 2)
-         )))
+         (message "Commands not undone"))))
 
 ;;;###mh-autoload
 (defun mh-store-msg (directory)
@@ -413,11 +359,15 @@ Default directory is the last directory used, or initially the value of
 
 ;;;###mh-autoload
 (defun mh-help ()
-  "Display cheat sheet for the MH-Folder commands in minibuffer."
+  "Display cheat sheet for the MH-E commands."
   (interactive)
-  (mh-ephem-message
-   (substitute-command-keys
-    (mapconcat 'identity (cdr (assoc nil mh-help-messages)) ""))))
+  (with-electric-help
+   (function
+    (lambda ()
+      (insert
+       (substitute-command-keys
+        (mapconcat 'identity (cdr (assoc nil mh-help-messages)) ""))))
+    mh-help-buffer)))
 
 ;;;###mh-autoload
 (defun mh-prefix-help ()
@@ -430,9 +380,14 @@ Default directory is the last directory used, or initially the value of
   ;; from the recent keys.
   (let* ((keys (recent-keys))
          (prefix-char (elt keys (- (length keys) 2))))
-    (mh-ephem-message
-     (substitute-command-keys
-      (mapconcat 'identity (cdr (assoc prefix-char mh-help-messages)) "")))))
+    (with-electric-help
+     (function
+      (lambda ()
+        (insert
+         (substitute-command-keys
+          (mapconcat 'identity
+                     (cdr (assoc prefix-char mh-help-messages)) "")))))
+     mh-help-buffer)))
 
 (provide 'mh-funcs)
 
index 0a893ef..b850c8f 100644 (file)
@@ -1,6 +1,6 @@
 ;;; mh-gnus.el --- Make MH-E compatible with installed version of Gnus.
 
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
 
 ;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
@@ -34,6 +34,7 @@
 (load "mm-uu" t t)                      ; Non-fatal dependency
 (load "mailcap" t t)                    ; Non-fatal dependency
 (load "smiley" t t)                     ; Non-fatal dependency
+(load "mailabbrev" t t)
 
 (defmacro mh-defun-compat (function arg-list &rest body)
   "This is a macro to define functions which are not defined.
@@ -74,12 +75,28 @@ BODY."
       (put-text-property 0 (length (car handle)) parameter value
                          (car handle))))
 
+;; Copy of function from mm-view.el
+(mh-defun-compat mm-inline-text-vcard (handle)
+  (let (buffer-read-only)
+    (mm-insert-inline
+     handle
+     (concat "\n-- \n"
+            (ignore-errors
+              (if (fboundp 'vcard-pretty-print)
+                  (vcard-pretty-print (mm-get-part handle))
+                (vcard-format-string
+                 (vcard-parse-string (mm-get-part handle)
+                                     'vcard-standard-filter))))))))
+
+;; Function from mm-decode.el used in PGP messages. Just define it with older
+;; gnus to avoid compiler warning.
+(mh-defun-compat mm-possibly-verify-or-decrypt (parts ctl)
+  nil)
+
 ;; Copy of original macro is in mm-decode.el
 (mh-defmacro-compat mm-handle-multipart-ctl-parameter (handle parameter)
   `(get-text-property 0 ,parameter (car ,handle)))
 
-(mh-do-in-xemacs (defvar default-enable-multibyte-characters))
-
 ;; Copy of original function in mm-decode.el
 (mh-defun-compat mm-readable-p (handle)
   "Say whether the content of HANDLE is readable."
@@ -134,10 +151,23 @@ BODY."
                                   file)))
          (mm-save-part-to-file handle file))))
 
+(defun mh-mm-text-html-renderer ()
+  "Find the renderer gnus is using to display text/html MIME parts."
+  (or (and (boundp 'mm-inline-text-html-renderer) mm-inline-text-html-renderer)
+      (and (boundp 'mm-text-html-renderer) mm-text-html-renderer)))
+
+(defun mh-mail-abbrev-make-syntax-table ()
+  "Call `mail-abbrev-make-syntax-table' if available."
+  (when (fboundp 'mail-abbrev-make-syntax-table)
+    (mail-abbrev-make-syntax-table)))
+
 (provide 'mh-gnus)
+
 ;;; Local Variables:
 ;;; no-byte-compile: t
 ;;; no-update-autoloads: t
+;;; indent-tabs-mode: nil
+;;; sentence-end-double-space: nil
 ;;; End:
 
 ;; arch-tag: 1e3638af-cad3-4c69-8427-bc8eb6e5e4fa
index f4edc7a..2b430a5 100644 (file)
 
 ;;; Code:
 
-
-(require 'mh-utils)
+(eval-when-compile (require 'mh-acros))
 (mh-require-cl)
-
-(eval-when (compile load eval)
-  (defvar mh-comp-loaded nil)
-  (unless mh-comp-loaded
-    (setq mh-comp-loaded t)
-    (require 'mh-comp)))                   ;Since we do this on sending
+(require 'mh-comp)
 
 (autoload 'mml-insert-tag "mml")
 
+(defvar mh-identity-pgg-default-user-id nil
+  "Holds the GPG key ID to be used by pgg.el.
+This is normally set as part of an Identity in `mh-identity-list'.")
+(make-variable-buffer-local 'mh-identity-pgg-default-user-id)
+
 ;;;###mh-autoload
 (defun mh-identity-make-menu ()
-  "Build (or rebuild) the Identity menu (e.g. after the list is modified)."
-  (when (and mh-identity-list (boundp 'mh-letter-mode-map))
-    (easy-menu-define mh-identity-menu mh-letter-mode-map
-      "mh-e identity menu"
-      (append
-       '("Identity")
-       ;; Dynamically render :type corresponding to `mh-identity-list'
-       ;; e.g.:
-       ;;  ["home" (mh-insert-identity "home")
-       ;;   :style radio :active (not (equal mh-identity-local "home"))
-       ;;   :selected (equal mh-identity-local "home")]
-       '(["Insert Auto Fields" (mh-insert-auto-fields) mh-auto-fields-list]
-         "--")
-       (mapcar (function
-                (lambda (arg)
-                  `[,arg  (mh-insert-identity ,arg) :style radio
-                          :active (not (equal mh-identity-local ,arg))
-                          :selected (equal mh-identity-local ,arg)]))
-               (mapcar 'car mh-identity-list))
-       '("--"
-         ["none" (mh-insert-identity "none") mh-identity-local]
-         ["Set Default for Session"
-          (setq mh-identity-default mh-identity-local) t]
-         ["Save as Default"
-          (customize-save-variable
-           'mh-identity-default mh-identity-local) t]
-         )))))
+  "Build the Identity menu.
+This should be called any time `mh-identity-list' or `mh-auto-fields-list'
+change."
+  (easy-menu-define mh-identity-menu mh-letter-mode-map
+    "MH-E identity menu"
+    (append
+     '("Identity")
+     ;; Dynamically render :type corresponding to `mh-identity-list'
+     ;; e.g.:
+     ;;  ["Home" (mh-insert-identity "Home")
+     ;;   :style radio :active (not (equal mh-identity-local "Home"))
+     ;;   :selected (equal mh-identity-local "Home")]
+     '(["Insert Auto Fields"
+        (mh-insert-auto-fields) mh-auto-fields-list]
+       "--")
+
+     (mapcar (function
+              (lambda (arg)
+                `[,arg  (mh-insert-identity ,arg) :style radio
+                        :selected (equal mh-identity-local ,arg)]))
+             (mapcar 'car mh-identity-list))
+     '(["None"
+        (mh-insert-identity "None") :style radio
+        :selected (not mh-identity-local)]
+       "--"
+       ["Set Default for Session"
+        (setq mh-identity-default mh-identity-local) t]
+       ["Save as Default"
+        (customize-save-variable 'mh-identity-default mh-identity-local) t]
+       ["Customize Identities" (customize-variable 'mh-identity-list) t]
+       ))))
 
 ;;;###mh-autoload
 (defun mh-identity-list-set (symbol value)
@@ -97,21 +100,36 @@ customization).  This is called after 'customize is used to alter
 (defun mh-header-field-delete (field value-only)
   "Delete FIELD in the mail header, or only its value if VALUE-ONLY is t.
 Return t if anything is deleted."
-  (when (mh-goto-header-field field)
-    (if (not value-only)
-        (beginning-of-line)
-      (forward-char))
-    (delete-region (point)
-                   (progn (mh-header-field-end)
-                          (if (not value-only) (forward-char 1))
-                          (point)))
-    t))
+  (let ((field-colon (if (string-match "^.*:$" field)
+                         field
+                       (concat field ":"))))
+    (when (mh-goto-header-field field-colon)
+      (if (not value-only)
+          (beginning-of-line)
+        (forward-char))
+      (delete-region (point)
+                     (progn (mh-header-field-end)
+                            (if (not value-only) (forward-char 1))
+                            (point)))
+      t)))
 
 (defvar mh-identity-signature-start nil
   "Marker for the beginning of a signature inserted by `mh-insert-identity'.")
 (defvar mh-identity-signature-end nil
   "Marker for the end of a signature inserted by `mh-insert-identity'.")
 
+(defun mh-identity-field-handler (field)
+  "Return the handler for a FIELD or nil if none set.
+The field name is downcased. If the FIELD begins with the character
+`:', then it must have a special handler defined in
+`mh-identity-handlers', else return an error since it is not a legal
+message header."
+  (or (cdr (assoc (downcase field) mh-identity-handlers))
+      (and (eq (aref field 0) ?:)
+           (error (format "Field %s - unknown mh-identity-handler" field)))
+      (cdr (assoc "default" mh-identity-handlers))
+      'mh-identity-handler-default))
+
 ;;;###mh-autoload
 (defun mh-insert-identity (identity)
   "Insert proper fields for given IDENTITY.
@@ -120,7 +138,7 @@ Edit the `mh-identity-list' variable to define identity."
    (list (completing-read
           "Identity: "
           (if mh-identity-local
-              (cons '("none")
+              (cons '("None")
                     (mapcar 'list (mapcar 'car mh-identity-list)))
             (mapcar 'list (mapcar 'car mh-identity-list)))
           nil t)))
@@ -129,83 +147,135 @@ Edit the `mh-identity-list' variable to define identity."
     (when mh-identity-local
       (let ((pers-list (cadr (assoc mh-identity-local mh-identity-list))))
         (while pers-list
-          (let ((field (concat (caar pers-list) ":")))
-            (cond
-             ((string-equal "signature:" field)
-              (when (and (boundp 'mh-identity-signature-start)
-                         (markerp mh-identity-signature-start))
-                (goto-char mh-identity-signature-start)
-                (forward-char -1)
-                (delete-region (point) mh-identity-signature-end)))
-             ((mh-header-field-delete field nil))))
+          (let* ((field (caar pers-list))
+                 (handler (mh-identity-field-handler field)))
+            (funcall handler field 'remove))
           (setq pers-list (cdr pers-list)))))
     ;; Then insert the replacement
-    (when (not (equal "none" identity))
+    (when (not (equal "None" identity))
       (let ((pers-list (cadr (assoc identity mh-identity-list))))
         (while pers-list
-          (let ((field (concat (caar pers-list) ":"))
-                (value (cdar pers-list)))
-            (cond
-             ;; No value, remove field
-             ((or (not value)
-                  (string= value ""))
-              (mh-header-field-delete field nil))
-             ;; Existing field, replace
-             ((mh-header-field-delete field t)
-              (insert value))
-             ;; Handle "signature" special case. Insert file or call function.
-             ((and (string-equal "signature:" field)
-                   (or (and (stringp value)
-                            (file-readable-p value))
-                       (fboundp value)))
-              (goto-char (point-max))
-              (if (not (looking-at "^$"))
-                  (insert "\n"))
-              (insert "\n")
-              (save-restriction
-                (narrow-to-region (point) (point))
-                (set (make-local-variable 'mh-identity-signature-start)
-                     (make-marker))
-                (set-marker mh-identity-signature-start (point))
-                (cond
-                 ;; If MIME composition done, insert signature at the end as
-                 ;; an inline MIME part.
-                 ((mh-mhn-directive-present-p)
-                  (insert "#\n" "Content-Description: Signature\n"))
-                 ((mh-mml-directive-present-p)
-                  (mml-insert-tag 'part 'type "text/plain"
-                                  'disposition "inline"
-                                  'description "Signature")))
-                (if (stringp value)
-                    (insert-file-contents value)
-                  (funcall value))
-                (goto-char (point-min))
-                (when (not (re-search-forward "^--" nil t))
-                  (cond ((mh-mhn-directive-present-p)
-                         (forward-line 2))
-                        ((mh-mml-directive-present-p)
-                         (forward-line 1)))
-                  (insert "-- \n"))
-                (set (make-local-variable 'mh-identity-signature-end)
-                     (make-marker))
-                (set-marker mh-identity-signature-end (point-max))))
-             ;; Handle "From" field differently, adding it at the beginning.
-             ((string-equal "From:" field)
-              (goto-char (point-min))
-              (insert "From: " value "\n"))
-             ;; Skip empty signature (Can't remove what we don't know)
-             ((string-equal "signature:" field))
-             ;; Other field, add at end
-             (t                         ;Otherwise, add the end.
-              (goto-char (point-min))
-              (mh-goto-header-end 0)
-              (mh-insert-fields field value))))
+          (let* ((field (caar pers-list))
+                 (value (cdar pers-list))
+                 (handler (mh-identity-field-handler field)))
+            (funcall handler field 'add value))
           (setq pers-list (cdr pers-list))))))
   ;; Remember what is in use in this buffer
-  (if (equal "none" identity)
+  (if (equal "None" identity)
       (setq mh-identity-local nil)
     (setq mh-identity-local identity)))
 
+;;;###mh-autoload
+(defun mh-identity-handler-gpg-identity (field action &optional value)
+  "For FIELD \"pgg-default-user-id\", process for ACTION 'remove or 'add.
+The buffer-local variable `mh-identity-pgg-default-user-id' is set to VALUE
+when action 'add is selected."
+  (cond
+   ((or (equal action 'remove)
+        (not value)
+        (string= value ""))
+    (setq mh-identity-pgg-default-user-id nil))
+   ((equal action 'add)
+    (setq mh-identity-pgg-default-user-id value))))
+
+;;;###mh-autoload
+(defun mh-identity-handler-signature (field action &optional value)
+  "For FIELD \"signature\", process headers for ACTION 'remove or 'add.
+The VALUE is added."
+  (cond
+   ((equal action 'remove)
+    (when (and (markerp mh-identity-signature-start)
+               (markerp mh-identity-signature-end))
+      (delete-region mh-identity-signature-start
+                     mh-identity-signature-end)))
+   (t
+    ;; Insert "signature". Nil value means to use `mh-signature-file-name'.
+    (when (not (mh-signature-separator-p)) ;...unless already present
+      (goto-char (point-max))
+      (save-restriction
+        (narrow-to-region (point) (point))
+        (if (null value)
+            (mh-insert-signature)
+          (mh-insert-signature value))
+        (set (make-local-variable 'mh-identity-signature-start)
+             (point-min-marker))
+        (set-marker-insertion-type mh-identity-signature-start t)
+        (set (make-local-variable 'mh-identity-signature-end)
+             (point-max-marker)))))))
+
+(defvar mh-identity-attribution-verb-start nil
+  "Marker for the beginning of the attribution verb.")
+(defvar mh-identity-attribution-verb-end nil
+  "Marker for the end of the attribution verb.")
+
+;;;###mh-autoload
+(defun mh-identity-handler-attribution-verb (field action &optional value)
+  "For FIELD \"attribution_verb\", process headers for ACTION 'remove or 'add.
+The VALUE is added."
+  (when (and (markerp mh-identity-attribution-verb-start)
+             (markerp mh-identity-attribution-verb-end))
+    (delete-region mh-identity-attribution-verb-start
+                   mh-identity-attribution-verb-end)
+    (goto-char mh-identity-attribution-verb-start)
+    (cond
+     ((equal action 'remove)              ; Replace with default
+      (mh-identity-insert-attribution-verb nil))
+     (t                                   ; Insert attribution verb.
+      (mh-identity-insert-attribution-verb value)))))
+
+;;;###mh-autoload
+(defun mh-identity-insert-attribution-verb (value)
+  "Insert VALUE as attribution verb, setting up delimiting markers.
+If VALUE is nil, use `mh-extract-from-attribution-verb'."
+  (save-restriction
+    (narrow-to-region (point) (point))
+    (if (null value)
+        (insert mh-extract-from-attribution-verb)
+      (insert value))
+    (set (make-local-variable 'mh-identity-attribution-verb-start)
+         (point-min-marker))
+    (set-marker-insertion-type mh-identity-attribution-verb-start t)
+    (set (make-local-variable 'mh-identity-attribution-verb-end)
+         (point-max-marker))))
+
+(defun mh-identity-handler-default (field action top &optional value)
+  "For FIELD, process mh-identity headers for ACTION 'remove or 'add.
+if TOP is non-nil, add the field and it's VALUE at the top of the header, else
+add it at the bottom of the header."
+  (let ((field-colon (if (string-match "^.*:$" field)
+                         field
+                       (concat field ":"))))
+    (cond
+     ((equal action 'remove)
+      (mh-header-field-delete field-colon nil))
+     (t
+      (cond
+       ;; No value, remove field
+       ((or (not value)
+            (string= value ""))
+        (mh-header-field-delete field-colon nil))
+       ;; Existing field, replace
+       ((mh-header-field-delete field-colon t)
+        (insert value))
+       ;; Other field, add at end or top
+       (t
+        (goto-char (point-min))
+        (if (not top)
+           (mh-goto-header-end 0))
+        (insert field-colon " " value "\n")))))))
+
+;;;###mh-autoload
+(defun mh-identity-handler-top (field action &optional value)
+  "For FIELD, process mh-identity headers for ACTION 'remove or 'add.
+If the field wasn't present, the VALUE is added at the top of the header."
+  (mh-identity-handler-default field action t value))
+
+;;;###mh-autoload
+(defun mh-identity-handler-bottom (field action &optional value)
+  "For FIELD, process mh-identity headers for ACTION 'remove or 'add.
+If the field wasn't present, the VALUE is added at the bottom of the header."
+  (mh-identity-handler-default field action nil value))
+
 (provide 'mh-identity)
 
 ;;; Local Variables:
index 1c052b1..42ca018 100644 (file)
@@ -1,6 +1,6 @@
 ;;; mh-inc.el --- MH-E `inc' and separate mail spool handling
 ;;
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
 
 ;; Author: Peter S. Galbraith <psg@debian.org>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
@@ -34,7 +34,8 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(eval-when-compile (require 'mh-acros))
+(mh-require-cl)
 
 (defvar mh-inc-spool-map (make-sparse-keymap)
   "Keymap for MH-E's mh-inc-spool commands.")
@@ -46,7 +47,8 @@
   '(lambda ()
      (interactive)
      (if mh-inc-spool-map-help
-         (mh-ephem-message (substring mh-inc-spool-map-help 0 -1))
+         (let ((mh-help-messages (list (list nil mh-inc-spool-map-help))))
+           (mh-help))
        (mh-ephem-message
         "There are no keys defined yet.  Customize `mh-inc-spool-list'"))))
 
index 734ce93..91eed42 100644 (file)
@@ -31,7 +31,6 @@
 ;;;        swish-e
 ;;;        mairix
 ;;;        namazu
-;;;        glimpse
 ;;;        grep
 ;;;
 ;;;  (2) To use this package, you first have to build an index. Please read
@@ -43,7 +42,7 @@
 
 ;;; Code:
 
-(require 'mh-utils)
+(eval-when-compile (require 'mh-acros))
 (mh-require-cl)
 (require 'mh-e)
 (require 'mh-mime)
@@ -66,8 +65,6 @@
      mh-mairix-regexp-builder)
     (namazu
      mh-namazu-binary mh-namazu-execute-search mh-namazu-next-result nil)
-    (glimpse
-     mh-glimpse-binary mh-glimpse-execute-search mh-glimpse-next-result nil)
     (pick
      mh-pick-binary mh-pick-execute-search mh-pick-next-result
      mh-pick-regexp-builder)
@@ -200,7 +197,8 @@ This function should only be called in the appropriate index folder buffer."
            (call-process "rm" nil nil nil
                          (format "%s%s/%s" mh-user-path
                                  (substring mh-current-folder 1) msg))
-           (remhash omsg (gethash ofolder mh-index-data))))
+           (when (gethash ofolder mh-index-data)
+             (remhash omsg (gethash ofolder mh-index-data)))))
         (t
          (setf (gethash msg mh-index-msg-checksum-map) checksum)
          (when origin-map
@@ -301,7 +299,8 @@ list of messages in that sequence."
              (pair (gethash checksum mh-index-checksum-origin-map))
              (ofolder (car pair))
              (omsg (cdr pair)))
-        (loop for seq in (gethash omsg (gethash ofolder seq-hash))
+        (loop for seq in (ignore-errors
+                           (gethash omsg (gethash ofolder seq-hash)))
               do (if (assoc seq seq-list)
                      (push msg (cdr (assoc seq seq-list)))
                    (push (list seq msg) seq-list)))))
@@ -374,7 +373,6 @@ index for each program:
     - `mh-swish-execute-search'
     - `mh-mairix-execute-search'
     - `mh-namazu-execute-search'
-    - `mh-glimpse-execute-search'
 
 If none of these programs are present then we use pick. If desired grep can be
 used instead. Details about these methods can be found in:
@@ -436,7 +434,7 @@ This has the effect of renaming already present X-MHE-Checksum headers."
           (save-excursion (mh-exec-cmd-quiet nil "rmf" buffer-name))
           (mh-exec-cmd-quiet nil "folder" "-create" "-fast" buffer-name)
           (setq index-folder buffer-name))
-      (setq index-folder (mh-index-new-folder index-folder)))
+      (setq index-folder (mh-index-new-folder index-folder search-regexp)))
 
     (let ((folder-path (format "%s%s" mh-user-path (substring folder 1)))
           (folder-results-map (make-hash-table :test #'equal))
@@ -587,13 +585,6 @@ PROC is used to convert the value to actual data."
                          mh-previous-window-config)
       (error "No search terms"))))
 
-(defun mh-replace-string (old new)
-  "Replace all occurrences of OLD with NEW in the current buffer."
-  (goto-char (point-min))
-  (let ((case-fold-search t))
-    (while (search-forward old nil t)
-      (replace-match new t t))))
-
 ;;;###mh-autoload
 (defun mh-index-parse-search-regexp (input-string)
   "Construct parse tree for INPUT-STRING.
@@ -739,28 +730,48 @@ results."
   "Check if MSG exists in FOLDER."
   (file-exists-p (format "%s%s/%s" mh-user-path (substring folder 1) msg)))
 
-(defun mh-index-new-folder (name)
-  "Create and return an MH folder name based on NAME.
-If the folder NAME already exists then check if NAME<2> exists. If it doesn't
-then it is created and returned. Otherwise try NAME<3>. This is repeated till
-we find a new folder name."
+(defun mh-index-new-folder (name search-regexp)
+  "Return a folder name based on NAME for search results of SEARCH-REGEXP.
+
+If folder NAME already exists and was generated for the same SEARCH-REGEXP
+then it is reused.
+
+Otherwise if the folder NAME was generated from a different search then check
+if NAME<2> can be used. Otherwise try NAME<3>. This is repeated till we find a
+new folder name.
+
+If the folder returned doesn't exist then it is created."
   (unless (mh-folder-name-p name)
     (error "The argument should be a valid MH folder name"))
-  (let ((chosen-name name))
-    (block unique-name
-      (unless (mh-folder-exists-p name)
-        (return-from unique-name))
-      (loop for index from 2
-            do (let ((new-name (format "%s<%s>" name index)))
-                 (unless (mh-folder-exists-p new-name)
-                   (setq chosen-name new-name)
-                   (return-from unique-name)))))
+  (let ((chosen-name
+         (loop for i from 1
+               for candidate = (if (equal i 1) name (format "%s<%s>" name i))
+               when (or (not (mh-folder-exists-p candidate))
+                        (equal (mh-index-folder-search-regexp candidate)
+                               search-regexp))
+               return candidate)))
+    ;; Do pending refiles/deletes...
+    (when (get-buffer chosen-name)
+      (mh-process-or-undo-commands chosen-name))
+    ;; Recreate folder...
+    (save-excursion (mh-exec-cmd-quiet nil "rmf" chosen-name))
     (mh-exec-cmd-quiet nil "folder" "-create" "-fast" chosen-name)
     (mh-remove-from-sub-folders-cache chosen-name)
     (when (boundp 'mh-speed-folder-map)
       (mh-speed-add-folder chosen-name))
     chosen-name))
 
+(defun mh-index-folder-search-regexp (folder)
+  "If FOLDER was created by a index search, return the search regexp.
+Return nil if FOLDER doesn't exist or the .mhe_index file is garbled."
+  (ignore-errors
+    (with-temp-buffer
+      (insert-file-contents
+       (format "%s%s/%s" mh-user-path (substring folder 1) mh-index-data-file))
+      (goto-char (point-min))
+      (forward-list 3)
+      (cadr (read (current-buffer))))))
+
 ;;;###mh-autoload
 (defun mh-index-insert-folder-headers ()
   "Annotate the search results with original folder names."
@@ -777,8 +788,27 @@ we find a new folder name."
         (insert (if last-folder "\n" "") current-folder "\n")
         (setq last-folder current-folder))
       (forward-line))
-    (when cur-msg (mh-goto-msg cur-msg t))
-    (set-buffer-modified-p old-buffer-modified-flag)))
+    (when cur-msg
+      (mh-notate-cur)
+      (mh-goto-msg cur-msg t))
+    (set-buffer-modified-p old-buffer-modified-flag))
+  (mh-index-create-imenu-index))
+
+;;;###mh-autoload
+(defun mh-index-create-imenu-index ()
+  "Create alist of folder names and positions in index folder buffers."
+  (save-excursion
+    (setq which-func-mode t)
+    (let ((alist ()))
+      (goto-char (point-min))
+      (while (re-search-forward "^+" nil t)
+        (save-excursion
+          (beginning-of-line)
+          (push (cons (buffer-substring-no-properties
+                       (point) (line-end-position))
+                      (set-marker (make-marker) (point)))
+                alist)))
+      (setq imenu--index-alist (nreverse alist)))))
 
 ;;;###mh-autoload
 (defun mh-index-group-by-folder ()
@@ -837,23 +867,6 @@ list of messages originally from that folder."
        folder (loop for x being the hash-keys of (gethash folder mh-index-data)
                     when (mh-msg-exists-p x folder) collect x)))))
 
-;;;###mh-autoload
-(defun mh-index-update-unseen (msg)
-  "Remove counterpart of MSG in source folder from `mh-unseen-seq'.
-Also `mh-update-unseen' is called in the original folder, if we have it open."
-  (let* ((checksum (gethash msg mh-index-msg-checksum-map))
-         (folder-msg-pair (gethash checksum mh-index-checksum-origin-map))
-         (orig-folder (car folder-msg-pair))
-         (orig-msg (cdr folder-msg-pair)))
-    (when (mh-index-match-checksum orig-msg orig-folder checksum)
-      (when (get-buffer orig-folder)
-        (save-excursion
-          (set-buffer orig-folder)
-          (unless (member orig-msg mh-seen-list) (push orig-msg mh-seen-list))
-          (mh-update-unseen)))
-      (mh-exec-cmd-daemon "mark" #'ignore orig-folder (format "%s" orig-msg)
-                          "-sequence" (symbol-name mh-unseen-seq) "-del"))))
-
 (defun mh-index-match-checksum (msg folder checksum)
   "Check if MSG in FOLDER has X-MHE-Checksum header value of CHECKSUM."
   (with-temp-buffer
@@ -973,90 +986,6 @@ update the source folder buffer if present."
 
 \f
 
-;; Glimpse interface
-
-(defvar mh-glimpse-binary (executable-find "glimpse"))
-(defvar mh-glimpse-directory ".glimpse")
-
-;;;###mh-autoload
-(defun mh-glimpse-execute-search (folder-path search-regexp)
-  "Execute glimpse and read the results.
-
-In the examples below, replace /home/user/Mail with the path to your MH
-directory.
-
-First create the directory /home/user/Mail/.glimpse. Then create the file
-/home/user/Mail/.glimpse/.glimpse_exclude with the following contents:
-
-    */.*
-    */#*
-    */,*
-    */*~
-    ^/home/user/Mail/.glimpse
-    ^/home/user/Mail/mhe-index
-
-If there are any directories you would like to ignore, append lines like the
-following to .glimpse_exclude:
-
-    ^/home/user/Mail/scripts
-
-You do not want to index the folders that hold the results of your searches
-since they tend to be ephemeral and the original messages are indexed anyway.
-The configuration file above assumes that the results are found in sub-folders
-of `mh-index-folder' which is +mhe-index by default.
-
-Use the following command line to generate the glimpse index. Run this
-daily from cron:
-
-    glimpseindex -H /home/user/Mail/.glimpse /home/user/Mail
-
-FOLDER-PATH is the directory in which SEARCH-REGEXP is used to search."
-  (set-buffer (get-buffer-create mh-index-temp-buffer))
-  (erase-buffer)
-  (call-process mh-glimpse-binary nil '(t nil) nil
-                                        ;(format "-%s" fuzz)
-                "-i" "-y"
-                "-H" (format "%s%s" mh-user-path mh-glimpse-directory)
-                "-F" (format "^%s" folder-path)
-                search-regexp)
-  (goto-char (point-min)))
-
-(defun mh-glimpse-next-result ()
-  "Read the next result.
-Parse it and return the message folder, message index and the match. If no
-other matches left then return nil. If the current record is invalid return
-'error."
-  (prog1
-      (block nil
-        (when (eobp)
-          (return nil))
-        (let ((eol-pos (line-end-position))
-              (bol-pos (line-beginning-position))
-              folder-start msg-end)
-          (goto-char bol-pos)
-          (unless (search-forward mh-user-path eol-pos t)
-            (return 'error))
-          (setq folder-start (point))
-          (unless (search-forward ": " eol-pos t)
-            (return 'error))
-          (let ((match (buffer-substring-no-properties (point) eol-pos)))
-            (forward-char -2)
-            (setq msg-end (point))
-            (unless (search-backward "/" folder-start t)
-              (return 'error))
-            (list (format "+%s" (buffer-substring-no-properties
-                                 folder-start (point)))
-                  (let ((val (ignore-errors (read-from-string
-                                             (buffer-substring-no-properties
-                                              (1+ (point)) msg-end)))))
-                    (if (and (consp val) (integerp (car val)))
-                        (car val)
-                      (return 'error)))
-                  match))))
-    (forward-line)))
-
-\f
-
 ;; Pick interface
 
 (defvar mh-index-pick-folder)
@@ -1319,16 +1248,12 @@ then the folders are searched recursively. All parameters ARGS are ignored."
 ;;;###mh-autoload
 (defun mh-index-sequenced-messages (folders sequence)
   "Display messages from FOLDERS in SEQUENCE.
-By default the folders specified by `mh-index-new-messages-folders' are
-searched. With a prefix argument, enter a space-separated list of folders, or
-nothing to search all folders.
-
-Argument SEQUENCE defaults to `mh-unseen-seq' and is the sequence that the
-function searches for in each of the FOLDERS. With a prefix argument, enter a
-sequence to use."
+All messages in the sequence you provide from the folders in
+`mh-index-new-messages-folders' are listed. With a prefix argument, enter a
+space-separated list of folders, or nothing to search all folders."
   (interactive
    (list (if current-prefix-arg
-             (split-string (read-string "Search folder(s) [all]? "))
+             (split-string (read-string "Search folder(s): [all] "))
            mh-index-new-messages-folders)
          (mh-read-seq-default "Search" nil)))
   (unless sequence (setq sequence mh-unseen-seq))
@@ -1367,26 +1292,26 @@ sequence to use."
 ;;;###mh-autoload
 (defun mh-index-new-messages (folders)
   "Display unseen messages.
-All messages in the `unseen' sequence from FOLDERS are displayed.
-By default the folders specified by `mh-index-new-messages-folders'
-are searched. With a prefix argument, enter a space-separated list of
-folders, or nothing to search all folders."
+If you use a program such as `procmail' to use `rcvstore' to file your
+incoming mail automatically, you can display new, unseen, messages using this
+command. All messages in the `unseen' sequence from the folders in
+`mh-index-new-messages-folders' are listed. With a prefix argument, enter a
+space-separated list of FOLDERS, or nothing to search all folders."
   (interactive
    (list (if current-prefix-arg
-             (split-string (read-string "Search folder(s) [all]? "))
+             (split-string (read-string "Search folder(s): [all] "))
            mh-index-new-messages-folders)))
   (mh-index-sequenced-messages folders mh-unseen-seq))
 
 ;;;###mh-autoload
 (defun mh-index-ticked-messages (folders)
   "Display ticked messages.
-All messages in the `tick' sequence from FOLDERS are displayed.
-By default the folders specified by `mh-index-ticked-messages-folders'
-are searched. With a prefix argument, enter a space-separated list of
-folders, or nothing to search all folders."
+All messages in `mh-tick-seq' from the folders in
+`mh-index-ticked-messages-folders' are listed. With a prefix argument, enter a
+space-separated list of FOLDERS, or nothing to search all folders."
   (interactive
    (list (if current-prefix-arg
-             (split-string (read-string "Search folder(s) [all]? "))
+             (split-string (read-string "Search folder(s): [all] "))
            mh-index-ticked-messages-folders)))
   (mh-index-sequenced-messages folders mh-tick-seq))
 
index 42ec4c4..095a8c3 100644 (file)
@@ -1,6 +1,6 @@
 ;;; mh-junk.el --- Interface to anti-spam measures
 
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
 
 ;; Author: Satyaki Das <satyaki@theforce.stanford.edu>,
 ;;         Bill Wohler <wohler@newt.com>
@@ -32,6 +32,8 @@
 
 ;;; Code:
 
+(eval-when-compile (require 'mh-acros))
+(mh-require-cl)
 (require 'mh-e)
 
 ;; Interactive functions callable from the folder buffer
 (defun mh-junk-blacklist (range)
   "Blacklist RANGE as spam.
 
-Check the documentation of `mh-interactive-range' to see how RANGE is read in
-interactive use.
+This command trains the spam program in use (see the `mh-junk-program' option)
+with the content of the range (see `mh-interactive-range') and then handles
+the message(s) as specified by the `mh-junk-disposition' option.
 
-First the appropriate function is called depending on the value of
-`mh-junk-choice'. Then if `mh-junk-mail-folder' is a string then the message is
-refiled to that folder. If nil, the message is deleted.
-
-To change the spam program being used, customize `mh-junk-program'. Directly
-setting `mh-junk-choice' is not recommended.
-
-The documentation for the following functions describes what setup is needed
-for the different spam fighting programs:
+For more information about using your particular spam fighting program, see:
 
+  - `mh-spamassassin-blacklist'
   - `mh-bogofilter-blacklist'
-  - `mh-spamprobe-blacklist'
-  - `mh-spamassassin-blacklist'"
+  - `mh-spamprobe-blacklist'"
   (interactive (list (mh-interactive-range "Blacklist")))
   (let ((blacklist-func (nth 1 (assoc mh-junk-choice mh-junk-function-alist))))
     (unless blacklist-func
       (error "Customize `mh-junk-program' appropriately"))
-    (let ((dest (cond ((null mh-junk-mail-folder) nil)
-                      ((equal mh-junk-mail-folder "") "+")
-                      ((eq (aref mh-junk-mail-folder 0) ?+)
-                       mh-junk-mail-folder)
-                      ((eq (aref mh-junk-mail-folder 0) ?@)
+    (let ((dest (cond ((null mh-junk-disposition) nil)
+                      ((equal mh-junk-disposition "") "+")
+                      ((eq (aref mh-junk-disposition 0) ?+)
+                       mh-junk-disposition)
+                      ((eq (aref mh-junk-disposition 0) ?@)
                        (concat mh-current-folder "/"
-                               (substring mh-junk-mail-folder 1)))
-                      (t (concat "+" mh-junk-mail-folder)))))
+                               (substring mh-junk-disposition 1)))
+                      (t (concat "+" mh-junk-disposition)))))
       (mh-iterate-on-range msg range
+        (message (format "Blacklisting message %d..." msg))
         (funcall (symbol-function blacklist-func) msg)
+        (message (format "Blacklisting message %d...done" msg))
+        (if (not (memq msg mh-seen-list))
+            (setq mh-seen-list (cons msg mh-seen-list)))
         (if dest
             (mh-refile-a-msg nil (intern dest))
           (mh-delete-a-msg nil)))
@@ -76,231 +75,124 @@ for the different spam fighting programs:
 
 ;;;###mh-autoload
 (defun mh-junk-whitelist (range)
-  "Whitelist RANGE incorrectly classified as spam.
-
-Check the documentation of `mh-interactive-range' to see how RANGE is read in
-interactive use.
+  "Whitelist RANGE as ham.
 
-First the appropriate function is called depending on the value of
-`mh-junk-choice'. Then the message is refiled to `mh-inbox'.
+This command reclassifies a range of messages (see `mh-interactive-range') as
+ham if it were incorrectly classified as spam. It then refiles the message
+into the `+inbox' folder.
 
-To change the spam program being used, customize `mh-junk-program'. Directly
-setting `mh-junk-choice' is not recommended."
+The `mh-junk-program' option specifies the spam program in use."
   (interactive (list (mh-interactive-range "Whitelist")))
   (let ((whitelist-func (nth 2 (assoc mh-junk-choice mh-junk-function-alist))))
     (unless whitelist-func
       (error "Customize `mh-junk-program' appropriately"))
     (mh-iterate-on-range msg range
+      (message (format "Whitelisting message %d..." msg))
       (funcall (symbol-function whitelist-func) msg)
+      (message (format "Whitelisting message %d...done" msg))
       (mh-refile-a-msg nil (intern mh-inbox)))
     (mh-next-msg)))
 
 \f
 
-;; Bogofilter Interface
-
-(defvar mh-bogofilter-executable (executable-find "bogofilter"))
-
-(defun mh-bogofilter-blacklist (msg)
-  "Classify MSG as spam.
-Tell bogofilter that the message is spam.
+;; Spamassassin Interface
 
-Bogofilter is a Bayesian spam filtering program. Get it from your local
-distribution or from:
-   http://bogofilter.sourceforge.net/
+(defvar mh-spamassassin-executable (executable-find "spamassassin"))
+(defvar mh-sa-learn-executable (executable-find "sa-learn"))
 
-You first need to teach bogofilter. This is done by running
+(defun mh-spamassassin-blacklist (msg)
+  "Blacklist MSG with SpamAssassin.
 
-   bogofilter -n < good-message
+SpamAssassin is one of the more popular spam filtering programs. Get it from
+your local distribution or from http://spamassassin.org/.
 
-on every good message, and
+To use SpamAssassin, add the following recipes to `.procmailrc':
 
-   bogofilter -s < spam-message
+    MAILDIR=$HOME/`mhparam Path`
 
-on every spam message. Most Bayesian filters need 1000 to 5000 of each to
-start doing a good job.
+    # Fight spam with SpamAssassin.
+    :0fw
+    | spamc
 
-To use bogofilter, add the following .procmailrc recipes which you can also
-find in the bogofilter man page:
+    # Anything with a spam level of 10 or more is junked immediately.
+    :0:
+    * ^X-Spam-Level: ..........
+    /dev/null
 
-   # Bogofilter
-   :0fw
-   | bogofilter -u -e -p
+    :0:
+    * ^X-Spam-Status: Yes
+    spam/.
 
-   :0
-   * ^X-Bogosity: Yes, tests=bogofilter
-   $SPAM
+If you don't use `spamc', use `spamassassin -P -a'.
 
-Bogofilter continues to feed the messages it classifies back into its
-database. Occasionally it misses, and those messages need to be reclassified.
-MH-E can do this for you. Use \\[mh-junk-blacklist] to reclassify messges in
-your +inbox as spam, and \\[mh-junk-whitelist] to reclassify messages in your
-spambox as good messages."
-  (unless mh-bogofilter-executable
-    (error "Couldn't find the bogofilter executable"))
-  (let ((msg-file (mh-msg-filename msg mh-current-folder)))
-    (call-process mh-bogofilter-executable msg-file 0 nil "-Ns")))
+Note that one of the recipes above throws away messages with a score greater
+than or equal to 10. Here's how you can determine a value that works best for
+you.
 
-(defun mh-bogofilter-whitelist (msg)
-  "Reinstate incorrectly filtered MSG.
-Train bogofilter to think of the message as non-spam."
-  (unless mh-bogofilter-executable
-    (error "Couldn't find the bogofilter executable"))
-  (let ((msg-file (mh-msg-filename msg mh-current-folder)))
-    (call-process mh-bogofilter-executable msg-file 0 nil "-Sn")))
+First, run `spamassassin -t' on every mail message in your archive and use
+Gnumeric to verify that the average plus the standard deviation of good mail
+is under 5, the SpamAssassin default for \"spam\".
 
-\f
+Using Gnumeric, sort the messages by score and view the messages with the
+highest score. Determine the score which encompasses all of your interesting
+messages and add a couple of points to be conservative. Add that many dots to
+the `X-Spam-Level:' header field above to send messages with that score down
+the drain.
 
-;; Spamprobe Interface
+In the example above, messages with a score of 5-9 are set aside in the
+`+spam' folder for later review. The major weakness of rules-based filters is
+a plethora of false positives so it is worthwhile to check.
 
-(defvar mh-spamprobe-executable (executable-find "spamprobe"))
+If SpamAssassin classifies a message incorrectly, or is unsure, you can use
+the MH-E commands \\[mh-junk-blacklist] and \\[mh-junk-whitelist].
 
-(defun mh-spamprobe-blacklist (msg)
-  "Classify MSG as spam.
-Tell spamprobe that the message is spam.
-
-Spamprobe is a Bayesian spam filtering program. More info about the program can
-be found at:
-   http://spamprobe.sourceforge.net
-
-Here is a procmail recipe to stores incoming spam mail into the folder +spam
-and good mail in /home/user/Mail/mdrop/mbox. This recipe is provided as an
-example in the spamprobe man page.
-
-   PATH=/bin:/usr/bin:/usr/local/bin
-   DEFAULT=/home/user/Mail/mdrop/mbox
-   SPAM=/home/user/Mail/spam/.
-
-   # Spamprobe filtering
-   :0
-   SCORE=| spamprobe receive
-   :0 wf
-   | formail -I \"X-SpamProbe: $SCORE\"
-   :0 a:
-   *^X-SpamProbe: SPAM
-   $SPAM
-
-Occasionally some good mail gets misclassified as spam. You can use
-\\[mh-junk-whitelist] to reclassify that as good mail."
-  (unless mh-spamprobe-executable
-    (error "Couldn't find the spamprobe executable"))
-  (let ((msg-file (mh-msg-filename msg mh-current-folder)))
-    (call-process mh-spamprobe-executable msg-file 0 nil "spam")))
+The \\[mh-junk-blacklist] command adds a `blacklist_from' entry to
+`~/spamassassin/user_prefs', deletes the message, and sends the message to the
+Razor, so that others might not see this spam. If the `sa-learn' command is
+available, the message is also recategorized as spam.
 
-(defun mh-spamprobe-whitelist (msg)
-  "Reinstate incorrectly filtered MSG.
-Train spamprobe to think of the message as non-spam."
-  (unless mh-spamprobe-executable
-    (error "Couldn't find the spamprobe executable"))
-  (let ((msg-file (mh-msg-filename msg mh-current-folder)))
-    (call-process mh-spamprobe-executable msg-file 0 nil "good")))
+The \\[mh-junk-whitelist] command adds a `whitelist_from' rule to the
+`~/.spamassassin/user_prefs' file. If the `sa-learn' command is available, the
+message is also recategorized as ham.
 
-\f
+Over time, you'll observe that the same host or domain occurs repeatedly in
+the `blacklist_from' entries, so you might think that you could avoid future
+spam by blacklisting all mail from a particular domain. The utility function
+`mh-spamassassin-identify-spammers' helps you do precisely that. This function
+displays a frequency count of the hosts and domains in the `blacklist_from'
+entries from the last blank line in `~/.spamassassin/user_prefs' to the end of
+the file. This information can be used so that you can replace multiple
+`blacklist_from' entries with a single wildcard entry such as:
 
-;; Spamassassin Interface
+    blacklist_from *@*amazingoffersdirect2u.com
 
-(defvar mh-spamassassin-executable (executable-find "spamassassin"))
-(defvar mh-sa-learn-executable (executable-find "sa-learn"))
+In versions of SpamAssassin (2.50 and on) that support a Bayesian classifier,
+\\[mh-junk-blacklist] uses the `sa-learn' program to recategorize the message
+as spam. Neither MH-E, nor SpamAssassin, rebuilds the database after adding
+words, so you will need to run `sa-learn --rebuild' periodically. This can be
+done by adding the following to your crontab:
 
-(defun mh-spamassassin-blacklist (msg)
-  "Blacklist MSG.
-This is done by sending the message to Razor and by appending the sender to
-~/.spamassassin/user_prefs in a blacklist_from rule. If sa-learn is available,
-the message is also recategorized as spam.
-
-Spamassassin is an excellent spam filter. For more information, see:
-  http://spamassassin.org/.
-
-I ran \"spamassassin -t\" on every mail message in my archive and ran an
-analysis in Gnumeric to find that the standard deviation of good mail
-scored under 5 (coincidentally, the spamassassin default for \"spam\").
-
-Furthermore, I observed that there weren't any messages with a score of 8
-or more that were interesting, so I added a couple of points to be
-conservative and send any message with a score of 10 or more down the
-drain. You might want to use a score of 12 or 13 to be really conservative.
-I have found that this really decreases the amount of junk to review.
-
-Messages with a score of 5-9 are set aside for later review. The major
-weakness of rules-based filters is a plethora of false positives\; I catch one
-or two legitimate messages in here a week, so it is worthwhile to check.
-
-You might choose to do this analysis yourself to pick a good score for
-deleting spam sight unseen, or you might pick a score out of a hat, or you
-might choose to be very conservative and not delete any messages at all.
-
-Based upon this discussion, here is what the associated ~/.procmailrc
-entries look like. These rules appear before my list filters so that spam
-sent to mailing lists gets pruned too.
-
-   #
-   # Spam
-   #
-   :0fw
-   | spamc
-
-   # Anything with a spam level of 10 or more is junked immediately.
-   :0:
-   * ^X-Spam-Level: ..........
-   /dev/null
-
-   :0
-   * ^X-Spam-Status: Yes
-   $SPAM
-
-If you don't use \"spamc\", use \"spamassassin -P -a\".
-
-A handful of spam does find its way into +inbox. In this case, use
-\\[mh-junk-blacklist] to add a \"blacklist_from\" line to
-~/spamassassin/user_prefs, delete the message, and send the message to the
-Razor, so that others might not see this spam.
-
-Over time, you see some patterns in the blacklisted addresses and can
-replace several lines with wildcards. For example, it is clear that High
-Speed Media is the biggest bunch of jerks on the Net. Here are some of the
-entries I have for them, and the list continues to grow.
-
-   blacklist_from      *@*-hsm-*.com
-   blacklist_from      *@*182*643*.com
-   blacklist_from      *@*antarhsm*.com
-   blacklist_from      *@*h*speed*
-   blacklist_from      *@*hsm*182*.com
-   blacklist_from      *@*hsm*643*.com
-   blacklist_from      *@*hsmridi2983cslt227.com
-   blacklist_from      *@*list*hsm*.com
-   blacklist_from      *@h*s*media*
-   blacklist_from      *@hsmdrct.com
-   blacklist_from      *@hsmridi2983csltsite.com
-
-The function `mh-spamassassin-identify-spammers' is provided that shows the
-frequency counts of the host and domain names in your blacklist_from
-entries. This can be helpful when editing the blacklist_from entries.
-
-In versions of spamassassin (2.50 and on) that support a Bayesian classifier,
-\\[mh-junk-blacklist] uses the sa-learn program to recategorize the message as
-spam. Neither MH-E, nor spamassassin, rebuilds the database after adding
-words, so you will need to run \"sa-learn --rebuild\" periodically. This can
-be done by adding the following to your crontab:
-
-  0 * * * *    sa-learn --rebuild > /dev/null 2>&1"
+    0 * * * *  sa-learn --rebuild > /dev/null 2>&1"
   (unless mh-spamassassin-executable
-    (error "Couldn't find the spamassassin executable"))
+    (error "Unable to find the spamassassin executable"))
   (let ((current-folder mh-current-folder)
         (msg-file (mh-msg-filename msg mh-current-folder))
         (sender))
     (save-excursion
-      (message "Giving this message the Razor...")
+      (message (format "Reporting message %d..." msg))
       (mh-truncate-log-buffer)
       (call-process mh-spamassassin-executable msg-file mh-log-buffer nil
-                    "--report" "--remove-from-whitelist")
+                    ;;"--report" "--remove-from-whitelist"
+                    "-r" "-R")          ; spamassassin V2.20
       (when mh-sa-learn-executable
           (message "Recategorizing this message as spam...")
           (call-process mh-sa-learn-executable msg-file mh-log-buffer nil
                         "--single" "--spam" "--local" "--no-rebuild"))
-      (message "Blacklisting address...")
+      (message (format "Blacklisting message %d..." msg))
       (set-buffer (get-buffer-create mh-temp-buffer))
       (erase-buffer)
-      (call-process (expand-file-name mh-scan-prog mh-progs) nil t nil
+      (call-process (expand-file-name mh-scan-prog mh-progs) mh-junk-background
+                    t nil
                     (format "%s" msg) current-folder
                     "-format" "%<(mymbox{from})%|%(addr{from})%>")
       (goto-char (point-min))
@@ -308,15 +200,19 @@ be done by adding the following to your crontab:
           (progn
             (setq sender (match-string 0))
             (mh-spamassassin-add-rule "blacklist_from" sender)
-            (message "Blacklisting address...done"))
-        (message "Blacklisting address...not done (from my address)")))))
+            (message (format "Blacklisting message %d...done" msg)))
+        (message (format "Blacklisting message %d...not done (from my address)" msg))))))
 
 (defun mh-spamassassin-whitelist (msg)
-  "Whitelist MSG.
-Add a whitelist_from rule to the ~/.spamassassin/user_prefs file. If sa-learn
-is available, then the message is recategorized as ham."
+  "Whitelist MSG with SpamAssassin.
+
+The \\[mh-junk-whitelist] command adds a `whitelist_from' rule to the
+`~/.spamassassin/user_prefs' file. If the `sa-learn' command is available, the
+message is also recategorized as ham.
+
+See `mh-spamassassin-blacklist' for more information."
   (unless mh-spamassassin-executable
-    (error "Couldn't find the spamassassin executable"))
+    (error "Unable to find the spamassassin executable"))
   (let ((msg-file (mh-msg-filename msg mh-current-folder))
         (show-buffer (get-buffer mh-show-buffer))
         from)
@@ -325,7 +221,8 @@ is available, then the message is recategorized as ham."
       (erase-buffer)
       (message "Removing spamassassin markup from message...")
       (call-process mh-spamassassin-executable msg-file mh-temp-buffer nil
-                    "--remove-markup")
+                    ;; "--remove-markup"
+                    "-d")               ; spamassassin V2.20
       (if show-buffer
           (kill-buffer show-buffer))
       (write-file msg-file)
@@ -333,15 +230,17 @@ is available, then the message is recategorized as ham."
         (message "Recategorizing this message as ham...")
         (call-process mh-sa-learn-executable msg-file mh-temp-buffer nil
                       "--single" "--ham" "--local --no-rebuild"))
-      (message "Whitelisting address...")
-      (setq from (car (ietf-drums-parse-address (mh-get-header-field "From:"))))
+      (message (format "Whitelisting message %d..." msg))
+      (setq from
+            (car (mh-funcall-if-exists
+                  ietf-drums-parse-address (mh-get-header-field "From:"))))
       (kill-buffer nil)
-      (unless (equal from "")
+      (unless (or (null from) (equal from ""))
         (mh-spamassassin-add-rule "whitelist_from" from))
-      (message "Whitelisting address...done"))))
+      (message (format "Whitelisting message %d...done" msg)))))
 
 (defun mh-spamassassin-add-rule (rule body)
-  "Add a new rule to ~/.spamassassin/user_prefs.
+  "Add a new rule to `~/.spamassassin/user_prefs'.
 The name of the rule is RULE and its body is BODY."
   (save-window-excursion
     (let* ((line (format "%s\t%s\n" rule body))
@@ -358,15 +257,15 @@ The name of the rule is RULE and its body is BODY."
           (kill-buffer nil)))))
 
 (defun mh-spamassassin-identify-spammers ()
-  "Identifies spammers who are repeat offenders.
+  "Identify spammers who are repeat offenders.
 
-For each blacklist_from entry from the last blank line of
-~/.spamassassin/user_prefs to the end of the file, a list of host and domain
-names along with their frequency counts is displayed. This information can be
-used to replace multiple blacklist_from entries with a single wildcard entry
-such as:
+This function displays a frequency count of the hosts and domains in the
+`blacklist_from' entries from the last blank line in
+`~/.spamassassin/user_prefs' to the end of the file. This information can be
+used so that you can replace multiple `blacklist_from' entries with a single
+wildcard entry such as:
 
-  blacklist_from *@*amazingoffersdirect2u.com"
+    blacklist_from *@*amazingoffersdirect2u.com"
   (interactive)
   (let* ((file (expand-file-name "~/.spamassassin/user_prefs"))
          (domains (make-hash-table :test 'equal)))
@@ -385,7 +284,7 @@ such as:
           ;; Add counts for each host and domain part.
           (while host
             (setq value (gethash (car host) domains))
-            (puthash (car host) (1+ (if (not value) 0 value)) domains)
+            (setf (gethash (car host) domains) (1+ (if (not value) 0 value)))
             (setq host (cdr host))))))
 
     ;; Output
@@ -400,6 +299,121 @@ such as:
     (reverse-region (point-min) (point-max))
     (goto-char (point-min))))
 
+\f
+
+;; Bogofilter Interface
+
+(defvar mh-bogofilter-executable (executable-find "bogofilter"))
+
+(defun mh-bogofilter-blacklist (msg)
+  "Blacklist MSG with Bogofilter.
+
+Bogofilter is a Bayesian spam filtering program. Get it from your local
+distribution or from http://bogofilter.sourceforge.net/.
+
+Bogofilter is taught by running:
+
+    bogofilter -n < good-message
+
+on every good message, and
+
+    bogofilter -s < spam-message
+
+on every spam message. This is called a full training; three other
+training methods are described in the FAQ that is distributed with bogofilter.
+Note that most Bayesian filters need 1000 to 5000 of each type of message to
+start doing a good job.
+
+To use Bogofilter, add the following recipes to `.procmailrc':
+
+    MAILDIR=$HOME/`mhparam Path`
+
+    # Fight spam with Bogofilter.
+    :0fw
+    | bogofilter -3 -e -p
+
+    :0:
+    * ^X-Bogosity: Yes, tests=bogofilter
+    spam/.
+
+    :0:
+    * ^X-Bogosity: Unsure, tests=bogofilter
+    spam/unsure/.
+
+If Bogofilter classifies a message incorrectly, or is unsure, you can use the
+MH-E commands \\[mh-junk-blacklist] and \\[mh-junk-whitelist] to update
+Bogofilter's training.
+
+The \"Bogofilter FAQ\" suggests that you run the following
+occasionally to shrink the database:
+
+    bogoutil -d wordlist.db | bogoutil -l wordlist.db.new
+    mv wordlist.db wordlist.db.prv
+    mv wordlist.db.new wordlist.db
+
+The \"Bogofilter tuning HOWTO\" describes how you can fine-tune Bogofilter."
+  (unless mh-bogofilter-executable
+    (error "Unable to find the bogofilter executable"))
+  (let ((msg-file (mh-msg-filename msg mh-current-folder)))
+    (call-process mh-bogofilter-executable msg-file mh-junk-background
+                  nil "-s")))
+
+(defun mh-bogofilter-whitelist (msg)
+  "Whitelist MSG with Bogofilter.
+
+See `mh-bogofilter-blacklist' for more information."
+  (unless mh-bogofilter-executable
+    (error "Unable to find the bogofilter executable"))
+  (let ((msg-file (mh-msg-filename msg mh-current-folder)))
+    (call-process mh-bogofilter-executable msg-file mh-junk-background
+                  nil "-n")))
+
+\f
+
+;; Spamprobe Interface
+
+(defvar mh-spamprobe-executable (executable-find "spamprobe"))
+
+(defun mh-spamprobe-blacklist (msg)
+  "Blacklist MSG with SpamProbe.
+
+SpamProbe is a Bayesian spam filtering program. Get it from your local
+distribution or from http://spamprobe.sourceforge.net.
+
+To use SpamProbe, add the following recipes to `.procmailrc':
+
+    MAILDIR=$HOME/`mhparam Path`
+
+    # Fight spam with SpamProbe.
+    :0
+    SCORE=| spamprobe receive
+
+    :0 wf
+    | formail -I \"X-SpamProbe: $SCORE\"
+
+    :0:
+    *^X-SpamProbe: SPAM
+    spam/.
+
+If SpamProbe classifies a message incorrectly, you can use the MH-E commands
+\\[mh-junk-blacklist] and \\[mh-junk-whitelist] to update SpamProbe's
+training."
+  (unless mh-spamprobe-executable
+    (error "Unable to find the spamprobe executable"))
+  (let ((msg-file (mh-msg-filename msg mh-current-folder)))
+    (call-process mh-spamprobe-executable msg-file mh-junk-background
+                  nil "spam")))
+
+(defun mh-spamprobe-whitelist (msg)
+  "Whitelist MSG with SpamProbe.
+
+See `mh-spamprobe-blacklist' for more information."
+  (unless mh-spamprobe-executable
+    (error "Unable to find the spamprobe executable"))
+  (let ((msg-file (mh-msg-filename msg mh-current-folder)))
+    (call-process mh-spamprobe-executable msg-file mh-junk-background
+                  nil "good")))
+
 (provide 'mh-junk)
 
 ;;; Local Variables:
index a557876..43119b6 100644 (file)
 ;;;;;;  mh-beginning-of-word mh-complete-word mh-open-line mh-fully-kill-draft
 ;;;;;;  mh-yank-cur-msg mh-insert-letter mh-send-letter mh-insert-auto-fields
 ;;;;;;  mh-check-whom mh-insert-signature mh-to-fcc mh-to-field mh-fill-paragraph-function
-;;;;;;  mh-send-other-window mh-send mh-reply mh-redistribute mh-forward
-;;;;;;  mh-extract-rejected-mail mh-edit-again) "mh-comp" "mh-comp.el"
-;;;;;;  (16625 53169))
+;;;;;;  mh-get-header-field mh-send-other-window mh-send mh-reply
+;;;;;;  mh-redistribute mh-forward mh-extract-rejected-mail mh-edit-again)
+;;;;;;  "mh-comp" "mh-comp.el" (16665 55172))
 ;;; Generated autoloads from mh-comp.el
 
 (autoload (quote mh-edit-again) "mh-comp" "\
 Clean up a draft or a message MSG previously sent and make it resendable.
 Default is the current message.
 The variable `mh-new-draft-cleaned-headers' specifies the headers to remove.
-See also documentation for `\\[mh-send]' function." t nil)
+
+See also `mh-send'." t nil)
 
 (autoload (quote mh-extract-rejected-mail) "mh-comp" "\
 Extract message MSG returned by the mail system and make it resendable.
 Default is the current message.  The variable `mh-new-draft-cleaned-headers'
 gives the headers to clean out of the original message.
-See also documentation for `\\[mh-send]' function." t nil)
+
+See also `mh-send'." t nil)
 
 (autoload (quote mh-forward) "mh-comp" "\
 Forward messages to the recipients TO and CC.
@@ -36,7 +38,7 @@ Default is the displayed message.
 Check the documentation of `mh-interactive-range' to see how RANGE is read in
 interactive use.
 
-See also documentation for `\\[mh-send]' function." t nil)
+See also `mh-send'." t nil)
 
 (autoload (quote mh-redistribute) "mh-comp" "\
 Redistribute displayed message to recipients TO and CC.
@@ -55,11 +57,12 @@ to reply to:
 If optional prefix argument INCLUDEP provided, then include the message
 in the reply using filter `mhl.reply' in your MH directory.
 If the file named by `mh-repl-formfile' exists, it is used as a skeleton
-for the reply.  See also documentation for `\\[mh-send]' function." t nil)
+for the reply.
+
+See also `mh-send'." t nil)
 
 (autoload (quote mh-send) "mh-comp" "\
 Compose and send a letter.
-
 Do not call this function from outside MH-E; use \\[mh-smail] instead.
 
 The file named by `mh-comp-formfile' will be used as the form.
@@ -70,7 +73,6 @@ passed three arguments: TO, CC, and SUBJECT." t nil)
 
 (autoload (quote mh-send-other-window) "mh-comp" "\
 Compose and send a letter in another window.
-
 Do not call this function from outside MH-E; use \\[mh-smail-other-window]
 instead.
 
@@ -80,6 +82,11 @@ details.
 If `mh-compose-letter-function' is defined, it is called on the draft and
 passed three arguments: TO, CC, and SUBJECT." t nil)
 
+(autoload (quote mh-get-header-field) "mh-comp" "\
+Find and return the body of FIELD in the mail header.
+Returns the empty string if the field is not in the header of the
+current buffer." nil nil)
+
 (autoload (quote mh-fill-paragraph-function) "mh-comp" "\
 Fill paragraph at or after point.
 Prefix ARG means justify as well. This function enables `fill-paragraph' to
@@ -96,9 +103,12 @@ Insert an Fcc: FOLDER field in the current message.
 Prompt for the field name with a completion list of the current folders." t nil)
 
 (autoload (quote mh-insert-signature) "mh-comp" "\
-Insert the file named by `mh-signature-file-name' at point.
+Insert the signature specified by `mh-signature-file-name' or FILE at point.
+A signature separator (`-- ') will be added if the signature block does not
+contain one and `mh-signature-separator-flag' is on.
 The value of `mh-letter-insert-signature-hook' is a list of functions to be
-called, with no arguments, before the signature is actually inserted." t nil)
+called, with no arguments, after the signature is inserted.
+The signature can also be inserted with `mh-identity-list'." t nil)
 
 (autoload (quote mh-check-whom) "mh-comp" "\
 Verify recipients of the current letter, showing expansion of any aliases." t nil)
@@ -109,7 +119,9 @@ Sets buffer-local `mh-insert-auto-fields-done-local' when done and inserted
 something.  If NON-INTERACTIVE is non-nil, do not be verbose and only
 attempt matches if `mh-insert-auto-fields-done-local' is nil.
 
-An `identity' entry is skipped if one was already entered manually." t nil)
+An `identity' entry is skipped if one was already entered manually.
+
+Return t if fields added; otherwise return nil." t nil)
 
 (autoload (quote mh-send-letter) "mh-comp" "\
 Send the draft letter in the current buffer.
@@ -117,13 +129,12 @@ If optional prefix argument ARG is provided, monitor delivery.
 The value of `mh-before-send-letter-hook' is a list of functions to be called,
 with no arguments, before doing anything.
 Run `\\[mh-edit-mhn]' if mhn directives are present; otherwise
-run `\\[mh-mml-to-mime]' if mml directives are present.
-Insert X-Mailer field if variable `mh-insert-x-mailer-flag' is set.
-Insert X-Face field if the file specified by `mh-x-face-file' exists." t nil)
+run `\\[mh-mml-to-mime]' if mml directives are present." t nil)
 
 (autoload (quote mh-insert-letter) "mh-comp" "\
 Insert a message into the current letter.
-Removes the header fields according to the variable `mh-invisible-headers'.
+Removes the header fields according to the variable
+`mh-invisible-header-fields-compiled'.
 Prefixes each non-blank line with `mh-ins-buf-prefix', unless
 `mh-yank-from-start-of-msg' is set for supercite in which case supercite is
 used to format the message.
@@ -168,42 +179,11 @@ If we are at the first header field go to the start of the message body." t nil)
 
 ;;;***
 \f
-;;;### (autoloads (mh-customize) "mh-customize" "mh-customize.el"
-;;;;;;  (16625 53481))
-;;; Generated autoloads from mh-customize.el
-
-(autoload (quote mh-customize) "mh-customize" "\
-Customize MH-E variables.
-With optional argument DELETE-OTHER-WINDOWS-FLAG, other windows in the frame
-are removed." t nil)
-
-;;;***
-\f
-;;;### (autoloads (mh-goto-cur-msg mh-update-sequences mh-folder-line-matches-show-buffer-p)
-;;;;;;  "mh-e" "mh-e.el" (16627 22341))
-;;; Generated autoloads from mh-e.el
-
-(autoload (quote mh-folder-line-matches-show-buffer-p) "mh-e" "\
-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,
-the message in the show buffer doesn't match." nil nil)
-
-(autoload (quote mh-update-sequences) "mh-e" "\
-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." t nil)
-
-(autoload (quote mh-goto-cur-msg) "mh-e" "\
-Position the cursor at the current message.
-When optional argument MINIMAL-CHANGES-FLAG is non-nil, the function doesn't
-recenter the folder buffer." nil nil)
-
-;;;***
-\f
 ;;;### (autoloads (mh-prefix-help mh-help mh-ephem-message mh-store-buffer
-;;;;;;  mh-store-msg mh-undo-folder mh-sort-folder mh-print-msg mh-page-digest-backwards
+;;;;;;  mh-store-msg mh-undo-folder mh-sort-folder mh-page-digest-backwards
 ;;;;;;  mh-page-digest mh-pipe-msg mh-pack-folder mh-list-folders
 ;;;;;;  mh-kill-folder mh-copy-msg mh-burst-digest) "mh-funcs" "mh-funcs.el"
-;;;;;;  (16625 54011))
+;;;;;;  (16671 49652))
 ;;; Generated autoloads from mh-funcs.el
 
 (autoload (quote mh-burst-digest) "mh-funcs" "\
@@ -245,15 +225,6 @@ Advance displayed message to next digested message." t nil)
 (autoload (quote mh-page-digest-backwards) "mh-funcs" "\
 Back up displayed message to previous digested message." t nil)
 
-(autoload (quote mh-print-msg) "mh-funcs" "\
-Print RANGE on printer.
-
-Check the documentation of `mh-interactive-range' to see how RANGE is read in
-interactive use.
-
-The variable `mh-lpr-command-format' is used to generate the print command.
-The messages are formatted by mhl. See the variable `mhl-formfile'." t nil)
-
 (autoload (quote mh-sort-folder) "mh-funcs" "\
 Sort the messages in the current folder by date.
 Calls the MH program sortm to do the work.
@@ -261,8 +232,7 @@ The arguments in the list `mh-sortm-args' are passed to sortm if the optional
 argument EXTRA-ARGS is given." t nil)
 
 (autoload (quote mh-undo-folder) "mh-funcs" "\
-Undo all pending deletes and refiles in current folder.
-Argument IGNORE is deprecated." t nil)
+Undo all pending deletes and refiles in current folder." t nil)
 
 (autoload (quote mh-store-msg) "mh-funcs" "\
 Store the file(s) contained in the current message into DIRECTORY.
@@ -280,19 +250,24 @@ Default directory is the last directory used, or initially the value of
 Display STRING in the minibuffer momentarily." nil nil)
 
 (autoload (quote mh-help) "mh-funcs" "\
-Display cheat sheet for the MH-Folder commands in minibuffer." t nil)
+Display cheat sheet for the MH-E commands." t nil)
 
 (autoload (quote mh-prefix-help) "mh-funcs" "\
 Display cheat sheet for the commands of the current prefix in minibuffer." t nil)
 
 ;;;***
 \f
-;;;### (autoloads (mh-insert-identity mh-identity-list-set mh-identity-make-menu)
-;;;;;;  "mh-identity" "mh-identity.el" (16625 54171))
+;;;### (autoloads (mh-identity-handler-bottom mh-identity-handler-top
+;;;;;;  mh-identity-insert-attribution-verb mh-identity-handler-attribution-verb
+;;;;;;  mh-identity-handler-signature mh-identity-handler-gpg-identity
+;;;;;;  mh-insert-identity mh-identity-list-set mh-identity-make-menu)
+;;;;;;  "mh-identity" "mh-identity.el" (16665 55172))
 ;;; Generated autoloads from mh-identity.el
 
 (autoload (quote mh-identity-make-menu) "mh-identity" "\
-Build (or rebuild) the Identity menu (e.g. after the list is modified)." nil nil)
+Build the Identity menu.
+This should be called any time `mh-identity-list' or `mh-auto-fields-list'
+change." nil nil)
 
 (autoload (quote mh-identity-list-set) "mh-identity" "\
 Update the `mh-identity-list' variable, and rebuild the menu.
@@ -304,10 +279,35 @@ customization).  This is called after 'customize is used to alter
 Insert proper fields for given IDENTITY.
 Edit the `mh-identity-list' variable to define identity." t nil)
 
+(autoload (quote mh-identity-handler-gpg-identity) "mh-identity" "\
+For FIELD \"pgg-default-user-id\", process for ACTION 'remove or 'add.
+The buffer-local variable `mh-identity-pgg-default-user-id' is set to VALUE
+when action 'add is selected." nil nil)
+
+(autoload (quote mh-identity-handler-signature) "mh-identity" "\
+For FIELD \"signature\", process headers for ACTION 'remove or 'add.
+The VALUE is added." nil nil)
+
+(autoload (quote mh-identity-handler-attribution-verb) "mh-identity" "\
+For FIELD \"attribution_verb\", process headers for ACTION 'remove or 'add.
+The VALUE is added." nil nil)
+
+(autoload (quote mh-identity-insert-attribution-verb) "mh-identity" "\
+Insert VALUE as attribution verb, setting up delimiting markers.
+If VALUE is nil, use `mh-extract-from-attribution-verb'." nil nil)
+
+(autoload (quote mh-identity-handler-top) "mh-identity" "\
+For FIELD, process mh-identity headers for ACTION 'remove or 'add.
+If the field wasn't present, the VALUE is added at the top of the header." nil nil)
+
+(autoload (quote mh-identity-handler-bottom) "mh-identity" "\
+For FIELD, process mh-identity headers for ACTION 'remove or 'add.
+If the field wasn't present, the VALUE is added at the bottom of the header." nil nil)
+
 ;;;***
 \f
-;;;### (autoloads (mh-inc-spool-list-set) "mh-inc" "mh-inc.el" (16625
-;;;;;;  54212))
+;;;### (autoloads (mh-inc-spool-list-set) "mh-inc" "mh-inc.el" (16671
+;;;;;;  49652))
 ;;; Generated autoloads from mh-inc.el
 
 (autoload (quote mh-inc-spool-list-set) "mh-inc" "\
@@ -319,14 +319,14 @@ This is called after 'customize is used to alter `mh-inc-spool-list'." nil nil)
 \f
 ;;;### (autoloads (mh-index-choose mh-namazu-execute-search mh-swish++-execute-search
 ;;;;;;  mh-swish-execute-search mh-index-ticked-messages mh-index-new-messages
-;;;;;;  mh-index-sequenced-messages mh-glimpse-execute-search mh-index-delete-from-sequence
-;;;;;;  mh-index-add-to-sequence mh-index-execute-commands mh-index-update-unseen
-;;;;;;  mh-index-visit-folder mh-index-delete-folder-headers mh-index-group-by-folder
+;;;;;;  mh-index-sequenced-messages mh-index-delete-from-sequence
+;;;;;;  mh-index-add-to-sequence mh-index-execute-commands mh-index-visit-folder
+;;;;;;  mh-index-delete-folder-headers mh-index-group-by-folder mh-index-create-imenu-index
 ;;;;;;  mh-index-insert-folder-headers mh-index-previous-folder mh-index-next-folder
 ;;;;;;  mh-index-parse-search-regexp mh-index-do-search mh-index-p
 ;;;;;;  mh-index-read-data mh-index-search mh-index-create-sequences
 ;;;;;;  mh-create-sequence-map mh-index-update-maps) "mh-index" "mh-index.el"
-;;;;;;  (16625 54348))
+;;;;;;  (16665 55172))
 ;;; Generated autoloads from mh-index.el
 
 (autoload (quote mh-index-update-maps) "mh-index" "\
@@ -367,7 +367,6 @@ index for each program:
     - `mh-swish-execute-search'
     - `mh-mairix-execute-search'
     - `mh-namazu-execute-search'
-    - `mh-glimpse-execute-search'
 
 If none of these programs are present then we use pick. If desired grep can be
 used instead. Details about these methods can be found in:
@@ -411,6 +410,9 @@ Jump to the previous folder marker." t nil)
 (autoload (quote mh-index-insert-folder-headers) "mh-index" "\
 Annotate the search results with original folder names." nil nil)
 
+(autoload (quote mh-index-create-imenu-index) "mh-index" "\
+Create alist of folder names and positions in index folder buffers." nil nil)
+
 (autoload (quote mh-index-group-by-folder) "mh-index" "\
 Partition the messages based on source folder.
 Returns an alist with the the folder names in the car and the cdr being the
@@ -422,10 +424,6 @@ Delete the folder headers." nil nil)
 (autoload (quote mh-index-visit-folder) "mh-index" "\
 Visit original folder from where the message at point was found." t nil)
 
-(autoload (quote mh-index-update-unseen) "mh-index" "\
-Remove counterpart of MSG in source folder from `mh-unseen-seq'.
-Also `mh-update-unseen' is called in the original folder, if we have it open." nil nil)
-
 (autoload (quote mh-index-execute-commands) "mh-index" "\
 Delete/refile the actual messages.
 The copies in the searched folder are then deleted/refiled to get the desired
@@ -442,62 +440,25 @@ Delete from SEQ the messages in MSGS.
 This function updates the source folder sequences. Also makes an attempt to
 update the source folder buffer if present." nil nil)
 
-(autoload (quote mh-glimpse-execute-search) "mh-index" "\
-Execute glimpse and read the results.
-
-In the examples below, replace /home/user/Mail with the path to your MH
-directory.
-
-First create the directory /home/user/Mail/.glimpse. Then create the file
-/home/user/Mail/.glimpse/.glimpse_exclude with the following contents:
-
-    */.*
-    */#*
-    */,*
-    */*~
-    ^/home/user/Mail/.glimpse
-    ^/home/user/Mail/mhe-index
-
-If there are any directories you would like to ignore, append lines like the
-following to .glimpse_exclude:
-
-    ^/home/user/Mail/scripts
-
-You do not want to index the folders that hold the results of your searches
-since they tend to be ephemeral and the original messages are indexed anyway.
-The configuration file above assumes that the results are found in sub-folders
-of `mh-index-folder' which is +mhe-index by default.
-
-Use the following command line to generate the glimpse index. Run this
-daily from cron:
-
-    glimpseindex -H /home/user/Mail/.glimpse /home/user/Mail
-
-FOLDER-PATH is the directory in which SEARCH-REGEXP is used to search." nil nil)
-
 (autoload (quote mh-index-sequenced-messages) "mh-index" "\
 Display messages from FOLDERS in SEQUENCE.
-By default the folders specified by `mh-index-new-messages-folders' are
-searched. With a prefix argument, enter a space-separated list of folders, or
-nothing to search all folders.
-
-Argument SEQUENCE defaults to `mh-unseen-seq' and is the sequence that the
-function searches for in each of the FOLDERS. With a prefix argument, enter a
-sequence to use." t nil)
+All messages in the sequence you provide from the folders in
+`mh-index-new-messages-folders' are listed. With a prefix argument, enter a
+space-separated list of folders, or nothing to search all folders." t nil)
 
 (autoload (quote mh-index-new-messages) "mh-index" "\
 Display unseen messages.
-All messages in the `unseen' sequence from FOLDERS are displayed.
-By default the folders specified by `mh-index-new-messages-folders'
-are searched. With a prefix argument, enter a space-separated list of
-folders, or nothing to search all folders." t nil)
+If you use a program such as `procmail' to use `rcvstore' to file your
+incoming mail automatically, you can display new, unseen, messages using this
+command. All messages in the `unseen' sequence from the folders in
+`mh-index-new-messages-folders' are listed. With a prefix argument, enter a
+space-separated list of FOLDERS, or nothing to search all folders." t nil)
 
 (autoload (quote mh-index-ticked-messages) "mh-index" "\
 Display ticked messages.
-All messages in the `tick' sequence from FOLDERS are displayed.
-By default the folders specified by `mh-index-ticked-messages-folders'
-are searched. With a prefix argument, enter a space-separated list of
-folders, or nothing to search all folders." t nil)
+All messages in `mh-tick-seq' from the folders in
+`mh-index-ticked-messages-folders' are listed. With a prefix argument, enter a
+space-separated list of FOLDERS, or nothing to search all folders." t nil)
 
 (autoload (quote mh-swish-execute-search) "mh-index" "\
 Execute swish-e and read the results.
@@ -620,54 +581,69 @@ system." nil nil)
 
 ;;;***
 \f
+;;;### (autoloads (mh-variants mh-variant-p mh-variant-set) "mh-init"
+;;;;;;  "mh-init.el" (16671 49652))
+;;; Generated autoloads from mh-init.el
+
+(autoload (quote mh-variant-set) "mh-init" "\
+Set the MH variant to VARIANT.
+Sets `mh-progs', `mh-lib', `mh-lib-progs' and `mh-flists-present-flag'.
+If the VARIANT is `autodetect', then first try nmh, then MH and finally
+GNU mailutils." t nil)
+
+(autoload (quote mh-variant-p) "mh-init" "\
+Return t if variant is any of VARIANTS.
+Currently known variants are 'mh and 'nmh." nil nil)
+
+(autoload (quote mh-variants) "mh-init" "\
+Return a list of installed variants of MH on the system.
+This function looks for MH in `mh-sys-path', `mh-path' and
+`exec-path'. The format of the list of variants that is returned is described
+by the variable `mh-variants'." nil nil)
+
+;;;***
+\f
 ;;;### (autoloads (mh-junk-whitelist mh-junk-blacklist) "mh-junk"
-;;;;;;  "mh-junk.el" (16625 54386))
+;;;;;;  "mh-junk.el" (16671 49652))
 ;;; Generated autoloads from mh-junk.el
 
 (autoload (quote mh-junk-blacklist) "mh-junk" "\
 Blacklist RANGE as spam.
 
-Check the documentation of `mh-interactive-range' to see how RANGE is read in
-interactive use.
-
-First the appropriate function is called depending on the value of
-`mh-junk-choice'. Then if `mh-junk-mail-folder' is a string then the message is
-refiled to that folder. If nil, the message is deleted.
-
-To change the spam program being used, customize `mh-junk-program'. Directly
-setting `mh-junk-choice' is not recommended.
+This command trains the spam program in use (see the `mh-junk-program' option)
+with the content of the range (see `mh-interactive-range') and then handles
+the message(s) as specified by the `mh-junk-disposition' option.
 
-The documentation for the following functions describes what setup is needed
-for the different spam fighting programs:
+For more information about using your particular spam fighting program, see:
 
+  - `mh-spamassassin-blacklist'
   - `mh-bogofilter-blacklist'
-  - `mh-spamprobe-blacklist'
-  - `mh-spamassassin-blacklist'" t nil)
+  - `mh-spamprobe-blacklist'" t nil)
 
 (autoload (quote mh-junk-whitelist) "mh-junk" "\
-Whitelist RANGE incorrectly classified as spam.
+Whitelist RANGE as ham.
 
-Check the documentation of `mh-interactive-range' to see how RANGE is read in
-interactive use.
+This command reclassifies a range of messages (see `mh-interactive-range') as
+ham if it were incorrectly classified as spam. It then refiles the message
+into the `+inbox' folder.
 
-First the appropriate function is called depending on the value of
-`mh-junk-choice'. Then the message is refiled to `mh-inbox'.
-
-To change the spam program being used, customize `mh-junk-program'. Directly
-setting `mh-junk-choice' is not recommended." t nil)
+The `mh-junk-program' option specifies the spam program in use." t nil)
 
 ;;;***
 \f
-;;;### (autoloads (mh-mime-inline-part mh-mime-save-part mh-push-button
-;;;;;;  mh-press-button mh-mime-display mh-decode-message-header
-;;;;;;  mh-mime-save-parts mh-display-emphasis mh-display-smileys
-;;;;;;  mh-add-missing-mime-version-header mh-destroy-postponed-handles
-;;;;;;  mh-mime-cleanup mh-mml-directive-present-p mh-mml-secure-message-encrypt-pgpmime
-;;;;;;  mh-mml-secure-message-sign-pgpmime mh-mml-attach-file mh-mml-forward-message
-;;;;;;  mh-mml-to-mime mh-mhn-directive-present-p mh-revert-mhn-edit
-;;;;;;  mh-edit-mhn mh-mhn-compose-forw mh-mhn-compose-external-compressed-tar
-;;;;;;  mh-mhn-compose-anon-ftp mh-mhn-compose-insertion mh-compose-forward
-;;;;;;  mh-compose-insertion) "mh-mime" "mh-mime.el" (16625 54523))
+;;;### (autoloads (mh-display-with-external-viewer mh-mime-inline-part
+;;;;;;  mh-mime-save-part mh-push-button mh-press-button mh-mime-display
+;;;;;;  mh-decode-message-header mh-mime-save-parts mh-display-emphasis
+;;;;;;  mh-display-smileys mh-add-missing-mime-version-header mh-destroy-postponed-handles
+;;;;;;  mh-mime-cleanup mh-mml-directive-present-p mh-mml-secure-message-signencrypt
+;;;;;;  mh-mml-secure-message-encrypt mh-mml-secure-message-sign
+;;;;;;  mh-mml-unsecure-message mh-mml-attach-file mh-mml-query-cryptographic-method
+;;;;;;  mh-mml-forward-message mh-mml-to-mime mh-mhn-directive-present-p
+;;;;;;  mh-revert-mhn-edit mh-edit-mhn mh-mhn-compose-forw mh-mhn-compose-external-type
+;;;;;;  mh-mhn-compose-external-compressed-tar mh-mhn-compose-anon-ftp
+;;;;;;  mh-mhn-compose-insertion mh-file-mime-type mh-have-file-command
+;;;;;;  mh-compose-forward mh-compose-insertion) "mh-mime" "mh-mime.el"
+;;;;;;  (16665 55171))
 ;;; Generated autoloads from mh-mime.el
 
 (autoload (quote mh-compose-insertion) "mh-mime" "\
@@ -686,6 +662,14 @@ come.
 Optional argument MESSAGE is the message to forward.
 If any of the optional arguments are absent, they are prompted for." t nil)
 
+(autoload (quote mh-have-file-command) "mh-mime" "\
+Return t if 'file' command is on the system.
+'file -i' is used to get MIME type of composition insertion." nil nil)
+
+(autoload (quote mh-file-mime-type) "mh-mime" "\
+Return MIME type of FILENAME from file command.
+Returns nil if file command not on system." nil nil)
+
 (autoload (quote mh-mhn-compose-insertion) "mh-mime" "\
 Add a directive to insert a MIME message part from a file.
 This is the typical way to insert non-text parts in a message.
@@ -718,6 +702,18 @@ DESCRIPTION, a line of text for the Content-description header.
 
 See also \\[mh-edit-mhn]." t nil)
 
+(autoload (quote mh-mhn-compose-external-type) "mh-mime" "\
+Add a directive to include a MIME reference to a remote file.
+The file should be available via anonymous ftp. This directive tells MH to
+include a reference to a message/external-body part.
+
+Arguments are ACCESS-TYPE, HOST and FILENAME, which tell where to find the
+file and TYPE which is the MIME Content-Type. Optional arguments include
+DESCRIPTION, a line of text for the Content-description header, ATTRIBUTES,
+EXTRA-PARAMS, and COMMENT.
+
+See also \\[mh-edit-mhn]." t nil)
+
 (autoload (quote mh-mhn-compose-forw) "mh-mime" "\
 Add a forw directive to this message, to forward a message with MIME.
 This directive tells MH to include the named messages in this one.
@@ -758,7 +754,9 @@ Undo the effect of \\[mh-edit-mhn] by reverting to the backup file.
 Optional non-nil argument NOCONFIRM means don't ask for confirmation." t nil)
 
 (autoload (quote mh-mhn-directive-present-p) "mh-mime" "\
-Check if the current buffer has text which might be a MHN directive." nil nil)
+Check if the text between BEGIN and END might be a MHN directive.
+The optional argument BEGIN defaults to the beginning of the buffer, while END
+defaults to the the end of the buffer." nil nil)
 
 (autoload (quote mh-mml-to-mime) "mh-mime" "\
 Compose MIME message from mml directives.
@@ -770,6 +768,9 @@ Forward a message as attachment.
 The function will prompt the user for a DESCRIPTION, a FOLDER and MESSAGE
 number." nil nil)
 
+(autoload (quote mh-mml-query-cryptographic-method) "mh-mime" "\
+Read the cryptographic method to use." nil nil)
+
 (autoload (quote mh-mml-attach-file) "mh-mime" "\
 Attach a file to the outgoing MIME message.
 The file is not inserted or encoded until you send the message with
@@ -781,12 +782,18 @@ This is basically `mml-attach-file' from gnus, modified such that a prefix
 argument yields an `inline' disposition and Content-Type is determined
 automatically." nil nil)
 
-(autoload (quote mh-mml-secure-message-sign-pgpmime) "mh-mime" "\
-Add directive to encrypt/sign the entire message." t nil)
+(autoload (quote mh-mml-unsecure-message) "mh-mime" "\
+Remove any secure message directives.
+The IGNORE argument is not used." t nil)
 
-(autoload (quote mh-mml-secure-message-encrypt-pgpmime) "mh-mime" "\
-Add directive to encrypt and sign the entire message.
-If called with a prefix argument DONTSIGN, only encrypt (do NOT sign)." t nil)
+(autoload (quote mh-mml-secure-message-sign) "mh-mime" "\
+Add security directive to sign the entire message using METHOD." t nil)
+
+(autoload (quote mh-mml-secure-message-encrypt) "mh-mime" "\
+Add security directive to encrypt the entire message using METHOD." t nil)
+
+(autoload (quote mh-mml-secure-message-signencrypt) "mh-mime" "\
+Add security directive to encrypt and sign the entire message using METHOD." t nil)
 
 (autoload (quote mh-mml-directive-present-p) "mh-mime" "\
 Check if the current buffer has text which may be an MML directive." nil nil)
@@ -840,10 +847,13 @@ Save MIME part at point." t nil)
 (autoload (quote mh-mime-inline-part) "mh-mime" "\
 Toggle display of the raw MIME part." t nil)
 
+(autoload (quote mh-display-with-external-viewer) "mh-mime" "\
+View MIME PART-INDEX externally." t nil)
+
 ;;;***
 \f
-;;;### (autoloads (mh-do-search mh-pick-do-search mh-do-pick-search
-;;;;;;  mh-search-folder) "mh-pick" "mh-pick.el" (16625 54571))
+;;;### (autoloads (mh-do-search mh-pick-do-search mh-search-folder)
+;;;;;;  "mh-pick" "mh-pick.el" (16671 49652))
 ;;; Generated autoloads from mh-pick.el
 
 (autoload (quote mh-search-folder) "mh-pick" "\
@@ -853,13 +863,6 @@ Add the messages found to the sequence named `search'.
 Argument WINDOW-CONFIG is the current window configuration and is used when
 the search folder is dismissed." t nil)
 
-(autoload (quote mh-do-pick-search) "mh-pick" "\
-Find messages that match the qualifications in the current pattern buffer.
-Messages are searched for in the folder named in `mh-searching-folder'.
-Add the messages found to the sequence named `search'.
-
-This is a deprecated function and `mh-pick-do-search' should be used instead." t nil)
-
 (autoload (quote mh-pick-do-search) "mh-pick" "\
 Find messages that match the qualifications in the current pattern buffer.
 Messages are searched for in the folder named in `mh-searching-folder'.
@@ -873,19 +876,62 @@ indexing program specified in `mh-index-program' is used." t nil)
 
 ;;;***
 \f
+;;;### (autoloads (mh-print-msg mh-ps-print-toggle-mime mh-ps-print-toggle-color
+;;;;;;  mh-ps-print-toggle-faces mh-ps-print-msg-show mh-ps-print-msg-file
+;;;;;;  mh-ps-print-msg) "mh-print" "mh-print.el" (16671 49652))
+;;; Generated autoloads from mh-print.el
+
+(autoload (quote mh-ps-print-msg) "mh-print" "\
+Print the messages in RANGE.
+
+Check the documentation of `mh-interactive-range' to see how RANGE is read in
+interactive use." t nil)
+
+(autoload (quote mh-ps-print-msg-file) "mh-print" "\
+Print to FILE the messages in RANGE.
+
+Check the documentation of `mh-interactive-range' to see how RANGE is read in
+interactive use." t nil)
+
+(autoload (quote mh-ps-print-msg-show) "mh-print" "\
+Print current show buffer to FILE." t nil)
+
+(autoload (quote mh-ps-print-toggle-faces) "mh-print" "\
+Toggle whether printing is done with faces or not." t nil)
+
+(autoload (quote mh-ps-print-toggle-color) "mh-print" "\
+Toggle whether color is used in printing messages." t nil)
+
+(autoload (quote mh-ps-print-toggle-mime) "mh-print" "\
+Cycle through available choices on how MIME parts should be printed.
+The available settings are:
+  1. Print only inline MIME parts.
+  2. Print all MIME parts.
+  3. Print no MIME parts." t nil)
+
+(autoload (quote mh-print-msg) "mh-print" "\
+Print RANGE on printer.
+
+Check the documentation of `mh-interactive-range' to see how RANGE is read in
+interactive use.
+
+The variable `mh-lpr-command-format' is used to generate the print command.
+The messages are formatted by mhl. See the variable `mhl-formfile'." t nil)
+
+;;;***
+\f
 ;;;### (autoloads (mh-narrow-to-tick mh-toggle-tick mh-thread-refile
 ;;;;;;  mh-thread-delete mh-thread-ancestor mh-thread-previous-sibling
 ;;;;;;  mh-thread-next-sibling mh-thread-forget-message mh-toggle-threads
 ;;;;;;  mh-thread-add-spaces mh-thread-update-scan-line-map mh-thread-inc
 ;;;;;;  mh-delete-subject-or-thread mh-delete-subject mh-narrow-to-range
 ;;;;;;  mh-narrow-to-to mh-narrow-to-cc mh-narrow-to-from mh-narrow-to-subject
-;;;;;;  mh-region-to-msg-list mh-interactive-range mh-range-to-msg-list
-;;;;;;  mh-iterate-on-range mh-iterate-on-messages-in-region mh-add-to-sequence
-;;;;;;  mh-notate-cur mh-notate-seq mh-map-to-seq-msgs mh-rename-seq
-;;;;;;  mh-translate-range mh-read-range mh-read-seq-default mh-notate-deleted-and-refiled
-;;;;;;  mh-widen mh-put-msg-in-seq mh-narrow-to-seq mh-msg-is-in-seq
-;;;;;;  mh-list-sequences mh-delete-seq) "mh-seq" "mh-seq.el" (16625
-;;;;;;  54690))
+;;;;;;  mh-interactive-range mh-range-to-msg-list mh-iterate-on-range
+;;;;;;  mh-iterate-on-messages-in-region mh-add-to-sequence mh-notate-cur
+;;;;;;  mh-rename-seq mh-translate-range mh-read-range mh-read-seq-default
+;;;;;;  mh-notate-deleted-and-refiled mh-widen mh-put-msg-in-seq
+;;;;;;  mh-narrow-to-seq mh-msg-is-in-seq mh-list-sequences mh-delete-seq)
+;;;;;;  "mh-seq" "mh-seq.el" (16668 22297))
 ;;; Generated autoloads from mh-seq.el
 
 (autoload (quote mh-delete-seq) "mh-seq" "\
@@ -895,8 +941,9 @@ Delete the SEQUENCE." t nil)
 List the sequences defined in the folder being visited." t nil)
 
 (autoload (quote mh-msg-is-in-seq) "mh-seq" "\
-Display the sequences that contain MESSAGE.
-Default is the displayed message." t nil)
+Display the sequences in which the current message appears.
+Use a prefix argument to display the sequences in which another MESSAGE
+appears." t nil)
 
 (autoload (quote mh-narrow-to-seq) "mh-seq" "\
 Restrict display of this folder to just messages in SEQUENCE.
@@ -909,10 +956,8 @@ Check the documentation of `mh-interactive-range' to see how RANGE is read in
 interactive use." t nil)
 
 (autoload (quote mh-widen) "mh-seq" "\
-Remove last restriction from current folder.
-If optional prefix argument ALL-FLAG is non-nil, then unwind to the beginning
-of the view stack thereby showing all messages that the buffer originally
-contained." t nil)
+Restore the previous limit.
+If optional prefix argument ALL-FLAG is non-nil, remove all limits." t nil)
 
 (autoload (quote mh-notate-deleted-and-refiled) "mh-seq" "\
 Notate messages marked for deletion or refiling.
@@ -965,16 +1010,6 @@ In FOLDER, translate the string EXPR to a list of messages numbers." nil nil)
 (autoload (quote mh-rename-seq) "mh-seq" "\
 Rename SEQUENCE to have NEW-NAME." t nil)
 
-(autoload (quote mh-map-to-seq-msgs) "mh-seq" "\
-Invoke the FUNC at each message in the SEQ.
-SEQ can either be a list of messages or a MH sequence. The remaining ARGS are
-passed as arguments to FUNC." nil nil)
-
-(autoload (quote mh-notate-seq) "mh-seq" "\
-Mark the scan listing.
-All messages in SEQ are marked with NOTATION at OFFSET from the beginning of
-the line." nil nil)
-
 (autoload (quote mh-notate-cur) "mh-seq" "\
 Mark the MH sequence cur.
 In addition to notating the current message with `mh-note-cur' the function
@@ -1019,37 +1054,44 @@ RANGE-PROMPT. A list of messages in that range is returned.
 If a MH range is given, say something like last:20, then a list containing
 the messages in that range is returned.
 
+If DEFAULT non-nil then it is returned.
+
 Otherwise, the message number at point is returned.
 
 This function is usually used with `mh-iterate-on-range' in order to provide
 a uniform interface to MH-E functions." nil nil)
 
-(autoload (quote mh-region-to-msg-list) "mh-seq" "\
-Return a list of messages within the region between BEGIN and END." nil nil)
-
 (autoload (quote mh-narrow-to-subject) "mh-seq" "\
-Narrow to a sequence containing all following messages with same subject." t nil)
+Limit to messages with same subject.
+With a prefix argument, edit PICK-EXPR.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command." t nil)
 
 (autoload (quote mh-narrow-to-from) "mh-seq" "\
-Limit to messages with the same From header field as the message at point.
-With a prefix argument, prompt for the regular expression, REGEXP given to
-pick." t nil)
+Limit to messages with the same `From:' field.
+With a prefix argument, edit PICK-EXPR.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command." t nil)
 
 (autoload (quote mh-narrow-to-cc) "mh-seq" "\
-Limit to messages with the same Cc header field as the message at point.
-With a prefix argument, prompt for the regular expression, REGEXP given to
-pick." t nil)
+Limit to messages with the same `Cc:' field.
+With a prefix argument, edit PICK-EXPR.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command." t nil)
 
 (autoload (quote mh-narrow-to-to) "mh-seq" "\
-Limit to messages with the same To header field as the message at point.
-With a prefix argument, prompt for the regular expression, REGEXP given to
-pick." t nil)
+Limit to messages with the same `To:' field.
+With a prefix argument, edit PICK-EXPR.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command." t nil)
 
 (autoload (quote mh-narrow-to-range) "mh-seq" "\
 Limit to messages in RANGE.
 
 Check the documentation of `mh-interactive-range' to see how RANGE is read in
-interactive use." t nil)
+interactive use.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command." t nil)
 
 (autoload (quote mh-delete-subject) "mh-seq" "\
 Mark all following messages with same subject to be deleted.
@@ -1103,14 +1145,15 @@ Mark current message and all its children for refiling to FOLDER." t nil)
 Toggle tick mark of all messages in RANGE." t nil)
 
 (autoload (quote mh-narrow-to-tick) "mh-seq" "\
-Restrict display of this folder to just messages in `mh-tick-seq'.
+Limit to messages in `mh-tick-seq'.
+
 Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command." t nil)
 
 ;;;***
 \f
 ;;;### (autoloads (mh-speed-add-folder mh-speed-invalidate-map mh-speed-flists
 ;;;;;;  mh-speed-view mh-speed-toggle mh-folder-speedbar-buttons)
-;;;;;;  "mh-speed" "mh-speed.el" (16625 54721))
+;;;;;;  "mh-speed" "mh-speed.el" (16665 55171))
 ;;; Generated autoloads from mh-speed.el
 
 (autoload (quote mh-folder-speedbar-buttons) "mh-speed" "\
@@ -1145,31 +1188,24 @@ The function invalidates the latest ancestor that is present." nil nil)
 
 ;;;***
 \f
-;;;### (autoloads (mh-get-msg-num mh-goto-address-find-address-at-point)
-;;;;;;  "mh-utils" "mh-utils.el" (16625 54979))
-;;; Generated autoloads from mh-utils.el
-
-(autoload (quote mh-goto-address-find-address-at-point) "mh-utils" "\
-Find e-mail address around or before point.
-Then search backwards to beginning of line for the start of an e-mail
-address.  If no e-mail address found, return nil." nil nil)
-
-(autoload (quote mh-get-msg-num) "mh-utils" "\
-Return the message number of the displayed message.
-If the argument ERROR-IF-NO-MESSAGE is non-nil, then complain if the cursor is
-not pointing to a message." nil nil)
-
-;;;***
-\f
 ;;;### (autoloads (mh-alias-apropos mh-alias-add-address-under-point
-;;;;;;  mh-alias-grab-from-field mh-alias-add-alias mh-alias-from-has-no-alias-p
+;;;;;;  mh-alias-grab-from-field mh-alias-add-alias mh-alias-for-from-p
 ;;;;;;  mh-alias-address-to-alias mh-alias-letter-expand-alias mh-alias-minibuffer-confirm-address
 ;;;;;;  mh-read-address mh-alias-reload-maybe mh-alias-reload) "mh-alias"
-;;;;;;  "mh-alias.el" (16625 53006))
+;;;;;;  "mh-alias.el" (16671 49553))
 ;;; Generated autoloads from mh-alias.el
 
 (autoload (quote mh-alias-reload) "mh-alias" "\
-Load MH aliases into `mh-alias-alist'." t nil)
+Reload MH aliases.
+
+Since aliases are updated frequently, MH-E will reload aliases automatically
+whenever an alias lookup occurs if an alias source (a file listed in your
+`Aliasfile:' profile component and your password file if variable
+`mh-alias-local-users' is non-nil) has changed. However, you can reload your
+aliases manually by calling this command directly.
+
+The value of `mh-alias-reloaded-hook' is a list of functions to be called,
+with no arguments, after the aliases have been loaded." t nil)
 
 (autoload (quote mh-alias-reload-maybe) "mh-alias" "\
 Load new MH aliases." nil nil)
@@ -1186,26 +1222,25 @@ Expand mail alias before point." nil nil)
 (autoload (quote mh-alias-address-to-alias) "mh-alias" "\
 Return the ADDRESS alias if defined, or nil." nil nil)
 
-(autoload (quote mh-alias-from-has-no-alias-p) "mh-alias" "\
-Return t is From has no current alias set.
-In the exceptional situation where there isn't a From header in the message the
-function returns nil." nil nil)
+(autoload (quote mh-alias-for-from-p) "mh-alias" "\
+Return t if sender's address has a corresponding alias." nil nil)
 
 (autoload (quote mh-alias-add-alias) "mh-alias" "\
 *Add ALIAS for ADDRESS in personal alias file.
-Prompts for confirmation if the address already has an alias.
-If the alias is already is use, `mh-alias-add-alias-to-file' will prompt." t nil)
+This function prompts you for an alias and address. If the alias exists
+already, you will have the choice of inserting the new alias before or after
+the old alias. In the former case, this alias will be used when sending mail
+to this alias. In the latter case, the alias serves as an additional folder
+name hint when filing messages." t nil)
 
 (autoload (quote mh-alias-grab-from-field) "mh-alias" "\
-*Add ALIAS for ADDRESS in personal alias file.
-Prompts for confirmation if the alias is already in use or if the address
-already has an alias." t nil)
+*Add alias for the sender of the current message." t nil)
 
 (autoload (quote mh-alias-add-address-under-point) "mh-alias" "\
-Insert an alias for email address under point." t nil)
+Insert an alias for address under point." t nil)
 
 (autoload (quote mh-alias-apropos) "mh-alias" "\
-Show all aliases that match REGEXP either in name or content." t nil)
+Show all aliases or addresses that match REGEXP." t nil)
 
 ;;;***
 \f
index 91cbcec..6b3c579 100644 (file)
@@ -34,7 +34,7 @@
 
 ;;; Code:
 
-(require 'mh-utils)
+(eval-when-compile (require 'mh-acros))
 (mh-require-cl)
 (require 'mh-comp)
 (require 'gnus-util)
@@ -46,8 +46,7 @@
 (autoload 'gnus-eval-format "gnus-spec")
 (autoload 'widget-convert-button "wid-edit")
 (autoload 'message-options-set-recipient "message")
-(autoload 'mml-secure-message-sign-pgpmime "mml-sec")
-(autoload 'mml-secure-message-encrypt-pgpmime "mml-sec")
+(autoload 'mml-unsecure-message "mml-sec")
 (autoload 'mml-minibuffer-read-file "mml")
 (autoload 'mml-minibuffer-read-description "mml")
 (autoload 'mml-insert-empty-tag "mml")
@@ -82,7 +81,7 @@ If any of the optional arguments are absent, they are prompted for."
                 (read-string "Forw Content-description: ")
                 (mh-prompt-for-folder "Message from" mh-sent-from-folder nil)
                 (read-string (format "Messages%s: "
-                                     (if mh-sent-from-msg
+                                     (if (numberp mh-sent-from-msg)
                                          (format " [%d]" mh-sent-from-msg)
                                        "")))))
   (if (equal mh-compose-insertion 'gnus)
@@ -114,6 +113,7 @@ MH profile.")
 ;; the variable, so things should work exactly as before.
 (defvar mh-have-file-command)
 
+;;;###mh-autoload
 (defun mh-have-file-command ()
   "Return t if 'file' command is on the system.
 'file -i' is used to get MIME type of composition insertion."
@@ -129,7 +129,8 @@ MH profile.")
 
 (defvar mh-file-mime-type-substitutions
   '(("application/msword" "\.xls" "application/ms-excel")
-    ("application/msword" "\.ppt" "application/ms-powerpoint"))
+    ("application/msword" "\.ppt" "application/ms-powerpoint")
+    ("text/plain" "\.vcf" "text/x-vcard"))
   "Substitutions to make for Content-Type returned from file command.
 The first element is the Content-Type returned by the file command.
 The second element is a regexp matching the file name, usually the extension.
@@ -151,6 +152,7 @@ Substitutions are made from the `mh-file-mime-type-substitutions' variable."
         (setq subst (cdr subst))))
     answer))
 
+;;;###mh-autoload
 (defun mh-file-mime-type (filename)
   "Return MIME type of FILENAME from file command.
 Returns nil if file command not on system."
@@ -192,12 +194,38 @@ Returns nil if file command not on system."
     ("message/external-body") ("message/partial") ("message/rfc822")
 
     ("text/enriched") ("text/html") ("text/plain") ("text/rfc822-headers")
-    ("text/richtext") ("text/xml")
+    ("text/richtext") ("text/x-vcard") ("text/xml")
 
     ("video/mpeg") ("video/quicktime"))
   "Legal MIME content types.
 See documentation for \\[mh-edit-mhn].")
 
+;; RFC 2045 - Multipurpose Internet Mail Extensions (MIME) Part One:
+;;            Format of Internet Message Bodies.
+;; RFC 2046 - Multipurpose Internet Mail Extensions (MIME) Part Two:
+;;            Media Types.
+;; RFC 2049 - Multipurpose Internet Mail Extensions (MIME) Part Five:
+;;            Conformance Criteria and Examples.
+;; RFC 2017 - Definition of the URL MIME External-Body Access-Type
+;; RFC 1738 - Uniform Resource Locators (URL)
+(defvar mh-access-types
+  '(("anon-ftp")        ; RFC2046 Anonymous File Transfer Protocol
+    ("file")            ; RFC1738 Host-specific file names
+    ("ftp")             ; RFC2046 File Transfer Protocol
+    ("gopher")          ; RFC1738 The Gopher Protocol
+    ("http")            ; RFC1738 Hypertext Transfer Protocol
+    ("local-file")      ; RFC2046 Local file access
+    ("mail-server")     ; RFC2046 mail-server Electronic mail address
+    ("mailto")          ; RFC1738 Electronic mail address
+    ("news")            ; RFC1738 Usenet news
+    ("nntp")            ; RFC1738 Usenet news using NNTP access
+    ("propspero")       ; RFC1738 Prospero Directory Service
+    ("telnet")          ; RFC1738 Telnet
+    ("tftp")            ; RFC2046 Trivial File Transfer Protocol
+    ("url")             ; RFC2017 URL scheme MIME access-type Protocol
+    ("wais"))           ; RFC1738 Wide Area Information Servers
+  "Legal MIME access-type values.")
+
 ;;;###mh-autoload
 (defun mh-mhn-compose-insertion (filename type description attributes)
   "Add a directive to insert a MIME message part from a file.
@@ -286,7 +314,7 @@ See also \\[mh-edit-mhn]."
                                 "type=tar; conversions=x-compress"
                                 "mode=image"))
 
-
+;;;###mh-autoload
 (defun mh-mhn-compose-external-type (access-type host filename type
                                                  &optional description
                                                  attributes extra-params
@@ -301,6 +329,18 @@ DESCRIPTION, a line of text for the Content-description header, ATTRIBUTES,
 EXTRA-PARAMS, and COMMENT.
 
 See also \\[mh-edit-mhn]."
+  (interactive (list
+                (completing-read "Access Type: " mh-access-types)
+                (read-string "Remote host: ")
+                (read-string "Remote url-path: ")
+                (completing-read "Content-Type: "
+                                 (if (fboundp 'mailcap-mime-types)
+                                     (mapcar 'list (mailcap-mime-types))
+                                   mh-mime-content-types))
+                (if current-prefix-arg (read-string "Content-description: "))
+                (if current-prefix-arg (read-string "Attributes: "))
+                (if current-prefix-arg (read-string "Extra Parameters: "))
+                (if current-prefix-arg (read-string "Comment: "))))
   (beginning-of-line)
   (insert "#@" type)
   (and attributes
@@ -314,7 +354,9 @@ See also \\[mh-edit-mhn]."
   (insert "access-type=" access-type "; ")
   (insert "site=" host)
   (insert "; name=" (file-name-nondirectory filename))
-  (insert "; directory=\"" (file-name-directory filename) "\"")
+  (let ((directory (file-name-directory filename)))
+    (and directory
+         (insert "; directory=\"" directory "\"")))
   (and extra-params
        (insert "; " extra-params))
   (insert "\n"))
@@ -332,7 +374,7 @@ See also \\[mh-edit-mhn]."
                 (read-string "Forw Content-description: ")
                 (mh-prompt-for-folder "Message from" mh-sent-from-folder nil)
                 (read-string (format "Messages%s: "
-                                     (if mh-sent-from-msg
+                                     (if (numberp mh-sent-from-msg)
                                          (format " [%d]" mh-sent-from-msg)
                                        "")))))
   (beginning-of-line)
@@ -349,7 +391,7 @@ See also \\[mh-edit-mhn]."
       (let ((start (point)))
         (insert " " messages)
         (subst-char-in-region start (point) ?, ? ))
-    (if mh-sent-from-msg
+    (if (numberp mh-sent-from-msg)
         (insert " " (int-to-string mh-sent-from-msg))))
   (insert "\n"))
 
@@ -380,10 +422,11 @@ arguments, after performing the conversion.
 
 The mhn program is part of MH version 6.8 or later."
   (interactive "*P")
+  (mh-mhn-quote-unescaped-sharp)
   (save-buffer)
   (message "mhn editing...")
   (cond
-   (mh-nmh-flag
+   ((mh-variant-p 'nmh)
     (mh-exec-cmd-error nil
                        "mhbuild" (if extra-args mh-mhn-args) buffer-file-name))
    (t
@@ -393,6 +436,19 @@ The mhn program is part of MH version 6.8 or later."
   (message "mhn editing...done")
   (run-hooks 'mh-edit-mhn-hook))
 
+(defun mh-mhn-quote-unescaped-sharp ()
+  "Quote `#' characters that haven't been quoted for `mhbuild'.
+If the `#' character is present in the first column, but it isn't part of a
+MHN directive then `mhbuild' gives an error. This function will quote all such
+characters."
+  (save-excursion
+    (goto-char (point-min))
+    (while (re-search-forward "^#" nil t)
+      (beginning-of-line)
+      (unless (mh-mhn-directive-present-p (point) (line-end-position))
+        (insert "#"))
+      (goto-char (line-end-position)))))
+
 ;;;###mh-autoload
 (defun mh-revert-mhn-edit (noconfirm)
   "Undo the effect of \\[mh-edit-mhn] by reverting to the backup file.
@@ -422,18 +478,24 @@ Optional non-nil argument NOCONFIRM means don't ask for confirmation."
     (after-find-file nil)))
 
 ;;;###mh-autoload
-(defun mh-mhn-directive-present-p ()
-  "Check if the current buffer has text which might be a MHN directive."
+(defun mh-mhn-directive-present-p (&optional begin end)
+  "Check if the text between BEGIN and END might be a MHN directive.
+The optional argument BEGIN defaults to the beginning of the buffer, while END
+defaults to the the end of the buffer."
+  (unless begin (setq begin (point-min)))
+  (unless end (setq end (point-max)))
   (save-excursion
     (block 'search-for-mhn-directive
-      (goto-char (point-min))
-      (while (re-search-forward "^#" nil t)
+      (goto-char begin)
+      (while (re-search-forward "^#" end t)
         (let ((s (buffer-substring-no-properties (point) (line-end-position))))
           (cond ((equal s ""))
                 ((string-match "^forw[ \t\n]+" s)
                  (return-from 'search-for-mhn-directive t))
                 (t (let ((first-token (car (split-string s "[ \t;@]"))))
-                     (when (string-match mh-media-type-regexp first-token)
+                     (when (and first-token
+                                (string-match mh-media-type-regexp
+                                              first-token))
                        (return-from 'search-for-mhn-directive t)))))))
       nil)))
 
@@ -450,14 +512,23 @@ function may be called manually before sending the draft as well."
   (require 'message)
   (when mh-gnus-pgp-support-flag ;; This is only needed for PGP
     (message-options-set-recipient))
-  (mml-to-mime))
+  (let ((saved-text (buffer-string))
+        (buffer (current-buffer))
+        (modified-flag (buffer-modified-p)))
+    (condition-case err (mml-to-mime)
+      (error
+       (with-current-buffer buffer
+         (delete-region (point-min) (point-max))
+         (insert saved-text)
+         (set-buffer-modified-p modified-flag))
+       (error (error-message-string err))))))
 
 ;;;###mh-autoload
 (defun mh-mml-forward-message (description folder message)
   "Forward a message as attachment.
 The function will prompt the user for a DESCRIPTION, a FOLDER and MESSAGE
 number."
-  (let ((msg (if (equal message "")
+  (let ((msg (if (and (equal message "") (numberp mh-sent-from-msg))
                  mh-sent-from-msg
                (car (read-from-string message)))))
     (cond ((integerp msg)
@@ -473,6 +544,19 @@ number."
                               description)))
           (t (error "The message number, %s is not a integer!" msg)))))
 
+(defvar mh-mml-cryptographic-method-history ())
+
+;;;###mh-autoload
+(defun mh-mml-query-cryptographic-method ()
+  "Read the cryptographic method to use."
+  (if current-prefix-arg
+      (let ((def (or (car mh-mml-cryptographic-method-history)
+                     mh-mml-method-default)))
+        (completing-read (format "Method: [%s] " def)
+                         '(("pgp") ("pgpmime") ("smime"))
+                         nil t nil 'mh-mml-cryptographic-method-history def))
+    mh-mml-method-default))
+
 ;;;###mh-autoload
 (defun mh-mml-attach-file (&optional disposition)
   "Attach a file to the outgoing MIME message.
@@ -499,22 +583,56 @@ automatically."
     (mml-insert-empty-tag 'part 'type type 'filename file
                           'disposition dispos 'description description)))
 
-;;;###mh-autoload
-(defun mh-mml-secure-message-sign-pgpmime ()
-  "Add directive to encrypt/sign the entire message."
-  (interactive)
+(defun mh-secure-message (method mode &optional identity)
+  "Add directive to Encrypt/Sign an entire message.
+METHOD should be one of: \"pgpmime\", \"pgp\", \"smime\".
+MODE should be one of: \"sign\", \"encrypt\", \"signencrypt\", \"none\".
+IDENTITY is optionally the default-user-id to use."
   (if (not mh-gnus-pgp-support-flag)
       (error "Sorry.  Your version of gnus does not support PGP/GPG")
-    (mml-secure-message-sign-pgpmime)))
+    ;; Check the arguments
+    (let ((valid-methods (list "pgpmime" "pgp" "smime"))
+          (valid-modes (list "sign" "encrypt" "signencrypt" "none")))
+      (if (not (member method valid-methods))
+          (error (format "Sorry. METHOD \"%s\" is invalid." method)))
+      (if (not (member mode valid-modes))
+          (error (format "Sorry. MODE \"%s\" is invalid" mode)))
+      (mml-unsecure-message)
+      (if (not (string= mode "none"))
+        (save-excursion
+          (goto-char (point-min))
+          (mh-goto-header-end 1)
+          (if mh-identity-pgg-default-user-id
+              (mml-insert-tag 'secure 'method method 'mode mode
+                              'sender mh-identity-pgg-default-user-id)
+            (mml-insert-tag 'secure 'method method 'mode mode)))))))
 
 ;;;###mh-autoload
-(defun mh-mml-secure-message-encrypt-pgpmime (&optional dontsign)
-  "Add directive to encrypt and sign the entire message.
-If called with a prefix argument DONTSIGN, only encrypt (do NOT sign)."
+(defun mh-mml-unsecure-message (&optional ignore)
+  "Remove any secure message directives.
+The IGNORE argument is not used."
   (interactive "P")
   (if (not mh-gnus-pgp-support-flag)
       (error "Sorry.  Your version of gnus does not support PGP/GPG")
-    (mml-secure-message-encrypt-pgpmime dontsign)))
+    (mml-unsecure-message)))
+
+;;;###mh-autoload
+(defun mh-mml-secure-message-sign (method)
+  "Add security directive to sign the entire message using METHOD."
+  (interactive (list (mh-mml-query-cryptographic-method)))
+  (mh-secure-message method "sign" mh-identity-pgg-default-user-id))
+
+;;;###mh-autoload
+(defun mh-mml-secure-message-encrypt (method)
+  "Add security directive to encrypt the entire message using METHOD."
+  (interactive (list (mh-mml-query-cryptographic-method)))
+  (mh-secure-message method "encrypt" mh-identity-pgg-default-user-id))
+
+;;;###mh-autoload
+(defun mh-mml-secure-message-signencrypt (method)
+  "Add security directive to encrypt and sign the entire message using METHOD."
+  (interactive (list (mh-mml-query-cryptographic-method)))
+  (mh-secure-message method "signencrypt" mh-identity-pgg-default-user-id))
 
 ;;;###mh-autoload
 (defun mh-mml-directive-present-p ()
@@ -667,19 +785,19 @@ actual storing."
         (folder (if (eq major-mode 'mh-show-mode)
                     mh-show-folder-buffer
                   mh-current-folder))
-        (command (if mh-nmh-flag "mhstore" "mhn"))
+        (command (if (mh-variant-p 'nmh) "mhstore" "mhn"))
         (directory
          (cond
           ((and (or arg
                     (equal nil mh-mime-save-parts-default-directory)
                     (equal t mh-mime-save-parts-default-directory))
                 (not mh-mime-save-parts-directory))
-           (read-file-name "Store in what directory? " nil nil t nil))
+           (read-file-name "Store in directory: " nil nil t nil))
           ((and (or arg
                     (equal t mh-mime-save-parts-default-directory))
                 mh-mime-save-parts-directory)
            (read-file-name (format
-                            "Store in what directory? [%s] "
+                            "Store in directory: [%s] "
                             mh-mime-save-parts-directory)
                            "" mh-mime-save-parts-directory t ""))
           ((stringp mh-mime-save-parts-default-directory)
@@ -689,7 +807,7 @@ actual storing."
     (if (and (equal directory "") mh-mime-save-parts-directory)
         (setq directory mh-mime-save-parts-directory))
     (if (not (file-directory-p directory))
-        (message "No directory specified.")
+        (message "No directory specified")
       (if (equal nil mh-mime-save-parts-default-directory)
           (setq mh-mime-save-parts-directory directory))
       (save-excursion
@@ -766,17 +884,18 @@ displayed."
                                       (mh-mime-handles (mh-buffer-data))))
               (unless handles (mh-decode-message-body)))
 
-            (when (and handles
-                       (or (not (stringp (car handles))) (cdr handles)))
-              ;; Goto start of message body
-              (goto-char (point-min))
-              (or (search-forward "\n\n" nil t) (goto-char (point-max)))
+            (cond ((and handles
+                        (or (not (stringp (car handles))) (cdr handles)))
+                   ;; Goto start of message body
+                   (goto-char (point-min))
+                   (or (search-forward "\n\n" nil t) (goto-char (point-max)))
 
-              ;; Delete the body
-              (delete-region (point) (point-max))
+                   ;; Delete the body
+                   (delete-region (point) (point-max))
 
-              ;; Display the MIME handles
-              (mh-mime-display-part handles)))
+                   ;; Display the MIME handles
+                   (mh-mime-display-part handles))
+                  (t (mh-signature-highlight))))
         (error
          (message "Please report this error. The error message is:\n %s"
                   (error-message-string err))
@@ -874,7 +993,7 @@ This is only useful if a Content-Disposition header is not present."
            (save-restriction
              (widen)
              (goto-char (point-min))
-             (not (re-search-forward "^-- $" nil t)))))))
+             (not (mh-signature-separator-p)))))))
 
 (defun mh-mime-display-single (handle)
   "Display a leaf node, HANDLE in the MIME tree."
@@ -904,7 +1023,8 @@ This is only useful if a Content-Disposition header is not present."
              (insert "\n")
              (mh-insert-mime-button handle (mh-mime-part-index handle) nil))
             ((and displayp (not mh-display-buttons-for-inline-parts-flag))
-             (or (mm-display-part handle) (mm-display-part handle)))
+             (or (mm-display-part handle) (mm-display-part handle))
+             (mh-signature-highlight handle))
             ((and displayp mh-display-buttons-for-inline-parts-flag)
              (insert "\n")
              (mh-insert-mime-button handle (mh-mime-part-index handle) nil)
@@ -912,6 +1032,28 @@ This is only useful if a Content-Disposition header is not present."
              (mh-mm-display-part handle)))
       (goto-char (point-max)))))
 
+(defun mh-signature-highlight (&optional handle)
+  "Highlight message signature in HANDLE.
+The optional argument, HANDLE is a MIME handle if the function is being used
+to highlight the signature in a MIME part."
+  (let ((regexp
+         (cond ((not handle) "^-- $")
+               ((not (and (equal (mm-handle-media-supertype handle) "text")
+                          (equal (mm-handle-media-subtype handle) "html")))
+                "^-- $")
+               ((eq (mh-mm-text-html-renderer) 'lynx) "^   --$")
+               (t "^--$"))))
+    (save-excursion
+      (goto-char (point-max))
+      (when (re-search-backward regexp nil t)
+        (mh-do-in-gnu-emacs
+          (let ((ov (make-overlay (point) (point-max))))
+            (overlay-put ov 'face 'mh-show-signature-face)
+            (overlay-put ov 'evaporate t)))
+        (mh-do-in-xemacs
+          (set-extent-property (make-extent (point) (point-max))
+                               'face 'mh-show-signature-face))))))
+
 (mh-do-in-xemacs
  (defvar dots)
  (defvar type))
@@ -954,7 +1096,9 @@ like \"K v\" which operate on individual MIME parts."
      :action 'mh-widget-press-button
      :button-keymap mh-mime-button-map
      :help-echo
-     "Mouse-2 click or press RET (in show buffer) to toggle display")))
+     "Mouse-2 click or press RET (in show buffer) to toggle display")
+    (dolist (ov (mh-funcall-if-exists overlays-in begin end))
+      (mh-funcall-if-exists overlay-put ov 'evaporate t))))
 
 ;; There is a bug in Gnus inline image display due to which an extra line
 ;; gets inserted every time it is viewed. To work around that problem we are
@@ -1009,7 +1153,8 @@ like \"K v\" which operate on individual MIME parts."
                   (when (eq mh-highlight-citation-p 'gnus)
                     (mh-gnus-article-highlight-citation))
                   (mh-display-smileys)
-                  (mh-display-emphasis))
+                  (mh-display-emphasis)
+                  (mh-signature-highlight handle))
                 (setq region (cons (progn (goto-char (point-min))
                                           (point-marker))
                                    (progn (goto-char (point-max))
@@ -1098,6 +1243,31 @@ button."
     (goto-char point)
     (set-buffer-modified-p nil)))
 
+;;;###mh-autoload
+(defun mh-display-with-external-viewer (part-index)
+  "View MIME PART-INDEX externally."
+  (interactive "P")
+  (when (consp part-index) (setq part-index (car part-index)))
+  (mh-folder-mime-action
+   part-index
+   #'(lambda ()
+       (let* ((part (get-text-property (point) 'mh-data))
+              (type (mm-handle-media-type part))
+              (methods (mapcar (lambda (x) (list (cdr (assoc 'viewer x))))
+                               (mailcap-mime-info type 'all)))
+              (def (caar methods))
+              (prompt (format "Viewer: %s" (if def (format "[%s] " def) "")))
+              (method (completing-read prompt methods nil nil nil nil def))
+              (folder mh-show-folder-buffer)
+              (buffer-read-only nil))
+         (when (string-match "^[^% \t]+$" method)
+           (setq method (concat method " %s")))
+         (flet ((mm-handle-set-external-undisplayer (handle function)
+                  (mh-handle-set-external-undisplayer folder handle function)))
+           (unwind-protect (mm-display-external part method)
+             (set-buffer-modified-p nil)))))
+   nil))
+
 (defun mh-widget-press-button (widget el)
   "Callback for widget, WIDGET.
 Parameter EL is unused."
@@ -1106,9 +1276,9 @@ Parameter EL is unused."
 
 (defun mh-mime-display-security (handle)
   "Display PGP encrypted/signed message, HANDLE."
-  (insert "\n")
   (save-restriction
     (narrow-to-region (point) (point))
+    (insert "\n")
     (mh-insert-mime-security-button handle)
     (mh-mime-display-mixed (cdr handle))
     (insert "\n")
@@ -1116,9 +1286,7 @@ Parameter EL is unused."
            mh-mime-security-button-end-line-format))
       (mh-insert-mime-security-button handle))
     (mm-set-handle-multipart-parameter
-     handle 'mh-region
-     (cons (set-marker (make-marker) (point-min))
-           (set-marker (make-marker) (point-max))))))
+     handle 'mh-region (cons (point-min-marker) (point-max-marker)))))
 
 ;;; I rewrote the security part because Gnus doesn't seem to ever minimize
 ;;; the button. That is once the mime-security button is pressed there seems
@@ -1149,8 +1317,22 @@ Parameter EL is unused."
 
 (defun mh-mime-security-press-button (handle)
   "Callback from security button for part HANDLE."
-  (when (mm-handle-multipart-ctl-parameter handle 'gnus-info)
-    (mh-mime-security-show-details handle)))
+  (if (mm-handle-multipart-ctl-parameter handle 'gnus-info)
+      (mh-mime-security-show-details handle)
+    (let ((region (mm-handle-multipart-ctl-parameter handle 'mh-region))
+          point)
+      (setq point (point))
+      (goto-char (car region))
+      (delete-region (car region) (cdr region))
+      (with-current-buffer (mm-handle-multipart-ctl-parameter handle 'buffer)
+        (let* ((mm-verify-option 'known)
+               (mm-decrypt-option 'known)
+               (new (mm-possibly-verify-or-decrypt (cdr handle) handle)))
+          (unless (eq new (cdr handle))
+            (mm-destroy-parts (cdr handle))
+            (setcdr handle new))))
+      (mh-mime-display-security handle)
+      (goto-char point))))
 
 ;; These variables should already be initialized in mm-decode.el if we have a
 ;; recent enough Gnus. The defvars are here to avoid compiler warnings.
@@ -1191,6 +1373,8 @@ Parameter EL is unused."
                            :action 'mh-widget-press-button
                            :button-keymap mh-mime-security-button-map
                            :help-echo "Mouse-2 click or press RET (in show buffer) to see security details.")
+    (dolist (ov (mh-funcall-if-exists overlays-in begin end))
+      (mh-funcall-if-exists overlay-put ov 'evaporate t))
     (when (equal info "Failed")
       (let* ((type (if (equal (car handle) "multipart/signed")
                        "verification" "decryption"))
@@ -1204,8 +1388,8 @@ The function decodes the message and displays it. It avoids decoding the same
 message multiple times."
   (let ((b (point))
         (clean-message-header mh-clean-message-header-flag)
-        (invisible-headers mh-invisible-headers)
-        (visible-headers mh-visible-headers))
+        (invisible-headers mh-invisible-header-fields-compiled)
+        (visible-headers nil))
     (save-excursion
       (save-restriction
         (narrow-to-region b b)
index a888f02..b92a98f 100644 (file)
@@ -1,6 +1,6 @@
 ;;; mh-pick.el --- make a search pattern and search for a message in MH-E
 
-;; Copyright (C) 1993, 1995, 2001, 2003 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1995, 2001, 2003, 2004 Free Software Foundation, Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
@@ -32,6 +32,8 @@
 
 ;;; Code:
 
+(eval-when-compile (require 'mh-acros))
+(mh-require-cl)
 (require 'mh-e)
 (require 'easymenu)
 (require 'gnus-util)
@@ -44,6 +46,9 @@
 (defvar mh-searching-folder nil)        ;Folder this pick is searching.
 (defvar mh-searching-function nil)
 
+(defconst mh-pick-single-dash  '(cc date from subject to)
+  "Search components that are supported by single-dash option in pick.")
+
 ;;;###mh-autoload
 (defun mh-search-folder (folder window-config)
   "Search FOLDER for messages matching a pattern.
@@ -138,16 +143,6 @@ with no arguments, upon entry to this mode.
   (setq mh-help-messages mh-pick-mode-help-messages)
   (run-hooks 'mh-pick-mode-hook))
 
-;;;###mh-autoload
-(defun mh-do-pick-search ()
-  "Find messages that match the qualifications in the current pattern buffer.
-Messages are searched for in the folder named in `mh-searching-folder'.
-Add the messages found to the sequence named `search'.
-
-This is a deprecated function and `mh-pick-do-search' should be used instead."
-  (interactive)
-  (mh-pick-do-search))
-
 ;;;###mh-autoload
 (defun mh-pick-do-search ()
   "Find messages that match the qualifications in the current pattern buffer.
@@ -260,6 +255,13 @@ COMPONENT is the component to search."
            "-rbrace"))
         (t (error "Unknown operator '%s' seen" (car expr)))))
 
+;; All implementations of pick have special options -cc, -date, -from and
+;; -subject that allow to search for corresponding components. Any other
+;; component is searched using option --COMPNAME, for example: `pick
+;; --x-mailer mh-e'. Mailutils `pick' supports this option using a certain
+;; kludge, but it prefers the following syntax for this purpose:
+;; `--component=COMPNAME --pattern=PATTERN'.
+;;                                           -- Sergey Poznyakoff, Aug 2003
 (defun mh-pick-regexp-builder (pattern-list)
   "Generate pick search expression from PATTERN-LIST."
   (let ((result ()))
@@ -267,9 +269,18 @@ COMPONENT is the component to search."
       (when (cdr pattern)
         (setq result `(,@result "-and" "-lbrace"
                        ,@(mh-pick-construct-regexp
-                          (cdr pattern) (if (car pattern)
-                                            (format "-%s" (car pattern))
-                                          "-search"))
+                          (if (and (mh-variant-p 'mu-mh) (car pattern))
+                              (format "--pattern=%s" (cdr pattern))
+                            (cdr pattern))
+                          (if (car pattern)
+                              (cond
+                               ((mh-variant-p 'mu-mh)
+                                (format "--component=%s" (car pattern)))
+                               ((member (car pattern) mh-pick-single-dash)
+                                (format "-%s" (car pattern)))
+                               (t
+                                (format "--%s" (car pattern))))
+                            "-search"))
                        "-rbrace"))))
     (cdr result)))
 
index 20950d3..8d2369e 100644 (file)
@@ -70,7 +70,7 @@
 
 ;;; Code:
 
-(require 'mh-utils)
+(eval-when-compile (require 'mh-acros))
 (mh-require-cl)
 (require 'mh-e)
 
 (defvar tool-bar-mode)
 
 ;;; Data structures (used in message threading)...
-(defstruct (mh-thread-message (:conc-name mh-message-)
-                              (:constructor mh-thread-make-message))
+(mh-defstruct (mh-thread-message (:conc-name mh-message-)
+                                 (:constructor mh-thread-make-message))
   (id nil)
   (references ())
   (subject "")
   (subject-re-p nil))
 
-(defstruct (mh-thread-container (:conc-name mh-container-)
-                                (:constructor mh-thread-make-container))
+(mh-defstruct (mh-thread-container (:conc-name mh-container-)
+                                   (:constructor mh-thread-make-container))
   message parent children
   (real-child-p t))
 
@@ -201,12 +201,15 @@ redone to get the new thread tree. This makes incremental threading easier.")
 
 ;;;###mh-autoload
 (defun mh-msg-is-in-seq (message)
-  "Display the sequences that contain MESSAGE.
-Default is the displayed message."
-  (interactive (list (mh-get-msg-num t)))
+  "Display the sequences in which the current message appears.
+Use a prefix argument to display the sequences in which another MESSAGE
+appears."
+  (interactive "P")
+  (if (not message)
+      (setq message (mh-get-msg-num t)))
   (let* ((dest-folder (loop for seq in mh-refile-list
-                            until (member message (cdr seq))
-                            finally return (car seq)))
+                            when (member message (cdr seq)) return (car seq)
+                            finally return nil))
          (deleted-flag (unless dest-folder (member message mh-delete-list))))
     (message "Message %d%s is in sequences: %s"
              message
@@ -269,12 +272,11 @@ interactive use."
   (let* ((internal-seq-flag (mh-internal-seq sequence))
          (original-msgs (mh-seq-msgs (mh-find-seq sequence)))
          (folders (list mh-current-folder))
-         (msg-list ()))
+         (msg-list (mh-range-to-msg-list range)))
+    (mh-add-msgs-to-seq msg-list sequence nil t)
     (mh-iterate-on-range m range
-      (push m msg-list)
       (unless (memq m original-msgs)
         (mh-add-sequence-notation m internal-seq-flag)))
-    (mh-add-msgs-to-seq msg-list sequence nil t)
     (if (not internal-seq-flag)
         (setq mh-last-seq-used sequence))
     (when mh-index-data
@@ -292,10 +294,8 @@ OP is one of 'widen and 'unthread."
 
 ;;;###mh-autoload
 (defun mh-widen (&optional all-flag)
-  "Remove last restriction from current folder.
-If optional prefix argument ALL-FLAG is non-nil, then unwind to the beginning
-of the view stack thereby showing all messages that the buffer originally
-contained."
+  "Restore the previous limit.
+If optional prefix argument ALL-FLAG is non-nil, remove all limits."
   (interactive "P")
   (let ((msg (mh-get-msg-num nil)))
     (when mh-folder-view-stack
@@ -532,28 +532,6 @@ should be replaced with:
     (mh-undefine-sequence sequence (mh-seq-msgs old-seq))
     (rplaca old-seq new-name)))
 
-;;;###mh-autoload
-(defun mh-map-to-seq-msgs (func seq &rest args)
-  "Invoke the FUNC at each message in the SEQ.
-SEQ can either be a list of messages or a MH sequence. The remaining ARGS are
-passed as arguments to FUNC."
-  (save-excursion
-    (let ((msgs (if (listp seq) seq (mh-seq-to-msgs seq))))
-      (while msgs
-        (if (mh-goto-msg (car msgs) t t)
-            (apply func (car msgs) args))
-        (setq msgs (cdr msgs))))))
-
-;;;###mh-autoload
-(defun mh-notate-seq (seq notation offset)
-  "Mark the scan listing.
-All messages in SEQ are marked with NOTATION at OFFSET from the beginning of
-the line."
-  (let ((msg-list (mh-seq-to-msgs seq)))
-    (mh-iterate-on-messages-in-region msg (point-min) (point-max)
-      (when (member msg msg-list)
-        (mh-notate nil notation offset)))))
-
 ;;;###mh-autoload
 (defun mh-notate-cur ()
   "Mark the MH sequence cur.
@@ -577,14 +555,6 @@ uses `overlay-arrow-position' to put a marker in the fringe."
                  "-sequence" (symbol-name seq)
                  (mh-coalesce-msg-list msgs)))))
 
-;; This has a tricky bug. mh-map-to-seq-msgs uses mh-goto-msg, which assumes
-;; that the folder buffer is sorted. However in this case that assumption
-;; doesn't hold. So we will do this the dumb way.
-;(defun mh-copy-seq-to-point (seq location)
-;  ;; Copy the scan listing of the messages in SEQUENCE to after the point
-;  ;; LOCATION in the current buffer.
-;  (mh-map-to-seq-msgs 'mh-copy-line-to-point seq location))
-
 (defvar mh-thread-last-ancestor)
 
 (defun mh-copy-seq-to-eob (seq)
@@ -614,21 +584,6 @@ uses `overlay-arrow-position' to put a marker in the fringe."
               (mh-index-data
                (mh-index-insert-folder-headers)))))))
 
-(defun mh-copy-line-to-point (msg location)
-  "Copy current message line to a specific location.
-The argument MSG is not used. The message in the current line is copied to
-LOCATION."
-  ;; msg is not used?
-  ;; Copy the current line to the LOCATION in the current buffer.
-  (beginning-of-line)
-  (save-excursion
-    (let ((beginning-of-line (point))
-          end)
-      (forward-line 1)
-      (setq end (point))
-      (goto-char location)
-      (insert-buffer-substring (current-buffer) beginning-of-line end))))
-
 ;;;###mh-autoload
 (defmacro mh-iterate-on-messages-in-region (var begin end &rest body)
   "Iterate over region.
@@ -702,7 +657,7 @@ a region in a cons cell."
     (nreverse msg-list)))
 
 ;;;###mh-autoload
-(defun mh-interactive-range (range-prompt)
+(defun mh-interactive-range (range-prompt &optional default)
   "Return interactive specification for message, sequence, range or region.
 By convention, the name of this argument is RANGE.
 
@@ -715,24 +670,17 @@ RANGE-PROMPT. A list of messages in that range is returned.
 If a MH range is given, say something like last:20, then a list containing
 the messages in that range is returned.
 
+If DEFAULT non-nil then it is returned.
+
 Otherwise, the message number at point is returned.
 
 This function is usually used with `mh-iterate-on-range' in order to provide
 a uniform interface to MH-E functions."
   (cond ((mh-mark-active-p t) (cons (region-beginning) (region-end)))
         (current-prefix-arg (mh-read-range range-prompt nil nil t t))
+        (default default)
         (t (mh-get-msg-num t))))
 
-;;;###mh-autoload
-(defun mh-region-to-msg-list (begin end)
-  "Return a list of messages within the region between BEGIN and END."
-  ;; If end is end of buffer back up one position
-  (setq end (if (equal end (point-max)) (1- end) end))
-  (let ((result))
-    (mh-iterate-on-messages-in-region index begin end
-      (when (numberp index) (push index result)))
-    result))
-
 \f
 
 ;;; Commands to handle new 'subject sequence.
@@ -772,7 +720,7 @@ Return number of messages put in the sequence:
     (if (or (not (looking-at mh-scan-subject-regexp))
             (not (match-string 3))
             (string-equal "" (match-string 3)))
-        (progn (message "No subject line.")
+        (progn (message "No subject line")
                nil)
       (let ((subject (match-string-no-properties 3))
             (list))
@@ -835,61 +783,57 @@ This function can only be used the folder is threaded."
      (mh-container-message (gethash (gethash msg mh-thread-index-id-map)
                                     mh-thread-id-table)))))
 
-;;;###mh-autoload
-(defun mh-narrow-to-subject ()
-  "Narrow to a sequence containing all following messages with same subject."
-  (interactive)
-  (let ((num (mh-get-msg-num nil))
-        (count (mh-subject-to-sequence t)))
-    (cond
-     ((not count)                       ; No subject line, delete msg anyway
-      nil)
-     ((= 0 count)                       ; No other msgs, delete msg anyway.
-      (message "No other messages with same Subject following this one.")
-      nil)
-     (t                                 ; We have a subject sequence.
-      (message "Found %d messages for subject sequence." count)
-      (mh-narrow-to-seq 'subject)
-      (if (numberp num)
-          (mh-goto-msg num t t))))))
-
-(defun mh-read-pick-regexp (default)
-  "With prefix arg read a pick regexp.
+(defun mh-edit-pick-expr (default)
+  "With prefix arg edit a pick expression.
 If no prefix arg is given, then return DEFAULT."
   (let ((default-string (loop for x in default concat (format " %s" x))))
     (if (or current-prefix-arg (equal default-string ""))
-        (delete "" (split-string (read-string "Pick regexp: " default-string)))
+        (delete "" (split-string (read-string "Pick expression: "
+                                              default-string)))
       default)))
 
 ;;;###mh-autoload
-(defun mh-narrow-to-from (&optional regexp)
-  "Limit to messages with the same From header field as the message at point.
-With a prefix argument, prompt for the regular expression, REGEXP given to
-pick."
+(defun mh-narrow-to-subject (&optional pick-expr)
+  "Limit to messages with same subject.
+With a prefix argument, edit PICK-EXPR.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
   (interactive
-   (list (mh-read-pick-regexp (mh-current-message-header-field 'from))))
-  (mh-narrow-to-header-field 'from regexp))
+   (list (mh-edit-pick-expr (mh-current-message-header-field 'subject))))
+  (mh-narrow-to-header-field 'subject pick-expr))
 
 ;;;###mh-autoload
-(defun mh-narrow-to-cc (&optional regexp)
-  "Limit to messages with the same Cc header field as the message at point.
-With a prefix argument, prompt for the regular expression, REGEXP given to
-pick."
+(defun mh-narrow-to-from (&optional pick-expr)
+  "Limit to messages with the same `From:' field.
+With a prefix argument, edit PICK-EXPR.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
   (interactive
-   (list (mh-read-pick-regexp (mh-current-message-header-field 'cc))))
-  (mh-narrow-to-header-field 'cc regexp))
+   (list (mh-edit-pick-expr (mh-current-message-header-field 'from))))
+  (mh-narrow-to-header-field 'from pick-expr))
 
 ;;;###mh-autoload
-(defun mh-narrow-to-to (&optional regexp)
-  "Limit to messages with the same To header field as the message at point.
-With a prefix argument, prompt for the regular expression, REGEXP given to
-pick."
+(defun mh-narrow-to-cc (&optional pick-expr)
+  "Limit to messages with the same `Cc:' field.
+With a prefix argument, edit PICK-EXPR.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
   (interactive
-   (list (mh-read-pick-regexp (mh-current-message-header-field 'to))))
-  (mh-narrow-to-header-field 'to regexp))
+   (list (mh-edit-pick-expr (mh-current-message-header-field 'cc))))
+  (mh-narrow-to-header-field 'cc pick-expr))
 
-(defun mh-narrow-to-header-field (header-field regexp)
-  "Limit to messages whose HEADER-FIELD match REGEXP.
+;;;###mh-autoload
+(defun mh-narrow-to-to (&optional pick-expr)
+  "Limit to messages with the same `To:' field.
+With a prefix argument, edit PICK-EXPR.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
+  (interactive
+   (list (mh-edit-pick-expr (mh-current-message-header-field 'to))))
+  (mh-narrow-to-header-field 'to pick-expr))
+
+(defun mh-narrow-to-header-field (header-field pick-expr)
+  "Limit to messages whose HEADER-FIELD match PICK-EXPR.
 The MH command pick is used to do the match."
   (let ((folder mh-current-folder)
         (original (mh-coalesce-msg-list
@@ -897,7 +841,7 @@ The MH command pick is used to do the match."
         (msg-list ()))
     (with-temp-buffer
       (apply #'mh-exec-cmd-output "pick" nil folder
-             (append original (list "-list") regexp))
+             (append original (list "-list") pick-expr))
       (goto-char (point-min))
       (while (not (eobp))
         (let ((num (read-from-string
@@ -939,7 +883,9 @@ The MH command pick is used to do the match."
   "Limit to messages in RANGE.
 
 Check the documentation of `mh-interactive-range' to see how RANGE is read in
-interactive use."
+interactive use.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
   (interactive (list (mh-interactive-range "Narrow to")))
   (when (assoc 'range mh-seq-list) (mh-delete-seq 'range))
   (mh-add-msgs-to-seq (mh-range-to-msg-list range) 'range)
@@ -958,7 +904,7 @@ subject sequence."
      ((not count)                       ; No subject line, delete msg anyway
       (mh-delete-msg (mh-get-msg-num t)))
      ((= 0 count)                       ; No other msgs, delete msg anyway.
-      (message "No other messages with same Subject following this one.")
+      (message "No other messages with same Subject following this one")
       (mh-delete-msg (mh-get-msg-num t)))
      (t                                 ; We have a subject sequence.
       (message "Marked %d messages for deletion" count)
@@ -1078,13 +1024,12 @@ SUBJECT and REFS fields."
            message)
           (container
            (setf (mh-container-message container)
-                 (mh-thread-make-message :subject subject
-                                         :subject-re-p subject-re-p
-                                         :id id :references refs)))
-          (t (let ((message (mh-thread-make-message
-                             :subject subject
-                             :subject-re-p subject-re-p
-                             :id id :references refs)))
+                 (mh-thread-make-message :id id :references refs
+                                         :subject subject
+                                         :subject-re-p subject-re-p)))
+          (t (let ((message (mh-thread-make-message :id id :references refs
+                                                    :subject-re-p subject-re-p
+                                                    :subject subject)))
                (prog1 message
                  (mh-thread-get-message-container message)))))))
 
@@ -1450,8 +1395,7 @@ MSG is the message being notated with NOTATION at OFFSET."
          (cur-scan-line (and mh-thread-scan-line-map
                              (gethash msg mh-thread-scan-line-map)))
          (old-scan-lines (loop for map in mh-thread-scan-line-map-stack
-                               collect (and map (gethash msg map))))
-         (notation (if (stringp notation) (aref notation 0) notation)))
+                               collect (and map (gethash msg map)))))
     (when cur-scan-line
       (setf (aref (car cur-scan-line) offset) notation))
     (dolist (line old-scan-lines)
@@ -1486,7 +1430,8 @@ MSG is the message being notated with NOTATION at OFFSET."
                               (setf (gethash msg mh-thread-scan-line-map) v))))
                  (when (> (hash-table-count mh-thread-scan-line-map) 0)
                    (insert (if (bobp) "" "\n") (car x) "\n")
-                   (mh-thread-generate-scan-lines thread-tree -2)))))))
+                   (mh-thread-generate-scan-lines thread-tree -2))))
+      (mh-index-create-imenu-index))))
 
 (defun mh-thread-folder ()
   "Generate thread view of folder."
@@ -1711,11 +1656,12 @@ start of the region and the second is the point at the end."
              (push msg unticked)
              (setcdr tick-seq (delq msg (cdr tick-seq)))
              (when (null (cdr tick-seq)) (setq mh-last-seq-used nil))
-             (mh-remove-sequence-notation msg t))
+             (mh-remove-sequence-notation msg (mh-colors-in-use-p)))
             (t
              (push msg ticked)
              (setq mh-last-seq-used mh-tick-seq)
-             (mh-add-sequence-notation msg t))))
+             (let ((mh-seq-list (cons `(,mh-tick-seq ,msg) mh-seq-list)))
+               (mh-add-sequence-notation msg (mh-colors-in-use-p))))))
     (mh-add-msgs-to-seq ticked mh-tick-seq nil t)
     (mh-undefine-sequence mh-tick-seq unticked)
     (when mh-index-data
@@ -1724,16 +1670,16 @@ start of the region and the second is the point at the end."
 
 ;;;###mh-autoload
 (defun mh-narrow-to-tick ()
-  "Restrict display of this folder to just messages in `mh-tick-seq'.
+  "Limit to messages in `mh-tick-seq'.
+
 Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
   (interactive)
   (cond ((not mh-tick-seq)
          (error "Enable ticking by customizing `mh-tick-seq'"))
         ((null (mh-seq-msgs (mh-find-seq mh-tick-seq)))
-         (message "No messages in tick sequence"))
+         (message "No messages in %s sequence" mh-tick-seq))
         (t (mh-narrow-to-seq mh-tick-seq))))
 
-
 (provide 'mh-seq)
 
 ;;; Local Variables:
index 967984d..2617a94 100644 (file)
 ;;; Code:
 
 ;; Requires
-(require 'mh-utils)
+(eval-when-compile (require 'mh-acros))
 (mh-require-cl)
 (require 'mh-e)
 (require 'speedbar)
+(require 'timer)
 
 ;; Global variables
 (defvar mh-speed-refresh-flag nil)
@@ -90,26 +91,25 @@ BUFFER is the MH-E buffer for which the speedbar buffer is to be created."
   "+"           mh-speed-expand-folder
   "-"           mh-speed-contract-folder
   "\r"          mh-speed-view
-  "f"           mh-speed-flists
-  "i"           mh-speed-invalidate-map)
+  "r"           mh-speed-refresh)
 
 (defvar mh-show-speedbar-key-map mh-folder-speedbar-key-map)
 (defvar mh-letter-speedbar-key-map mh-folder-speedbar-key-map)
 
 ;; Menus for speedbar...
 (defvar mh-folder-speedbar-menu-items
-  '(["Visit Folder" mh-speed-view
+  '("--"
+    ["Visit Folder" mh-speed-view
      (save-excursion
        (set-buffer speedbar-buffer)
        (get-text-property (line-beginning-position) 'mh-folder))]
-    ["Expand nested folders" mh-speed-expand-folder
+    ["Expand Nested Folders" mh-speed-expand-folder
      (and (get-text-property (line-beginning-position) 'mh-children-p)
           (not (get-text-property (line-beginning-position) 'mh-expanded)))]
-    ["Contract nested folders" mh-speed-contract-folder
+    ["Contract Nested Folders" mh-speed-contract-folder
      (and (get-text-property (line-beginning-position) 'mh-children-p)
           (get-text-property (line-beginning-position) 'mh-expanded))]
-    ["Run Flists" mh-speed-flists t]
-    ["Invalidate cached folders" mh-speed-invalidate-map t])
+    ["Refresh Speedbar" mh-speed-refresh t])
   "Extra menu items for speedbar.")
 
 (defvar mh-show-speedbar-menu-items mh-folder-speedbar-menu-items)
@@ -352,6 +352,14 @@ Optional ARGS are ignored."
 (defvar mh-speed-current-folder nil)
 (defvar mh-speed-flists-folder nil)
 
+(defmacro mh-process-kill-without-query (process)
+  "PROCESS can be killed without query on Emacs exit.
+Avoid using `process-kill-without-query' if possible since it is now
+obsolete."
+  (if (fboundp 'set-process-query-on-exit-flag)
+      `(set-process-query-on-exit-flag ,process nil)
+    `(process-kill-without-query ,process)))
+
 ;;;###mh-autoload
 (defun mh-speed-flists (force &rest folders)
   "Execute flists -recurse and update message counts.
@@ -396,6 +404,7 @@ only for that one folder."
                             (or mh-speed-flists-folder '("-recurse"))))
                ;; Run flists on all folders the next time around...
                (setq mh-speed-flists-folder nil)
+               (mh-process-kill-without-query mh-speed-flists-process)
                (set-process-filter mh-speed-flists-process
                                    'mh-speed-parse-flists-output)))))))
 
@@ -494,6 +503,14 @@ next."
       (when (equal folder "")
         (clrhash mh-sub-folders-cache)))))
 
+(defun mh-speed-refresh ()
+  "Refresh the speedbar.
+Use this function to refresh the speedbar if folders have been added or
+deleted or message ranges have been updated outside of MH-E."
+  (interactive)
+  (mh-speed-flists t)
+  (mh-speed-invalidate-map ""))
+
 ;;;###mh-autoload
 (defun mh-speed-add-folder (folder)
   "Add FOLDER since it is being created.
index b196691..a57567a 100644 (file)
 
 ;;; Code:
 
-;; Is this XEmacs-land? Located here since needed by mh-customize.el.
-(defvar mh-xemacs-flag (featurep 'xemacs)
-  "Non-nil means the current Emacs is XEmacs.")
-
-;; The Emacs coding conventions require that the cl package not be required at
-;; runtime. However, the cl package in versions of Emacs prior to 21.4 left cl
-;; routines in their macro expansions. Use mh-require-cl to provide the cl
-;; routines in the best way possible.
-(eval-when-compile (require 'cl))
-(defmacro mh-require-cl ()
-  (if (eq (car (macroexpand '(setf (gethash foo bar) baz))) 'cl-puthash)
-      `(require 'cl)
-    `(eval-when-compile (require 'cl))))
+(defvar recursive-load-depth-limit)
+(eval-and-compile
+  (if (and (boundp 'recursive-load-depth-limit)
+           (integerp recursive-load-depth-limit)
+           (> 50 recursive-load-depth-limit))
+      (setq recursive-load-depth-limit 50)))
 
+(eval-when-compile (require 'mh-acros))
 (mh-require-cl)
 (require 'gnus-util)
 (require 'font-lock)
@@ -58,6 +52,7 @@
 
 (load "mm-decode" t t)                  ; Non-fatal dependency
 (load "mm-view" t t)                    ; Non-fatal dependency
+(load "vcard" t t)                      ; Non-fatal dependency
 (load "hl-line" t t)                    ; Non-fatal dependency
 (load "executable" t t)                 ; Non-fatal dependency on
                                         ; executable-find
 
 ;;; Autoloads
 (autoload 'gnus-article-highlight-citation "gnus-cite")
+(autoload 'message-fetch-field "message")
+(autoload 'message-tokenize-header "message")
 (require 'sendmail)
-(autoload 'Info-goto-node "info")
 (unless (fboundp 'make-hash-table)
   (autoload 'make-hash-table "cl"))
 
-;;; Set for local environment:
-;;; mh-progs and mh-lib used to be set in paths.el, which tried to
-;;; figure out at build time which of several possible directories MH
-;;; was installed into.  But if you installed MH after building Emacs,
-;;; this would almost certainly be wrong, so now we do it at run time.
-
-(defvar mh-progs nil
-  "Directory containing MH commands, such as inc, repl, and rmm.")
-
-(defvar mh-lib nil
-  "Directory containing the MH library.
-This directory contains, among other things, the components file.")
-
-(defvar mh-lib-progs nil
-  "Directory containing MH helper programs.
-This directory contains, among other things, the mhl program.")
-
-(defvar mh-nmh-flag nil
-  "Non-nil means nmh is installed on this system instead of MH.")
-
-(defvar mh-flists-present-flag nil
-  "Non-nil means that we have `flists'.")
-
-;;;###autoload
-(put 'mh-progs 'risky-local-variable t)
-;;;###autoload
-(put 'mh-lib 'risky-local-variable t)
-;;;###autoload
-(put 'mh-lib-progs 'risky-local-variable t)
-;;;###autoload
-(put 'mh-nmh-flag 'risky-local-variable t)
-
 ;;; CL Replacements
 (defun mh-search-from-end (char string)
   "Return the position of last occurrence of CHAR in STRING.
@@ -115,92 +79,52 @@ of `search' in the CL package."
         when (equal (aref string index) char) return index
         finally return nil))
 
-;;; Macros to generate correct code for different emacs variants
-
-(defmacro mh-do-in-gnu-emacs (&rest body)
-  "Execute BODY if in GNU Emacs."
-  (unless mh-xemacs-flag `(progn ,@body)))
-(put 'mh-do-in-gnu-emacs 'lisp-indent-hook 'defun)
-
-(defmacro mh-do-in-xemacs (&rest body)
-  "Execute BODY if in GNU Emacs."
-  (when mh-xemacs-flag `(progn ,@body)))
-(put 'mh-do-in-xemacs 'lisp-indent-hook 'defun)
-
-(defmacro mh-funcall-if-exists (function &rest args)
-  "Call FUNCTION with ARGS as parameters if it exists."
-  (if (fboundp function)
-      `(funcall ',function ,@args)))
-
-(defmacro mh-make-local-hook (hook)
-  "Make HOOK local if needed.
-XEmacs and versions of GNU Emacs before 21.1 require `make-local-hook' to be
-called."
-  (when (and (fboundp 'make-local-hook)
-             (not (get 'make-local-hook 'byte-obsolete-info)))
-    `(make-local-hook ,hook)))
-
-(defmacro mh-mark-active-p (check-transient-mark-mode-flag)
-  "A macro that expands into appropriate code in XEmacs and nil in GNU Emacs.
-In GNU Emacs if CHECK-TRANSIENT-MARK-MODE-FLAG is non-nil then check if
-variable `transient-mark-mode' is active."
-  (cond (mh-xemacs-flag                 ;XEmacs
-         `(and (boundp 'zmacs-regions) zmacs-regions (region-active-p)))
-        ((not check-transient-mark-mode-flag) ;GNU Emacs
-         `(and (boundp 'mark-active) mark-active))
-        (t                              ;GNU Emacs
-         `(and (boundp 'transient-mark-mode) transient-mark-mode
-               (boundp 'mark-active) mark-active))))
-
 ;;; Additional header fields that might someday be added:
 ;;; "Sender: " "Reply-to: "
 
+\f
+;;; Scan Line Formats
+
 (defvar mh-scan-msg-number-regexp "^ *\\([0-9]+\\)"
-  "Regexp to find the number of a message in a scan line.
-The message's number must be surrounded with \\( \\)")
+  "This regexp is used to extract the message number from a scan line.
+Note that the message number must be placed in a parenthesized expression as
+in the default of \"^ *\\\\([0-9]+\\\\)\".")
 
 (defvar mh-scan-msg-overflow-regexp "^[?0-9][0-9]"
-  "Regexp to find a scan line in which the message number overflowed.
-The message's number is left truncated in this case.")
+  "This regexp matches scan lines in which the message number overflowed.")
 
 (defvar mh-scan-msg-format-regexp "%\\([0-9]*\\)(msg)"
-  "Regexp to find message number width in an scan format.
-The message number width must be surrounded with \\( \\).")
+  "This regexp is used to find the message number width in a scan format.
+Note that the message number must be placed in a parenthesized expression as
+in the default of \"%\\\\([0-9]*\\\\)(msg)\".")
 
 (defvar mh-scan-msg-format-string "%d"
-  "Format string for width of the message number in a scan format.
+  "This is a format string for width of the message number in a scan format.
 Use `0%d' for zero-filled message numbers.")
 
 (defvar mh-scan-msg-search-regexp "^[^0-9]*%d[^0-9]"
-  "Format string containing a regexp matching the scan listing for a message.
-The desired message's number will be an argument to format.")
-
-(defvar mh-default-folder-for-message-function nil
-  "Function to select a default folder for refiling or Fcc.
-If set to a function, that function is called with no arguments by
-`\\[mh-refile-msg]' and `\\[mh-to-fcc]' to get a default when
-prompting the user for a folder.  The function is called from within a
-`save-excursion', with point at the start of the message.  It should
-return the folder to offer as the refile or Fcc folder, as a string
-with a leading `+' sign.  It can also return an empty string to use no
-default, or nil to calculate the default the usual way.
-NOTE: This variable is not an ordinary hook;
-It may not be a list of functions.")
+  "This format string regexp matches the scan line for a particular message.
+Use `%d' to represent the location of the message number within the
+expression as in the default of \"^[^0-9]*%d[^0-9]\".")
+
+(defvar mh-cmd-note 4
+  "This is the number of characters to skip over before inserting notation.
+This variable should be set with the function `mh-set-cmd-note'. This variable
+may be updated dynamically if `mh-adaptive-cmd-note-flag' is non-nil and
+`mh-scan-format-file' is t.")
+(make-variable-buffer-local 'mh-cmd-note)
+
+(defvar mh-note-seq ?%
+  "Messages in a user-defined sequence are marked by this character.
+Messages in the `search' sequence are marked by this character as well.")
+
+\f
 
 (defvar mh-show-buffer-mode-line-buffer-id "    {show-%s} %d"
   "Format string to produce `mode-line-buffer-identification' for show buffers.
 First argument is folder name.  Second is message number.")
 
-(defvar mh-cmd-note 4
-  "Column to insert notation.
-Use `mh-set-cmd-note' to modify it.
-This value may be dynamically updated if `mh-adaptive-cmd-note-flag' is
-non-nil and `mh-scan-format-file' is t.
-Note that the first column is column number 0.")
-(make-variable-buffer-local 'mh-cmd-note)
-
-(defvar mh-note-seq "%"
-  "String whose first character is used to notate messages in a sequence.")
+\f
 
 (defvar mh-mail-header-separator "--------"
   "*Line used by MH to separate headers from text in messages being composed.
@@ -213,11 +137,29 @@ Do not make this a regexp as it may be the argument to `insert' and it is
 passed through `regexp-quote' before being used by functions like
 `re-search-forward'.")
 
+(defvar mh-signature-separator-regexp "^-- $"
+  "Regexp used to find signature separator.
+See `mh-signature-separator'.")
+
+(defvar mh-signature-separator "-- \n"
+  "Text of a signature separator.
+A signature separator is used to separate the body of a message from the
+signature. This can be used by user agents such as MH-E to render the
+signature differently or to suppress the inclusion of the signature in a
+reply.
+Use `mh-signature-separator-regexp' when searching for a separator.")
+
+(defun mh-signature-separator-p ()
+  "Return non-nil if buffer includes \"^-- $\"."
+  (save-excursion
+    (goto-char (point-min))
+    (re-search-forward mh-signature-separator-regexp nil t)))
+
 ;; Variables for MIME display
 
 ;; Structure to keep track of MIME handles on a per buffer basis.
-(defstruct (mh-buffer-data (:conc-name mh-mime-)
-                           (:constructor mh-make-buffer-data))
+(mh-defstruct (mh-buffer-data (:conc-name mh-mime-)
+                              (:constructor mh-make-buffer-data))
   (handles ())                          ; List of MIME handles
   (handles-cache (make-hash-table))     ; Cache to avoid multiple decodes of
                                         ; nested messages
@@ -331,7 +273,7 @@ passed through `regexp-quote' before being used by functions like
   "A regular expression probably matching an e-mail address.")
 
 ;; From goto-addr.el, which we don't want to force-load on users.
-;;;###mh-autoload
+
 (defun mh-goto-address-find-address-at-point ()
   "Find e-mail address around or before point.
 Then search backwards to beginning of line for the start of an e-mail
@@ -348,7 +290,18 @@ address.  If no e-mail address found, return nil."
 In MH-E we frequently need to find the end of headers in nested messages, where
 the buffer has been narrowed. This function works in this situation."
   (save-excursion
-    (rfc822-goto-eoh)
+    ;; XXX: The following replaces a call to rfc822-goto-eoh. Occasionally,
+    ;; mail headers that MH-E has to read contains lines of the form:
+    ;;    From xxx@yyy Mon May 10 11:48:07 2004
+    ;; In this situation, rfc822-goto-eoh doesn't go to the end of the
+    ;; header. The replacement allows From_ lines in the mail header.
+    (goto-char (point-min))
+    (loop for p = (re-search-forward
+                   "^\\([:\n]\\|[^: \t\n]+[ \t\n]\\)" nil 'move)
+          do (cond ((null p) (return))
+                   (t (goto-char (match-beginning 0))
+                      (unless (looking-at "From ") (return))
+                      (goto-char p))))
     (point)))
 
 (defun mh-in-header-p ()
@@ -528,17 +481,20 @@ message about the fontification operation."
 ;; hidden and can be programmatically removed in mh-quit), and the variable
 ;; names have the form mh-temp-.*-buffer.
 (defconst mh-temp-buffer " *mh-temp*")  ;scratch
+(defconst mh-temp-fetch-buffer " *mh-fetch*")  ;wget/curl/fetch output
 
 ;; The names of MH-E buffers that are not ephemeral and can be used by the
 ;; user (and deleted by the user when no longer needed) have a "*MH-E " prefix
 ;; (so they can be programmatically removed in mh-quit), and the variable
 ;; names have the form mh-.*-buffer.
+(defconst mh-aliases-buffer "*MH-E Aliases*") ;alias lookups
 (defconst mh-folders-buffer "*MH-E Folders*") ;folder list
+(defconst mh-help-buffer "*MH-E Help*") ;quick help
 (defconst mh-info-buffer "*MH-E Info*") ;version information buffer
 (defconst mh-log-buffer "*MH-E Log*") ;output of MH commands and so on
+(defconst mh-mail-delivery-buffer "*MH-E Mail Delivery*") ;mail delivery log
 (defconst mh-recipients-buffer "*MH-E Recipients*") ;killed when draft sent
 (defconst mh-sequences-buffer "*MH-E Sequences*") ;sequences list
-(defconst mh-mail-delivery-buffer "*MH-E Mail Delivery*") ;mail delivery log
 
 ;; Number of lines to keep in mh-log-buffer.
 (defvar mh-log-buffer-lines 100)
@@ -593,7 +549,6 @@ message about the fontification operation."
             (cons modeline-buffer-id-left-extent "XEmacs%N:"))
           (cons modeline-buffer-id-right-extent " %17b")))))
 
-
 ;;; This holds a documentation string used by describe-mode.
 (defun mh-showing-mode (&optional arg)
   "Change whether messages should be displayed.
@@ -614,7 +569,6 @@ With arg, display messages iff ARG is positive."
 ;; Showing message with headers or normally.
 (defvar mh-showing-with-headers nil)
 
-
 ;;; MH-E macros
 
 (defmacro with-mh-folder-updating (save-modification-flag &rest body)
@@ -742,7 +696,7 @@ of the buffer in the event window is preserved."
   (unlock-buffer)
   (setq buffer-file-name nil))
 
-;;;###mh-autoload
+
 (defun mh-get-msg-num (error-if-no-message)
   "Return the message number of the displayed message.
 If the argument ERROR-IF-NO-MESSAGE is non-nil, then complain if the cursor is
@@ -915,6 +869,16 @@ still visible.\n")
 (mh-defun-show-buffer mh-show-index-ticked-messages mh-index-ticked-messages)
 (mh-defun-show-buffer mh-show-index-sequenced-messages
                       mh-index-sequenced-messages)
+(mh-defun-show-buffer mh-show-catchup mh-catchup)
+(mh-defun-show-buffer mh-show-ps-print-toggle-mime mh-ps-print-toggle-mime)
+(mh-defun-show-buffer mh-show-ps-print-toggle-color mh-ps-print-toggle-color)
+(mh-defun-show-buffer mh-show-ps-print-toggle-faces mh-ps-print-toggle-faces)
+(mh-defun-show-buffer mh-show-ps-print-msg-file mh-ps-print-msg-file)
+(mh-defun-show-buffer mh-show-ps-print-msg mh-ps-print-msg)
+(mh-defun-show-buffer mh-show-ps-print-msg-show mh-ps-print-msg-show)
+(mh-defun-show-buffer mh-show-toggle-mime-buttons mh-toggle-mime-buttons)
+(mh-defun-show-buffer mh-show-display-with-external-viewer
+                      mh-display-with-external-viewer)
 
 ;;; Populate mh-show-mode-map
 (gnus-define-keys mh-show-mode-map
@@ -941,7 +905,6 @@ still visible.\n")
   "g"    mh-show-goto-msg
   "i"    mh-show-inc-folder
   "k"    mh-show-delete-subject-or-thread
-  "l"    mh-show-print-msg
   "m"    mh-show-send
   "n"    mh-show-next-undeleted-msg
   "\M-n" mh-show-next-unread-msg
@@ -961,6 +924,7 @@ still visible.\n")
   "?"    mh-prefix-help
   "'"    mh-index-ticked-messages
   "S"    mh-show-sort-folder
+  "c"    mh-show-catchup
   "f"    mh-show-visit-folder
   "i"    mh-index-search
   "k"    mh-show-kill-folder
@@ -992,6 +956,17 @@ still visible.\n")
   "b"    mh-show-junk-blacklist
   "w"    mh-show-junk-whitelist)
 
+(gnus-define-keys (mh-show-ps-print-map "P" mh-show-mode-map)
+  "?"  mh-prefix-help
+  "A"  mh-show-ps-print-toggle-mime
+  "C"  mh-show-ps-print-toggle-color
+  "F"  mh-show-ps-print-toggle-faces
+  "M"  mh-show-ps-print-toggle-mime
+  "f"  mh-show-ps-print-msg-file
+  "l"   mh-show-print-msg
+  "p"  mh-show-ps-print-msg
+  "s"  mh-show-ps-print-msg-show)
+
 (gnus-define-keys (mh-show-thread-map "T" mh-show-mode-map)
   "?"    mh-prefix-help
   "u"    mh-show-thread-ancestor
@@ -1026,9 +1001,11 @@ still visible.\n")
 (gnus-define-keys (mh-show-mime-map "K" mh-show-mode-map)
   "?"           mh-prefix-help
   "a"           mh-mime-save-parts
+  "e"           mh-show-display-with-external-viewer
   "v"           mh-show-toggle-mime-part
   "o"           mh-show-save-mime-part
   "i"           mh-show-inline-mime-part
+  "t"           mh-show-toggle-mime-buttons
   "\t"          mh-show-next-button
   [backtab]     mh-show-prev-button
   "\M-\t"       mh-show-prev-button)
@@ -1115,7 +1092,10 @@ still visible.\n")
 (define-derived-mode mh-show-mode text-mode "MH-Show"
   "Major mode for showing messages in MH-E.\\<mh-show-mode-map>
 The value of `mh-show-mode-hook' is a list of functions to
-be called, with no arguments, upon entry to this mode."
+be called, with no arguments, upon entry to this mode.
+See also `mh-folder-mode'.
+
+\\{mh-show-mode-map}"
   (set (make-local-variable 'mail-header-separator) mh-mail-header-separator)
   (setq paragraph-start (default-value 'paragraph-start))
   (mh-show-unquote-From)
@@ -1210,8 +1190,9 @@ be called, with no arguments, upon entry to this mode."
 (mh-do-in-xemacs (defvar default-enable-multibyte-characters))
 
 (defun mh-face-display-function ()
-  "Display a Face or X-Face header field.
-Display Face if both are present."
+  "Display a Face, X-Face, or X-Image-URL header field.
+If more than one of these are present, then the first one found in this order
+is used."
   (save-restriction
     (goto-char (point-min))
     (re-search-forward "\n\n" (point-max) t)
@@ -1226,7 +1207,8 @@ Display Face if both are present."
                         type 'png))
             (x-face (setq raw (mh-uncompface x-face)
                           type 'pbm))
-            (url (setq type 'url)))
+            (url (setq type 'url))
+            (t (multiple-value-setq (type raw) (mh-picon-get-image))))
       (when type
         (goto-char (point-min))
         (when (re-search-forward "^from:" (point-max) t)
@@ -1261,10 +1243,15 @@ Display Face if both are present."
              ((and (eq type 'pbm)
                    (fboundp 'x-face-xmas-wl-display-x-face)
                    (fboundp 'executable-find) (executable-find "uncompface"))
-              (mh-funcall-if-exists x-face-xmas-wl-display-x-face)))
+              (mh-funcall-if-exists x-face-xmas-wl-display-x-face))
+             ;; Picon display
+             ((and raw (member type '(xpm xbm gif)))
+              (when (featurep type)
+                (set-extent-begin-glyph
+                 (make-extent (point) (point))
+                 (make-glyph (vector type ':data raw))))))
             (when raw (insert " "))))))))
 
-
 (defun mh-show-xface ()
   "Display X-Face."
   (when (and window-system mh-show-use-xface-flag
@@ -1274,49 +1261,207 @@ Display Face if both are present."
 
 \f
 
+;; Picon display
+
+;;; XXX: This should be customizable. As a side-effect of setting this
+;;;   variable, arrange to reset mh-picon-existing-directory-list to 'unset.
+(defvar mh-picon-directory-list
+  '("~/.picons" "~/.picons/users" "~/.picons/usenix" "~/.picons/news"
+    "~/.picons/domains" "~/.picons/misc"
+    "/usr/share/picons/" "/usr/share/picons/users" "/usr/share/picons/usenix"
+    "/usr/share/picons/news" "/usr/share/picons/domains"
+    "/usr/share/picons/misc")
+  "List of directories where picons reside.
+The directories are searched for in the order they appear in the list.")
+
+(defvar mh-picon-existing-directory-list 'unset
+  "List of directories to search in.")
+
+(defvar mh-picon-cache (make-hash-table :test #'equal))
+
+(defvar mh-picon-image-types
+  (loop for type in '(xpm xbm gif)
+        when (or (mh-do-in-gnu-emacs
+                   (ignore-errors
+                     (mh-funcall-if-exists image-type-available-p type)))
+                 (mh-do-in-xemacs (featurep type)))
+        collect type))
+
+(defun mh-picon-set-directory-list ()
+  "Update `mh-picon-existing-directory-list' if needed."
+  (when (eq mh-picon-existing-directory-list 'unset)
+    (setq mh-picon-existing-directory-list
+          (loop for x in mh-picon-directory-list
+                when (file-directory-p x) collect x))))
+
+(defun* mh-picon-get-image ()
+  "Find the best possible match and return contents."
+  (mh-picon-set-directory-list)
+  (save-restriction
+    (let* ((from-field (ignore-errors (car (message-tokenize-header
+                                            (mh-get-header-field "from:")))))
+           (from (car (ignore-errors
+                        (mh-funcall-if-exists ietf-drums-parse-address
+                                              from-field))))
+           (host (and from
+                      (string-match "\\([^+]*\\)\\(+.*\\)?@\\(.*\\)" from)
+                      (downcase (match-string 3 from))))
+           (user (and host (downcase (match-string 1 from))))
+           (canonical-address (format "%s@%s" user host))
+           (cached-value (gethash canonical-address mh-picon-cache))
+           (host-list (and host (delete "" (split-string host "\\."))))
+           (match nil))
+      (cond (cached-value (return-from mh-picon-get-image cached-value))
+            ((not host-list) (return-from mh-picon-get-image nil)))
+      (setq match
+            (block 'loop
+              ;; u@h search
+              (loop for dir in mh-picon-existing-directory-list
+                    do (loop for type in mh-picon-image-types
+                             ;; [path]user@host
+                             for file1 = (format "%s/%s.%s"
+                                                 dir canonical-address type)
+                             when (file-exists-p file1)
+                             do (return-from 'loop file1)
+                             ;; [path]user
+                             for file2 = (format "%s/%s.%s" dir user type)
+                             when (file-exists-p file2)
+                             do (return-from 'loop file2)
+                             ;; [path]host
+                             for file3 = (format "%s/%s.%s" dir host type)
+                             when (file-exists-p file3)
+                             do (return-from 'loop file3)))
+              ;; facedb search
+              ;; Search order for user@foo.net:
+              ;;   [path]net/foo/user
+              ;;   [path]net/foo/user/face
+              ;;   [path]net/user
+              ;;   [path]net/user/face
+              ;;   [path]net/foo/unknown
+              ;;   [path]net/foo/unknown/face
+              ;;   [path]net/unknown
+              ;;   [path]net/unknown/face
+              (loop for u in (list user "unknown")
+                    do (loop for dir in mh-picon-existing-directory-list
+                             do (loop for x on host-list by #'cdr
+                                      for y = (mh-picon-generate-path x u dir)
+                                      do (loop for type in mh-picon-image-types
+                                               for z1 = (format "%s.%s" y type)
+                                               when (file-exists-p z1)
+                                               do (return-from 'loop z1)
+                                               for z2 = (format "%s/face.%s"
+                                                                y type)
+                                               when (file-exists-p z2)
+                                               do (return-from 'loop z2)))))))
+      (setf (gethash canonical-address mh-picon-cache)
+            (mh-picon-file-contents match)))))
+
+(defun mh-picon-file-contents (file)
+  "Return details about FILE.
+A list of consisting of a symbol for the type of the file and the file
+contents as a string is returned. If FILE is nil, then both elements of the
+list are nil."
+  (if (stringp file)
+      (with-temp-buffer
+        (let ((type (and (string-match ".*\\.\\(...\\)$" file)
+                         (intern (match-string 1 file)))))
+          (insert-file-contents-literally file)
+          (values type (buffer-string))))
+    (values nil nil)))
+
+(defun mh-picon-generate-path (host-list user directory)
+  "Generate the image file path.
+HOST-LIST is the parsed host address of the email address, USER the username
+and DIRECTORY is the directory relative to which the path is generated."
+  (loop with acc = ""
+        for elem in host-list
+        do (setq acc (format "%s/%s" elem acc))
+        finally return (format "%s/%s%s" directory acc user)))
+
+\f
+
 ;; X-Image-URL display
 
 (defvar mh-x-image-cache-directory nil
   "Directory where X-Image-URL images are cached.")
-
-(defvar mh-convert-executable (executable-find "convert"))
-(defvar mh-wget-executable (executable-find "wget"))
+(defvar mh-x-image-scaling-function
+  (cond ((executable-find "convert")
+         'mh-x-image-scale-with-convert)
+        ((and (executable-find "anytopnm") (executable-find "pnmscale")
+              (executable-find "pnmtopng"))
+         'mh-x-image-scale-with-pnm)
+        (t 'ignore))
+  "Function to use to scale image to proper size.")
+(defvar mh-wget-executable nil)
+(defvar mh-wget-choice
+  (or (and (setq mh-wget-executable (executable-find "wget")) 'wget)
+      (and (setq mh-wget-executable (executable-find "fetch")) 'fetch)
+      (and (setq mh-wget-executable (executable-find "curl")) 'curl)))
+(defvar mh-wget-option
+  (cdr (assoc mh-wget-choice '((curl . "-o") (fetch . "-o") (wget . "-O")))))
 (defvar mh-x-image-temp-file nil)
 (defvar mh-x-image-url nil)
 (defvar mh-x-image-marker nil)
 (defvar mh-x-image-url-cache-file nil)
 
+;; Functions to scale image to proper size
+(defun mh-x-image-scale-with-pnm (input output)
+  "Scale image in INPUT file and write to OUTPUT file using pnm tools."
+  (let ((res (shell-command-to-string
+              (format "anytopnm < %s | pnmscale -xysize 96 48 | pnmtopng > %s"
+                      input output))))
+    (unless (equal res "")
+      (delete-file output))))
+
+(defun mh-x-image-scale-with-convert (input output)
+  "Scale image in INPUT file and write to OUTPUT file using ImageMagick."
+  (call-process "convert" nil nil nil "-geometry" "96x48" input output))
+
 (defun mh-x-image-url-cache-canonicalize (url)
   "Canonicalize URL.
-Replace the ?/ character with a ?! character."
-  (with-temp-buffer
-    (insert url)
-    (goto-char (point-min))
-    (while (search-forward "/" nil t) (replace-match "!"))
-    (format "%s/%s.png" mh-x-image-cache-directory (buffer-string))))
+Replace the ?/ character with a ?! character and append .png."
+   (format "%s/%s.png" mh-x-image-cache-directory
+           (with-temp-buffer
+             (insert url)
+             (mh-replace-string "/" "!")
+             (buffer-string))))
+
+(defun mh-x-image-set-download-state (file data)
+  "Setup a symbolic link from FILE to DATA."
+  (if data
+      (make-symbolic-link (symbol-name data) file t)
+    (delete-file file)))
+
+(defun mh-x-image-get-download-state (file)
+  "Check the state of FILE by following any symbolic links."
+  (unless (file-exists-p mh-x-image-cache-directory)
+    (call-process "mkdir" nil nil nil mh-x-image-cache-directory))
+  (cond ((file-symlink-p file)
+         (intern (file-name-nondirectory (file-chase-links file))))
+        ((not (file-exists-p file)) nil)
+        (t 'ok)))
 
 (defun mh-x-image-url-fetch-image (url cache-file marker sentinel)
   "Fetch and display the image specified by URL.
 After the image is fetched, it is stored in CACHE-FILE. It will be displayed
 in a buffer and position specified by MARKER. The actual display is carried
 out by the SENTINEL function."
-  (if (and mh-wget-executable
-           mh-fetch-x-image-url
-           (or (eq mh-fetch-x-image-url t)
-               (y-or-n-p (format "Fetch %s? " url))))
-      (let ((buffer (get-buffer-create (generate-new-buffer-name " *mh-url*")))
-            (filename (make-temp-name "/tmp/mhe-wget")))
+  (if mh-wget-executable
+      (let ((buffer (get-buffer-create (generate-new-buffer-name
+                                        mh-temp-fetch-buffer)))
+            (filename (or (mh-funcall-if-exists make-temp-file "mhe-fetch")
+                          (expand-file-name (make-temp-name "~/mhe-fetch")))))
         (save-excursion
           (set-buffer buffer)
           (set (make-local-variable 'mh-x-image-url-cache-file) cache-file)
           (set (make-local-variable 'mh-x-image-marker) marker)
           (set (make-local-variable 'mh-x-image-temp-file) filename))
         (set-process-sentinel
-         (start-process "*wget*" buffer mh-wget-executable "-O" filename url)
+         (start-process "*mh-x-image-url-fetch*" buffer
+                        mh-wget-executable mh-wget-option filename url)
          sentinel))
-    ;; Make sure we don't ask about this image again
-    (when (and mh-wget-executable (eq mh-fetch-x-image-url 'ask))
-      (make-symbolic-link mh-x-image-cache-directory cache-file t))))
+    ;; Temporary failure
+    (mh-x-image-set-download-state cache-file 'try-again)))
 
 (defun mh-x-image-display (image marker)
   "Display IMAGE at MARKER."
@@ -1326,7 +1471,8 @@ out by the SENTINEL function."
           (default-enable-multibyte-characters nil)
           (buffer-modified-flag (buffer-modified-p)))
       (unwind-protect
-          (when (and (file-readable-p image) (not (file-symlink-p image)))
+          (when (and (file-readable-p image) (not (file-symlink-p image))
+                     (eq marker mh-x-image-marker))
             (goto-char marker)
             (mh-do-in-gnu-emacs
               (mh-funcall-if-exists insert-image (create-image image 'png)))
@@ -1350,32 +1496,56 @@ The argument CHANGE is ignored."
         (setq marker mh-x-image-marker
               cache-filename mh-x-image-url-cache-file
               temp-file mh-x-image-temp-file))
-      (when mh-convert-executable
-        (call-process mh-convert-executable nil nil nil "-resize" "96x48"
-                       temp-file cache-filename))
-      (if (file-exists-p cache-filename)
-          (mh-x-image-display cache-filename marker)
-        (make-symbolic-link mh-x-image-cache-directory cache-filename t))
+      (cond
+       ;; Check if we have `convert'
+       ((eq mh-x-image-scaling-function 'ignore)
+        (message "The `convert' program is needed to display X-Image-URL")
+        (mh-x-image-set-download-state cache-filename 'try-again))
+       ;; Scale fetched image
+       ((and (funcall mh-x-image-scaling-function temp-file cache-filename)
+             nil))
+       ;; Attempt to display image if we have it
+       ((file-exists-p cache-filename)
+        (mh-x-image-display cache-filename marker))
+       ;; We didn't find the image. Should we try to display it the next time?
+       (t (mh-x-image-set-download-state cache-filename 'try-again)))
       (ignore-errors
         (set-marker marker nil)
         (delete-process process)
         (kill-buffer wget-buffer)
         (delete-file temp-file)))))
 
+(defun mh-x-image-url-sane-p (url)
+  "Check if URL is something sensible."
+  (let ((len (length url)))
+    (cond ((< len 5) nil)
+          ((not (equal (substring url 0 5) "http:")) nil)
+          ((> len 100) nil)
+          (t t))))
+
 (defun mh-x-image-url-display (url)
   "Display image from location URL.
 If the URL isn't present in the cache then it is fetched with wget."
-  (let ((cache-filename (mh-x-image-url-cache-canonicalize url))
-        (marker (set-marker (make-marker) (point))))
-    (cond ((file-exists-p cache-filename)
+  (let* ((cache-filename (mh-x-image-url-cache-canonicalize url))
+         (state (mh-x-image-get-download-state cache-filename))
+         (marker (set-marker (make-marker) (point))))
+    (set (make-local-variable 'mh-x-image-marker) marker)
+    (cond ((not (mh-x-image-url-sane-p url)))
+          ((eq state 'ok)
            (mh-x-image-display cache-filename marker))
+          ((or (not mh-wget-executable)
+               (eq mh-x-image-scaling-function 'ignore)))
+          ((eq state 'never))
           ((not mh-fetch-x-image-url)
            (set-marker marker nil))
-          ((and (not (file-exists-p mh-x-image-cache-directory))
-                (call-process "mkdir" nil nil nil mh-x-image-cache-directory)
-                nil))
-          ((and (file-exists-p mh-x-image-cache-directory)
-                (file-directory-p mh-x-image-cache-directory))
+          ((eq state 'try-again)
+           (mh-x-image-set-download-state cache-filename nil)
+           (mh-x-image-url-fetch-image url cache-filename marker
+                                       'mh-x-image-scale-and-display))
+          ((and (eq mh-fetch-x-image-url 'ask)
+                (not (y-or-n-p (format "Fetch %s? " url))))
+           (mh-x-image-set-download-state cache-filename 'never))
+          ((eq state nil)
            (mh-x-image-url-fetch-image url cache-filename marker
                                        'mh-x-image-scale-and-display)))))
 
@@ -1386,27 +1556,32 @@ If the URL isn't present in the cache then it is fetched with wget."
 If optional arg MSG is non-nil, display that message instead."
   (if mh-showing-mode (mh-show msg)))
 
-(defun mh-show (&optional message)
+(defun mh-show (&optional message redisplay-flag)
   "Show message at cursor.
 If optional argument MESSAGE is non-nil, display that message instead.
 Force a two-window display with the folder window on top (size given by the
 variable `mh-summary-height') and the show buffer below it.
 If the message is already visible, display the start of the message.
 
+If REDISPLAY-FLAG is non-nil, the default when called interactively, the
+message is redisplayed even if the show buffer was already displaying the
+correct message.
+
 Display of the message is controlled by setting the variables
 `mh-clean-message-header-flag' and `mhl-formfile'.  The default behavior is
 to scroll uninteresting headers off the top of the window.
 Type \"\\[mh-header-display]\" to see the message with all its headers."
-  (interactive)
-  (and mh-showing-with-headers
-       (or mhl-formfile mh-clean-message-header-flag)
-       (mh-invalidate-show-buffer))
+  (interactive (list nil t))
+  (when (or redisplay-flag
+            (and mh-showing-with-headers
+                 (or mhl-formfile mh-clean-message-header-flag)))
+    (mh-invalidate-show-buffer))
   (mh-show-msg message))
 
-(defun mh-show-mouse (EVENT)
+(defun mh-show-mouse (event)
   "Move point to mouse EVENT and show message."
   (interactive "e")
-  (mouse-set-point EVENT)
+  (mouse-set-point event)
   (mh-show))
 
 (defun mh-summary-height ()
@@ -1428,10 +1603,12 @@ arguments, after the message has been displayed."
   (let ((folder mh-current-folder)
         (folders (list mh-current-folder))
         (clean-message-header mh-clean-message-header-flag)
-        (show-window (get-buffer-window mh-show-buffer)))
+        (show-window (get-buffer-window mh-show-buffer))
+        (display-mime-buttons-flag mh-display-buttons-for-inline-parts-flag))
     (if (not (eq (next-window (minibuffer-window)) (selected-window)))
         (delete-other-windows))         ; force ourself to the top window
     (mh-in-show-buffer (mh-show-buffer)
+      (setq mh-display-buttons-for-inline-parts-flag display-mime-buttons-flag)
       (if (and show-window
                (equal (mh-msg-filename msg folder) buffer-file-name))
           (progn                        ;just back up to start
@@ -1443,6 +1620,9 @@ arguments, after the message has been displayed."
         (shrink-window (- (window-height) (or mh-summary-height
                                               (mh-summary-height)))))
     (mh-recenter nil)
+    ;; The following line is a nop which forces update of the scan line so
+    ;; that font-lock will update it (if needed)...
+    (mh-notate nil nil mh-cmd-note)
     (if (not (memq msg mh-seen-list))
         (setq mh-seen-list (cons msg mh-seen-list)))
     (when mh-update-sequences-after-mh-show-flag
@@ -1518,8 +1698,8 @@ Sets the current buffer to the show buffer."
     ;; Bind variables in folder buffer in case they are local
     (let ((formfile mhl-formfile)
           (clean-message-header mh-clean-message-header-flag)
-          (invisible-headers mh-invisible-headers)
-          (visible-headers mh-visible-headers)
+          (invisible-headers mh-invisible-header-fields-compiled)
+          (visible-headers nil)
           (msg-filename (mh-msg-filename msg-num folder-name))
           (show-buffer mh-show-buffer)
           (mm-inline-media-tests mh-mm-inline-media-tests))
@@ -1596,7 +1776,10 @@ Sets the current buffer to the show buffer."
 Header is cleaned from START to the end of the message header.
 INVISIBLE-HEADERS contains a regular expression specifying lines to delete
 from the header. VISIBLE-HEADERS contains a regular expression specifying the
-lines to display. INVISIBLE-HEADERS is ignored if VISIBLE-HEADERS is non-nil."
+lines to display. INVISIBLE-HEADERS is ignored if VISIBLE-HEADERS is non-nil.
+
+Note that MH-E no longer supports the `mh-visible-headers' variable, so
+this function could be trimmed of this feature too."
   (let ((case-fold-search t)
         (buffer-read-only nil)
         (after-change-functions nil))   ;Work around emacs-20 font-lock bug
@@ -1639,8 +1822,7 @@ If NOTATION is nil then no change in the buffer occurs."
         (with-mh-folder-updating (t)
           (beginning-of-line)
           (forward-char offset)
-          (let* ((change-stack-flag (and (stringp notation)
-                                         (equal offset (1+ mh-cmd-note))
+          (let* ((change-stack-flag (and (equal offset (1+ mh-cmd-note))
                                          (not (eq notation mh-note-seq))))
                  (msg (and change-stack-flag (or msg (mh-get-msg-num nil))))
                  (stack (and msg (gethash msg mh-sequence-notation-history)))
@@ -1652,7 +1834,7 @@ If NOTATION is nil then no change in the buffer occurs."
                 ;; at the bottom of the stack. If the sequence is deleted,
                 ;; the correct notation will be shown.
                 (setf (gethash msg mh-sequence-notation-history)
-                      (reverse (cons (aref notation 0) (cdr (reverse stack)))))
+                      (reverse (cons notation (cdr (reverse stack)))))
               ;; Since we don't have any sequence notations in the way, just
               ;; notate the scan line.
               (delete-char 1)
@@ -1660,25 +1842,6 @@ If NOTATION is nil then no change in the buffer occurs."
             (when change-stack-flag
               (mh-thread-update-scan-line-map msg notation offset)))))))
 
-(defun mh-find-msg-get-num (step)
-  "Return the message number of the message nearest the cursor.
-Jumps over non-message lines, such as inc errors.
-If we have to search, STEP tells whether to search forward or backward."
-  (or (mh-get-msg-num nil)
-      (let ((msg-num nil)
-            (nreverses 0))
-        (while (and (not msg-num)
-                    (< nreverses 2))
-          (cond ((eobp)
-                 (setq step -1)
-                 (setq nreverses (1+ nreverses)))
-                ((bobp)
-                 (setq step 1)
-                 (setq nreverses (1+ nreverses))))
-          (forward-line step)
-          (setq msg-num (mh-get-msg-num nil)))
-        msg-num)))
-
 (defun mh-goto-msg (number &optional no-error-if-no-message dont-show)
   "Position the cursor at message NUMBER.
 Optional non-nil second argument NO-ERROR-IF-NO-MESSAGE means return nil
@@ -1699,10 +1862,6 @@ Non-nil third argument DONT-SHOW means not to show the message."
     (or dont-show (not return-value) (mh-maybe-show number))
     return-value))
 
-(defun mh-msg-search-pat (n)
-  "Return a search pattern for message N in the scan listing."
-  (format mh-scan-msg-search-regexp n))
-
 (defun mh-get-profile-field (field)
   "Find and return the value of FIELD in the current buffer.
 Returns nil if the field is not in the buffer."
@@ -1716,120 +1875,65 @@ Returns nil if the field is not in the buffer."
              (end-of-line)
              (buffer-substring start (point)))))))
 
-(defvar mail-user-agent)
-(defvar read-mail-command)
-
 (defvar mh-find-path-run nil
   "Non-nil if `mh-find-path' has been run already.")
 
 (defun mh-find-path ()
-  "Set `mh-progs', `mh-lib', and `mh-lib-progs' variables.
+  "Set variables from user's MH profile.
 Set `mh-user-path', `mh-draft-folder', `mh-unseen-seq', `mh-previous-seq',
 `mh-inbox' from user's MH profile.
 The value of `mh-find-path-hook' is a list of functions to be called, with no
 arguments, after these variable have been set."
-  (mh-find-progs)
+  (mh-variants)
   (unless mh-find-path-run
     (setq mh-find-path-run t)
-    (setq read-mail-command 'mh-rmail)
-    (setq mail-user-agent 'mh-e-user-agent))
-  (save-excursion
-    ;; Be sure profile is fully expanded before switching buffers
-    (let ((profile (expand-file-name (or (getenv "MH") "~/.mh_profile"))))
-      (set-buffer (get-buffer-create mh-temp-buffer))
-      (setq buffer-offer-save nil)      ;for people who set default to t
-      (erase-buffer)
-      (condition-case err
-          (insert-file-contents profile)
-        (file-error
-         (mh-install profile err)))
-      (setq mh-user-path (mh-get-profile-field "Path:"))
-      (if (not mh-user-path)
-          (setq mh-user-path "Mail"))
-      (setq mh-user-path
-            (file-name-as-directory
-             (expand-file-name mh-user-path (expand-file-name "~"))))
-      (unless mh-x-image-cache-directory
-        (setq mh-x-image-cache-directory
-              (expand-file-name ".mhe-x-image-cache" mh-user-path)))
-      (setq mh-draft-folder (mh-get-profile-field "Draft-Folder:"))
-      (if mh-draft-folder
-          (progn
-            (if (not (mh-folder-name-p mh-draft-folder))
-                (setq mh-draft-folder (format "+%s" mh-draft-folder)))
-            (if (not (file-exists-p (mh-expand-file-name mh-draft-folder)))
-                (error "Draft folder \"%s\" not found.  Create it and try again"
-                       (mh-expand-file-name mh-draft-folder)))))
-      (setq mh-inbox (mh-get-profile-field "Inbox:"))
-      (cond ((not mh-inbox)
-             (setq mh-inbox "+inbox"))
-            ((not (mh-folder-name-p mh-inbox))
-             (setq mh-inbox (format "+%s" mh-inbox))))
-      (setq mh-unseen-seq (mh-get-profile-field "Unseen-Sequence:"))
-      (if mh-unseen-seq
-          (setq mh-unseen-seq (intern mh-unseen-seq))
-        (setq mh-unseen-seq 'unseen))   ;old MH default?
-      (setq mh-previous-seq (mh-get-profile-field "Previous-Sequence:"))
-      (if mh-previous-seq
-          (setq mh-previous-seq (intern mh-previous-seq)))
-      (run-hooks 'mh-find-path-hook)
-      (mh-collect-folder-names))))
+    (save-excursion
+      ;; Be sure profile is fully expanded before switching buffers
+      (let ((profile (expand-file-name (or (getenv "MH") "~/.mh_profile"))))
+        (set-buffer (get-buffer-create mh-temp-buffer))
+        (setq buffer-offer-save nil)      ;for people who set default to t
+        (erase-buffer)
+        (condition-case err
+            (insert-file-contents profile)
+          (file-error
+           (mh-install profile err)))
+        (setq mh-user-path (mh-get-profile-field "Path:"))
+        (if (not mh-user-path)
+            (setq mh-user-path "Mail"))
+        (setq mh-user-path
+              (file-name-as-directory
+               (expand-file-name mh-user-path (expand-file-name "~"))))
+        (unless mh-x-image-cache-directory
+          (setq mh-x-image-cache-directory
+                (expand-file-name ".mhe-x-image-cache" mh-user-path)))
+        (setq mh-draft-folder (mh-get-profile-field "Draft-Folder:"))
+        (if mh-draft-folder
+            (progn
+              (if (not (mh-folder-name-p mh-draft-folder))
+                  (setq mh-draft-folder (format "+%s" mh-draft-folder)))
+              (if (not (file-exists-p (mh-expand-file-name mh-draft-folder)))
+                  (error
+                   "Draft folder \"%s\" not found.  Create it and try again"
+                         (mh-expand-file-name mh-draft-folder)))))
+        (setq mh-inbox (mh-get-profile-field "Inbox:"))
+        (cond ((not mh-inbox)
+               (setq mh-inbox "+inbox"))
+              ((not (mh-folder-name-p mh-inbox))
+               (setq mh-inbox (format "+%s" mh-inbox))))
+        (setq mh-unseen-seq (mh-get-profile-field "Unseen-Sequence:"))
+        (if mh-unseen-seq
+            (setq mh-unseen-seq (intern mh-unseen-seq))
+          (setq mh-unseen-seq 'unseen))   ;old MH default?
+        (setq mh-previous-seq (mh-get-profile-field "Previous-Sequence:"))
+        (if mh-previous-seq
+            (setq mh-previous-seq (intern mh-previous-seq)))
+        (run-hooks 'mh-find-path-hook)
+        (mh-collect-folder-names)))))
 
 (defun mh-file-command-p (file)
   "Return t if file FILE is the name of a executable regular file."
   (and (file-regular-p file) (file-executable-p file)))
 
-(defun mh-find-progs ()
-  "Find the directories for the installed MH/nmh binaries and config files.
-Set the `mh-progs' and `mh-lib', and `mh-lib-progs' variables to the
-directory names and set `mh-nmh-flag' if we detect nmh instead of MH."
-  (unless (and mh-progs mh-lib mh-lib-progs)
-    (let ((path (or (mh-path-search exec-path "mhparam")
-                    (mh-path-search '("/usr/local/nmh/bin" ; nmh default
-                                      "/usr/local/bin/mh/"
-                                      "/usr/local/mh/"
-                                      "/usr/bin/mh/" ;Ultrix 4.2, Linux
-                                      "/usr/new/mh/" ;Ultrix <4.2
-                                      "/usr/contrib/mh/bin/" ;BSDI
-                                      "/usr/pkg/bin/" ; NetBSD
-                                      "/usr/local/bin/"
-                                      )
-                                    "mhparam"))))
-      (if (not path)
-          (error "Unable to find the `mhparam' command"))
-      (save-excursion
-        (let ((tmp-buffer (get-buffer-create mh-temp-buffer)))
-          (set-buffer tmp-buffer)
-          (unwind-protect
-              (progn
-                (call-process (expand-file-name "mhparam" path)
-                              nil '(t nil) nil "libdir" "etcdir")
-                (goto-char (point-min))
-                (if (search-forward-regexp "^libdir:\\s-\\(\\S-+\\)\\s-*$"
-                                           nil t)
-                    (setq mh-lib-progs (match-string 1)
-                          mh-lib mh-lib-progs
-                          mh-progs path))
-                (goto-char (point-min))
-                (if (search-forward-regexp "^etcdir:\\s-\\(\\S-+\\)\\s-*$"
-                                           nil t)
-                    (setq mh-lib (match-string 1)
-                          mh-nmh-flag t)))
-            (kill-buffer tmp-buffer))))
-      (unless (and mh-progs mh-lib mh-lib-progs)
-        (error "Unable to determine paths from `mhparam' command"))
-      (setq mh-flists-present-flag
-            (file-exists-p (expand-file-name "flists" mh-progs))))))
-
-(defun mh-path-search (path file)
-  "Search PATH, a list of directory names, for FILE.
-Returns the element of PATH that contains FILE, or nil if not found."
-  (while (and path
-              (not (funcall 'mh-file-command-p
-                            (expand-file-name file (car path)))))
-    (setq path (cdr path)))
-  (car path))
-
 (defvar mh-no-install nil)              ;do not run install-mh
 
 (defun mh-install (profile error-val)
@@ -1911,18 +2015,18 @@ not updated."
   (let ((entry (mh-find-seq seq))
         (internal-seq-flag (mh-internal-seq seq)))
     (if (and msgs (atom msgs)) (setq msgs (list msgs)))
-    (unless internal-flag
-      (mh-add-to-sequence seq msgs)
-      (when (not dont-annotate-flag)
-        (mh-iterate-on-range msg msgs
-          (unless (memq msg (cdr entry))
-            (mh-add-sequence-notation msg internal-seq-flag)))))
     (if (null entry)
         (setq mh-seq-list
               (cons (mh-make-seq seq (mh-canonicalize-sequence msgs))
                     mh-seq-list))
       (if msgs (setcdr entry (mh-canonicalize-sequence
-                              (append msgs (mh-seq-msgs entry))))))))
+                              (append msgs (mh-seq-msgs entry))))))
+    (unless internal-flag
+      (mh-add-to-sequence seq msgs)
+      (when (not dont-annotate-flag)
+        (mh-iterate-on-range msg msgs
+          (unless (memq msg (cdr entry))
+            (mh-add-sequence-notation msg internal-seq-flag)))))))
 
 (defun mh-canonicalize-sequence (msgs)
   "Sort MSGS in decreasing order and remove duplicates."
@@ -2076,12 +2180,15 @@ aren't usually mail folders are hidden."
       (goto-char (point-min))
       (while (not (and (eolp) (bolp)))
         (goto-char (line-end-position))
-        (let ((has-pos (search-backward " has " (line-beginning-position) t)))
+        (let ((start-pos (line-beginning-position))
+              (has-pos (search-backward " has " (line-beginning-position) t)))
           (when (integerp has-pos)
             (while (equal (char-after has-pos) ? )
               (decf has-pos))
             (incf has-pos)
-            (let* ((name (buffer-substring (line-beginning-position) has-pos))
+            (while (equal (char-after start-pos) ? )
+              (incf start-pos))
+            (let* ((name (buffer-substring start-pos has-pos))
                    (first-char (aref name 0))
                    (last-char (aref name (1- (length name)))))
               (unless (member first-char '(?. ?# ?,))
@@ -2189,7 +2296,9 @@ whether the completion is over."
 If ALLOW-ROOT-FOLDER-FLAG is non-nil then \"+\" is allowed to be a folder name
 corresponding to `mh-user-path'."
   (mh-normalize-folder-name
-   (let ((minibuffer-local-completion-map mh-folder-completion-map)
+   (let ((minibuffer-completing-file-name t)
+         (completion-root-regexp "^[+/]")
+         (minibuffer-local-completion-map mh-folder-completion-map)
          (mh-allow-root-folder-flag allow-root-folder-flag))
      (completing-read prompt 'mh-folder-completion-function nil nil nil
                       'mh-folder-hist default))
@@ -2206,11 +2315,10 @@ non-nil then the function will accept the folder +, which means all folders
 when used in searching."
   (if (null default)
       (setq default ""))
-  (let* ((default-string (cond (default-string (format " [%s]? "
-                                                       default-string))
-                               ((equal "" default) "? ")
-                               (t (format " [%s]? " default))))
-         (prompt (format "%s folder%s" prompt default-string))
+  (let* ((default-string (cond (default-string (format "[%s] " default-string))
+                               ((equal "" default) "")
+                               (t (format "[%s] " default))))
+         (prompt (format "%s folder: %s" prompt default-string))
          (mh-current-folder-name mh-current-folder)
          read-name folder-name)
     (while (and (setq read-name (mh-folder-completing-read
@@ -2452,6 +2560,13 @@ Put the output into buffer after point.  Set mark after inserted text."
       (setq l (cdr l)))
     new-list))
 
+(defun mh-replace-string (old new)
+  "Replace all occurrences of OLD with NEW in the current buffer."
+  (goto-char (point-min))
+  (let ((case-fold-search t))
+    (while (search-forward old nil t)
+      (replace-match new t t))))
+
 (defun mh-replace-in-string (regexp newtext string)
   "Replace REGEXP with NEWTEXT everywhere in STRING and return result.
 NEWTEXT is taken literally---no \\DIGIT escapes will be recognized.