summaryrefslogtreecommitdiff
path: root/lisp/mh-e
diff options
context:
space:
mode:
authorBill Wohler <wohler@newt.com>2004-08-15 22:00:06 +0000
committerBill Wohler <wohler@newt.com>2004-08-15 22:00:06 +0000
commitf0d73c14e2c9b9329a86ed8092f9329823598638 (patch)
tree673d530ab2247283cf5af3b570fa6a78450f144c /lisp/mh-e
parent6dad1714dbc14c28b3ea54bd32744b6ff0ac2d76 (diff)
downloademacs-f0d73c14e2c9b9329a86ed8092f9329823598638.tar.gz
Upgraded to MH-E version 7.4.80.
See etc/MH-E-NEWS and lisp/mh-e/ChangeLog for details.
Diffstat (limited to 'lisp/mh-e')
-rw-r--r--lisp/mh-e/ChangeLog2008
-rw-r--r--lisp/mh-e/mh-alias.el207
-rw-r--r--lisp/mh-e/mh-comp.el450
-rw-r--r--lisp/mh-e/mh-customize.el2662
-rw-r--r--lisp/mh-e/mh-e.el524
-rw-r--r--lisp/mh-e/mh-funcs.el97
-rw-r--r--lisp/mh-e/mh-gnus.el36
-rw-r--r--lisp/mh-e/mh-identity.el296
-rw-r--r--lisp/mh-e/mh-inc.el8
-rw-r--r--lisp/mh-e/mh-index.el225
-rw-r--r--lisp/mh-e/mh-junk.el454
-rw-r--r--lisp/mh-e/mh-loaddefs.el513
-rw-r--r--lisp/mh-e/mh-mime.el288
-rw-r--r--lisp/mh-e/mh-pick.el39
-rw-r--r--lisp/mh-e/mh-seq.el212
-rw-r--r--lisp/mh-e/mh-speed.el33
-rw-r--r--lisp/mh-e/mh-utils.el743
17 files changed, 5730 insertions, 3065 deletions
diff --git a/lisp/mh-e/ChangeLog b/lisp/mh-e/ChangeLog
index 3d19028b099..645e9a1bd6d 100644
--- a/lisp/mh-e/ChangeLog
+++ b/lisp/mh-e/ChangeLog
@@ -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.
@@ -66,7 +302,7 @@
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.
@@ -87,6 +323,128 @@
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.
@@ -95,6 +453,8 @@
* 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.
@@ -103,6 +463,810 @@
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.
@@ -131,6 +1295,848 @@
(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.
diff --git a/lisp/mh-e/mh-alias.el b/lisp/mh-e/mh-alias.el
index bd20b9118b0..1356e2c8b95 100644
--- a/lisp/mh-e/mh-alias.el
+++ b/lisp/mh-e/mh-alias.el
@@ -27,75 +27,12 @@
;;; 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.
@@ -116,15 +53,23 @@
(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].")
+
;;; 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)))
@@ -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 ""))
diff --git a/lisp/mh-e/mh-comp.el b/lisp/mh-e/mh-comp.el
index 489b6690bc7..cde52c65043 100644
--- a/lisp/mh-e/mh-comp.el
+++ b/lisp/mh-e/mh-comp.el
@@ -33,11 +33,12 @@
;;; 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.
diff --git a/lisp/mh-e/mh-customize.el b/lisp/mh-e/mh-customize.el
index 2ce36c88726..0cf35b3c0d9 100644
--- a/lisp/mh-e/mh-customize.el
+++ b/lisp/mh-e/mh-customize.el
@@ -34,814 +34,585 @@
;;
;; 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)))
+
+
+;;; 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)
-;;; MH-E Customization (:group mh)
-
-;;; Toolbar configuration (:group 'mh-toolbar)
-
-(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)
-
-;; 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))
-
-(defun mh-tool-bar-customize ()
- "Call `mh-customize' from the toolbar."
- (interactive)
- (mh-customize t))
-
-(defun mh-tool-bar-folder-help ()
- "Visit \"(mh-e)Top\"."
- (interactive)
- (Info-goto-node "(mh-e)Top")
- (delete-other-windows))
-
-(defun mh-tool-bar-letter-help ()
- "Visit \"(mh-e)Draft Editing\"."
- (interactive)
- (Info-goto-node "(mh-e)Draft Editing")
- (delete-other-windows))
-
-(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)))
-
-(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)
+;;; 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)
-;; 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.
+
-This will default to t if you are in an environment that supports
-toolbars and xpm."
- :type 'boolean
- :group 'mh-toolbar)
+;;; Aliases (:group 'mh-alias)
- (defcustom mh-xemacs-toolbar-position (if mh-xemacs-use-toolbar-flag
- 'default
- nil)
- "*Where to put the toolbar.
+(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)
-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-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)
-A nil value means do not use a toolbar.
+(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)
-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-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-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:
+(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)
- (:KEYWORD FUNC1 FUNC2 FUNC3 ...)
+(defcustom mh-alias-local-users t
+ "*If on, local users are added to alias completion.
-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.
+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'.
-Each element of BUTTONS is a list consisting of four mandatory items and one
-optional item as follows:
+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.
- (FUNCTION MODES ICON DOC &optional ENABLE-EXPR)
+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)
-where,
+(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'.
- FUNCTION is the name of the function that will be executed when the button
- is clicked.
+For example, consider the following password file entry:
- 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.
+ psg:x:1000:1000:Peter S Galbraith,,,:/home/psg:/bin/tcsh
- ICON is the icon that is drawn in the button.
+The following settings of this option will produce the associated aliases:
- 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.
+ \"local.\" local.peter.galbraith
+ \"\" peter.galbraith
+ Use Login psg
- 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)))))))
+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)
-(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'"))
+(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)
-;;; 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)
+;;; Organizing Your Mail with Folders (:group 'mh-folder)
-(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."
+(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-speed)
+ :group 'mh-folder)
-;;; Options for controlling scan listing (:group 'mh-folder)
+;;; Folder Selection (:group 'mh-folder-selection)
-(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)
-
-(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)
+ :group 'mh-folder-selection)
-(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)
+;;; Identities (:group 'mh-identity)
-(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)
+(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)
-(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)
+(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-recursive-folders-flag nil
- "*Non-nil means that commands which operate on folders do so recursively."
+(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)
+ :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-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-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-folder)
+(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-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-folder)
+;;; Incorporating Your Mail (:group 'mh-inc)
-(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."
+(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-folder)
-(make-variable-buffer-local 'mh-scan-prog)
-
-(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)
-
-(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)
+ :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-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)
-;;; 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"))))
-;;; 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 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))
+ "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-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)
+
+
+
+;;; 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)
+
-;;; Message display (:group 'mh-show)
+;;; 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)
+
+
+
+;;; 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)
+
+
+
+;;; 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)
+
+
+
+;;; 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)
+
+
+
+;;; 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 \"Never fetch\" (nil), images are never fetched and only displayed
+if they are already present in the cache.
-If set to t, the image is fetched.
+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'.
-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.
+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."
-;;; 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)
+;;; The Speedbar (:group 'mh-speed)
-(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)
-
-(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.
+ :group 'mh-speed)
-If nil, or the file does not exist, nothing is added to the message header."
- :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.
+;;; The Toolbar (:group 'mh-toolbar)
-If the symbol `body', then yank the message minus the header.
+(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 `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.
+;; 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 `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.
+(defun mh-tool-bar-customize ()
+ "Call `mh-customize' from the toolbar."
+ (interactive)
+ (mh-customize t))
-If the symbol `attribution', then yank the message minus the header and add
-a simple attribution line at the top.
+(defun mh-tool-bar-folder-help ()
+ "Visit \"(mh-e)Top\"."
+ (interactive)
+ (Info-goto-node "(mh-e)Top")
+ (delete-other-windows))
-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-letter-help ()
+ "Visit \"(mh-e)Draft Editing\"."
+ (interactive)
+ (Info-goto-node "(mh-e)Draft Editing")
+ (delete-other-windows))
-If nil, yank only the portion of the message following the point.
+(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)))
-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)
+(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)
-
+;; 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.
-;;; Alias handling (: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-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)
+ (defcustom mh-xemacs-toolbar-position (if mh-xemacs-use-toolbar-flag
+ 'default
+ nil)
+ "*Where to put the 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)
+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-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)
+A nil value means do not use a 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)
+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-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)
+(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:
-(defcustom mh-alias-local-users t
- "*If t, local users are completed in MH-E To: and Cc: prompts.
+ (:KEYWORD FUNC1 FUNC2 FUNC3 ...)
-Users with a userid greater than some magic number (usually 200) are available
-for completion.
+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.
-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)
+Each element of BUTTONS is a list consisting of four mandatory items and one
+optional item as follows:
-(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.
+ (FUNCTION MODES ICON DOC &optional ENABLE-EXPR)
-For example, given the following passwd file line:
+where,
- psg:x:1000:1000:Peter S Galbraith,,,:/home/psg:/bin/tcsh
+ FUNCTION is the name of the function that will be executed when the button
+ is clicked.
-here are the derived aliases for different values of this variable:
+ 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.
- \"local.\" -> local.peter.galbraith
- \"\" -> peter.galbraith
- nii -> psg
+ ICON is the icon that is drawn in the button.
-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)
+ 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.
-(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)
+ 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'"))
-;;; Multiple personalities (:group 'mh-identity)
+;;; Hooks (:group 'mh-hooks + group where hook described)
-(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 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.
-(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.
+If this hook is entirely empty (nil), the text of the message is inserted
+with `mh-ins-buf-prefix' prefixed to each line.
-There is one special case for KEYWORD, that of \"identity\", which means to
-insert that identity using `mh-insert-identity'.
+See also the variable `mh-yank-from-start-of-msg', which controls how
+much of the message passed to the hook.
-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)
+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.
-(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)
-
-
-
-;;; 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)
-;;; 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)
-
-(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)
-
-
+;;; Faces (:group 'mh-*-faces + group where faces described)
-;;; 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."
-;;; 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)
+
+
+
+;;; 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)
+
+
+
+;;; 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."
-;;; 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)
-
-
-
-;;; 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
diff --git a/lisp/mh-e/mh-e.el b/lisp/mh-e/mh-e.el
index e72304c4412..5cb7f90f1e3 100644
--- a/lisp/mh-e/mh-e.el
+++ b/lisp/mh-e/mh-e.el
@@ -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.
@@ -75,24 +75,19 @@
;; 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)
@@ -101,35 +96,27 @@
(defvar font-lock-auto-fontify)
(defvar font-lock-defaults)
-(defconst mh-version "7.4.4" "Version number of MH-E.")
+(defconst mh-version "7.4.80" "Version number of MH-E.")
;;; Autoloads
(autoload 'Info-goto-node "info")
-
-
-(defvar mh-note-deleted "D"
- "String whose first character is used to notate deleted messages.")
-
-(defvar mh-note-refiled "^"
- "String whose first character is used to notate refiled messages.")
-
-(defvar mh-note-cur "+"
- "String whose first character is used to notate the current message.")
-
(defvar mh-partial-folder-mode-line-annotation "select"
"Annotation when displaying part of a folder.
The string is displayed after the folder's name. nil for no annotation.")
+
+;;; Scan Line Formats
+
;;; Parameterize MH-E to work with different scan formats. The defaults work
;;; with the standard MH scan listings, in which the first 4 characters on
;;; the line are the message number, followed by two places for notations.
-;; The following scan formats are passed to the scan program if the
-;; setting of `mh-scan-format-file' above is nil. They are identical
-;; except the later one makes use of the nmh `decode' function to
-;; decode RFC 2047 encodings. If you just want to change the width of
-;; the msg number, use the `mh-set-cmd-note' function.
+;; The following scan formats are passed to the scan program if the setting of
+;; `mh-scan-format-file' is t. They are identical except the later one makes
+;; use of the nmh `decode' function to decode RFC 2047 encodings. If you just
+;; want to change the width of the msg number, use the `mh-set-cmd-note'
+;; function.
(defvar mh-scan-format-mh
(concat
@@ -150,11 +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
+ \"*\\\\(..................\\\\)\")\".")
@@ -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")
diff --git a/lisp/mh-e/mh-funcs.el b/lisp/mh-e/mh-funcs.el
index 46201860e2a..ef745f4c06f 100644
--- a/lisp/mh-e/mh-funcs.el
+++ b/lisp/mh-e/mh-funcs.el
@@ -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
@@ -233,60 +237,6 @@ Otherwise just send the message's body without the headers."
(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.
Calls the MH program sortm to do the work.
@@ -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)
diff --git a/lisp/mh-e/mh-gnus.el b/lisp/mh-e/mh-gnus.el
index 0a893efa3c9..b850c8fdc43 100644
--- a/lisp/mh-e/mh-gnus.el
+++ b/lisp/mh-e/mh-gnus.el
@@ -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
diff --git a/lisp/mh-e/mh-identity.el b/lisp/mh-e/mh-identity.el
index f4edc7a2087..2b430a52fe1 100644
--- a/lisp/mh-e/mh-identity.el
+++ b/lisp/mh-e/mh-identity.el
@@ -39,47 +39,50 @@
;;; 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:
diff --git a/lisp/mh-e/mh-inc.el b/lisp/mh-e/mh-inc.el
index 1c052b140bd..42ca018506f 100644
--- a/lisp/mh-e/mh-inc.el
+++ b/lisp/mh-e/mh-inc.el
@@ -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'"))))
diff --git a/lisp/mh-e/mh-index.el b/lisp/mh-e/mh-index.el
index 734ce938616..91eed420e2e 100644
--- a/lisp/mh-e/mh-index.el
+++ b/lisp/mh-e/mh-index.el
@@ -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."
-;; 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)))
-
-
-
;; 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))
diff --git a/lisp/mh-e/mh-junk.el b/lisp/mh-e/mh-junk.el
index 42ec4c444d3..095a8c3c3fd 100644
--- a/lisp/mh-e/mh-junk.el
+++ b/lisp/mh-e/mh-junk.el
@@ -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
@@ -39,36 +41,33 @@
(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)))
-;; 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\".
-
+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.
-
+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))))
+
+
+;; 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")))
+
+
+
+;; 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:
diff --git a/lisp/mh-e/mh-loaddefs.el b/lisp/mh-e/mh-loaddefs.el
index a5578760845..43119b62be0 100644
--- a/lisp/mh-e/mh-loaddefs.el
+++ b/lisp/mh-e/mh-loaddefs.el
@@ -11,22 +11,24 @@
;;;;;; 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)
;;;***
-;;;### (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)
-
-;;;***
-
-;;;### (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)
-
-;;;***
-
;;;### (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)
;;;***
-;;;### (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)
+
;;;***
-;;;### (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)
;;;### (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)
;;;***
+;;;### (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)
+
+;;;***
+
;;;### (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)
;;;***
-;;;### (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)
+
;;;***
-;;;### (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)
;;;***
+;;;### (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)
+
+;;;***
+
;;;### (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)
;;;***
;;;### (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)
;;;***
-;;;### (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)
-
-;;;***
-
;;;### (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)
;;;***
diff --git a/lisp/mh-e/mh-mime.el b/lisp/mh-e/mh-mime.el
index 91cbcec0c06..6b3c5793be5 100644
--- a/lisp/mh-e/mh-mime.el
+++ b/lisp/mh-e/mh-mime.el
@@ -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)
diff --git a/lisp/mh-e/mh-pick.el b/lisp/mh-e/mh-pick.el
index a888f02154f..b92a98f26cc 100644
--- a/lisp/mh-e/mh-pick.el
+++ b/lisp/mh-e/mh-pick.el
@@ -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.
@@ -139,16 +144,6 @@ with no arguments, upon entry to this mode.
(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.
Messages are searched for in the folder named in `mh-searching-folder'.
@@ -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)))
diff --git a/lisp/mh-e/mh-seq.el b/lisp/mh-e/mh-seq.el
index 20950d36c4c..8d2369ed19a 100644
--- a/lisp/mh-e/mh-seq.el
+++ b/lisp/mh-e/mh-seq.el
@@ -70,7 +70,7 @@
;;; Code:
-(require 'mh-utils)
+(eval-when-compile (require 'mh-acros))
(mh-require-cl)
(require 'mh-e)
@@ -78,15 +78,15 @@
(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
@@ -533,28 +533,6 @@ should be replaced with:
(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.
In addition to notating the current message with `mh-note-cur' the function
@@ -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))
-
;;; 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:
diff --git a/lisp/mh-e/mh-speed.el b/lisp/mh-e/mh-speed.el
index 967984d1104..2617a941de1 100644
--- a/lisp/mh-e/mh-speed.el
+++ b/lisp/mh-e/mh-speed.el
@@ -34,10 +34,11 @@
;;; 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.
diff --git a/lisp/mh-e/mh-utils.el b/lisp/mh-e/mh-utils.el
index b1966915e86..a57567a7bd3 100644
--- a/lisp/mh-e/mh-utils.el
+++ b/lisp/mh-e/mh-utils.el
@@ -33,20 +33,14 @@
;;; 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
@@ -69,43 +64,12 @@
;;; 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: "
+
+;;; 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.")
+
+
(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.")
+
(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."
+;; 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)))
+
+
+
;; 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.