Mercurial > emacs
changeset 50702:7dd3d5eae9c7
Upgraded to MH-E version 7.3.
See etc/MH-E-NEWS and lisp/mh-e/ChangeLog for details.
author | Bill Wohler <wohler@newt.com> |
---|---|
date | Fri, 25 Apr 2003 05:52:00 +0000 |
parents | cb5f0a5d5b36 |
children | 1074aeb2a2fd |
files | etc/ChangeLog etc/MH-E-NEWS etc/NEWS lisp/mh-e/ChangeLog lisp/mh-e/mh-alias.el lisp/mh-e/mh-comp.el lisp/mh-e/mh-customize.el lisp/mh-e/mh-e.el lisp/mh-e/mh-funcs.el lisp/mh-e/mh-identity.el lisp/mh-e/mh-inc.el lisp/mh-e/mh-index.el lisp/mh-e/mh-junk.el lisp/mh-e/mh-loaddefs.el lisp/mh-e/mh-mime.el lisp/mh-e/mh-pick.el lisp/mh-e/mh-seq.el lisp/mh-e/mh-speed.el lisp/mh-e/mh-utils.el lisp/mh-e/mh-xemacs-compat.el lisp/mh-e/mh-xemacs-icons.el lisp/toolbar/highlight.pbm lisp/toolbar/highlight.xpm |
diffstat | 23 files changed, 6398 insertions(+), 1558 deletions(-) [+] |
line wrap: on
line diff
--- a/etc/ChangeLog Fri Apr 25 04:32:25 2003 +0000 +++ b/etc/ChangeLog Fri Apr 25 05:52:00 2003 +0000 @@ -1,3 +1,8 @@ +2003-04-24 Bill Wohler <wohler@newt.com> + + * MH-E-NEWS: Upgraded to MH-E version 7.3. + + 2003-04-03 Kenichi Handa <handa@etlken2> * HELLO: Fix the malayalam line.
--- a/etc/MH-E-NEWS Fri Apr 25 04:32:25 2003 +0000 +++ b/etc/MH-E-NEWS Fri Apr 25 05:52:00 2003 +0000 @@ -1,3 +1,260 @@ +Copyright (C) 2003 Free Software Foundation, Inc. + +Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. + + +* Changes in MH-E 7.3 + +** New Features in MH-E 7.3 + +*** Unified function arguments + +Any function with MSG-OR-SEQ in its docstring uses the displayed +message by default for this argument. However, if a prefix argument is +provided, then the user is prompted for a message sequence. If the +variable `transient-mark-mode' is non-nil and the mark is active, then +the function operates on the messages in the selected region. In a +program, MSG-OR-SEQ can be a message number, a list of message +numbers, a region in a cons cell, or a sequence. + +*** MH-Index view of unseen messages + +Use "F n (mh-index-new-messages)" or Folder -> View New Messages menu +item to display messages in the `mh-unseen-seq' sequence in folders +specified by `mh-index-new-messages-folders'. With a prefix argument, +enter a space-separated list of folders, or nothing to search all +folders. + +Like other MH-Index folders, use "v (mh-index-visit-folder)" if you +wish to visit the original folder with the unseen message. This is +usually not necessary since the original message is annotated if you +reply, deleted if you delete the message, or refiled if you refile the +message (closes SF #701756). + +*** Spam software support + +MH-E now supports several spam filters including Bogofilter, +SpamProbe, and SpamAssassin. Spam that is mistakenly considered to be +good mail can be reclassified as spam with "J b (mh-junk-blacklist)". +Conversely, good mail that is accidently considered to be spam can be +reclassified with "J w (mh-junk-whitelist)" (closes SF #669518). + +If a message is blacklisted, and `mh-junk-mail-folder' is a string, +then the message is refiled to that folder. If this variable is nil, +the message is deleted. If a message is whitelisted, then the message +is refiled to `mh-inbox'. + +To change the spam program being used, customize `mh-junk-program'. +This should only be necessary if you have multiple filters on your +system and MH-E picked the wrong one. These customization variables +are found in the new customization group `mh-junk'. + +The documentation for the following functions describes what setup is +needed for the different spam fighting programs: + + - `mh-bogofilter-blacklist' + - `mh-spamprobe-blacklist' + - `mh-spamassassin-blacklist' + +*** Relative folder specification @ supported + +You can now use the relative folder marker @ in folder names (closes +SF #666774). + +*** Marking messages + +Messages can now be highlighted with "' (mh-toggle-tick)", Sequence -> +Toggle Tick Mark menu item or the "Toggle tick mark" button. These +messages are added to the "tick" sequence, although this sequence can +be changed in `mh-tick-seq'. The highlighting effect can be modified +by customizing `mh-folder-tick-face' (closes SF #623367). + +There is also a new keybinding "/ ' (mh-narrow-to-tick)" and menu item +Sequence -> Narrow to Tick Sequence to narrow the view to the +highlighted messages. + +*** mh-default-folder-list now takes recipients + +If you wish to file a message based upon the recipient of a message +(such as a mailing list), you can now indicate that when filling out +the address in the `mh-default-folder-list' customization variable. + +*** Face header field supported + +In addition to the X-Face header field, the Face header field, which +can display color images, is now supported. As a bonus, the external +xface-e21 library is no longer required. + +*** X-Image-URL support + +Images specified in X-Image-URL header fields are now supported. +See the customization variable `mh-fetch-x-image-url' to enable this +support. + +*** Fcc completion + +Folders in Fcc fields in message drafts can now be completed with +M-TAB. + +** New Variables in MH-E 7.3 + +Variables that have been added to MH-E that have not been discussed +elsewhere are listed here. + +*** mh-auto-fields-list + +Alist of addresses for which header lines are automatically inserted. +When a regular expression matches in the To or cc fields of a message, +the corresponding header field is automatically inserted in the +message header. It also allows the automatic setting of an identity +(using `mh-insert-identity') to set an alternate identity when sending +messages to a certain person or mailing list. + +Since this is a more general use of `mh-insert-mail-followup-to-flag' +and `mh-insert-mail-followup-to-list', these variables have been removed. + +*** mh-show-xface-face + +Face for displaying the X-Face image. + +*** mh-xemacs-toolbar-position + +This customization variable allows the user to place the toolbar on +the four edges of the frame. + +*** mh-xemacs-use-toolbar-flag + +This customization variable is used to enable or disable the toolbar +under XEmacs. + +** Variables Deleted in MH-E 7.3 + +Variables that have been removed from MH-E that have not been +discussed elsewhere are listed here. + +*** mh-decode-content-transfer-encoded-message-flag + +No longer needed since the external program mimencode is no longer +used. + +*** mh-index-show-hook + +This hook was never used, so it was removed. + +*** mh-tool-bar-reply-3-buttons-flag + +Obsolete. This functionality is present `mh-tool-bar-folder-buttons'. + +** Bug Fixes in MH-E 7.3 + +*** Can't refile message + +Messages with invalid addresses were causing errors in ali which +prevented the refiling of messages. The ali error is now shown in the +"*MH-E Log*" buffer and refiling suggests the last folder used (closes +SF #680388). + +*** Empty body triggers duped header + +If the body was empty the header would be treated like the body and +was therefore displayed twice. This has been fixed (closes SF +#681162). + +*** mml or mhl directives not always processed + +The mml and mhl directives used to create body parts were not +processed if one re-edited a draft, or if they added the directives +manually. The directives are now always processed upon sending the +letter. You may still, of course, use "C-c C-m m (mh-mml-to-mime)" or +"C-c C-e (mh-edit-mhn)" to manually create the MIME body parts from +the directives and then send the draft. + +*** mh-alias-grab-from-field fails + +MH-E was adding aliases with angle brackets around the address when +there wasn't a phrase (usually, the user's name), to go with it. This +caused ali to fail which caused problems in MH-E. This is probably a +bug in ali, but MH-E no longer inserts angle brackets around the +address unless there is a phrase, which avoids the problem (closes SF +#690216). + +*** XEmacs fixes + +MH-E is now fully supported under XEmacs and compiles without any +warnings. + +In particular, the following now work under XEmacs: + +- X-Face, Face, and X-Image-URL header fields +- MH-E logo in mode line +- Emphasis (bold, italics, etc.) +- Smilies +- Toolbar + +*** Indexed folders should respect mh-show-threads-flag + +Indexed folders are now threaded if `mh-show-threads-flag' is non-nil +(closes SF #709667). + +*** Threading index view loses folder info + +This has been fixed (closes SF #709672). + +*** No undo information when re-editing drafts + +Undo is turned on in the draft buffer when using "e (mh-edit-again)" +(closes SF #712777). + +*** Forwarded base64 encoded messages are incorrectly displayed + +This has been fixed (closes SF #681518). + +*** Append to *MH-E Log* buffer + +The last 100 lines of log messages are kept in the *MH-E Log* buffer. +Previously, the buffer was erased every time it was written (closes SF +#685476). In addition, many of the MH-E commands now send their output +into this buffer instead of a plethora of other special-purpose +buffers. + +*** mh-inc-folder complains if no mail and no current message + +The function `mh-inc-folder' no longer calls `mh-show' if point is not +on a valid scan line. This keeps `mh-inc-folder' from complaining +(closes SF #678115). + +*** Folder normalization strips leading slash + +Leading "/" characters in folder names entered by the user were being +lost. This has been fixed (closes SF #676890). + +*** Print header doesn't show message + +When printing a sequence, the header simply indicated that a sequence, +but not which one, was being printed and did not show the message +number. This has been fixed. If more than one message is printed, a +page of the scan lines is printed and its header indicates the +sequence or message range. The pages with the actual messages all set +the header to the folder and message displayed on that page. + +*** Aliases constantly reloaded + +Empty lists are now handled properly (closes SF #693859). + +*** Remove RCS keywords + +Removed RCS keywords per Emacs conventions (closes SF #680731). + +*** Replace mimencode + +MH-E was enhanced to decode message based on charset and +Content-Transfer-Encoding. This eliminates the need for the external +program mimencode (closes SF #674857). + + + * Changes in MH-E 7.2 This release includes the new features of filing hints, hierarchical
--- a/etc/NEWS Fri Apr 25 04:32:25 2003 +0000 +++ b/etc/NEWS Fri Apr 25 05:52:00 2003 +0000 @@ -100,7 +100,7 @@ ** MH-E changes. -Upgraded to MH-E version 7.2. There have been major changes since +Upgraded to MH-E version 7.3. There have been major changes since version 5.0.2; see MH-E-NEWS for details. +++
--- a/lisp/mh-e/ChangeLog Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/ChangeLog Fri Apr 25 05:52:00 2003 +0000 @@ -1,3 +1,1561 @@ +2003-04-24 Bill Wohler <wohler@newt.com> + + * Released MH-E version 7.3. + + * MH-E-NEWS, README: Updated for release 7.3. + + * mh-e.el (Version, mh-version): Updated for release 7.3. + +2003-04-24 Satyaki Das <satyakid@stanford.edu> + + * mh-xemacs-compat.el (mh-utils): Require mh-utils at compile + time, since the mh-do-in-xemacs macro is used. + + * mh-inc.el (cl): Require cl at compile time since we are using + the loop and setf macros. + +2003-04-24 Satyaki Das <satyakid@stanford.edu> + + * mh-unit.el (mh-files): Fix the list of files to check. + +2003-04-24 Bill Wohler <wohler@newt.com> + + * ChangeLog: Appended copyright to end of file. + + * Makefile: Added copyright and license. + + * README: Added copyright. + + * import-emacs: Changed copyright from Newt Software to Bill + Wohler and use license from mh-e.el, except that this file is + a part of MH-E, not GNU Emacs. + + * mh-alias.el: Updated copyright so that it doesn't wrap upon + advice from Richard Stallman who said to use two-digit years when + they are surrounded by 4-digit years that are in the same century + and to break up copyrights on multiple lines. + * mh-comp.el: Ditto. + * mh-e.el: Ditto. + * mh-funcs.el: Ditto. + * mh-identity.el: Ditto. + * mh-mime.el: Ditto. + * mh-seq.el: Ditto. + * mh-utils.el: Ditto. + * mh-xemacs-compat.el: Ditto. + + * mh-unit.el: New file. Unit tests for MH-E. This version merely + runs checkdoc and lm-verify which is useful before releasing the + software. It can and should be expanded to do real unit tests. + +2003-04-22 Mark D Baushke <mdb@gnu.org> + + * mh-alias.el: Update Copyright. + * mh-comp.el: Ditto. + * mh-customize.el: Ditto. + * mh-e.el: Ditto. + * mh-funcs.el: Ditto. + * mh-identity.el: Ditto. + * mh-index.el: Ditto. + * mh-mime.el: Ditto. + * mh-pick.el: Ditto. + * mh-seq.el: Ditto. + * mh-speed.el: Ditto. + * mh-utils.el: Ditto. + * mh-xemacs-compat.el: Ditto. + +2003-04-22 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-normalize-folder-name): Make the completion + code work properly with XEmacs. This change is neeeded since + split-string behaves differently in XEmacs than it does in GNU + Emacs. + (mh-exec-cmd-error): Add a comment, so that we change it later on. + +2003-04-18 Steve Youngs <youngs@xemacs.org> + + * mh-xemacs-icons.el (mh-xemacs-icons): Provide 'mh-xemacs-icons' + not 'mh-xemacs-toolbar'. + + * mh-xemacs-compat.el (mh-xemacs-toolbar): Remove require, it's + now called 'mh-xemacs-icons' and it is required from + 'mh-customize'. + + * mh-customize.el: Require 'mh-xemacs-icons' instead of + 'mh-xemacs-toolbar'. + +2003-04-17 Peter S Galbraith <psg@debian.org> + + * mh-xemacs-icons.el: New file (renamed from mh-xemacs-toolbar.el). + Holds XEmacs icons. + + * mh-xemacs-toolbar.el: Deleted. + + * Makefile: Incorporate the file renaming. + +2003-04-15 Bill Wohler <wohler@newt.com> + + * mh-comp.el (mh-forward): Pass a list of messages into + mh-compose-and-send-mail instead of msg-or-seq. + (mh-annotate-msg): The previous version called + mh-iterate-on-msg-or-seq in the letter buffer. The new version + simply adds the ability to operate on message lists. Thanks to + Satyaki for the fix and suggestion for passing a list from + mh-forward. + +2003-04-14 Bill Wohler <wohler@newt.com> + + * mh-comp.el (mh-annotate-msg): Updated to handle msg-or-seq for + mh-forward was passing a msg-or-seq to mh-compose-and-send-mail + which in turn passed the msg-or-seq to mh-annotate-msg. In + particular, forwarding a region failed. Note that the msgs + argument in much of mh-comp.el should really be converted to + msg-or-seq accordingly. But not now, unless something is broken as + was the case here. We can revamp after the release. + +2003-04-13 Bill Wohler <wohler@newt.com> + + * mh-funcs.el (mh-kill-folder): Added space after prompt to give + the (yes or no) bit a little elbow room. + + * mh-xemacs-toolbar.el: Removing a copyright is a no-no. + Reinstated Steve's copyright. + +2003-04-12 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-do-in-gnu-emacs, mh-do-in-xemacs): Add + indentation hooks for the macros. + +2003-04-11 Bill Wohler <wohler@newt.com> + + * mh-alias.el, mh-comp.el, mh-customize.el, mh-funcs.el, + mh-identity.el, mh-inc.el, mh-index.el, mh-junk.el, mh-utils.el: + Merged in changes from CVS GNU Emacs. These included the removal + of trailing whitespace. + + * mh-customize.el: The "anti-entropy" check-in. Moved groups + around slightly to reflect commentary. Moved defcustoms around + to preserve alphabetization. Big diff, little content. + (mh-xemacs-use-toolbar-flag): Doc fix. + (mh-xemacs-toolbar-position): Fixed typo in docstring. + (mh-default-folder-list): Updated docstring to reflect new Check + Recipient tag. Also, set type of Address to regexp. + (mh-x-mailer-string): Moved to mh-comp.el where it is used. + + * mh-comp.el (mh-x-mailer-string): Moved here from customize.el. + Not quite sure how it got to mh-customize.el in the first place. + + * mh-e.el (mh-folder-folder-menu): Added Folder -> View New + Messages menu item. + + * mh-utils.el (mh-show-folder-menu): Ditto. + + * mh-inc.el: Added Change Log comment (lm-verify fix). + + * mh-index.el (mh-index-search): Added documentation about prefix + argument for users, in addition to documentation for programmers. + + * mh-mime.el (mh-edit-mhn, mh-edit-mhn, mh-mml-to-mime): Docstring + fixes germaine to the change whereby we now check for MIME + directives before sending. + + * mh-xemacs-toolbar.el: Fixed copyright. Added Change Log comment + (lm-verify fix). Added standard MH-E local variables. Removed + time-stamp stuff. + +2003-04-11 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-seq.el (mh-iterate-on-msg-or-seq): Add a missed comma. + +2003-04-10 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-index.el (mh-index-visit-folder): Prompt before reusing + existing folder buffer. + + * mh-xemacs-toolbar.el (require): Require mh-utils at compile + time to avoid compilation error when doing "make bootstrap" in + CVS Emacs. + + * mh-inc.el (mh-inc-spool-list): Declare it so that a compile + time warning is avoided when doing "make bootstrap" in CVS Emacs. + +2003-04-10 Peter S Galbraith <psg@debian.org> + + * mh-inc.el (mh-inc-spool-generator): Changed to a defun instead + of a defmacro, applying Satyaki's patch. + (mh-inc-spool-def-key): same. + (mh-inc-spool-make): same. + + * mh-utils.el: define-key "I" in mh-show-mode-map for + mh-inc-spool-map. + + * mh-comp.el (mh-modify-header-field): Remove debug message. + +2003-04-10 Peter S Galbraith <psg@debian.org> + + * mh-inc.el (mh-inc-spool-map-help): Default to nil. + (mh-inc-spool-map): Make "?" key display message when + `mh-inc-spool-map-help' is nil (instead of mh-inc-spool-map-help + containing the message). + + * mh-e.el: require mh-inc.el + * mh-e.el: define-key "I" in mh-folder-mode-map for mh-inc-spool-map. + (mh-help-messages): Add help string for "I" key. + +2003-04-09 Peter S Galbraith <psg@debian.org> + + * mh-inc.el: New file. New feature to `inc' mail from various + spool files into different folders. + + * mh-loaddefs.el: Regenerate for mh-inc's mh-inc-spool-list-set. + + * Makefile (MH-E-IMG): Add highlight icon. + (MH-E-SRC): Add mh-inc.el file. + + * mh-customize.el (mh-inc-spool-list): New variable for new + feature to `inc' mail from various spool files into different + folders. + +2003-04-09 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-mail-delivery-buffer): Add a defconst for + mh-mail-delivery-buffer. + + * mh-comp.el (mh-send-letter): Use mh-mail-delivery-buffer. + + * mh-mime.el (mh-small-image-p): Add mh-funcall-if-exists to + avoid compiler warning in GNU Emacs. + +2003-04-08 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-mime.el (mh-small-image-p): Make the function slightly more + error-resistant in XEmacs. + + * mh-seq.el (mh-narrow-to-seq, mh-widen): Update tool-bar-map in + the show buffer if needed. This allows us to display the widen + button in the show buffer only when the folder is narrowed. + + * mh-customize.el (mh-tool-bar-define): Changed so that a + separate tool-bar-map is used in show-mode when folder is + narrowed to a sequence. + +2003-04-08 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-seq.el (mh-iterate-on-msg-or-seq): Reinstate the use of + make-symbol since using gensym causes compiler warnings in CVS + Emacs. + +2003-04-08 Bill Wohler <wohler@newt.com> + + * mh-comp.el (mh-forward): Function didn't handle a region of + messages. Use new function mh-msg-or-seq-to-msg-list to get a list + of messages in all circumstances. Also, use mh-coalesce-msg-list + on message list before submitting to forw since this should always + be done when calling a program to reduce the chance of exceeding + command-line limits. + + * mh-seq.el (mh-iterate-on-msg-or-seq): Backed out previous + change. A nil msg-or-seq should mean no messages, and Satyaki is + going to use gensym instead of make-symbol. + (mh-msg-or-seq-to-msg-list): New function to convert a msg-or-seq + to a list of message numbers. + + * mh-e.el (mh-coalesce-msg-list): Touched up the docstring a + little. + + * mh-funcs.el (mh-print-msg): Can now print regions, message + lists, sequences and, of course, single messages. This version + works a little differently from the old version. Instead of + calling mhl | lpr once on all messages, mhl | lpr is called once + per message in order to put each message's number in the header. + Thanks to Satyaki for some code and ideas. + + * mh-seq.el (mh-iterate-on-msg-or-seq): The argument msg-or-seq + can now be nil which means the current message. Make local symbols + so that local variables don't step on user's symbols (the msgs + symbol got me). + +2003-04-06 Bill Wohler <wohler@newt.com> + + * mh-comp.el (mh-forward): Updated docstrings to indicate that a + list of messages is acceptable as well. + + * mh-e.el (mh-delete-msg, mh-delete-msg-no-motion, mh-refile-msg) + (mh-undo, mh-notate-user-sequences, mh-delete-msg-from-seq): Ditto. + + * mh-funcs.el (mh-copy-msg, mh-print-msg): Ditto. + + * mh-junk.el (mh-junk-blacklist, mh-junk-whitelist): Ditto. + + * mh-seq.el (mh-put-msg-in-seq, mh-iterate-on-msg-or-seq) + (mh-interactive-msg-or-seq): Ditto. + +2003-04-06 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-junk.el (mh-junk-blacklist, mh-junk-whitelist): Call + mh-refile-a-msg and mh-delete-a-msg with nil as the message + number since that is more efficient. + + * mh-seq.el (mh-iterate-on-msg-or-seq): Extended so that it will + handle lists of messages numbers as well. + (mh-put-msg-in-seq): Use mh-iterate-on-msg-or-seq to simplify the + function. + + * mh-funcs.el (mh-copy-msg): Same as above. + + * mh-e.el (mh-refile-msg): Make it more efficient. Using nil in + mh-refile-a-msg avoids needing to re-search-forward to that + message. + (mh-undo): Fix typo in interactive spec. + (mh-notate-user-sequences): Generalize the function to take a + msg-or-seq as argument. + (mh-delete-msg-from-seq): Extend the function so that it is now + able to subtract messages belonging in one sequence from another. + (mh-undo): Unify the region and sequence handling. The message + number branch of the function does extra stuff, so we can't merge + that in. + +2003-04-06 Bill Wohler <wohler@newt.com> + + * mh-comp.el (mh-forward): Use mh-interactive-msg-or-seq. Inserted + consistent verbiage in docstring for msg-or-seq. + (mh-reply): Don't mention default in opening line in all + docstrings. + + * mh-e.el (mh-delete-msg, mh-refile-msg) + (mh-undo, mh-delete-msg-from-seq): Use mh-interactive-msg-or-seq. + Inserted consistent verbiage in docstring for msg-or-seq. In + mh-delete-msg-from-seq, renamed msg-or-region to msg-or-seq. + + * mh-funcs.el (mh-copy-msg, mh-print-msg): Use + mh-interactive-msg-or-seq. Inserted consistent verbiage in + docstring for msg-or-seq. + + * mh-junk.el (mh-junk-blacklist, mh-junk-whitelist): Inserted + consistent verbiage in docstring for msg-or-seq. + + * mh-seq.el (mh-msg-is-in-seq): Don't mention default in opening + line in all docstrings. + (mh-put-msg-in-seq): Use mh-interactive-msg-or-seq. Inserted + consistent verbiage in docstring for msg-or-seq. + + * mh-e.el (mh-delete-msg, mh-delete-msg-no-motion, mh-refile-msg): + Rewritten to use new mh-interactive-msg-or-seq function and + mh-iterate-on-msg-or-seq macro. mh-delete-msg-no-motion gained the + ability to operate on regions. + + * mh-junk.el (mh-junk-blacklist, mh-junk-whitelist): Rewritten to + use new mh-interactive-msg-or-seq function and + mh-iterate-on-msg-or-seq macro thereby gaining the ability to + operate on sequences or regions. + + * mh-seq.el (mh-iterate-on-msg-or-seq): New macro to execute code + on a message, a region of messages, or a sequence. This macro + should be in all functions that operate on messages to provide a + uniform interface. + (mh-interactive-msg-or-seq): New function used in interactive + calls to obtain a message number, region, or sequence. This + function should be in all functions that operate on messages to + provide a uniform interface. + + * mh-utils.el (with-mh-folder-updating, mh-in-show-buffer): Use + 'defun lisp-indent-hook property instead of 1 to fix indentation + of these macros. + +2003-04-05 Peter S Galbraith <psg@debian.org> + + * mh-loaddefs.el: Regenerated. + * mh-funcs.el (mh-ephem-message): autoload. + +2003-04-04 Peter S Galbraith <psg@debian.org> + + * mh-e.el (mh-folder-from-address): Minor Fix. Wrong ending of + `when' block. + +2003-04-04 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-mime.el (mh-mml-directive-present-p): The regexp has been + modified to recognize directives to encrypt/sign messages. + +2003-04-03 Mark D. Baushke <mdb@gnu.org> + + * mh-e.el (mh-folder-from-address): E-mail messages missing the + To: field, but which have a Cc: field should also be handled. + +2003-04-03 Bill Wohler <wohler@newt.com> + + * mh-e.el (mh-inc-folder): Modified the prompt text to read + better. + + * mh-comp.el (mh-forward): Deleted local variable `compose'. + Deleted obsolete setting of mh-{mmh|mml}-compose-insert-flag. + (mh-letter-menu): Use mh-{mmh|mml}-directive-present-p instead of + obsolete. mh-{mmh|mml}-compose-insert-flag. + (mh-letter-mode): Deleted obsolete setting of + mh-{mmh|mml}-compose-insert-flag. + (mh-send-letter): This function now automatically runs the + directive-to-MIME conversion if any directives are detected, + rather than relying on the unreliable + mh-{mmh|mml}-compose-insert-flag variables. Updated docstring + accordingly. + + * mh-identity.el (mh-insert-identity): Use + mh-{mmh|mml}-directive-present-p instead of obsolete. + mh-{mmh|mml}-compose-insert-flag. + + * mh-loaddefs.el: Regenerated. + + * mh-mime.el (mh-mhn-compose-type, mh-mhn-compose-external-type) + (mh-mhn-compose-forw, mh-edit-mhn, mh-mml-to-mime) + (mh-mml-forward-message, mh-mml-attach-file) + (mh-mml-secure-message-sign-pgpmime) + (mh-mml-secure-message-encrypt-pgpmime): Deleted obsolete setting + of mh-{mmh|mml}-compose-insert-flag. + (mh-mml-directive-present-p): Checkdoc fix. + + * mh-utils.el (mh-mhn-compose-insert-flag, + mh-mml-compose-insert-flag): Deleted. Replaced by + mh-{mhn|mml}-directive-present-p. + +2003-04-03 Mark D. Baushke <mdb@gnu.org> + + * mh-e.el (mh-folder-from-address): Fix minor problem with To: + address processing. + + * mh-e.el (mh-folder-from-address): Bugfix match ?+ character not + a "?+" string. + +2003-04-03 Peter S Galbraith <psg@debian.org> + + * mh-e.el (mh-inc-folder): Add second optional argument for the + folder to inc new mail into instead of mh-inbox. + +2003-04-03 Peter S Galbraith <psg@debian.org> + + * mh-e.el (mh-folder-from-address): The first match found in + `mh-default-folder-list' is used. + + * mh-customize.el (mh-default-folder-list): Tweak docs + +2003-04-03 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-loaddefs.el: Regenerated. + + * mh-mime.el (mh-mhn-directive-present-p): New function to test if + a MHN directive is present in the current buffer. + (mh-mml-directive-present-p): New function to test if a MML + directive is present in the current buffer. + + * mh-comp.el (mh-letter-mode): Originally this function checked if + a #forw directive was present and set mh-mhn-compose-insert-flag + to t. The modification generalizes this test so that one of the + variables mh-{mml|mhn}-compose-insert-flag will get set if we have + any sort of MHN or MML directive is already present. + + * mh-seq.el (tool-bar-map): Add a defvar to avoid compiler + warnings in CVS version of GNU Emacs. + + * mh-utils.el (tool-bar-map): Same as above. + + * mh-e.el (tool-bar-map): same as above. + +2003-04-02 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-xemacs-toolbar.el (mh-xemacs-toolbar-toggle-tick-icon): + Change color to match mh-folder-tick-face. + + * highlight.xpm: Same as above. + +2003-04-02 Peter S Galbraith <psg@debian.org> + + * mh-e.el (mh-folder-from-address): Check `mh-default-folder-list' + for cases against the recipient instead of the originator. + + * mh-customize.el (mh-default-folder-list): Add extra boolean flag + to conditionally check the recipient address instead of the + originator. + +2003-04-02 Peter S Galbraith <psg@debian.org> + + * mh-customize.el (mh-folder-tick-face): Change tick highlight + face to a background yellow-green, as suggested by Bill. + +2003-04-01 Peter S Galbraith <psg@debian.org> + + * highlight.xpm: New icon for mh-toggle-tick. + + * mh-xemacs-toolbar.el (mh-xemacs-icon-map): Add tool-bar entry + for mh-toggle-tick. + (mh-xemacs-toolbar-toggle-tick-icon): New constant. + + * mh-customize.el: Add tool-bar entry for mh-toggle-tick. + +2003-03-31 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-loaddefs.el: Regenerated. + + * mh-utils.el (mh-show-narrow-to-tick, mh-show-limit-map) + (mh-show-sequence-menu): Add new interactive function + mh-show-narrow-to-tick callable from the show buffer and arrange + for a key binding and a menu entry. + + * mh-seq.el (mh-narrow-to-tick): New interactive function that + narrows to the tick sequence. + + * mh-e.el (mh-folder-sequence-menu, mh-limit-map): Arrange for a + key binding and a menu entry for mh-narrow-to-tick. + + * mh-comp.el (mh-letter-mode): Enable undo since we could be + reusing a show buffer where undo is disabled (closes SF #712777). + +2003-03-31 Peter S Galbraith <psg@debian.org> + + * mh-e.el (mh-folder-sequence-menu): Add entry for mh-toggle-tick. + + * mh-utils.el (mh-show-sequence-menu): Add entry for + mh-show-toggle-tick. + +2003-03-28 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-seq.el (mh-delete-seq): If the tick sequence is killed with + "S k" then the highlighting wasn't getting removed. The change + fixes this. + +2003-03-27 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-e.el (mh-notate-user-sequences): Extend it so that only the + messages in a part of the folder are notated. + (mh-delete-msg-from-seq): Extend it so that it will delete all + messages in the marked region. + (mh-delete-a-msg-from-seq): New function that deletes a single + message from a sequence. + (mh-clear-text-properties): If there is a ticked unseen message + and the message is removed from the unseen list with "S d" then + unticking the message doesn't change the highlight. This change + fixes this. + +2003-03-27 Peter S Galbraith <psg@debian.org> + + * mh-xemacs-toolbar.el (mh-xemacs-toolbar-*-icon): Use original + 24x24 icons, changing background only. + +2003-03-27 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-junk.el (mh-spamassassin-identify-spammers): Remove unused + variable buffer-exists. + (mh-spamassassin-identify-spammers): Remove unused variable user. + + * mh-customize.el (mh-junk-choose): Tweak it to remove XEmacs + compiler warning. + +2003-03-26 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-seq.el (mh-thread-print-scan-lines): Handling of a boundary + condition when messages from the last source folder had been + removed was incorrect. This caused a folder header to appear + without any messages listed under it. This change fixes this. + (mh-thread-forget-message): Remove the entry from the scan line + table as well. This is needed for proper display of threaded view + of index folders. + +2003-03-26 Bill Wohler <wohler@newt.com> + + * Makefile, README, import-emacs, mh-alias.el, mh-comp.el, + mh-customize.el, mh-e.el, mh-funcs.el, mh-identity.el, + mh-index.el, mh-loaddefs.el, mh-mime.el, mh-pick.el, mh-seq.el, + mh-speed.el, mh-utils.el, mh-xemacs-compat.el, + mh-xemacs-toolbar.el: Removed RCS keywords per Emacs conventions + (closes SF #680731). + + +2003-03-26 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-index.el: Fix commentary to mention that mairix is supported + as well. + + * mh-loaddefs.el: Regenerated. + + * mh-utils.el (mh-show-junk-blacklist, mh-show-junk-whitelist): + Interactive functions callable from the show buffer. + (mh-show-junk-map): Key bindings in show mode. + + * mh-e.el (mh-junk-map): Key bindings to call spam program. + (mh-help-messages): Update help text. + + * mh-customize.el (mh-junk): New customization group for spam + program interface. + (mh-junk-choice, mh-junk-function-alist, mh-junk-choose): + Functions and variables that decide which junk program is used. + (mh-junk-program, mh-junk-mail-folder): User customizable + variables that control the choice of spam program and the action + performed on received spam. + + * Makefile (MH-E-SRC): Add mh-junk.el. + +2003-03-26 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-loaddefs.el: Regenerated. + + * mh-utils.el (mh-show-toggle-tick, mh-show-mode-map): New + interactive function callable from the show buffer and a key + binding for it. + + * mh-seq.el (mh-delete-seq): Remove highlight from tick sequence. + (mh-put-msg-in-seq): Disable adding messages to tick sequence. + (mh-widen): Reset mh-tick-seq-changed-when-narrowed-flag. + (mh-tick-add-overlay, mh-tick-remove-overlay, mh-notate-tick) + (mh-toggle-tick): New functions to highlight/unhighlight tick + sequence and the interactive function that is used to toggle + tick. + + * mh-e.el (mh-tick-seq-changed-when-narrowed-flag): New variable + that remembers if we are narrowed to the tick sequence. In that + case the highlighting isn't shown, since it adds no extra info. + (mh-folder-mode): Initialize mh-tick-seq-changed-when-narrowed-flag. + (mh-notate-user-sequences): Notate the tick sequence. + (mh-internal-seq): Treat mh-tick-seq like an internal sequence. + (mh-delete-msg-from-seq): Don't allow deletion from tick sequence. + (mh-folder-mode-map): Add key binding for "'" + + * mh-customize.el (mh-tick-seq, mh-folder-tick-face): New + customizable variables that contain the name of the tick sequence + and the face to use to highlight it. + +2003-03-25 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-loaddefs.el: Regenerated. + + * mh-seq.el (mh-thread-print-scan-lines): New function which + prints out thread tree. It maintains the original folder info if + the folder was created by index search (closes SF #709672). + (mh-copy-seq-to-eob, mh-thread-inc, mh-thread-folder): Use + factored out function mh-thread-print-scan-lines. + (mh-toggle-threads): Since threading is allowed in index folders + there can be lines in the folder which aren't valid message scan + lines. So it is OK for mh-get-msg-num to fail once in a while. + + * mh-index.el (mh-index-update-maps): Make the parsing of messages + that need to annotated with the X-MHE-Checksum header more robust. + If the search yielded no results then an error was being produced. + (mh-index-search): Enable automatic threading of index folders if + mh-show-threads-flag is non-nil (closes SF #709667). + (mh-index-next-folder): Relax error checking since index folder + can be threaded while the source folder info is visible. + (mh-index-group-by-folder): New function that is used in + mh-thread-folder to keep source folder info visible during + threading. + +2003-03-25 Bill Wohler <wohler@newt.com> + + * mh-loaddefs.el: Regenerated. + + * mh-customize.el (mh-index-new-messages-folders): New variable + that controls which folders "F n (mh-index-new-messages)" + accesses. Was mh-flists-search-folders. + + * mh-index.el (mh-flists-search-folders): Still used internally, + but users now use new option mh-index-new-messages-folders. + Removed documentation since to avoid duplication with + mh-index-new-messages-folders. + (mh-flists-recursive-search-flag): Deleted. Use + mh-recursive-folders-flag instead. + (mh-flists-execute): Updated docs to specify which global + variables are used. Use mh-recursive-folders-flag instead of + mh-flists-recursive-search-flag. + (mh-index-new-messages): Edited doc, and refer to new option + mh-index-new-messages-folders. Ditto within code. Don't need to + prepend + to folder name as flists does that for us. Use + +2003-03-24 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-e.el (mh-refile-msg): Add optional argument that controls + whether mh-last-destination-folder is updated or not. + +2003-03-22 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-customize.el (mh-tool-bar-define): Fix a problem in the + XEmacs version which caused the show mode toolbar to have the + buttons in the reverse order. Also the add-hooks are no longer + needed since mh-toolbar-init is called in the appropriate modes. + + * mh-comp.el (mh-letter-mode): Call mh-toolbar-init in XEmacs to + initialize toolbar. + + * mh-utils.el (mh-show-mode): Same as above. + + * mh-e.el (mh-folder-mode): Same as above. + +2003-03-21 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-exec-cmd-env-daemon): New function which + executes a command asynchronously with its own environment. + + * mh-comp.el (mh-redistribute): The function has been modified so + that /bin/sh isn't used to run send. It has also been refactored + so that the same code isn't repeated. + +2003-03-21 Bill Wohler <wohler@newt.com> + + * mh-customize.el (mh-invisible-header-fields): Added X-Bogosity + for bogofilter. + +2003-03-21 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-loaddefs.el: Regenerated. + + * mh-xemacs-toolbar.el: Remove the code since that gets generated + when mh-tool-bar-define is expanded. + (mh-xemacs-icon-map): A alist to map GNU Emacs icon names to the + actual icons to be used in XEmacs. This is used in + mh-tool-bar-define. + + * mh-customize.el (mh-toolbar): Use this group in XEmacs as well. + (mh-tool-bar-item-*): All these constants have been removed since + they aren't needed in the new scheme. + (mh-tool-bar-reply-3-buttons-flag): This variable has been + removed. + (mh-tool-bar-search-function): This is now used in XEmacs as well. + (mh-tool-bar-folder-set, mh-tool-bar-folder-buttons-set) + (mh-tool-bar-letter-buttons-set, mh-tool-bar-show-set) + (mh-tool-bar-letter-set): These functions aren't defined at the + top level any more. + (mh-tool-bar-reply-generator): A macro to generate the required + functions for the three reply buttons. + (mh-tool-bar-search, mh-tool-bar-customize) + (mh-tool-bar-folder-help, mh-tool-bar-letter-help) + (mh-tool-bar-reply-from, mh-show-tool-bar-reply-from) + (mh-tool-bar-reply-to, mh-show-tool-bar-reply-to) + (mh-tool-bar-reply-all, mh-show-tool-bar-reply-all): New + interactive functions that are called when tool bar buttons are + clicked. + (mh-xemacs-use-toolbar-flag, mh-xemacs-toolbar-position): + Additional customizable variables that are present only for + XEmacs. + (mh-tool-bar-define): A macro that generates the required code + for GNU Emacs and XEmacs tool bar. + (mh-tool-bar-define): Define the MH-E tool bar. + +2003-03-17 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-seq.el (mh-notate-cur): Notate current message only if it + hasn't been marked for deletion or refiling. + +2003-03-15 Bill Wohler <wohler@newt.com> + + * mh-customize.el (mh-invisible-header-fields): Added + X-Spam-Checker-Version. + (mh-auto-fields-list): checkdoc fix. + +2003-03-12 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-index.el (mh-index-new-messages): If the destination folder + where the unseen messages are supposed to be copied to was + already present, but MH-E doesn't have it open, then a new folder + was being created. The change fixes this. + (mh-index-update-unseen, mh-flists-recursive-search-flag): Fix + checkdoc warnings. + + * mh-loaddefs.el: Regenerated. + +2003-03-11 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-index.el (mh-flists-results-folder): Subfolder under + +mhe-index where the results of the flists call is put. + (mh-index-generate-pretty-name): Make sure that normal index + searching will never use the folder reserved for the flists + results. + (mh-index-search): Add an extra parameter that marks all the + messages in the index folder to the unseen sequence. + (mh-index-update-unseen): Function to keep unseen sequence of + index folder synced with the actual folders from where the + messages were copied. This works only if the unseen messages are + displayed with mh-show. Killing the unseen sequence in the index + folder or adding/removing messages to it doesn't change the + unseen sequence in the source folders yet. + (mh-flists-search-folders): Variable that decides the folders on + which flists is run. + (mh-flists-recursive-search-flag): If non-nil, flists is passed + the -recurse option. + (mh-flists-execute): Function which uses /bin/sh to execute + flists and then print out the list of message files that match. + (mh-index-new-messages): New interactive function which searches + for messages in the unseen sequence (closes SF #701756). + + * mh-utils.el (mh-show-folder-map): Add binding for + mh-index-new-messages. + (mh-show-msg): Update the unseen sequence in the source folder. + + * mh-e.el (mh-folder-font-lock-unseen): The function assumes that + the end of buffer is reached when there isn't a valid scan line + on the current line. This doesn't work in the index folder since + we have lines containing the folder name and empty lines in + between the actual scan lines. The modification removes this + assumption. + (mh-folder-map): Add key binding for "Fn" + + * mh-seq.el (mh-iterate-on-messages-in-region): If the point is + not at the beginning of the line, then the first message in the + region would be missed. The fix avoids this. + + * mh-mime.el (mh-inline-vcard-p): Don't try to inline vcards if + we don't have the right libraries. + +2003-03-10 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-e.el (mh-next-undeleted-msg, mh-previous-undeleted-msg) + (mh-next-msg): Add optional argument wait-after-complaining-flag. + If non-nil and there are no undeleted messages after (or before) + the current one, then pause for a second after printing out the + message. + (mh-refile-or-write-again): Modify call to mh-next-msg to use the + wait-after-complaining-flag. + +2003-03-10 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-e.el (mh-refile-or-write-again): If mh-next-msg fails to find + a message to go to it prints out a diagnostic, which overwrites + the diagnostic about the folder the message was refiled to. The + change fixes this. + +2003-03-09 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-seq.el (mh-widen, mh-narrow-to-seq): Update + mh-narrowed-to-seq before notating sequences. This is a bit + helpful for mh-tick.el. + (mh-put-msg-in-seq): Fix a minor bug. No internal sequence should + be notated -- the original code was doing the right thing only for + the "unseen" sequence. + + * mh-index.el (mh-index-choose): Add autoload cookie for + mh-index-choose. This is needed for GNU Emacs 20.5. + + * mh-loaddefs.el: Regenerated. + +2003-03-09 Bill Wohler <wohler@newt.com> + + * mh-mime.el (mh-display-smileys): This function originally had a + test to see if font-lock-maximum-size was bound, but this was + recently removed. The test was put in for a reason; if + font-lock-maximum-size isn't bound, void-variable errors would + ensue. I put the bound test back in. + +2003-03-08 Steve Youngs <youngs@xemacs.org> + + * mh-mime.el (mh-mime-security-button-map): Use 'mh-push-button' + in XEmacs as well. + +2003-03-07 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-xemacs-toolbar.el: Declare a whole bunch of stuff for GNU + Emacs, so that we don't get so many compiler warnings. Also + surround calls to set-specifier and toolbar-make-button-list with + mh-funcall-if-exists. Maybe GNU Emacs shouldn't try to compile + this file in the first place. + + * mh-xemacs-compat.el (mh-modeline-glyph): Declare it within + mh-do-in-xemacs to avoid compiler warning in GNU Emacs. + (mh-xemacs-push-button): Removed. + + * mh-mime.el (mh-mime-button-map): Use the generalized + mh-push-button function. + (mh-push-button): Enhance it so that it works on XEmacs too. + +2003-03-08 Steve Youngs <youngs@xemacs.org> + + * mh-xemacs-compat.el (mh-modeline-logo): New constant holding the + modeline image. + (mh-modeline-glyph): Use it. + +2003-03-08 Steve Youngs <youngs@xemacs.org> + + * mh-xemacs-toolbar.el: New file that defines and displays a + toolbar in XEmacs. + + * mh-xemacs-compat.el (mh-xemacs-toolbar): Require it here. + + * Makefile (MH-E-SRC): Add mh-xemacs-toolbar.el. + + * mh-customize.el (mh-toolbar): + (mh-tool-bar-letter-buttons): + (mh-tool-bar-letter-buttons-set): + (mh-tool-bar-folder-buttons): + (mh-tool-bar-folder-buttons-set): + (mh-tool-bar-search-function): + (mh-tool-bar-reply-3-buttons-flag): + (mh-tool-bar-item-inc): + (mh-tool-bar-item-save-mime): + (mh-tool-bar-item-prev-msg): + (mh-tool-bar-item-page-msg): + (mh-tool-bar-item-next-msg): + (mh-tool-bar-item-delete): + (mh-tool-bar-item-refile): + (mh-tool-bar-item-undo): + (mh-tool-bar-item-perform): + (mh-tool-bar-item-toggle-show): + (mh-tool-bar-item-reply-from): + (mh-tool-bar-item-reply-to): + (mh-tool-bar-item-reply-all): + (mh-tool-bar-item-reply): + (mh-tool-bar-item-alias): + (mh-tool-bar-item-compose): + (mh-tool-bar-item-rescan): + (mh-tool-bar-item-repack): + (mh-tool-bar-item-search): + (mh-tool-bar-item-visit): + (mh-tool-bar-item-prefs): + (mh-tool-bar-item-help): + (mh-tool-bar-item-widen): + (mh-tool-bar-item-send): + (mh-tool-bar-item-attach): + (mh-tool-bar-item-spell): + (mh-tool-bar-item-save): + (mh-tool-bar-item-undo-op): + (mh-tool-bar-item-kill): + (mh-tool-bar-item-copy): + (mh-tool-bar-item-paste): + (mh-tool-bar-item-kill-draft): + (mh-tool-bar-item-comp-prefs): + The MH-E toolbar for XEmacs is defined differently from the + GNU/Emacs version, so only define these if we're in GNU/Emacs. + XEmacs doesn't need to see them and it's always good to cut down + on pollution. + +2003-03-08 Steve Youngs <youngs@xemacs.org> + + * mh-mime.el (mh-mime-button-map): Bind the 2nd mouse button to + `mh-xemacs-push-button' in XEmacs. + (mh-mime-security-button-map): Ditto. + + * mh-xemacs-compat.el: Shush the byte-compiler. + (mh-xemacs-push-button): New function to make MIME buttons work in + XEmacs. + +2003-03-08 Steve Youngs <youngs@xemacs.org> + + * mh-mime.el (mh-display-emphasis): Don't test + `font-lock-maximum-size' to see if it is bound, just test for a + non-nil value. This variable can have a nil value which makes it + bound and dividing nil by 8 throws an error. + This fixes a bug in MH-E under XEmacs when + `font-lock-maximum-size' is nil that prevented article emphasis + and smiley display which in turn was causing the "Flush changes in + article x y/n" errors. + (mh-display-smileys): Ditto. + +2003-03-08 Steve Youngs <youngs@xemacs.org> + + * mh-utils.el (mh-logo-display): Display logo in XEmacs as well. + + * mh-xemacs-compat.el (mh-modeline-glyph): New. The MH-E modeline + logo for XEmacs. + +2003-03-06 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-allow-root-folder-flag): New global variable + that decides if "+" is an acceptable folder name. + (mh-folder-completion-function): Refine the test for existing + folders to take mh-allow-root-folder-flag into account. + (mh-folder-completing-read, mh-prompt-for-folder): Use the + allow-root-folder-flag argument of mh-prompt-for-folder and add a + similar argument to mh-folder-completing-read. + (mh-exec-cmd-error): Make the function nicer by using + process-environment to pass the environment variable assignments. + +2003-03-05 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-mime.el (mh-push-button): Preserve point in the show buffer + if the mouse is used to expand/contract a button. + + * mh-customize.el (mh-x-face-file): Mention X-Image-URL in + documentation. + + * mh-comp.el (mh-insert-x-face): Modified to allow insertion of + X-Image-URL header field. + +2003-03-04 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-face-display-function): Modified to facilitate + display of X-Image-URL images. + (mh-find-path): Initialize X-Image-URL cache directory. + (mh-x-image-url-cache-canonicalize, mh-x-image-url-fetch-image) + (mh-x-image-scale-and-display, mh-x-image-url-display) + (mh-x-image-display): New functions for X-Image-URL image display + and cache management. + + * mh-customize.el (mh-show-use-xface-flag): Add info about + requirements for X-Image-URL display. + (mh-fetch-x-image-url): New customizable variable that controls + fetching of X-Image-URL. + +2003-03-04 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-make-local-hook): New macro which works around + API changes in add-hook. Version of GNU Emacs before 21.1 and + XEmacs require a call to make-local-hook and just the LOCAL + argument of add-hook is not sufficient. + (mh-show-mode): Make kill-buffer-hook buffer local. + + * mh-e.el (mh-folder-mode): Same as above. + + * mh-comp.el (mh-compose-and-send-mail): Same as above. + +2003-03-02 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-mime.el (mh-push-button): Clicking on a MIME button used to + cause the window with the show buffer to be selected. With this + change the selected window doesn't change. + +2003-03-01 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-speed.el (mh-speed-flists): Avoid a potential race condition. + When flists is called manually, or when an unseen message is read, + mh-speed-partial-line was not reinitialized. + + * mh-e.el (mh-visit-folder): If mh-visit-folder is used to visit + the folder currently being visited (effectively doing a rescan) + then mh-previous-window-config is erroneously set. The change + fixes this. + + * mh-customize.el (mh-index-show-hook): Remove unused variable. + +2003-02-28 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-e.el (mh-scan-folder): Call mh-reset-threads-and-narrowing + only after the user has replied to question. This avoids premature + clearing of the folder. + (mh-rescan-folder, mh-visit-folder): Remove calls to + mh-reset-threads-and-narrowing since it is now called in + mh-scan-folder anyway. + + * mh-funcs.el (mh-sort-folder): Same as above. + +2003-02-26 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-alias.el (mh-alias-alist): Change initial value to a symbol, + so that it is different from the empty list, which could also + mean that there are no aliases. + (mh-alias-reload-maybe): Change test so that empty alist of + aliases is properly handled (closes SF #693859). + +2003-02-25 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-mime.el (mh-decode-message-header): The message header could + be encoded, for instance the author's name could contain + characters not in ASCII. This function will decode such header + fields. + (mh-mm-inline-message): Use mh-decode-message-header. + + * mh-utils.el (mh-display-msg): Use mh-decode-message-header. + (mh-message-number-width): Use mh-scan-prog instead of "scan". + + * mh-loaddefs.el: Regenerated. + +2003-02-24 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-truncate-log-buffer): Refine it so that the + function will do the right thing even if called from a buffer + other than mh-log-buffer. + +2003-02-22 Peter S Galbraith <psg@debian.org> + + * mh-alias.el (mh-alias-add-alias): Really fix SF #690216. + This functions needs to strip brackets on standalone addresses as + well. + +2003-02-21 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-xemacs-compat.el (replace-regexp-in-string): Remove the + definition since it isn't used any more. + +2003-02-20 Peter S Galbraith <psg@debian.org> + + * mh-alias.el (mh-alias-which-file-has-alias): Bug fix. Needed to + specify `noerror' on search. + + * mh-alias.el (mh-alias-suggest-alias): Add condition for input + string being an email address in brackets. We need to strip out + the brackets. (closes SF #690216) + +2003-02-20 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-pick.el (mh-search-folder): The function was setting the + global value of the variables mh-current-folder and + mh-previous-window-config. This can lead to problems in code which + assumes that these variables are nil when we aren't in a folder + buffer. So make the variables local before setting them. + +2003-02-19 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-mime.el (mh-mime-display): All the MIME display code has been + wrapped in a condition-case so that if something goes wrong, the + raw message will be displayed. + + * mh-funcs.el (mh-undo-folder): Comment out call to sit-for that + seems unnecessary. + + * mh-e.el (mh-scan-folder): Messages marked for deletion or + refiling weren't getting annotated properly. The change fixes + this. + (mh-process-or-undo-commands): Change prompt to reflect what + really happens in the code. + +2003-02-18 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-comp.el (mh-folder-expand-at-point): The function + mail-abbrev-complete-alias often returns nil. This had the + unfortunate consequence of always causing an error. The change + fixes this. + + * mh-alias.el (mh-alias-canonicalize-suggestion): New function + which obviates the our need replace-regexp-in-string. + (mh-alias-suggest-alias): Use mh-alias-canonicalize-suggestion to + eliminate calls to replace-regexp-in-string. This avoids problems + in Emacs20. + + * mh-utils.el (mh-notate): Handle the case when nil is passed as + notation gracefully. + (mh-speed-flists-active-p): New function that returns non-nil if + flists is being used in the speedbar to update message counts. + + * mh-seq.el (mh-put-msg-in-seq): Fix a bug which made it + impossible to add messages to the unseen sequence. Also adding + messages to the unseen sequence will now update the speedbar + message counts immediately. + + * mh-e.el (mh-get-new-mail, mh-process-commands) + (mh-undefine-sequence): Update speedbar message counts, if the + speedbar is active and is displaying message counts. + (mh-delete-msg-from-seq): In addition to updating message counts, + unhighlight the message so that interactively removing messages + from the unseen sequence makes the bold highlight of unseen + messages in the scan buffer go away. + (mh-clear-text-properties): New function that removes all text + properties from the current scan line. + +2003-02-15 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-face-display-function): Wrap call of + insert-image in mh-funcall-if-exists. This avoids a compiler + warning in Emacs20. + + * mh-speed.el (mh-speed-flists): Weaken test a bit to avoid + compiler warning in Emacs20. + (mh-speedbar-change-expand-button-char): Wrap call of + speedbar-insert-image-button-maybe in mh-funcall-if-exists. This + function isn't present in the speedbar that ships with Emacs20, so + calling it there causes an error. + + * mh-seq.el (mh-msg-is-in-seq): Adjust loop call a bit to avoid + compiler warning in XEmacs. The XEmacs compiler should be improved + so that such spurious warnings from builtin macros are suppressed. + + * mh-index.el (mh-index-search): Same as above. + + * mh-e.el (tool-bar-mode): The declaration is needed for Emacs20 + too. + + * mh-comp.el (mailabbrev): Try loading it any way. Some day XEmacs + will get it and then MH-E will just use it. + (tool-bar-mode, tool-bar-map): These declarations are needed for + Emacs20 too. + (mh-mail-abbrev-make-syntax-table, mh-folder-expand-at-point): + Remove mh-mail-abbrev-make-syntax-table since mh-funcall-if-exists + can be used instead. + + * mh-alias.el (require): Avoid autoloading functions that may not + be defined. + (mh-read-address, mh-alias-letter-expand-alias): Rewrite using + mh-funcall-if-exists. + +2003-02-15 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-loaddefs.el: Regenerated. + + * mh-speed.el (mh-folder-speedbar-buttons, mh-speed-add-buttons) + (mh-speed-toggle): Reuse markers instead of creating more of them. + (mh-speed-flists-folder, mh-speed-flists): Add optional folder + argument to mh-speed-flists so that message counts are updated + only for that one folder. + (mh-speed-parse-flists-output): If no change in counts then avoid + consing. + + * mh-index.el (mh-index-execute): Rewritten to use a temporary + buffer that is not left behind. + + * mh-funcs.el (mh-store-buffer): Use mh-log-buffer instead of the + special purpose *Store Output* buffer. + +2003-02-14 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-customize.el (mh-show-xface-face): Make it always be black + foreground on a white background (the reverse of that can make + some X-Face images look creepy). + + * mh-utils.el (mh-truncate-log-buffer): Modify the function to + return the current size of mh-log-buffer. Also we are now a bit + more careful in adding separators between consecutive messages. + (mh-exec-cmd): Fix a bug where the the log buffer would be + displayed even if no error happened in the current command but + the log buffer had messages from a previous error. + + * mh-mime.el (mh-mime-save-parts): Use mh-log-buffer to show + error messages. + + * mh-alias.el (mh-alias-local-users): Add a space between parens. + +2003-02-14 Steve Youngs <youngs@xemacs.org> + + * mh-utils.el (mh-face-display-function): Call + `x-face-xmas-wl-display-x-face' using `mh-funcall-if-exists'. + + * mh-xemacs-compat.el (replace-regexp-in-string): New. + +2003-02-13 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-log-buffer-lines): New variable that keeps + track of the number of lines to keep in mh-log-buffer. + (mh-truncate-log-buffer): New function that is used to make sure + that the log buffer doesn't grow to unbounded size. + (mh-exec-cmd, mh-exec-cmd-daemon, mh-handle-process-error): Use + mh-truncate-log-buffer instead of erase-buffer to keep some + number of previous log messages around (closes SF #685476). + +2003-02-13 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-e.el (tool-bar-mode): Declare it in XEmacs. + (mh-folder-mode): Use mh-funcall-if-exists to call hl-line-mode. + + * mh-utils.el (mh-funcall-if-exists): New macro that calls a + function only if it exists. + (mh-logo-display, mh-defun-show-buffer): Use mh-funcall-if-exists + to call the functions find-image and deactivate-mark. + + * mh-mime.el (mh-mime-cleanup, mh-small-image-p) + (mh-mm-display-part): Use mh-funcall-if-exists to call the + functions image-size and remove-images. + + * mh-comp.el (tool-bar-map, tool-bar-mode): Declare the variables + in XEmacs. + (mh-folder-expand-at-point): Use mh-funcall-if-exists to call + mail-abbrev-complete-alias if it exists. + + * mh-alias.el (mh-read-address): Use mh-funcall-if-exists for + future extensibility. + +2003-02-13 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-logo-display): The function find-image is + present only in GNU Emacs. + (mh-defun-show-buffer): The function deactivate-mark is present + only in GNU Emacs. + (default-enable-multibyte-characters): Declare it in XEmacs to + avoid compiler warning. + (mh-face-display-function): Avoid inserting space if there isn't + any Face or X-Face header field to display. + + * mh-seq.el (mh-thread-last-ancestor): Move declaration of + variable before its first use to silence XEmacs warning. + + * mh-mime.el (default-enable-multibyte-characters, dots, type): + Declare these in XEmacs to remove compiler warnings in XEmacs. + (mh-mime-cleanup, mh-mm-display-part): Call remove-images only in + GNU Emacs. + (mh-small-image-p): Call image-size only in GNU Emacs. + + * mh-index.el (mh-mairix-next-result): Fix a bug where a quote + was missing. + (mh-swish++-regexp-builder): Remove the unused binding meta. + + * mh-e.el (mh-folder-size): Pass on an extra value to remove + XEmacs warning. + (mh-folder-mode): Surround calls to hl-line-mode and + tool-bar-mode with mh-do-in-gnu-emacs since these functions + aren't present in XEmacs. + + * mh-customize.el (mh-tool-bar-show-set, mh-tool-bar-letter-set) + (mh-tool-bar-folder-set): These functions call tool-bar-* + functions which are present only in GNU Emacs. So surround them + with mh-do-in-gnu-emacs. + + * mh-comp.el (mh-letter-mode, mh-folder-expand-at-point): Only + call these functions in GNU Emacs. + (mail-abbrevs): Declare it in XEmacs. + + * mh-alias.el (mh-read-address): Call completing-read-multiple + only in GNU Emacs. + (mail-abbrevs): Declare it in XEmacs. + (mh-alias-add-alias-to-file): Remove unused code. + +2003-02-14 Ville Skyttä <scop@xemacs.org> + + * mh-comp.el: Add autoloaded auto-mode-alist association. + +2003-02-13 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-face-display-function): Make the XEmacs part a + little simpler. + +2003-02-14 Steve Youngs <youngs@xemacs.org> + + * mh-customize.el (mh-show-xface-face): XEmacs doesn't have the + ':inherit' keyword for defface, rewrite with sane defaults. + + * mh-utils.el (mh-face-display-function): Fix bug that was + corrupting xface images when displayed with XEmacs' internal + xface image support. Also make XEmacs honour 'mh-show-xface-face' + when using internal xface image support. + +2003-02-12 Peter S Galbraith <psg@debian.org> + + * mh-comp.el (mh-modify-header-field): New function. To header + FIELD add VALUE. If OVERWRITE-FLAG is non-nil then the old value, + if present, is discarded. This is more flexible than before. + (mh-insert-auto-fields): Use it. This and the new function are a + courtesy of Satyaki. Thanks! + + * mh-customize.el (mh-auto-fields-list): Doc tweaks suggested by + Bill. + +2003-02-12 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-comp.el (mh-folder-expand-at-point): Tweak the error + message. Completion in the Fcc header field is only supported in + GNU Emacs 21. + +2003-02-12 Peter S Galbraith <psg@debian.org> + + * mh-customize.el (mh-auto-fields-list): Reorder after + `mh-identity-list' since it needs it to be defined. Move to + mh-identity customization group. + +2003-02-11 Peter S Galbraith <psg@debian.org> + + * mh-customize.el (mh-insert-mail-followup-to-flag): Removed. + Obsolete. + (mh-insert-mail-followup-to-list): Removed. Obsolete. Use + `mh-auto-fields-list' instead, which is a more general solution. + (mh-auto-fields-list): New defcustom. Alist of addresses for + which header lines are automatically inserted. Replaces + `mh-insert-mail-followup-to-list'. + + * mh-comp.el (mh-insert-mail-followup-to): Removed. Obsolete. + (mh-insert-auto-fields): New function. Insert custom fields if To + or Cc match `mh-auto-fields-list', replacing + mh-insert-mail-followup-to with a more general solution. + (mh-compose-and-send-mail): Call mh-insert-auto-fields instead of + mh-insert-mail-followup-to. Also don't call mh-insert-identity to + insert default setting if mh-insert-auto-fields inserted an + identity. + +2003-02-11 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-show-xface-function): Try to load the external + x-face library only if XEmacs doesn't have xface support. + (mh-face-display-function): Renamed. Also handle various + permutations of x-face and xface support in XEmacs better. + + * mh-customize.el (mh-show-use-xface-flag): Any emacs whose + major version is greater than or equal to 21 supports display of + X-Face and Face header fields. + +2003-02-11 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-do-in-gnu-emacs, mh-do-in-xemacs): Macros that + execute code only in GNU Emacs and XEmacs respectively. + (mh-emacs21-face-display-function): Refactor to make it slightly + nicer. Get rid of compiler warnings in GNU Emacs by using the + above macros. Also check for presence of xface feature (in XEmacs + specific code) before trying to display X-Face header field image. + +2003-02-11 Steve Youngs <youngs@xemacs.org> + + * mh-customize.el (mh-show-use-xface-flag): If using XEmacs and + can't find the external x-face pkg still enable X-Face images if + feature 'xface is present. + Update the doc string. + + * mh-utils.el (mh-emacs21-face-display-function): Make it work in + XEmacs. + (mh-show-xface-function): If using XEmacs without xface support, + use x-face.el pkg. If using XEmacs with xface support, or Emacs + 21, use mh-emacs21-face-display-function. + +2003-02-11 Mark D. Baushke <mdb@gnu.org> + + * mh-customize.el (mh-invisible-header-fields): Add + "X-Notes-Item:" which is generated by Lotus Notes Domino. See + URL<http://www-12.lotus.com/ldd/doc/domino_notes/Rnext/help6_admin.nsf + /f4b82fbb75e942a6852566ac0037f284/5eda03c647f879c285256c1d00396051 + ?OpenDocument&Highlight=0,x-notes-item> for details on how Domino + users may disable (restore the default) generation of these headers. + +2003-02-10 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-comp.el (mh-folder-expand-at-point): Add function doc string + and produce a nicer error message for Emacs versions that lack + mail-abbrev-complete-alias. + + * mh-utils.el (mh-handle-process-error): Check doc fix. + + * mh-e.el (mh-folder-from-address): Same as above. + +2003-02-10 Peter S Galbraith <psg@debian.org> + + * mh-comp.el: require mailabbrev, except in XEmacs. + (mh-mail-abbrev-make-syntax-table): New defmacro to call + mail-abbrev-make-syntax-table introduced in Emacs21. + (mh-folder-expand-at-point): Handle nested folders. + All of the above was written by Satyaki. I just applied the patch + and tested. + +2003-02-09 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-comp.el: Fixes to keep the byte compiler happy. + + * mh-customize.el (mh-invisible-header-fields): Modified to + remove space after ":" in header field names. + +2003-02-09 Peter S Galbraith <psg@mixed.dyndns.org> + + * mh-comp.el (mh-letter-complete): Add completion for fcc lines. + (mh-folder-expand-at-point): Do completion at point for folder + name. Like `mh-alias-letter-expand-alias' for aliases, it doesn't + work on XEmacs because it relies on `mail-abbrev-complete-alias' + to do completion. Maybe Steve could update XEmacs' mailabbrev.el? + +2003-02-09 Peter S Galbraith <psg@debian.org> + + * mh-customize.el (mh-invisible-header-fields): Remove trailing + space in "X-Face: " and "Face: " entries since those line often + break there. + +2003-02-08 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-emacs21-face-display-function): Use + mh-show-xface-face to colorize X-Face image. + + * mh-customize.el (mh-invisible-header-fields): Add extra headers + to ignore. + (mh-show-xface-face): Allow customization of the X-Face colors. + +2003-02-07 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-uncompface-executable, mh-uncompface): Remember + the path of the uncompface executable so that we don't need to + search for it every time. + (mh-emacs21-face-display-function): If more than one X-Face (or + Face) header field was present then the fields would get + concatenated, leading to garbled output. The change only displays + the first image. + + * mh-customize.el (mh-x-face-file): Change documentation since it + can now be used to insert a Face header field. + + * mh-comp.el (mh-insert-x-face): Generalized to allow insertion + of Face header field. + +2003-02-06 Bill Wohler <wohler@newt.com> + + * mh-utils.el (mh-emacs21-face-display-function): Updated + docstring. It is a common mistake to refer to a header field as a + header. The term header refers to the entire header while the term + header field refers to a single field. + + * mh-customize.el (mh-show-use-xface-flag): Ditto. + +2003-02-06 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-show-xface-function): Modified to use + mh-emacs21-face-display-function if we are running GNU Emacs 21. + (mh-face-to-png): New function to convert a Face header to a png + image. + (mh-uncompface): New function which converts an X-Face header to + a pbm image. + (mh-icontopbm): New function that does the job of icontopbm. + (mh-emacs21-face-display-function): New function that displays + Face/X-Face image in GNU Emacs 21. + (mh-show-xface): Modified to test if we are running in X. + Otherwise face display is suppressed. + + * mh-customize.el (mh-show-use-xface-flag): Tweak it, now that + MH-E supports face display natively on Emacs 21. Also remove the + check for window-system since it doesn't belong in a customizable + variable. + +2003-02-06 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (sendmail): Require it so that XEmacs can find + rfc822-goto-eoh. + (mh-mail-header-end): A substitute for mail-header-end that + doesn't widen the buffer. This is essential to avoid problems when + dealing with nested messages. + (mh-in-header-p, mh-letter-header-font-lock) + (mh-header-field-font-lock, mh-show-font-lock-fontify-region) + (mh-show-unquote-From): Use mh-mail-header-end instead of + mail-header-end. + + * mh-mime.el (mh-decode-message-body): same as above (closes SF + #681518). + + * mh-comp.el (mh-yank-cur-msg): same as above. + +2003-02-05 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-display-msg): Call mh-show-mode before invisible + headers are cleaned. This means that any surviving X-Face header + can be removed unconditionally in mh-clean-msg-header. + (mh-clean-msg-header): Since the function is now called with a + read-only buffer, make the buffer temporarily writable. + + * mh-mime.el (mh-mm-inline-message): Do X-Face display before + invisible headers are removed. + + * mh-customize.el (mh-invisible-headers): Simplified since the + X-Face header isn't treated specially any more. + (mh-invisible-header-fields): Add Face: and X-Face: to list of + invisible headers. + + * mh-mime.el (mh-mime-display): If body is empty the headers would + be treated like the body. The change fixes this (closes SF #681162). + (mh-mime-display): This change really fixes the above problem. + +2003-02-04 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-current-folder-name): Global variable that + keeps track of current folder. + (mh-normalize-folder-name): Substitute @ with + mh-current-folder-name (closes SF #666774). + (mh-prompt-for-folder): Bind mh-current-folder-name. Also + invalidate cache if we are visiting a folder that wasn't found in + the sub-folder cache. This is an indication that folders may have + been created outside of MH-E and so the cache may be stale. + +2003-02-03 Satyaki Das <satyaki@theforce.stanford.edu> + + * mh-utils.el (mh-decode-content-transfer-encoded-message): Removed. + (mh-display-msg): Remove the use of the above function. + (mh-normalize-folder-name): Leading "/" characters were being + lost. The change fixes this (closes SF #676890). + + * mh-mime.el (mh-decode-message-body): New function, factored out + from mh-mime-display and enhanced, to decode message based on + charset and content-transfer-encoding. This eliminates the need + for the external mimencode (closes SF #674857). + (mh-mime-display): Use mh-decode-message-body. + + * mh-e.el (mh-header-display): Don't need the binding since the + variable isn't present any more. + (mh-inc-folder): Avoid calling mh-show if point is not on a valid + scan line (closes SF #678115). + + * mh-customize.el + (mh-decode-content-transfer-encoded-message-flag): Removed. + +2003-02-03 Bill Wohler <wohler@newt.com> + + * import-emacs: MH-E now has its own directory in Emacs. + + * mh-e.el: (mh-version): Set to 7.2+cvs. + 2003-02-03 Bill Wohler <wohler@newt.com> * Released MH-E version 7.2. @@ -4061,7 +5619,7 @@ Non-fatal depencencies on the mm-decode, mm-uu and mm-view libraries. -2002-07-15 Satyaki Das <satyaki@theforce.stanford.edu> +2002-07-15 Satyaki Das <satyaki@theforce.stanford.edu> * mh-utils.el (mh-require, mh-autoload): Remove these macros. (mh-decode-mime): Initialized to t iff the mm-decode library is @@ -4674,7 +6232,7 @@ (mh-filter-out-non-text): New function to filter out attachments from message being yanked. -2002-05-20 Bill Wohler <Bill.Wohler@openwave.com> +2002-05-20 Bill Wohler <Bill.Wohler@openwave.com> * mh-utils.el (mh-invisible-headers-show-xface): First sentence of docstring was not entirely on first line so was truncated in @@ -6017,3 +7575,10 @@ (install): $MH-E-SRC is copied to $(EMACS_HOME)/lisp/mail, not $(EMACS_HOME)/src. (dist): Leave release in current directory. + + +Copyright (C) 2003 Free Software Foundation, Inc. + +Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved.
--- a/lisp/mh-e/mh-alias.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-alias.el Fri Apr 25 05:52:00 2003 +0000 @@ -1,6 +1,7 @@ ;;; mh-alias.el --- MH-E mail alias completion and expansion ;; -;; Copyright (C) 1994, 1995, 1996, 1997, 2001, 2002 Free Software Foundation, Inc. +;; Copyright (C) 1994, 95, 96, 1997, +;; 2001, 02, 2003 Free Software Foundation, Inc. ;; Author: Peter S. Galbraith <psg@debian.org> ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -93,8 +94,6 @@ ;;; Change Log: -;; $Id: mh-alias.el,v 1.2 2003/02/03 20:55:30 wohler Exp $ - ;;; Code: (require 'mh-e) @@ -103,10 +102,12 @@ (eval-when-compile (defvar mail-abbrev-syntax-table)) ;;; Autoloads -(autoload 'mail-abbrev-complete-alias "mailabbrev") -(autoload 'multi-prompt "multi-prompt") +(eval-when (compile load eval) + (ignore-errors + (require 'mailabbrev) + (require 'multi-prompt))) -(defvar mh-alias-alist nil +(defvar mh-alias-alist 'not-read "Alist of MH aliases.") (defvar mh-alias-blind-alist nil "Alist of MH aliases that are blind lists.") @@ -180,7 +181,7 @@ (insert-file-contents "/etc/passwd"))) ((stringp mh-alias-local-users) (insert mh-alias-local-users "\n") - (shell-command-on-region (point-min)(point-max) mh-alias-local-users t) + (shell-command-on-region (point-min) (point-max) mh-alias-local-users t) (goto-char (point-min)))) (while (< (point) (point-max)) (cond @@ -241,7 +242,7 @@ (defun mh-alias-reload-maybe () "Load new MH aliases." - (if (or (not mh-alias-alist) ; Doesn't exist, so create it. + (if (or (eq mh-alias-alist 'not-read) ; Doesn't exist, so create it. (mh-alias-tstamp nil)) ; Out of date, so recreate it. (mh-alias-reload))) @@ -253,12 +254,16 @@ ALIAS must be a string for a single alias. If USER is t, then assume ALIAS is an address and call ali -user. ali returns the string unchanged if not defined. The same is done here." - (save-excursion - (let ((user-arg (if user "-user" "-nouser"))) - (mh-exec-cmd-quiet t "ali" user-arg "-nolist" alias)) - (goto-char (point-max)) - (if (looking-at "^$") (delete-backward-char 1)) - (buffer-substring (point-min)(point-max)))) + (condition-case err + (save-excursion + (let ((user-arg (if user "-user" "-nouser"))) + (mh-exec-cmd-quiet t "ali" user-arg "-nolist" alias)) + (goto-char (point-max)) + (if (looking-at "^$") (delete-backward-char 1)) + (buffer-substring (point-min)(point-max))) + (error (progn + (message (error-message-string err)) + alias)))) (defun mh-alias-expand (alias) "Return expansion for ALIAS. @@ -280,15 +285,14 @@ (let* ((minibuffer-local-completion-map mh-alias-read-address-map) (completion-ignore-case mh-alias-completion-ignore-case-flag) (the-answer - (or (cond - ((fboundp 'completing-read-multiple) - (completing-read-multiple prompt mh-alias-alist nil nil)) - ((featurep 'multi-prompt) - (multi-prompt "," nil prompt mh-alias-alist nil nil)) - (t - (split-string - (completing-read prompt mh-alias-alist nil nil) - ",")))))) + (cond ((fboundp 'completing-read-multiple) + (mh-funcall-if-exists + completing-read-multiple prompt mh-alias-alist nil nil)) + ((featurep 'multi-prompt) + (mh-funcall-if-exists + multi-prompt "," nil prompt mh-alias-alist nil nil)) + (t (split-string + (completing-read prompt mh-alias-alist nil nil) ","))))) (if (not mh-alias-expand-aliases-flag) (mapconcat 'identity the-answer ", ") ;; Loop over all elements, checking if in passwd aliast or blind first @@ -325,12 +329,14 @@ (message "No alias for %s" the-name)))))) (self-insert-command 1)) +(mh-do-in-xemacs (defvar mail-abbrevs)) + ;;;###mh-autoload (defun mh-alias-letter-expand-alias () "Expand mail alias before point." (mh-alias-reload-maybe) (let ((mail-abbrevs mh-alias-alist)) - (mail-abbrev-complete-alias)) + (mh-funcall-if-exists mail-abbrev-complete-alias)) (when mh-alias-expand-aliases-flag (let* ((end (point)) (syntax-table (syntax-table)) @@ -350,6 +356,9 @@ (defun mh-alias-suggest-alias (string) "Suggest an alias for STRING." (cond + ((string-match "^<\\(.*\\)>$" string) + ;; <somename@foo.bar> -> recurse, stripping brackets. + (mh-alias-suggest-alias (match-string 1 string))) ((string-match "^\\sw+$" string) ;; One word -> downcase it. (downcase string)) @@ -389,9 +398,25 @@ (format "%s %s" (match-string 2 string) (match-string 1 string)))) (t ;; Output string, with spaces replaced by dots. - (downcase (replace-regexp-in-string - "\\.\\.+" "." - (replace-regexp-in-string " +" "." string)))))) + (mh-alias-canonicalize-suggestion string)))) + +(defun mh-alias-canonicalize-suggestion (string) + "Process STRING to replace spacess by periods. +First all spaces are replaced by periods. Then every run of consecutive periods +are replaced with a single period. Finally the string is converted to lower +case." + (with-temp-buffer + (insert string) + ;; Replace spaces with periods + (goto-char (point-min)) + (replace-regexp " +" ".") + ;; Replace consecutive periods with a single period + (goto-char (point-min)) + (replace-regexp "\\.\\.+" ".") + ;; Convert to lower case + (downcase-region (point-min) (point-max)) + ;; Whew! all done... + (buffer-string))) (defun mh-alias-which-file-has-alias (alias file-list) "Return the name of writable file which defines ALIAS from list FILE-LIST." @@ -403,7 +428,7 @@ (erase-buffer) (when (file-writable-p (car file-list)) (insert-file-contents (car file-list)) - (if (re-search-forward (concat "^" (regexp-quote alias) ":")) + (if (re-search-forward (concat "^" (regexp-quote alias) ":") nil t) (setq found (car file-list) the-list nil) (setq the-list (cdr the-list))))) @@ -470,14 +495,18 @@ ;;;###mh-autoload (defun mh-alias-from-has-no-alias-p () - "Return t is From has no current alias set." + "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." (mh-alias-reload-maybe) (save-excursion (if (not (mh-folder-line-matches-show-buffer-p)) nil ;No corresponding show buffer (if (eq major-mode 'mh-folder-mode) (set-buffer mh-show-buffer)) - (not (mh-alias-address-to-alias (mh-extract-from-header-value)))))) + (let ((from-header (mh-extract-from-header-value))) + (and from-header + (not (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. @@ -491,7 +520,6 @@ (goto-char (point-min)) (let ((alias-search (concat alias ":")) (letter) - (here (point)) (case-fold-search t)) (cond ;; Search for exact match (if we had the same alias before) @@ -538,7 +566,11 @@ (interactive "P\nP") (mh-alias-reload-maybe) (setq alias (completing-read "Alias: " mh-alias-alist nil nil alias)) + (if (and address (string-match "^<\\(.*\\)>$" address)) + (setq address (match-string 1 address))) (setq address (read-string "Address: " address)) + (if (string-match "^<\\(.*\\)>$" address) + (setq address (match-string 1 address))) (let ((address-alias (mh-alias-address-to-alias address)) (alias-address (mh-alias-expand alias))) (if (string-equal alias-address alias) @@ -571,7 +603,8 @@ (insert-file-contents (mh-msg-filename (mh-get-msg-num t)))) ((eq major-mode 'mh-folder-mode) (error "Cursor not pointing to a message"))) - (let* ((address (mh-extract-from-header-value)) + (let* ((address (or (mh-extract-from-header-value) + (error "Message has no From: header"))) (alias (mh-alias-suggest-alias address))) (mh-alias-add-alias alias address))))
--- a/lisp/mh-e/mh-comp.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-comp.el Fri Apr 25 05:52:00 2003 +0000 @@ -1,6 +1,7 @@ ;;; mh-comp.el --- MH-E functions for composing messages -;; Copyright (C) 1993,1995,1997,2000,2001,2002 Free Software Foundation, Inc. +;; Copyright (C) 1993, 95, 1997, +;; 2000, 01, 02, 2003 Free Software Foundation, Inc. ;; Author: Bill Wohler <wohler@newt.com> ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -30,14 +31,14 @@ ;;; Change Log: -;; $Id: mh-comp.el,v 1.2 2003/02/03 20:55:30 wohler Exp $ - ;;; Code: (require 'mh-e) (require 'gnus-util) (require 'easymenu) (require 'cl) +(eval-when (compile load eval) + (ignore-errors (require 'mailabbrev))) ;; Shush the byte-compiler (defvar adaptive-fill-first-line-regexp) @@ -309,27 +310,21 @@ ;;;###mh-autoload (defun mh-forward (to cc &optional msg-or-seq) - "Forward one or more messages to the recipients TO and CC. - -Use the optional MSG-OR-SEQ to specify a message or sequence to forward. + "Forward messages to the recipients TO and CC. +Use optional MSG-OR-SEQ argument to specify a message or sequence to forward. +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is forwarded. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence. -Default is the displayed message. If optional prefix argument is given then -prompt for the message sequence. If variable `transient-mark-mode' is non-nil -and the mark is active, then the selected region is forwarded. See also documentation for `\\[mh-send]' function." (interactive (list (mh-read-address "To: ") (mh-read-address "Cc: ") - (cond - ((mh-mark-active-p t) - (mh-region-to-msg-list (region-beginning) (region-end))) - (current-prefix-arg - (mh-read-seq-default "Forward" t)) - (t - (mh-get-msg-num t))))) + (mh-interactive-msg-or-seq "Forward"))) (let* ((folder mh-current-folder) - (msgs (cond ((numberp msg-or-seq) (list msg-or-seq)) - ((listp msg-or-seq) msg-or-seq) - (t (mh-seq-to-msgs msg-or-seq)))) + (msgs (mh-msg-or-seq-to-msg-list msg-or-seq)) (config (current-window-configuration)) (fwd-msg-file (mh-msg-filename (car msgs) folder)) ;; forw always leaves file in "draft" since it doesn't have -draft @@ -337,7 +332,8 @@ (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-current-folder msgs) + mh-current-folder + (mh-coalesce-msg-list msgs)) (prog1 (mh-read-draft "" draft-name t) (mh-insert-fields "To:" to "Cc:" cc) @@ -353,14 +349,12 @@ (setq orig-from (mh-get-header-field "From:")) (setq orig-subject (mh-get-header-field "Subject:"))) (let ((forw-subject - (mh-forwarded-letter-subject orig-from orig-subject)) - (compose)) + (mh-forwarded-letter-subject orig-from orig-subject))) (mh-insert-fields "Subject:" forw-subject) (goto-char (point-min)) ;; If using MML, translate mhn (if (equal mh-compose-insertion 'gnus) (save-excursion - (setq compose t) (re-search-forward (format "^\\(%s\\)?$" mh-mail-header-separator)) (while @@ -386,12 +380,10 @@ (forward-line 1)) (delete-other-windows) (mh-add-msgs-to-seq msgs 'forwarded t) - (mh-compose-and-send-mail draft "" folder msg-or-seq + (mh-compose-and-send-mail draft "" folder msgs to forw-subject cc mh-note-forw "Forwarded:" config) - (if compose - (setq mh-mml-compose-insert-flag t)) (mh-letter-mode-message))))) (defun mh-forwarded-letter-subject (from subject) @@ -439,38 +431,27 @@ (mh-goto-header-end 0) (insert "Resent-To: " to "\n") (if (not (equal cc "")) (insert "Resent-cc: " cc "\n")) - (mh-clean-msg-header (point-min) - "^Message-Id:\\|^Received:\\|^Return-Path:\\|^Sender:\\|^Date:\\|^From:" - nil) + (mh-clean-msg-header + (point-min) + "^Message-Id:\\|^Received:\\|^Return-Path:\\|^Sender:\\|^Date:\\|^From:" + nil) (save-buffer) (message "Redistributing...") - (if (not mh-redist-background) - (if mh-redist-full-contents - (call-process "/bin/sh" nil 0 nil "-c" - (format "mhdist=1 mhaltmsg=%s %s -push %s" - buffer-file-name - (expand-file-name mh-send-prog mh-progs) - buffer-file-name)) - (call-process "/bin/sh" nil 0 nil "-c" - (format - "mhdist=1 mhaltmsg=%s mhannotate=1 %s -push %s" - (mh-msg-filename msg folder) - (expand-file-name mh-send-prog mh-progs) - buffer-file-name)))) - (mh-annotate-msg msg folder mh-note-dist - "-component" "Resent:" - "-text" (format "\"%s %s\"" to cc)) - (if mh-redist-background - (mh-exec-cmd-daemon "/bin/sh" nil "-c" - (format "mhdist=1 mhaltmsg=%s %s %s %s" - (if mh-redist-full-contents - buffer-file-name - (mh-msg-filename msg folder)) - (if mh-redist-full-contents - "" - "mhannotate=1") - (mh-expand-file-name "send" mh-progs) - buffer-file-name))) + (let ((env "mhdist=1")) + ;; Setup environment... + (setq env (concat env " mhaltmsg=" (if mh-redist-full-contents + buffer-file-name + (mh-msg-filename msg folder)))) + (unless mh-redist-full-contents + (setq env (concat env " mhannotate=1"))) + ;; Redistribute... + (if mh-redist-background + (mh-exec-cmd-env-daemon env mh-send-prog nil buffer-file-name) + (mh-exec-cmd-error env mh-send-prog "-push" buffer-file-name)) + ;; Annotate... + (mh-annotate-msg msg folder mh-note-dist + "-component" "Resent:" + "-text" (format "\"%s %s\"" to cc))) (kill-buffer draft) (message "Redistributing...done")))) @@ -501,7 +482,8 @@ ;;;###mh-autoload (defun mh-reply (message &optional reply-to includep) - "Reply to MESSAGE (default: current message). + "Reply to MESSAGE. +Default is the displayed message. If the optional argument REPLY-TO is not given, prompts for type of addresses to reply to: from sender only, @@ -706,14 +688,15 @@ (buffer-substring (point-min) (1- (point-max))))) (defun mh-annotate-msg (msg buffer note &rest args) - "Mark MSG in BUFFER with character NOTE and annotate message with ARGS." - (apply 'mh-exec-cmd "anno" buffer msg args) + "Mark MSG in BUFFER with character NOTE and annotate message with ARGS. +MSG can be a message number, a list of message numbers, or a sequence." + (apply 'mh-exec-cmd "anno" buffer + (if (listp msg) (append msg args) (cons msg args))) (save-excursion (cond ((get-buffer buffer) ; Buffer may be deleted (set-buffer buffer) - (if (numberp msg) - (mh-notate msg note (1+ mh-cmd-note)) - (mh-notate-seq msg note (1+ mh-cmd-note))))))) + (mh-iterate-on-msg-or-seq nil msg + (mh-notate nil note (1+ mh-cmd-note))))))) (defun mh-insert-fields (&rest name-values) "Insert the NAME-VALUES pairs in the current buffer. @@ -776,7 +759,7 @@ "Extract From: string from header." (save-excursion (if (not (mh-goto-header-field "From:")) - (error "No From header line found") + nil (skip-chars-forward " \t") (buffer-substring-no-properties (point) (progn (mh-header-field-end)(point)))))) @@ -812,9 +795,9 @@ ;; 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-compose-insert-flag] + mh-edit-mhn (mh-mhn-directive-present-p)] ["Pull in All Compositions (gnus)" - mh-mml-to-mime mh-mml-compose-insert-flag] + 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])))) @@ -857,6 +840,11 @@ (mail-mode-fill-paragraph arg) (fill-paragraph arg)))) +;; Avoid compiler warnings in XEmacs and Emacs 20 +(eval-when-compile + (defvar tool-bar-mode) + (defvar tool-bar-map)) + ;;;###autoload (define-derived-mode mh-letter-mode text-mode "MH-Letter" "Mode for composing letters in MH-E.\\<mh-letter-mode-map> @@ -918,8 +906,11 @@ (setq paragraph-separate paragraph-start) ;; --- End of code from sendmail.el --- + ;; Enable undo since a show-mode buffer might have been reused. + (buffer-enable-undo) (if (and (boundp 'tool-bar-mode) tool-bar-mode) (set (make-local-variable 'tool-bar-map) mh-letter-tool-bar-map)) + (mh-funcall-if-exists mh-toolbar-init :letter) (make-local-variable 'font-lock-defaults) (cond ((or (equal mh-highlight-citation-p 'font-lock) @@ -933,16 +924,6 @@ ;; ...or the header only (setq font-lock-defaults '(mh-show-font-lock-keywords t)))) (easy-menu-add mh-letter-menu) - ;; See if a "forw: -mime" message containing a MIME composition. - ;; Mode clears local vars, so can't do this in mh-forward. - (save-excursion - (goto-char (point-min)) - (when (and (re-search-forward - (format "^\\(%s\\)?$" mail-header-separator) nil t) - (= 0 (forward-line 1)) - (looking-at "^#forw")) - (require 'mh-mime) ;Need mh-mhn-compose-insert-flag local var - (setq mh-mhn-compose-insert-flag t))) (setq fill-column mh-letter-fill-column) ;; If text-mode-hook turned on auto-fill, tune it for messages (when auto-fill-function @@ -1055,16 +1036,25 @@ ;;; Routines to compose and send a letter. (defun mh-insert-x-face () - "Append X-Face field to header. + "Append X-Face, Face or X-Image-URL field to header. If the field already exists, this function does nothing." (when (and (file-exists-p mh-x-face-file) (file-readable-p mh-x-face-file)) (save-excursion - (when (null (mh-position-on-field "X-Face")) - (insert "X-Face: ") - (goto-char (+ (point) (cadr (insert-file-contents mh-x-face-file)))) - (if (not (looking-at "^")) - (insert "\n")))))) + (unless (or (mh-position-on-field "X-Face") + (mh-position-on-field "Face") + (mh-position-on-field "X-Image-URL")) + (save-excursion + (goto-char (+ (point) (cadr (insert-file-contents mh-x-face-file)))) + (if (not (looking-at "^")) + (insert "\n"))) + (unless (looking-at "\\(X-Face\\|Face\\|X-Image-URL\\): ") + (insert "X-Face: ")))))) + +(defvar mh-x-mailer-string nil + "*String containing the contents of the X-Mailer header field. +If nil, this variable is initialized to show the version of MH-E, Emacs, and +MH the first time a message is composed.") (defun mh-insert-x-mailer () "Append an X-Mailer field to the header. @@ -1116,21 +1106,39 @@ (setq fields (cdr fields)))) search-result))) -(defun mh-insert-mail-followup-to () - "Insert Mail-Followup-To: if To or Cc match `mh-insert-mail-followup-to-list'." +(defun mh-insert-auto-fields () + "Insert custom fields if To or Cc match `mh-auto-fields-list'." (save-excursion - (if (and (or (mh-goto-header-field "To:")(mh-goto-header-field "cc:")) - (not (mh-goto-header-field "Mail-Followup-To: "))) - (let ((list mh-insert-mail-followup-to-list)) - (while list - (let ((regexp (nth 0 (car list))) - (entry (nth 1 (car list)))) - (when (mh-regexp-in-field-p regexp "To:" "cc:") - (if (mh-goto-header-field "Mail-Followup-To: ") - (insert entry ", ") - (mh-goto-header-end 0) - (insert "Mail-Followup-To: " entry "\n"))) - (setq list (cdr list)))))))) + (when (and (or (mh-goto-header-field "To:")(mh-goto-header-field "cc:"))) + (let ((list mh-auto-fields-list)) + (while list + (let ((regexp (nth 0 (car list))) + (entries (nth 1 (car list)))) + (when (mh-regexp-in-field-p regexp "To:" "cc:") + (let ((entry-list entries)) + (while entry-list + (let ((field (caar entry-list)) + (value (cdar entry-list))) + (cond + ((equal "identity" field) + (when (assoc value mh-identity-list) + (mh-insert-identity value))) + (t + (mh-modify-header-field field value + (equal field "From"))))) + (setq entry-list (cdr entry-list)))))) + (setq list (cdr list))))))) + +(defun mh-modify-header-field (field value &optional overwrite-flag) + "To header FIELD add VALUE. +If OVERWRITE-FLAG is non-nil then the old value, if present, is discarded." + (cond ((mh-goto-header-field (concat field ":")) + (insert value) + (if overwrite-flag + (delete-region (point) (line-end-position)) + (insert ", "))) + (t (mh-goto-header-end 0) + (insert field ": " value "\n")))) (defun mh-compose-and-send-mail (draft send-args sent-from-folder sent-from-msg @@ -1149,12 +1157,13 @@ for `mh-annotate-msg'. CONFIG is the window configuration to restore after sending the letter." (pop-to-buffer draft) - (if mh-insert-mail-followup-to-flag (mh-insert-mail-followup-to)) + (mh-insert-auto-fields) (mh-letter-mode) ;; mh-identity support (if (and (boundp 'mh-identity-default) - 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) @@ -1169,6 +1178,7 @@ (setq mh-previous-window-config config) (setq mode-line-buffer-identification (list " {%b}")) (mh-logo-display) + (mh-make-local-hook 'kill-buffer-hook) (add-hook 'kill-buffer-hook 'mh-tidy-draft-buffer nil t) (if (and (boundp 'mh-compose-letter-function) mh-compose-letter-function) @@ -1193,19 +1203,16 @@ 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 variable `mh-mhn-compose-insert-flag' is set. -Run `\\[mh-mml-to-mime]' if variable `mh-mml-compose-insert-flag' is set. +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." (interactive "P") (run-hooks 'mh-before-send-letter-hook) - (cond - ((and (boundp 'mh-mhn-compose-insert-flag) - mh-mhn-compose-insert-flag) - (mh-edit-mhn)) - ((and (boundp 'mh-mml-compose-insert-flag) - mh-mml-compose-insert-flag) - (mh-mml-to-mime))) + (cond ((mh-mhn-directive-present-p) + (mh-edit-mhn)) + ((mh-mml-directive-present-p) + (mh-mml-to-mime))) (if mh-insert-x-mailer-flag (mh-insert-x-mailer)) (mh-insert-x-face) (save-buffer) @@ -1232,7 +1239,7 @@ (mh-goto-header-field "Content-Type:")) (setq mh-send-args (format "-mime %s" mh-send-args))) (cond (arg - (pop-to-buffer "MH mail delivery") + (pop-to-buffer mh-mail-delivery-buffer) (erase-buffer) (mh-exec-cmd-output mh-send-prog t "-watch" "-nopush" "-nodraftfolder" mh-send-args file-name) @@ -1339,7 +1346,7 @@ (eq t mh-yank-from-start-of-msg))) ;; supercite needs the full header (concat - (buffer-substring (point-min) (mail-header-end)) + (buffer-substring (point-min) (mh-mail-header-end)) "\n" (buffer-substring (region-beginning) (region-end)))) (yank-region @@ -1472,6 +1479,33 @@ (insert " ")) (forward-line -1)))) +(mh-do-in-xemacs (defvar mail-abbrevs)) + +(defun mh-folder-expand-at-point () + "Do folder name completion in Fcc header field." + (let* ((end (point)) + (syntax-table (syntax-table)) + (beg (unwind-protect + (save-excursion + (mh-funcall-if-exists mail-abbrev-make-syntax-table) + (set-syntax-table mail-abbrev-syntax-table) + (backward-word 1) + (point)) + (set-syntax-table syntax-table))) + (folder (buffer-substring beg end)) + (leading-plus (and (> (length folder) 0) (equal (aref folder 0) ?+))) + (last-slash (mh-search-from-end ?/ folder)) + (prefix (and last-slash (substring folder 0 last-slash))) + (mail-abbrevs + (mapcar #'(lambda (x) + (list (cond (prefix (format "%s/%s" prefix x)) + (leading-plus (format "+%s" x)) + (t x)))) + (mh-folder-completion-function folder nil t)))) + (if (fboundp 'mail-abbrev-complete-alias) + (mh-funcall-if-exists mail-abbrev-complete-alias) + (error "Fcc completion not supported in your version of Emacs")))) + ;;;###mh-autoload (defun mh-letter-complete (arg) "Perform completion on header field or word preceding point. @@ -1480,12 +1514,19 @@ passing the prefix ARG if any." (interactive "P") (let ((case-fold-search t)) - (if (and (mh-in-header-p) - (save-excursion - (mh-header-field-beginning) - (looking-at "^.*\\(to\\|cc\\|from\\):"))) - (mh-alias-letter-expand-alias) - (funcall mh-letter-complete-function arg)))) + (cond + ((and (mh-in-header-p) + (save-excursion + (mh-header-field-beginning) + (looking-at "^fcc:"))) + (mh-folder-expand-at-point)) + ((and (mh-in-header-p) + (save-excursion + (mh-header-field-beginning) + (looking-at "^.*\\(to\\|cc\\|from\\):"))) + (mh-alias-letter-expand-alias)) + (t + (funcall mh-letter-complete-function arg))))) ;;; Build the letter-mode keymap: ;;; If this changes, modify mh-letter-mode-help-messages accordingly, above. @@ -1532,6 +1573,8 @@ ;; "C-c /" prefix is used in mh-letter-mode by pgp.el and mailcrypt.el. +;;;###autoload(add-to-list 'auto-mode-alist '("/drafts/[0-9]+\\'" . mh-letter-mode)) + (provide 'mh-comp) ;;; Local Variables:
--- a/lisp/mh-e/mh-customize.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-customize.el Fri Apr 25 05:52:00 2003 +0000 @@ -1,6 +1,6 @@ ;;; mh-customize.el --- MH-E customization -;; Copyright (C) 2002 Free Software Foundation, Inc. +;; Copyright (C) 2002, 2003 Free Software Foundation, Inc. ;; Author: Bill Wohler <wohler@newt.com> ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -26,9 +26,9 @@ ;;; Commentary: -;; All of the defgroups, defcustoms, and deffaces in MH-E are found here. This -;; makes it possible to customize modules that aren't loaded yet. It also -;; makes it easier to organize the customization groups. +;; All of the defgroups, defcustoms, and deffaces in MH-E are found +;; here. This makes it possible to customize modules that aren't loaded +;; yet. It also makes it easier to organize the customization groups. ;; This file contains the following sections: ;; @@ -55,8 +55,6 @@ ;;; Change Log: -;; $Id: mh-customize.el,v 1.2 2003/02/03 20:55:30 wohler Exp $ - ;;; Code: (provide 'mh-customize) (require 'mh-e) @@ -95,12 +93,31 @@ :link '(custom-manual "(mh-e)Customizing Moving Mail") :group 'mh) +(defgroup mh-index nil + "Indexed searching." + :link '(custom-manual "(mh-e)Customizing mh-e") + :prefix "mh-" + :group 'mh) + +(defgroup mh-junk nil + "Spam handling." + :link '(custom-manual "(mh-e)Customizing mh-e") + :prefix "mh-junk-" + :group 'mh) + (defgroup mh-show nil "Message display." :prefix "mh-" :link '(custom-manual "(mh-e)Customizing Reading") :group 'mh) +(defgroup mh-faces nil + "Faces used in MH-E." + :link '(custom-manual "(mh-e)Customizing mh-e") + :prefix "mh-" + :group 'faces + :group 'mh) + (defgroup mh-letter nil "Composing messages." :prefix "mh-" @@ -113,25 +130,12 @@ :prefix "mh-alias-" :group 'mh) -(defgroup mh-index nil - "Indexed searching." - :link '(custom-manual "(mh-e)Customizing mh-e") - :prefix "mh-" - :group 'mh) - (defgroup mh-identity nil "Multiple personalities." :link '(custom-manual "(mh-e)Customizing mh-e") :prefix "mh-" :group 'mh) -(defgroup mh-faces nil - "Faces used in MH-E." - :link '(custom-manual "(mh-e)Customizing mh-e") - :prefix "mh-" - :group 'faces - :group 'mh) - (defgroup mh-hooks nil "MH-E hooks." :link '(custom-manual "(mh-e)Customizing mh-e") @@ -174,52 +178,6 @@ ;;; Toolbar configuration (:group 'mh-toolbar) -(defconst mh-tool-bar-item-inc "Incorporate new mail in Inbox") -(defconst mh-tool-bar-item-save-mime "Save MIME parts") -(defconst mh-tool-bar-item-prev-msg "Previous message") -(defconst mh-tool-bar-item-page-msg "Page this message") -(defconst mh-tool-bar-item-next-msg "Next message") -(defconst mh-tool-bar-item-delete "Mark for deletion") -(defconst mh-tool-bar-item-refile "Refile this message") -(defconst mh-tool-bar-item-undo "Undo this mark") -(defconst mh-tool-bar-item-perform "Perform moves and deletes") -(defconst mh-tool-bar-item-toggle-show "Toggle showing message") -(defconst mh-tool-bar-item-reply-from "Reply to \"from\"") -(defconst mh-tool-bar-item-reply-to "Reply to \"to\"") -(defconst mh-tool-bar-item-reply-all "Reply to \"all\"") -(defconst mh-tool-bar-item-reply "Reply to this message") -(defconst mh-tool-bar-item-alias "Grab From alias") -(defconst mh-tool-bar-item-compose "Compose new message") -(defconst mh-tool-bar-item-rescan "Rescan this folder") -(defconst mh-tool-bar-item-repack "Repack this folder") -(defconst mh-tool-bar-item-search "Search") -(defconst mh-tool-bar-item-visit "Visit other folder") -(defconst mh-tool-bar-item-prefs "MH-E preferences") -(defconst mh-tool-bar-item-help "Help") -(defconst mh-tool-bar-item-widen "Widen from this sequence") - -(defconst mh-tool-bar-item-send "Send this letter") -(defconst mh-tool-bar-item-attach "Insert attachment") -(defconst mh-tool-bar-item-spell "Check spelling") -(defconst mh-tool-bar-item-save "Save current buffer to its file") -(defconst mh-tool-bar-item-undo-op "Undo last operation") -(defconst mh-tool-bar-item-kill - "Cut (kill) text in region between mark and current position") -(defconst mh-tool-bar-item-copy - "Copy text in region between mark and current position") -(defconst mh-tool-bar-item-paste - "Paste (yank) text cut or copied earlier") -(defconst mh-tool-bar-item-kill-draft "Kill this draft") -(defconst mh-tool-bar-item-comp-prefs "MH-E composition preferences") - -(defcustom mh-tool-bar-reply-3-buttons-flag nil - "*Non-nil means use three buttons for reply commands in tool-bar. -If you have room on your tool-bar because you are using a large font, you -may set this variable to expand the single reply button into three buttons -that won't lead to minibuffer prompt about who to reply to." - :type 'boolean - :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." @@ -228,389 +186,393 @@ (function :tag "Other function")) :group 'mh-toolbar) -(eval-when-compile (defvar tool-bar-map)) -(defvar mh-show-tool-bar-map nil) -(defun mh-tool-bar-show-set () - "Construct toolbar for `mh-show-mode'." - (when (fboundp 'tool-bar-add-item) - (setq - mh-show-tool-bar-map - (let ((tool-bar-map (make-sparse-keymap))) - (if (member mh-tool-bar-item-inc mh-tool-bar-folder-buttons) - (tool-bar-add-item "mail" 'mh-inc-folder 'mh-showtoolbar-inc-folder - :help mh-tool-bar-item-inc)) - (if (member mh-tool-bar-item-save-mime mh-tool-bar-folder-buttons) - (tool-bar-add-item "attach" 'mh-mime-save-parts - 'mh-showtoolbar-mime-save-parts - :help mh-tool-bar-item-save-mime)) - (if (member mh-tool-bar-item-prev-msg mh-tool-bar-folder-buttons) - (tool-bar-add-item "left_arrow" 'mh-show-previous-undeleted-msg - 'mh-showtoolbar-prev - :help mh-tool-bar-item-prev-msg)) - (if (member mh-tool-bar-item-page-msg mh-tool-bar-folder-buttons) - (tool-bar-add-item "page-down" 'mh-show-page-msg 'mh-showtoolbar-page - :help mh-tool-bar-item-page-msg)) - (if (member mh-tool-bar-item-next-msg mh-tool-bar-folder-buttons) - (tool-bar-add-item "right_arrow" 'mh-show-next-undeleted-msg - 'mh-showtoolbar-next - :help mh-tool-bar-item-next-msg)) - (if (member mh-tool-bar-item-delete mh-tool-bar-folder-buttons) - (tool-bar-add-item "close" 'mh-show-delete-msg - 'mh-showtoolbar-delete - :help mh-tool-bar-item-delete)) - (if (member mh-tool-bar-item-refile mh-tool-bar-folder-buttons) - (tool-bar-add-item "refile" 'mh-show-refile-msg - 'mh-showtoolbar-refile - :help mh-tool-bar-item-refile)) - (if (member mh-tool-bar-item-undo mh-tool-bar-folder-buttons) - (tool-bar-add-item "undo" 'mh-show-undo 'mh-showtoolbar-undo - :help mh-tool-bar-item-undo)) - (if (member mh-tool-bar-item-perform mh-tool-bar-folder-buttons) - (tool-bar-add-item "execute" 'mh-show-execute-commands - 'mh-showtoolbar-exec - :help mh-tool-bar-item-perform)) - (if (member mh-tool-bar-item-toggle-show mh-tool-bar-folder-buttons) - (tool-bar-add-item "show" 'mh-show-toggle-showing - 'mh-showtoolbar-toggle-show - :help mh-tool-bar-item-toggle-show)) - (if (member mh-tool-bar-item-reply-from mh-tool-bar-folder-buttons) - (tool-bar-add-item "reply-from" - (lambda (&optional arg) - (interactive "P") - (set-buffer mh-show-folder-buffer) - (mh-reply (mh-get-msg-num nil) "from" arg)) - 'mh-showtoolbar-reply-from - :help mh-tool-bar-item-reply-from)) - (if (member mh-tool-bar-item-reply-to mh-tool-bar-folder-buttons) - (tool-bar-add-item "reply-to" - (lambda (&optional arg) - (interactive "P") - (set-buffer mh-show-folder-buffer) - (mh-reply (mh-get-msg-num nil) "to" arg)) - 'mh-showtoolbar-reply-to - :help mh-tool-bar-item-reply-to)) - (if (member mh-tool-bar-item-reply-all mh-tool-bar-folder-buttons) - (tool-bar-add-item "reply-all" - (lambda (&optional arg) - (interactive "P") - (set-buffer mh-show-folder-buffer) - (mh-reply (mh-get-msg-num nil) "all" arg)) - 'mh-showtoolbar-reply-all - :help mh-tool-bar-item-reply-all)) - (if (member mh-tool-bar-item-reply mh-tool-bar-folder-buttons) - (tool-bar-add-item "mail/reply2" 'mh-show-reply - 'mh-showtoolbar-reply - :help mh-tool-bar-item-reply)) - (if (member mh-tool-bar-item-alias mh-tool-bar-folder-buttons) - (tool-bar-add-item "alias" 'mh-alias-grab-from-field - 'mh-showtoolbar-alias - :help mh-tool-bar-item-alias - :enable '(mh-alias-from-has-no-alias-p))) - (if (member mh-tool-bar-item-compose mh-tool-bar-folder-buttons) - (tool-bar-add-item "mail_compose" 'mh-send 'mh-showtoolbar-compose - :help mh-tool-bar-item-compose)) - (if (member mh-tool-bar-item-rescan mh-tool-bar-folder-buttons) - (tool-bar-add-item "rescan" 'mh-show-rescan-folder - 'mh-showtoolbar-rescan - :help mh-tool-bar-item-rescan)) - (if (member mh-tool-bar-item-repack mh-tool-bar-folder-buttons) - (tool-bar-add-item "repack" 'mh-show-pack-folder - 'mh-showtoolbar-pack - :help mh-tool-bar-item-repack)) - (if (member mh-tool-bar-item-search mh-tool-bar-folder-buttons) - (tool-bar-add-item "search" - (lambda (&optional arg) - (interactive "P") - (call-interactively - mh-tool-bar-search-function)) - 'mh-showtoolbar-search - :help mh-tool-bar-item-search)) - (if (member mh-tool-bar-item-visit mh-tool-bar-folder-buttons) - (tool-bar-add-item "fld_open" 'mh-visit-folder - 'mh-showtoolbar-visit - :help mh-tool-bar-item-visit)) - (if (member mh-tool-bar-item-prefs mh-tool-bar-folder-buttons) - (tool-bar-add-item "preferences" (lambda () - (interactive) - (mh-customize t)) - 'mh-showtoolbar-customize - :help mh-tool-bar-item-prefs)) - (if (member mh-tool-bar-item-help mh-tool-bar-folder-buttons) - (tool-bar-add-item "help" (lambda () - (interactive) - (Info-goto-node "(mh-e)Top") - (delete-other-windows)) - 'mh-showtoolbar-help - :help mh-tool-bar-item-help)) - tool-bar-map)))) +;; 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) + +;; XEmacs has a couple of extra customizations... +(mh-do-in-xemacs + (require 'mh-xemacs-icons) + (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) -(defvar mh-letter-tool-bar-map nil) -;;;###mh-autoload -(defun mh-tool-bar-letter-set () - "Construct toolbar for `mh-letter-mode'." - (when (fboundp 'tool-bar-add-item) - (setq - mh-letter-tool-bar-map - (let ((tool-bar-map (make-sparse-keymap))) - (if (member mh-tool-bar-item-send mh-tool-bar-letter-buttons) - (tool-bar-add-item "mail_send" 'mh-send-letter - 'mh-lettertoolbar-send - :help mh-tool-bar-item-send)) - (if (member mh-tool-bar-item-attach mh-tool-bar-letter-buttons) - (tool-bar-add-item "attach" 'mh-compose-insertion - 'mh-lettertoolbar-compose - :help mh-tool-bar-item-attach)) - (if (member mh-tool-bar-item-spell mh-tool-bar-letter-buttons) - (tool-bar-add-item "spell" 'ispell-message 'mh-lettertoolbar-ispell - :help mh-tool-bar-item-spell)) - (if (member mh-tool-bar-item-save mh-tool-bar-letter-buttons) - (tool-bar-add-item-from-menu 'save-buffer "save")) - (if (member mh-tool-bar-item-undo-op mh-tool-bar-letter-buttons) - (tool-bar-add-item-from-menu 'undo "undo")) - (if (member mh-tool-bar-item-kill mh-tool-bar-letter-buttons) - (tool-bar-add-item-from-menu 'kill-region "cut")) - (if (member mh-tool-bar-item-copy mh-tool-bar-letter-buttons) - (tool-bar-add-item-from-menu 'menu-bar-kill-ring-save "copy")) - (if (member mh-tool-bar-item-paste mh-tool-bar-letter-buttons) - (tool-bar-add-item-from-menu 'yank "paste")) - (if (member mh-tool-bar-item-kill-draft mh-tool-bar-letter-buttons) - (tool-bar-add-item "close" 'mh-fully-kill-draft - 'mh-lettertoolbar-kill - :help mh-tool-bar-item-kill-draft)) - (if (member mh-tool-bar-item-comp-prefs mh-tool-bar-letter-buttons) - (tool-bar-add-item "preferences" (lambda () - (interactive) - (mh-customize t)) - 'mh-lettertoolbar-customize - :help mh-tool-bar-item-comp-prefs)) - (if (member mh-tool-bar-item-help mh-tool-bar-letter-buttons) - (tool-bar-add-item "help" (lambda () - (interactive) - (Info-goto-node "(mh-e)Draft Editing") - (delete-other-windows)) - 'mh-lettertoolbar-help - :help mh-tool-bar-item-help)) - tool-bar-map)))) + (defcustom mh-xemacs-toolbar-position (if mh-xemacs-use-toolbar-flag + 'default + nil) + "*Where to put the toolbar. + +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\". + +A nil value means do not use a toolbar. + +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)) + +(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: + + (:KEYWORD FUNC1 FUNC2 FUNC3 ...) + +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. + +Each element of BUTTONS is a list of four things: + + (FUNCTION MODES ICON DOC) + +where, + + FUNCTION is the name of the function that will be executed when the button + is clicked. + + 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. + + ICON is the icon that is drawn in the button. -(defvar mh-folder-tool-bar-map nil) -(defvar mh-folder-seq-tool-bar-map nil - "Tool-bar to use when narrowed to a sequence in MH-Folder buffers.") -;;;###mh-autoload -(defun mh-tool-bar-folder-set () - "Construct toolbar for `mh-folder-mode'." - (when (fboundp 'tool-bar-add-item) - (setq - mh-folder-tool-bar-map - (let ((tool-bar-map (make-sparse-keymap))) - (if (member mh-tool-bar-item-inc mh-tool-bar-folder-buttons) - (tool-bar-add-item "mail" 'mh-inc-folder - 'mh-foldertoolbar-inc-folder - :help mh-tool-bar-item-inc)) - (if (member mh-tool-bar-item-save-mime mh-tool-bar-folder-buttons) - (tool-bar-add-item "attach" 'mh-mime-save-parts - 'mh-foldertoolbar-mime-save-parts - :help mh-tool-bar-item-save-mime)) - (if (member mh-tool-bar-item-prev-msg mh-tool-bar-folder-buttons) - (tool-bar-add-item "left_arrow" 'mh-previous-undeleted-msg - 'mh-foldertoolbar-prev - :help mh-tool-bar-item-prev-msg)) - (if (member mh-tool-bar-item-page-msg mh-tool-bar-folder-buttons) - (tool-bar-add-item "page-down" 'mh-page-msg 'mh-foldertoolbar-page - :help mh-tool-bar-item-page-msg)) - (if (member mh-tool-bar-item-next-msg mh-tool-bar-folder-buttons) - (tool-bar-add-item "right_arrow" 'mh-next-undeleted-msg - 'mh-foldertoolbar-next - :help mh-tool-bar-item-next-msg)) - (if (member mh-tool-bar-item-delete mh-tool-bar-folder-buttons) - (tool-bar-add-item "close" 'mh-delete-msg 'mh-foldertoolbar-delete - :help mh-tool-bar-item-delete)) - (if (member mh-tool-bar-item-refile mh-tool-bar-folder-buttons) - (tool-bar-add-item "refile" 'mh-refile-msg 'mh-foldertoolbar-refile - :help mh-tool-bar-item-refile)) - (if (member mh-tool-bar-item-undo mh-tool-bar-folder-buttons) - (tool-bar-add-item "undo" 'mh-undo 'mh-foldertoolbar-undo - :help mh-tool-bar-item-undo)) - (if (member mh-tool-bar-item-perform mh-tool-bar-folder-buttons) - (tool-bar-add-item "execute" 'mh-execute-commands - 'mh-foldertoolbar-exec - :help mh-tool-bar-item-perform)) - (if (member mh-tool-bar-item-toggle-show mh-tool-bar-folder-buttons) - (tool-bar-add-item "show" 'mh-toggle-showing - 'mh-foldertoolbar-toggle-show - :help mh-tool-bar-item-toggle-show)) - (if (member mh-tool-bar-item-reply-from mh-tool-bar-folder-buttons) - (tool-bar-add-item "reply-from" - (lambda (&optional arg) - (interactive "P") - (mh-reply (mh-get-msg-num nil) "from" arg)) - 'mh-foldertoolbar-reply-from - :help mh-tool-bar-item-reply-from)) - (if (member mh-tool-bar-item-reply-to mh-tool-bar-folder-buttons) - (tool-bar-add-item "reply-to" - (lambda (&optional arg) - (interactive "P") - (mh-reply (mh-get-msg-num nil) "to" arg)) - 'mh-foldertoolbar-reply-to - :help mh-tool-bar-item-reply-to)) - (if (member mh-tool-bar-item-reply-all mh-tool-bar-folder-buttons) - (tool-bar-add-item "reply-all" - (lambda (&optional arg) - (interactive "P") - (mh-reply (mh-get-msg-num nil) "all" arg)) - 'mh-foldertoolbar-reply-all - :help mh-tool-bar-item-reply-all)) - (if (member mh-tool-bar-item-reply mh-tool-bar-folder-buttons) - (tool-bar-add-item "mail/reply2" 'mh-reply - 'mh-foldertoolbar-reply - :help mh-tool-bar-item-reply)) - (if (member mh-tool-bar-item-alias mh-tool-bar-folder-buttons) - (tool-bar-add-item "alias" 'mh-alias-grab-from-field - 'mh-foldertoolbar-alias - :help mh-tool-bar-item-alias - :enable '(mh-alias-from-has-no-alias-p))) - (if (member mh-tool-bar-item-compose mh-tool-bar-folder-buttons) - (tool-bar-add-item "mail_compose" 'mh-send 'mh-foldertoolbar-compose - :help mh-tool-bar-item-compose)) - (if (member mh-tool-bar-item-rescan mh-tool-bar-folder-buttons) - (tool-bar-add-item "rescan" 'mh-rescan-folder - 'mh-foldertoolbar-rescan - :help mh-tool-bar-item-rescan)) - (if (member mh-tool-bar-item-repack mh-tool-bar-folder-buttons) - (tool-bar-add-item "repack" 'mh-pack-folder 'mh-foldertoolbar-pack - :help mh-tool-bar-item-repack)) - (if (member mh-tool-bar-item-search mh-tool-bar-folder-buttons) - (tool-bar-add-item "search" - (lambda (&optional arg) - (interactive "P") - (call-interactively - mh-tool-bar-search-function)) - 'mh-foldertoolbar-search - :help mh-tool-bar-item-search)) - (if (member mh-tool-bar-item-visit mh-tool-bar-folder-buttons) - (tool-bar-add-item "fld_open" 'mh-visit-folder - 'mh-foldertoolbar-visit - :help mh-tool-bar-item-visit)) - (if (member mh-tool-bar-item-prefs mh-tool-bar-folder-buttons) - (tool-bar-add-item "preferences" (lambda () - (interactive) - (mh-customize t)) - 'mh-foldertoolbar-customize - :help mh-tool-bar-item-prefs)) - (if (member mh-tool-bar-item-help mh-tool-bar-folder-buttons) - (tool-bar-add-item "help" (lambda () - (interactive) - (Info-goto-node "(mh-e)Top") - (delete-other-windows)) - 'mh-foldertoolbar-help - :help mh-tool-bar-item-help)) - tool-bar-map)) + 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." + ;; 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) (equal (length button) 4)) + (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)) + (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))) + (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 (cons buffer toolbar)) + (set-specifier top-toolbar-visible-p t) + (set-specifier top-toolbar-height height)) + ((eq mh-xemacs-toolbar-position 'bottom) + (set-specifier bottom-toolbar (cons buffer toolbar)) + (set-specifier bottom-toolbar-visible-p t) + (set-specifier bottom-toolbar-height height)) + ((eq mh-xemacs-toolbar-position 'left) + (set-specifier left-toolbar (cons buffer toolbar)) + (set-specifier left-toolbar-visible-p t) + (set-specifier left-toolbar-width width)) + ((eq mh-xemacs-toolbar-position 'right) + (set-specifier right-toolbar (cons buffer toolbar)) + (set-specifier right-toolbar-visible-p t) + (set-specifier right-toolbar-width width)) + (t (set-specifier default-toolbar (cons buffer toolbar)))))))) + ;; 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))))))) - (setq mh-folder-seq-tool-bar-map - (let ((tool-bar-map (copy-keymap mh-folder-tool-bar-map))) - (if (member mh-tool-bar-item-widen mh-tool-bar-folder-buttons) - (tool-bar-add-item "widen" 'mh-widen 'mh-foldertoolbar-widen - :help mh-tool-bar-item-widen)) - tool-bar-map)))) - -(defun mh-tool-bar-folder-buttons-set (symbol value) - "Update the `mh-tool-bar-folder-buttons' variable, and rebuild the tool-bar. -Sets the default for SYMBOL (e.g. `mh-tool-bar-folder-buttons') to VALUE (as -set in customization). This is called after 'customize is used to alter -`mh-tool-bar-folder-buttons'." - (set-default symbol value) - (mh-tool-bar-show-set) - (mh-tool-bar-folder-set)) - -(custom-declare-variable - 'mh-tool-bar-folder-buttons - '(append - (list mh-tool-bar-item-inc - mh-tool-bar-item-save-mime - mh-tool-bar-item-prev-msg - mh-tool-bar-item-page-msg - mh-tool-bar-item-next-msg - mh-tool-bar-item-delete - mh-tool-bar-item-refile - mh-tool-bar-item-undo - mh-tool-bar-item-perform -;;; mh-tool-bar-item-toggle-show - ) - (if mh-tool-bar-reply-3-buttons-flag - (list mh-tool-bar-item-reply-from - mh-tool-bar-item-reply-to - mh-tool-bar-item-reply-all) - (list mh-tool-bar-item-reply)) - (list mh-tool-bar-item-alias - mh-tool-bar-item-compose - mh-tool-bar-item-rescan -;;; mh-tool-bar-item-repack - mh-tool-bar-item-search - mh-tool-bar-item-visit - mh-tool-bar-item-prefs - mh-tool-bar-item-help - mh-tool-bar-item-widen)) - "Buttons to include in MH-E folder/show toolbar." - :group 'mh-toolbar - :set 'mh-tool-bar-folder-buttons-set - :type `(set (const ,mh-tool-bar-item-inc) - (const ,mh-tool-bar-item-save-mime) - (const ,mh-tool-bar-item-prev-msg) - (const ,mh-tool-bar-item-page-msg) - (const ,mh-tool-bar-item-next-msg) - (const ,mh-tool-bar-item-delete) - (const ,mh-tool-bar-item-refile) - (const ,mh-tool-bar-item-undo) - (const ,mh-tool-bar-item-perform) - (const ,mh-tool-bar-item-toggle-show) - (const ,mh-tool-bar-item-reply-from) - (const ,mh-tool-bar-item-reply-to) - (const ,mh-tool-bar-item-reply-all) - (const ,mh-tool-bar-item-reply) - (const ,mh-tool-bar-item-alias) - (const ,mh-tool-bar-item-compose) - (const ,mh-tool-bar-item-rescan) - (const ,mh-tool-bar-item-repack) - (const ,mh-tool-bar-item-search) - (const ,mh-tool-bar-item-visit) - (const ,mh-tool-bar-item-prefs) - (const ,mh-tool-bar-item-help) - (const ,mh-tool-bar-item-widen))) - -(defun mh-tool-bar-letter-buttons-set (symbol value) - "Update the `mh-tool-bar-letter-buttons' variable, and rebuild the tool-bar. -Sets the default for SYMBOL (e.g. `mh-tool-bar-letter-buttons') to VALUE (as -set in customization). This is called after 'customize is used to alter -`mh-tool-bar-letter-buttons'." - (set-default symbol value) - (mh-tool-bar-letter-set)) - -(custom-declare-variable - 'mh-tool-bar-letter-buttons - '(list mh-tool-bar-item-send - mh-tool-bar-item-attach - mh-tool-bar-item-spell - mh-tool-bar-item-save - mh-tool-bar-item-undo-op - mh-tool-bar-item-kill - mh-tool-bar-item-copy - mh-tool-bar-item-paste - mh-tool-bar-item-kill-draft - mh-tool-bar-item-comp-prefs - mh-tool-bar-item-help) - "Buttons to include in MH-E letter toolbar." - :group 'mh-toolbar - :set 'mh-tool-bar-letter-buttons-set - :type `(set (const ,mh-tool-bar-item-send) - (const ,mh-tool-bar-item-attach) - (const ,mh-tool-bar-item-spell) - (const ,mh-tool-bar-item-save) - (const ,mh-tool-bar-item-undo-op) - (const ,mh-tool-bar-item-kill) - (const ,mh-tool-bar-item-copy) - (const ,mh-tool-bar-item-paste) - (const ,mh-tool-bar-item-kill-draft) - (const ,mh-tool-bar-item-comp-prefs) - (const ,mh-tool-bar-item-help))) +(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-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'")) @@ -660,12 +622,16 @@ (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 has the associated address. You do not need to list your aliases here -as that lookup is already performed. +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. + See `mh-prompt-for-refile-folder' and `mh-folder-from-address' for more information." - :type '(repeat (list (string :tag "Address") - (string :tag "Folder"))) + :type '(repeat (list (regexp :tag "Address") + (string :tag "Folder") + (boolean :tag "Check Recipient"))) :group 'mh-folder) (defcustom mh-default-folder-must-exist-flag t @@ -695,6 +661,44 @@ :type 'string :group 'mh-folder) + +(defcustom mh-inc-spool-list nil + "*Alist of alternate spool files, corresponding folders and keybindings. +Here's an example. Suppose you have subscribed to the MH-E devel mailing +list. You could filter its mail into a separate spool file named +~/mail/mh-e using Procmail and a .procmailrc entry like: + +MAILDIR=$HOME/mail #you'd better make sure it exists +:0: +* ^From mh-e-devel-admin@lists.sourceforge.net +mh-e + +If you wanted to incorporate that spool file into an MH folder called +mh-e by pressing \"I m\" in folder-mode or by `M-x mh-inc-spool-mh-e', +you would setup `mh-inc-spool-list' with an entry: + + Spool file: ~/mail/mh-e + Folder: mh-e + Key binding: m + +Then, you could also install `xbuffy' and configure an extra mailbox like so: + +box ~/mail/mh-e + title mh-e + origMode + polltime 10 + headertime 0 + command gnudoit -q '(mh-inc-spool-mh-e)' + +Note that the entry above uses the gnuserv package to communicate the +command `mh-inc-spool-mh-e' to Emacs. It will incorporate the spool file +when clicking the xbuffy box with the middle mouse button." + :type '(repeat (list (file :tag "Spool file") + (string :tag "Folder") + (character :tag "Key binding"))) + :set 'mh-inc-spool-list-set + :group 'mh-folder) + (defcustom mh-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 @@ -712,12 +716,6 @@ directory) :group 'mh-folder) -(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-print-background-flag nil "*Non-nil means messages should be printed in the background. WARNING: do not delete the messages until printing is finished; @@ -725,6 +723,12 @@ :type 'boolean :group 'mh-folder) +(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-recursive-folders-flag nil "*Non-nil means that commands which operate on folders do so recursively." :type 'boolean @@ -769,6 +773,12 @@ directory) :group 'mh-folder) +(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 @@ -779,6 +789,86 @@ +;;; Indexed 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. +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")))) + +(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. + +More information about setting up an indexing program to use with MH-E can be +found in the documentation of `mh-index-search'." + :type '(choice (const :tag "Auto-detect" nil) + (const :tag "swish++" swish++) + (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) + + + +;;; Spam Handling (: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)) + "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.") + +(defun mh-junk-choose (symbol value) + "Choose spam program to use. +The function is always called with SYMBOL bound to `mh-junk-program' and VALUE +bound to the new value of `mh-junk-program'. The function sets the variable +`mh-junk-choice' in addition to `mh-junk-program'." + (set symbol value) + (setq mh-junk-choice + (or value + (loop for element in mh-junk-function-alist + until (executable-find (symbol-name (car element))) + 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")) + :group 'mh-junk) + +(defcustom mh-junk-program nil + "Spam program that MH-E shall use. +The possible choices are bogofilter, spamprobe, and spamassassin. By default +this variable is nil which means that the programs are tried in order and the +first one found is used." + :type '(choice (const :tag "auto-detect" nil) + (const :tag "bogofilter" bogofilter) + (const :tag "spamprobe" spamprobe) + (const :tag "spamassassin" spamassassin)) + :set 'mh-junk-choose + :group 'mh-junk) + + + ;;; Message display (:group 'mh-show) (defcustom mh-bury-show-buffer-flag t @@ -798,21 +888,6 @@ :type 'boolean :group 'mh-show) -(defcustom mh-decode-content-transfer-encoded-message-flag - (and (fboundp 'executable-find) (executable-find "mimencode") t) - "Non-nil means decode messages with `mimencode', if necessary. - -Messages which are encoded as quoted-printable or base64 are translated into -8-bit characters by the `mimencode' command. - -This variable is initialized to t if `mimencode' is available. - -The `mimencode' program is part of the metamail package. The source can be -obtained from - ftp://thumper.bellcore.com/pub/nsb/" - :type 'boolean - :group 'mh-show) - (defcustom mh-display-buttons-for-inline-parts-flag nil "*Non-nil means display buttons for all inline MIME parts. If non-nil, buttons are displayed for all MIME parts. Inline parts start off @@ -830,6 +905,24 @@ :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. + +If set to t, the image is fetched. + +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. + +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)) + :group 'mh-show) + (defcustom mh-graphical-smileys-flag t "*Non-nil means graphical smileys are displayed. Non-nil means that small graphics will be used in the show buffer instead of @@ -854,6 +947,177 @@ (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. +Use the function `mh-invisible-headers' to generate this variable. +If `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." + (setq mh-invisible-headers + (concat + "^" + (let ((max-specpdl-size 1000) ;workaround for insufficient default + (fields mh-invisible-header-fields)) + (regexp-opt fields t))))) + +(defun mh-invisible-header-fields-set (symbol value) + "Update `mh-invisible-header-fields'. +The function is called with SYMBOL bound to `mh-invisible-header-fields' and +VALUE is the the list of headers that are invisible. As a side effect, the +variable `mh-invisible-fields' is set." + (set-default symbol value) + (mh-invisible-headers)) + +;; Keep fields alphabetized. Mention source, if known. +(defcustom mh-invisible-header-fields + '("Approved:" + "Autoforwarded:" + "Bestservhost:" + "Cancel-Lock:" ; NNTP posts + "Content-" ; RFC 2045 + "Delivered-To:" ; Egroups/yahoogroups mailing list manager + "Delivery-Date:" ; MH + "Delivery:" + "Encoding:" + "Errors-To:" + "Face:" ; Gnus Face header + "Forwarded:" ; MH + "From " ; sendmail + "Importance:" ; MS Outlook + "In-Reply-To:" ; MH + "Lines:" + "List-" ; Mailman mailing list manager + "List-" ; Unknown mailing list managers + "List-Subscribe:" ; Unknown mailing list managers + "List-Unsubscribe:" ; Unknown mailing list managers + "Mail-from:" ; MH + "Mailing-List:" ; Egroups/yahoogroups mailing list manager + "Message-Id:" ; RFC 822 + "Mime-Version" ; RFC 2045 + "NNTP-" ; News + "Old-Return-Path:" + "Original-Encoded-Information-Types:" ; X400 + "Original-Lines:" ; mail to news + "Original-Newsgroups:" ; mail to news + "Original-NNTP-" ; mail to news + "Original-Path:" ; mail to news + "Original-Received:" ; mail to news + "Original-To:" ; mail to news + "Original-X-" ; mail to news + "P1-Content-Type:" ; X400 + "P1-Message-Id:" ; X400 + "P1-Recipient:" ; X400 + "Path:" + "Precedence:" + "Prev-Resent" ; MH + "Priority:" + "Received:" ; RFC 822 + "References:" + "Remailed-" ; MH + "Replied:" ; MH + "Resent" ; MH + "Return-Path:" ; RFC 822 + "Sensitivity:" ; MS Outlook + "Status:" ; sendmail + "Ua-Content-Id:" ; X400 + "User-Agent:" + "Via:" ; MH + "X-Abuse-Info:" + "X-Accept-Language:" + "X-Accept-Language:" ; Netscape/Mozilla + "X-Ack:" + "X-Apparently-From:" ; MS Outlook + "X-Apparently-To:" ; Egroups/yahoogroups mailing list manager + "X-Authentication-Warning:" ; sendmail + "X-Beenthere:" ; Mailman mailing list manager + "X-Bogosity:" ; bogofilter + "X-Complaints-To:" + "X-Cron-Env:" + "X-Delivered" + "X-Envelope-Sender:" + "X-Envelope-To:" + "X-Face:" + "X-Folder:" ; Spam + "X-From-Line" + "X-Gnus-Mail-Source:" ; gnus + "X-Habeas-SWE-1:" ; Spam + "X-Habeas-SWE-2:" ; Spam + "X-Habeas-SWE-3:" ; Spam + "X-Habeas-SWE-4:" ; Spam + "X-Habeas-SWE-5:" ; Spam + "X-Habeas-SWE-6:" ; Spam + "X-Habeas-SWE-7:" ; Spam + "X-Habeas-SWE-8:" ; Spam + "X-Habeas-SWE-9:" ; Spam + "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-Listserver:" ; Unknown mailing list managers + "X-Loop:" ; Unknown mailing list managers + "X-MIME-Autoconverted:" ; sendmail + "X-MIMETrack:" + "X-MS-TNEF-Correlator:" ; MS Outlook + "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-MimeOLE:" ; MS Outlook + "X-Mozilla-Status:" ; Netscape/Mozilla + "X-Msmail-" ; MS Outlook + "X-News:" ; News + "X-No-Archive:" + "X-Notes-Item:" ; Lotus Notes Domino structured header + "X-Orcl-Content-Type:" + "X-Original-Complaints-To:" + "X-Original-Date:" ; SourceForge mailing list manager + "X-Original-Trace:" + "X-OriginalArrivalTime:" ; Hotmail + "X-Originating-IP:" ; Hotmail + "X-Priority:" ; MS Outlook + "X-Qotd-" ; User added + "X-Received-Date:" + "X-Received:" + "X-Request-" + "X-SBClass:" ; Spam + "X-SBNote:" ; Spam + "X-SBPass:" ; Spam + "X-SBRule:" ; Spam + "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-SpamBouncer:" ; Spam + "X-Trace:" + "X-UIDL:" + "X-UserInfo1:" + "X-VSMLoop:" ; NTMail + "X-Vms-To:" + "X-Wss-Id:" ; Worldtalk gateways + "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 `mh-visible-headers' is set." + :type '(repeat (string :tag "Header field")) + :set 'mh-invisible-header-fields-set + :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 @@ -884,25 +1148,40 @@ :type 'boolean :group 'mh-show) -(defcustom mh-show-use-xface-flag - (and window-system - (not (null (cond - (mh-xemacs-flag - (locate-library "x-face")) - ((>= emacs-major-version 21) - (locate-library "x-face-e21")) - (t ;Emacs20 - nil)))) - (not (null (and (fboundp 'executable-find) - (executable-find - "uncompface"))))) - "*Non-nil means display faces in `mh-show-mode' with external x-face package. -It is available from ftp://ftp.jpl.org/pub/elisp/. Download it and put its -files in the Emacs `load-path' and MH-E will invoke it automatically for you if -this variable is non-nil. +(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. -The `uncompface' binary is also required to be in the execute PATH. It can -be obtained from: ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.Z" +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 +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. + +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." :type 'boolean :group 'mh-show) @@ -932,163 +1211,6 @@ :group 'mh-show) (put 'mhl-formfile 'info-file "mh-e") -(defvar mh-invisible-headers nil - "*Regexp matching lines in a message header that are not to be shown. -If `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." - (setq mh-invisible-headers - (concat - "^" - (let ((max-specpdl-size 1000) ;workaround for insufficient default - (fields (append (if (not mh-show-use-xface-flag) - '("X-Face: ")) - mh-invisible-header-fields))) - (regexp-opt fields t))))) - -(defun mh-invisible-header-fields-set (symbol value) - "Update `mh-invisible-header-fields'. -The function is called with SYMBOL bound to `mh-invisible-header-fields' and -VALUE is the the list of headers that are invisible. As a side effect, the -variable `mh-invisible-fields' is set." - (set-default symbol value) - (mh-invisible-headers)) - -;; Keep fields alphabetized. Mention source, if known. -(defcustom mh-invisible-header-fields - '("Autoforwarded: " - "Bestservhost: " - "Content-" ; RFC 2045 - "Delivered-To: " ; Egroups/yahoogroups mailing list manager - "Delivery-Date: " ; MH - "Delivery: " - "Encoding: " - "Errors-To: " - "Forwarded: " ; MH - "From " ; sendmail - "Importance: " ; MS Outlook - "In-Reply-To: " ; MH - "Lines: " - "List-" ; Mailman mailing list manager - "List-" ; Unknown mailing list managers - "List-Subscribe: " ; Unknown mailing list managers - "List-Unsubscribe: " ; Unknown mailing list managers - "Mail-from: " ; MH - "Mailing-List: " ; Egroups/yahoogroups mailing list manager - "Message-Id: " ; RFC 822 - "Mime-Version" ; RFC 2045 - "NNTP-" ; News - "Old-Return-Path: " - "Original-Encoded-Information-Types: " ; X400 - "P1-Content-Type: " ; X400 - "P1-Message-Id: " ; X400 - "P1-Recipient: " ; X400 - "Path: " - "Precedence: " - "Prev-Resent" ; MH - "Priority: " - "Received: " ; RFC 822 - "References: " - "Remailed-" ; MH - "Replied: " ; MH - "Resent" ; MH - "Return-Path: " ; RFC 822 - "Sensitivity: " ; MS Outlook - "Status: " ; sendmail - "Ua-Content-Id: " ; X400 - "User-Agent: " - "Via: " ; MH - "X-Abuse-Info: " - "X-Accept-Language: " - "X-Accept-Language: " ; Netscape/Mozilla - "X-Ack: " - "X-Apparently-From: " ; MS Outlook - "X-Apparently-To: " ; Egroups/yahoogroups mailing list manager - "X-Authentication-Warning: " ; sendmail - "X-Beenthere: " ; Mailman mailing list manager - "X-Complaints-To: " - "X-Cron-Env: " - "X-Delivered" - "X-Envelope-Sender: " - "X-Envelope-To: " - "X-Folder: " ; Spam - "X-From-Line" - "X-Gnus-Mail-Source: " ; gnus - "X-Habeas-SWE-1: " ; Spam - "X-Habeas-SWE-2: " ; Spam - "X-Habeas-SWE-3: " ; Spam - "X-Habeas-SWE-4: " ; Spam - "X-Habeas-SWE-5: " ; Spam - "X-Habeas-SWE-6: " ; Spam - "X-Habeas-SWE-7: " ; Spam - "X-Habeas-SWE-8: " ; Spam - "X-Habeas-SWE-9: " ; Spam - "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-Listserver: " ; Unknown mailing list managers - "X-Loop: " ; Unknown mailing list managers - "X-MIME-Autoconverted: " ; sendmail - "X-MIMETrack: " - "X-MS-TNEF-Correlator: " ; MS Outlook - "X-Mailing-List: " ; Unknown mailing list managers - "X-Mailman-Version: " ; Mailman mailing list manager - "X-Message-Id" - "X-MHE-Checksum" ; Checksum added during index search - "X-MimeOLE: " ; MS Outlook - "X-Mozilla-Status: " ; Netscape/Mozilla - "X-Msmail-" ; MS Outlook - "X-News: " ; News - "X-No-Archive: " - "X-Orcl-Content-Type: " - "X-Original-Complaints-To: " - "X-Original-Date: " ; SourceForge mailing list manager - "X-Original-Trace: " - "X-OriginalArrivalTime: " ; Hotmail - "X-Originating-IP: " ; Hotmail - "X-Priority: " ; MS Outlook - "X-Qotd-" ; User added - "X-Received-Date: " - "X-Received: " - "X-Request-" - "X-SBClass: " ; Spam - "X-SBNote: " ; Spam - "X-SBPass: " ; Spam - "X-SBRule: " ; Spam - "X-Scanned-By" - "X-Sender: " - "X-Server-Date: " - "X-Server-Uuid: " - "X-Sieve: " ; Sieve filtering - "X-Spam-Level: " ; Spam - "X-Spam-Score: " ; Spam - "X-Spam-Status: " ; Spam - "X-SpamBouncer: " ; Spam - "X-Trace: " - "X-UIDL: " - "X-UserInfo1: " - "X-VSMLoop: " ; NTMail - "X-Vms-To: " - "X-Wss-Id: " ; Worldtalk gateways - "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 `mh-visible-headers' is set." - :type '(repeat (string :tag "Header field")) - :set 'mh-invisible-header-fields-set - :group 'mh-show) - ;;; Composing messages (:group 'mh-letter) @@ -1134,40 +1256,14 @@ :type 'string :group 'mh-letter) -(defcustom mh-insert-mail-followup-to-flag t - "Non-nil means maybe append a Mail-Followup-To field to the header. -The insertion is done if the To: or Cc: fields matches an entry in -`mh-insert-mail-followup-to-list'." +(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-insert-mail-followup-to-list nil - "Alist of addresses for which a Mail-Followup-To field is inserted. -Each element has the form (REGEXP ADDRESS). -When the REGEXP appears in the To or cc fields of a message, the corresponding -ADDRESS is inserted in a Mail-Followup-To field. - -Here's a customization example: - - regexp: mh-e-users@lists.s\\\\(ourceforge\\\\|f\\\\).net - address: mh-e-users@lists.sourceforge.net - -This corresponds to: - - (setq mh-insert-mail-followup-to-list - '((\"mh-e-users@lists.s\\\\(ourceforge\\\\|f\\\\).net\" - \"mh-e-users@lists.sourceforge.net\"))) - -While it might be tempting to add a descriptive name to the mailing list -address, consider that this field will appear in other people's outgoing -mail in their To: field. It might be best to keep it simple." - :type '(repeat (list (string :tag "Regexp") - (string :tag "Address"))) - :group 'mh-letter) - -(defcustom mh-insert-x-mailer-flag t - "*Non-nil means append an X-Mailer field to the header." - :type 'boolean +(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-letter-fill-column 72 @@ -1207,16 +1303,28 @@ :group 'mh-letter) (defcustom mh-x-face-file "~/.face" - "*File name containing the encoded X-Face string to insert in outgoing mail. -If nil, or the file does not exist, nothing is added to message headers." + "*File containing X-Face or Face header field to insert in outgoing mail. + +If the file starts with either of the strings \"X-Face: \", \"Face: \" or +\"X-Image-URL: \" then it is assumed to contain the whole field and is added to +the message header verbatim. Otherwise it is assumed that the file contains the +value of the X-Face header field. + +X-Face header fields can be generated using `compface', which can be obtained +from ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.Z. The \"Online +X-Face Convertor\" at http://www.dairiki.org/xface/ is a useful resource for +quick conversion of images into X-Face header fields. + +There is a `make-face' script that converts a jpeg image to a Face header +field at http://quimby.gnus.org/circus/face/make-face. + +The URL of any image can be used for the X-Image-URL field and no processing +of the image is required. + +If nil, or the file does not exist, nothing is added to the message header." :type 'file :group 'mh-letter) -(defvar mh-x-mailer-string nil - "*String containing the contents of the X-Mailer header field. -If nil, this variable is initialized to show the version of MH-E, Emacs, and -MH the first time a message is composed.") - (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 @@ -1260,39 +1368,24 @@ (const :tag "Entire message with headers" t)) :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) - ;;; Alias handling (:group 'mh-alias) -(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]." - :group 'mh-alias - :type '(choice (file) (repeat file))) - -(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." - :group 'mh-alias - :type 'boolean) - (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." - :group 'mh-alias - :type 'boolean) + :type 'boolean + :group 'mh-alias) + +(defcustom mh-alias-expand-aliases-flag nil + "*Non-nil means to expand aliases entered in the minibuffer. +In other words, aliases entered in the minibuffer will be expanded to the full +address in the message draft. By default, this expansion is not performed." + :type 'boolean + :group 'mh-alias) (defcustom mh-alias-flash-on-comma t "*Specify whether to flash or warn on translation. @@ -1301,10 +1394,28 @@ 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." - :group 'mh-alias :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))) + (const :tag "Don't flash nor warn if no translation" nil)) + :group 'mh-alias) + +(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) + +(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) (defcustom mh-alias-local-users t "*If t, local users are completed in MH-E To: and Cc: prompts. @@ -1314,52 +1425,71 @@ 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." - :group 'mh-alias - :type '(choice (boolean) (string))) + :type '(choice (boolean) (string)) + :group 'mh-alias) -(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." - :group 'mh-alias - :type '(choice (const :tag "Use AliasFile MH profile component" nil) - (file :tag "Alias file") - (repeat :tag "List of alias files" file))) - -(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)) +(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) -;;; Indexed searching (:group 'mh-index) +;;; Multiple personalities (:group 'mh-identity) + +(defvar mh-identity-list ()) -(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. +(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. + +There is one special case for KEYWORD, that of \"identity\", which means to +insert that identity using `mh-insert-identity'. -More information about setting up an indexing program to use with MH-E can be -found in the documentation of `mh-index-search'." - :type '(choice (const :tag "Auto-detect" nil) - (const :tag "swish++" swish++) - (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) +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) - - -;;; Multiple personalities (:group 'mh-identity) +(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) (defcustom mh-identity-list nil "*List holding MH-E identity. @@ -1408,20 +1538,6 @@ :set 'mh-identity-list-set :group 'mh-identity) -(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) @@ -1481,12 +1597,6 @@ :group 'mh-hooks :group 'mh-folder) -(defcustom mh-index-show-hook nil - "Invoked after the message has been displayed." - :type 'hook - :group 'mh-hooks - :group 'mh-index) - (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. @@ -1685,6 +1795,13 @@ "Face for highlighting subject text in MH-Folder buffers." :group 'mh-folder-faces) +(defface mh-folder-tick-face + '((((class color) (background dark)) (:background "#dddf7e")) + (((class color) (background light)) (:background "#dddf7e")) + (t (:underline t))) + "Face used to show ticked messages." + :group 'mh-folder-faces) + (defvar mh-folder-address-face 'mh-folder-address-face "Face for highlighting the address in MH-Folder buffers.") (copy-face 'mh-folder-subject-face 'mh-folder-address-face) @@ -1774,6 +1891,12 @@ "Face for highlighting the From: header field." :group 'mh-show-faces) +(defface mh-show-xface-face + '((t (:foreground "black" :background "white"))) + "Face for displaying the X-Face image. +The background and foreground is used in the image." + :group 'mh-show-faces) + (defvar mh-show-subject-face 'mh-show-subject-face "Face for highlighting the Subject header field.") (copy-face 'mh-folder-subject-face 'mh-show-subject-face)
--- a/lisp/mh-e/mh-e.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-e.el Fri Apr 25 05:52:00 2003 +0000 @@ -1,10 +1,11 @@ ;;; mh-e.el --- GNU Emacs interface to the MH mail system -;; Copyright (C) 1985,86,87,88,90,92,93,94,95,97,2000,2001,2002 Free Software Foundation, Inc. +;; Copyright (C) 1985, 86, 87, 88, 90, 92, 93, 94, 95, 97, 1999, +;; 2000, 01, 02, 2003 Free Software Foundation, Inc. ;; Author: Bill Wohler <wohler@newt.com> ;; Maintainer: Bill Wohler <wohler@newt.com> -;; Version: 7.2 +;; Version: 7.3 ;; Keywords: mail ;; This file is part of GNU Emacs. @@ -79,8 +80,6 @@ ;; Maintenance picked up by Bill Wohler <wohler@newt.com> and the ;; SourceForge Crew <http://mh-e.sourceforge.net/>. 2001. -;; $Id: mh-e.el,v 1.262 2003/02/03 19:11:43 wohler Exp $ - ;;; Code: (require 'cl) @@ -92,6 +91,7 @@ (> 50 recursive-load-depth-limit)) (setq recursive-load-depth-limit 50))) +(require 'mh-inc) (require 'mh-utils) (require 'gnus-util) (require 'easymenu) @@ -102,7 +102,7 @@ (defvar font-lock-auto-fontify) (defvar font-lock-defaults) -(defconst mh-version "7.2" "Version number of MH-E.") +(defconst mh-version "7.3" "Version number of MH-E.") ;;; Autoloads (autoload 'Info-goto-node "info") @@ -413,7 +413,7 @@ (cond ((not mh-folder-unseen-seq-cache) nil) - ((not cur-msg) ;Presumably at end of buffer + ((>= (point) limit) ;Presumably at end of buffer (setq mh-folder-unseen-seq-cache nil) nil) ((member cur-msg mh-folder-unseen-seq-cache) @@ -432,8 +432,7 @@ ;; Examine how we must have exited the loop... (let ((cur-msg (mh-get-msg-num nil))) (cond - ((or (not cur-msg) - (<= limit (point)) + ((or (<= limit (point)) (not (member cur-msg mh-folder-unseen-seq-cache))) (setq mh-folder-unseen-seq-cache nil) nil) @@ -468,6 +467,10 @@ (defvar mh-narrowed-to-seq nil) ;Sequence display is narrowed to or ;nil if not narrowed. +(defvar mh-tick-seq-changed-when-narrowed-flag nil) + ;Has tick sequence changed while the + ;folder was narrowed to it? + (defvar mh-view-ops ()) ;Stack of ops that change the folder ;view (such as narrowing or threading). @@ -535,34 +538,27 @@ (defun mh-delete-msg (msg-or-seq) "Mark the specified MSG-OR-SEQ for subsequent deletion and move to the next. - -Default is the displayed message. If optional prefix argument is given then -prompt for the message sequence. If variable `transient-mark-mode' is non-nil -and the mark is active, then the selected region is marked for deletion." - (interactive (list (cond - ((mh-mark-active-p t) - (cons (region-beginning) (region-end))) - (current-prefix-arg - (mh-read-seq-default "Delete" t)) - (t - (cons (line-beginning-position) (line-end-position)))))) +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is marked for deletion. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence." + (interactive (list (mh-interactive-msg-or-seq "Delete"))) (mh-delete-msg-no-motion msg-or-seq) (mh-next-msg)) (defun mh-delete-msg-no-motion (msg-or-seq) "Mark the specified MSG-OR-SEQ for subsequent deletion. -Default is the displayed message. If optional prefix argument is provided, -then prompt for the message sequence." - (interactive (list (if current-prefix-arg - (mh-read-seq-default "Delete" t) - (mh-get-msg-num t)))) - (cond ((numberp msg-or-seq) - (mh-delete-a-msg msg-or-seq)) - ((and (consp msg-or-seq) - (numberp (car msg-or-seq)) (numberp (cdr msg-or-seq))) - (mh-iterate-on-messages-in-region () (car msg-or-seq) (cdr msg-or-seq) - (mh-delete-a-msg nil))) - (t (mh-map-to-seq-msgs 'mh-delete-a-msg msg-or-seq)))) +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is marked for deletion. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence." + (interactive (list (mh-interactive-msg-or-seq "Delete"))) + (mh-iterate-on-msg-or-seq () msg-or-seq + (mh-delete-a-msg nil))) (defun mh-execute-commands () "Process outstanding delete and refile requests." @@ -593,7 +589,6 @@ (mh-invalidate-show-buffer)) (let ((mh-decode-mime-flag nil) (mhl-formfile nil) - (mh-decode-content-transfer-encoded-message-flag nil) (mh-clean-message-header-flag nil)) (mh-show-msg nil) (mh-in-show-buffer (mh-show-buffer) @@ -601,28 +596,31 @@ (mh-recenter 0)) (setq mh-showing-with-headers t))) -(defun mh-inc-folder (&optional maildrop-name) +(defun mh-inc-folder (&optional maildrop-name folder) "Inc(orporate)s new mail into the Inbox folder. Optional argument MAILDROP-NAME specifies an alternate maildrop from the -default. If the prefix argument is given, incorporates mail into the current -folder, otherwise uses the folder named by `mh-inbox'. +default. The optional argument FOLDER specifies where to incorporate mail +instead of the default named by `mh-inbox'. The value of `mh-inc-folder-hook' is a list of functions to be called, with no arguments, after incorporating new mail. Do not call this function from outside MH-E; use \\[mh-rmail] instead." (interactive (list (if current-prefix-arg (expand-file-name (read-file-name "inc mail from file: " - mh-user-path))))) + mh-user-path))) + (if current-prefix-arg + (mh-prompt-for-folder "inc mail into" mh-inbox t)))) + (if (not folder) + (setq folder mh-inbox)) (let ((threading-needed-flag nil)) (let ((config (current-window-configuration))) - (if (not maildrop-name) - (cond ((not (get-buffer mh-inbox)) - (mh-make-folder mh-inbox) - (setq threading-needed-flag mh-show-threads-flag) - (setq mh-previous-window-config config)) - ((not (eq (current-buffer) (get-buffer mh-inbox))) - (switch-to-buffer mh-inbox) - (setq mh-previous-window-config config))))) + (cond ((not (get-buffer folder)) + (mh-make-folder folder) + (setq threading-needed-flag mh-show-threads-flag) + (setq mh-previous-window-config config)) + ((not (eq (current-buffer) (get-buffer folder))) + (switch-to-buffer folder) + (setq mh-previous-window-config config)))) (mh-get-new-mail maildrop-name) (when (and threading-needed-flag (save-excursion @@ -632,7 +630,8 @@ (and (message "Not threading since the number of messages exceeds `mh-large-folder'") nil)))) (mh-toggle-threads)) - (if mh-showing-mode (mh-show)) + (beginning-of-line) + (if (and mh-showing-mode (looking-at mh-scan-valid-regexp)) (mh-show)) (run-hooks 'mh-inc-folder-hook))) (defun mh-last-msg () @@ -643,8 +642,10 @@ (forward-line -1)) (mh-recenter nil)) -(defun mh-next-undeleted-msg (&optional arg) - "Move to the next undeleted message ARG in window." +(defun mh-next-undeleted-msg (&optional arg wait-after-complaining-flag) + "Move to the next undeleted message ARG in window. +If optional argument WAIT-AFTER-COMPLAINING-FLAG is non-nil and we are at the +last undeleted message then pause for a second after printing message." (interactive "p") (setq mh-next-direction 'forward) (forward-line 1) @@ -652,38 +653,73 @@ (beginning-of-line) (mh-maybe-show)) (t (forward-line -1) - (message "No more undeleted messages")))) + (message "No more undeleted messages") + (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: a) The folder name associated with the address in the alist - `mh-default-folder-list'. + `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. b) The address' corresponding alias from the user's personal aliases file prefixed by `mh-default-folder-prefix'. 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." - ;; Is address in mh-default-folder-list? - (let* ((address - (nth 1 (mail-extract-address-components - (mh-extract-from-header-value)))) - (folder-name - (nth 1 (assoc-ignore-case address mh-default-folder-list)))) + ;; Loop for all entries in mh-default-folder-list + (save-excursion + (let ((folder-name + (car + (delq nil + (mapcar + (lambda (list) + (let ((address-regexp (nth 0 list)) + (folder (nth 1 list)) + (to-flag (nth 2 list))) + (when (or + (mh-goto-header-field (if to-flag "To:" "From:")) + ; if the To: field is missing, try Cc: + (and to-flag (mh-goto-header-field "cc:"))) + (let ((endfield (save-excursion + (mh-header-field-end)(point)))) + (if (re-search-forward address-regexp endfield t) + folder + (when to-flag ;Try Cc: as well + (mh-goto-header-field "cc:") + (let ((endfield (save-excursion + (mh-header-field-end)(point)))) + (when (re-search-forward + address-regexp endfield t) + folder)))))))) + mh-default-folder-list))))) - ;; If not, is there an alias for the address? - (if (not folder-name) - (let* ((alias (mh-alias-address-to-alias address))) - (setq folder-name - (and alias (concat "+" mh-default-folder-prefix alias))))) + ;; Make sure a result from `mh-default-folder-list' begins with "+" + ;; since 'mh-expand-file-name below depends on it + (when (and folder-name (not (eq (aref folder-name 0) ?+))) + (setq folder-name (concat "+" folder-name))) - ;; If mh-default-folder-must-exist-flag set, check that folder exists. - (if (and folder-name - (or (not mh-default-folder-must-exist-flag) - (file-exists-p (mh-expand-file-name folder-name)))) - folder-name))) + ;; If not, is there an alias for the address? + (when (not folder-name) + (let* ((from-header (mh-extract-from-header-value)) + (address (and from-header + (nth 1 (mail-extract-address-components + from-header)))) + (alias (and address (mh-alias-address-to-alias address)))) + (when alias + (setq folder-name + (and alias (concat "+" mh-default-folder-prefix alias)))))) + + ;; If mh-default-folder-must-exist-flag set, check that folder exists. + (if (and folder-name + (or (not mh-default-folder-must-exist-flag) + (file-exists-p (mh-expand-file-name folder-name)))) + folder-name)))) (defun mh-prompt-for-refile-folder () "Prompt the user for a folder in which the message should be filed. @@ -710,29 +746,26 @@ ""))) t)) -(defun mh-refile-msg (msg-or-seq folder) - "Refile MSG-OR-SEQ (default: displayed message) into FOLDER. -If optional prefix argument provided, then prompt for message sequence. +(defun mh-refile-msg (msg-or-seq folder + &optional dont-update-last-destination-flag) + "Refile MSG-OR-SEQ into FOLDER. +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. If variable `transient-mark-mode' is non-nil and the mark is active, then the -selected region is marked for refiling." - (interactive - (list (cond - ((mh-mark-active-p t) - (cons (region-beginning) (region-end))) - (current-prefix-arg - (mh-read-seq-default "Refile" t)) - (t - (cons (line-beginning-position) (line-end-position)))) - (intern (mh-prompt-for-refile-folder)))) - (setq mh-last-destination (cons 'refile folder) - mh-last-destination-folder mh-last-destination) - (cond ((numberp msg-or-seq) - (mh-refile-a-msg msg-or-seq folder)) - ((and (consp msg-or-seq) - (numberp (car msg-or-seq)) (numberp (cdr msg-or-seq))) - (mh-iterate-on-messages-in-region () (car msg-or-seq) (cdr msg-or-seq) - (mh-refile-a-msg nil folder))) - (t (mh-map-to-seq-msgs 'mh-refile-a-msg msg-or-seq folder))) +selected region is marked for refiling. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence. + +If optional argument DONT-UPDATE-LAST-DESTINATION-FLAG is non-nil then the +variables `mh-last-destination' and `mh-last-destination-folder' are not +updated." + (interactive (list (mh-interactive-msg-or-seq "Refile") + (intern (mh-prompt-for-refile-folder)))) + (unless dont-update-last-destination-flag + (setq mh-last-destination (cons 'refile folder) + mh-last-destination-folder mh-last-destination)) + (mh-iterate-on-msg-or-seq () msg-or-seq + (mh-refile-a-msg nil folder)) (mh-next-msg)) (defun mh-refile-or-write-again (message) @@ -742,13 +775,16 @@ (interactive (list (mh-get-msg-num t))) (if (null mh-last-destination) (error "No previous refile or write")) - (cond ((eq (car mh-last-destination) 'refile) - (mh-refile-a-msg message (cdr mh-last-destination)) - (message "Destination folder: %s" (cdr mh-last-destination))) - (t - (apply 'mh-write-msg-to-file message (cdr mh-last-destination)) - (message "Destination: %s" (cdr mh-last-destination)))) - (mh-next-msg)) + (let (output) + (setq output + (cond ((eq (car mh-last-destination) 'refile) + (mh-refile-a-msg message (cdr mh-last-destination)) + (format "Destination folder: %s" (cdr mh-last-destination))) + (t + (apply 'mh-write-msg-to-file message (cdr mh-last-destination)) + (format "Destination: %s" (cdr mh-last-destination))))) + (mh-next-msg (interactive-p)) + (message output))) (defun mh-quit () "Quit the current MH-E folder. @@ -809,14 +845,17 @@ (mh-in-show-buffer (mh-show-buffer) (scroll-down arg))) -(defun mh-previous-undeleted-msg (&optional arg) - "Move to the previous undeleted message ARG in window." +(defun mh-previous-undeleted-msg (&optional arg wait-after-complaining-flag) + "Move to the previous undeleted message ARG in window. +If optional argument WAIT-AFTER-COMPLAINING-FLAG is non-nil and we are at the +first undeleted message then pause for a second after printing message." (interactive "p") (setq mh-next-direction 'backward) (beginning-of-line) (cond ((re-search-backward mh-scan-good-msg-regexp nil t arg) (mh-maybe-show)) - (t (message "No previous undeleted message")))) + (t (message "No previous undeleted message") + (if wait-after-complaining-flag (sit-for 1))))) (defun mh-previous-unread-msg (&optional count) "Move to previous unread message. @@ -994,7 +1033,6 @@ nil))) (setq mh-next-direction 'forward) (let ((threaded-flag (memq 'unthread mh-view-ops))) - (mh-reset-threads-and-narrowing) (mh-scan-folder mh-current-folder (or range "all") dont-exec-pending) (cond (threaded-flag (mh-toggle-threads)) (mh-index-data (mh-index-insert-folder-headers))))) @@ -1040,14 +1078,10 @@ Default is the displayed message. If optional prefix argument is provided, then prompt for the message sequence. If variable `transient-mark-mode' is non-nil and the mark is active, then the -selected region is unmarked." - (interactive (list (cond - ((mh-mark-active-p t) - (cons (region-beginning) (region-end))) - (current-prefix-arg - (mh-read-seq-default "Undo" t)) - (t - (mh-get-msg-num t))))) +selected region is unmarked. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence." + (interactive (list (mh-interactive-msg-or-seq "Undo"))) (cond ((numberp msg-or-seq) (let ((original-position (point))) (beginning-of-line) @@ -1064,12 +1098,8 @@ (mh-maybe-show)) (goto-char original-position) (error "Nothing to undo")))) - ((and (consp msg-or-seq) - (numberp (car msg-or-seq)) (numberp (cdr msg-or-seq))) - (mh-iterate-on-messages-in-region () (car msg-or-seq) (cdr msg-or-seq) - (mh-undo-msg nil))) - (t - (mh-map-to-seq-msgs 'mh-undo-msg msg-or-seq))) + (t (mh-iterate-on-msg-or-seq () msg-or-seq + (mh-undo-msg nil)))) (if (not (mh-outstanding-commands-p)) (mh-set-folder-modified-p nil))) @@ -1176,10 +1206,10 @@ (call-process (expand-file-name "flist" mh-progs) nil t nil "-norecurse" folder "-sequence" (symbol-name mh-unseen-seq)) (goto-char (point-min)) - (multiple-value-bind (folder1 unseen total) + (multiple-value-bind (folder unseen total) (mh-parse-flist-output-line (buffer-substring (point) (line-end-position))) - (values total unseen)))) + (values total unseen folder)))) (defun mh-visit-folder (folder &optional range index-data) "Visit FOLDER and display RANGE of messages. @@ -1197,12 +1227,12 @@ (list folder-name (mh-read-msg-range folder-name current-prefix-arg)))) (let ((config (current-window-configuration)) + (current-buffer (current-buffer)) (threaded-view-flag mh-show-threads-flag)) (save-excursion (when (get-buffer folder) (set-buffer folder) - (setq threaded-view-flag (memq 'unthread mh-view-ops)) - (mh-reset-threads-and-narrowing))) + (setq threaded-view-flag (memq 'unthread mh-view-ops)))) (when index-data (mh-make-folder folder) (setq mh-index-data (car index-data) @@ -1221,7 +1251,8 @@ (mh-index-data (mh-index-insert-folder-headers))) (unless mh-showing-mode (delete-other-windows)) - (setq mh-previous-window-config config)) + (unless (eq current-buffer (current-buffer)) + (setq mh-previous-window-config config))) nil) ;;;###mh-autoload @@ -1305,11 +1336,14 @@ (mh-notate nil mh-note-refiled mh-cmd-note) (run-hooks 'mh-refile-msg-hook))))) -(defun mh-next-msg () - "Move backward or forward to the next undeleted message in the buffer." +(defun mh-next-msg (&optional wait-after-complaining-flag) + "Move backward or forward to the next undeleted message in the buffer. +If optional argument WAIT-AFTER-COMPLAINING-FLAG is non-nil and we are at the +last message, then wait for a second after telling the user that there aren't +any more unread messages." (if (eq mh-next-direction 'forward) - (mh-next-undeleted-msg 1) - (mh-previous-undeleted-msg 1))) + (mh-next-undeleted-msg 1 wait-after-complaining-flag) + (mh-previous-undeleted-msg 1 wait-after-complaining-flag))) (defun mh-next-unread-msg (&optional count) "Move to next unread message. @@ -1406,7 +1440,10 @@ ["Widen from Sequence" mh-widen mh-narrowed-to-seq] "--" ["Narrow to Subject Sequence" mh-narrow-to-subject t] + ["Narrow to Tick Sequence" mh-narrow-to-tick + (and mh-tick-seq (mh-seq-msgs (mh-find-seq mh-tick-seq)))] ["Delete Rest of Same Subject" mh-delete-subject t] + ["Toggle Tick Mark" mh-toggle-tick t] "--" ["Push State Out to MH" mh-update-sequences t])) @@ -1459,6 +1496,7 @@ "--" ["List Folders" mh-list-folders t] ["Visit a Folder..." mh-visit-folder t] + ["View New Messages" mh-index-new-messages t] ["Search a Folder..." mh-search-folder t] ["Indexed Search..." mh-index-search t] "--" @@ -1474,6 +1512,9 @@ (set-specifier horizontal-scrollbar-visible-p nil (cons (current-buffer) nil))))) +;; Avoid compiler warnings in XEmacs and GNU Emacs 20 +(eval-when-compile (defvar tool-bar-mode)) + (defmacro mh-write-file-functions-compat () "Return `write-file-functions' if it exists. Otherwise return `local-write-file-hooks'. This macro exists purely for @@ -1483,6 +1524,9 @@ ''write-file-functions ;Emacs 21.4 ''local-write-file-hooks)) ;<Emacs 21.4, XEmacs +;; Avoid compiler warning +(defvar tool-bar-map) + (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> @@ -1519,6 +1563,8 @@ 'mh-seen-list nil ; List of displayed messages 'mh-next-direction 'forward ; Direction to move to next message 'mh-narrowed-to-seq nil ; Sequence display is narrowed to + 'mh-tick-seq-changed-when-narrowed-flag nil + ; Tick seq changed while narrowed 'mh-view-ops () ; Stack that keeps track of the order ; in which narrowing/threading has been ; carried out. @@ -1537,11 +1583,11 @@ (setq truncate-lines t) (auto-save-mode -1) (setq buffer-offer-save t) + (mh-make-local-hook (mh-write-file-functions-compat)) (add-hook (mh-write-file-functions-compat) 'mh-execute-commands nil t) (make-local-variable 'revert-buffer-function) (make-local-variable 'hl-line-mode) ; avoid pollution - (if (fboundp 'hl-line-mode) - (hl-line-mode 1)) + (mh-funcall-if-exists hl-line-mode 1) (setq revert-buffer-function 'mh-undo-folder) (or (assq 'mh-showing-mode minor-mode-alist) (setq minor-mode-alist @@ -1551,6 +1597,7 @@ (easy-menu-add mh-folder-folder-menu) (if (and (boundp 'tool-bar-mode) tool-bar-mode) (set (make-local-variable 'tool-bar-map) mh-folder-tool-bar-map)) + (mh-funcall-if-exists mh-toolbar-init :folder) (if (and mh-xemacs-flag font-lock-auto-fontify) (turn-on-font-lock))) ; Force font-lock in XEmacs. @@ -1570,7 +1617,9 @@ (cond ((null (get-buffer folder)) (mh-make-folder folder)) (t - (or dont-exec-pending (mh-process-or-undo-commands folder)) + (unless dont-exec-pending + (mh-process-or-undo-commands folder) + (mh-reset-threads-and-narrowing)) (switch-to-buffer folder))) (mh-regenerate-headers range) (if (zerop (buffer-size)) @@ -1578,7 +1627,7 @@ (message "Folder %s is empty" folder) (message "No messages in %s, range %s" folder range)) (mh-goto-cur-msg)) - (when dont-exec-pending + (when (mh-outstanding-commands-p) (mh-notate-deleted-and-refiled))) (defun mh-set-cmd-note (width) @@ -1742,6 +1791,8 @@ (if new-mail-flag (progn (mh-make-folder-mode-line) + (when (mh-speed-flists-active-p) + (mh-speed-flists t mh-current-folder)) (when (memq 'unthread mh-view-ops) (mh-thread-inc folder start-of-inc)) (mh-goto-cur-msg)) @@ -1861,8 +1912,9 @@ (if (mh-outstanding-commands-p) (if (or mh-do-not-confirm-flag (y-or-n-p - "Process outstanding deletes and refiles (or lose them)? ")) + "Process outstanding deletes and refiles? ")) (mh-process-commands folder) + (set-buffer folder) (mh-undo-folder))) (mh-update-unseen) (mh-invalidate-show-buffer)) @@ -1914,6 +1966,8 @@ ;; Redraw folder buffer if needed (when (and redraw-needed-flag) + (when (mh-speed-flists-active-p) + (mh-speed-flists t mh-current-folder)) (cond ((memq 'unthread mh-view-ops) (mh-thread-inc folder (point-max))) (mh-index-data (mh-index-insert-folder-headers))))) @@ -1962,10 +2016,10 @@ (or mh-delete-list mh-refile-list)) (defun mh-coalesce-msg-list (messages) - "Give a list of MESSAGES, return a list of message number ranges. -Sort of the opposite of `mh-read-msg-list', which expands ranges. -Message lists passed to MH programs go through this so -command line arguments won't exceed system limits." + "Given a list of MESSAGES, return a list of message number ranges. +This is the inverse of `mh-read-msg-list', which expands ranges. +Message lists passed to MH programs should be processed by this function +to avoid exceeding system command line argument limits." (let ((msgs (sort (copy-sequence messages) 'mh-greaterp)) (range-high nil) (prev -1) @@ -2059,44 +2113,84 @@ (setq msgs (cons num msgs))))) msgs)) -(defun mh-notate-user-sequences () - "Mark the scan listing of all messages in user-defined sequences." +(defun mh-notate-user-sequences (&optional msg-or-seq) + "Mark user-defined sequences in the messages specified by MSG-OR-SEQ. +The optional argument MSG-OR-SEQ can be a message number, a list of message +numbers, a sequence, a region in a cons cell, or nil in which case all +messages in the folder buffer are notated." + (unless msg-or-seq + (setq msg-or-seq (cons (point-min) (point-max)))) (let ((seqs mh-seq-list) - (msg-hash (make-hash-table))) + (msg-hash (make-hash-table)) + (tick-msgs (and mh-tick-seq (mh-seq-msgs (mh-find-seq mh-tick-seq))))) (dolist (seq seqs) (unless (mh-internal-seq (mh-seq-name seq)) (dolist (msg (mh-seq-msgs seq)) (setf (gethash msg msg-hash) t)))) - (mh-iterate-on-messages-in-region msg (point-min) (point-max) + (mh-iterate-on-msg-or-seq msg msg-or-seq (when (gethash msg msg-hash) - (mh-notate nil mh-note-seq (1+ mh-cmd-note)))))) + (mh-notate nil mh-note-seq (1+ mh-cmd-note))) + (mh-notate-tick msg tick-msgs)))) (defun mh-internal-seq (name) "Return non-nil if NAME is the name of an internal MH-E sequence." (or (memq name '(answered cur deleted forwarded printed)) (eq name mh-unseen-seq) + (and mh-tick-seq (eq name mh-tick-seq)) (eq name mh-previous-seq) (mh-folder-name-p name))) -(defun mh-delete-msg-from-seq (message sequence &optional internal-flag) - "Delete MESSAGE from SEQUENCE. -MESSAGE defaults to displayed message. From Lisp, optional third arg -INTERNAL-FLAG non-nil means do not inform MH of the change." - (interactive (list (mh-get-msg-num t) +(defun mh-delete-msg-from-seq (msg-or-seq sequence &optional internal-flag) + "Delete MSG-OR-SEQ from SEQUENCE. +Default value of MSG-OR-SEQ is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is deleted from SEQUENCE.. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence; optional third arg INTERNAL-FLAG non-nil +means do not inform MH of the change." + (interactive (list (mh-interactive-msg-or-seq "Delete") (mh-read-seq-default "Delete from" t) nil)) (let ((entry (mh-find-seq sequence))) - (cond (entry - (mh-notate-if-in-one-seq message ? (1+ mh-cmd-note) sequence) - (if (not internal-flag) - (mh-undefine-sequence sequence (list message))) - (setcdr entry (delq message (mh-seq-msgs entry))))))) + (when entry + (mh-iterate-on-msg-or-seq msg msg-or-seq + (when (memq msg (mh-seq-msgs entry)) + (mh-notate nil ? (1+ mh-cmd-note))) + (mh-delete-a-msg-from-seq msg sequence internal-flag) + (mh-clear-text-properties nil)) + (mh-notate-user-sequences msg-or-seq) + (when (and (eq sequence mh-unseen-seq) (mh-speed-flists-active-p)) + (mh-speed-flists t mh-current-folder))))) + +(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." + (let ((entry (mh-find-seq sequence))) + (when (and entry (memq msg (mh-seq-msgs entry))) + (if (not internal-flag) + (mh-undefine-sequence sequence (list msg))) + (setcdr entry (delq msg (mh-seq-msgs entry)))))) + +(defun mh-clear-text-properties (message) + "Clear all text properties (except mh-tick) from the scan line for MESSAGE." + (save-excursion + (with-mh-folder-updating (t) + (when (or (not message) (mh-goto-msg message t t)) + (beginning-of-line) + (let ((tick-property (get-text-property (point) 'mh-tick))) + (set-text-properties (point) (line-end-position) nil) + (when tick-property + (add-text-properties (point) (line-end-position) + `(mh-tick ,tick-property)))))))) (defun mh-undefine-sequence (seq msgs) "Remove from the SEQ the list of MSGS." - (mh-exec-cmd "mark" mh-current-folder "-delete" - "-sequence" (symbol-name seq) - (mh-coalesce-msg-list msgs))) + (prog1 (mh-exec-cmd "mark" mh-current-folder "-delete" + "-sequence" (symbol-name seq) + (mh-coalesce-msg-list msgs)) + (when (and (eq seq mh-unseen-seq) (mh-speed-flists-active-p)) + (mh-speed-flists t mh-current-folder)))) (defun mh-define-sequence (seq msgs) "Define the SEQ to contain the list of MSGS. @@ -2181,6 +2275,7 @@ (gnus-define-keys mh-folder-mode-map " " mh-page-msg "!" mh-refile-or-write-again + "'" mh-toggle-tick "," mh-header-display "." mh-alt-show ">" mh-write-msg-to-file @@ -2227,6 +2322,7 @@ "i" mh-index-search "k" mh-kill-folder "l" mh-list-folders + "n" mh-index-new-messages "o" mh-alt-visit-folder "p" mh-pack-folder "r" mh-rescan-folder @@ -2234,6 +2330,13 @@ "u" mh-undo-folder "v" mh-visit-folder) +(define-key mh-folder-mode-map "I" mh-inc-spool-map) + +(gnus-define-keys (mh-junk-map "J" mh-folder-mode-map) + "?" mh-prefix-help + "b" mh-junk-blacklist + "w" mh-junk-whitelist) + (gnus-define-keys (mh-sequence-map "S" mh-folder-mode-map) "?" mh-prefix-help "d" mh-delete-msg-from-seq @@ -2254,6 +2357,7 @@ "o" mh-thread-refile) (gnus-define-keys (mh-limit-map "/" mh-folder-mode-map) + "'" mh-narrow-to-tick "?" mh-prefix-help "s" mh-narrow-to-subject "w" mh-widen) @@ -2304,8 +2408,8 @@ '((nil "[i]nc, [.]show, [,]show all, [n]ext, [p]revious,\n" "[d]elete, [o]refile, e[x]ecute,\n" "[s]end, [r]eply.\n" - "Prefix characters:\n [F]older, [S]equence, MIME [K]eys, " - "[T]hread, / Limit, e[X]tract, [D]igest.") + "Prefix characters:\n [F]older, [S]equence, [J]unk, MIME [K]eys," + "\n [T]hread, / Limit, e[X]tract, [D]igest, [I]nc spools.") (?F "[l]ist, [v]isit folder;\n" "[t]hread; [s]earch; [i]ndexed search;\n" @@ -2318,7 +2422,8 @@ (?X "un[s]har, [u]udecode message") (?D "[b]urst digest") (?K "[v]iew, [i]nline, [o]utput/save MIME part; save [a]ll parts; \n" - "[TAB] next; [SHIFT-TAB] previous")) + "[TAB] next; [SHIFT-TAB] previous") + (?J "[b]lacklist, [w]hitelist message")) "Key binding cheat sheet. This is an associative array which is used to show the most common commands.
--- a/lisp/mh-e/mh-funcs.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-funcs.el Fri Apr 25 05:52:00 2003 +0000 @@ -1,6 +1,6 @@ ;;; mh-funcs.el --- MH-E functions not everyone will use right away -;; Copyright (C) 1993, 1995, 2001, 2002 Free Software Foundation, Inc. +;; Copyright (C) 1993, 1995, 2001, 02, 2003 Free Software Foundation, Inc. ;; Author: Bill Wohler <wohler@newt.com> ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -32,8 +32,6 @@ ;;; Change Log: -;; $Id: mh-funcs.el,v 1.2 2003/02/03 20:55:30 wohler Exp $ - ;;; Code: (require 'mh-e) @@ -76,33 +74,21 @@ ;;;###mh-autoload (defun mh-copy-msg (msg-or-seq folder) "Copy the specified MSG-OR-SEQ to another FOLDER without deleting them. -Default is the displayed message. If optional prefix argument is provided, -then prompt for the message sequence." - (interactive (list (cond - ((mh-mark-active-p t) - (cons (region-beginning) (region-end))) - (current-prefix-arg - (mh-read-seq-default "Copy" t)) - (t - (cons (line-beginning-position) (line-end-position)))) +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is copied. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence." + (interactive (list (mh-interactive-msg-or-seq "Copy") (mh-prompt-for-folder "Copy to" "" t))) - (let ((msg-list (cond ((numberp msg-or-seq) (list msg-or-seq)) - ((symbolp msg-or-seq) (mh-seq-to-msgs msg-or-seq)) - ((and (consp msg-or-seq) (numberp (car msg-or-seq)) - (numberp (cdr msg-or-seq))) - (let ((result ())) - (mh-iterate-on-messages-in-region msg - (car msg-or-seq) (cdr msg-or-seq) - (mh-notate nil mh-note-copied mh-cmd-note) - (push msg result)) - result)) - (t msg-or-seq)))) + (let ((msg-list (let ((result ())) + (mh-iterate-on-msg-or-seq msg msg-or-seq + (mh-notate nil mh-note-copied mh-cmd-note) + (push msg result)) + result))) (mh-exec-cmd "refile" (mh-coalesce-msg-list msg-list) - "-link" "-src" mh-current-folder folder) - (cond ((numberp msg-or-seq) - (mh-notate msg-or-seq mh-note-copied mh-cmd-note)) - ((symbolp msg-or-seq) - (mh-notate-seq msg-or-seq mh-note-copied mh-cmd-note))))) + "-link" "-src" mh-current-folder folder))) ;;;###mh-autoload (defun mh-kill-folder () @@ -111,7 +97,7 @@ and then removes the folder (directory) itself." (interactive) (if (or mh-index-data - (yes-or-no-p (format "Remove folder %s (and all included messages)?" + (yes-or-no-p (format "Remove folder %s (and all included messages)? " mh-current-folder))) (let ((folder mh-current-folder) (window-config mh-previous-window-config)) @@ -246,57 +232,60 @@ ;;;###mh-autoload (defun mh-print-msg (msg-or-seq) - "Print MSG-OR-SEQ (default: displayed message) on printer. -If optional prefix argument provided, then prompt for the message sequence. + "Print MSG-OR-SEQ on printer. +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is printed. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence. + 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 (if current-prefix-arg - (reverse (mh-seq-to-msgs - (mh-read-seq-default "Print" t))) - (mh-get-msg-num t)))) - (if (numberp msg-or-seq) - (message "Printing message...") - (message "Printing sequence...")) - (let ((print-command - (if (numberp msg-or-seq) - (format "%s -nobell -clear %s %s | %s" - (expand-file-name "mhl" mh-lib-progs) - (mh-msg-filename msg-or-seq) - (if (stringp mhl-formfile) - (format "-form %s" mhl-formfile) - "") - (format mh-lpr-command-format - (if (numberp msg-or-seq) - (format "%s/%d" mh-current-folder - msg-or-seq) - (format "Sequence from %s" mh-current-folder)))) - (format "(scan -clear %s ; %s -nobell -clear %s %s) | %s" - (mapconcat (function (lambda (msg) msg)) msg-or-seq " ") - (expand-file-name "mhl" mh-lib-progs) - (if (stringp mhl-formfile) - (format "-form %s" mhl-formfile) - "") - (mh-msg-filenames msg-or-seq) - (format mh-lpr-command-format - (if (numberp msg-or-seq) - (format "%s/%d" mh-current-folder - msg-or-seq) - (format "Sequence from %s" - mh-current-folder))))))) - (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)) - (if (numberp msg-or-seq) - (mh-notate msg-or-seq mh-note-printed mh-cmd-note) - (mh-notate-seq msg-or-seq mh-note-printed mh-cmd-note)) - (mh-add-msgs-to-seq msg-or-seq 'printed t) - (if (numberp msg-or-seq) - (message "Printing message...done") - (message "Printing sequence...done")))) - -(defun mh-msg-filenames (msgs &optional folder) - "Return a list of file names for MSGS in FOLDER (default current folder)." - (mapconcat (function (lambda (msg) (mh-msg-filename msg folder))) msgs " ")) + (interactive (list (mh-interactive-msg-or-seq "Print"))) + (message "Printing...") + (let (msgs) + ;; Gather message numbers and add them to "printed" sequence. + (mh-iterate-on-msg-or-seq msg msg-or-seq + (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 msg-or-seq) + (format "Folder: %s, Messages: %s" + mh-current-folder msgs-string)) + ((symbolp msg-or-seq) + (format "Folder: %s, Sequence: %s" + mh-current-folder msg-or-seq))))) + (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) @@ -314,7 +303,6 @@ (when mh-index-data (mh-index-update-maps mh-current-folder)) (message "Sorting folder...done") - (mh-reset-threads-and-narrowing) (mh-scan-folder mh-current-folder "all") (cond (threaded-flag (mh-toggle-threads)) (mh-index-data (mh-index-insert-folder-headers))))) @@ -334,7 +322,9 @@ (mh-unmark-all-headers t))) (t (message "Commands not undone.") - (sit-for 2)))) + ;; Remove by 2003-06-30 if nothing seems amiss. XXX + ;; (sit-for 2) + ))) ;;;###mh-autoload (defun mh-store-msg (directory) @@ -378,9 +368,9 @@ (if (looking-at "^[#:]....+\n\\( ?\n\\)?end$") nil ;most likely end of a uuencode (point)))))) - (log-buffer (get-buffer-create "*Store Output*")) (command "sh") - (uudecode-filename "(unknown filename)")) + (uudecode-filename "(unknown filename)") + log-begin) (if (not sh-start) (save-excursion (goto-char (point-min)) @@ -389,31 +379,33 @@ (buffer-substring (point) (progn (end-of-line) (point))))))) (save-excursion - (set-buffer log-buffer) - (erase-buffer) + (set-buffer (get-buffer-create mh-log-buffer)) + (setq log-begin (mh-truncate-log-buffer)) (if (not (file-directory-p store-directory)) (progn (insert "mkdir " directory "\n") - (call-process "mkdir" nil log-buffer t store-directory))) + (call-process "mkdir" nil mh-log-buffer t store-directory))) (insert "cd " directory "\n") (setq mh-store-default-directory directory) (if (not sh-start) (progn (setq command "uudecode") (insert uudecode-filename " being uudecoded...\n")))) - (set-window-start (display-buffer log-buffer) 0) ;watch progress - (let (value) - (let ((default-directory (file-name-as-directory store-directory))) - (setq value (call-process-region sh-start (point-max) command - nil log-buffer t))) - (set-buffer log-buffer) - (mh-handle-process-error command value)) - (insert "\n(mh-store finished)\n"))) + (set-window-start (display-buffer mh-log-buffer) log-begin) ;watch progress + (let ((default-directory (file-name-as-directory store-directory))) + (if (equal (call-process-region sh-start (point-max) command + nil mh-log-buffer t) + 0) + (save-excursion + (set-buffer mh-log-buffer) + (insert "\n(mh-store finished)\n")) + (error "Error occurred during execution of %s" command))))) ;;; Help Functions +;;;###mh-autoload (defun mh-ephem-message (string) "Display STRING in the minibuffer momentarily." (message "%s" string)
--- a/lisp/mh-e/mh-identity.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-identity.el Fri Apr 25 05:52:00 2003 +0000 @@ -1,6 +1,6 @@ -;;; mh-identity.el --- Multiple Identify support for MH-E. +;;; mh-identity.el --- Multiple identify support for MH-E. -;; Copyright (C) 2002 Free Software Foundation, Inc. +;; Copyright (C) 2002, 2003 Free Software Foundation, Inc. ;; Author: Peter S. Galbraith <psg@debian.org> ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -37,8 +37,6 @@ ;;; Change Log: -;; $Id: mh-identity.el,v 1.2 2003/02/03 20:55:30 wohler Exp $ - ;;; Code: @@ -169,11 +167,9 @@ (cond ;; If MIME composition done, insert signature at the end as ;; an inline MIME part. - ((and (boundp 'mh-mhn-compose-insert-flag) - mh-mhn-compose-insert-flag) + ((mh-mhn-directive-present-p) (insert "#\n" "Content-Description: Signature\n")) - ((and (boundp 'mh-mml-compose-insert-flag) - mh-mml-compose-insert-flag) + ((mh-mml-directive-present-p) (mml-insert-tag 'part 'type "text/plain" 'disposition "inline" 'description "Signature"))) @@ -182,12 +178,10 @@ (funcall value)) (goto-char (point-min)) (when (not (re-search-forward "^--" nil t)) - (if (and (boundp 'mh-mhn-compose-insert-flag) - mh-mhn-compose-insert-flag) - (forward-line 2)) - (if (and (boundp 'mh-mml-compose-insert-flag) - mh-mml-compose-insert-flag) - (forward-line 1)) + (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))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/mh-e/mh-inc.el Fri Apr 25 05:52:00 2003 +0000 @@ -0,0 +1,104 @@ +;;; mh-inc.el --- MH-E `inc' and separate mail spool handling +;; +;; Copyright (C) 2003 Free Software Foundation, Inc. + +;; Author: Peter S. Galbraith <psg@debian.org> +;; Maintainer: Bill Wohler <wohler@newt.com> +;; Keywords: mail +;; See: mh-e.el + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Support for inc. In addition to reading from the system mailbox, inc can +;; also be used to incorporate mail from multiple spool files into separate +;; folders. See `C-h v mh-inc-spool-list'. + +;;; Change Log: + +;;; Code: + +(eval-when-compile (require 'cl)) + +(defvar mh-inc-spool-map (make-sparse-keymap) + "Keymap for MH-E's mh-inc-spool commands.") + +(defvar mh-inc-spool-map-help nil + "Help text to for `mh-inc-spool-map'.") + +(define-key mh-inc-spool-map "?" + '(lambda () + (interactive) + (if mh-inc-spool-map-help + (mh-ephem-message (substring mh-inc-spool-map-help 0 -1)) + (mh-ephem-message + "There are no keys defined yet. Customize `mh-inc-spool-list'")))) + +(defun mh-inc-spool-generator (folder spool) + "Create a command to inc into FOLDER from SPOOL file." + (let ((folder1 (make-symbol "folder")) + (spool1 (make-symbol "spool"))) + (set folder1 folder) + (set spool1 spool) + (setf (symbol-function (intern (concat "mh-inc-spool-" folder))) + `(lambda () + ,(format "Inc spool file %s into folder %s" spool folder) + (interactive) + (mh-inc-folder ,spool1 (concat "+" ,folder1)))))) + +(defun mh-inc-spool-def-key (key folder) + "Define a KEY in `mh-inc-spool-map' to inc FOLDER and collect help string." + (when (not (= 0 key)) + (define-key mh-inc-spool-map (format "%c" key) + (intern (concat "mh-inc-spool-" folder))) + (setq mh-inc-spool-map-help (concat mh-inc-spool-map-help "[" + (char-to-string key) + "] inc " folder " folder\n")))) + +;; Avoid compiler warning +(eval-when-compile (defvar mh-inc-spool-list)) + +(defun mh-inc-spool-make () + "Make all commands and defines keys for contents of `mh-inc-spool-list'." + (when mh-inc-spool-list + (setq mh-inc-spool-map-help nil) + (loop for elem in mh-inc-spool-list + do (let ((spool (nth 0 elem)) + (folder (nth 1 elem)) + (key (nth 2 elem))) + (progn + (mh-inc-spool-generator folder spool) + (mh-inc-spool-def-key key folder)))))) + +;;;###mh-autoload +(defun mh-inc-spool-list-set (symbol value) + "Set-default SYMBOL to VALUE to update the `mh-inc-spool-list' variable. +Also rebuilds the user commands. +This is called after 'customize is used to alter `mh-inc-spool-list'." + (set-default symbol value) + (mh-inc-spool-make)) + +(provide 'mh-inc) + +;;; Local Variables: +;;; indent-tabs-mode: nil +;;; sentence-end-double-space: nil +;;; End: + +;;; mh-inc.el ends here
--- a/lisp/mh-e/mh-index.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-index.el Fri Apr 25 05:52:00 2003 +0000 @@ -1,6 +1,6 @@ ;;; mh-index -- MH-E interface to indexing programs -;; Copyright (C) 2002 Free Software Foundation, Inc. +;; Copyright (C) 2002, 2003 Free Software Foundation, Inc. ;; Author: Satyaki Das <satyaki@theforce.stanford.edu> ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -29,6 +29,7 @@ ;;; (1) The following search engines are supported: ;;; swish++ ;;; swish-e +;;; mairix ;;; namazu ;;; glimpse ;;; grep @@ -40,8 +41,6 @@ ;;; Change Log: -;; $Id: mh-index.el,v 1.2 2003/02/03 20:55:30 wohler Exp $ - ;;; Code: (require 'cl) @@ -165,21 +164,22 @@ will execute CMD with ARGS and pass the first `mh-index-max-cmdline-args' strings to it. This is repeated till all the strings have been used." (goto-char (point-min)) - (let ((out (get-buffer-create " *mh-xargs-output*"))) - (save-excursion - (set-buffer out) - (erase-buffer)) - (while (not (eobp)) - (let ((arg-list (reverse args)) - (count 0)) - (while (and (not (eobp)) (< count mh-index-max-cmdline-args)) - (push (buffer-substring-no-properties (point) (line-end-position)) - arg-list) - (incf count) - (forward-line)) - (apply #'call-process cmd nil (list out nil) nil (nreverse arg-list)))) - (erase-buffer) - (insert-buffer-substring out))) + (let ((current-buffer (current-buffer))) + (with-temp-buffer + (let ((out (current-buffer))) + (set-buffer current-buffer) + (while (not (eobp)) + (let ((arg-list (reverse args)) + (count 0)) + (while (and (not (eobp)) (< count mh-index-max-cmdline-args)) + (push (buffer-substring-no-properties (point) (line-end-position)) + arg-list) + (incf count) + (forward-line)) + (apply #'call-process cmd nil (list out nil) nil + (nreverse arg-list)))) + (erase-buffer) + (insert-buffer-substring out))))) @@ -230,7 +230,8 @@ (point) (line-end-position))) (forward-line) (save-excursion - (cond ((eolp) + (cond ((not (string-match "^[0-9]*$" msg))) + ((eolp) ;; need to compute checksum (set-buffer mh-checksum-buffer) (insert mh-user-path (substring folder 1) "/" msg "\n")) @@ -260,6 +261,9 @@ (mh-index-update-single-msg msg checksum origin-map))) (forward-line)))))) +(defvar mh-flists-results-folder "new" + "Subfolder for `mh-index-folder' where flists output is placed.") + (defun mh-index-generate-pretty-name (string) "Given STRING generate a name which is suitable for use as a folder name. White space from the beginning and end are removed. All spaces in the name are @@ -288,19 +292,24 @@ (subst-char-in-region (point-min) (point-max) ?\n ?_ t) (subst-char-in-region (point-min) (point-max) ?\r ?_ t) (subst-char-in-region (point-min) (point-max) ?/ ?$ t) - (truncate-string-to-width (buffer-substring (point-min) (point-max)) 20))) + (let ((out (truncate-string-to-width (buffer-string) 20))) + (cond ((eq mh-indexer 'flists) mh-flists-results-folder) + ((equal out mh-flists-results-folder) (concat out "1")) + (t out))))) ;;;###mh-autoload (defun* mh-index-search (redo-search-flag folder search-regexp - &optional window-config) + &optional window-config unseen-flag) "Perform an indexed search in an MH mail folder. +Use a prefix argument to repeat the search, as in REDO-SEARCH-FLAG below. If REDO-SEARCH-FLAG is non-nil and the current folder buffer was generated by a index search, then the search is repeated. Otherwise, FOLDER is searched with SEARCH-REGEXP and the results are presented in an MH-E folder. If FOLDER is \"+\" then mail in all folders are searched. Optional argument WINDOW-CONFIG stores the window configuration that will be restored after the user quits the -folder containing the index search results. +folder containing the index search results. If optional argument UNSEEN-FLAG +is non-nil, then all the messages are marked as unseen. Four indexing programs are supported; if none of these are present, then grep is used. This function picks the first program that is available on your @@ -381,7 +390,7 @@ (message "Processing %s output... " mh-indexer) (goto-char (point-min)) (loop for next-result = (funcall mh-index-next-result-function) - when (null next-result) return nil + while next-result do (unless (eq next-result 'error) (unless (gethash (car next-result) folder-results-map) (setf (gethash (car next-result) folder-results-map) @@ -403,9 +412,13 @@ (cons folder msg))))) folder-results-map) + ;; Mark messages as unseen (if needed) + (when (and unseen-flag (> result-count 0)) + (mh-exec-cmd "mark" index-folder "all" + "-sequence" (symbol-name mh-unseen-seq) "-add")) + ;; Generate scan lines for the hits. - (let ((mh-show-threads-flag nil)) - (mh-visit-folder index-folder () (list folder-results-map origin-map))) + (mh-visit-folder index-folder () (list folder-results-map origin-map)) (goto-char (point-min)) (forward-line) @@ -548,9 +561,8 @@ With non-nil optional argument BACKWARD-FLAG, jump to the previous group of results." (interactive "P") - (if (or (null mh-index-data) - (memq 'unthread mh-view-ops)) - (message "Only applicable in an unthreaded MH-E index search buffer") + (if (null mh-index-data) + (message "Only applicable in an MH-E index search buffer") (let ((point (point))) (forward-line (if backward-flag -1 1)) (cond ((if backward-flag @@ -628,6 +640,22 @@ (set-buffer-modified-p old-buffer-modified-flag))) ;;;###mh-autoload +(defun mh-index-group-by-folder () + "Partition the messages based on source folder. +Returns an alist with the the folder names in the car and the cdr being the +list of messages originally from that folder." + (save-excursion + (goto-char (point-min)) + (let ((result-table (make-hash-table))) + (loop for msg being hash-keys of mh-index-msg-checksum-map + do (push msg (gethash (car (gethash + (gethash msg mh-index-msg-checksum-map) + mh-index-checksum-origin-map)) + result-table))) + (loop for x being the hash-keys of result-table + collect (cons x (nreverse (gethash x result-table))))))) + +;;;###mh-autoload (defun mh-index-delete-folder-headers () "Delete the folder headers." (let ((cur-msg (mh-get-msg-num nil)) @@ -662,9 +690,28 @@ (when (not folder) (setq folder (car (gethash (gethash msg mh-index-msg-checksum-map) mh-index-checksum-origin-map)))) - (mh-visit-folder - folder (loop for x being the hash-keys of (gethash folder mh-index-data) - when (mh-msg-exists-p x folder) collect x)))) + (when (or (not (get-buffer folder)) + (y-or-n-p (format "Reuse buffer displaying %s? " folder))) + (mh-visit-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." @@ -918,7 +965,7 @@ (when (or (eobp) (and (bolp) (eolp))) (return nil)) (unless (eq (char-after) ?/) - (return error)) + (return 'error)) (let ((start (point)) end msg-start) (setq end (line-end-position)) @@ -1000,6 +1047,68 @@ +;; Interface to unseen messages script + +(defvar mh-flists-search-folders) + +(defun mh-flists-execute (&rest args) + "Search for unseen messages in `mh-flists-search-folders'. +If `mh-recursive-folders-flag' is t, then the folders are searched +recursively. All parameters ARGS are ignored." + (set-buffer (get-buffer-create mh-index-temp-buffer)) + (erase-buffer) + (unless (executable-find "sh") + (error "Didn't find sh")) + (with-temp-buffer + (let ((unseen (symbol-name mh-unseen-seq))) + (insert "for folder in `flists " + (cond ((eq mh-flists-search-folders t) mh-inbox) + ((eq mh-flists-search-folders nil) "") + ((listp mh-flists-search-folders) + (loop for folder in mh-flists-search-folders + concat (concat " " folder)))) + (if mh-recursive-folders-flag " -recurse" "") + " -sequence " unseen " -noshowzero -fast` ; do\n" + "mhpath \"+$folder\" " unseen "\n" "done\n")) + (call-process-region + (point-min) (point-max) "sh" nil (get-buffer mh-index-temp-buffer)))) + +;;;###mh-autoload +(defun mh-index-new-messages (folders) + "Display new messages. +All messages in the `mh-unseen-seq' 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." + (interactive + (list (if current-prefix-arg + (split-string (read-string "Folders to search: ")) + mh-index-new-messages-folders))) + (let* ((mh-flists-search-folders folders) + (mh-indexer 'flists) + (mh-index-execute-search-function 'mh-flists-execute) + (mh-index-next-result-function 'mh-mairix-next-result) + (mh-mairix-folder mh-user-path) + (mh-index-regexp-builder nil) + (new-folder (format "%s/%s" mh-index-folder mh-flists-results-folder)) + (window-config (if (equal new-folder mh-current-folder) + mh-previous-window-config + (current-window-configuration))) + (redo-flag nil)) + (cond ((buffer-live-p (get-buffer new-folder)) + ;; The destination folder is being visited. Trick `mh-index-search' + ;; into thinking that the folder was the result of a previous search. + (set-buffer new-folder) + (setq mh-index-previous-search (list "+" mh-flists-results-folder)) + (setq redo-flag t)) + ((mh-folder-exists-p new-folder) + ;; Folder exists but we don't have it open. That means they are + ;; stale results from a old flists search. Clear it out. + (mh-exec-cmd-quiet nil "rmf" new-folder))) + (mh-index-search redo-flag "+" mh-flists-results-folder window-config t))) + + + ;; Swish interface (defvar mh-swish-binary (executable-find "swish-e")) @@ -1163,7 +1272,7 @@ (defun mh-swish++-regexp-builder (regexp-list) "Generate query for swish++. REGEXP-LIST is an alist of fields and values." - (let ((regexp "") meta) + (let ((regexp "")) (dolist (elem regexp-list) (when (cdr elem) (setq regexp (concat regexp " and " @@ -1264,6 +1373,7 @@ +;;;###mh-autoload (defun mh-index-choose () "Choose an indexing function. The side-effects of this function are that the variables `mh-indexer',
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/mh-e/mh-junk.el Fri Apr 25 05:52:00 2003 +0000 @@ -0,0 +1,416 @@ +;;; mh-junk.el --- Interface to anti-spam measures + +;; Copyright (C) 2003 Free Software Foundation, Inc. + +;; Author: Satyaki Das <satyaki@theforce.stanford.edu>, +;; Bill Wohler <wohler@newt.com> +;; Maintainer: Bill Wohler <wohler@newt.com> +;; Keywords: mail, spam + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Spam handling in MH-E. + +;;; Change Log: + +;;; Code: + +(require 'mh-e) + +;; Interactive functions callable from the folder buffer +;;;###mh-autoload +(defun mh-junk-blacklist (msg-or-seq) + "Blacklist MSG-OR-SEQ as spam. +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is blacklisted. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence. + +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: + + - `mh-bogofilter-blacklist' + - `mh-spamprobe-blacklist' + - `mh-spamassassin-blacklist'" + (interactive (list (mh-interactive-msg-or-seq "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) ?@) + (concat mh-current-folder "/" + (substring mh-junk-mail-folder 1))) + (t (concat "+" mh-junk-mail-folder))))) + (mh-iterate-on-msg-or-seq msg msg-or-seq + (funcall (symbol-function blacklist-func) msg) + (if dest + (mh-refile-a-msg nil (intern dest)) + (mh-delete-a-msg nil))) + (mh-next-msg)))) + +;;;###mh-autoload +(defun mh-junk-whitelist (msg-or-seq) + "Whitelist MSG-OR-SEQ incorrectly classified as spam. +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is whitelisted. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence. + +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." + (interactive (list (mh-interactive-msg-or-seq "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-msg-or-seq msg msg-or-seq + (funcall (symbol-function whitelist-func) 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. + +Bogofilter is a Bayesian spam filtering program. Get it from your local +distribution or from: + http://bogofilter.sourceforge.net/ + +You first need to teach bogofilter. This is done by running + + bogofilter -n < good-message + +on every good message, and + + bogofilter -s < spam-message + +on every spam message. Most Bayesian filters need 1000 to 5000 of each to +start doing a good job. + +To use bogofilter, add the following .procmailrc recipes which you can also +find in the bogofilter man page: + + # Bogofilter + :0fw + | bogofilter -u -e -p + + :0 + * ^X-Bogosity: Yes, tests=bogofilter + $SPAM + +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"))) + +(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"))) + + + +;; Spamprobe Interface + +(defvar mh-spamprobe-executable (executable-find "spamprobe")) + +(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"))) + +(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"))) + + + +;; Spamassassin Interface + +(defvar mh-spamassassin-executable (executable-find "spamassassin")) +(defvar mh-sa-learn-executable (executable-find "sa-learn")) + +(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" + (unless mh-spamassassin-executable + (error "Couldn't 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...") + (mh-truncate-log-buffer) + (call-process mh-spamassassin-executable msg-file mh-log-buffer nil + "--report" "--remove-from-whitelist") + (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...") + (set-buffer (get-buffer-create mh-temp-buffer)) + (erase-buffer) + (call-process (expand-file-name mh-scan-prog mh-progs) nil t nil + (format "%s" msg) current-folder + "-format" "%<(mymbox{from})%|%(addr{from})%>") + (goto-char (point-min)) + (if (search-forward-regexp "^\\(.+\\)$" nil t) + (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)"))))) + +(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." + (unless mh-spamassassin-executable + (error "Couldn't find the spamassassin executable")) + (let ((msg-file (mh-msg-filename msg mh-current-folder)) + (show-buffer (get-buffer mh-show-buffer)) + from) + (save-excursion + (set-buffer (get-buffer-create mh-temp-buffer)) + (erase-buffer) + (message "Removing spamassassin markup from message...") + (call-process mh-spamassassin-executable msg-file mh-temp-buffer nil + "--remove-markup") + (if show-buffer + (kill-buffer show-buffer)) + (write-file msg-file) + (when mh-sa-learn-executable + (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:")))) + (kill-buffer nil) + (unless (equal from "") + (mh-spamassassin-add-rule "whitelist_from" from)) + (message "Whitelisting address...done")))) + +(defun mh-spamassassin-add-rule (rule body) + "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)) + (case-fold-search t) + (file (expand-file-name "~/.spamassassin/user_prefs")) + (buffer-exists (find-buffer-visiting file))) + (find-file file) + (if (not (search-forward (format "\n%s" line) nil t)) + (progn + (goto-char (point-max)) + (insert (if (bolp) "" "\n") line) + (save-buffer))) + (if (not buffer-exists) + (kill-buffer nil))))) + +(defun mh-spamassassin-identify-spammers () + "Identifies 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: + + blacklist_from *@*amazingoffersdirect2u.com" + (interactive) + (let* ((file (expand-file-name "~/.spamassassin/user_prefs")) + (domains (make-hash-table :test 'equal))) + (find-file file) + ;; Only consider entries between last blank line and end of file. + (goto-char (1- (point-max))) + (search-backward-regexp "^$") + ;; Perform frequency count. + (save-excursion + (while (search-forward-regexp "^blacklist_from\\s-*\\(.*\\)@\\(.*\\)$" + nil t) + (let ((host (match-string 2)) + value) + ;; Remove top-level-domain from hostname. + (setq host (cdr (reverse (split-string host "\\.")))) + ;; 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) + (setq host (cdr host)))))) + + ;; Output + (delete-other-windows) + (pop-to-buffer (get-buffer-create "*MH-E Spammer Frequencies*")) + (erase-buffer) + (maphash '(lambda (key value) "" + (if (> value 2) + (insert (format "%s %s\n" key value)))) + domains) + (sort-numeric-fields 2 (point-min) (point-max)) + (reverse-region (point-min) (point-max)) + (goto-char (point-min)))) + +(provide 'mh-junk) + +;;; Local Variables: +;;; indent-tabs-mode: nil +;;; sentence-end-double-space: nil +;;; End: + +;;; mh-junk.el ends here
--- a/lisp/mh-e/mh-loaddefs.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-loaddefs.el Fri Apr 25 05:52:00 2003 +0000 @@ -5,7 +5,6 @@ ;;; Keywords: mail ;;; Commentary: ;;; Change Log: -;; $Id: mh-loaddefs.el,v 1.36 2003/02/03 19:15:13 wohler Exp $ ;;; Code: ;;;### (autoloads (mh-letter-complete mh-open-line mh-fully-kill-draft @@ -13,7 +12,7 @@ ;;;;;; 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" -;;;;;; (15924 43423)) +;;;;;; (16039 39609)) ;;; Generated autoloads from mh-comp.el (autoload (quote mh-edit-again) "mh-comp" "\ @@ -29,13 +28,15 @@ See also documentation for `\\[mh-send]' function." t nil) (autoload (quote mh-forward) "mh-comp" "\ -Forward one or more messages to the recipients TO and CC. - -Use the optional MSG-OR-SEQ to specify a message or sequence to forward. +Forward messages to the recipients TO and CC. +Use optional MSG-OR-SEQ argument to specify a message or sequence to forward. +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is forwarded. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence. -Default is the displayed message. If optional prefix argument is given then -prompt for the message sequence. If variable `transient-mark-mode' is non-nil -and the mark is active, then the selected region is forwarded. See also documentation for `\\[mh-send]' function." t nil) (autoload (quote mh-redistribute) "mh-comp" "\ @@ -45,7 +46,8 @@ setting of the variable `mh-redist-full-contents'. See its documentation." t nil) (autoload (quote mh-reply) "mh-comp" "\ -Reply to MESSAGE (default: current message). +Reply to MESSAGE. +Default is the displayed message. If the optional argument REPLY-TO is not given, prompts for type of addresses to reply to: from sender only, @@ -107,8 +109,8 @@ 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 variable `mh-mhn-compose-insert-flag' is set. -Run `\\[mh-mml-to-mime]' if variable `mh-mml-compose-insert-flag' is set. +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) @@ -149,8 +151,8 @@ ;;;*** -;;;### (autoloads (mh-tool-bar-folder-set mh-tool-bar-letter-set -;;;;;; mh-customize) "mh-customize" "mh-customize.el" (15933 21842)) +;;;### (autoloads (mh-customize) "mh-customize" "mh-customize.el" +;;;;;; (16038 15647)) ;;; Generated autoloads from mh-customize.el (autoload (quote mh-customize) "mh-customize" "\ @@ -158,16 +160,10 @@ With optional argument DELETE-OTHER-WINDOWS-FLAG, other windows in the frame are removed." t nil) -(autoload (quote mh-tool-bar-letter-set) "mh-customize" "\ -Construct toolbar for `mh-letter-mode'." nil nil) - -(autoload (quote mh-tool-bar-folder-set) "mh-customize" "\ -Construct toolbar for `mh-folder-mode'." nil nil) - ;;;*** ;;;### (autoloads (mh-goto-cur-msg mh-update-sequences mh-folder-line-matches-show-buffer-p) -;;;;;; "mh-e" "mh-e.el" (15934 48879)) +;;;;;; "mh-e" "mh-e.el" (16040 30321)) ;;; Generated autoloads from mh-e.el (autoload (quote mh-folder-line-matches-show-buffer-p) "mh-e" "\ @@ -186,11 +182,11 @@ ;;;*** -;;;### (autoloads (mh-prefix-help mh-help mh-store-buffer mh-store-msg -;;;;;; mh-undo-folder mh-sort-folder mh-print-msg mh-page-digest-backwards +;;;### (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-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" -;;;;;; (15923 15465)) +;;;;;; (16039 39632)) ;;; Generated autoloads from mh-funcs.el (autoload (quote mh-burst-digest) "mh-funcs" "\ @@ -200,8 +196,12 @@ (autoload (quote mh-copy-msg) "mh-funcs" "\ Copy the specified MSG-OR-SEQ to another FOLDER without deleting them. -Default is the displayed message. If optional prefix argument is provided, -then prompt for the message sequence." t nil) +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is copied. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence." t nil) (autoload (quote mh-kill-folder) "mh-funcs" "\ Remove the current folder and all included messages. @@ -229,8 +229,14 @@ Back up displayed message to previous digested message." t nil) (autoload (quote mh-print-msg) "mh-funcs" "\ -Print MSG-OR-SEQ (default: displayed message) on printer. -If optional prefix argument provided, then prompt for the message sequence. +Print MSG-OR-SEQ on printer. +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is printed. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence. + 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) @@ -256,6 +262,9 @@ Default directory is the last directory used, or initially the value of `mh-store-default-directory' or the current directory." t nil) +(autoload (quote mh-ephem-message) "mh-funcs" "\ +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) @@ -265,7 +274,7 @@ ;;;*** ;;;### (autoloads (mh-insert-identity mh-identity-list-set mh-identity-make-menu) -;;;;;; "mh-identity" "mh-identity.el" (15900 46388)) +;;;;;; "mh-identity" "mh-identity.el" (16039 39644)) ;;; Generated autoloads from mh-identity.el (autoload (quote mh-identity-make-menu) "mh-identity" "\ @@ -283,12 +292,24 @@ ;;;*** -;;;### (autoloads (mh-namazu-execute-search mh-swish++-execute-search -;;;;;; mh-swish-execute-search mh-glimpse-execute-search mh-index-execute-commands -;;;;;; mh-index-visit-folder mh-index-delete-folder-headers mh-index-insert-folder-headers +;;;### (autoloads (mh-inc-spool-list-set) "mh-inc" "mh-inc.el" (16040 +;;;;;; 51164)) +;;; Generated autoloads from mh-inc.el + +(autoload (quote mh-inc-spool-list-set) "mh-inc" "\ +Set-default SYMBOL to VALUE to update the `mh-inc-spool-list' variable. +Also rebuilds the user commands. +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-new-messages mh-glimpse-execute-search +;;;;;; mh-index-execute-commands mh-index-update-unseen mh-index-visit-folder +;;;;;; mh-index-delete-folder-headers mh-index-group-by-folder mh-index-insert-folder-headers ;;;;;; mh-index-previous-folder mh-index-next-folder mh-index-parse-search-regexp ;;;;;; mh-index-do-search mh-index-search mh-index-update-maps) -;;;;;; "mh-index" "mh-index.el" (15924 45743)) +;;;;;; "mh-index" "mh-index.el" (16038 15647)) ;;; Generated autoloads from mh-index.el (autoload (quote mh-index-update-maps) "mh-index" "\ @@ -300,13 +321,15 @@ (autoload (quote mh-index-search) "mh-index" "\ Perform an indexed search in an MH mail folder. +Use a prefix argument to repeat the search, as in REDO-SEARCH-FLAG below. If REDO-SEARCH-FLAG is non-nil and the current folder buffer was generated by a index search, then the search is repeated. Otherwise, FOLDER is searched with SEARCH-REGEXP and the results are presented in an MH-E folder. If FOLDER is \"+\" then mail in all folders are searched. Optional argument WINDOW-CONFIG stores the window configuration that will be restored after the user quits the -folder containing the index search results. +folder containing the index search results. If optional argument UNSEEN-FLAG +is non-nil, then all the messages are marked as unseen. Four indexing programs are supported; if none of these are present, then grep is used. This function picks the first program that is available on your @@ -358,12 +381,21 @@ (autoload (quote mh-index-insert-folder-headers) "mh-index" "\ Annotate the search results with original folder names." 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 +list of messages originally from that folder." nil nil) + (autoload (quote mh-index-delete-folder-headers) "mh-index" "\ 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 @@ -403,6 +435,13 @@ FOLDER-PATH is the directory in which SEARCH-REGEXP is used to search." nil nil) +(autoload (quote mh-index-new-messages) "mh-index" "\ +Display new messages. +All messages in the `mh-unseen-seq' 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) + (autoload (quote mh-swish-execute-search) "mh-index" "\ Execute swish-e and read the results. @@ -515,16 +554,69 @@ FOLDER-PATH is the directory in which SEARCH-REGEXP is used to search." nil nil) +(autoload (quote mh-index-choose) "mh-index" "\ +Choose an indexing function. +The side-effects of this function are that the variables `mh-indexer', +`mh-index-execute-search-function', and `mh-index-next-result-function' are +set according to the first indexer in `mh-indexer-choices' present on the +system." nil nil) + +;;;*** + +;;;### (autoloads (mh-junk-whitelist mh-junk-blacklist) "mh-junk" +;;;;;; "mh-junk.el" (16023 25085)) +;;; Generated autoloads from mh-junk.el + +(autoload (quote mh-junk-blacklist) "mh-junk" "\ +Blacklist MSG-OR-SEQ as spam. +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is blacklisted. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence. + +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: + + - `mh-bogofilter-blacklist' + - `mh-spamprobe-blacklist' + - `mh-spamassassin-blacklist'" t nil) + +(autoload (quote mh-junk-whitelist) "mh-junk" "\ +Whitelist MSG-OR-SEQ incorrectly classified as spam. +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is whitelisted. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence. + +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) + ;;;*** ;;;### (autoloads (mh-mime-inline-part mh-mime-save-part mh-push-button -;;;;;; mh-press-button mh-mime-display 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-secure-message-encrypt-pgpmime mh-mml-secure-message-sign-pgpmime -;;;;;; mh-mml-attach-file mh-mml-forward-message mh-mml-to-mime -;;;;;; mh-revert-mhn-edit mh-edit-mhn mh-mhn-compose-forw mh-mhn-compose-external-compressed-tar +;;;;;; 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" (15923 15465)) +;;;;;; mh-compose-insertion) "mh-mime" "mh-mime.el" (16039 39680)) ;;; Generated autoloads from mh-mime.el (autoload (quote mh-compose-insertion) "mh-mime" "\ @@ -591,7 +683,8 @@ already inserted in the draft, fills in all the MIME components and header fields. -This step should be done last just before sending the message. +This step is performed automatically when sending the message, but this +function may be called manually before sending the draft as well. The `\\[mh-revert-mhn-edit]' command undoes this command. The arguments in the list `mh-mhn-args' are passed to mhn if this function is passed an optional @@ -602,8 +695,7 @@ from a file), \\[mh-mhn-compose-anon-ftp] (external reference to file via anonymous ftp), \\[mh-mhn-compose-external-compressed-tar] (reference to compressed tar file via anonymous ftp), and \\[mh-mhn-compose-forw] (forward -message). If these helper functions are used, `mh-edit-mhn' is run -automatically when the draft is sent. +message). The value of `mh-edit-mhn-hook' is a list of functions to be called, with no arguments, after performing the conversion. @@ -614,8 +706,13 @@ 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) + (autoload (quote mh-mml-to-mime) "mh-mime" "\ -Compose MIME message from mml directives." t nil) +Compose MIME message from mml directives. +This step is performed automatically when sending the message, but this +function may be called manually before sending the draft as well." t nil) (autoload (quote mh-mml-forward-message) "mh-mime" "\ Forward a message as attachment. @@ -640,6 +737,9 @@ 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-directive-present-p) "mh-mime" "\ +Check if the current buffer has text which may be an MML directive." nil nil) + (autoload (quote mh-mime-cleanup) "mh-mime" "\ Free the decoded MIME parts." nil nil) @@ -663,6 +763,9 @@ mh_profile directives, since this function calls on mhstore or mhn to do the actual storing." t nil) +(autoload (quote mh-decode-message-header) "mh-mime" "\ +Decode RFC2047 encoded message header fields." nil nil) + (autoload (quote mh-mime-display) "mh-mime" "\ Display (and possibly decode) MIME handles. Optional argument, PRE-DISSECTED-HANDLES is a list of MIME handles. If @@ -689,7 +792,7 @@ ;;;*** ;;;### (autoloads (mh-do-search mh-pick-do-search mh-do-pick-search -;;;;;; mh-search-folder) "mh-pick" "mh-pick.el" (15924 45743)) +;;;;;; mh-search-folder) "mh-pick" "mh-pick.el" (16037 44490)) ;;; Generated autoloads from mh-pick.el (autoload (quote mh-search-folder) "mh-pick" "\ @@ -719,14 +822,16 @@ ;;;*** -;;;### (autoloads (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-inc mh-delete-subject-or-thread +;;;### (autoloads (mh-narrow-to-tick mh-toggle-tick mh-notate-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-inc mh-delete-subject-or-thread ;;;;;; mh-delete-subject mh-narrow-to-subject mh-region-to-msg-list +;;;;;; mh-interactive-msg-or-seq mh-msg-or-seq-to-msg-list mh-iterate-on-msg-or-seq ;;;;;; 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-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" (15923 15465)) +;;;;;; "mh-seq" "mh-seq.el" (16039 39691)) ;;; Generated autoloads from mh-seq.el (autoload (quote mh-delete-seq) "mh-seq" "\ @@ -736,17 +841,21 @@ 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: current message)." t nil) +Display the sequences that contain MESSAGE. +Default is the displayed message." t nil) (autoload (quote mh-narrow-to-seq) "mh-seq" "\ Restrict display of this folder to just messages in SEQUENCE. Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command." t nil) (autoload (quote mh-put-msg-in-seq) "mh-seq" "\ -Add MSG-OR-SEQ (default: displayed message) to SEQUENCE. -If optional prefix argument provided, then prompt for the message sequence. -If variable `transient-mark-mode' is non-nil and the mark is active, then -the selected region is added to the sequence." t nil) +Add MSG-OR-SEQ to SEQUENCE. +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is added to the sequence. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence." t nil) (autoload (quote mh-widen) "mh-seq" "\ Remove restrictions from current folder, thereby showing all messages." t nil) @@ -779,6 +888,34 @@ If VAR is nil then the loop is executed without any binding." nil (quote macro)) +(autoload (quote mh-iterate-on-msg-or-seq) "mh-seq" "\ +Iterate an operation over a region or sequence. + +VAR is bound to each message in turn in a loop over MSG-OR-SEQ, which can be a +message number, a list of message numbers, a sequence, or a region in a cons +cell. In each iteration, BODY is executed. + +The parameter MSG-OR-SEQ is usually created with `mh-interactive-msg-or-seq' +in order to provide a uniform interface to MH-E functions." nil (quote macro)) + +(autoload (quote mh-msg-or-seq-to-msg-list) "mh-seq" "\ +Return a list of messages for MSG-OR-SEQ. +MSG-OR-SEQ can be a message number, a list of message numbers, a sequence, or +a region in a cons cell." nil nil) + +(autoload (quote mh-interactive-msg-or-seq) "mh-seq" "\ +Return interactive specification for message, sequence, or region. +By convention, the name of this argument is msg-or-seq. + +If variable `transient-mark-mode' is non-nil and the mark is active, then this +function returns a cons-cell of the region. +If optional prefix argument provided, then prompt for message sequence with +SEQUENCE-PROMPT and return sequence. +Otherwise, the message number at point is returned. + +This function is usually used with `mh-iterate-on-msg-or-seq' 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) @@ -829,11 +966,23 @@ (autoload (quote mh-thread-refile) "mh-seq" "\ Mark current message and all its children for refiling to FOLDER." t nil) +(autoload (quote mh-notate-tick) "mh-seq" "\ +Highlight current line if MSG is in TICKED-MSGS. +If optional argument IGNORE-NARROWING is non-nil then highlighting is carried +out even if folder is narrowed to `mh-tick-seq'." nil nil) + +(autoload (quote mh-toggle-tick) "mh-seq" "\ +Toggle tick mark of all messages in region BEGIN to END." t nil) + +(autoload (quote mh-narrow-to-tick) "mh-seq" "\ +Restrict display of this folder to just 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" (15933 21584)) +;;;;;; "mh-speed" "mh-speed.el" (16037 44491)) ;;; Generated autoloads from mh-speed.el (autoload (quote mh-folder-speedbar-buttons) "mh-speed" "\ @@ -854,7 +1003,8 @@ (autoload (quote mh-speed-flists) "mh-speed" "\ Execute flists -recurse and update message counts. -If FORCE is non-nil the timer is reset." t nil) +If FORCE is non-nil the timer is reset. If FOLDER is non-nil then flists is run +only for that one folder." t nil) (autoload (quote mh-speed-invalidate-map) "mh-speed" "\ Remove FOLDER from various optimization caches." t nil) @@ -866,7 +1016,7 @@ ;;;*** ;;;### (autoloads (mh-get-msg-num mh-goto-address-find-address-at-point) -;;;;;; "mh-utils" "mh-utils.el" (15924 47279)) +;;;;;; "mh-utils" "mh-utils.el" (16039 40655)) ;;; Generated autoloads from mh-utils.el (autoload (quote mh-goto-address-find-address-at-point) "mh-utils" "\ @@ -885,7 +1035,7 @@ ;;;;;; mh-alias-add-alias mh-alias-from-has-no-alias-p mh-alias-address-to-alias ;;;;;; mh-alias-letter-expand-alias mh-alias-minibuffer-confirm-address ;;;;;; mh-read-address mh-alias-reload) "mh-alias" "mh-alias.el" -;;;;;; (15924 45743)) +;;;;;; (16039 39579)) ;;; Generated autoloads from mh-alias.el (autoload (quote mh-alias-reload) "mh-alias" "\ @@ -904,7 +1054,9 @@ 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." nil nil) +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-add-alias) "mh-alias" "\ *Add ALIAS for ADDRESS in personal alias file.
--- a/lisp/mh-e/mh-mime.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-mime.el Fri Apr 25 05:52:00 2003 +0000 @@ -1,6 +1,6 @@ ;;; mh-mime.el --- MH-E support for composing MIME messages -;; Copyright (C) 1993, 1995, 2001, 2002 Free Software Foundation, Inc. +;; Copyright (C) 1993, 1995, 2001, 02, 2003 Free Software Foundation, Inc. ;; Author: Bill Wohler <wohler@newt.com> ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -32,8 +32,6 @@ ;;; Change Log: -;; $Id: mh-mime.el,v 1.100 2003/01/25 19:18:51 satyaki Exp $ - ;;; Code: (require 'cl) @@ -58,6 +56,7 @@ (autoload 'mml-insert-empty-tag "mml") (autoload 'mml-to-mime "mml") (autoload 'mml-attach-file "mml") +(autoload 'rfc2047-decode-region "rfc2047") ;;;###mh-autoload (defun mh-compose-insertion (&optional inline) @@ -235,7 +234,6 @@ The file specified by FILENAME is encoded as TYPE. An optional DESCRIPTION is used as the Content-Description field, optional set of ATTRIBUTES and an optional COMMENT can also be included." - (setq mh-mhn-compose-insert-flag t) (beginning-of-line) (insert "#" type) (and attributes @@ -306,7 +304,6 @@ EXTRA-PARAMS, and COMMENT. See also \\[mh-edit-mhn]." - (setq mh-mhn-compose-insert-flag t) (beginning-of-line) (insert "#@" type) (and attributes @@ -341,7 +338,6 @@ (if mh-sent-from-msg (format " [%d]" mh-sent-from-msg) ""))))) - (setq mh-mhn-compose-insert-flag t) (beginning-of-line) (insert "#forw [") (and description @@ -368,7 +364,8 @@ already inserted in the draft, fills in all the MIME components and header fields. -This step should be done last just before sending the message. +This step is performed automatically when sending the message, but this +function may be called manually before sending the draft as well. The `\\[mh-revert-mhn-edit]' command undoes this command. The arguments in the list `mh-mhn-args' are passed to mhn if this function is passed an optional @@ -379,8 +376,7 @@ from a file), \\[mh-mhn-compose-anon-ftp] (external reference to file via anonymous ftp), \\[mh-mhn-compose-external-compressed-tar] \ \(reference to compressed tar file via anonymous ftp), and \\[mh-mhn-compose-forw] (forward -message). If these helper functions are used, `mh-edit-mhn' is run -automatically when the draft is sent. +message). The value of `mh-edit-mhn-hook' is a list of functions to be called, with no arguments, after performing the conversion. @@ -396,7 +392,6 @@ (t (mh-exec-cmd-error (format "mhdraft=%s" buffer-file-name) "mhn" (if extra-args mh-mhn-args) buffer-file-name))) - (setq mh-mhn-compose-insert-flag nil) (revert-buffer t t) (message "mhn editing...done") (run-hooks 'mh-edit-mhn-hook)) @@ -429,18 +424,35 @@ (insert-file-contents backup-file)) (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." + (save-excursion + (block 'search-for-mhn-directive + (goto-char (point-min)) + (while (re-search-forward "^#" nil 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) + (return-from 'search-for-mhn-directive t))))))) + nil))) + ;;; MIME composition functions ;;;###mh-autoload (defun mh-mml-to-mime () - "Compose MIME message from mml directives." + "Compose MIME message from mml directives. +This step is performed automatically when sending the message, but this +function may be called manually before sending the draft as well." (interactive) (when mh-gnus-pgp-support-flag ;; This is only needed for PGP (message-options-set-recipient)) - (mml-to-mime) - (setq mh-mml-compose-insert-flag nil)) + (mml-to-mime)) ;;;###mh-autoload (defun mh-mml-forward-message (description folder message) @@ -460,8 +472,7 @@ (mml-attach-file (format "%s%s/%d" mh-user-path (substring folder 1) msg) "message/rfc822" - description)) - (setq mh-mml-compose-insert-flag t)) + description))) (t (error "The message number, %s is not a integer!" msg))))) ;;;###mh-autoload @@ -488,8 +499,7 @@ nil t nil nil "attachment")))) (mml-insert-empty-tag 'part 'type type 'filename file - 'disposition dispos 'description description) - (setq mh-mml-compose-insert-flag t))) + 'disposition dispos 'description description))) ;;;###mh-autoload (defun mh-mml-secure-message-sign-pgpmime () @@ -497,8 +507,7 @@ (interactive) (if (not mh-gnus-pgp-support-flag) (error "Sorry. Your version of gnus does not support PGP/GPG") - (mml-secure-message-sign-pgpmime) - (setq mh-mml-compose-insert-flag t))) + (mml-secure-message-sign-pgpmime))) ;;;###mh-autoload (defun mh-mml-secure-message-encrypt-pgpmime (&optional dontsign) @@ -507,8 +516,16 @@ (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) - (setq mh-mml-compose-insert-flag t))) + (mml-secure-message-encrypt-pgpmime dontsign))) + +;;;###mh-autoload +(defun mh-mml-directive-present-p () + "Check if the current buffer has text which may be an MML directive." + (save-excursion + (goto-char (point-min)) + (re-search-forward + "\\(<#part\\(.\\|\n\\)*>[ \n\t]*<#/part>\\|^<#secure.+>$\\)" + nil t))) @@ -547,6 +564,8 @@ (mh-defun-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." @@ -610,8 +629,7 @@ "Free the decoded MIME parts." (let ((mime-data (gethash (current-buffer) mh-globals-hash))) ;; This is for Emacs, what about XEmacs? - (cond ((fboundp 'remove-images) - (remove-images (point-min) (point-max)))) + (mh-funcall-if-exists remove-images (point-min) (point-max)) (when mime-data (mm-destroy-parts (mh-mime-handles mime-data)) (remhash (current-buffer) mh-globals-hash)))) @@ -662,6 +680,7 @@ (when (and mh-graphical-smileys-flag (fboundp 'smiley-region) (boundp 'font-lock-maximum-size) + font-lock-maximum-size (>= (/ font-lock-maximum-size 8) (buffer-size))) (smiley-region (point-min) (point-max)))) @@ -669,8 +688,8 @@ (defun mh-display-emphasis () "Function to display graphical emphasis." (when (and mh-graphical-emphasis-flag - (boundp 'font-lock-maximum-size) - (>= (/ font-lock-maximum-size 8) (buffer-size))) + (if font-lock-maximum-size + (>= (/ font-lock-maximum-size 8) (buffer-size)))) (flet ((article-goto-body ())) ; shadow this function to do nothing (save-excursion (goto-char (point-min)) @@ -685,7 +704,10 @@ (unless (>= (string-to-number emacs-version) 21) ;; XEmacs doesn't care. (set-keymap-parent map mh-show-mode-map)) - (define-key map [mouse-2] 'mh-push-button) + (mh-do-in-gnu-emacs + (define-key map [mouse-2] 'mh-push-button)) + (mh-do-in-xemacs + (define-key map '(button2) 'mh-push-button)) (dolist (c mh-mime-button-commands) (define-key map (cadr c) (car c))) map)) @@ -708,7 +730,10 @@ (unless (>= (string-to-number emacs-version) 21) (set-keymap-parent map mh-show-mode-map)) (define-key map "\r" 'mh-press-button) - (define-key map [mouse-2] 'mh-push-button) + (mh-do-in-gnu-emacs + (define-key map [mouse-2] 'mh-push-button)) + (mh-do-in-xemacs + (define-key map '(button2) 'mh-push-button)) map)) (defvar mh-mime-save-parts-directory nil @@ -755,22 +780,46 @@ (if (equal nil mh-mime-save-parts-default-directory) (setq mh-mime-save-parts-directory directory)) (save-excursion - (set-buffer (get-buffer-create " *mh-store*")) + (set-buffer (get-buffer-create mh-log-buffer)) (cd directory) (setq mh-mime-save-parts-directory directory) - (erase-buffer) - (apply 'call-process - (expand-file-name command mh-progs) nil t nil - (mh-list-to-string (list folder msg "-auto"))) - (if (> (buffer-size) 0) - (save-window-excursion - (switch-to-buffer-other-window " *mh-store*") - (sit-for 3))))))) + (let ((initial-size (mh-truncate-log-buffer))) + (apply 'call-process + (expand-file-name command mh-progs) nil t nil + (mh-list-to-string (list folder msg "-auto"))) + (if (> (buffer-size) initial-size) + (save-window-excursion + (switch-to-buffer-other-window mh-log-buffer) + (sit-for 3)))))))) ;; Avoid errors if gnus-sum isn't loaded yet... (defvar gnus-newsgroup-charset nil) (defvar gnus-newsgroup-name nil) +(defun mh-decode-message-body () + "Decode message based on charset. +If message has been encoded for transfer take that into account." + (let* ((ct (ignore-errors (mail-header-parse-content-type + (message-fetch-field "Content-Type" t)))) + (charset (mail-content-type-get ct 'charset)) + (cte (message-fetch-field "Content-Transfer-Encoding"))) + (when (stringp cte) (setq cte (mail-header-strip cte))) + (when (or (not ct) (equal (car ct) "text/plain")) + (save-restriction + (narrow-to-region (min (1+ (mh-mail-header-end)) (point-max)) + (point-max)) + (mm-decode-body charset + (and cte (intern (downcase + (gnus-strip-whitespace cte)))) + (car ct)))))) + +;;;###mh-autoload +(defun mh-decode-message-header () + "Decode RFC2047 encoded message header fields." + (when mh-decode-mime-flag + (let ((buffer-read-only nil)) + (rfc2047-decode-region (point-min) (mh-mail-header-end))))) + ;;;###mh-autoload (defun mh-mime-display (&optional pre-dissected-handles) "Display (and possibly decode) MIME handles. @@ -778,36 +827,43 @@ present they are displayed otherwise the buffer is parsed and then displayed." (let ((handles ()) - (folder mh-show-folder-buffer)) + (folder mh-show-folder-buffer) + (raw-message-data (buffer-string))) (flet ((mm-handle-set-external-undisplayer (handle function) (mh-handle-set-external-undisplayer folder handle function))) - ;; If needed dissect the current buffer - (if pre-dissected-handles - (setq handles pre-dissected-handles) - (setq handles (or (mm-dissect-buffer nil) (mm-uu-dissect))) - (setf (mh-mime-handles (mh-buffer-data)) - (mm-merge-handles handles (mh-mime-handles (mh-buffer-data)))) + (goto-char (point-min)) + (unless (search-forward "\n\n" nil t) + (goto-char (point-max)) + (insert "\n\n")) + + (condition-case err + (progn + ;; If needed dissect the current buffer + (if pre-dissected-handles + (setq handles pre-dissected-handles) + (setq handles (or (mm-dissect-buffer nil) (mm-uu-dissect))) + (setf (mh-mime-handles (mh-buffer-data)) + (mm-merge-handles handles + (mh-mime-handles (mh-buffer-data)))) + (unless handles (mh-decode-message-body))) - ;; Use charset to decode body... - (unless handles - (let* ((ct (ignore-errors - (mail-header-parse-content-type - (message-fetch-field "Content-Type" t)))) - (charset (mail-content-type-get ct 'charset))) - (when (stringp charset) - (mm-decode-body charset))))) + (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))) - (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))) + ;; 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))) + (error + (message "Please report this error. The error message is:\n %s" + (error-message-string err)) + (delete-region (point-min) (point-max)) + (insert raw-message-data)))))) (defun mh-mime-display-part (handle) "Decides the viewer to call based on the type of HANDLE." @@ -868,7 +924,8 @@ (let* ((image (mm-get-image handle))) (cond ((fboundp 'glyph-width) ;; XEmacs -- totally untested, copied from gnus - (and (< (glyph-width image) + (and (mh-funcall-if-exists glyphp image) + (< (glyph-width image) (or mh-max-inline-image-width (window-pixel-width))) (< (glyph-height image) @@ -876,8 +933,9 @@ (window-pixel-height))))) ((fboundp 'image-size) ;; Emacs21 -- copied from gnus - (let ((size (image-size image))) - (and (< (cdr size) + (let ((size (mh-funcall-if-exists image-size image))) + (and size + (< (cdr size) (or mh-max-inline-image-height (1- (window-height)))) (< (car size) @@ -889,7 +947,8 @@ (defun mh-inline-vcard-p (handle) "Decide if HANDLE is a vcard that must be displayed inline." (let ((type (mm-handle-type handle))) - (and (consp type) + (and (or (featurep 'vcard) (fboundp 'vcard-pretty-print)) + (consp type) (equal (car type) "text/x-vcard") (save-excursion (save-restriction @@ -933,6 +992,10 @@ (mh-mm-display-part handle))) (goto-char (point-max))))) +(mh-do-in-xemacs + (defvar dots) + (defvar type)) + (defun mh-insert-mime-button (handle index displayed) "Insert MIME button for HANDLE. INDEX is the part number that will be DISPLAYED. It is also used by commands @@ -999,9 +1062,9 @@ (progn ;; Delete the button and displayed part (if any) (let ((region (get-text-property point 'mh-region))) - (when region - (when (fboundp 'remove-images) - (remove-images (car region) (cdr region)))) + (when (and region (fboundp 'remove-images)) + (mh-funcall-if-exists + remove-images (car region) (cdr region))) (mm-display-part handle) (when region (delete-region (car region) (cdr region)))) @@ -1067,20 +1130,33 @@ displayed. This function is called when the mouse is used to click the MIME button." (interactive "e") - (set-buffer (window-buffer (posn-window (event-start event)))) - (select-window (posn-window (event-start event))) - (let* ((pos (posn-point (event-start event))) - (folder mh-show-folder-buffer) - (mm-inline-media-tests mh-mm-inline-media-tests) - (data (get-text-property pos 'mh-data)) - (function (get-text-property pos 'mh-callback)) - (buffer-read-only nil)) - (flet ((mm-handle-set-external-undisplayer - (handle function) - (mh-handle-set-external-undisplayer folder handle function))) - (goto-char pos) - (unwind-protect (and function (funcall function data)) - (set-buffer-modified-p nil))))) + (save-excursion + (let* ((event-window + (or (mh-funcall-if-exists posn-window (event-start event));GNU Emacs + (mh-funcall-if-exists event-window event))) ;XEmacs + (event-position + (or (mh-funcall-if-exists posn-point (event-start event)) ;GNU Emacs + (mh-funcall-if-exists event-closest-point event))) ;XEmacs + (original-window (selected-window)) + (original-position (progn + (set-buffer (window-buffer event-window)) + (set-marker (make-marker) (point)))) + (folder mh-show-folder-buffer) + (mm-inline-media-tests mh-mm-inline-media-tests) + (data (get-text-property event-position 'mh-data)) + (function (get-text-property event-position 'mh-callback)) + (buffer-read-only nil)) + (unwind-protect + (progn + (select-window event-window) + (flet ((mm-handle-set-external-undisplayer (handle func) + (mh-handle-set-external-undisplayer folder handle func))) + (goto-char event-position) + (and function (funcall function data)))) + (set-buffer-modified-p nil) + (goto-char original-position) + (set-marker original-position nil) + (select-window original-window))))) ;;;###mh-autoload (defun mh-mime-save-part () @@ -1242,6 +1318,7 @@ handles)))) (goto-char (point-min)) + (mh-show-xface) (cond (clean-message-header (mh-clean-msg-header (point-min) invisible-headers @@ -1249,7 +1326,7 @@ (goto-char (point-min))) (t (mh-start-of-uncleaned-message))) - (mh-show-xface) + (mh-decode-message-header) (mh-show-addr) ;; The other highlighting types don't need anything special (when (eq mh-highlight-citation-p 'gnus)
--- a/lisp/mh-e/mh-pick.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-pick.el Fri Apr 25 05:52:00 2003 +0000 @@ -1,6 +1,6 @@ ;;; mh-pick.el --- make a search pattern and search for a message in MH-E -;; Copyright (C) 1993, 1995, 2001 Free Software Foundation, Inc. +;; Copyright (C) 1993, 1995, 2001, 2003 Free Software Foundation, Inc. ;; Author: Bill Wohler <wohler@newt.com> ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -30,8 +30,6 @@ ;;; Change Log: -;; $Id: mh-pick.el,v 1.30 2003/01/27 04:16:47 wohler Exp $ - ;;; Code: (require 'mh-e) @@ -62,9 +60,9 @@ (mh-make-pick-template) (message "")) (setq mh-searching-function 'mh-pick-do-search - mh-searching-folder pick-folder - mh-current-folder folder - mh-previous-window-config window-config) + mh-searching-folder pick-folder) + (mh-make-local-vars 'mh-current-folder folder + 'mh-previous-window-config window-config) (message "%s" (substitute-command-keys (concat "Type \\[mh-do-search] to search messages, " "\\[mh-help] for help.")))))
--- a/lisp/mh-e/mh-seq.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-seq.el Fri Apr 25 05:52:00 2003 +0000 @@ -1,6 +1,6 @@ ;;; mh-seq.el --- MH-E sequences support -;; Copyright (C) 1993, 1995, 2001, 2002 Free Software Foundation, Inc. +;; Copyright (C) 1993, 1995, 2001, 02, 2003 Free Software Foundation, Inc. ;; Author: Bill Wohler <wohler@newt.com> ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -68,8 +68,6 @@ ;;; Change Log: -;; $Id: mh-seq.el,v 1.101 2003/01/26 00:57:35 jchonig Exp $ - ;;; Code: (require 'cl) @@ -146,8 +144,10 @@ (mh-undefine-sequence sequence '("all")) (mh-delete-seq-locally sequence) (mh-iterate-on-messages-in-region msg (point-min) (point-max) - (when (and (member msg msg-list) (not (mh-seq-containing-msg msg nil))) - (mh-notate nil ? (1+ mh-cmd-note)))))) + (cond ((and mh-tick-seq (eq sequence mh-tick-seq)) + (mh-notate-tick msg ())) + ((and (member msg msg-list) (not (mh-seq-containing-msg msg nil))) + (mh-notate nil ? (1+ mh-cmd-note))))))) ;; Avoid compiler warnings (defvar view-exit-action) @@ -195,10 +195,12 @@ ;;;###mh-autoload (defun mh-msg-is-in-seq (message) - "Display the sequences that contain MESSAGE (default: current message)." + "Display the sequences that contain MESSAGE. +Default is the displayed message." (interactive (list (mh-get-msg-num t))) (let* ((dest-folder (loop for seq in mh-refile-list - when (member message (cdr seq)) return (car seq))) + until (member message (cdr seq)) + finally return (car seq))) (deleted-flag (unless dest-folder (member message mh-delete-list)))) (message "Message %d%s is in sequences: %s" message @@ -209,6 +211,9 @@ (mh-list-to-string (mh-seq-containing-msg message t)) " ")))) +;; Avoid compiler warning +(defvar tool-bar-map) + ;;;###mh-autoload (defun mh-narrow-to-seq (sequence) "Restrict display of this folder to just messages in SEQUENCE. @@ -224,6 +229,7 @@ (setq mh-thread-scan-line-map (make-hash-table :test #'eql)) (mh-copy-seq-to-eob sequence) (narrow-to-region eob (point-max)) + (setq mh-narrowed-to-seq sequence) (mh-notate-user-sequences) (mh-notate-deleted-and-refiled) (mh-notate-cur) @@ -233,44 +239,42 @@ (setq mh-mode-line-annotation (symbol-name sequence)) (mh-make-folder-mode-line) (mh-recenter nil) - (if (and (boundp 'tool-bar-mode) tool-bar-mode) - (set (make-local-variable 'tool-bar-map) - mh-folder-seq-tool-bar-map)) - (setq mh-narrowed-to-seq sequence) + (when (and (boundp 'tool-bar-mode) tool-bar-mode) + (set (make-local-variable 'tool-bar-map) + mh-folder-seq-tool-bar-map) + (when (buffer-live-p (get-buffer mh-show-buffer)) + (save-excursion + (set-buffer (get-buffer mh-show-buffer)) + (set (make-local-variable 'tool-bar-map) + mh-show-seq-tool-bar-map)))) (push 'widen mh-view-ops))) (t (error "No messages in sequence `%s'" (symbol-name sequence)))))) ;;;###mh-autoload (defun mh-put-msg-in-seq (msg-or-seq sequence) - "Add MSG-OR-SEQ (default: displayed message) to SEQUENCE. -If optional prefix argument provided, then prompt for the message sequence. -If variable `transient-mark-mode' is non-nil and the mark is active, then -the selected region is added to the sequence." - (interactive (list (cond - ((mh-mark-active-p t) - (cons (region-beginning) (region-end))) - (current-prefix-arg - (mh-read-seq-default "Add messages from" t)) - (t - (cons (line-beginning-position) (line-end-position)))) + "Add MSG-OR-SEQ to SEQUENCE. +Default is the displayed message. +If optional prefix argument is provided, then prompt for the message sequence. +If variable `transient-mark-mode' is non-nil and the mark is active, then the +selected region is added to the sequence. +In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a +region in a cons cell, or a sequence." + (interactive (list (mh-interactive-msg-or-seq "Add messages from") (mh-read-seq-default "Add to" nil))) - (let ((internal-seq-flag (mh-internal-seq sequence)) - msg-list) - (cond ((and (consp msg-or-seq) - (numberp (car msg-or-seq)) (numberp (cdr msg-or-seq))) - (mh-iterate-on-messages-in-region m (car msg-or-seq) (cdr msg-or-seq) - (push m msg-list) - (unless internal-seq-flag - (mh-notate nil mh-note-seq (1+ mh-cmd-note)))) - (mh-add-msgs-to-seq msg-list sequence internal-seq-flag t)) - ((or (numberp msg-or-seq) (listp msg-or-seq)) - (when (numberp msg-or-seq) - (setq msg-or-seq (list msg-or-seq))) - (mh-add-msgs-to-seq msg-or-seq sequence internal-seq-flag)) - (t (mh-add-msgs-to-seq (mh-seq-to-msgs msg-or-seq) sequence))) + (when (and (interactive-p) mh-tick-seq (eq sequence mh-tick-seq)) + (error "Use `mh-toggle-tick' to add messages to %s" mh-tick-seq)) + (let* ((internal-seq-flag (mh-internal-seq sequence)) + (note-seq (if internal-seq-flag nil mh-note-seq)) + (msg-list ())) + (mh-iterate-on-msg-or-seq m msg-or-seq + (push m msg-list) + (mh-notate nil note-seq (1+ mh-cmd-note))) + (mh-add-msgs-to-seq msg-list sequence nil t) (if (not internal-seq-flag) - (setq mh-last-seq-used sequence)))) + (setq mh-last-seq-used sequence)) + (when (and (eq sequence mh-unseen-seq) (mh-speed-flists-active-p)) + (mh-speed-flists t mh-current-folder)))) (defun mh-valid-view-change-operation-p (op) "Check if the view change operation can be performed. @@ -300,13 +304,18 @@ (mh-make-folder-mode-line)) (if msg (mh-goto-msg msg t t)) + (setq mh-narrowed-to-seq nil) + (setq mh-tick-seq-changed-when-narrowed-flag nil) (mh-notate-deleted-and-refiled) (mh-notate-user-sequences) (mh-notate-cur) (mh-recenter nil))) - (if (and (boundp 'tool-bar-mode) tool-bar-mode) - (set (make-local-variable 'tool-bar-map) mh-folder-tool-bar-map)) - (setq mh-narrowed-to-seq nil)) + (when (and (boundp 'tool-bar-mode) tool-bar-mode) + (set (make-local-variable 'tool-bar-map) mh-folder-tool-bar-map) + (when (buffer-live-p (get-buffer mh-show-buffer)) + (save-excursion + (set-buffer (get-buffer mh-show-buffer)) + (set (make-local-variable 'tool-bar-map) mh-show-tool-bar-map))))) ;; FIXME? We may want to clear all notations and add one for current-message ;; and process user sequences. @@ -408,8 +417,9 @@ uses `overlay-arrow-position' to put a marker in the fringe." (let ((cur (car (mh-seq-to-msgs 'cur)))) (when (and cur (mh-goto-msg cur t t)) - (mh-notate nil mh-note-cur mh-cmd-note) (beginning-of-line) + (when (looking-at mh-scan-good-msg-regexp) + (mh-notate nil mh-note-cur mh-cmd-note)) (setq mh-arrow-marker (set-marker mh-arrow-marker (point))) (setq overlay-arrow-position mh-arrow-marker)))) @@ -431,6 +441,8 @@ ; ;; 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) "Copy SEQ to the end of the buffer." ;; It is quite involved to write something which will work at any place in @@ -455,12 +467,8 @@ (forward-line)) ;; Remove scan lines and read results from pre-computed tree (delete-region (point-min) (point-max)) - (let ((thread-tree (mh-thread-generate mh-current-folder ())) - (mh-thread-body-width - (- (window-width) mh-cmd-note - (1- mh-scan-field-subject-start-offset))) - (mh-thread-last-ancestor nil)) - (mh-thread-generate-scan-lines thread-tree -2))) + (mh-thread-print-scan-lines + (mh-thread-generate mh-current-folder ()))) (mh-index-data (mh-index-insert-folder-headers))))))) @@ -491,12 +499,83 @@ (let ((binding-needed-flag var)) `(save-excursion (goto-char ,begin) + (beginning-of-line) (while (and (<= (point) ,end) (not (eobp))) (when (looking-at mh-scan-valid-regexp) (let ,(if binding-needed-flag `((,var (mh-get-msg-num t))) ()) ,@body)) (forward-line 1))))) +(put 'mh-iterate-on-messages-in-region 'lisp-indent-hook 'defun) + +;;;###mh-autoload +(defmacro mh-iterate-on-msg-or-seq (var msg-or-seq &rest body) + "Iterate an operation over a region or sequence. + +VAR is bound to each message in turn in a loop over MSG-OR-SEQ, which can be a +message number, a list of message numbers, a sequence, or a region in a cons +cell. In each iteration, BODY is executed. + +The parameter MSG-OR-SEQ is usually created with `mh-interactive-msg-or-seq' +in order to provide a uniform interface to MH-E functions." + (unless (symbolp var) + (error "Can not bind the non-symbol %s" var)) + (let ((binding-needed-flag var) + (msgs (make-symbol "msgs")) + (seq-hash-table (make-symbol "seq-hash-table"))) + `(cond ((numberp ,msg-or-seq) + (when (mh-goto-msg ,msg-or-seq t t) + (let ,(if binding-needed-flag `((,var ,msg-or-seq)) ()) + ,@body))) + ((and (consp ,msg-or-seq) + (numberp (car ,msg-or-seq)) (numberp (cdr ,msg-or-seq))) + (mh-iterate-on-messages-in-region ,var + (car ,msg-or-seq) (cdr ,msg-or-seq) + ,@body)) + (t (let ((,msgs (if (and ,msg-or-seq (symbolp ,msg-or-seq)) + (mh-seq-to-msgs ,msg-or-seq) + ,msg-or-seq)) + (,seq-hash-table (make-hash-table))) + (dolist (msg ,msgs) + (setf (gethash msg ,seq-hash-table) t)) + (mh-iterate-on-messages-in-region v (point-min) (point-max) + (when (gethash v ,seq-hash-table) + (let ,(if binding-needed-flag `((,var v)) ()) + ,@body)))))))) + +(put 'mh-iterate-on-msg-or-seq 'lisp-indent-hook 'defun) + +;;;###mh-autoload +(defun mh-msg-or-seq-to-msg-list (msg-or-seq) + "Return a list of messages for MSG-OR-SEQ. +MSG-OR-SEQ can be a message number, a list of message numbers, a sequence, or +a region in a cons cell." + (let (msg-list) + (mh-iterate-on-msg-or-seq msg msg-or-seq + (push msg msg-list)) + (nreverse msg-list))) + +;;;###mh-autoload +(defun mh-interactive-msg-or-seq (sequence-prompt) + "Return interactive specification for message, sequence, or region. +By convention, the name of this argument is msg-or-seq. + +If variable `transient-mark-mode' is non-nil and the mark is active, then this +function returns a cons-cell of the region. +If optional prefix argument provided, then prompt for message sequence with +SEQUENCE-PROMPT and return sequence. +Otherwise, the message number at point is returned. + +This function is usually used with `mh-iterate-on-msg-or-seq' 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-seq-default sequence-prompt t)) + (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." @@ -1005,17 +1084,12 @@ (buffer-read-only nil) (old-buffer-modified-flag (buffer-modified-p))) (delete-region (point-min) (point-max)) - (let ((mh-thread-body-width (- (window-width) mh-cmd-note - (1- mh-scan-field-subject-start-offset))) - (mh-thread-last-ancestor nil)) - (mh-thread-generate-scan-lines thread-tree -2)) + (mh-thread-print-scan-lines thread-tree) (mh-notate-user-sequences) (mh-notate-deleted-and-refiled) (mh-notate-cur) (set-buffer-modified-p old-buffer-modified-flag)))) -(defvar mh-thread-last-ancestor) - (defun mh-thread-generate-scan-lines (tree level) "Generate scan lines. TREE is the hierarchical tree of messages, SCAN-LINE-MAP maps message indices @@ -1099,6 +1173,25 @@ (mh-thread-parse-scan-line (format "%s%s" spaces old-line))))) (forward-line 1)))) +(defun mh-thread-print-scan-lines (thread-tree) + "Print scan lines in THREAD-TREE in threaded mode." + (let ((mh-thread-body-width (- (window-width) mh-cmd-note + (1- mh-scan-field-subject-start-offset))) + (mh-thread-last-ancestor nil)) + (if (null mh-index-data) + (mh-thread-generate-scan-lines thread-tree -2) + (loop for x in (mh-index-group-by-folder) + do (let* ((old-map mh-thread-scan-line-map) + (mh-thread-scan-line-map (make-hash-table))) + (setq mh-thread-last-ancestor nil) + (loop for msg in (cdr x) + do (let ((v (gethash msg old-map))) + (when v + (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))))))) + (defun mh-thread-folder () "Generate thread view of folder." (message "Threading %s..." (buffer-name)) @@ -1115,10 +1208,7 @@ (let* ((range (mh-coalesce-msg-list msg-list)) (thread-tree (mh-thread-generate (buffer-name) range))) (delete-region (point-min) (point-max)) - (let ((mh-thread-body-width (- (window-width) mh-cmd-note - (1- mh-scan-field-subject-start-offset))) - (mh-thread-last-ancestor nil)) - (mh-thread-generate-scan-lines thread-tree -2)) + (mh-thread-print-scan-lines thread-tree) (mh-notate-user-sequences) (mh-notate-deleted-and-refiled) (mh-notate-cur) @@ -1137,7 +1227,7 @@ (let ((msg-list ())) (goto-char (point-min)) (while (not (eobp)) - (let ((index (mh-get-msg-num t))) + (let ((index (mh-get-msg-num nil))) (when index (push index msg-list))) (forward-line)) @@ -1161,6 +1251,7 @@ (id-index (gethash id mh-thread-id-index-map)) (duplicates (gethash id mh-thread-duplicates))) (remhash index mh-thread-index-id-map) + (remhash index mh-thread-scan-line-map) (cond ((and (eql index id-index) (null duplicates)) (remhash id mh-thread-id-index-map)) ((eql index id-index) @@ -1308,6 +1399,85 @@ (mh-refile-a-msg nil folder)) (mh-next-msg))))) + + +;; Tick mark handling + +;; Functions to highlight and unhighlight ticked messages. +(defun mh-tick-add-overlay () + "Add tick overlay to current line." + (with-mh-folder-updating (t) + (let ((overlay + (or (mh-funcall-if-exists make-overlay (point) (line-end-position)) + (mh-funcall-if-exists make-extent (point) (line-end-position))))) + (or (mh-funcall-if-exists overlay-put overlay 'face 'mh-folder-tick-face) + (mh-funcall-if-exists set-extent-face overlay 'mh-folder-tick-face)) + (mh-funcall-if-exists set-extent-priority overlay 10) + (add-text-properties (point) (line-end-position) `(mh-tick ,overlay))))) + +(defun mh-tick-remove-overlay () + "Remove tick overlay from current line." + (let ((overlay (get-text-property (point) 'mh-tick))) + (when overlay + (with-mh-folder-updating (t) + (or (mh-funcall-if-exists delete-overlay overlay) + (mh-funcall-if-exists delete-extent overlay)) + (remove-text-properties (point) (line-end-position) `(mh-tick nil)))))) + +;;;###mh-autoload +(defun mh-notate-tick (msg ticked-msgs &optional ignore-narrowing) + "Highlight current line if MSG is in TICKED-MSGS. +If optional argument IGNORE-NARROWING is non-nil then highlighting is carried +out even if folder is narrowed to `mh-tick-seq'." + (when mh-tick-seq + (let ((narrowed-to-tick (and (not ignore-narrowing) + (eq mh-narrowed-to-seq mh-tick-seq))) + (overlay (get-text-property (point) 'mh-tick)) + (in-tick (member msg ticked-msgs))) + (cond (narrowed-to-tick (mh-tick-remove-overlay)) + ((and (not overlay) in-tick) (mh-tick-add-overlay)) + ((and overlay (not in-tick)) (mh-tick-remove-overlay)))))) + +;; Interactive function to toggle tick. +;;;###mh-autoload +(defun mh-toggle-tick (begin end) + "Toggle tick mark of all messages in region BEGIN to END." + (interactive (cond ((mh-mark-active-p t) + (list (region-beginning) (region-end))) + (t (list (line-beginning-position) (line-end-position))))) + (unless mh-tick-seq + (error "Enable ticking by customizing `mh-tick-seq'")) + (let* ((tick-seq (mh-find-seq mh-tick-seq)) + (tick-seq-msgs (mh-seq-msgs tick-seq))) + (mh-iterate-on-messages-in-region msg begin end + (cond ((member msg tick-seq-msgs) + (mh-undefine-sequence mh-tick-seq (list msg)) + (setcdr tick-seq (delq msg (cdr tick-seq))) + (when (null (cdr tick-seq)) (setq mh-last-seq-used nil)) + (mh-tick-remove-overlay)) + (t + (mh-add-msgs-to-seq (list msg) mh-tick-seq nil t) + (setq mh-last-seq-used mh-tick-seq) + (mh-tick-add-overlay)))) + (when (and (eq mh-tick-seq mh-narrowed-to-seq) + (not mh-tick-seq-changed-when-narrowed-flag)) + (setq mh-tick-seq-changed-when-narrowed-flag t) + (let ((ticked-msgs (mh-seq-msgs (mh-find-seq mh-tick-seq)))) + (mh-iterate-on-messages-in-region msg (point-min) (point-max) + (mh-notate-tick msg ticked-msgs t)))))) + +;;;###mh-autoload +(defun mh-narrow-to-tick () + "Restrict display of this folder to just 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")) + (t (mh-narrow-to-seq mh-tick-seq)))) + + (provide 'mh-seq) ;;; Local Variables:
--- a/lisp/mh-e/mh-speed.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-speed.el Fri Apr 25 05:52:00 2003 +0000 @@ -1,6 +1,6 @@ ;;; mh-speed.el --- Speedbar interface for MH-E. -;; Copyright (C) 2002 Free Software Foundation, Inc. +;; Copyright (C) 2002, 2003 Free Software Foundation, Inc. ;; Author: Satyaki Das <satyaki@theforce.stanford.edu> ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -31,8 +31,6 @@ ;;; Change Log: -;; $Id: mh-speed.el,v 1.37 2003/01/31 03:18:18 satyaki Exp $ - ;;; Code: ;; Requires @@ -70,7 +68,8 @@ 'mh-speedbar-folder-face 0) (forward-line -1) (setf (gethash nil mh-speed-folder-map) - (set-marker (make-marker) (1+ (line-beginning-position)))) + (set-marker (or (gethash nil mh-speed-folder-map) (make-marker)) + (1+ (line-beginning-position)))) (add-text-properties (line-beginning-position) (1+ (line-beginning-position)) `(mh-folder nil mh-expanded nil mh-children-p t mh-level 0)) @@ -278,7 +277,9 @@ (save-excursion (forward-line -1) (setf (gethash folder-name mh-speed-folder-map) - (set-marker (make-marker) (1+ (line-beginning-position)))) + (set-marker (or (gethash folder-name mh-speed-folder-map) + (make-marker)) + (1+ (line-beginning-position)))) (add-text-properties (line-beginning-position) (1+ (line-beginning-position)) `(mh-folder ,folder-name @@ -309,8 +310,10 @@ (setq start-region (point)) (while (and (get-text-property (point) 'mh-level) (> (get-text-property (point) 'mh-level) level)) - (remhash (get-text-property (point) 'mh-folder) - mh-speed-folder-map) + (let ((folder (get-text-property (point) 'mh-folder))) + (when (gethash folder mh-speed-folder-map) + (set-marker (gethash folder mh-speed-folder-map) nil) + (remhash folder mh-speed-folder-map))) (forward-line)) (delete-region start-region (point)) (forward-line -1) @@ -344,24 +347,29 @@ (delete-other-windows))))) (defvar mh-speed-current-folder nil) +(defvar mh-speed-flists-folder nil) ;;;###mh-autoload -(defun mh-speed-flists (force) +(defun mh-speed-flists (force &optional folder) "Execute flists -recurse and update message counts. -If FORCE is non-nil the timer is reset." +If FORCE is non-nil the timer is reset. If FOLDER is non-nil then flists is run +only for that one folder." (interactive (list t)) (when force - (when (timerp mh-speed-flists-timer) - (cancel-timer mh-speed-flists-timer)) - (setq mh-speed-flists-timer nil) + (when mh-speed-flists-timer + (cancel-timer mh-speed-flists-timer) + (setq mh-speed-flists-timer nil)) (when (and (processp mh-speed-flists-process) (not (eq (process-status mh-speed-flists-process) 'exit))) + (set-process-filter mh-speed-flists-process t) (kill-process mh-speed-flists-process) + (setq mh-speed-partial-line "") (setq mh-speed-flists-process nil))) + (setq mh-speed-flists-folder folder) (unless mh-speed-flists-timer (setq mh-speed-flists-timer (run-at-time - nil mh-speed-flists-interval + nil (and mh-speed-run-flists-flag mh-speed-flists-interval) (lambda () (unless (and (processp mh-speed-flists-process) (not (eq (process-status mh-speed-flists-process) @@ -376,8 +384,11 @@ (setq mh-speed-flists-process (start-process "*flists*" nil (expand-file-name "flists" mh-progs) - "-recurse" + (or mh-speed-flists-folder "-recurse") + (if mh-speed-flists-folder "-noall" "-all") "-sequence" (symbol-name mh-unseen-seq))) + ;; Run flists on all folders the next time around... + (setq mh-speed-flists-folder nil) (set-process-filter mh-speed-flists-process 'mh-speed-parse-flists-output))))))) @@ -397,7 +408,10 @@ mh-speed-partial-line "") (multiple-value-setq (folder unseen total) (mh-parse-flist-output-line line mh-speed-current-folder)) - (when (and folder unseen total) + (when (and folder unseen total + (let ((old-pair (gethash folder mh-speed-flists-cache))) + (or (not (equal (car old-pair) unseen)) + (not (equal (cdr old-pair) total))))) (setf (gethash folder mh-speed-flists-cache) (cons unseen total)) (save-excursion (when (buffer-live-p (get-buffer speedbar-buffer)) @@ -514,7 +528,8 @@ (insert-char char 1 t) (put-text-property (point) (1- (point)) 'invisible nil) ;; make sure we fix the image on the text here. - (speedbar-insert-image-button-maybe (- (point) 2) 3))))) + (mh-funcall-if-exists + speedbar-insert-image-button-maybe (- (point) 2) 3))))) (provide 'mh-speed)
--- a/lisp/mh-e/mh-utils.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-utils.el Fri Apr 25 05:52:00 2003 +0000 @@ -1,6 +1,7 @@ ;;; mh-utils.el --- MH-E code needed for both sending and reading -;; Copyright (C) 1993, 1995, 1997, 2000, 2001, 2002 Free Software Foundation, Inc. +;; Copyright (C) 1993, 95, 1997, +;; 2000, 01, 02, 2003 Free Software Foundation, Inc. ;; Author: Bill Wohler <wohler@newt.com> ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -30,8 +31,6 @@ ;;; Change Log: -;; $Id: mh-utils.el,v 1.2 2003/02/03 20:55:30 wohler Exp $ - ;;; Code: ;; Is this XEmacs-land? Located here since needed by mh-customize.el. @@ -57,7 +56,7 @@ ;;; Autoloads (autoload 'gnus-article-highlight-citation "gnus-cite") -(autoload 'mail-header-end "sendmail") +(require 'sendmail) (autoload 'Info-goto-node "info") (unless (fboundp 'make-hash-table) (autoload 'make-hash-table "cl")) @@ -100,7 +99,30 @@ when (equal (aref string index) char) return index finally return nil)) -;;; Macro to generate correct code for different emacs variants +;;; 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. @@ -287,19 +309,6 @@ (".*" mm-inline-text mm-readable-p)) "Alist of media types/tests saying whether types can be displayed inline.") -;; Needed by mh-comp.el and mh-mime.el -(defvar mh-mhn-compose-insert-flag nil - "Non-nil means MIME insertion was done. -Triggers an automatic call to `mh-edit-mhn' in `mh-send-letter'. -This variable is buffer-local.") -(make-variable-buffer-local 'mh-mhn-compose-insert-flag) - -(defvar mh-mml-compose-insert-flag nil - "Non-nil means that a MIME insertion was done. -This buffer-local variable is used to remember if a MIME insertion was done. -Triggers an automatic call to `mh-mml-to-mime' in `mh-send-letter'.") -(make-variable-buffer-local 'mh-mml-compose-insert-flag) - ;; Copy of `goto-address-mail-regexp' (defvar mh-address-mail-regexp "[-a-zA-Z0-9._]+@[-a-zA-z0-9_]+\\.+[a-zA-Z0-9]+" @@ -318,9 +327,17 @@ (goto-char (match-beginning 0)))) (match-string-no-properties 0))) +(defun mh-mail-header-end () + "Substitute for `mail-header-end' that doesn't widen the buffer. +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) + (point))) + (defun mh-in-header-p () "Return non-nil if the point is in the header of a draft message." - (< (point) (mail-header-end))) + (< (point) (mh-mail-header-end))) (defun mh-header-field-beginning () "Move to the beginning of the current header field. @@ -342,7 +359,7 @@ Argument LIMIT limits search." (if (= (point) limit) nil - (let* ((mail-header-end (save-match-data (mail-header-end))) + (let* ((mail-header-end (save-match-data (mh-mail-header-end))) (lesser-limit (if (< mail-header-end limit) mail-header-end limit))) (when (mh-in-header-p) (set-match-data (list 1 lesser-limit)) @@ -354,7 +371,7 @@ Argument LIMIT limits search." (if (= (point) limit) nil - (let* ((mail-header-end (mail-header-end)) + (let* ((mail-header-end (mh-mail-header-end)) (lesser-limit (if (< mail-header-end limit) mail-header-end limit)) (case-fold-search t)) (when (and (< (point) mail-header-end) ;Only within header @@ -424,7 +441,7 @@ dealt with by gnus highlighting. The region between BEG and END is given over to be fontified and LOUDLY controls if a user sees a message about the fontification operation." - (let ((header-end (mail-header-end))) + (let ((header-end (mh-mail-header-end))) (cond ((and (< beg header-end)(< end header-end)) (font-lock-default-fontify-region beg end loudly)) @@ -501,6 +518,10 @@ (defconst mh-log-buffer "*MH-E Log*") ;output of MH commands and so on (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) ;; Window configuration before MH-E command. (defvar mh-previous-window-config nil) @@ -535,14 +556,23 @@ (defun mh-logo-display () "Modify mode line to display MH-E logo." - (when (fboundp 'find-image) - (add-text-properties - 0 2 - `(display ,(or mh-logo-cache - (setq mh-logo-cache - (find-image '((:type xpm :ascent center - :file "mh-logo.xpm")))))) - (car mode-line-buffer-identification)))) + (mh-do-in-gnu-emacs + (add-text-properties + 0 2 + `(display ,(or mh-logo-cache + (setq mh-logo-cache + (mh-funcall-if-exists + find-image '((:type xpm :ascent center + :file "mh-logo.xpm")))))) + (car mode-line-buffer-identification))) + (mh-do-in-xemacs + (setq modeline-buffer-identification + (list + (if mh-modeline-glyph + (cons modeline-buffer-id-left-extent mh-modeline-glyph) + (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) @@ -585,7 +615,7 @@ ,@(if (not save-modification-flag) '((mh-set-folder-modified-p nil))))) -(put 'with-mh-folder-updating 'lisp-indent-hook 1) +(put 'with-mh-folder-updating 'lisp-indent-hook 'defun) (defmacro mh-in-show-buffer (show-buffer &rest body) "Format is (mh-in-show-buffer (SHOW-BUFFER) &body BODY). @@ -600,7 +630,7 @@ ,@body) (select-window mh-in-show-buffer-saved-window)))) -(put 'mh-in-show-buffer 'lisp-indent-hook 1) +(put 'mh-in-show-buffer 'lisp-indent-hook 'defun) (defmacro mh-make-seq (name msgs) "Create sequence NAME with the given MSGS." @@ -726,11 +756,11 @@ folder-buffer) (delete-other-windows)) (mh-goto-cur-msg t) - (and (fboundp 'deactivate-mark) (deactivate-mark)) + (mh-funcall-if-exists deactivate-mark) (unwind-protect (prog1 (call-interactively (function ,original-function)) (setq normal-exit t)) - (and (fboundp 'deactivate-mark) (deactivate-mark)) + (mh-funcall-if-exists deactivate-mark) (cond ((not normal-exit) (set-window-configuration config)) ,(if dont-return @@ -819,11 +849,17 @@ (mh-defun-show-buffer mh-show-thread-previous-sibling mh-thread-previous-sibling) (mh-defun-show-buffer mh-show-index-visit-folder mh-index-visit-folder t) +(mh-defun-show-buffer mh-show-toggle-tick mh-toggle-tick) +(mh-defun-show-buffer mh-show-narrow-to-tick mh-narrow-to-tick) +(mh-defun-show-buffer mh-show-junk-blacklist mh-junk-blacklist) +(mh-defun-show-buffer mh-show-junk-whitelist mh-junk-whitelist) +(mh-defun-show-buffer mh-show-index-new-messages mh-index-new-messages) ;;; Populate mh-show-mode-map (gnus-define-keys mh-show-mode-map " " mh-show-page-msg "!" mh-show-refile-or-write-again + "'" mh-show-toggle-tick "," mh-show-header-display "." mh-show-show ">" mh-show-write-message-to-file @@ -867,6 +903,7 @@ "i" mh-index-search "k" mh-show-kill-folder "l" mh-show-list-folders + "n" mh-index-new-messages "o" mh-show-visit-folder "r" mh-show-rescan-folder "s" mh-show-search-folder @@ -884,6 +921,13 @@ "s" mh-show-msg-is-in-seq "w" mh-show-widen) +(define-key mh-show-mode-map "I" mh-inc-spool-map) + +(gnus-define-keys (mh-show-junk-map "J" mh-show-mode-map) + "?" mh-prefix-help + "b" mh-show-junk-blacklist + "w" mh-show-junk-whitelist) + (gnus-define-keys (mh-show-thread-map "T" mh-show-mode-map) "?" mh-prefix-help "u" mh-show-thread-ancestor @@ -894,6 +938,7 @@ "o" mh-show-thread-refile) (gnus-define-keys (mh-show-limit-map "/" mh-show-mode-map) + "'" mh-show-narrow-to-tick "?" mh-prefix-help "s" mh-show-narrow-to-subject "w" mh-show-widen) @@ -932,7 +977,12 @@ ["Widen from Sequence" mh-show-widen t] "--" ["Narrow to Subject Sequence" mh-show-narrow-to-subject t] + ["Narrow to Tick Sequence" mh-show-narrow-to-tick + (save-excursion + (set-buffer mh-show-folder-buffer) + (and mh-tick-seq (mh-seq-msgs (mh-find-seq mh-tick-seq))))] ["Delete Rest of Same Subject" mh-show-delete-subject t] + ["Toggle Tick Mark" mh-show-toggle-tick t] "--" ["Push State Out to MH" mh-show-update-sequences t])) @@ -979,6 +1029,7 @@ "--" ["List Folders" mh-show-list-folders t] ["Visit a Folder..." mh-show-visit-folder t] + ["View New Messages" mh-show-index-new-messages t] ["Search a Folder..." mh-show-search-folder t] ["Indexed Search..." mh-index-search t] "--" @@ -988,6 +1039,9 @@ ;;; Ensure new buffers won't get this mode if default-major-mode is nil. (put 'mh-show-mode 'mode-class 'special) +;; Avoid compiler warning +(defvar tool-bar-map) + (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 @@ -1015,7 +1069,9 @@ (turn-on-font-lock)) (if (and (boundp 'tool-bar-mode) tool-bar-mode) (set (make-local-variable 'tool-bar-map) mh-show-tool-bar-map)) + (mh-funcall-if-exists mh-toolbar-init :show) (when mh-decode-mime-flag + (mh-make-local-hook 'kill-buffer-hook) (add-hook 'kill-buffer-hook 'mh-mime-cleanup nil t)) (easy-menu-add mh-show-sequence-menu) (easy-menu-add mh-show-message-menu) @@ -1034,27 +1090,226 @@ (if (fboundp 'goto-address) (goto-address)))) + + +;; X-Face and Face display (defvar mh-show-xface-function - (cond ((and mh-xemacs-flag (locate-library "x-face")) + (cond ((and mh-xemacs-flag (locate-library "x-face") (not (featurep 'xface))) (load "x-face" t t) - (if (fboundp 'x-face-xmas-wl-display-x-face) - #'x-face-xmas-wl-display-x-face - #'ignore)) - ((and (not mh-xemacs-flag) (>= emacs-major-version 21)) - (load "x-face-e21" t t) - (if (fboundp 'x-face-decode-message-header) - #'x-face-decode-message-header - #'ignore)) + #'mh-face-display-function) + ((>= emacs-major-version 21) + #'mh-face-display-function) (t #'ignore)) "Determine at run time what function should be called to display X-Face.") +(defvar mh-uncompface-executable + (and (fboundp 'executable-find) (executable-find "uncompface"))) + +(defun mh-face-to-png (data) + "Convert base64 encoded DATA to png image." + (with-temp-buffer + (insert data) + (ignore-errors (base64-decode-region (point-min) (point-max))) + (buffer-string))) + +(defun mh-uncompface (data) + "Run DATA through `uncompface' to generate bitmap." + (with-temp-buffer + (insert data) + (when (and mh-uncompface-executable + (equal (call-process-region (point-min) (point-max) + mh-uncompface-executable t '(t nil)) + 0)) + (mh-icontopbm) + (buffer-string)))) + +(defun mh-icontopbm () + "Elisp substitute for `icontopbm'." + (goto-char (point-min)) + (let ((end (point-max))) + (while (re-search-forward "0x\\(..\\)\\(..\\)," nil t) + (save-excursion + (goto-char (point-max)) + (insert (string-to-number (match-string 1) 16)) + (insert (string-to-number (match-string 2) 16)))) + (delete-region (point-min) end) + (goto-char (point-min)) + (insert "P4\n48 48\n"))) + +(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." + (save-restriction + (goto-char (point-min)) + (re-search-forward "\n\n" (point-max) t) + (narrow-to-region (point-min) (point)) + (let* ((case-fold-search t) + (default-enable-multibyte-characters nil) + (face (message-fetch-field "face" t)) + (x-face (message-fetch-field "x-face" t)) + (url (message-fetch-field "x-image-url" t)) + raw type) + (cond (face (setq raw (mh-face-to-png face) + type 'png)) + (x-face (setq raw (mh-uncompface x-face) + type 'pbm)) + (url (setq type 'url))) + (when type + (goto-char (point-min)) + (when (re-search-forward "^from:" (point-max) t) + ;; GNU Emacs + (mh-do-in-gnu-emacs + (if (eq type 'url) + (mh-x-image-url-display url) + (mh-funcall-if-exists + insert-image (create-image + raw type t + :foreground (face-foreground 'mh-show-xface-face) + :background (face-background 'mh-show-xface-face)) + " "))) + ;; XEmacs + (mh-do-in-xemacs + (cond + ((eq type 'url) + (mh-x-image-url-display url)) + ((eq type 'png) + (when (featurep 'png) + (set-extent-begin-glyph + (make-extent (point) (point)) + (make-glyph (vector 'png ':data (mh-face-to-png face)))))) + ;; Try internal xface support if available... + ((and (eq type 'pbm) (featurep 'xface)) + (set-glyph-face + (set-extent-begin-glyph + (make-extent (point) (point)) + (make-glyph (vector 'xface ':data (concat "X-Face: " x-face)))) + 'mh-show-xface-face)) + ;; Otherwise try external support with x-face... + ((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))) + (when raw (insert " ")))))))) + + (defun mh-show-xface () "Display X-Face." - (when (and mh-show-use-xface-flag + (when (and window-system mh-show-use-xface-flag (or mh-decode-mime-flag mhl-formfile mh-clean-message-header-flag)) (funcall mh-show-xface-function))) + + +;; 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-temp-file nil) +(defvar mh-x-image-url nil) +(defvar mh-x-image-marker nil) +(defvar mh-x-image-url-cache-file nil) + +(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)))) + +(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"))) + (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) + 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)))) + +(defun mh-x-image-display (image marker) + "Display IMAGE at MARKER." + (save-excursion + (set-buffer (marker-buffer marker)) + (let ((buffer-read-only nil) + (default-enable-multibyte-characters nil) + (buffer-modified-flag (buffer-modified-p))) + (unwind-protect + (when (and (file-readable-p image) (not (file-symlink-p image))) + (goto-char marker) + (mh-do-in-gnu-emacs + (mh-funcall-if-exists insert-image (create-image image 'png))) + (mh-do-in-xemacs + (when (featurep 'png) + (set-extent-begin-glyph + (make-extent (point) (point)) + (make-glyph + (vector 'png ':data (with-temp-buffer + (insert-file-contents-literally image) + (buffer-string)))))))) + (set-buffer-modified-p buffer-modified-flag))))) + +(defun mh-x-image-scale-and-display (process change) + "When the wget PROCESS terminates scale and display image. +The argument CHANGE is ignored." + (when (eq (process-status process) 'exit) + (let (marker temp-file cache-filename wget-buffer) + (save-excursion + (set-buffer (setq wget-buffer (process-buffer process))) + (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)) + (ignore-errors + (set-marker marker nil) + (delete-process process) + (kill-buffer wget-buffer) + (delete-file temp-file))))) + +(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) + (mh-x-image-display cache-filename marker)) + ((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)) + (mh-x-image-url-fetch-image url cache-filename marker + 'mh-x-image-scale-and-display))))) + + + (defun mh-maybe-show (&optional msg) "Display message at cursor, but only if in show mode. If optional arg MSG is non-nil, display that message instead." @@ -1110,6 +1365,7 @@ (if (not (memq msg mh-seen-list)) (setq mh-seen-list (cons msg mh-seen-list))) (when mh-update-sequences-after-mh-show-flag + (if mh-index-data (mh-index-update-unseen msg)) (mh-update-sequences)) (run-hooks 'mh-show-hook)) @@ -1147,32 +1403,12 @@ (delete-other-windows) (switch-to-buffer edit-buffer))) -(defun mh-decode-content-transfer-encoded-message () - "Run mimencode on message body, if needed." - (let ((case-fold-search t) - (header-end (mail-header-end))) - (goto-char (point-min)) - (when (re-search-forward "^content-transfer-encoding: " header-end t) - (let ((enc (buffer-substring-no-properties (point) (line-end-position))) - cmdline) - (setq cmdline - (cond ((string-match "base64" enc) (list "-u" "-b" "-p")) - ((string-match "quoted-printable" enc) (list "-u" "-q")) - (t nil))) - (when cmdline - (beginning-of-line) - (insert "Removed-") - (setq header-end (mail-header-end)) - (goto-char (1+ header-end)) - (apply #'call-process-region (1+ header-end) (point-max) "mimencode" - t t nil cmdline)))))) - (defun mh-show-unquote-From () "Decode >From at beginning of lines for `mh-show-mode'." (save-excursion (let ((modified (buffer-modified-p)) (case-fold-search nil)) - (goto-char (mail-header-end)) + (goto-char (mh-mail-header-end)) (while (re-search-forward "^>From" nil t) (replace-match "From")) (set-buffer-modified-p modified)))) @@ -1226,8 +1462,6 @@ (list "-form" formfile)) msg-filename) (insert-file-contents-literally msg-filename)) - (if mh-decode-content-transfer-encoded-message-flag - (mh-decode-content-transfer-encoded-message)) ;; Cleanup old mime handles (mh-mime-cleanup) ;; Use mm to display buffer @@ -1235,6 +1469,7 @@ (mh-add-missing-mime-version-header) (setf (mh-buffer-data) (mh-make-buffer-data)) (mh-mime-display)) + (mh-show-mode) ;; Header cleanup (goto-char (point-min)) (cond (clean-message-header @@ -1244,6 +1479,7 @@ (goto-char (point-min))) (t (mh-start-of-uncleaned-message))) + (mh-decode-message-header) ;; the parts of visiting we want to do (no locking) (or (eq buffer-undo-list t) ;don't save undo info for prev msgs (setq buffer-undo-list nil)) @@ -1253,7 +1489,6 @@ (setq buffer-backed-up nil) (auto-save-mode 1) (set-mark nil) - (mh-show-mode) (unwind-protect (when (and mh-decode-mime-flag (not formfile)) (setq buffer-read-only nil) @@ -1276,6 +1511,7 @@ from the header. VISIBLE-HEADERS contains a regular expression specifying the lines to display. INVISIBLE-HEADERS is ignored if VISIBLE-HEADERS is non-nil." (let ((case-fold-search t) + (buffer-read-only nil) (after-change-functions nil)) ;Work around emacs-20 font-lock bug ;causing an endless loop. (save-restriction @@ -1306,15 +1542,17 @@ (defun mh-notate (msg notation offset) "Mark MSG with the character NOTATION at position OFFSET. -Null MSG means the message at cursor." +Null MSG means the message at cursor. +If NOTATION is nil then no change in the buffer occurs." (save-excursion (if (or (null msg) (mh-goto-msg msg t t)) (with-mh-folder-updating (t) (beginning-of-line) (forward-char offset) - (delete-char 1) - (insert notation))))) + (let ((notation (or notation (char-after)))) + (delete-char 1) + (insert notation)))))) (defun mh-find-msg-get-num (step) "Return the message number of the message nearest the cursor. @@ -1405,6 +1643,9 @@ (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 @@ -1542,7 +1783,7 @@ (set-buffer tmp-buffer) (erase-buffer) (apply 'call-process - (expand-file-name "scan" mh-progs) nil '(t nil) nil + (expand-file-name mh-scan-prog mh-progs) nil '(t nil) nil (list folder "last" "-format" "%(msg)")) (goto-char (point-min)) (if (re-search-forward mh-scan-msg-number-regexp nil 0 1) @@ -1582,6 +1823,7 @@ sorted-msgs)) (defvar mh-sub-folders-cache (make-hash-table :test #'equal)) +(defvar mh-current-folder-name nil) (defun mh-normalize-folder-name (folder &optional empty-string-okay dont-remove-trailing-slash) @@ -1602,8 +1844,18 @@ (setq folder (replace-match "/" nil t folder))) (let* ((length (length folder)) (trailing-slash-present (and (> length 0) - (equal (aref folder (1- length)) ?/)))) - (let ((components (split-string folder "/")) + (equal (aref folder (1- length)) ?/))) + (leading-slash-present (and (> length 0) + (equal (aref folder 0) ?/)))) + (when (and (> length 0) (equal (aref folder 0) ?@) + (stringp mh-current-folder-name)) + (setq folder (format "%s/%s/" mh-current-folder-name + (substring folder 1)))) + ;; XXX: Purge empty strings from the list that split-string returns. In + ;; XEmacs, (split-string "+foo/" "/") returns ("+foo" "") while in GNU + ;; Emacs it returns ("+foo"). In the code it is assumed that the + ;; components list has no empty strings. + (let ((components (delete "" (split-string folder "/"))) (result ())) ;; Remove .. and . from the pathname. (dolist (component components) @@ -1618,7 +1870,9 @@ ;; Remove trailing '/' if needed. (unless (and trailing-slash-present dont-remove-trailing-slash) (when (not (equal folder "")) - (setq folder (substring folder 0 (1- (length folder)))))))) + (setq folder (substring folder 0 (1- (length folder)))))) + (when leading-slash-present + (setq folder (concat "/" folder))))) (cond ((and empty-string-okay (equal folder ""))) ((equal folder "") (setq folder "+")) ((not (equal (aref folder 0) ?+)) (setq folder (concat "+" folder))))) @@ -1713,9 +1967,23 @@ (defvar mh-folder-hist nil) (defvar mh-speed-folder-map) +(defvar mh-speed-flists-cache) + +(defvar mh-allow-root-folder-flag nil + "Non-nil means \"+\" is an acceptable folder name. +This variable is used to communicate with `mh-folder-completion-function'. That +function can have exactly three arguments so we bind this variable to t or nil. + +This variable should never be set.") + (defvar mh-folder-completion-map (copy-keymap minibuffer-local-completion-map)) (define-key mh-folder-completion-map " " 'minibuffer-complete) +(defun mh-speed-flists-active-p () + "Check if speedbar is running with message counts enabled." + (and (featurep 'mh-speed) + (> (hash-table-count mh-speed-flists-cache) 0))) + (defun mh-folder-completion-function (name predicate flag) "Programmable completion for folder names. NAME is the partial folder name that has been input. PREDICATE if non-nil is a @@ -1747,14 +2015,19 @@ (all-completions remainder (mh-sub-folders last-complete t) predicate)) ((eq flag 'lambda) - (file-exists-p - (concat mh-user-path - (substring (mh-normalize-folder-name name) 1))))))) + (let ((path (concat mh-user-path + (substring (mh-normalize-folder-name name) 1)))) + (cond (mh-allow-root-folder-flag (file-exists-p path)) + ((equal path mh-user-path) nil) + (t (file-exists-p path)))))))) -(defun mh-folder-completing-read (prompt default) - "Read folder name with PROMPT and default result DEFAULT." +(defun mh-folder-completing-read (prompt default allow-root-folder-flag) + "Read folder name with PROMPT and default result DEFAULT. +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-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)) t)) @@ -1775,8 +2048,10 @@ ((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 prompt default)) + (while (and (setq read-name (mh-folder-completing-read + prompt default allow-root-folder-flag)) (equal read-name "") (equal default ""))) (cond ((or (equal read-name "") @@ -1790,6 +2065,14 @@ (cond ((and (> (length folder-name) 0) (eq (aref folder-name (1- (length folder-name))) ?/)) (setq folder-name (substring folder-name 0 -1)))) + (let* ((last-slash (mh-search-from-end ?/ folder-name)) + (parent (and last-slash (substring folder-name 0 last-slash))) + (child (if last-slash + (substring folder-name (1+ last-slash)) + (substring folder-name 1)))) + (unless (member child + (mapcar #'car (gethash parent mh-sub-folders-cache))) + (mh-remove-from-sub-folders-cache folder-name))) (let ((new-file-flag (not (file-exists-p (mh-expand-file-name folder-name))))) (cond ((and new-file-flag @@ -1809,6 +2092,24 @@ (mh-expand-file-name folder-name))))) folder-name)) +(defun mh-truncate-log-buffer () + "If `mh-log-buffer' is too big then truncate it. +If the number of lines in `mh-log-buffer' exceeds `mh-log-buffer-lines' then +keep only the last `mh-log-buffer-lines'. As a side effect the point is set to +the end of the log buffer. + +The function returns the size of the final size of the log buffer." + (with-current-buffer (get-buffer-create mh-log-buffer) + (goto-char (point-max)) + (save-excursion + (when (equal (forward-line (- mh-log-buffer-lines)) 0) + (delete-region (point-min) (point)))) + (unless (or (bobp) + (save-excursion + (and (equal (forward-line -1) 0) (equal (char-after) ?)))) + (insert "\n\n")) + (buffer-size))) + ;;; Issue commands to MH. (defun mh-exec-cmd (command &rest args) @@ -1818,14 +2119,14 @@ The output is not read or parsed by MH-E." (save-excursion (set-buffer (get-buffer-create mh-log-buffer)) - (erase-buffer) - (apply 'call-process - (expand-file-name command mh-progs) nil t nil - (mh-list-to-string args)) - (if (> (buffer-size) 0) - (save-window-excursion - (switch-to-buffer-other-window mh-log-buffer) - (sit-for 5))))) + (let ((initial-size (mh-truncate-log-buffer))) + (apply 'call-process + (expand-file-name command mh-progs) nil t nil + (mh-list-to-string args)) + (if (> (buffer-size) initial-size) + (save-window-excursion + (switch-to-buffer-other-window mh-log-buffer) + (sit-for 5)))))) (defun mh-exec-cmd-error (env command &rest args) "In environment ENV, execute mh-command COMMAND with ARGS. @@ -1834,19 +2135,15 @@ (save-excursion (set-buffer (get-buffer-create mh-temp-buffer)) (erase-buffer) - (let ((status - (if env - ;; the shell hacks necessary here shows just how broken Unix is - (apply 'call-process "/bin/sh" nil t nil "-c" - (format "%s %s ${1+\"$@\"}" - env - (expand-file-name command mh-progs)) - command - (mh-list-to-string args)) - (apply 'call-process - (expand-file-name command mh-progs) nil t nil - (mh-list-to-string args))))) - (mh-handle-process-error command status)))) + (let ((process-environment process-environment)) + ;; XXX: We should purge the list that split-string returns of empty + ;; strings. This can happen in XEmacs if leading or trailing spaces + ;; are present. + (dolist (elem (if (stringp env) (split-string env " ") ())) + (push elem process-environment)) + (mh-handle-process-error + command (apply #'call-process (expand-file-name command mh-progs) + nil t nil (mh-list-to-string args)))))) (defun mh-exec-cmd-daemon (command filter &rest args) "Execute MH command COMMAND in the background. @@ -1858,7 +2155,7 @@ ARGS are passed to COMMAND as command line arguments." (save-excursion (set-buffer (get-buffer-create mh-log-buffer)) - (erase-buffer)) + (mh-truncate-log-buffer)) (let* ((process-connection-type nil) (process (apply 'start-process command nil @@ -1866,6 +2163,22 @@ (mh-list-to-string args)))) (set-process-filter process (or filter 'mh-process-daemon)))) +(defun mh-exec-cmd-env-daemon (env command filter &rest args) + "In ennvironment ENV, execute mh-command COMMAND in the background. + +ENV is nil or a string of space-separated \"var=value\" elements. +Signals an error if process does not complete successfully. + +If FILTER is non-nil then it is used to process the output otherwise the +default filter `mh-process-daemon' is used. See `set-process-filter' for more +details of FILTER. + +ARGS are passed to COMMAND as command line arguments." + (let ((process-environment process-environment)) + (dolist (elem (if (stringp env) (split-string env " ") ())) + (push elem process-environment)) + (apply #'mh-exec-cmd-daemon command filter args))) + (defun mh-process-daemon (process output) "PROCESS daemon that puts OUTPUT into a temporary buffer. Any output from the process is displayed in an asynchronous pop-up window." @@ -1933,30 +2246,20 @@ (apply 'mh-exec-cmd-output (expand-file-name command mh-lib-progs) nil args)) (defun mh-handle-process-error (command status) - "Raise error if COMMAND returned non-zero STATUS, otherwise return STATUS. -STATUS is return value from `call-process'. -Program output is in current buffer. -If output is too long to include in error message, display the buffer." - (cond ((eq status 0) ;success - status) - ((stringp status) ;kill string - (error "%s: %s" command status)) - (t ;exit code - (cond - ((= (buffer-size) 0) ;program produced no error message - (error "%s: exit code %d" command status)) - (t - ;; will error message fit on one line? - (goto-line 2) - (if (and (< (buffer-size) (frame-width)) - (eobp)) - (error "%s" - (buffer-substring 1 (progn (goto-char 1) - (end-of-line) - (point)))) - (display-buffer (current-buffer)) - (error "%s failed with status %d. See error message in other window" - command status))))))) + "Raise error if COMMAND returned non-zero STATUS, otherwise return STATUS." + (if (equal status 0) + status + (goto-char (point-min)) + (insert (if (integerp status) + (format "%s: exit code %d\n" command status) + (format "%s: %s\n" command status))) + (save-excursion + (let ((error-message (buffer-substring (point-min) (point-max)))) + (set-buffer (get-buffer-create mh-log-buffer)) + (mh-truncate-log-buffer) + (insert error-message))) + (error "%s failed, check %s buffer for error message" + command mh-log-buffer))) (defun mh-list-to-string (l) "Flatten the list L and make every element of the new list into a string."
--- a/lisp/mh-e/mh-xemacs-compat.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-xemacs-compat.el Fri Apr 25 05:52:00 2003 +0000 @@ -1,6 +1,6 @@ ;;; mh-xemacs-compat.el --- GNU Emacs Functions needed by XEmacs -;; Copyright (C) 2001, 2002 Free Software Foundation, Inc. +;; Copyright (C) 2001, 02, 2003 Free Software Foundation, Inc. ;; Author: FSF ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -28,13 +28,13 @@ ;;; Change Log: -;; $Id: mh-xemacs-compat.el,v 1.13 2002/11/30 01:21:42 wohler Exp $ - ;;; Code: ;;; Some requires: (require 'rfc822) +(eval-when-compile (require 'mh-utils)) + ;;; Simple compatibility: (unless (fboundp 'match-string-no-properties) @@ -52,6 +52,42 @@ (unless (fboundp 'cancel-timer) (defalias 'cancel-timer 'delete-itimer)) +;; Set up the modeline glyph +(defconst mh-modeline-logo + "/* XPM */ +static char * file[] = { +\"18 13 2 1\", +\"# c #666699\", +\". c None s None\", +\"........##........\", +\".......####.......\", +\"......######......\", +\"......######......\", +\"....#########.....\", +\"..##############..\", +\".##...######....#.\", +\"##...#.#.####...#.\", +\"....#..#.##.#...#.\", +\"...#..##.#.#.#....\", +\"...#..#..#..#.#...\", +\"...#..#.##..#.##..\", +\"...#..#.#..#....#.\"};" + "The image for the modeline logo.") + +(mh-do-in-xemacs + (defvar mh-modeline-glyph + (progn + (let* ((data mh-modeline-logo) + (glyph (make-glyph + (cond ((and (featurep 'xpm) + (device-on-window-system-p) + has-modeline-p) + `[xpm :data ,data]) + (t [string :data "MH-E"]))))) + (set-glyph-face glyph 'modeline-buffer-id) + glyph)) + "Cute little logo to put in the modeline of MH-E buffers.")) + (provide 'mh-xemacs-compat) ;;; Local Variables:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/mh-e/mh-xemacs-icons.el Fri Apr 25 05:52:00 2003 +0000 @@ -0,0 +1,1306 @@ +;;; mh-xemacs-icons.el --- icons for the MH-E toolbars under XEmacs +;; +;; Copyright (C) 2003 Free Software Foundation, Inc. + +;; Author: Various (See below) +;; Maintainer: Bill Wohler <wohler@newt.com> +;; Keywords: mail toolbar +;; See: mh-e.el + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This file contains the toolbar icons that MH-E uses under XEmacs. Some +;; icons were created for MH-E and others were copied from other Emacs modes. +;; The XPM files are copied into defconst's and the background colour is +;; changed. + +;; The alist `mh-xemacs-icon-map' contains a map of the icon file names under +;; GNU Emacs to the constant name under XEmacs. To add new icons for XEmacs +;; this variable should be updated as well. + +;;; Change Log: + +;;; Code: + +;; Avoid compiler warning +(eval-and-compile + (require 'mh-utils) + (defvar mh-xemacs-toolbar-folder-toolbar nil) + (defvar mh-xemacs-toolbar-letter-toolbar nil)) + + + +;; Define the toolbar icons. + +;; Derived From lisp/toolbar/mail.xpm +(defconst mh-xemacs-toolbar-inc-folder-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 5 1\", +\" c Gray0\", +\". c #673e666663d4\", +\"X c #a852a7bea3d2\", +\"o c #eb46ea1de471\", +\"O c Gray75 s backgroundToolBarColor\", +/* pixels */ +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOO OOOOOO\", +\"OOOOOOOOO .ooX OOOOO\", +\"OOOO .XooooooX OOOOO\", +\"OOO .Xoooooooooo.XX OOOO\", +\"OOO o..ooooooooX.Xo OOOO\", +\"OOO XoX..oooooo.Xoo OOOO\", +\"OOOO oooXX.Xoo...ooX OOO\", +\"OOOO oooooXX..XoX.Xo OOO\", +\"OOOO Xoooo.ooooooo.X OOO\", +\"OOOOO oooXXoooooooo.X OO\", +\"OOOOO ooo.oooooooooX OO\", +\"OOOOO XoXXooooooX OOOO\", +\"OOOOOO o.ooooX OOOOOOO\", +\"OOOOOO .XoX OOOOOOOOOO\", +\"OOOOOO .. OOOOOOOOOOOOO\", +\"OOOOOOO OOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\"};") + "*MH inc folder icon.") + +;; Derived from lisp/toolbar/attach.pbm +(defconst mh-xemacs-toolbar-mime-save-parts-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * file[] = { +\"24 24 2 1\", +\". c Gray75 s backgroundToolBarColor\", +\" c black\", +/* pixels */ +\"........................\", +\"........................\", +\"........................\", +\"........... ...........\", +\".......... .. ..........\", +\"......... .... .........\", +\"......... .... .........\", +\"......... .... .........\", +\"......... . .. .........\", +\"......... . .. .........\", +\"......... . .. . .......\", +\"......... . .. . .......\", +\"......... . .. . .......\", +\"......... . .. . .......\", +\"......... . .. . .......\", +\"......... . .. . .......\", +\"......... . .. . .......\", +\"......... .. .. .......\", +\".......... .... ........\", +\"........... .. .........\", +\"............ ..........\", +\"........................\", +\"........................\", +\"........................\"};") + "*MH save MIME parts icon.") + +;; Derived from lisp/toolbar/right_arrow.xpm +(defconst mh-xemacs-toolbar-next-undeleted-msg-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * right_arrow_xpm[] = { +\"24 24 9 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c #020202\", +\"+ c #1A1A1A\", +\"@ c #779D6D\", +\"# c #88AE80\", +\"$ c #97B78B\", +\"% c #9EBA92\", +\"& c #E9EFE8\", +\"* c #3C5936\", +\" \", +\" \", +\" \", +\" \", +\" \", +\" .. \", +\" .&.. \", +\" .&&&.. \", +\" .&&&&&.. \", +\" .&&&&&&&.. \", +\" .&&&&&&&&&+. \", +\" +&&&&&&&&&&%.. \", +\" .%#######@@*.. \", +\" .%#####@@*.. \", +\" .%###@@*.. \", +\" .$#@@*.. \", +\" .#@*.. \", +\" .*.. \", +\" .. \", +\" \", +\" \", +\" \", +\" \", +\" \"};") + "*MH previous message icon.") + +;; Derived from mh-e/page-down.xpm +(defconst mh-xemacs-toolbar-page-msg-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * mail_page_xpm[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 5 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c black\", +\"X c #ea03ea03d271\", +\"o c #a5d8a5d89550\", +\"O c #d305d305bc3c\", +/* pixels */ +\" \", +\" \", +\" .................. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XoooooooooooooXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .Xoooooooooo..oXX. \", +\" .XXXXXXXXXXX..XXX. \", +\" .XXXXXXXXXXX..XXX. \", +\" .XooooooXXXX..XXX. \", +\" .XXXXXXXXXXX..XXX. \", +\" .XXXXXXXXX.O..O.X. \", +\" .Xoooooooo.....XX. \", +\" .XXXXXXXXXX....XX. \", +\" .XXXXXXXXXXX..XXX. \", +\" .XXXXXXXXXXXooXXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .................. \", +\" \", +\" \", +\" \"};") + "MH page message icon.") + +;; Derived from lisp/toolbar/left_arrow.xpm +(defconst mh-xemacs-toolbar-previous-undeleted-msg-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * left_arrow_xpm[] = { +\"24 24 9 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c #020202\", +\"+ c #121A12\", +\"@ c #78A16E\", +\"# c #86AD7D\", +\"$ c #B2C6AE\", +\"% c #263222\", +\"& c #E7EDE6\", +\"* c #497241\", +\" \", +\" \", +\" \", +\" \", +\" \", +\" .. \", +\" ..$. \", +\" ..&&$. \", +\" ..&&&&$. \", +\" ..&&&&&&$. \", +\" .+&&&&&&&&$. \", +\" ..$&&&&&&&&&$% \", +\" ..**@@@#####@. \", +\" ..**@#@###@. \", +\" ..**@#@#@. \", +\" ..**@@@. \", +\" ..*@*. \", +\" ..*. \", +\" .. \", +\" \", +\" \", +\" \", +\" \", +\" \"};") + "MH next message icon.") + +;; Derived from lisp/toolbar/close.xpm +(defconst mh-xemacs-toolbar-delete-msg-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 2 1\", +\" c Gray0\", +\". c Gray75 s backgroundToolBarColor\", +/* pixels */ +\"........................\", +\"........................\", +\"........................\", +\"........................\", +\"........................\", +\"........................\", +\"....... .... ..........\", +\"....... .. .........\", +\"........ . ..........\", +\"........ ...........\", +\"......... ............\", +\"......... ...........\", +\"........ ..........\", +\"........ . .........\", +\"....... ... ........\", +\"....... ..... .........\", +\"........................\", +\"........................\", +\"........................\", +\"........................\", +\"........................\", +\"........................\", +\"........................\", +\"........................\"};") + "MH delete message icon.") + +;; Derived from mh-e/refile.xpm +(defconst mh-xemacs-toolbar-refile-msg-icon + (mh-funcall-if-exists toolbar-make-button-list +"/* XPM */ +static char * refile_xpm[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 7 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c black\", +\"X c #a5d8a5d89550\", +\"o c #d305d305bc3c\", +\"O c #ea03ea03d271\", +\"+ c #828282827474\", +\"@ c #61b761b7600a\", +/* pixels */ +\" . \", +\" ..X. \", +\" ..XoO.... \", +\" ..XooooO.+. \", +\" ..XooooooOX.. .. \", +\" .@@ooooooOOO@. ... \", +\" .O@oooooOOOOO..@@. \", +\" .OO@oooOOOOOO..@@. \", +\" ...OO@XooOOOOO...@@. \", +\" ..+.O@XooOOOO..@@@@@. \", +\" .++..XooOOOO..@@@@@@. \", +\" .++.@oooOO...@@@@@@@. \", +\" ..+.XooOOO..@@@@@@@. \", +\" .++.OOOO.@@@@@@@@. \", +\" .+.oOO..@@@@@@@. \", +\" .++.OO.@@@@@@@. \", +\" .++.O.@@@@@.. \", +\" ..+.O.@@@@@. \", +\" .++..@@@@. \", +\" ..++.@@@. \", +\" .+.@@. \", +\" ...@. \", +\" ... \", +\" . \"};") + "MH refile message icon.") + +;; Derived from lisp/toolbar/undo.xpm +(defconst mh-xemacs-toolbar-undo-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 5 1\", +\" c Gray0\", +\". c #ae6e66e76a0a\", +\"X c #c6c67d7d8181\", +\"o c #e4e4e4e4dcdc\", +\"O c Gray75 s backgroundToolBarColor\", +/* pixels */ +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOO OOOOOOOOOOOOOO\", +\"OOOOOOOO OOOOOOOOOOOOOO\", +\"OOOOOOO oX OOOOOOOOOOO\", +\"OOOOOO ooooX. OOOOOOOOO\", +\"OOOOOOO oo .. OOOOOOOO\", +\"OOOOOOOO OOO . OOOOOOOO\", +\"OOOOOOOOO OOOO . OOOOOOO\", +\"OOOOOOOOOOOOOOO OOOOOOO\", +\"OOOOOOOOOOOOOOO OOOOOOO\", +\"OOOOOOOOOOOOOOO OOOOOOOO\", +\"OOOOOOOOOOOOOO OOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\"};") + "MH undo icon.") + +;; Derived from mh-e/execute.xpm +(defconst mh-xemacs-toolbar-execute-commands-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * mail_exec_xpm[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 6 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c black\", +\"X c #a5d8a5d89550\", +\"o c #d305d305bc3c\", +\"O c #ea03ea03d271\", +\"+ c white\", +/* pixels */ +\" \", +\" \", +\" \", +\" .. \", +\" XX .. \", +\" oo XX .. \", +\" OO oo XX .. \", +\" OO oo XX .. \", +\" OO oo XX .. \", +\" OO oo XX .. \", +\" OO oo XX .. \", +\" OO oo XX .. \", +\" OO oo XX .. \", +\" OO oo XX \", +\" OO oo \", +\" OO + .. \", +\" XX .. \", +\" oo XX \", +\" OO oo \", +\" OO \", +\" \", +\" \", +\" \", +\" \"};") + "MH execute commands icon.") + +;; Derived from mh-e/highlight.xpm +(defconst mh-xemacs-toolbar-toggle-tick-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * highlight_xpm[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 4 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c black\", +\"X c #828282827474\", +\"o c #dd00df007e00\", +/* pixels */ +\" ..... \", +\" ..XXX.. \", +\" .XXXXX. \", +\" .XXXXX.. \", +\" .XXXXX. \", +\" .XXXXX. \", +\" .XXXXX. \", +\" .ooXX. \", +\" ..ooo. \", +\" oooo .... \", +\"oo.ooo....oo ... \", +\"o.o.ooo.oo.o.ooo.o \", +\".ooo.oo.oo.o.ooooo \", +\".ooo.oo.oo.o.ooooo \", +\".ooo.oo...oo.ooooo \", +\".....oo.oo.o.ooooo \", +\".ooo.oo.oo.o.ooooo \", +\".ooo.oo.oo.o.ooo.o \", +\". oo.o....ooo...o \", +\" oo oooo \", +\" \", +\" \", +\" \", +\" \"};") + "MH toggle tick icon.") + +;; Derived from mh-e/show.xpm +(defconst mh-xemacs-toolbar-toggle-showing-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * mail_show_xpm[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 4 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c black\", +\"X c #ea03ea03d271\", +\"o c #a5d8a5d89550\", +/* pixels */ +\" \", +\" \", +\" .................. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XoooooooooooooXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XoooooooooooooXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XooooooXXXXXXXXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XoooooooooXXXXXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .XXXXXXXXXXXXXXXX. \", +\" .................. \", +\" \", +\" \", +\" \"};") + "MH toggle showing icon.") + +;; Derived from mh-e/reply-all.xpm +(defconst mh-xemacs-toolbar-reply-all-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * reply_all_xpm[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 9 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c black\", +\"X c #673e666663d4\", +\"o c #eb46ea1de471\", +\"O c #a852a7bea3d2\", +\"+ c #ae51c17b9b26\", +\"@ c #8d4d97577838\", +\"# c #7c7c8b8b6e6e\", +\"$ c #5e0868be52d3\", +/* pixels */ +\" \", +\" \", +\" .... \", +\" .....XooO. \", +\" .....XOooooooO. \", +\" .XOooooooooooXOO. \", +\" .oXXooooooooOXOo. \", +\" .OoOXXooooooXOoo. \", +\" .oooOOXOooXXXooO. \", +\" ........XXOoOXOo. \", +\" ..++++@.ooooooXO. \", +\" ..+@@@.oooooooXO. \", +\" ..+@@@#.oooooooO.. \", +\" ..++@@@#$.ooooO... \", +\" .++++@@#.$ .. \", +\" .+@@@#.o .. .O .O \", +\" .+@#$. .O. .O .O \", +\" .#$. .O .o .O .O \", +\" .$. . .O .O .O \", +\" . ....O .O .O \", +\" .O .O .O .O \", +\" .O .O .O .O \", +\" .O .O .O .O \", +\" \"};") + "Reply to \"All\" icon.") + +;; Derived from mh-e/reply-from.xpm +(defconst mh-xemacs-toolbar-reply-from-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * reply_from_xpm[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 9 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c black\", +\"X c #673e666663d4\", +\"o c #eb46ea1de471\", +\"O c #a852a7bea3d2\", +\"+ c #ae51c17b9b26\", +\"@ c #8d4d97577838\", +\"# c #7c7c8b8b6e6e\", +\"$ c #5e0868be52d3\", +/* pixels */ +\" \", +\" \", +\" .... \", +\" .....XooO. \", +\" .....XOooooooO. \", +\" .XOooooooooooXOO. \", +\" .oXXooooooooOXOo. \", +\" .OoOXXooooooXOoo. \", +\" .oooOOXOooXXXooO. \", +\" ........XXOoOXOo. \", +\" ..++++@.ooooooXO. \", +\" ..+@@@.oooooooXO. \", +\" ..+@@@#.oooooooO.. \", +\" ..++@@@#$.ooooO... \", +\" #.$.oO... \", +\" ...O . .... \", +\" ...O \", +\" .O \", +\" ...O ..O .... .O O. \", +\" ...O ..O .OO. ..... \", +\" .O .O . . . . . \", +\" .O .O .OO. . . . \", +\" .O .O .... . O . \", +\" \"};") + "Reply to \"From\" icon..") + +;; Derived from mh-e/reply-to.xpm +(defconst mh-xemacs-toolbar-reply-to-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * reply_to_xpm[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 9 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c black\", +\"X c #673e666663d4\", +\"o c #eb46ea1de471\", +\"O c #a852a7bea3d2\", +\"+ c #ae51c17b9b26\", +\"@ c #8d4d97577838\", +\"# c #7c7c8b8b6e6e\", +\"$ c #5e0868be52d3\", +/* pixels */ +\" \", +\" \", +\" .... \", +\" .....XooO. \", +\" .....XOooooooO. \", +\" .XOooooooooooXOO. \", +\" .oXXooooooooOXOo. \", +\" .OoOXXooooooXOoo. \", +\" .oooOOXOooXXXooO. \", +\" ........XXOoOXOo. \", +\" ..++++@.ooooooXO. \", +\" ..+@@@.oooooooXO. \", +\" ..+@@@#.oooooooO.. \", +\" ..++@@@#$.ooooO... \", +\" .++++@@#.$ \", +\" .+@@@#.o ...... \", +\" .+@#$. OO.OOO \", +\" .#$. .O \", +\" .$. .O .... \", +\" . .O .OO. \", +\" .O . . \", +\" .O .OO. \", +\" .O .... \", +\" \"};") + "Reply to \"To\" icon..") + +;; Derived from mh-e/mail/reply2.xpm +(defconst mh-xemacs-toolbar-reply-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * mail_reply_xpm[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 9 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c black\", +\"X c #673e666663d4\", +\"o c #eb46ea1de471\", +\"O c #a852a7bea3d2\", +\"+ c #ae51c17b9b26\", +\"@ c #8d4d97577838\", +\"# c #7c7c8b8b6e6e\", +\"$ c #5e0868be52d3\", +/* pixels */ +\" \", +\" \", +\" \", +\" \", +\" \", +\" .... \", +\" .....XooO. \", +\" .....XOooooooO. \", +\" .XOooooooooooXOO. \", +\" .oXXooooooooOXOo. \", +\" .OoOXXooooooXOoo. \", +\" .oooOOXOooXXXooO. \", +\" ........XXOoOXOo. \", +\" ..++++@.ooooooXO. \", +\" ..+@@@.oooooooXO. \", +\" ..+@@@#.oooooooO.. \", +\" ..++@@@#$.ooooO... \", +\" .++++@@#.$.oO... \", +\" .+@@@#.o.... \", +\" .+@#$... \", +\" .#$. \", +\" .$. \", +\" . \", +\" \"};") + "Reply to current message icon.") + +;; Derived from mh-e/alias.xpm +(defconst mh-xemacs-toolbar-alias-grab-from-field-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * alias_xpm[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 4 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c #61b761b7600a\", +\"X c #a5d8a5d89550\", +\"o c black\", +/* pixels */ +\" \", +\" \", +\" \", +\" ...... \", +\" ...XXXX..XX \", +\" o..ooooooo... \", +\" ooo oooo..X \", +\" o.X ooo... \", +\" o.X ooo.XX \", +\" o.X oo.. \", +\" o.X oo. \", +\" o... oo.. \", +\" o.X o.. \", +\" o.XX oX. \", +\" o.... oo. \", +\" o..XX oooo \", +\" o...XXX XXoooo \", +\" ooo........ooooo \", +\" oooooXXooooo.oo \", +\" ooo o..oo\", +\" o...\", +\" ooo\", +\" oo\", +\" \"};") + "MH alias grab from field icon.") + +;; Derived from toolbar/mail_send.xpm +(defconst mh-xemacs-toolbar-send-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 9 1\", +\" c Gray0\", +\". c #757560602020\", +\"X c #6711662663d9\", +\"o c #8e8e7d7d4545\", +\"O c #adad8e8e3030\", +\"+ c #d8d8bebe6a6a\", +\"@ c #a8fba84da483\", +\"# c #eb79ea70e4f4\", +\"$ c Gray75 s backgroundToolBarColor\", +/* pixels */ +\"$$$$$$$$$$$$$$$$$$$$$$$$\", +\"$$$$$$$$$$$$$$$$$$$$$$$$\", +\"$$$$$$$$$$$$$ $$$$$$$\", +\"$$$$$$$$ X##@ $$$$$$\", +\"$$$ X@######@ $$$$$$\", +\"$$ X@##########X@@ $$$$$\", +\"$$ #XX########@X@# $$$$$\", +\"$$ @#@XX######X@## $$$$$\", +\"$$$ ###@@X@##XXX##@ $ $$\", +\"$$$ #####@@XX@#@X@# + $\", +\"$$$ @####X#######X@ +o $\", +\"$$$$ ###@@######## +o $$\", +\"$$$$ ###X######## +o $$$\", +\"$$$$ @#@@######@ +o $$$$\", +\"$$$$$ #X####@ +o $$$$$\", +\"$$$$$ X@#@ $ +o $$$$$$\", +\"$$$$$ XX $$$ +o $$$$$$$\", +\"$$$$$$ $$$$ +o $$$$$$$$\", +\"$$$$$$$$$$$O. $$$$$$$$$\", +\"$$$$$$$$$$$ $$$$$$$$$$$\", +\"$$$$$$$$$$$$$$$$$$$$$$$$\", +\"$$$$$$$$$$$$$$$$$$$$$$$$\", +\"$$$$$$$$$$$$$$$$$$$$$$$$\", +\"$$$$$$$$$$$$$$$$$$$$$$$$\"};") + "MH send icon.") + +;; Derived from mh-e/rescan.xpm +(defconst mh-xemacs-toolbar-rescan-folder-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * mail_rescan_xpm[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 6 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c black\", +\"X c #a5d8a5d89550\", +\"o c #d305d305bc3c\", +\"O c #ea03ea03d271\", +\"+ c #828282827474\", +/* pixels */ +\" \", +\" \", +\" .............. \", +\" .XXXXXXXXXXXX.. \", +\" .XXXXXXXXXXXX.X. \", +\" .XXXXXXXXXXXX.oo. \", +\" ..............ooo. \", +\" .OOOOOOOOOOOO.ooo. \", +\" .O++++++++++O.ooo. \", +\" .O+XXXXXXXX+O.ooo. \", +\" .O+XXXXXXXX+O.ooo. \", +\" .O+XXXXXXXX+O.ooo. \", +\" .O+XXXXXXXX+O.ooo. \", +\" .O++++++++++O.ooo. \", +\" .OOOOOOOOOOOO.ooo. \", +\" .O++++++++++O.ooo. \", +\" .O+XXXXXXXX+O.ooo. \", +\" .O+XXXXXXXX+O.ooX. \", +\" .O+XXXXXXXX+O.oo.. \", +\" .O++++++++++O.o.. \", +\" ..OOOOOOOOOOOO... \", +\" ................ \", +\" \", +\" \"};") + "MH rescan folder icon.") + +;; Derived from mh-e/repack.xpm +(defconst mh-xemacs-toolbar-pack-folder-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * mail_repack_xpm[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 6 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c black\", +\"X c #a5d8a5d89550\", +\"o c #d305d305bc3c\", +\"O c #ea03ea03d271\", +\"+ c #828282827474\", +/* pixels */ +\" \", +\" \", +\" .............. \", +\" .XXXXXXXXXXXX.. \", +\" .XXXXXXXXXXXX.X. \", +\" .XXXXXXXXXXXX.oo. \", +\" ..............ooo. \", +\" .OOOOOOOOOOOO.oo. \", +\" .O++++++++++O.oo. \", +\" .O+XXXXXXXX+O.o. \", +\" .+XXXXXXXX+.o.. \", +\" .+XX...XXX+.... \", +\" ....o.......oo. \", +\" ....o.....Oooo. \", +\" .OOO...OOOO.oooo. \", +\" .++++++++++.oooo. \", +\" .+XXXXXXXX+.oooo. \", +\" .O+XXXXXXXX+O.ooX. \", +\" .O+XXXXXXXX+O.oo.. \", +\" .O++++++++++O.o.. \", +\" ..OOOOOOOOOOOO... \", +\" ................ \", +\" \", +\" \"};") + "MH repack folder icon.") + +;; Derived from lisp/toolbar/search.xpm +(defconst mh-xemacs-toolbar-search-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 8 1\", +\" c #011801180102\", +\". c #464646463e3e\", +\"X c #5c5c5c5c57a0\", +\"o c #878787877979\", +\"O c #a910a91097af\", +\"+ c #ce5ace5ab851\", +\"@ c #e79de79dd134\", +\"# c Gray75 s backgroundToolBarColor\", +/* pixels */ +\"########################\", +\"########################\", +\"############# ##########\", +\"########### O #########\", +\"######### O@@.#########\", +\"####### O@@@@@ ########\", +\"##### O+@@@@@@O #######\", +\"#### XX@++@@@@@@.#######\", +\"#### @.O+@@@@@@@@ ######\", +\"#### @@.++@@@@@@@O #####\", +\"#### @@.o+O. .+@@ #####\", +\"#### @XO+O.O++o.+@@ ####\", +\"#### O+@.O@@+Oo.@@+ ###\", +\"#### X@@@ +#+OOO @@@@ ##\", +\"#### O@@@ +@OOOo @@@o ##\", +\"##### @@@.oOOOoX.@@ ###\", +\"##### O@@O.oOOX @ #####\", +\"######X@@@O. .X ######\", +\"###### @@@@@@@+ #####\", +\"####### @@@@@O ## ####\", +\"####### O@@+. #### ###\", +\"######## @O ####### ###\", +\"######### #############\", +\"########################\"};") + "MH search icon.") + +;; Derived from lisp/toolbar/fld_open.xpm +(defconst mh-xemacs-toolbar-visit-folder-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 4 1\", +\" c Gray0\", +\". c #909090909090\", +\"X c #fefefefefefe\", +\"o c Gray75 s backgroundToolBarColor\", +/* pixels */ +\"oooooooooooooooooooooooo\", +\"oooooooooooooooooooooooo\", +\"oooooooooooooooooooooooo\", +\"oooooooooooooooooooooooo\", +\"oooooooooooooooooooooooo\", +\"oooooooooooooo oooooooo\", +\"ooooooooooo .. ooooooo\", +\"oooo oo ....XXo ooo\", +\"ooo .. ....XXXX .. ooo\", +\"ooo .....XXXXX .... ooo\", +\"oooo ..XXXXX ...... ooo\", +\"oooo ..XXX ........ ooo\", +\"ooooo .XX .......... ooo\", +\"ooooo ..X .......... ooo\", +\"oooooo .X .......... ooo\", +\"oooooo .. ........ oooo\", +\"ooooooo . ...... oooooo\", +\"ooooooo . ..... oooooooo\", +\"oooooooo ... ooooooooo\", +\"oooooooo . ooooooooooo\", +\"ooooooooo ooooooooooooo\", +\"oooooooooooooooooooooooo\", +\"oooooooooooooooooooooooo\", +\"oooooooooooooooooooooooo\"};") + "MH visit folder icon.") + +;; Derived from lisp/toolbar/help.xpm +(defconst mh-xemacs-toolbar-help-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 6 1\", +\" c Gray0\", +\". c #65658b8b5e5e\", +\"X c #934ab2448dfb\", +\"o c #b35dc8c8afaf\", +\"O c #e0b2e944df83\", +\"+ c Gray75 s backgroundToolBarColor\", +/* pixels */ +\"++++++++++++++++++++++++\", +\"++++++++++++++++++++++++\", +\"++++++++++++++++++++++++\", +\"++++++++++++++++++++++++\", +\"+++++++++ ++++++++++\", +\"++++++++ oOOOO +++++++++\", +\"+++++++ OOOOOOO ++++++++\", +\"++++++ oOo oOo +++++++\", +\"+++++++ O +++ OO +++++++\", +\"+++++++O ++++ Oo +++++++\", +\"++++++++++++ OO. +++++++\", +\"+++++++++++ OOX ++++++++\", +\"++++++++++ OOX +++++++++\", +\"+++++++++ XOX ++++++++++\", +\"+++++++++ OX +++++++++++\", +\"+++++++++ +++++++++++\", +\"++++++++++++++++++++++++\", +\"++++++++++ ++++++++++++\", +\"+++++++++ Oo +++++++++++\", +\"+++++++++ oX +++++++++++\", +\"++++++++++ ++++++++++++\", +\"++++++++++++++++++++++++\", +\"++++++++++++++++++++++++\", +\"++++++++++++++++++++++++\"};") + "MH help icon.") + +;; Derived from lisp/toolbar/mail_send.xpm +(defconst mh-xemacs-toolbar-send-letter-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 9 1\", +\" c Gray0\", +\". c #675e6580613e\", +\"X c #8c8c7c7c6969\", +\"o c #9b458d377822\", +\"O c #a941a6459f3e\", +\"+ c #c8c8b2b29898\", +\"@ c #dadac2c2a5a5\", +\"# c #eb4dea2fe4ad\", +\"$ c Gray75 s backgroundToolBarColor\", +/* pixels */ +\"$$$$$$$$$$$$$$$$$$$$$$$$\", +\"$$$$$$$$$$$$$$$$$$$$$$$$\", +\"$$$$$$$$$$$$$ $$$$$$$\", +\"$$$$$$$$ .@#+ $$$$$$\", +\"$$$ .+#####@O $$$$$$\", +\"$$ .+##########.+O $$$$$\", +\"$$ @..########O.+# $$$$$\", +\"$$ O@O..@#####.+## $$$$$\", +\"$$$ ###+O.O##...##O $$$$\", +\"$$$ @####@+..O#O.+# $$$$\", +\"$$$ O####.#######.O $$$$\", +\"$$$$ ###+O########.O $$$\", +\"$$$$ ###.########@O $$$\", +\"$$$$ +#+O#####@O $$$$$\", +\"$$$$$ #.###@O $$$$$$\", +\"$$$$$ .O@O $$ .. $$$$$\", +\"$$$$$ .. $$$$ .oo. $$$$\", +\"$$$$$$ $$$$$ oo $$$\", +\"$$$$$$$$$$$$$$$ Oo $$$$$\", +\"$$$$$$$$$$$$$$ oOOX $$$$\", +\"$$$$$$$$$$$$$$ ++++ $$$$\", +\"$$$$$$$$$$$$$ O@@@@O $$$\", +\"$$$$$$$$$$$$$ $$$\", +\"$$$$$$$$$$$$$$$$$$$$$$$$\"};") + "MH send letter icon.") + +;; This is the same icon as `mh-xemacs-toolbar-mime-save-parts-icon', +;; so there is no point in duplicating it. +(defconst mh-xemacs-toolbar-compose-insertion-icon + mh-xemacs-toolbar-mime-save-parts-icon + "MH compose insertion icon.") + +;; Derived from lisp/toolbar/spell.xpm +(defconst mh-xemacs-toolbar-ispell-message-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 5 1\", +\" c Gray0\", +\". c #41415b5b3939\", +\"X c #4c2f6b4e42d1\", +\"o c #5fe086865454\", +\"O c Gray75 s backgroundToolBarColor\", +/* pixels */ +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOO OO OOO OOOOOOOO\", +\"OOO OO O OO O OO OOOOOOO\", +\"OOO O OO OOOOOOOOOO\", +\"OOO OO O OO O OO OOOOOOO\", +\"OOO OO O OOO OOOO OO\", +\"OOOOOOOOOOOOOOOOOOO OOO\", +\"OOOOOOOOOOO OOOOO OOOO\", +\"OOOOOOOOOOO X OOO . OOOO\", +\"OOOOOOOOOOOO X O X OOOOO\", +\"OOOOOOOOOOOO Xo o. OOOOO\", +\"OOOOOOOOOOOOO XoX OOOOOO\", +\"OOOOOOOOOOOOO Xo. OOOOOO\", +\"OOOOOOOOOOOOOO X OOOOOOO\", +\"OOOOOOOOOOOOOO X OOOOOOO\", +\"OOOOOOOOOOOOOOO OOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\"};") + "MH Ispell message icon.") + +;; Derived from lisp/toolbar/save.xpm +(defconst mh-xemacs-toolbar-save-buffer-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 5 1\", +\" c #01be01be01be\", +\". c #62dd62dd62dd\", +\"X c Gray62\", +\"o c #e625e625e625\", +\"O c Gray75 s backgroundToolBarColor\", +/* pixels */ +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOO OOOOOOOOO\", +\"OOOOOOOOOOO X. OOOOOOOO\", +\"OOOOOOOOO oXoX OOOOOOOO\", +\"OOOOOOO oXoooXX OOOOOOO\", +\"OOOOO oXoooooo. OOOOOOO\", +\"OOO XoooooooooX OOOOOO\", +\"OO XooooooooooooX OOOOOO\", +\"OO .XoooooooooooX. OOOOO\", +\"OOO XooooooooooXXX OOOOO\", +\"OOO .XoooooooXX..X. OOOO\", +\"OOOO XoooooXX...X.X OOOO\", +\"OOOO .XooXX.Xoo.X.X. OOO\", +\"OOOOO XXX.oooooX.X. OOO\", +\"OOOOO .XXoo.ooooXX OOO\", +\"OOOOOO XX.o XooX. OOOOO\", +\"OOOOOO .XXooXoX OOOOOOO\", +\"OOOOOOO .X.oX OOOOOOOOO\", +\"OOOOOOOO OOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\"};") + "MH save buffer icon.") + +;; Derived from lisp/toolbar/cut.xpm +(defconst mh-xemacs-toolbar-kill-region-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 2 1\", +\" c Gray0\", +\". c Gray75 s backgroundToolBarColor\", +/* pixels */ +\"........................\", +\"........................\", +\"........................\", +\"........................\", +\"........................\", +\".................. .....\", +\"................ ......\", +\"............... .......\", +\".............. ........\", +\"............. .........\", +\".... .... ..... ..\", +\"... ... .. ... ....\", +\"... ... ......\", +\".... ... .........\", +\".......... ............\", +\"......... ............\", +\"........ .. ............\", +\"....... ... ............\", +\"....... .. .............\", +\"....... ..............\", +\"........................\", +\"........................\", +\"........................\", +\"........................\"};") + "MH kill region icon.") + +;; Derived from lisp/toolbar/copy.xpm +(defconst mh-xemacs-toolbar-kill-ring-save-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 7 1\", +\" c Gray0\", +\". c #424242423a3a\", +\"X c #68e968e96363\", +\"o c #a8b1a8b1992b\", +\"O c #d3d3d3d3bdbd\", +\"+ c #e419e419cd6b\", +\"@ c Gray75 s backgroundToolBarColor\", +/* pixels */ +\"@@@@@@@@@@@@@@@@@@@@@@@@\", +\"@@@@@@@@@@@@@@@@@@@@@@@@\", +\"@@@@@@@@@@@@@@@@@@@@@@@@\", +\"@@@@@@@@@@@@@@@@@@@@@@@@\", +\"@@@@@@@@@@@@@@@@@@@@@@@@\", +\"@@@@@@@@ @@@@@@@@@@@@@@\", +\"@@@@@@ Oo @@@@@@@@@@@@@\", +\"@@@@ .ooOO @@@@ @@@@@@@\", +\"@@@@ +XoOOo @ Oo @@@@@@\", +\"@@@@ +.oO++ .ooOO @@@@@@\", +\"@@@@ XoO+++ +XoOOo @@@@@\", +\"@@@@ oOO+++ +.oO++ @@@@@\", +\"@@@@ oO++++ XoOO++o @@@@\", +\"@@@@@ +++++ oOO++++o @@@\", +\"@@@@@ o++++ oO++++++ @@@\", +\"@@@@@@ ++o +++++++o @@\", +\"@@@@@@ o @@ o++++o @@@\", +\"@@@@@@@ @@@@@ ++o @@@@@\", +\"@@@@@@@@@@ @@ o @@@@@@@\", +\"@@@@@@@ @@ @@@@@@@@@\", +\"@@@@@@@ @@@@@@@@@@@@\", +\"@@@@@@@@@@ @@@@@@@@@@@@@\", +\"@@@@@@@@@@@@@@@@@@@@@@@@\", +\"@@@@@@@@@@@@@@@@@@@@@@@@\"};") + "MH kill ring save icon.") + +;; Derived from lisp/toolbar/paste.xpm +(defconst mh-xemacs-toolbar-yank-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 5 1\", +\" c Gray0\", +\". c #62ee62ee62ee\", +\"X c Gray68\", +\"o c Gray82\", +\"O c Gray75 s backgroundToolBarColor\", +/* pixels */ +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOO OOOOOOOOOOOO\", +\"OOOOOOO ooo OOOOOO OOOO\", +\"OOOOO ooooo OOO OOO\", +\"OOO oo. .Xoo OO OOO\", +\"OO ooo.oX..oo OOOOO OOOO\", +\"OO ooo.X..oooo OOOOOOOOO\", +\"OOO oo..Xooooo O OOOOOO\", +\"OOO oooooooooo oX OOOOO\", +\"OOOO ooooooo XXoo OOOOO\", +\"OOOO ooooooo o.XooX OOOO\", +\"OOOOO oooooo o.Xooo OOOO\", +\"OOOOO oooooo .XooooX OOO\", +\"OOOOOO ooooX XooooooX OO\", +\"OOOOOO XXOXX Xooooooo OO\", +\"OOOOOOO XXXX oooooooX O\", +\"OOOOOOO XX O XooooX OO\", +\"OOOOOOOO OOOO ooX OOOO\", +\"OOOOOOOOOOOOOO X OOOOOO\", +\"OOOOOOOOOOOOOOO OOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\", +\"OOOOOOOOOOOOOOOOOOOOOOOO\"};") + "MH yank icon.") + +;; This is the same icon as `mh-xemacs-toolbar-delete-msg-icon' +;; so there is no point in duplicating it here. +(defconst mh-xemacs-toolbar-fully-kill-draft-icon + mh-xemacs-toolbar-delete-msg-icon + "MH fully kill draft icon.") + +;; Derived from lisp/toolbar/preferences.xpm +(defconst mh-xemacs-toolbar-preferences-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * preferences_xpm[] = { +\"24 24 8 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c #000000\", +\"+ c #E1E0E0\", +\"@ c #D7C99B\", +\"# c #9A6C4E\", +\"$ c #A4A199\", +\"% c #858579\", +\"& c #AD8E30\", +\" \", +\" \", +\" \", +\" .. \", +\" ..++. . \", +\" ..++++. .@. \", +\" ...+++++++. .@#. \", +\" ..++++++++++. .@#. \", +\" .++++++#++++++.@#. \", +\" .+++++#++++++.@#. \", +\" .++#+#+++++.@#. \", +\" .++#$#++++.@#.+. \", +\" .++##+++.@#.++@. \", +\" .++++++.@#.+++@%. \", +\" .++++&+..@$$$$%. \", +\" .++++..$$$$$$@. \", +\" .+$%%$+++++.. \", +\" .+++++++++. \", +\" .++++++.. \", +\" .++++@. \", +\" .++.. \", +\" .. \", +\" \", +\" \"};") + "MH preferences icon.") + +;; This is the same icon as `mh-xemacs-toolbar-help-icon' so there is +;; no point in duplicating it here. +(defconst mh-xemacs-toolbar-letter-help-icon + mh-xemacs-toolbar-help-icon + "MH letter help icon.") + +;; Derived from mh-e/widen.xpm +(defconst mh-xemacs-toolbar-widen-icon + (mh-funcall-if-exists toolbar-make-button-list + "/* XPM */ +static char * widen_xpm[] = { +/* columns rows colors chars-per-pixel */ +\"24 24 3 1\", +\" c Gray75 s backgroundToolBarColor\", +\". c #8d4d97577838\", +\"X c black\", +/* pixels */ +\" \", +\" \", +\" \", +\" . . \", +\" . . \", +\" . . \", +\" . . \", +\" . . \", +\" . XX XX . \", +\" . XX XX . \", +\" . XX XX . \", +\" .XXXXXXXX XXXXXXXX. \", +\" .XXXXXXXX XXXXXXXX. \", +\" . XX XX . \", +\" . XX XX . \", +\" . XX XX . \", +\" . . \", +\" . . \", +\" . . \", +\" . . \", +\" . . \", +\" \", +\" \", +\" \"};") + "MH widen icon.") + +(defvar mh-xemacs-icon-map + '((mail . mh-xemacs-toolbar-inc-folder-icon) + (attach . mh-xemacs-toolbar-mime-save-parts-icon) + (right_arrow . mh-xemacs-toolbar-next-undeleted-msg-icon) + (page-down . mh-xemacs-toolbar-page-msg-icon) + (left_arrow . mh-xemacs-toolbar-previous-undeleted-msg-icon) + (close . mh-xemacs-toolbar-delete-msg-icon) + (refile . mh-xemacs-toolbar-refile-msg-icon) + (undo . mh-xemacs-toolbar-undo-icon) + (execute . mh-xemacs-toolbar-execute-commands-icon) + (highlight . mh-xemacs-toolbar-toggle-tick-icon) + (show . mh-xemacs-toolbar-toggle-showing-icon) + (reply-from . mh-xemacs-toolbar-reply-from-icon) + (reply-to . mh-xemacs-toolbar-reply-to-icon) + (reply-all . mh-xemacs-toolbar-reply-all-icon) + (mail/reply2 . mh-xemacs-toolbar-reply-icon) + (alias . mh-xemacs-toolbar-alias-grab-from-field-icon) + (mail_compose . mh-xemacs-toolbar-send-icon) + (rescan . mh-xemacs-toolbar-rescan-folder-icon) + (repack . mh-xemacs-toolbar-pack-folder-icon) + (search . mh-xemacs-toolbar-search-icon) + (fld_open . mh-xemacs-toolbar-visit-folder-icon) + (mail_send . mh-xemacs-toolbar-send-letter-icon) + (spell . mh-xemacs-toolbar-ispell-message-icon) + (save . mh-xemacs-toolbar-save-buffer-icon) + (cut . mh-xemacs-toolbar-kill-region-icon) + (copy . mh-xemacs-toolbar-kill-ring-save-icon) + (paste . mh-xemacs-toolbar-yank-icon) + (preferences . mh-xemacs-toolbar-preferences-icon) + (help . mh-xemacs-toolbar-help-icon) + (widen . mh-xemacs-toolbar-widen-icon)) + "Map GNU Emacs icon file names to XEmacs image constants.") + + + +(provide 'mh-xemacs-icons) + +;;; Local Variables: +;;; indent-tabs-mode: nil +;;; sentence-end-double-space: nil +;;; End: + +;;; mh-xemacs-icons.el ends here
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/toolbar/highlight.pbm Fri Apr 25 05:52:00 2003 +0000 @@ -0,0 +1,3 @@ +P4 +24 24 +ÿÿÿÿÿ×ÿÿ“ÿÿ/ÿÿGÿÿ—ÿþ¯ÿþÿÿþÿ#ÏÿQ(¿‰(?‰(?‰È?ù(?‰(?‰(¿ËÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/toolbar/highlight.xpm Fri Apr 25 05:52:00 2003 +0000 @@ -0,0 +1,33 @@ +/* XPM */ +static char * highlight_xpm[] = { +/* columns rows colors chars-per-pixel */ +"24 24 4 1", +" c None", +". c black", +"X c #828282827474", +"o c #dd00df007e00", +/* pixels */ +" ..... ", +" ..XXX.. ", +" .XXXXX. ", +" .XXXXX.. ", +" .XXXXX. ", +" .XXXXX. ", +" .XXXXX. ", +" .ooXX. ", +" ..ooo. ", +" oooo .... ", +"oo.ooo....oo ... ", +"o.o.ooo.oo.o.ooo.o ", +".ooo.oo.oo.o.ooooo ", +".ooo.oo.oo.o.ooooo ", +".ooo.oo...oo.ooooo ", +".....oo.oo.o.ooooo ", +".ooo.oo.oo.o.ooooo ", +".ooo.oo.oo.o.ooo.o ", +". oo.o....ooo...o ", +" oo oooo ", +" ", +" ", +" ", +" "};