From: Eshel Yaron Date: Sun, 25 Aug 2024 08:27:29 +0000 (+0200) Subject: Drop Electric-command-loop and all transitive dependents X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=6e257eb49b7eafa056622f95be063954fd55fd82;p=emacs.git Drop Electric-command-loop and all transitive dependents --- diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in index 45d6ab29615..0a67d5a1560 100644 --- a/doc/misc/Makefile.in +++ b/doc/misc/Makefile.in @@ -68,9 +68,9 @@ DOCMISC_W32 = @DOCMISC_W32@ ## Info files to build and install on all platforms. INFO_COMMON = auth autotype calc ccmode cl dbus dired-x \ - ediff edt efaq eglot eieio emacs-gnutls \ + ediff efaq eglot eieio emacs-gnutls \ emacs-mime epa erc ert eshell eudc eww flymake forms gnus \ - htmlfontify idlwave ido info.info mairix-el message mh-e \ + htmlfontify idlwave ido info.info mairix-el message \ modus-themes newsticker nxml-mode octave-mode org pcl-cvs pgg \ rcirc reftex remember sasl sc ses sieve smtpmail \ speedbar todo-mode tramp transient url use-package \ diff --git a/doc/misc/edt.texi b/doc/misc/edt.texi deleted file mode 100644 index 1a835f79d7f..00000000000 --- a/doc/misc/edt.texi +++ /dev/null @@ -1,938 +0,0 @@ -\input texinfo -@setfilename ../../info/edt.info -@settitle EDT Emulation for Emacs -@include docstyle.texi - -@copying -This file documents the EDT emulation package for Emacs. - -Copyright @copyright{} 1986, 1992, 1994--1995, 1999--2024 Free Software -Foundation, Inc. - -@quotation -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.3 or -any later version published by the Free Software Foundation; with no -Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,'' -and with the Back-Cover Texts as in (a) below. A copy of the license -is included in the section entitled ``GNU Free Documentation License''. - -(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and -modify this GNU manual.'' -@end quotation -@end copying - -@dircategory Emacs misc features -@direntry -* EDT: (edt). An Emacs emulation of the EDT editor. -@end direntry - -@titlepage -@title EDT Emulation User's Manual -@author Kevin Gallagher -@author @email{kevin.gal@@verizon.net} -@page -@vskip 0pt plus 1filll -@insertcopying -@end titlepage - -@contents - -@ifnottex -@node Top -@top Emacs EDT emulation -This manual describes the Emacs EDT package, which provides emulation -of DEC's EDT editor. - -@insertcopying -@end ifnottex - -@menu -* Overview:: Overview of the EDT package. -* Supported terminals:: Terminals/keyboards that are supported. -* Starting emulation:: How to get started. -* Platform-specific notes:: Notes specific to certain platforms. -* Differences:: How does this EDT emulation differ from real EDT? -* Highlights:: Some highlights, and comparisons to the - original Emacs EDT emulation. -* Customizing:: Customizing emulation. -* GNU Free Documentation License:: The license for this manual. -@end menu - -@node Overview -@chapter Overview of the EDT Package - -This manual describes version 4.0 of the EDT Emulation for Emacs. -It comes with special functions which replicate nearly all of -EDT's keypad mode behavior. It sets up default keypad and function key -bindings which closely match those found in EDT@. Support is provided so -that users may reconfigure most keypad and function key bindings to -their own liking. - -Version 4.0 contains several enhancements (@pxref{Changes}). - -@menu -* Quick start:: How to begin using EDT. -* Changes:: What's new in version 4.0. -* Goals:: The aims of this package. -@end menu - -@node Quick start -@section How to Begin Using EDT - -To start the EDT Emulation, first start Emacs and then enter @kbd{M-x -edt-emulation-on} to begin the emulation. After initialization is -complete, the following message will appear below the status line -informing you that the emulation has been enabled: ``Default EDT keymap -active''. - - You can have the EDT Emulation start up automatically, each time you -initiate an Emacs session, by adding the following line to your -@file{.emacs} file: - -@example -(add-hook 'emacs-startup-hook 'edt-emulation-on) -@end example - -@noindent @strong{Important:} Be sure to read the rest of this manual. -It contains very useful information on how the EDT Emulation behaves and -how to customize it to your liking. - -@noindent The EDT emulation consists of the following files: - -@itemize - -@item -@file{edt.texi}---This manual. - -@item -@file{edt-user.el}---An example customization file (located in the -Emacs distribution etc directory). - -@item -@file{edt.el}---EDT emulation functions and default configuration. - -@item -@file{edt-lk201.el}---Built-in support for DEC LK-201 keyboards. - -@item -@file{edt-vt100.el}---Built-in support for DEC VT-100 (and above) terminals. - -@item -@file{edt-pc.el}---Built-in support for PC 101 Keyboards under MS-DOS. - -@item -@file{edt-mapper.el}---Create an EDT LK-201 map file for keyboards -without built-in support. - -@end itemize - -@node Changes -@section What's New in Version 4.0 - -Version 4.0 contains the following enhancements: - -@enumerate - -@item -Scroll margins at the top and bottom of the window are now supported. -(The design was copied from @file{tpu-extras.el}.) By default, this -feature is enabled with the top margin set to 10% of the window and the -bottom margin set to 15% of the window. To change these settings, you -can invoke the function @code{edt-set-scroll-margins} in your -@file{.emacs} file. For example, the following line - -@example -(edt-set-scroll-margins "20%" "25%") -@end example - -@noindent sets the top margin to 20% of the window and the bottom margin -to 25% of the window. To disable this feature, set each margin to 0%. -You can also invoke @code{edt-set-scroll-margins} interactively while -EDT Emulation is active to change the settings for that session. - -@strong{Please note:} Another way to set the scroll margins is to use -the Emacs customization feature to set the following two variables -directly: @code{edt-top-scroll-margin} and @code{edt-bottom-scroll-margin}. - -Enter the Emacs @code{customize} command. First select the -@samp{Editing} group and then select the @samp{Emulations} group. -Finally, select the @samp{Edt} group and follow the directions. - -@item -The @samp{SUBS} command is now supported and bound to @kbd{GOLD-Enter} -by default. (This design was copied from @file{tpu-edt.el}.) Note, in -earlier versions of EDT Emulation, @kbd{GOLD-Enter} was assigned to the -Emacs function @code{query-replace}. The binding of -@code{query-replace} has been moved to @kbd{GOLD-/}. If you prefer to -restore @code{query-replace} to @kbd{GOLD-Enter}, then use an EDT user -customization file, @file{edt-user.el}, to do this -(@pxref{Customizing}). - -@item -If you access a workstation using an X Server, observe that the -initialization file generated by @file{edt-mapper.el} will now contain -the name of the X Server vendor. This is a convenience for those who -have access to their Unix account from more than one type of X Server. -Since different X Servers typically require different EDT emulation -initialization files, @file{edt-mapper.el} will now generate these -different initialization files and save them with different names. -Then, the correct initialization file for the particular X server in use -is loaded correctly automatically. - -@item -Also, @file{edt-mapper.el} is now capable of binding an @acronym{ASCII} -key sequence, providing the @acronym{ASCII} key sequence prefix is -already known by Emacs to be a prefix. As a result of providing this -support, some terminal/keyboard/window system configurations, which -don't have a complete set of sensible function key bindings built into -Emacs in @code{input-decode-map}, can still be configured for use with -EDT Emulation. (Note: In a few rare circumstances this does not work -properly. In particular, it does not work if a subset of the leading -@acronym{ASCII} characters in a key sequence are recognized by Emacs as -having an existing binding. For example, if the keypad 7 (@key{KP7}) -key generates the sequence @samp{@key{ESC}Ow} and @samp{@key{ESC}O} is already -bound to a function, pressing @key{KP7} when told to do so by -@file{edt-mapper.el} will result in @file{edt-mapper.el} incorrectly -mapping @samp{@key{ESC}O} to @key{KP7} and @samp{w} to @key{KP8}. If -something like this happens to you, it is probably a bug in the support -for your keyboard within Emacs @strong{or} a bug in the Unix -termcap/terminfo support for your terminal @strong{or} a bug in the -terminal emulation software you are using.) - -@item -The @code{edt-quit} function (bound to @kbd{GOLD-q} by default) has been -modified to warn the user when file-related buffer modifications exist. -It now cautions the user that those modifications will be lost if the -user quits without saving those buffers. - -@end enumerate - -@node Goals -@section The Aims of this Package - -@enumerate - -@item -Emulate EDT Keypad Mode commands closely so that current EDT users will -find that it easy and comfortable to use Emacs with a small learning -curve. - -@item -Make it easy for a user to customize EDT emulation key bindings without -knowing much about Emacs Lisp. - -@item -Make it easy to switch between the original EDT default bindings and the -user's customized EDT bindings, without having to exit Emacs. - -@item -Provide support for some TPU/EVE functions not supported in EDT. - -@item -Provide an easy way to restore @strong{all} original Emacs key bindings, -just as they existed before the EDT emulation was first invoked. - -@item -Supports highlighting of marked text within the EDT emulation on all -platforms on which Emacs supports highlighting of marked text. - -@item -Handle terminal configuration interactively for most terminal -configurations, when the emulation is invoked for the first time. - -@item -Support a PC AT keyboard under MS-DOS. - -@end enumerate - -@node Supported terminals -@chapter Terminals/Keyboards that are Supported - -Keyboards used under a Window System are supported via the -@code{edt-mapper} function. The first time you invoke the emulation -under a window system, the @code{edt-mapper} function is run -automatically and the user is prompted to identify which keys the -emulation is to use for the standard keypad and function keys EDT -expects (e.g., @key{PF1}, @key{PF2}, @key{KP0}, @key{KP1}, @key{F1}, -@key{F2}, etc.). This configuration is saved to disk read each time the -emulation is invoked. - -In character oriented connections not running a window manager, built-in -support for the following terminals/keyboards is provided: - -@enumerate - -@item -DEC VT-100 series and higher. This includes well behaved VT clones and -emulators. If you are using a VT series terminal, be sure that the -@env{TERM} environment variable is set properly before invoking emacs. - -@item -PC AT keyboard under MS-DOS. - -@end enumerate - -Be sure to read @ref{Platform-specific notes} to see if those notes -apply to you. - -@node Starting emulation -@chapter How to Get Started - -Start up Emacs and enter @kbd{M-x edt-emulation-on} to begin the -emulation. After initialization is complete, the following message will -appear below the status line informing you that the emulation has been -enabled: ``Default EDT keymap active''. - -You can have the EDT Emulation start up automatically, each time you -initiate an Emacs session, by adding the following line to your -@file{.emacs} file: - -@example -(add-hook 'emacs-startup-hook 'edt-emulation-on) -@end example - -A reference sheet is included (later on) listing the default EDT -Emulation key bindings. This sheet is also accessible on line from -within Emacs by pressing @key{PF2}, @kbd{GOLD-H}, or @samp{HELP} (when -in the EDT Default Mode). - -It is easy to customize key bindings in the EDT Emulation -(@pxref{Customizing}). Customizations are placed in a file called -@file{edt-user.el}. The Emacs @file{etc/} directory contains an -example. If @file{edt-user.el} is found in your Emacs load path -during EDT Emulation initialization, then the following message will -appear below the status line indicating that the emulation has been -enabled, enhanced by your own customizations: ``User EDT custom keymap -active''. - -Once enabled, it is easy to switch back and forth between your -customized EDT Emulation key bindings and the default EDT Emulation key -bindings. (Look at the binding to @kbd{GOLD-Z} in the sample -@file{edt-user.el} file.) It is also easy to turn off the emulation -(via the command @code{edt-emulation-off}). Doing so completely -restores the original key bindings in effect just prior to invoking the -emulation. - -Emacs binds keys to @acronym{ASCII} control characters and so does the -real EDT@. Where EDT key bindings and Emacs key bindings conflict, -the default Emacs key bindings are retained by the EDT emulation by -default. If you are a die-hard EDT user you may not like this. The -@ref{Control keys} section explains how to change this so that the EDT -bindings to @acronym{ASCII} control characters override the default -Emacs bindings. - -@node Platform-specific notes -@chapter Notes Specific to Certain Platforms - -@menu -* Sun workstations:: Sun workstations running X. -* MS-DOS:: PC users running MS-DOS. -* GNU/Linux:: PC users running GNU/Linux. -* Unix:: Using @key{NumLock} for the @key{PF1} key on Unix systems. -@end menu - -@node Sun workstations -@section Sun Workstations Running X - -Some earlier Sun keyboards do not have arrow keys separate from the -keypad keys. It is difficult to emulate the full EDT keypad and still -retain use of the arrow keys on such keyboards. - -The Sun Type 5 and other more recent Sun keyboards, however, do have -separate arrow keys. This makes them candidates for setting up a -reasonable EDT keypad emulation. - -Depending upon the configuration of the version of X installed on your -system, you may find the default X keynames for the keypad keys don't -permit Emacs to interpret some or all the keypad keys as something other -than arrow keys, numeric keys, @key{Home}, @key{PageUp}, etc. Both Sun -and HP have been particularly guilty of making bizarre keysym -assignments to the keypad keys. - -In most cases, the X Windows command, @code{xmodmap}, can be used to -correct the problem. Here's a sample @file{.xmodmaprc} file which -corrects this problem on one Sun workstation configuration using an -older SunOS release configured with a Sun Type 5 keyboard: - -@example -! File: .xmodmaprc -! -! Set up Sun Type 5 keypad for use with the Emacs EDT Emulation -! -keycode 53 = KP_Divide -keycode 54 = KP_Multiply -keycode 57 = KP_Decimal -keycode 75 = KP_7 -keycode 76 = KP_8 -keycode 77 = KP_9 -keycode 78 = KP_Subtract -keycode 97 = KP_Enter -keycode 98 = KP_4 -keycode 99 = KP_5 -keycode 100 = KP_6 -keycode 101 = KP_0 -keycode 105 = F24 -keycode 119 = KP_1 -keycode 120 = KP_2 -keycode 121 = KP_3 -keycode 132 = KP_Add -@end example - -If @file{edt-mapper.el} does not recognize your keypad keys as unique -keys, use the command @samp{xmodmap -pke} to get a listing of the actual -key codes and the keysyms mapped to them and then generate you own -custom @file{.xmodmaprc} similar to the one above. - -Next, feed @file{.xmodmaprc} to the @code{xmodmap} command and all the -Sun Type 5 keypad keys will now be configurable for the emulation of an -LK-201 keypad (less the @key{,} key). In this example, the line - -@example -keycode 105 = F24 -@end example - -@noindent changes the X Windows name of the keypad @key{NumLock} key to -be known internally as the @key{F24} key. Doing so permits it to be -configured to behave as the @key{PF1} (@key{GOLD}) key. - -The side effect of this change is that you will no longer have a -@key{NumLock} key. If you are using other software under X which -requires a @key{NumLock} key, then examine your keyboard and look for -one you don't use and redefine it to be the @key{NumLock} key. -Basically, you need to clear the @key{NumLock} key from being assigned -as a modifier, assign it to the key of your choice, and then add it back -as a modifier. (@ref{Unix} for further help on how to do this.) - -@node MS-DOS -@section PC Users Running MS-DOS - -By default, F1 is configured to emulate the @key{PF1} (@key{GOLD}) key. -But @key{NumLock} can be used instead if you load a freeware TSR -distributed with MS-Kermit, call @samp{gold.com}. This was once -distributed in a file called @file{gold22.zip} and came with the source -code as well as a loadable binary image. (See @file{edt-pc.el} in the -Emacs @file{lisp/emulation} directory for more information.) - -@node GNU/Linux -@section PC Users Running GNU/Linux - -The default X server configuration varies from distribution to -distribution and release to release of GNU/Linux. If your system fails -to recognize the keypad keys as distinct keys, change the NumLock state, -turning it on or off, as the case may be, then try again. If this -doesn't solve your problem, you may have to modify the X keysym mappings -with @code{xmodmap}. - -On one distribution on an Intel PC, the following @file{.xmodmaprc} set -things up nicely. - -@example -! File: .xmodmaprc -! -! Set up PC keypad under GNU/Linux for the Emacs EDT Emulation -! -clear mod2 -keycode 77 = F12 -keycode 96 = Num_Lock Pointer_EnableKeys -add mod2 = Num_Lock -@end example - -In this example, after feeding the file to the @code{xmodmap} command, -the PC @key{NumLock} keypad key will be configurable for the emulation -of the @key{PF1} key. The PC keypad can now emulate an LK-201 keypad -(less the comma key), the standard keyboard supplied with DEC terminals -VT-200 and above. This @file{.xmodmaprc} file switches the role of the -@key{F12} and @key{NumLock} keys. It has been tested on Red Hat -GNU/Linux 5.2. Other versions of GNU/Linux may require different -keycodes. (@ref{Unix} for further help on how to do this.) - -@strong{Please note:} Remember, it may be necessary to have @key{NumLock} in -one position (ON) or the other (OFF) for the PC keypad to emulate the -LK-201 keypad properly. - -@node Unix -@section General Notes on Using @key{NumLock} for the @key{PF1} Key on Unix Systems - -Making the physical @key{NumLock} key available for use in the EDT Emulation -requires some modification to the default X Window settings. Since the -keycode assignments vary from system to system, some investigation is -needed to see how to do this on a particular system. - -You will need to look at the output generated by @code{xmodmap} invoked -with the "-pm" switch. For example, on Red Hat GNU/Linux 5.2 on a PC, we -get the following output when running @samp{xmodmap -pm}: - -@example -xmodmap: up to 2 keys per modifier, (keycodes in parentheses): - -shift Shift_L (0x32), Shift_R (0x3e) -lock Caps_Lock (0x42) -control Control_L (0x25), Control_R (0x6d) -mod1 Alt_L (0x40), Alt_R (0x71) -mod2 Num_Lock (0x4d) -mod3 -mod4 -mod5 Scroll_Lock (0x4e) -@end example - -@noindent Note that Num_Lock is assigned to the modifier @samp{mod2}. This is -what hides Num_Lock from being seen by Emacs. - -Now, @samp{xmodmap -pke} yields: - -@example - . - . - . -keycode 77 = Num_Lock Pointer_EnableKeys - . - . - . -keycode 96 = F12 - . - . - . -@end example - -@noindent So, in Red Hat GNU/Linux 5.2 on a PC, Num_Lock generates keycode 77. -The following steps are taken: - -@enumerate -@item -clear the assignment of Num_Lock to mod2; -@item -swap the keycodes assigned to F12 and Num_Lock; -@item -assign Num_Lock back to mod2. -@end enumerate - -@noindent The @file{.xmodmaprc} file looks like this: - -@example -! File: .xmodmaprc -! -! Set up PC keypad under GNU/Linux for the Emacs EDT Emulation -! -clear mod2 -keycode 77 = F12 -keycode 96 = Num_Lock Pointer_EnableKeys -add mod2 = Num_Lock -@end example - -So, after executing @samp{xmodmap .xmodmaprc}, a press of the physical -@key{F12} key looks like a Num_Lock keypress to X@. Also, a press of the -physical @key{NumLock} key looks like a press of the @key{F12} key to X. - -Now, @file{edt-mapper.el} will see @samp{f12} when the physical -@key{NumLock} key is pressed, allowing the @key{NumLock} key to be used -as the EDT @key{PF1} (@key{GOLD}) key. - -@node Differences -@chapter How Does this EDT Emulation Differ from Real EDT? - -In general, you will find that this emulation of EDT replicates most, -but not all, of EDT's most used Keypad Mode editing functions and -behavior. It is not perfect, but most EDT users who have tried the -emulation agree that it is quite good enough to make it easy for -die-hard EDT users to move over to using Emacs. - -Here's a list of the most important differences between EDT and this GNU -Emacs EDT Emulation. The list is short but you must be aware of these -differences if you are to use the EDT Emulation effectively. - -@enumerate - -@item -Entering repeat counts works a little differently than in EDT. - -EDT allows users to enter a repeat count before entering a command that -accepts repeat counts. For example, when using the real EDT, pressing -these three keys in sequence, @kbd{GOLD 5 KP1}, will move the cursor in -the current direction 5 words. This does @strong{not} work in Emacs! - -Emacs provides two ways to enter repeat counts and neither involves -using the @key{GOLD} key. First, repeat counts can be entered in Emacs -by using the @key{ESC} key. For example, pressing these keys in -sequence, @kbd{ESC 1 0 KP1}, will move the cursor in the current -direction 10 words. Second, Emacs provides another command called -@code{universal-argument} that can be used to do the same thing. -Normally, in Emacs has this bound to @kbd{C-u}. - -@item -EDT's line mode commands and nokeypad mode commands are @strong{not} -supported (with one important exception; see item 8 in -@ref{Highlights}). Although, at first, this may seem like a big -omission, the set of built-in Emacs commands provides a much richer set -of capabilities which more than make up for this omission. - -To enter Emacs commands not bound to keys, you can press @kbd{GOLD KP7} -or the @key{DO} key. Emacs will display its own command prompt "M-x". -This stands for the keypress @kbd{Meta-x}, where @key{Meta} is a special -shift key. The @key{Alt} key is often mapped to behave as a @key{Meta} -key. So, you can also invoke this prompt by pressing @kbd{Meta-x}. -Typing the sequence @kbd{ESC x} will also invoke the prompt. - -@item -Selected text is highlighted @strong{only} on systems where Emacs -supports the highlighting of text. - -@item -Just like in TPU/EVE, the @key{ENTER} key is @strong{not} used to -terminate input when the editor prompts you for input. The @key{RETURN} -key is used, instead. (@key{KP4} and @key{KP5} (the direction keys) do -terminate input for the @samp{FIND} command, just like in EDT, however.) - -@end enumerate - -@node Highlights -@chapter Some Highlights, and Comparisons to the Original Emacs EDT Emulation - -@enumerate - -@item -The EDT define key command is supported (@code{edt-define-key}) and is -bound to @kbd{C-k} in the default EDT mode when EDT control sequence -bindings are enabled, or when the sample @file{edt-user.el} -customization file is used. The TPU/EVE learn command is supported but -not bound to a key in the default EDT mode but is bound in the sample -@file{edt-user.el} file. - -Unlike the TPU/EVE learn command, which uses one key to begin the learn -sequence, @kbd{C-l}, and another command to remember the sequence, -@kbd{C-r}, this version of the learn command (@code{edt-learn}) serves -as a toggle to both begin and to remember the learn sequence. - -Many users who change the meaning of a key with the define key and the -learn commands, would like to be able to restore the original key -binding without having to quit and restart emacs. So a restore key -command is provided to do just that. When invoked, it prompts you to -press the key to which you wish the last replaced key definition -restored. It is bound to @kbd{GOLD C-k} in the default EDT mode when -EDT control sequence bindings are enabled or the sample -@file{edt-user.el} customization file is used. - -@item -Direction support is fully supported. - -@item -All original Emacs bindings are fully restored when EDT emulation is -turned off. So, if a fellow worker comes over to your terminal to help -you with a software problem, for example, and is completely confused by -your EDT emulation bindings, just enter the command, -@code{edt-emulation-off}, at the @samp{M-x} prompt and the original -Emacs bindings will be restored. To resume the EDT emulation, just -enter @code{edt-emulation-on}. - -@item -User custom EDT bindings are kept separate from the default EDT -bindings. One can toggle back and forth between the custom EDT bindings -and default EDT bindings. - -@item -The Emacs functions in @file{edt.el} attempt to emulate, where -practical, the exact behavior of the corresponding EDT keypad mode -commands. In a few cases, the emulation is not exact, but we hope you -will agree it is close enough. In a very few cases, we chose to use the -Emacs way of handling things. As mentioned earlier, we do not emulate -the EDT @samp{SUBS} command. Instead, we chose to use the Emacs -@code{query-replace} function, which we find to be easier to use. - -@item -Emacs uses the regexp assigned to @code{page-delimiter} to determine -what marks a page break. This is normally @samp{^\f}, which causes the -@code{edt-page} command to ignore form feeds not located at the -beginning of a line. To emulate the EDT @samp{PAGE} command exactly, -page-delimiter is set to @samp{\f} when EDT emulation is turned on, and -restored to @samp{^\f} when EDT emulation is turned off. But, since -some users prefer the Emacs definition of a page break, or may wish to -preserve a customized definition of page break, one can override the EDT -definition by placing - -@example -(setq edt-keep-current-page-delimiter t) -@end example - -@noindent in your @file{.emacs} file. Or, you can used the Emacs customize -command to change its setting. - -@item -The EDT definition of a section of a terminal window is hardwired to be -16 lines of its one-and-only 24-line window (the EDT @samp{SECT} command -bound to @key{KP8}). That's two-thirds of the window at a time. Since -Emacs, like TPU/EVE, can handle multiple windows of sizes of other than -24 lines, the definition of section used here has been modified to -two-thirds of the current window. (There is also an -@code{edt-scroll-window} function which you may prefer over the -@samp{SECT} emulation.) - -@item -Cursor movement and deletion involving word entities is identical to -EDT@. This, above all else, gives the die-hard EDT user a sense of being -at home. Also, an emulation of EDT's @samp{SET ENTITY WORD} command is -provided, for those users who like to customize movement by a word at a -time to their own liking. - -@item -EDT's @samp{FIND} and @samp{FNDNXT} are supported. - -@item -EDT's @samp{APPEND}, @samp{REPLACE}, and @samp{SUBS} commands are supported. - -@item -@samp{CHNGCASE} is supported. It works on individual characters or -selected text, if @samp{SELECT} is active. In addition, two new -commands are provided: @code{edt-lowercase} and @code{edt-uppercase}. -They work on individual @strong{words} or selected text, if -@samp{SELECT} is active. - -@item -Form feed and tab insert commands are supported. - -@item -A new command, @code{edt-duplicate-word}, is provided. If you -experiment with it, you might find it to be surprisingly useful and may -wonder how you ever got along without it! It is assigned to @kbd{C-j} -in the sample @file{edt-user.el} customization file. - -@item -TPU/EVE's Rectangular Cut and Paste functions (originally from the -EVE-Plus package) are supported. But unlike the TPU/EVE versions, these -here support both insert and overwrite modes. The seven rectangular -functions are bound to @key{F7}, @key{F8}, @kbd{GOLD-F8}, @key{F9}, -@kbd{GOLD-F9}, @key{F10}, and @kbd{GOLD-F10} in the default EDT mode. - -@item -The original EDT emulation package set up many default regular and GOLD -bindings. We tried to preserve most (but not all!)@: of these, so users -of the original emulation package will feel more at home. - -Nevertheless, there are still many GOLD key sequences which are not -bound to any functions. These are prime candidates to use for your own -customizations. - -Also, there are several commands in @file{edt.el} not bound to any key. -So, you will find it worthwhile to look through @file{edt.el} for -functions you may wish to add to your personal customized bindings. - -@item -The VT200/VT300 series terminals steal the function keys @key{F1} to -@key{F5} for their own use. These do not generate signals which are -sent to the host. So, @file{edt.el} does not assign any default -bindings to @key{F1} through @key{F5}. - -In addition, our VT220 terminals generate an interrupt when the @key{F6} -key is pressed (@samp{^C} or @samp{^Y}, can't remember which) and not -the character sequence documented in the manual. So, binding Emacs -commands to @key{F6} will not work if your terminal behaves the same -way. - -@item -The VT220 terminal has no @key{ESC}, @key{BS}, nor @key{LF} keys, as -does a VT100. So the default EDT bindings adopt the standard DEC -convention of having the @key{F11}, @key{F12}, and @key{F13} keys, on a -VT200 series (and above) terminal, assigned to the same EDT functions -that are bound to @key{ESC}, @key{BS}, and @key{LF} on a VT100 terminal. - -@item -Each user, through the use of a private @file{edt-user.el} file, can -customize, very easily, personal EDT emulation bindings. - -@item -The EDT @samp{SELECT} and @samp{RESET} functions are supported. -However, unlike EDT, pressing @samp{RESET} to cancel text selection does -@strong{not} reset the existing setting of the current direction. - -We also provide a TPU/EVE like version of the single @samp{SELECT/RESET} -function, called @code{edt-toggle-select}, which makes the EDT -@samp{SELECT} function into a toggle on/off switch. That is, if -selection is on, pressing @samp{SELECT} again turns selection off -(cancels selection). This function is used in the sample -@file{edt-user.el} customization file. - -@item -EDT scroll margins are supported, but are disabled by default. -(@ref{Scroll margins} for instructions on how to enable them.) - -@end enumerate - -@node Customizing -@chapter Customizing Emulation - -Most EDT users, at one time or another, make some custom key bindings, -or use someone else's custom key bindings, which they come to depend -upon just as if they were built-in bindings. This EDT Emulation for GNU -Emacs is designed to make it easy to customize bindings. - -If you wish to customize the EDT Emulation to use some of your own key -bindings, you need to make a private version of @file{edt-user.el} in -your own private lisp directory. The Emacs @file{etc/} directory -contains an example for you to use as a template and for ideas. -@c This seems to be untrue. -@ignore -There are two sample files @file{edt-user.el1} and @file{edt-user.el2} -for you to use as templates and for ideas. Look at @file{edt-user.el1} -first. Unless you will be using two or more very different types of -terminals on the same system, you need not look at @file{edt-user.el2}. -@end ignore - -First, you need to have your own private lisp directory, say -@file{~/lisp}, and you should add it to the Emacs load path. - -@strong{Please note:} A few sites have different load-path requirements, -so the above directions may need some modification if your site has such -special needs. - -@menu -* Init file:: Creating your own @file{edt-user.el} file. -* Words:: Specifying word entities. -* Control keys:: Enabling EDT control key sequence bindings. -* Scroll margins:: Setting scroll margins. -@end menu - -@node Init file -@section Creating your own @file{edt-user.el} File - -A sample @file{edt-user.el} file is provided in the Emacs @file{etc/} -directory. You should use it as a guide to learn how you can customize -EDT emulation bindings to your own liking. Names used to identify the -set of LK-201 keypad and function keys are: - -@example -Keypad Keys: - PF1 PF2 PF3 PF4 - KP7 KP8 KP9 KP- - KP4 KP5 KP6 KP, - KP1 KP2 KP3 - KP0 KPP KPE -@end example - -@example -Arrow Keys: - LEFT RIGHT DOWN UP -@end example - -@example -Function Keys: - F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 - HELP DO F17 F18 F19 F20 - - FIND INSERT REMOVE - SELECT PREVIOUS NEXT -@end example - -Note: Many VT-200 terminals, and above, steal function keys @key{F1} -through @key{F5} for terminal setup control and don't send anything to -the host if pressed. So customizing bindings to these keys may not work -for you. - -There are three basic functions that do the EDT emulation custom -bindings: @code{edt-bind-key}, @code{edt-bind-gold-key}, and -@code{edt-bind-function-key}. - -The first two are for binding functions to keys which are standard -across most keyboards. This makes them keyboard independent, making it -possible to define these key bindings for all terminals in the file -@file{edt.el}. - -The first, @code{edt-bind-key}, is used typically to bind emacs commands -to control keys, although some people use it to bind commands to other -keys, as well. (For example, some people use it to bind the VT200 -seldom used back-tick key (@samp{`}) to the function @samp{ESC-prefix} -so it will behave like an @key{ESC} key.) The second function, -@code{edt-bind-gold-key}, is used to bind emacs commands to gold key -sequences involving alphanumeric keys, special character keys, and -control keys. - -The third function, @code{edt-bind-function-key}, is terminal dependent -and is defined in a terminal specific file (see @file{edt-vt100.el} for -example). It is used to bind emacs commands to LK-201 function keys, to -keypad keys, and to gold sequences of those keys. - -@node Words -@section Specifying Word Entities - -The variable @code{edt-word-entities} is used to emulate EDT's @samp{SET -ENTITY WORD} command. It contains a list of characters to be treated as -words in themselves. If the user does not define -@code{edt-word-entities} in his/her @file{.emacs} file, then it is set -up with the EDT default containing only @key{TAB}. - -The characters are stored in the list by their numerical values, not as -strings. Emacs supports several ways to specify the numerical value of -a character. One method is to use the question mark: @samp{?A} means -the numerical value for @samp{A}, @samp{?/} means the numerical value -for @samp{/}, and so on. Several unprintable characters have special -representations: - -@example -?\b specifies BS, C-h -?\t specifies TAB, C-i -?\n specifies LFD, C-j -?\v specifies VTAB, C-k -?\f specifies FF, C-l -?\r specifies CR, C-m -?\e specifies ESC, C-[ -?\\ specifies \ -@end example - -Here are some examples: - -@example -(setq edt-word-entities '(?\t ?- ?/)) ; specifies TAB, - , and / -(setq edt-word-entities '(?\t) ; specifies TAB, the default -@end example - -@noindent You can also specify characters by their decimal ASCII values: - -@example -(setq edt-word-entities '(9 45 47)) ; specifies TAB, - , and / -@end example - -@node Control keys -@section Enabling EDT Control Key Sequence Bindings - -Where EDT key bindings and Emacs key bindings conflict, the default -Emacs key bindings are retained by default. Some die-hard EDT users -may not like this. So, if the variable -@code{edt-use-EDT-control-key-bindings} is set to true in a user's -@file{.emacs} file, then the default EDT Emulation mode will enable most -of the original EDT control key sequence bindings. If you wish to do -this, add the following line to your @file{.emacs} file: - -@example -(setq edt-use-EDT-control-key-bindings t) -@end example - -@node Scroll margins -@section Setting Scroll Margins - -Scroll margins at the top and bottom of the window are now supported. -(The design was copied from @file{tpu-extras.el}.) By default, this -feature is enabled with the top margin set to 10% of the window and the -bottom margin set to 15% of the window. To change these settings, you -can invoke the function @code{edt-set-scroll-margins} in your -@file{.emacs} file. For example, the following line - -@example -(edt-set-scroll-margins "20%" "25%") -@end example - -@noindent sets the top margin to 20% of the window and the bottom margin -to 25% of the window. To disable this feature, set each margin to 0%. -You can also invoke @code{edt-set-scroll-margins} interactively while -EDT Emulation is active to change the settings for that session. - -@strong{Please note:} Another way to set the scroll margins is to use -the Emacs customization feature to set the following two variables -directly: @code{edt-top-scroll-margin} and @code{edt-bottom-scroll-margin}. - -Enter the Emacs @code{customize} command. First select the -@samp{Editing} group and then select the @samp{Emulations} group. -Finally, select the @samp{Edt} group and follow the directions. - -@node GNU Free Documentation License -@appendix GNU Free Documentation License -@include doclicense.texi - -@bye diff --git a/doc/misc/message.texi b/doc/misc/message.texi index 468bf81599d..a888e12e010 100644 --- a/doc/misc/message.texi +++ b/doc/misc/message.texi @@ -1914,7 +1914,6 @@ when it doesn't lead to the user having to wait. @vindex message-send-mail-function @findex message-send-mail-function @findex message-send-mail-with-sendmail -@findex message-send-mail-with-mh @findex message-send-mail-with-qmail @findex message-smtpmail-send-it @findex smtpmail-send-it @@ -1924,8 +1923,8 @@ Function used to send the current buffer as mail. The default is @code{message-send-mail-with-sendmail}, or @code{smtpmail-send-it} according to the system. Other valid values include @code{message-send-mail-with-mailclient}, -@code{message-send-mail-with-mh}, @code{message-send-mail-with-qmail}, -@code{message-smtpmail-send-it} and @code{feedmail-send-it}. +@code{message-send-mail-with-qmail}, @code{message-smtpmail-send-it} and +@code{feedmail-send-it}. The function @code{message-send-mail-with-sendmail} pipes your article to the @@ -1980,14 +1979,6 @@ recognized values of @samp{mailer} are sendmail, qmail, mh, and mailclient. -@item message-mh-deletable-headers -@vindex message-mh-deletable-headers -Most versions of MH doesn't like being fed messages that contain the -headers in this variable. If this variable is non-@code{nil} (which is -the default), these headers will be removed before mailing when sending -messages via MH@. Set it to @code{nil} if your MH can handle these -headers. - @item message-qmail-inject-program @vindex message-qmail-inject-program @cindex qmail diff --git a/doc/misc/mh-e.texi b/doc/misc/mh-e.texi deleted file mode 100644 index 3e98a14ecfc..00000000000 --- a/doc/misc/mh-e.texi +++ /dev/null @@ -1,8986 +0,0 @@ -\input texinfo @c -*- mode: texinfo; coding: utf-8; -*- -@c -@c Note: This document requires makeinfo version 4.6 or greater to build. -@c -@c %**start of header -@setfilename ../../info/mh-e.info -@settitle The MH-E Manual -@include docstyle.texi -@c %**end of header - -@c Version of the software and manual. -@set VERSION 8.6 -@c Edition of the manual. It is either empty for the first edition or -@c has the form ", nth Edition" (without the quotes). -@set EDITION -@set UPDATED 2016-04-29 -@set UPDATE-MONTH April, 2016 - -@c Other variables. -@set MH-BOOK-HOME https://rand-mh.sourceforge.io/book/ -@set MH-E-HOME https://mh-e.sourceforge.io/ - -@c Copyright -@copying -This is version @value{VERSION}@value{EDITION} of @cite{The MH-E -Manual}, last updated @value{UPDATED}. - -Copyright @copyright{} 1995, 2001--2003, 2005--2024 Free Software -Foundation, Inc. - -@c This dual license has been agreed upon by the FSF. - -@quotation -Permission is granted to copy, distribute and/or modify this document -under the terms of either: - -@enumerate a -@item -the GNU Free Documentation License, Version 1.3 or any later version -published by the Free Software Foundation; with no Invariant Sections, -with the Front-Cover Texts being ``A GNU Manual,'' and with the -Back-Cover Texts as in (a) below. A copy of the license is included in -the section entitled ``GNU Free Documentation License.'' - -(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and -modify this GNU manual.'' - -@item -the GNU General Public License as published by the Free Software -Foundation; either version 3, or (at your option) any later version. A -copy of the license is included in the section entitled ``GNU General -Public License.'' -@end enumerate - -@end quotation -@end copying - -@c Info Directory Entry -@dircategory Emacs network features -@direntry -* MH-E: (mh-e). Emacs interface to the MH mail system. -@end direntry - -@c Title Page -@titlepage -@title The MH-E Manual -@subtitle Version @value{VERSION}@value{EDITION} -@subtitle @value{UPDATE-MONTH} -@author Bill Wohler - -@c Copyright Page -@page -@vskip 0pt plus 1filll -@insertcopying -@end titlepage - -@ifnottex -@html - -@end html -@insertcopying -@end ifnottex - -@c Table of Contents -@contents - -@html - -@end html - -@node Preface -@unnumbered Preface - -@cindex Emacs -@cindex Unix commands, Emacs -@cindex preface - -This manual introduces another interface to the MH mail system that is -accessible through the GNU Emacs editor, namely, @emph{MH-E}. MH-E is -easy to use. I don't assume that you know GNU Emacs or even MH at this -point, since I didn't know either of them when I discovered MH-E@. -However, MH-E was the tip of the iceberg, and I discovered more and -more niceties about GNU Emacs and MH@. Now I'm fully hooked on both of -them. - -The MH-E package is distributed with Emacs@footnote{Version -@value{VERSION} of MH-E appeared in Emacs 24.4. It is compatible with -MH versions 6.8.4 and higher, all versions of nmh, and GNU mailutils -1.0 and higher}, so you shouldn't have to do anything special to use -it. Gnus is also required; it is bundled with Emacs. This manual -covers MH-E version @value{VERSION}. To help you decide which version -you have, see @ref{Getting Started}. - -@findex help-with-tutorial -@kindex C-h t - -If you don't already use GNU Emacs but want to learn more, you can -read a built-in tutorial by starting GNU Emacs and typing @kbd{C-h t} -(@code{help-with-tutorial}). (To learn about this notation, see -@ref{Conventions}.) If you want to take the plunge, consult the -@iftex -@cite{GNU Emacs Manual}, -@end iftex -@ifinfo -@ref{Top, , GNU Emacs Manual, emacs, GNU Emacs Manual}, -@end ifinfo -@ifhtml -@uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/, -@cite{GNU Emacs Manual}}, -@end ifhtml -from the Free Software Foundation. - -If more information is needed, you can go to the Unix manual pages of -the individual MH commands. When the name is not obvious, I'll guide -you to a relevant MH manual page that describes the action more fully. - -@c ":" does not work in index entries in Info. -@cindex @cite{MH & nmh - Email for Users & Programmers} -@cindex MH book -@cindex info -@kindex C-h i - -This manual is available in both Info and online formats. The Info -version is distributed with Emacs and can be accessed with the -@command{info} command (@samp{info mh-e}) or within Emacs (@kbd{C-h i -m mh-e @key{RET}}). The online version is available at -@uref{https://mh-e.sourceforge.io/manual/, SourceForge}. Another great -online resource is the book -@uref{https://rand-mh.sourceforge.io/book/, @cite{MH & nmh: Email for -Users & Programmers}} (also known as @dfn{the MH book}). - -I hope you enjoy this manual! If you have any comments, or suggestions -for this document, please let me know. - -@cindex Bill Wohler -@cindex Wohler, Bill - -@noindent -Bill Wohler <@i{wohler at newt.com}>@* -8 February 1995@* -24 February 2006 - -@node Conventions -@chapter GNU Emacs Terms and Conventions - -@cindex Emacs -@cindex Emacs, conventions -@cindex Emacs, terms -@cindex Unix commands, Emacs -@cindex conventions, Emacs -@cindex terms, Emacs - -If you're an experienced Emacs user, you can skip the following -conventions and definition of terms and go directly to the next -section (@pxref{Getting Started}). - -@cindex Emacs commands -@cindex MH commands -@cindex Unix commands -@cindex commands -@cindex commands, MH -@cindex commands, Unix -@cindex commands, shell -@cindex functions -@cindex shell commands - -In general, @dfn{functions} in this text refer to Emacs Lisp functions -that one would call from within Emacs Lisp programs (for example, -@code{(mh-inc-folder)}). On the other hand, @dfn{commands} are those -things that are run by the user, such as @kbd{i} or @kbd{M-x -mh-inc-folder}. Programs outside of Emacs are specifically called MH -commands, shell commands, or Unix commands. - -@cindex conventions, key names -@cindex key names - -The conventions for key names are as follows: - -@table @kbd -@item C-x -Hold down the @key{CTRL} (Control) key and press the @kbd{x} key. -@c ------------------------- -@item M-x -Hold down the @key{META} or @key{ALT} key and press the @kbd{x} key. - -Since some keyboards don't have a @key{META} key, you can generate -@kbd{M-x}, for example, by pressing @key{ESC} (Escape), -@emph{releasing it}, and then pressing the @kbd{x} key. -@c ------------------------- -@item @key{RET} -Press the @key{RETURN} or @key{ENTER} key. This is normally used to -complete a command. -@c ------------------------- -@item @key{SPC} -Press the space bar. -@c ------------------------- -@item @key{TAB} -Press the @key{TAB} key. -@c ------------------------- -@item @key{DEL} -Press the @key{DELETE} key. -@c ------------------------- -@item @key{BS} -Press the @key{BACKSPACE} key. -@end table - -@cindex Emacs, prefix argument -@cindex prefix argument -@kindex C-u - -A @dfn{prefix argument} allows you to pass an argument to any Emacs -function. To pass an argument, type @kbd{C-u} before the Emacs command -or keystroke. Numeric arguments can be passed as well. For example, to -insert five f's, use @kbd{C-u 5 f}. There is a default of four when -using @kbd{C-u}, and you can use multiple prefix arguments to provide -arguments of powers of four. To continue our example, you could insert -four f's with @kbd{C-u f}, 16 f's with @kbd{C-u C-u f}, 64 f's with -@kbd{C-u C-u C-u f}, and so on. Numeric and valueless negative -arguments can also be inserted with the @key{META} key. Examples -include @kbd{M-5} to specify an argument of 5, or @kbd{M--} which -specifies a negative argument with no particular value. - -@sp 1 -@center @strong{NOTE} - -@quotation -The prefix @kbd{C-u} or @kbd{M-} is not necessary in MH-E's MH-Folder -mode (@pxref{Reading Mail Tour}). In this mode, simply enter the -numerical argument before entering the command. -@end quotation -@sp 1 - -@cindex @file{.emacs} -@cindex Emacs, variables -@cindex files, @file{.emacs} -@cindex variables -@findex setq - -Emacs uses @dfn{variables} to hold values. These can be changed via -calls to the function @code{setq} in @file{~/.emacs}. - -@cindex Emacs, options -@cindex options -@findex customize-group -@findex customize-option - -Variables in MH-E that are normally modified by the user are called -@dfn{options} and are modified through the customize functions (such -as @kbd{M-x customize-option} or @kbd{M-x customize-group}). -@ifnothtml -@xref{Easy Customization,,,emacs,The GNU Emacs Manual}, in @cite{The -GNU Emacs Manual}. -@end ifnothtml -@ifhtml -See section -@uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Easy-Customization.html, -Easy Customization} in @cite{The GNU Emacs Manual}. -@end ifhtml -@xref{Options}. - -@cindex Emacs, faces -@cindex faces -@cindex highlighting -@findex customize-face - -You can specify various styles for displaying text using @dfn{faces}. -MH-E provides a set of faces that you can use to personalize the look -of your MH-E buffers. Use the command @kbd{M-x customize-face} to do -this. -@ifnothtml -@xref{Face Customization,,,emacs,The GNU Emacs Manual}, in @cite{The -GNU Emacs Manual}. -@end ifnothtml -@ifhtml -See section -@uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Face-Customization.html, -Face Customization} in @cite{The GNU Emacs Manual}. -@end ifhtml - -@cindex abnormal hooks -@cindex hooks -@cindex normal hooks -@findex add-hook -@findex customize-option - -Commands often offer @dfn{hooks} which enable you to extend or modify -the way a command works. -@ifnothtml -@ref{Hooks, , Hooks, emacs, The GNU Emacs Manual}, in @cite{The GNU -Emacs Manual} -@end ifnothtml -@ifhtml -See section -@uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Hooks.html, -Hooks} in @cite{The GNU Emacs Manual} -@end ifhtml -for a description about @dfn{normal hooks} and @dfn{abnormal hooks}. -MH-E uses normal hooks in nearly all cases, so you can assume that we -are talking about normal hooks unless we explicitly mention that a -hook is abnormal. We also follow the conventions described in that -section: the name of the abnormal hooks end in @code{-functions} and all -the rest of the MH-E hooks end in @code{-hook}. You can add hooks with -either @code{customize-option} or @code{add-hook}. - -@cindex Emacs, mark -@cindex Emacs, point -@cindex Emacs, region -@cindex mark -@cindex point -@cindex region -@kindex C-@@ -@kindex C-SPC - -There are several other terms that are used in Emacs that you should -know. The @dfn{point} is where the cursor currently is. You can save -your current place in the file by setting a @dfn{mark}. This operation -is useful in several ways. The mark can be later used when defining a -@dfn{region}, which is the text between the point and mark. Many -commands operate on regions, such as those for deleting text or -filling paragraphs. A mark can be set with @kbd{C-@@} (or -@kbd{C-@key{SPC}}). - -@cindex completion -@cindex Emacs, completion -@cindex Emacs, file completion -@cindex Emacs, folder completion -@cindex Emacs, minibuffer -@cindex file completion -@cindex folder completion -@cindex minibuffer -@kindex SPC -@kindex TAB - -The @dfn{minibuffer} is the bottom line of the Emacs window, where all -prompting and multiple-character input is directed. You can use -@dfn{completion} to enter values such as folders. Completion means -that Emacs fills in text for you when you type @key{SPC} or @key{TAB}. -A second @key{SPC} or @key{TAB} will list all possibilities at that -point. -@ifnothtml -@xref{Completion, , Completion, emacs, The GNU Emacs Manual}. -@end ifnothtml -@ifhtml -See the section -@uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Completion.html, -Completion} in @cite{The GNU Emacs Manual}. -@end ifhtml -Note that @key{SPC} cannot be used for completing filenames and -folders. - -@findex help-with-tutorial -@kindex C-h t -@kindex M-x - -The minibuffer is also where you enter Emacs function names after -typing @kbd{M-x}. For example, in the preface, I mentioned that you -could obtain help with @kbd{C-h t} (@code{help-with-tutorial}). What -this means is that you can get a tutorial by typing either @kbd{C-h t} -or @kbd{M-x help-with-tutorial}. In the latter case, you are prompted -for @samp{help-with-tutorial} in the minibuffer after typing -@kbd{M-x}. - -@cindex ~ - -The @samp{~} notation in filenames represents your home directory. -This notation is used by many shells including @command{bash}, -@code{tcsh}, and @command{csh}. It is analogous to the environment -variable @samp{$HOME}. For example, @file{~/.emacs} can be written -@file{$HOME/.emacs} or using the absolute path as in -@file{/home/wohler/.emacs} instead. - -@cindex Emacs, interrupting -@cindex Emacs, quitting -@cindex interrupting -@cindex quitting - -@i{In case of trouble:} Emacs can be interrupted at any time with -@kbd{C-g}. For example, if you've started a command that requests that -you enter something in the minibuffer, but then you change your mind, -type @kbd{C-g} and you'll be back where you started. If you want to -exit Emacs entirely, use @kbd{C-x C-c}. - -@node Getting Started -@chapter Getting Started - -@cindex MH-E, versions -@cindex history -@cindex versions of MH-E - -Because there are many old versions of MH-E out there, it is important -to know which version you have. I'll be talking about @w{Version 8} -which is pretty close to @w{Version 6} and @w{Version 7}. It differs -from @w{Version 4} and @w{Version 5} and is vastly different from -@w{Version 3}. @xref{History}. - -@findex mh-version - -To determine which version of MH-E that you have, enter @kbd{M-x -mh-version @key{RET}}. Hopefully it says that you're running -@w{Version @value{VERSION}} which is the latest version as of this -printing. - -If your version is much older than this, please consider upgrading. -You can have your system administrator upgrade the system-wide -version, or you can install your own personal version. It's really -quite easy. @xref{Getting MH-E}, for instructions for getting and -installing MH-E. - -If the @code{mh-version} command displays @samp{No MH variant -detected}@footnote{In very old versions of MH-E, you may get the error -message, @samp{Cannot find the commands `inc' and `mhl' and the file -`components'} if MH-E can't find MH@. In this case, you need to update -MH-E, and you may need to install MH too. However, newer versions of -MH-E are better at finding MH if it is on your system.}, then you need -to install MH or tell MH-E where to find MH. - -@cindex Debian -@cindex nmh -@cindex GNU mailutils MH - -If you don't have MH on your system already, you must install a -variant of MH@. The Debian mh-e package does this for you -automatically (@pxref{Getting MH-E}). Most people use -@uref{https://www.nongnu.org/nmh/, nmh}, but you may be interested in -trying out @uref{https://mailutils.org/, GNU mailutils MH}, which -supports IMAP@. Your GNU/Linux distribution probably has packages for -both of these. - -@cindex @command{install-mh} -@cindex MH commands, @command{install-mh} -@cindex MH book - -If you've never run MH before, you need to run @command{install-mh} -from the shell before you continue. This sets up your personal MH -environment@footnote{See the section -@uref{@value{MH-BOOK-HOME}/../overall/setup.html, Setting Up MH} in the -MH book.}. If you don't, you'll be greeted with the error message: -@samp{Install MH and run install-mh before running MH-E}. This is all -you need to know about MH to use MH-E, but the more you know about MH, -the more you can leverage its power. See the -@uref{@value{MH-BOOK-HOME}/../, MH book} to learn more about MH. - -@cindex @samp{Path} MH profile component -@cindex MH profile -@cindex MH profile component -@cindex MH profile component, @samp{Path} - -Your MH environment includes your @dfn{MH profile} which is found in -the file @file{~/.mh_profile}, or the file named in the environment -variable @samp{$MH}. This file contains a number of @dfn{MH -profile components}. For example, the @samp{Path:} MH profile -component contains the path to your mail directory, which is -@file{~/Mail} by default. - -@cindex @command{mhparam} -@cindex MH commands, @command{mhparam} -@vindex exec-path -@vindex mh-path -@vindex mh-sys-path -@vindex mh-variant -@vindex mh-variant-in-use - -There are several options MH-E uses to interact with your MH -installation. The option @code{mh-variant} specifies the variant used -by MH-E (@pxref{Options}). The default setting of this option is -@samp{Auto-detect} which means that MH-E will automatically choose the -first of nmh, MH, or GNU mailutils MH that it finds in the directories -listed in @code{mh-path} (which you can customize), -@code{mh-sys-path}, and @code{exec-path}. If MH-E can't find MH at -all, you may have to customize @code{mh-path} and add the directory in -which the command @command{mhparam} is located. If, on the other hand, -you have both nmh and GNU mailutils MH installed (for example) and -@code{mh-variant-in-use} was initialized to nmh but you want to use -GNU mailutils MH, then you can set @code{mh-variant} to -@samp{gnu-mh}. - -@vindex mh-flists-present-flag -@vindex mh-lib -@vindex mh-lib-progs -@vindex mh-progs - -When @code{mh-variant} is changed, MH-E resets @code{mh-progs}, -@code{mh-lib}, @code{mh-lib-progs}, @code{mh-flists-present-flag}, and -@code{mh-variant-in-use} accordingly. - -@cindex @file{.emacs} -@cindex files, @file{.emacs} - -@sp 1 -@center @strong{NOTE} - -@quotation -Prior to version 8, it was often necessary to set some of these -variables in @file{~/.emacs}; now it is no longer necessary and can -actually cause problems. -@end quotation -@sp 1 - -@cindex MH profile component, @samp{Draft-Folder} -@cindex MH profile component, @samp{Path} -@cindex MH profile component, @samp{Previous-Sequence} -@cindex MH profile component, @samp{Unseen-Sequence} -@cindex @samp{Draft-Folder} MH profile component -@cindex @samp{Path} MH profile component -@cindex @samp{Previous-Sequence} MH profile component -@cindex @samp{Unseen-Sequence} MH profile component -@findex mh-find-path -@vindex mh-draft-folder -@vindex mh-find-path-hook -@vindex mh-inbox -@vindex mh-previous-seq -@vindex mh-unseen-seq -@vindex mh-user-path - -In addition to setting variables that point to MH itself, MH-E also -sets a handful of variables that point to where you keep your mail. -During initialization, the function @code{mh-find-path} sets -@code{mh-user-path} from your @samp{Path:} MH profile component (but -defaults to @samp{Mail} if one isn't present), @code{mh-draft-folder} -from @samp{Draft-Folder:}, @code{mh-unseen-seq} from -@samp{Unseen-Sequence:}, @code{mh-previous-seq} from -@samp{Previous-Sequence:}, and @code{mh-inbox} from @samp{Inbox:} -(defaults to @samp{+inbox}). The hook @code{mh-find-path-hook} is run -after these variables have been set. This hook can be used the change -the value of these variables if you need to run with different values -between MH and MH-E. - -@node Tour Through MH-E -@chapter Tour Through MH-E - -@cindex introduction -@cindex tour -@cindex tutorial - -This chapter introduces some of the terms you'll need to know and then -takes you on a tour of MH-E@footnote{The keys mentioned in these -chapters refer to the default key bindings. If you've changed the -bindings, refer to the command summaries at the beginning of each -chapter for a mapping between default key bindings and function -names.}. When you're done, you'll be able to send, read, and file -mail, which is all that a lot of people ever do. But if you're the -curious or adventurous type, read the rest of the manual to be able to -use all the features of MH-E@. I suggest you read this chapter first to -get the big picture, and then you can read the manual as you wish. - -@menu -* Sending Mail Tour:: -* Reading Mail Tour:: -* Processing Mail Tour:: -* Leaving MH-E:: -* More About MH-E:: -@end menu - -@node Sending Mail Tour -@section Sending Mail - -@cindex MH-Letter mode -@cindex mode -@cindex modes, MH-Letter -@cindex sending mail -@findex mh-smail - -Let's start our tour by sending ourselves a message which we can later -read and process. Enter @kbd{M-x mh-smail} to invoke the MH-E program -to send messages. Your message appears in an Emacs buffer whose -mode@footnote{A @dfn{mode} changes Emacs to make it easier to edit a -particular type of text.} is MH-Letter. - -Enter your login name in the @samp{To:} header field. Press the -@key{TAB} twice to move the cursor past the @samp{Cc:} field, since no -carbon copies are to be sent, and on to the @samp{Subject:} field. -Enter @kbd{Test} or anything else that comes to mind. - -Press @key{TAB} again to move the cursor to the body of the message. -Enter some text, using normal Emacs commands. You should now have -something like this@footnote{If you're running Emacs under the X -Window System, then you would also see a menu bar and a tool bar. I've -left out the menu bar and tool bar in all of the example screens.}: - -@cartouche -@smallexample - - - - - - ---:-- *scratch* All L1 (Lisp Interaction)------------------------- -To: wohler -cc: -Subject: Test -X-Mailer: MH-E 8.1; nmh 1.1; GNU Emacs 23.1 --------- -This is a test message to get the wheels churning...# - - ---:** @{draft@} All L5 (MH-Letter)---------------------------------- -Type C-c C-c to send message, C-C ? for help -@end smallexample -@end cartouche -@i{MH-E message composition window} - -Note the line of dashes that separates the header and the body of the -message. It is essential that these dashes (or a blank line) are -present or the body of your message will be considered to be part of -the header. - -@cindex help -@findex describe-mode -@kindex C-c ? -@kindex C-c C-c -@kindex C-h m - -There are several commands specific to MH-Letter mode@footnote{You can -get quick help for the commands used most often with @kbd{C-c ?} or -more complete help with the @kbd{C-h m} (@code{describe-mode}) -command.}, but at this time we'll only use @kbd{C-c C-c} to send your -message. Type @kbd{C-c C-c} now. That's all there is to it! - -@node Reading Mail Tour -@section Receiving Mail - -@cindex @command{inc} -@cindex @command{scan} -@cindex MH commands, @command{inc} -@cindex MH commands, @command{scan} -@cindex MH-Folder mode -@cindex modes, MH-Folder -@cindex reading mail -@findex mh-rmail - -To read the mail you've just sent yourself, enter @kbd{M-x mh-rmail}. -This incorporates the new mail and puts the output from -@command{inc}@footnote{See the section -@uref{@value{MH-BOOK-HOME}/reapre.html, Reading Mail: inc show next -prev} in the MH book.} (called @dfn{scan lines} after the MH program -@command{scan}@footnote{See the section -@uref{@value{MH-BOOK-HOME}/faswsprs.html, Find and Specify with scan -pick Ranges Sequences} in the MH book.} which prints a one-line -summary of each message) into a buffer called @samp{+inbox} whose -major mode is MH-Folder. - -@findex mh-rmail -@kindex F r - -@sp 1 -@center @strong{NOTE} - -@quotation - -The @kbd{M-x mh-rmail} command will show you only new mail, not mail -you have already read. If you were to run this tour again, you would -use @kbd{F r} to pull all your messages into MH-E. -@end quotation -@sp 1 - -@kindex RET -@kindex n -@kindex p - -You should see the scan line for your message, and perhaps others. Use -@kbd{n} or @kbd{p} to move the cursor to your test message and type -@key{RET} to read your message. You should see something like: - -@cartouche -@smallexample - 3 t08/24 root received fax files on Wed Aug 24 11:00:13 -0700 1 -# 4+t08/24 To:wohler Test< - -This is a test message to get the wheels churning... - - - ---:-- @{show-+inbox@} 4 All L1 (MH-Show)---------------------------- - -@end smallexample -@end cartouche -@i{After incorporating new messages} - -@kindex DEL -@kindex SPC - -If you typed a long message, you can view subsequent pages with -@key{SPC} and previous pages with @key{DEL}. - -@node Processing Mail Tour -@section Processing Mail - -@cindex processing mail -@kindex RET -@kindex r - -The first thing we want to do is reply to the message that we sent -ourselves. Ensure that the cursor is still on the same line as your -test message and type @kbd{r}. You are prompted in the minibuffer with -@samp{Reply to whom:}. Here MH-E is asking whether you'd like to reply -to the original sender only, to the sender and primary recipients, or -to the sender and all recipients. You can press @key{TAB} to see these -choices. If you simply press @key{RET}, you'll reply only to the -sender. Press @key{RET} now. - -You'll find yourself in an Emacs buffer similar to that when you were -sending the original message, like this: - -@cartouche -@smallexample -To: -cc: -Subject: Re: Test -In-Reply-To: <31054.1142621351@@stop.mail-abuse.org> -References: <31054.1142621351@@stop.mail-abuse.org> -Comments: In-Reply-To Bill Wohler - message dated "Fri, 17 Mar 2006 10:49:11 -0800." -X-Mailer: MH-E 8.1; nmh 1.1; GNU Emacs 23.1 --------- -# - ---:-- @{draft@} All L10 (MH-Letter)---------------------------------- -To: wohler -Subject: Test -X-Mailer: MH-E 8.1; nmh 1.1; GNU Emacs 23.1 -Date: Fri, 17 Mar 2006 10:49:11 -0800 -From: Bill Wohler - -This is a test message to get the wheels churning... - ---:-- @{show-+inbox@} 4 All L1 (MH-Show)---------------------------- -Type C-c C-c to send message, C-c ? for help -@end smallexample -@end cartouche -@i{Composition window during reply} - -@findex backward-char -@findex forward-char -@findex next-line -@findex previous-line -@kindex C-b -@kindex C-c C-c -@kindex C-c C-f C-t -@kindex C-f -@kindex C-n -@kindex C-p -@kindex BS - -By default, MH will not add you to the address list of your replies, -so if you find that the @samp{To:} header field is missing, don't -worry. In this case, type @kbd{C-c C-f C-t} to create and go to the -@samp{To:} field, where you can type your login name again. You can -move around with the arrow keys or with @kbd{C-p} -(@code{previous-line}), @kbd{C-n} (@code{next-line}), @kbd{C-b} -(@code{backward-char}), and @kbd{C-f} (@code{forward-char}) and can -delete the previous character with @key{BS}. When you're finished -editing your message, send it with @kbd{C-c C-c} as before. - -@cindex @command{refile} -@cindex MH commands, @command{refile} -@cindex folders -@kindex SPC -@kindex o - -You'll often want to save messages that were sent to you in an -organized fashion. This is done with @dfn{folders}. You can use -folders to keep messages from your friends, or messages related to a -particular topic. With your cursor in the MH-Folder buffer and -positioned on the message you sent to yourself, type @kbd{o} to output -(@command{refile} in MH parlance) that message to a folder. Enter -@kbd{test} at the @samp{Destination folder:} prompt and type @kbd{y} -(or @key{SPC}) when MH-E asks to create the folder @samp{+test}. Note -that a @samp{^} (caret) appears next to the message number, which -means that the message has been marked for refiling but has not yet -been refiled. We'll talk about how the refile is actually carried out -in a moment. - -@cindex MH-Folder mode -@cindex modes, MH-Folder -@kindex d -@kindex i -@kindex RET -@kindex n -@kindex p -@kindex x - -Your previous reply is now waiting in the system mailbox. You -incorporate this mail into your MH-Folder buffer named @samp{+inbox} -with the @kbd{i} command. Do this now. After the mail is incorporated, -use @kbd{n} or @kbd{p} to move the cursor to the new message, and read -it with @key{RET}. Let's delete this message by typing @kbd{d}. Note -that a @samp{D} appears next to the message number. This means that -the message is marked for deletion but is not yet deleted. To perform -the deletion (and the refile we did previously), use the @kbd{x} -command. - -@findex mh-smail -@kindex m - -If you want to send another message you can use @kbd{m} instead of -@kbd{M-x mh-smail}. So go ahead, send some mail to your friends! - -@cindex help -@cindex prefix characters -@findex describe-mode -@kindex ? -@kindex C-h m -@kindex F ? - -You can get a quick reminder about these commands by typing @kbd{?}. -This lists several @dfn{prefix characters}. To list the commands -available via the prefix characters, type the prefix character -followed by a @kbd{?}, for example, @kbd{F ?}. More complete help is -available with the @kbd{C-h m} (@code{describe-mode}) command. - -@node Leaving MH-E -@section Leaving MH-E - -@cindex Emacs, quitting -@cindex quitting -@kindex C-x C-c -@kindex x - -You may now wish to exit @command{emacs} entirely. Use @kbd{C-x C-c} -to exit @command{emacs}. If you exited without running @kbd{x} in the -@samp{+inbox} buffer, Emacs will offer to save it for you. Type -@kbd{y} or @key{SPC} to save @samp{+inbox} changes, which means to -perform any refiles and deletes that you did there. - -@findex mh-rmail -@kindex C-x b -@kindex C-x k -@kindex q - -If you don't want to leave Emacs, you can type @kbd{q} to bury (hide) -the MH-E folder or delete it entirely with @kbd{C-x k}. You can then -later recall it with @kbd{C-x b} or @kbd{M-x mh-rmail}. - -@cindex @command{packf} -@cindex MH commands, @command{packf} -@cindex exporting folders -@cindex folders, exporting -@cindex mbox-style folder - -On the other hand, if you no longer want to use MH and MH-E, you can -take your mail with you. You can copy all of your mail into a single -file, mbox-style, by using the MH command @command{packf}. For -example, to create a file called @file{msgbox} with the messages in -your @samp{+inbox} folder, use @samp{packf +inbox}. The -@command{packf} command will append the messages to the file if it -already exists, so you can use @samp{folders -recurse -fast} in a -script to copy all of your messages into a single file, or using the -@samp{-file} argument, a file for each folder. - -@node More About MH-E -@section More About MH-E - -These are the basic commands to get you going, but there are plenty -more. If you think that MH-E is for you, read the rest of the manual -to find out how you can: - -@itemize @bullet -@item -Print your messages (@pxref{Printing}). -@c ------------------------- -@item -Edit messages and include your signature (@pxref{Editing Drafts}). -@c ------------------------- -@item -Forward messages (@pxref{Forwarding}). -@c ------------------------- -@item -Read digests (@pxref{Digests}). -@c ------------------------- -@item -Edit bounced messages (@pxref{Editing Again}). -@c ------------------------- -@item -Send multimedia messages (@pxref{Adding Attachments}). -@c ------------------------- -@item -Read HTML messages (@pxref{HTML}). -@c ------------------------- -@item -Use aliases and identities (@pxref{Aliases}, @pxref{Identities}). -@c ------------------------- -@item -Create different views of your mail (@pxref{Threading}, @pxref{Limits}). -@c ------------------------- -@item -Deal with junk mail (@pxref{Junk}). -@c ------------------------- -@item -Handle signed and encrypted messages (@pxref{Reading PGP}, -@pxref{Sending PGP}). -@c ------------------------- -@item -Process mail that was sent with @command{shar} or @command{uuencode} -(@pxref{Files and Pipes}). -@c ------------------------- -@item -Use sequences conveniently (@pxref{Sequences}). -@c ------------------------- -@item -Use the speedbar, tool bar, and menu bar (@pxref{Speedbar}, @pxref{Tool -Bar}, @pxref{Menu Bar}). -@c ------------------------- -@item -Show header fields in different fonts (@pxref{Reading Mail}). -@c ------------------------- -@item -Find previously refiled messages (@pxref{Searching}). -@c ------------------------- -@item -Place messages in a file (@pxref{Files and Pipes}). -@end itemize - -Remember that you can also use MH commands when you're not running -MH-E (and when you are!). - -@node Using This Manual -@chapter Using This Manual - -This chapter begins the meat of the manual which goes into more detail -about every MH-E command and option. - -@cindex Emacs, info -@cindex Emacs, built-in help -@cindex info -@cindex built-in help -@findex describe-mode -@findex mh-help -@kindex ? -@kindex C-c ? -@kindex C-h C-h -@kindex C-h C-k i -@kindex C-h i -@kindex C-h m - -There are many commands, but don't get intimidated. There are command -summaries at the beginning of each chapter. In case you have or would -like to rebind the keys, the command summaries also list the -associated Emacs Lisp function. Furthermore, even if you're stranded -on a desert island with a laptop and are without your manuals, you can -get a summary of all these commands with GNU Emacs built-in help: use -@kbd{C-h m} (@code{describe-mode}) for a brief summary of commands, -@kbd{?} (@code{mh-help}) for an even briefer summary@footnote{This -help appears in a buffer called @file{*MH-E Help*} -(@pxref{Miscellaneous}).} (@kbd{C-c ?} in MH-Letter mode), or @kbd{C-h -i} to read this manual via Info. The built-in help is quite good; try -running @kbd{C-h C-h}. This brings up a list of available help topics, -one of which displays the documentation for a given key (like @kbd{C-h -k C-n}). Another useful help feature is to view the manual section -that describes a given key (such as @kbd{C-h K i}). In addition, -review @ref{Conventions}, if any of the GNU Emacs conventions are -strange to you. - -In addition to all of the commands, it is also possible to reconfigure -MH-E to fit the needs of even the most demanding user. The following -chapters also describe all of the options, show the defaults, and make -recommendations for customization. - -However, when customizing your mail environment, first try to change -what you want in MH, and only change MH-E if changing MH is not -possible. That way you will get the same behavior inside and outside -GNU Emacs. Note that MH-E does not provide hooks for customizations -that can be done in MH; this omission is intentional. - -@cindex Emacs Lisp Manual -@cindex Emacs, Emacs Lisp Manual -@cindex Emacs, info -@cindex Emacs, online help -@cindex info -@cindex online help - -I hope I've included enough examples here to get you well on your way. -If you want to explore Emacs Lisp further, a programming manual does -exist, -@c Yes, some of the stuff in the following sections is redundant, but -@c TeX barfs if the @ifs are inside the @footnote. -@iftex -@footnote{The @cite{GNU Emacs Lisp Reference Manual} should be available -via the Info system by typing @kbd{C-h i m Emacs Lisp -@key{RET}}. It is also available online at @* -@uref{https://www.gnu.org/software/emacs/manual/elisp.html}.} -@end iftex -@ifinfo -@footnote{@xref{Top, The GNU Emacs Lisp Reference Manual, , elisp, GNU -Emacs Lisp Reference Manual}, which should be available via the -Info system. It is also available online at -@uref{https://www.gnu.org/software/emacs/manual/elisp.html}.} -@end ifinfo -@ifhtml -@footnote{The -@uref{https://www.gnu.org/software/emacs/manual/elisp.html, -The GNU Emacs Lisp Reference Manual} should be available via -the Info system by typing @kbd{C-h i m Emacs Lisp @key{RET}}.} -@end ifhtml -and you can look at the code itself for examples. Look in the Emacs -Lisp directory on your system (such as -@file{/usr/local/share/emacs/lisp/mh-e}) and find all the @file{mh-*.el} -files there. When calling MH-E and other Emacs Lisp functions directly -from Emacs Lisp code, you'll need to know the correct arguments. Use -the built-in help for this. For example, try @kbd{C-h f -mh-execute-commands @key{RET}}. If you write your own functions, -please do not prefix your symbols (variables and functions) with -@samp{mh-}. This prefix is reserved for the MH-E package. To avoid -conflicts with existing MH-E symbols, use a prefix like @samp{my-} or -your initials. (Unless, of course, your initials happen to be @emph{mh}!) - -@menu -* Options:: -* Ranges:: -* Folder Selection:: -@end menu - -@node Options -@section Options - -@cindex Emacs, customizing -@cindex Emacs, setting options -@cindex customizing MH-E -@cindex setting options -@findex customize-option -@vindex mh-lpr-command-format@r{, example} - -Many string or integer options are easy to modify using @kbd{M-x -customize-option}. For example, to modify the option that controls -printing, you would run @kbd{M-x customize-option @key{RET} -mh-lpr-command-format @key{RET}}. In the buffer that appears, modify -the string to the right of the variable. For example, you may change -the @command{lpr} command with @samp{nenscript -G -r -2 -i'%s'}. Then -use the @samp{State} combo box and select @samp{Save for Future -Sessions}. To read more about @code{mh-lpr-command-format}, see -@ref{Printing}. - -@cindex nil -@cindex off, option -@cindex on, option -@cindex option, turning on and off -@cindex t -@findex customize-option -@vindex mh-bury-show-buffer-flag@r{, example} - -Options can also hold boolean values. In Emacs Lisp, the boolean -values are @code{nil}, which means false, and @code{t}, which means -true. The @code{customize-option} function makes it easy to change -boolean values; simply click on the toggle button in the customize -buffer to switch between @samp{on} (@code{t}) and @samp{off} -(@code{nil}). For example, try setting @code{mh-bury-show-buffer-flag} -to @samp{off} to keep the MH-Show buffer at the top of the buffer -stack. Use the @samp{State} combo box and choose @samp{Set for Current -Session} to see how the option affects the show buffer. Then choose -the @samp{Erase Customization} menu item to reset the option to the -default, which places the MH-Show buffer at the bottom of the buffer -stack. - -@vindex mh-mhl-format-file@r{, example} - -The text usually says to turn on an option by setting it to a -@emph{non-@code{nil}} value, because sometimes values other than -@samp{on} are meaningful. An example of this is the variable -@code{mh-mhl-format-file} (@pxref{Viewing}). Other options, such as -hooks, involve a little more Emacs Lisp programming expertise. - -@cindex customization group, @samp{mh} -@cindex @samp{mh} customization group -@findex customize-group -@findex mh-customize - -You can browse all of the MH-E options with the @code{customize-group} -function. Try entering @kbd{M-x customize-group @key{RET} mh -@key{RET}} to view the top-level options as well as buttons for all of -the MH-E customization groups. Another way to view the MH-E -customization group is to use @kbd{M-x mh-customize @key{RET}}. - -@node Ranges -@section Ranges - -@c Sync with mh-folder-mode docstring. - -@cindex message abbreviations -@cindex message ranges -@cindex ranges - -Many commands that operate on individual messages, such as -@code{mh-forward} or @code{mh-refile-msg} take a @code{RANGE} -argument. This argument can be used in several ways. - -@kindex C-u@r{, with ranges} - -If you provide the prefix argument @kbd{C-u} to these commands, then -you will be prompted for the message range. This can be any valid MH -range which can include messages, sequences (@pxref{Sequences}), and -the abbreviations (described in the @command{mh}(1) man page): - -@table @samp -@item - -Indicates all messages in the range to , inclusive. The -range must be nonempty. -@c ------------------------- -@item :N -@itemx :+N -@itemx :-N -Up to N messages beginning with (or ending with) message num. Num may -be any of the predefined symbols: first, prev, cur, next or last. -@c ------------------------- -@item first:N -@itemx prev:N -@itemx next:N -@itemx last:N -The first, previous, next or last messages, if they exist. -@c ------------------------- -@item all -All of the messages. -@end table - -For example, a range that shows all of these things is @samp{1 2 3 -5-10 last:5 unseen}. - -@vindex transient-mark-mode - -If the option @code{transient-mark-mode} is turned on and you set a -region in the MH-Folder buffer, then the MH-E command will perform the -operation on all messages in that region. - -@cindex @samp{mh-range} customization group -@cindex customization group, @samp{mh-range} - -The @samp{mh-range} customization group contains a single option which -affects how ranges are interpreted. - -@vtable @code -@item mh-interpret-number-as-range-flag -On means interpret a number as a range (default: @samp{on}). -@end vtable - -@vindex mh-interpret-number-as-range-flag - -Since one of the most frequent ranges used is @samp{last:N}, MH-E will -interpret input such as @samp{200} as @samp{last:200} if the -@code{mh-interpret-number-as-range-flag} option is on (which is the -default). If you need to scan just the message 200, then use the range -@samp{200:1} or @samp{200-200}. - -@node Folder Selection -@section Folder Selection - -@cindex completion, folders -@cindex folders, completion -@cindex folders, selecting - -When you choose a folder in MH-E via a command such as @kbd{o} -(@code{mh-refile-msg}), completion is used to enter the folder -@ifnothtml -(@pxref{Completion, , , emacs, The GNU Emacs Manual}). -@end ifnothtml -@ifhtml -(see the section -@uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Completion.html, -Completion} in @cite{The GNU Emacs Manual}). -@end ifhtml -In addition, MH-E has several ways of choosing a suitable default so -that the folder can often be selected with a single @key{RET} key. - -@cindex customization group, @samp{mh-folder-selection} -@cindex @samp{mh-folder-selection} customization group - -The @samp{mh-folder-selection} customization group contains some -options which are used to help with this. - -@vtable @code -@item mh-default-folder-for-message-function -Function to select a default folder for refiling or @samp{Fcc:} -(default: @code{nil}). -@c ------------------------- -@item mh-default-folder-list -List of addresses and folders (default: @code{nil}). -@c ------------------------- -@item mh-default-folder-must-exist-flag -On means guessed folder name must exist to be used (default: -@samp{on}). -@c ------------------------- -@item mh-default-folder-prefix -Prefix used for folder names generated from aliases (default: @code{""}). -@end vtable - -@vindex mh-default-folder-for-message-function - -You can set the option @code{mh-default-folder-for-message-function} -to a function that provides a default folder for the message to be -refiled. When this function is called, the current buffer contains the -message being refiled and point is at the start of the message. This -function should return the default folder as a string with a leading -@samp{+} sign. It can also return @code{nil} so that the last folder -name is used as the default, or an empty string to suppress the -default entirely. - -Otherwise, the name of the destination folder is derived from the -sender as follows: - -@enumerate -@vindex mh-default-folder-list -@item -The folder name associated with the first address found in the list -@code{mh-default-folder-list} is used. Each element in this list -contains a @samp{Check Recipient} item. If this item is turned on, -then the address is checked against the recipient instead of the -sender. This is useful for mailing lists. -@c ------------------------- -@vindex mh-default-folder-prefix -@item -An alias prefixed by @code{mh-default-folder-prefix} corresponding to -the address is used. The prefix is used to prevent clutter in your -mail directory. @xref{Aliases}. -@end enumerate - -@vindex mh-default-folder-must-exist-flag - -If the derived folder does not exist, and -@code{mh-default-folder-must-exist-flag} is @code{t}, then the last -folder name used is suggested. This is useful if you get mail from -various people for whom you have an alias, but file them all in the -same project folder. - -@node Incorporating Mail -@chapter Incorporating Your Mail - -@cindex @samp{Folder} menu -@cindex incorporating -@cindex menu, @samp{Folder} - -This chapter talks about getting mail from your system mailbox into -your MH @samp{+inbox} folder. The following command accomplishes that -and is found in the @samp{Folder} menu. - -@table @kbd -@cindex @samp{Folder > Incorporate New Mail} menu item -@cindex menu item, @samp{Folder > Incorporate New Mail} -@findex mh-inc-folder -@kindex i -@item i -Incorporate new mail into a folder (@code{mh-inc-folder}). -@end table - -@cindex @samp{mh-inc} customization group -@cindex customization group, @samp{mh-inc} - -The following options in the @samp{mh-inc} customization group are -used. - -@vtable @code -@item mh-inc-prog -Program to incorporate mail (default: @code{"inc"}). -@c ------------------------- -@item mh-inc-spool-list -Alternate spool files (default: @code{nil}). -@end vtable - -The following hook is available. - -@vtable @code -@findex mh-inc-folder -@item mh-inc-folder-hook -Hook run by @code{mh-inc-folder} after incorporating mail into a -folder (default: @code{nil}). -@end vtable - -@cindex @samp{+inbox} -@findex mh-inc-folder -@kindex i - -If at any time you receive new mail, incorporate the new mail into -your @samp{+inbox} buffer with @kbd{i} (@code{mh-inc-folder}). Note -that @kbd{i} will display the @samp{+inbox} buffer, even if there -isn't any new mail. You can incorporate mail from any file into the -current folder by specifying a prefix argument; you'll be prompted for -the name of the file to use as well as the destination folder (for -example, @kbd{C-u i ~/mbox @key{RET} +tmp @key{RET}}). - -@cindex @file{.emacs} -@cindex Emacs, notification of new mail -@cindex files, @file{.emacs} -@cindex new mail -@cindex notification of new mail - -Emacs can notify you when you have new mail by displaying @samp{Mail} -in the mode line. To enable this behavior, and to have a clock in the -mode line as well, add the following to @file{~/.emacs}: - -@findex display-time - -@smalllisp -(display-time) -@end smalllisp - -@cindex @command{inc} -@cindex incorporating -@cindex MH commands, @command{inc} -@vindex mh-inc-prog -@vindex mh-progs - -The name of the program that incorporates new mail is stored in -@code{mh-inc-prog}; it is @code{"inc"} by default. This program -generates a one-line summary for each of the new messages. Unless it -is an absolute pathname, the file is assumed to be in the -@code{mh-progs} directory (@pxref{Getting Started}). You may also link -a file to @command{inc} that uses a different format (see -@samp{mh-profile}(5), and sections -@uref{@value{MH-BOOK-HOME}/reapre.html, Reading Mail: inc show next -prev} and @uref{@value{MH-BOOK-HOME}/mhstr.html, MH Format Strings} in -the MH book). You'll then need to modify several variables -appropriately (@pxref{Scan Line Formats}). - -@vindex mh-inc-spool-list - -You can use the @code{mh-inc-spool-list} variable to direct MH-E to -retrieve mail from arbitrary spool files other than your system -mailbox, file it in folders other than your @samp{+inbox}, and assign -key bindings to incorporate this mail. - -@cindex @command{procmail} -@cindex @file{.procmailrc} -@cindex Unix commands, @command{procmail} -@cindex files, @file{.procmailrc} - -Suppose you are subscribed to the @i{mh-e-devel} mailing list and you -use @command{procmail} to filter this mail into @file{~/mail/mh-e} -with the following recipe in @file{.procmailrc}: - -@smallexample -PATH=$PATH:/usr/bin/mh -MAILDIR=$HOME/`mhparam Path` -:0: -* ^From mh-e-devel-admin@@stop.mail-abuse.org -mh-e -@end smallexample - -@findex mh-inc-spool-* -@kindex I * - -In order to incorporate @file{~/mail/mh-e} into @samp{+mh-e} with an -@kbd{I m} (@code{mh-inc-spool-mh-e}) command, customize this option, -and click on the @samp{INS} button. Enter a @samp{Spool File} of -@samp{~/mail/mh-e}, a @samp{Folder} of @samp{mh-e}, and a @samp{Key -Binding} of @samp{m}. - -@cindex @command{emacsclient} -@cindex @command{xbuffy} -@cindex Unix commands, @command{emacsclient} -@cindex Unix commands, @command{xbuffy} - -You can use @command{xbuffy} to automate the incorporation of this -mail using the Emacs command @command{emacsclient} as follows: - -@smallexample -box ~/mail/mh-e - title mh-e - origMode - polltime 10 - headertime 0 - command emacsclient --eval '(mh-inc-spool-mh-e)' -@end smallexample - -@findex mh-inc-folder -@kindex i -@vindex mh-inc-folder-hook - -You can set the hook @code{mh-inc-folder-hook}, which is called after -new mail is incorporated by the @kbd{i} (@code{mh-inc-folder}) -command. A good use of this hook is to rescan the whole folder either -after running @kbd{M-x mh-rmail} the first time or when you've changed -the message numbers from outside of MH-E. - -@findex mh-execute-commands -@findex mh-rescan-folder@r{, example} -@findex mh-show@r{, example} -@vindex mh-inc-folder-hook@r{, example} - -@smalllisp -@group -(defun my-mh-inc-folder-hook () - "Hook to rescan folder after incorporating mail." - (if (buffer-modified-p) ; @r{if outstanding refiles and deletes,} - (mh-execute-commands)) ; @r{carry them out} - (mh-rescan-folder) ; @r{synchronize with +inbox} - (mh-show)) ; @r{show the current message} - -(add-hook 'mh-inc-folder-hook 'my-mh-inc-folder-hook) - -@i{Rescan folder after incorporating new mail via mh-inc-folder-hook} - -@end group -@end smalllisp - -@node Reading Mail -@chapter Reading Your Mail - -@cindex @samp{+inbox} -@cindex MH-Folder mode -@cindex MH-Show mode -@cindex modes, MH-Folder -@cindex modes, MH-Show -@cindex reading mail -@findex mh-rmail -@kindex F r -@kindex F v - -The MH-E entry point for reading mail is @kbd{M-x mh-rmail}. This -command incorporates your mail and creates a buffer called -@samp{+inbox} in MH-Folder mode. The command @kbd{M-x mh-rmail} shows -you only new mail, not mail you have already read@footnote{If you want -to see your old mail as well, use @kbd{F r} to pull all your messages -into MH-E@. Or, give a prefix argument to @code{mh-rmail} so it will -prompt you for folder to visit like @kbd{F v} (for example, @kbd{C-u -M-x mh-rmail @key{RET} bob @key{RET}}). @xref{Folders}.}. - -@findex display-time -@vindex read-mail-command - -There are some commands that need to read mail, such as @kbd{mouse-2} -over the @samp{Mail} button that @code{display-time} adds to the mode -line. You can configure Emacs to have these commands use MH-E by -setting the option @code{read-mail-command} to @samp{mh-rmail}. - -@cindex @command{scan} -@cindex @samp{Message} menu -@cindex MH commands, @command{scan} -@cindex menu, @samp{Message} -@cindex scan lines - -The @samp{+inbox} buffer contains @dfn{scan lines}, which are one-line -summaries of each incorporated message. You can perform most MH -commands on these messages via one- or two-letter commands in either -the MH-Folder or MH-Show buffers or by using the @samp{Message} menu. -See @command{scan}(1) for a description of the contents of the scan -lines, and see the Figure in @ref{Reading Mail Tour}, for an example. - -@table @kbd -@kindex ? -@findex mh-help -@item ? -Display cheat sheet for the MH-E commands (@code{mh-help}). -@c ------------------------- -@cindex @samp{Message > Show Message} menu item -@cindex menu item, @samp{Message > Show Message} -@kindex RET -@findex mh-show -@item @key{RET} -Display message (@code{mh-show}). -@c ------------------------- -@cindex @samp{Message > Show Message with Header} menu item -@cindex menu item, @samp{Message > Show Message with Header} -@kindex , @r{(comma)} -@findex mh-header-display -@item , (comma) -Display message with all header fields (@code{mh-header-display}). -@c ------------------------- -@cindex @samp{Message > Show Message with Preferred Alternative} menu item -@cindex menu item, @samp{Message > Show Message with Preferred Alternative} -@kindex : @r{(colon)} -@findex mh-show-preferred-alternative -@item : (colon) -Display message with the default preferred alternative -(@code{mh-show-preferred-alternative}). -@c ------------------------- -@kindex ; @r{(semicolon)} -@findex mh-toggle-mh-decode-mime-flag -@item ; (semicolon) -Toggle the value of @code{mh-decode-mime-flag} -(@code{mh-toggle-mh-decode-mime-flag}). -@c ------------------------- -@kindex SPC -@findex mh-page-msg -@item @key{SPC} -Display next page in message (@code{mh-page-msg}). -@c ------------------------- -@kindex BS -@findex mh-previous-page -@item @key{BS} -Display previous page in message (@code{mh-previous-page}). -@c ------------------------- -@cindex @samp{Message > Write Message to File...} menu item -@cindex menu item, @samp{Message > Write Message to File...} -@kindex > -@findex mh-write-msg-to-file -@item > -Append message to end of file (@code{mh-write-msg-to-file}). -@c ------------------------- -@cindex @samp{Message > Pipe Message to Command...} menu item -@cindex menu item, @samp{Message > Pipe Message to Command...} -@kindex | -@findex mh-pipe-msg -@item | -Pipe message through shell command (@code{mh-pipe-msg}). -@c ------------------------- -@kindex C-d -@findex mh-delete-msg-no-motion -@item C-d -Delete range, don't move to next message -(@code{mh-delete-msg-no-motion}). -@c ------------------------- -@cindex @samp{Message > Delete Message} menu item -@cindex menu item, @samp{Message > Delete Message} -@kindex d -@findex mh-delete-msg -@item d -Delete range (@code{mh-delete-msg}). -@c ------------------------- -@kindex D ? -@findex mh-prefix-help -@item D ? -Display cheat sheet for the commands of the current prefix in -minibuffer (@code{mh-prefix-help}). -@c ------------------------- -@kindex D SPC -@findex mh-page-digest -@item D @key{SPC} -Display next message in digest (@code{mh-page-digest}). -@c ------------------------- -@kindex D BS -@findex mh-page-digest-backwards -@item D @key{BS} -Display previous message in digest (@code{mh-page-digest-backwards}). -@c ------------------------- -@cindex @samp{Message > Burst Digest Message} menu item -@cindex menu item, @samp{Message > Burst Digest Message} -@kindex D b -@findex mh-burst-digest -@item D b -Break up digest into separate messages (@code{mh-burst-digest}). -@c ------------------------- -@cindex @samp{Message > Go to Message by Number...} menu item -@cindex menu item, @samp{Message > Go to Message by Number...} -@kindex g -@findex mh-goto-msg -@item g -Go to a message (@code{mh-goto-msg}). -@c ------------------------- -@kindex k -@findex mh-delete-subject-or-thread -@item k -Delete messages with same subject or thread -(@code{mh-delete-subject-or-thread}). -@c ------------------------- -@kindex K ? -@findex mh-prefix-help -@item K ? -Display cheat sheet for the commands of the current prefix in -minibuffer (@code{mh-prefix-help}). -@c ------------------------- -@kindex K TAB -@findex mh-next-button -@item K @key{TAB} -Go to the next button (@code{mh-next-button}). -@c ------------------------- -@kindex K S-TAB -@findex mh-prev-button -@item K S-@key{TAB} -Go to the previous button (@code{mh-prev-button}). -@c ------------------------- -@kindex K a -@findex mh-mime-save-parts -@item K a -Save attachments (@code{mh-mime-save-parts}). -@c ------------------------- -@kindex K e -@findex mh-display-with-external-viewer -@item K e -View attachment externally (@code{mh-display-with-external-viewer}). -@c ------------------------- -@kindex K i -@findex mh-folder-inline-mime-part -@item K i -Show attachment verbatim (@code{mh-folder-inline-mime-part}). -@c ------------------------- -@kindex K o -@findex mh-folder-save-mime-part -@item K o -Save (output) attachment (@code{mh-folder-save-mime-part}). -@c ------------------------- -@kindex K t -@findex mh-toggle-mime-buttons -@item K t -Toggle option @code{mh-display-buttons-for-inline-parts-flag} -(@code{mh-toggle-mime-buttons}). -@c ------------------------- -@kindex K v -@findex mh-folder-toggle-mime-part -@item K v -View attachment (@code{mh-folder-toggle-mime-part}). -@c ------------------------- -@cindex @samp{Message > Modify Message} menu item -@cindex menu item, @samp{Message > Modify Message} -@kindex M -@findex mh-modify -@item M -Edit message (@code{mh-modify}). -@c ------------------------- -@cindex @samp{Message > Go to First Message} menu item -@cindex menu item, @samp{Message > Go to First Message} -@kindex M-< -@findex mh-first-msg -@item M-< -Display first message (@code{mh-first-msg}). -@c ------------------------- -@cindex @samp{Message > Go to Last Message} menu item -@cindex menu item, @samp{Message > Go to Last Message} -@kindex M-> -@findex mh-last-msg -@item M-> -Display last message (@code{mh-last-msg}). -@c ------------------------- -@kindex M-n -@findex mh-next-unread-msg -@item M-n -Display next unread message (@code{mh-next-unread-msg}). -@c ------------------------- -@kindex M-p -@findex mh-previous-unread-msg -@item M-p -Display previous unread message (@code{mh-previous-unread-msg}). -@c ------------------------- -@cindex @samp{Message > Next Message} menu item -@cindex menu item, @samp{Message > Next Message} -@kindex n -@findex mh-next-undeleted-msg -@item n -Display next message (@code{mh-next-undeleted-msg}). -@c ------------------------- -@cindex @samp{Message > Previous Message} menu item -@cindex menu item, @samp{Message > Previous Message} -@kindex p -@findex mh-previous-undeleted-msg -@item p -Display previous message (@code{mh-previous-undeleted-msg}). -@c ------------------------- -@kindex P ? -@findex mh-prefix-help -@item P ? -Display cheat sheet for the commands of the current prefix in -minibuffer (@code{mh-prefix-help}). -@c ------------------------- -@kindex P C -@findex mh-ps-print-toggle-color -@item P C -Toggle whether color is used in printing messages -(@code{mh-ps-print-toggle-color}). -@c ------------------------- -@kindex P F -@findex mh-ps-print-toggle-faces -@item P F -Toggle whether printing is done with faces or not -(@code{mh-ps-print-toggle-faces}). -@c ------------------------- -@kindex P f -@findex mh-ps-print-msg-file -@item P f -Print range to file (@code{mh-ps-print-msg-file}). -@c ------------------------- -@cindex @samp{Message > Print Message} menu item -@cindex menu item, @samp{Message > Print Message} -@kindex P l -@findex mh-print-msg -@item P l -Print range the old fashioned way -(@code{mh-print-msg}). -@c ------------------------- -@kindex P p -@findex mh-ps-print-msg -@item P p -Print range (@code{mh-ps-print-msg}). -@c ------------------------- -@kindex X ? -@findex mh-prefix-help -@item X ? -Display cheat sheet for the commands of the current prefix in -minibuffer (@code{mh-prefix-help}). -@c ------------------------- -@cindex @samp{Message > Unpack Uuencoded Message...} menu item -@cindex menu item, @samp{Message > Unpack Uuencoded Message...} -@kindex X s -@kindex X u -@findex mh-store-msg -@item X s -@itemx X u -Unpack message created with @command{uudecode} or @command{shar} -(@code{mh-store-msg}). -@c ------------------------- -@kindex mouse-2 -@findex mh-show-mouse -@item mouse-2 -Move point to mouse event and show message (@code{mh-show-mouse}). -@end table - -Within the MH-Show buffer, the following command is defined. - -@table @kbd -@kindex RET -@kindex mouse-1 -@kindex mouse-2 -@findex mh-press-button -@item @key{RET} -@itemx mouse-1 -@itemx mouse-2 -View contents of button (@code{mh-press-button}). -@end table - -@cindex @samp{mh-show} customization group -@cindex customization group, @samp{mh-show} - -The following table lists options in the @samp{mh-show} customization -group that are used while reading mail. - -@vtable @code -@item mh-bury-show-buffer-flag -On means show buffer is buried (default: @samp{on}). -@c ------------------------- -@item mh-clean-message-header-flag -On means remove extraneous header fields (default: @samp{on}). -@c ------------------------- -@item mh-decode-mime-flag -On means attachments are handled (default: @samp{on} if the Gnus -@samp{mm-decode} package is present). -@c ------------------------- -@item mh-display-buttons-for-alternatives-flag -On means display buttons for all alternative attachments (default: -@samp{off}). -@c ------------------------- -@item mh-display-buttons-for-inline-parts-flag -On means display buttons for all inline attachments (default: -@samp{off}). -@c ------------------------- -@item mh-do-not-confirm-flag -On means non-reversible commands do not prompt for confirmation -(default: @samp{off}). -@c ------------------------- -@item mh-fetch-x-image-url -Control fetching of @samp{X-Image-URL:} header field image (default: -@samp{Never Fetch}). -@c ------------------------- -@item mh-graphical-smileys-flag -On means graphical smileys are displayed (default: @samp{on}). -@c ------------------------- -@item mh-graphical-emphasis-flag -On means graphical emphasis is displayed (default: @samp{on}). -@c ------------------------- -@item mh-highlight-citation-style -Style for highlighting citations (default: @samp{Multicolor}). -@c ------------------------- -@item mh-invisible-header-fields-default -List of hidden header fields (default: a checklist too long to list -here). -@c ------------------------- -@item mh-invisible-header-fields -Additional header fields to hide (default: @code{nil}). -@c ------------------------- -@item mh-lpr-command-format -Command used to print (default: @code{"lpr -J '%s'"}). -@c ------------------------- -@item mh-max-inline-image-height -Maximum inline image height if @samp{Content-Disposition:} is not -present (default: 0). -@c ------------------------- -@item mh-max-inline-image-width -Maximum inline image width if @samp{Content-Disposition:} is not -present(default: 0). -@c ------------------------- -@item mh-mhl-format-file -Specifies the format file to pass to the @command{mhl} program -(default: @samp{Use Default mhl Format (Printing Only)}). -@c ------------------------- -@item mh-mime-save-parts-default-directory -Default directory to use for @kbd{K a}. -@c ------------------------- -@item mh-print-background-flag -On means messages should be printed in the background (default: -@samp{off}). -@c ------------------------- -@item mh-show-buffer-mode-line-buffer-id -Format string to produce @code{mode-line-buffer-identification} for -show buffers (default: @code{" @{show-%s@} %d"}). -@c ------------------------- -@item mh-show-maximum-size -Maximum size of message (in bytes) to display automatically (default: -0). -@c ------------------------- -@item mh-show-use-xface-flag -On means display face images in MH-Show buffers (default: @samp{on}). -@c ------------------------- -@item mh-store-default-directory -Default directory for @kbd{X s} (default: @samp{Current}). -@c ------------------------- -@item mh-summary-height -Number of lines in MH-Folder buffer (including the mode line) -(default: depends on size of frame). -@end vtable - -The following hooks are available. - -@vtable @code -@item mh-delete-msg-hook -Hook run after marking each message for deletion (default: @code{nil}). -@c ------------------------- -@item mh-show-hook -Hook run after @key{RET} shows a message (default: @code{nil}). -@c ------------------------- -@item mh-show-mode-hook -Hook run upon entry to @code{mh-show-mode} (default: @code{nil}). -@end vtable - -The following faces are available. - -@vtable @code -@item mh-show-cc -Face used to highlight @samp{cc:} header fields. -@c ------------------------- -@item mh-show-date -Face used to highlight @samp{Date:} header fields. -@c ------------------------- -@item mh-show-from -Face used to highlight @samp{From:} header fields. -@c ------------------------- -@item mh-show-header -Face used to deemphasize less interesting header fields. -@c ------------------------- -@item mh-show-pgg-bad -Bad PGG signature face. -@c ------------------------- -@item mh-show-pgg-good -Good PGG signature face. -@c ------------------------- -@item mh-show-pgg-unknown -Unknown or untrusted PGG signature face. -@c ------------------------- -@item mh-show-signature -Signature face. -@c ------------------------- -@item mh-show-subject -Face used to highlight @samp{Subject:} header fields. -@c ------------------------- -@item mh-show-to -Face used to highlight @samp{To:} header fields. -@c ------------------------- -@item mh-show-xface -X-Face image face. -@end vtable - -The functions and variables introduced here are explained in more -detail in the following sections. - -@menu -* Viewing:: -* Viewing Attachments:: -* HTML:: -* Digests:: -* Reading PGP:: -* Printing:: -* Files and Pipes:: -* Navigating:: -* Miscellaneous Commands and Options:: -@end menu - -@node Viewing -@section Viewing Your Mail - -@findex mh-header-display -@findex mh-page-msg -@findex mh-previous-page -@findex mh-show -@findex mh-show-mouse -@kindex , @r{(comma)} -@kindex . @r{(period)} -@kindex BS -@kindex RET -@kindex SPC -@kindex mouse-2 - -The command @key{RET} (@code{mh-show}) displays the message that the -cursor is on while @kbd{mouse-2} (@code{mh-show-mouse}) displays the -message that the mouse cursor is on. If the message is already -displayed, it scrolls to the beginning of the message. Use @key{SPC} -(@code{mh-page-msg}) and @key{BS} (@code{mh-previous-page}) to move -forwards and backwards one page at a time through the message. You can -give either of these commands a prefix argument that specifies the -number of lines to scroll (such as @kbd{10 @key{SPC}}). The @key{SPC} -command will also show the next undeleted message if it is used at the -bottom of a message. MH-E normally hides a lot of the superfluous -header fields that mailers add to a message, but if you wish to see -all of them, use the command @kbd{,} (comma; -@code{mh-header-display}). - -@vindex mh-show-maximum-size - -The option @code{mh-show-maximum-size} provides an opportunity to skip -over large messages which may be slow to load. The default value of 0 -means that all message are shown regardless of size. - -A litany of options control what displayed messages look like. - -@vindex mh-show-cc -@vindex mh-show-date -@vindex mh-show-from -@vindex mh-show-header -@vindex mh-show-subject -@vindex mh-show-to - -First, the appearance of the header fields can be modified by -customizing the associated face: @code{mh-show-to}, @code{mh-show-cc}, -@code{mh-show-from}, @code{mh-show-date}, and @code{mh-show-subject}. -The face @code{mh-show-header} is used to deemphasize the other, less -interesting, header fields. - -@cindex regular expressions, @code{mh-invisible-header-fields} -@vindex mh-clean-message-header-flag -@vindex mh-invisible-header-fields -@vindex mh-invisible-header-fields-default - -Normally messages are delivered with a handful of uninteresting header -fields. These are hidden by turning on the option -@code{mh-clean-message-header-flag} (which it is by default). The -header fields listed in the option -@code{mh-invisible-header-fields-default} are hidden, although you can -check off any field that you would like to see. Header fields that you -would like to hide that aren't listed can be added to the option -@code{mh-invisible-header-fields} with a couple of caveats. Regular -expressions are not allowed. Unique fields should have a @samp{:} -suffix; otherwise, the element can be used to render invisible an -entire class of fields that start with the same prefix. If you think a -header field should be generally ignored, please update -@uref{https://sourceforge.net/p/mh-e/bugs/245/, SF #245}. - -@cindex header field, @samp{Face} -@cindex header field, @samp{X-Face} -@cindex header field, @samp{X-Image-URL} -@cindex @samp{Face} header field -@cindex @samp{X-Face} header field -@cindex @samp{X-Image-URL} header field -@vindex mh-show-use-xface-flag - -MH-E can display the content of @samp{Face:}, @samp{X-Face:}, and -@samp{X-Image-URL:} header fields. If any of these fields occur in the -header of your message, the sender's face will appear in the -@samp{From:} header field. If more than one of these fields appear, -then the first field found in the order @samp{Face:}, @samp{X-Face:}, -and @samp{X-Image-URL:} will be used. The option -@code{mh-show-use-xface-flag} is used to turn this feature on and off. -This feature will be turned on by default if your system supports it. - -The first header field used, if present, is the Gnus-specific -@samp{Face:} field@footnote{For more information, see -@uref{https://quimby.gnus.org/circus/face/}.}. - -@cindex @command{uncompface} -@cindex Emacs, packages, @samp{x-face} -@cindex Unix commands, @command{uncompface} -@cindex @samp{x-face} package -@vindex mh-show-xface - -@c FIXME: These URLs do not seem to work any more. -Next is the traditional @samp{X-Face:} header field@footnote{The -display of this field requires the -@uref{ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.Z, -@command{uncompface} program}.} MH-E renders the foreground and -background of the image using the associated attributes of the face -@code{mh-show-xface}. - -@cindex @command{convert} -@cindex @command{wget} -@cindex ImageMagick -@cindex Unix commands, @command{convert} -@cindex Unix commands, @command{wget} -@vindex mh-fetch-x-image-url - -Finally, MH-E will display images referenced by the -@samp{X-Image-URL:} header field if neither the @samp{Face:} nor the -@samp{X-Face:} fields are present@footnote{The display of the images -requires the @uref{https://www.gnu.org/software/wget/wget.html, -@command{wget} program} to fetch the image and the @command{convert} -program from the @uref{https://www.imagemagick.org/script/index.php, -ImageMagick suite}.}. 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. The option -@code{mh-fetch-x-image-url} controls the fetching of the -@samp{X-Image-URL:} header field image with the following values: - -@table @samp -@item Ask Before Fetching -You are prompted before the image is fetched. MH-E will remember your -reply and will either use the already fetched image the next time the -same URL is encountered or silently skip it if you didn't fetch it the -first time. This is a good setting. -@c ------------------------- -@item Never Fetch -Images are never fetched and only displayed if they are already -present in the cache. This is the default. -@end table - -There isn't a value of @samp{Always Fetch} for privacy and DOS (denial -of service) reasons. For example, fetching a URL can tip off a spammer -that you've read his email (which is why you shouldn't blindly answer -yes if you've set this option to @samp{Ask Before Fetching}). Someone -may also flood your network and fill your disk drive by sending a -torrent of messages, each specifying a unique URL to a very large -file. - -@cindex @file{.mhe-x-image-cache} -@cindex files, @file{.mhe-x-image-cache} - -The cache of images is found in the directory -@file{.mhe-x-image-cache} within your MH directory. You can add your -own face to the @samp{From:} field too. @xref{Picture}. - -@cindex @command{mhl} -@cindex MH commands, @command{mhl} -@vindex mh-mhl-format-file - -Normally MH-E takes care of displaying messages itself (rather than -calling an MH program to do the work). If you'd rather have -@command{mhl} display the message (within MH-E), change the option -@code{mh-mhl-format-file} from its default value of @samp{Use Default -mhl Format (Printing Only)}. You can set this option to @samp{Use -Default mhl Format} to get the same output as you would get if you ran -@command{mhl} from the shell. If you have a format file that you want -MH-E to use, you can set this option to @samp{Specify an mhl Format -File} and enter the name of your format file (@command{mhl}(1) or -section @uref{@value{MH-BOOK-HOME}/shomes.html#Usisho, Using mhl} in -the MH book tells you how to write one). Your format file should -specify a non-zero value for @samp{overflowoffset} to allow MH-E to -parse the header. Note that @command{mhl} is always used for printing -and forwarding; in this case, the value of @code{mh-mhl-format-file} -is consulted if you have specified a format file. - -@cindex citations, highlighting -@cindex highlighting citations -@vindex mh-highlight-citation-style - -If the sender of the message has cited other messages in his message, -then MH-E will highlight these citations to emphasize the sender's -actual response. The option @code{mh-highlight-citation-style} can be -customized to change the highlighting style. The @samp{Multicolor} -method uses a different color for each indentation while the -@samp{Monotone} method highlights all citations in red. To disable -highlighting of citations entirely, choose @samp{None}. - -@cindex URLs, highlighting -@cindex email addresses, highlighting -@cindex highlighting URLs -@cindex highlighting email addresses -@cindex links, following -@findex goto-address-at-point -@kindex C-c RET -@kindex mouse-2 -@vindex goto-address-highlight-p - -Email addresses and URLs in the message are highlighted if the option -@code{goto-address-highlight-p} is on, which it is by default. To view -the web page for a highlighted URL or to send a message using a -highlighted email address, use @kbd{mouse-2} or @kbd{C-c @key{RET}} -(@code{goto-address-at-point}). @xref{Sending Mail}, to see how to -configure Emacs to send the message using MH-E. - -@cindex boldface, showing -@cindex emphasis -@cindex italics, showing -@cindex smileys -@cindex typesetting -@cindex underline, showing -@vindex gnus-emphasis-alist -@vindex mh-decode-mime-flag -@vindex mh-graphical-emphasis-flag -@vindex mh-graphical-smileys-flag - -It is a long standing custom to inject body language using a -cornucopia of punctuation, also known as the @dfn{smileys}. MH-E can -render these as graphical widgets if the option -@code{mh-graphical-smileys-flag} is turned on, which it is by default. -Smileys include patterns such as :-) and ;-). Similarly, a few -typesetting features are indicated in ASCII text with certain -characters. If your terminal supports it, MH-E can render these -typesetting directives naturally if the option -@code{mh-graphical-emphasis-flag} is turned on, which it is by -default. For example, _underline_ will be -@ifhtml -@html -underlined, -@end html -@end ifhtml -@ifnothtml -underlined, -@end ifnothtml -*bold* will appear in @b{bold}, /italics/ will appear in @i{italics}, -and so on. See the option @code{gnus-emphasis-alist} for the whole -list. Both of these options are disabled if the option -@code{mh-decode-mime-flag} is turned off. @xref{Viewing Attachments}. - -@cindex signature separator -@cindex vCard -@vindex mh-show-signature - -MH-E normally renders signatures and vCards in italics so that the -body of the message stands out more. MH-E depends on the presence of -the @dfn{signature separator} (@code{"-- "}) to do this. You can also -customize the face @code{mh-show-signature} so the appearance of the -signature block is more to your liking. - -@vindex mh-show-hook -@vindex mh-show-mode-hook - -Two hooks can be used to control how messages are displayed. The first -hook, @code{mh-show-mode-hook}, is called early on in the process of -the message display. It is usually used to perform some action on the -message's buffer. The second hook, @code{mh-show-hook}, is the last -thing called after messages are displayed. It's used to affect the -message's content, the behavior of MH-E in general, or when -@code{mh-show-mode-hook} is too early. - -@cindex MH-Show mode -@cindex modes, MH-Show -@vindex mh-show-buffer-mode-line-buffer-id - -For those who like to modify their mode lines, use -@code{mh-show-buffer-mode-line-buffer-id} to modify the mode line in -the MH-Show buffers. Place the two escape strings @samp{%s} and -@samp{%d}, which will display the folder name and the message number, -respectively, somewhere in the string in that order. The default value -of @code{"@{show-%s@} %d"} yields a mode line of - -@smallexample ------@{show-+inbox@} 4 (MH-Show)--Bot-------------------------------- -@end smallexample - -@node Viewing Attachments -@section Viewing Attachments - -@cindex attachments -@cindex body parts -@cindex @command{mhshow} -@cindex @command{show} -@cindex MH commands, @command{mhshow} -@cindex MH commands, @command{show} -@cindex MIME -@cindex multimedia mail - -MH has the ability to display @dfn{@sc{mime}} (Multipurpose Internet -Mail Extensions) messages which are simply messages with additional -@dfn{body parts} or @dfn{attachments}. You can use the MH commands -@command{show}@footnote{See the section -@uref{@value{MH-BOOK-HOME}/reapre.html, Reading Mail: inc show next -prev} in the MH book.} or @command{mhshow}@footnote{See the section -@uref{@value{MH-BOOK-HOME}/usimim.html#ReMIMa, Reading MIME Mail} in -the MH book.} from the shell to read @sc{mime} messages@footnote{You -can call them directly from Emacs if you're running the X Window -System: type @kbd{M-! xterm -e mhshow @var{message-number}}. You can -leave out the @samp{xterm -e} if you use @command{mhlist} or -@command{mhstore}.}. - -@cindex Emacs, packages, @samp{mm-decode} -@cindex @samp{mm-decode} package -@findex mh-toggle-mh-decode-mime-flag -@kindex ; @r{(semicolon)} -@vindex mh-decode-mime-flag - -MH-E can handle attachments as well if the Gnus @samp{mm-decode} -package is present. If so, the option @code{mh-decode-mime-flag} will -be on. Otherwise, you'll see the @sc{mime} body parts rather than text -or attachments. There isn't much point in turning off the option -@code{mh-decode-mime-flag}; however, you can inspect it if it appears -that the body parts are not being interpreted correctly or toggle it -with the command @kbd{;} (semicolon; -@code{mh-toggle-mh-decode-mime-flag}) to view the raw message. This -option also controls the display of quoted-printable messages and -other graphical widgets. @xref{Viewing}. - -@cindex buttons - -Attachments in MH-E are indicated by @dfn{buttons} like this: - -@smallexample -[1. image/jpeg; foo.jpg]... -@end smallexample - -@findex mh-next-button -@findex mh-press-button -@findex mh-prev-button -@kindex RET -@kindex K TAB -@kindex K S-TAB -@kindex mouse-1 -@kindex mouse-2 - -To view the contents of the button, use either @kbd{mouse-1} or -@kbd{mouse-2} on the button or @key{RET} (@code{mh-press-button}) when -the cursor is over the button. This command is a toggle so if you use -it again on the same attachment, it is hidden. If Emacs does not know -how to display the attachment, then Emacs offers to save the -attachment in a file. To move the cursor to the next button, use the -command @kbd{K @key{TAB}} (@code{mh-next-button}). If the end of the -buffer is reached then the search wraps over to the start of the -buffer. To move the cursor to the previous button, use the command -@kbd{K S-@key{TAB}} (@code{mh-prev-button}). If the beginning of the -buffer is reached then the search wraps over to the end of the buffer. - -@cindex attachments, viewing -@cindex viewing attachments -@findex mh-folder-toggle-mime-part -@kindex K v - -Another way to view the contents of a button is to use the command -@kbd{K v} (@code{mh-folder-toggle-mime-part}). This command displays -(or hides) the attachment associated with the button under the cursor. -If the cursor is not located over a button, then the cursor first -moves to the next button, wrapping to the beginning of the message if -necessary. This command has the advantage over the previous commands -of working from the MH-Folder buffer. You can also provide a numeric -prefix argument (as in @kbd{4 K v}) to view the attachment labeled -with that number. If Emacs does not know how to display the -attachment, then Emacs offers to save the attachment in a file. - -@cindex @file{/etc/mailcap} -@cindex files, @file{/etc/mailcap} -@findex mailcap-mime-info -@findex mh-display-with-external-viewer -@kindex K e - -If Emacs does not know how to view an attachment, you could save it -into a file and then run some program to open it. It is easier, -however, to launch the program directly from MH-E with the command -@kbd{K e} (@code{mh-display-with-external-viewer}). While you'll most -likely use this to view spreadsheets and documents, it is also useful -to use your browser to view HTML attachments with higher fidelity than -what Emacs can provide. This command displays the attachment -associated with the button under the cursor. If the cursor is not -located over a button, then the cursor first moves to the next button, -wrapping to the beginning of the message if necessary. You can provide -a numeric prefix argument (as in @kbd{4 K e}) to view the attachment -labeled with that number. This command tries to provide a reasonable -default for the viewer by calling the Emacs function -@code{mailcap-mime-info}. This function usually reads the file -@file{/etc/mailcap}. - -@cindex attachments, saving -@cindex saving attachments -@findex mh-folder-save-mime-part -@kindex K o - -Use the command @kbd{K o} (@code{mh-folder-save-mime-part}) to save -attachments (the mnemonic is ``output''). This command saves the -attachment associated with the button under the cursor. If the cursor -is not located over a button, then the cursor first moves to the next -button, wrapping to the beginning of the message if necessary. You can -also provide a numeric prefix argument (as in @kbd{3 K o}) to save the -attachment labeled with that number. This command prompts you for a -filename and suggests a specific name if it is available. - -@cindex @command{mhn} -@cindex @command{mhstore} -@cindex MH commands, @command{mhn} -@cindex MH commands, @command{mhstore} -@findex mh-mime-save-parts -@kindex K a -@vindex mh-mime-save-parts-default-directory - -You can save all of the attachments at once with the command @kbd{K a} -(@code{mh-mime-save-parts}). The attachments are saved in the -directory specified by the option -@code{mh-mime-save-parts-default-directory} unless you use a prefix -argument (as in @kbd{C-u K a}) in which case you are prompted for the -directory. These directories may be superseded by MH profile -components, since this function calls on @command{mhstore} -(@command{mhn}) to do the work. - -@vindex mh-mime-save-parts-default-directory - -The default value for the option -@code{mh-mime-save-parts-default-directory} is @samp{Prompt Always} so -that you are always prompted for the directory in which to save the -attachments. However, if you usually use the same directory within a -session, then you can set this option to @samp{Prompt the First Time} -to avoid the prompt each time. you can make this directory permanent -by choosing @samp{Directory} and entering the directory's name. - -@cindex attachments, inline -@cindex inline attachments -@findex mh-toggle-mime-buttons -@kindex K t -@vindex mh-display-buttons-for-inline-parts-flag - -The sender can request that attachments should be viewed inline so -that they do not really appear like an attachment at all to the -reader. Most of the time, this is desirable, so by default MH-E -suppresses the buttons for inline attachments. On the other hand, you -may receive code or HTML which the sender has added to his message as -inline attachments so that you can read them in MH-E@. In this case, it -is useful to see the buttons so that you know you don't have to cut -and paste the code into a file; you can simply save the attachment. If -you want to make the buttons visible for inline attachments, you can -use the command @kbd{K t} (@code{mh-toggle-mime-buttons}) to toggle -the visibility of these buttons. You can turn on these buttons -permanently by turning on the option -@code{mh-display-buttons-for-inline-parts-flag}. - -MH-E cannot display all attachments inline however. It can display -text (including @sc{html}) and images. - -@cindex header field, @samp{Content-Disposition} -@cindex inline images -@cindex @samp{Content-Disposition} header field -@vindex mh-max-inline-image-height -@vindex mh-max-inline-image-width - -Some older mail programs do not insert the needed -plumbing@footnote{This plumbing is the @samp{Content-Disposition:} -header field.} to tell MH-E whether to display the attachments inline -or not. If this is the case, MH-E will display these images inline if -they are smaller than the window. However, you might want to allow -larger images to be displayed inline. To do this, you can change the -options @code{mh-max-inline-image-width} and -@code{mh-max-inline-image-height} from their default value of zero to -a large number. The size of your screen is a good choice for these -numbers. - -@cindex alternatives -@cindex attachments, alternatives -@vindex mh-display-buttons-for-alternatives-flag - -Sometimes, a mail program will produce multiple alternatives of an -attachment in increasing degree of faithfulness to the original -content. By default, only the preferred alternative is displayed. If -the option @code{mh-display-buttons-for-alternatives-flag} is on, then -the preferred part is shown inline and buttons are shown for each of -the other alternatives. - -@vindex mm-discouraged-alternatives - -Many people prefer to see the @samp{text/plain} alternative rather -than the @samp{text/html} alternative. To do this in MH-E, customize -the option @code{mm-discouraged-alternatives}, and add -@samp{text/html}. The next best alternative, if any, will be shown. - -@findex mh-show-preferred-alternative -@kindex : @r{(colon)} - -Occasionally, though, you might want to see the preferred alternative. -The command @kbd{:} (@code{mh-show-preferred-alternative}) displays -the message with the default preferred alternative. This is as if -@code{mm-discouraged-alternatives} is set to @samp{nil}. Use the -command @key{RET} (@code{mh-show}) to show the message normally again. - -@kindex K i -@findex mh-folder-inline-mime-part - -You can view the raw contents of an attachment with the command @kbd{K -i} (@code{mh-folder-inline-mime-part}). This command displays (or -hides) the contents of the attachment associated with the button under -the cursor verbatim. If the cursor is not located over a button, then -the cursor first moves to the next button, wrapping to the beginning -of the message if necessary. You can also provide a numeric prefix -argument (as in @kbd{4 K i}) to view the attachment labeled with that -number. - -For additional information on buttons, see -@ifinfo -@ref{Article Buttons,,,gnus}, and @ref{MIME Commands,,,gnus}. -@end ifinfo -@ifnotinfo -the chapters @uref{https://www.gnus.org/manual/gnus_101.html#SEC101, -Article Buttons} and -@uref{https://www.gnus.org/manual/gnus_108.html#SEC108, MIME Commands} -in the @cite{The Gnus Manual}. -@end ifnotinfo - -@node HTML -@section HTML - -@cindex HTML -@cindex Gnus - -MH-E can display messages that have been sent in HTML. The -content of the message will appear in the MH-Show buffer as you would -expect if the entire message is HTML, or there is an inline HTML body -part. However, if there is an HTML body part that is an attachment, -then you'll see a button like this: - -@smallexample -[1. text/html; foo.html]... -@end smallexample - -To see how to read the contents of this body part, see @ref{Viewing -Attachments}. - -@vindex mm-text-html-renderer - -The browser that MH-E uses is determined by the option -@code{mm-text-html-renderer}. The default setting is set automatically -based upon the presence of a known browser on your system. If you wish -to use a different browser, then set this option accordingly. See the -documentation for the browser you use for additional information on -how to use it. In particular, find and disable the option to render -images, as displaying remote images can tip off spammers that the -email address they have used is valid. - -@vindex mm-text-html-renderer - -If you're confused about which @code{mm-text-html-renderer} to use, -here's a brief description of each, sorted by name. - -@table @asis -@cindex browser, @samp{gnus-w3m} -@cindex @samp{gnus-w3m} -@cindex browser, @samp{w3m} -@cindex @samp{w3m} -@item @samp{gnus-w3m} -The @samp{gnus-w3m} browser requires an external program. It's quick, -produces pretty nice output, and it highlights links. It renders -@samp{–} and @samp{®} okay. It sometimes fails to wrap lines -properly. It always downloads remote images. -@c ------------------------- -@cindex browser, @samp{links} -@cindex @samp{links} -@item @samp{links} -The @samp{links} browser requires an external program. It's quick, and -produces nicer output than @samp{lynx} on single column mails in -tables. However, it doesn't show links and it doesn't do as nice a job -on multi-column tables as some lines wrap. It does do a good job of -fitting text within 80 columns. It appears to render special -characters using ASCII equivalents. For example, @samp{®} appears -as (R). It does not download images. -@c ------------------------- -@cindex browser, @samp{lynx} -@cindex @samp{lynx} -@item @samp{lynx} -The @samp{lynx} browser requires an external program. It's quick and -produces pretty decent output but it doesn't show links. It doesn't -seem to do multi-column tables which makes output much cleaner. It -centers the output and wraps long lines more than most. It does not -always handle special characters like @samp{®} or @samp{–}. -It does not download images. -@c ------------------------- -@item @samp{shr} -@cindex @samp{shr} -This choice does not require an external program, but it does require -that Emacs be configured at build time to use @samp{libxml2}. It is -fairly quick, it highlights links, and it supports HTML color -declarations. It renders @samp{–} and @samp{®} okay. It -sometimes truncates text, particularly if the message tries to have -fancy text layout. By default it does not download images; this -behavior is controlled by the options @code{mm-html-blocked-images} -and @code{mm-html-inhibit-images} -@ifinfo -(@pxref{Display Customization,,,emacs-mime}). -@end ifinfo -@ifnotinfo -(see section @uref{https://www.gnus.org/manual/emacs-mime_6.html, -Display Customization} in the @cite{The Emacs MIME Manual}). -@end ifnotinfo -@c ------------------------- -@cindex browser, @samp{w3m} -@cindex @samp{w3m} -@kindex mouse-2 -@item @samp{w3m} -The @samp{w3m} browser requires an external program. It's quick, -produces pretty nice output, and it highlights links. These can be -clicked with @kbd{mouse-2} to view the content of the link in -@samp{w3m}. The @samp{w3m} browser handles tables well and actually -respects the table's width parameter (which can cause text to wrap if -the author didn't anticipate that the page would be viewed in Emacs). -It does not download images by default; this behavior is controlled by -the option @code{mm-w3m-safe-url-regexp} -@ifinfo -(@pxref{Display Customization,,,emacs-mime}). -@end ifinfo -@ifnotinfo -(see section @uref{https://www.gnus.org/manual/emacs-mime_6.html, -Display Customization} in the @cite{The Emacs MIME Manual}). -@end ifnotinfo -@c ------------------------- -@cindex browser, @samp{w3m-standalone} -@cindex @samp{w3m-standalone} -@cindex browser, @samp{w3m} -@cindex @samp{w3m} -@item @samp{w3m-standalone} -This browser is quick, but does not show links. It handles simple -tables but some tables get rendered much wider than the Emacs frame. -This browser renders @samp{–} and @samp{®} okay. It does not -download images. -@end table - -@vindex mm-text-html-renderer - -For a couple more sources of information about -@code{mm-text-html-renderer}, -@ifinfo -@xref{Display Customization,,,emacs-mime}, and the documentation for -the Gnus command @kbd{W h} (@pxref{Article Washing,,,gnus}). -@end ifinfo -@ifnotinfo -see section @uref{https://www.gnus.org/manual/emacs-mime_6.html, -Display Customization} in the @cite{The Emacs MIME Manual} and the -documentation for the Gnus command @kbd{W h} (see section -@uref{https://www.gnus.org/manual/gnus_48.html#Article-Washing, Article -Washing} in the -@cite{The Gnus Manual}). -@end ifnotinfo - -@cindex @file{.emacs} -@cindex files, @file{.emacs} -@findex browse-url-at-mouse -@kindex S-mouse-2 - -A useful key binding that you can add to @file{~/.emacs} is the -following which displays an HTML link or textual URL in an external -browser when clicked with @kbd{S-mouse-2}. This binding works in any -buffer, including HTML buffers. - -@smalllisp -(global-set-key [S-mouse-2] 'browse-url-at-mouse) -@end smalllisp - -@node Digests -@section Digests - -@cindex digests -@findex mh-page-digest -@findex mh-page-digest-backwards -@kindex D BS -@kindex D SPC -@kindex BS -@kindex SPC - -A digest is a message that contains other messages. Special MH-E -commands let you read digests conveniently. You can use @key{SPC} and -@key{BS} to page through the digest as if it were a normal message, -but if you wish to skip to the next message in the digest, use -@kbd{D @key{SPC}} (@code{mh-page-digest}). To return to a previous message, -use @kbd{D @key{BS}} (@code{mh-page-digest-backwards}). - -@cindex @command{burst} -@cindex MH commands, @command{burst} -@cindex MH-Folder Show mode -@cindex modes, MH-Folder Show -@findex mh-burst-digest -@kindex d -@kindex D b -@kindex t - -Another handy command is @kbd{D b} (@code{mh-burst-digest}). This -command uses the MH command @command{burst}@footnote{See the section -@uref{@value{MH-BOOK-HOME}/burdig.html, Bursting Messages} in the MH -book.} to break out each message in the digest into its own message. -Using this command, you can quickly delete unwanted messages, like -this: Once the digest is split up, toggle out of MH-Folder Show mode -with @kbd{t} (@pxref{Folders}) so that the scan lines fill the screen -and messages aren't displayed. Then use @kbd{d} (@pxref{Reading Mail}) -to quickly delete messages that you don't want to read (based on the -@samp{Subject:} header field). You can also burst the digest to reply -directly to the people who posted the messages in the digest. One -problem you may encounter is that the @samp{From:} header fields are -preceded with a @samp{>} so that your reply can't create the -@samp{To:} field correctly. In this case, you must correct the -@samp{To:} field yourself. This is described later (@pxref{Editing -Drafts}). - -@node Reading PGP -@section Signed and Encrypted Messages - -@cindex GPG -@cindex GnuPG -@cindex Gnus -@cindex OpenPGP -@cindex PGP -@cindex RFC 3156 -@cindex encrypted messages -@cindex security -@cindex signed messages - -You can read encrypted or signed PGP or GPG messages with -MH-E@footnote{@cite{MIME Security with OpenPGP} is documented in -@uref{https://www.rfc-editor.org/rfc/rfc3156.txt, RFC 3156}. However, -MH-E can also decrypt old-style PGP messages that are not in MIME -format.}. This section assumes that you already have a good -understanding of GPG and have set up your keys appropriately. - -If someone sends you a signed message, here is what you'll see: - -@smallexample -@group -[[PGP Signed Part:Bill Wohler ]] -This is a signed message. - -[[End of PGP Signed Part]] -@end group -@end smallexample - -@cindex keychain -@cindex key server -@cindex signed messages - -If the key for the given signature is not in your keychain, you'll be -given the opportunity to fetch the key from a key server and verify -the key. If the message is really large, the verification process can -take a long time. You can press @kbd{C-g} at any time to -cancel@footnote{Unfortunately in the current version, the validation -process doesn't display a message so it appears that MH-E has hung. We -hope that this will be fixed in the future.}. - -If the signature doesn't check out, you might see something like this: - -@smallexample -@group -[[PGP Signed Part:Failed]] -This is a signed message. -This is garbage added after the signature was made. - -[[End of PGP Signed Part]] -@end group -@end smallexample - -@cindex decrypting messages - -If someone sends you an encrypted message, MH-E will ask for your -passphrase to decrypt the message. You should see something like this: - -@smallexample -@group -[[PGP Encrypted Part:OK]] - -[[PGP Signed Part:Bill Wohler ]] -This is the secret message. - -[[End of PGP Signed Part]] - -[[End of PGP Encrypted Part]] -@end group -@end smallexample - -If there is a problem decrypting the message, the button will say: - -@smallexample -[[PGP Encrypted Part:Failed]] -@end smallexample - -You can read the contents of this button using the methods described in -@ref{Viewing Attachments}. If the message were corrupted, you'd see -this: - -@smallexample -[[PGP Encrypted Part:Failed] -Invalid base64 data] -@end smallexample - -If your passphrase were incorrect, you'd see something like this: - -@smallexample -[GNUPG:] ENC_TO CD9C88BB610BD9AD 1 0 -[GNUPG:] USERID_HINT CD9C88BB610BD9AD Bill Wohler -[GNUPG:] NEED_PASSPHRASE CD9C88BB610BD9AD CD9C88BB610BD9AD 1 0 -[GNUPG:] BAD_PASSPHRASE CD9C88BB610BD9AD -gpg: encrypted with 1024-bit RSA key, ID 610BD9AD, created 1997-09-09 - "Bill Wohler " -gpg: public key decryption failed: bad passphrase -[GNUPG:] BEGIN_DECRYPTION -[GNUPG:] DECRYPTION_FAILED -gpg: decryption failed: secret key not available -[GNUPG:] END_DECRYPTION - -gpg exited abnormally: '2' -@end smallexample - -@vindex mh-show-pgg-bad -@vindex mh-show-pgg-good -@vindex mh-show-pgg-unknown - -The appearance of the buttons is controlled by the faces -@code{mh-show-pgg-good}, @code{mh-show-pgg-bad}, and -@code{mh-show-pgg-unknown} depending on the validity of the signature. -The latter is used whether the signature is unknown or untrusted. - -@node Printing -@section Printing Your Mail - -@cindex printing -@findex mh-ps-print-msg -@findex mh-ps-print-msg-file -@kindex P f -@kindex P p -@vindex mh-lpr-command-format -@vindex mh-print-background-flag - -To print messages in MH-E, use the command @kbd{P p} -(@code{mh-ps-print-msg}). You can print all the messages in a range -(as in @kbd{C-u P p 1 3 5-7 last:5 frombob @key{RET}}, -@pxref{Ranges}). You can also send the output to a file with @kbd{P f} -(@code{mh-ps-print-msg-file}). This command will print inline text -attachments but will not decrypt messages. However, when a message is -displayed in an MH-Show buffer, then that buffer is used verbatim for -printing with the caveat that only text attachments, if opened inline, -are printed. Therefore, encrypted messages can be printed by showing -and decrypting them first. The commands @kbd{P p} and @kbd{P f} do not -use the options @code{mh-lpr-command-format} or -@code{mh-print-background-flag}, described below. - -@findex mh-ps-print-toggle-color -@kindex P C -@vindex ps-print-color-p - -Colors are emulated on black-and-white printers with shades of gray. -This might produce illegible output, even if your screen colors only -use shades of gray. If this is the case, try using the command @kbd{P -C} (@code{mh-ps-print-toggle-color}) to toggle between color, no -color, and a black and white representation of the colors and see -which works best. You change this setting permanently by customizing -the option @code{ps-print-color-p}. - -@findex mh-ps-print-toggle-faces -@kindex P F - -Another related function is the command @kbd{P F} -(@code{mh-ps-print-toggle-faces}). This command toggles between using -faces and not. When faces are enabled, the printed message will look -very similar to the message in the MH-Show buffer. - -@cindex @samp{ps-print} package -@cindex Emacs, packages, @samp{ps-print} - -MH-E uses the @samp{ps-print} package to do the printing, so you can -customize the printing further by going to the @samp{ps-print} -customization group. - -@cindex @command{lpr} -@cindex @command{mhl} -@cindex MH commands, @command{mhl} -@cindex Unix commands, @command{lpr} -@findex mh-print-msg -@kindex P l - -An alternative to using the @samp{ps-print} package is the command -@kbd{P l} (@code{mh-print-msg}) (the @i{l} is for @i{l}ine printer or -@i{l}pr). You can print all the messages in a range. The message is -formatted with @command{mhl}@footnote{See the section -@uref{@value{MH-BOOK-HOME}/shomes.html#Usisho, Using mhl} in the MH -book.} and printed with the @command{lpr} command. - -@kindex P f -@kindex P l -@kindex P p -@vindex mh-lpr-command-format -@vindex mh-print-background-flag - -The command @kbd{P l} uses two options. The option -@code{mh-lpr-command-format} contains the Unix command line which -performs the actual printing. The string can contain one escape, -@samp{%s}, which is replaced by the name of the folder and the message -number and is useful for print job names. The default setting is -@code{"lpr -J '%s'"}. I use @code{"mpage -h'%s' -b Letter -H1of -mlrtb --P"} which produces a nice header and adds a bit of margin so the text -fits within my printer's margins. Normally messages are printed in the -foreground. If this is slow on your system, you may elect to turn on -the option @code{mh-print-background-flag} to print in the background. -If you do this, do not delete the message until it is printed or else -the output may be truncated. These options are not used by the -commands @kbd{P p} or @kbd{P f}. - -@node Files and Pipes -@section Files and Pipes - -@cindex files -@cindex pipes -@findex mh-refile-or-write-again -@findex mh-write-msg-to-file -@kindex > -@kindex ! - -MH-E does offer a couple of commands that are not a part of MH@. The -first one, @kbd{>} (@code{mh-write-msg-to-file}), writes a message to -a file. You are prompted for the filename. If the file already exists, -the message is appended to it. You can also write the message to the -file without the header by specifying a prefix argument (such as -@kbd{C-u > /tmp/foobar @key{RET}}). Subsequent writes to the same file -can be made with the command @kbd{!} -(@code{mh-refile-or-write-again}). - -@findex mh-pipe-msg -@kindex | -@kindex l - -You can also pipe the message through a Unix shell command with the -command @kbd{|} (@code{mh-pipe-msg}). You are prompted for the Unix -command through which you wish to run your message. If you give a -prefix argument to this command, the message header is included in the -text passed to the command (the contrived example @kbd{C-u | lpr} -would be done with the @kbd{l} command instead). - -@cindex @command{shar} -@cindex @command{uuencode} -@cindex Unix commands, @command{shar} -@cindex Unix commands, @command{uuencode} -@findex mh-store-msg -@kindex X s -@vindex mh-store-default-directory - -If the message is a shell archive @command{shar} or has been run -through @command{uuencode} use @kbd{X s} (@code{mh-store-msg}) to -extract the body of the message. The default directory for extraction -is the current directory; however, you have a chance to specify a -different extraction directory. The next time you use this command, -the default directory is the last directory you used. If you would -like to change the initial default directory, customize the option -@code{mh-store-default-directory}, change the value from -@samp{Current} to @samp{Directory}, and then enter the name of the -directory for storing the content of these messages. - -@findex mh-store-buffer -@kindex RET -@kindex X s - -By the way, @kbd{X s} calls the Emacs Lisp function -@code{mh-store-buffer}. I mention this because you can use it directly -if you're editing a buffer that contains a file that has been run -through @command{uuencode} or @command{shar}. For example, you can -extract the contents of the current buffer in your home directory by -typing @kbd{M-x mh-store-buffer @key{RET} ~ @key{RET}}. - -@node Navigating -@section Navigating - -@cindex moving between messages -@cindex navigation -@findex mh-first-msg -@findex mh-goto-msg -@findex mh-last-msg -@findex mh-next-undeleted-msg -@findex mh-next-unread-msg -@findex mh-previous-undeleted-msg -@findex mh-previous-unread-msg -@kindex g -@kindex M-< -@kindex M-> -@kindex M-n -@kindex M-p -@kindex n -@kindex p - -To move on to the next message, use the command @kbd{n} -(@code{mh-next-undeleted-msg}); use @kbd{p} -(@code{mh-previous-undeleted-msg}) to read the previous message. To -move to the next unread message, use @kbd{M-n} -(@code{mh-next-unread-msg}); use @kbd{M-p} -(@code{mh-previous-unread-msg}) to move to the previous unread -message. These commands can be given a prefix argument to specify how -many messages to skip (for example, @kbd{5 n}). You can also move to a -specific message with @kbd{g} (@code{mh-goto-msg}). You can enter the -message number either before or after typing @kbd{g}. In the latter -case, Emacs prompts you. Finally, you can go to the first or last -message with @kbd{M-<} (@code{mh-first-msg}) and @kbd{M->} -(@code{mh-last-msg}) respectively. - -@cindex MH-Folder mode -@cindex modes, MH-Folder -@findex next-line -@findex previous-line -@kindex C-n -@kindex C-p -@kindex RET - -You can also use the Emacs commands @kbd{C-p} (@code{previous-line}) -and @kbd{C-n} (@code{next-line}) to move up and down the scan lines in -the MH-Folder window. These commands can be used in conjunction with -@key{RET} to look at deleted or refiled messages. - -@cindex deleting messages -@findex mh-delete-msg -@kindex d -@kindex n -@kindex p - -To mark a message for deletion, use the command @kbd{d} -(@code{mh-delete-msg}). A @samp{D} is placed by the message in the -scan window, and the next undeleted message is displayed. If the -previous command had been @kbd{p}, then the next message displayed is -the first undeleted message previous to the message just deleted. Use -@kbd{n} to force subsequent @kbd{d} commands to move forward to the -next undeleted message after deleting the message under the cursor. -You may also specify a range (for example, @kbd{C-u d 1 3 5-7 last:5 -frombob @key{RET}}, @pxref{Ranges}). - -@findex mh-delete-msg-no-motion -@kindex C-d - -The command @kbd{C-d} (@code{mh-delete-msg-no-motion}) marks the -message (or messages in range) for deletion but leaves the cursor at -the current message in case you wish to perform other operations on -the message. - -@findex mh-delete-subject -@findex mh-delete-subject-or-thread -@findex mh-thread-delete -@findex mh-undo -@kindex k -@kindex T d -@kindex u - -And to delete more messages faster, you can use @kbd{k} -(@code{mh-delete-subject-or-thread}) to delete all the messages with -the same subject as the current message. This command puts these -messages in a sequence named @samp{subject}. You can undo this action -by using @kbd{u} (@code{mh-undo}) with a prefix argument and then -specifying the @samp{subject} sequence. However, if the buffer is -displaying a threaded view of the folder then @kbd{k} behaves like -@kbd{T d} (@code{mh-thread-delete}). @xref{Threading}. - -@findex mh-execute-commands -@kindex x - -However you mark a message for deletion, the command @kbd{x} -(@code{mh-execute-commands}) actually carries out the deletion -(@pxref{Folders}). - -@vindex mh-delete-msg-hook - -The hook @code{mh-delete-msg-hook} is called after you mark a message -for deletion. For example, a past maintainer of MH-E used this once -when he kept statistics on his mail usage. - -@node Miscellaneous Commands and Options -@section Miscellaneous Commands and Options - -This section contains a few more miscellaneous commands and options. - -@cindex editing message -@findex mh-modify -@kindex M - -There are times when you need to edit a message. For example, you may -need to fix a broken Content-Type header field. You can do this with -the command @kbd{M} (@code{mh-modify}). It displays the raw message in -an editable buffer. When you are done editing, save and kill the -buffer as you would any other. - -@findex mh-kill-folder -@findex mh-pack-folder -@vindex mh-do-not-confirm-flag - -Commands such as @code{mh-pack-folder} prompt to confirm whether to -process outstanding moves and deletes or not before continuing. -Turning on the option @code{mh-do-not-confirm-flag} means that these -actions will be performed---which is usually desired but cannot be -retracted---without question@footnote{In previous versions of MH-E, -this option suppressed the confirmation in @code{mh-kill-folder}. -Since this kept most users from setting this option, -@code{mh-kill-folder} was modified in version 6.0 to always ask for -confirmation subject to @code{mh-kill-folder-suppress-prompt-functions}. -@xref{Folders}.}. - -@cindex MH-Folder mode -@cindex modes, MH-Folder -@vindex mh-summary-height - -The option @code{mh-summary-height} controls the number of scan lines -displayed in the MH-Folder window, including the mode line. The -default value of this option is @samp{Automatic} which means that the -MH-Folder buffer will maintain the same proportional size if the frame -is resized. If you'd prefer a fixed height, then choose the -@samp{Fixed Size} option and enter the number of lines you'd like to -see. - -@vindex mh-bury-show-buffer-flag - -Normally the buffer for displaying messages is buried at the bottom at -the buffer stack. You may wish to disable this feature by turning off -the option @code{mh-bury-show-buffer-flag}. One advantage of not -burying the show buffer is that one can delete the show buffer more -easily in an electric buffer list because of its proximity to its -associated MH-Folder buffer. Try running @kbd{M-x -electric-buffer-list} to see what I mean. - -@cindex @file{.emacs} -@cindex files, @file{.emacs} -@cindex reading mail - -Before we leave this section, I'll include a function that I use as a -front end to MH-E@footnote{Stephen Gildea's favorite binding is -@kbd{(global-set-key "\C-cr" 'mh-rmail)}.}. It toggles between your -working window configuration, which may be quite involved---windows -filled with source, compilation output, man pages, and other -documentation---and your MH-E window configuration. Like the rest of -the customization described in this section, simply add the following -code to @file{~/.emacs}. - -@iftex -@filbreak -@end iftex - -@findex mh-rmail@r{, example} - -@smalllisp -@group -(defvar my-mh-screen-saved nil - "Set to non-nil when MH-E window configuration shown.") -(defvar my-normal-screen nil "Normal window configuration.") -(defvar my-mh-screen nil "MH-E window configuration.") - -(defun my-mh-rmail (&optional arg) - "Toggle between MH-E and normal screen configurations. -With non-nil or prefix argument, include mailbox as well -when going into mail." - (interactive "P") ; @r{user callable function, P=prefix arg} - (setq my-mh-screen-saved ; @r{save state} - (cond - ;; @r{Bring up MH-E screen if arg or normal window configuration.} - ;; @r{If arg or +inbox buffer doesn't exist, run mh-rmail.} - ((or arg (null my-mh-screen-saved)) - (setq my-normal-screen (current-window-configuration)) - (if (or arg (null (get-buffer "+inbox"))) - (mh-rmail) - (set-window-configuration my-mh-screen)) - t) ; @r{set my-mh-screen-saved to @code{t}} - ;; @r{Otherwise, save MH-E screen and restore normal screen.} - (t - (setq my-mh-screen (current-window-configuration)) - (set-window-configuration my-normal-screen) - nil)))) ; @r{set my-mh-screen-saved to nil} - -(global-set-key "\C-x\r" 'my-mh-rmail) ;@r{ call with C-x @key{RET}} - -@i{Starting MH-E} - -@end group -@end smalllisp - -If you type an argument (@kbd{C-u}) or if @code{my-mh-screen-saved} is -@code{nil} (meaning a non-MH-E window configuration), the current -window configuration is saved, either the @samp{+inbox} buffer is -displayed or @code{mh-rmail} is run, and the MH-E window configuration -is shown. Otherwise, the MH-E window configuration is saved and the -original configuration is displayed. - -@node Folders -@chapter Organizing Your Mail with Folders - -@cindex @samp{Folder} menu -@cindex @samp{Message} menu -@cindex folders -@cindex menu, @samp{Folder} -@cindex menu, @samp{Message} -@cindex using folders - -This chapter discusses the things you can do with folders within MH-E@. -The commands in this chapter are also found in the @samp{Folder} and -@samp{Message} menus. - -@table @kbd -@kindex ? -@findex mh-help -@item ? -Display cheat sheet for the MH-E commands (@code{mh-help}). -@c ------------------------- -@kindex ! -@findex mh-refile-or-write-again -@item ! -Repeat last output command (@code{mh-refile-or-write-again}). -@c ------------------------- -@cindex @samp{Message > Copy Message to Folder...} menu item -@cindex menu item, @samp{Message > Copy Message to Folder...} -@kindex c -@findex mh-copy-msg -@item c -Copy range to folder (@code{mh-copy-msg}). -@c ------------------------- -@kindex F ? -@findex mh-prefix-help -@item F ? -Display cheat sheet for the commands of the current prefix in -minibuffer (@code{mh-prefix-help}). -@c ------------------------- -@kindex F ' -@findex mh-index-ticked-messages -@item F ' -Display ticked messages (@code{mh-index-ticked-messages}). -@c ------------------------- -@kindex F c -@findex mh-catchup -@item F c -Delete range from the @samp{unseen} sequence (@code{mh-catchup}). -@c ------------------------- -@kindex F k -@findex mh-kill-folder -@item F k -Remove folder (@code{mh-kill-folder}). -@c ------------------------- -@cindex @samp{Folder > List Folders} menu item -@cindex menu item, @samp{Folder > List Folders} -@kindex F l -@findex mh-list-folders -@item F l -List all folders (@code{mh-list-folders}). -@c ------------------------- -@cindex @samp{Folder > View New Messages} menu item -@cindex menu item, @samp{Folder > View New Messages} -@kindex F n -@findex mh-index-new-messages -@item F n -Display unseen messages (@code{mh-index-new-messages}). -@c ------------------------- -@cindex @samp{Folder > Pack Folder} menu item -@cindex menu item, @samp{Folder > Pack Folder} -@kindex F p -@findex mh-pack-folder -@item F p -Pack folder (@code{mh-pack-folder}). -@c ------------------------- -@kindex F q -@findex mh-index-sequenced-messages -@item F q -Display messages in any sequence (@code{mh-index-sequenced-messages}). -@c ------------------------- -@cindex @samp{Folder > Rescan Folder} menu item -@cindex menu item, @samp{Folder > Rescan Folder} -@kindex F r -@findex mh-rescan-folder -@item F r -Rescan folder (@code{mh-rescan-folder}). -@c ------------------------- -@cindex @samp{Folder > Search...} menu item -@cindex menu item, @samp{Folder > Search...} -@kindex F s -@findex mh-search -@item F s -Search your MH mail (@code{mh-search}). -@c ------------------------- -@cindex @samp{Folder > Sort Folder} menu item -@cindex menu item, @samp{Folder > Sort Folder} -@kindex F S -@findex mh-sort-folder -@item F S -Sort folder (@code{mh-sort-folder}). -@c ------------------------- -@kindex F u -@findex mh-undo-folder -@item F u -Undo all refiles and deletes in the current folder (@code{mh-undo-folder}). -@c ------------------------- -@cindex @samp{Folder > Visit a Folder...} menu item -@cindex menu item, @samp{Folder > Visit a Folder...} -@kindex F v -@findex mh-visit-folder -@item F v -Visit folder (@code{mh-visit-folder}). -@c ------------------------- -@cindex @samp{Message > Refile Message} menu item -@cindex menu item, @samp{Message > Refile Message} -@kindex o -@findex mh-refile-msg -@item o -Refile (output) range into folder (@code{mh-refile-msg}). -@c ------------------------- -@cindex @samp{Folder > Quit MH-E} menu item -@cindex menu item, @samp{Folder > Quit MH-E} -@kindex q -@findex mh-quit -@item q -Quit the current MH-E folder (@code{mh-quit}). -@c ------------------------- -@cindex @samp{Folder > Toggle Show/Folder} menu item -@cindex menu item, @samp{Folder > Toggle Show/Folder} -@kindex t -@findex mh-toggle-showing -@item t -Toggle between MH-Folder and MH-Folder Show modes -(@code{mh-toggle-showing}). -@c ------------------------- -@cindex @samp{Message > Undo Delete/Refile} menu item -@cindex menu item, @samp{Message > Undo Delete/Refile} -@kindex u -@findex mh-undo -@item u -Undo pending deletes or refiles in range (@code{mh-undo}). -@c ------------------------- -@cindex @samp{Message > Execute Delete/Refile} menu item -@cindex menu item, @samp{Message > Execute Delete/Refile} -@kindex x -@findex mh-execute-commands -@item x -Process outstanding delete and refile requests -(@code{mh-execute-commands}). -@end table - -@cindex @samp{mh-folder} customization group -@cindex customization group, @samp{mh-folder} - -The @samp{mh-folder} customization group is used to tune these -commands. - -@vtable @code -@item mh-new-messages-folders -Folders searched for the @samp{unseen} sequence (default: -@code{Inbox}). -@c ------------------------- -@item mh-ticked-messages-folders -Folders searched for @code{mh-tick-seq} (default: @code{t}). -@c ------------------------- -@item mh-large-folder -The number of messages that indicates a large folder (default: 200). -@c ------------------------- -@item mh-recenter-summary-flag -On means to recenter the summary window (default: @samp{off}). -@c ------------------------- -@item mh-recursive-folders-flag -On means that commands which operate on folders do so recursively -(default: @samp{off}). -@c ------------------------- -@item mh-sortm-args -Additional arguments for @command{sortm} (default: @code{nil}). -@end vtable - -The following hooks are available. - -@vtable @code -@item mh-after-commands-processed-hook -Hook run by @kbd{x} after performing outstanding refile and delete -requests (default: @code{nil}). -@c ------------------------- -@item mh-before-commands-processed-hook -Hook run by @kbd{x} before performing outstanding refile and delete -requests (default: @code{nil}). -@c ------------------------- -@item mh-before-quit-hook -Hook run by q before quitting MH-E (default: @code{nil}). -@c ------------------------- -@item mh-folder-mode-hook -Hook run by @code{mh-folder-mode} when visiting a new folder (default: -@code{nil}). -@c ------------------------- -@item mh-kill-folder-suppress-prompt-functions -Abnormal hook run at the beginning of @code{mh-kill-folder} (default: -@code{'mh-search-p}). -@c ------------------------- -@item mh-pack-folder-hook -Hook run by @code{mh-pack-folder} after renumbering the messages -(default: @code{nil}). -@c ------------------------- -@item mh-quit-hook -Hook run by q after quitting MH-E (default: @code{nil}). -@c ------------------------- -@item mh-refile-msg-hook -Hook run by o after marking each message for refiling (default: -@code{nil}). -@end vtable - -The following faces are available for customizing the appearance of -the MH-Folder buffer. @xref{Scan Line Formats}. - -@vtable @code -@item mh-folder-address -Recipient face. -@c ------------------------- -@item mh-folder-body -Body text face. -@c ------------------------- -@item mh-folder-cur-msg-number -Current message number face. -@c ------------------------- -@item mh-folder-date -Date face. -@c ------------------------- -@item mh-folder-deleted -Deleted message face. -@c ------------------------- -@item mh-folder-followup -@samp{Re:} face. -@c ------------------------- -@item mh-folder-msg-number -Message number face. -@c ------------------------- -@item mh-folder-refiled -Refiled message face. -@c ------------------------- -@vindex mh-scan-format-nmh -@vindex mh-scan-sent-to-me-sender-regexp -@item mh-folder-sent-to-me-hint -Fontification hint face in messages sent directly to us. The detection -of messages sent to us is governed by the scan format -@code{mh-scan-format-nmh} and regular expression -@code{mh-scan-sent-to-me-sender-regexp}. -@c ------------------------- -@vindex mh-scan-format-nmh -@vindex mh-scan-sent-to-me-sender-regexp -@item mh-folder-scan-format -Sender face in messages sent directly to us. The detection of messages -sent to us is governed by the scan format @code{mh-scan-format-nmh} -and regular expression @code{mh-scan-sent-to-me-sender-regexp}. -@c ------------------------- -@item mh-folder-subject -Subject face. -@c ------------------------- -@item mh-folder-tick -Ticked message face. -@c ------------------------- -@item mh-folder-to -@samp{To:} face. -@end vtable - -@vindex mh-folder-mode-hook - -The hook @code{mh-folder-mode-hook} is called when visiting a new -folder in MH-Folder mode. This could be used to set your own key -bindings, for example: - -@vindex mh-folder-mode-hook@r{, example} - -@smalllisp -@group -(defvar my-mh-init-done nil - "Non-nil when one-time MH-E settings made.") - -(defun my-mh-folder-mode-hook () - "Hook to set key bindings in MH-Folder mode." - (if (not my-mh-init-done) ; @r{only need to bind the keys once } - (progn - (local-set-key "//" 'my-search-msg) - (local-set-key "b" 'mh-burst-digest) ; @r{better use of @kbd{b}} - (setq my-mh-init-done t)))) - -(add-hook 'mh-folder-mode-hook 'my-mh-folder-mode-hook) - -(defun my-search-msg () - "Search for a regexp in the current message." - (interactive) ; @r{user function} - (save-window-excursion - (other-window 1) ; @r{go to next window} - (isearch-forward-regexp))) ; @r{string search; hit return} - ; @r{ when done} - -@i{Create additional key bindings via mh-folder-mode-hook} - -@end group -@end smalllisp - -@cindex @command{folder} -@cindex @command{refile} -@cindex MH commands, @command{folder} -@cindex MH commands, @command{refile} -@findex mh-refile-msg -@kindex o -@vindex mh-refile-msg-hook - -MH-E has analogies for each of the MH @command{folder} and -@command{refile} commands@footnote{See the sections -@uref{@value{MH-BOOK-HOME}/fol.html#Youfol, Your Current Folder: -folder} and @uref{@value{MH-BOOK-HOME}/fol.html#Movref, Moving and -Linking Messages: refile} in the MH book.}. To refile a message in -another folder, use the command @kbd{o} (@code{mh-refile-msg}) -(mnemonic: ``output''). You are prompted for the folder name -(@pxref{Folder Selection}). Note that this command can also be used to -create folders. If you specify a folder that does not exist, you will -be prompted to create it. The hook @code{mh-refile-msg-hook} is called -after a message is marked to be refiled. - -@findex mh-write-msg-to-file -@kindex ! - -If you are refiling several messages into the same folder, you can use -the command @kbd{!} (@code{mh-refile-or-write-again}) to repeat the -last refile or write (for the description of @kbd{>} -(@code{mh-write-msg-to-file}), @pxref{Files and Pipes}). You can use a -range in either case (for example, @kbd{C-u o 1 3 5-7 last:5 frombob -@key{RET}}, @pxref{Ranges}). - -@cindex expunging refiles and deletes -@cindex undoing refiles and deletes -@findex mh-undo -@kindex u - -If you've deleted a message or refiled it, but changed your mind, you -can cancel the action before you've executed it. Use @kbd{u} -(@code{mh-undo}) to undo a refile on or deletion of a single message. -You can also undo refiles and deletes for messages that are found in a -given range (@pxref{Ranges}). - -@findex mh-undo-folder -@kindex F u - -Alternatively, you can use @kbd{F u} (@code{mh-undo-folder}) to undo -all refiles and deletes in the current folder. - -@findex mh-execute-commands -@kindex x - -If you've marked messages to be deleted or refiled and you want to go -ahead and delete or refile the messages, use @kbd{x} -(@code{mh-execute-commands}). Many MH-E commands that may affect the -numbering of the messages (such as @kbd{F r} or @kbd{F p}) will ask if -you want to process refiles or deletes first and then either run -@kbd{x} for you or undo the pending refiles and deletes. - -@kindex x -@vindex mh-after-commands-processed-hook -@vindex mh-before-commands-processed-hook -@vindex mh-current-folder - -The command @kbd{x} runs @code{mh-before-commands-processed-hook} -before the commands are processed and -@code{mh-after-commands-processed-hook} after the commands are -processed. Variables that are useful with the former hook include -@code{mh-delete-list} and @code{mh-refile-list} which can be used to -see which changes will be made to the current folder, -@code{mh-current-folder}. Variables that are useful with the latter -hook include @code{mh-folders-changed}, which lists which folders were -affected by deletes and refiles. This list will always include the -current folder @code{mh-current-folder}. - -@findex mh-copy-msg -@kindex c -@kindex o - -If you wish to copy a message to another folder, you can use the -command @kbd{c} (@code{mh-copy-msg}) (see the @option{-link} argument -to @command{refile}(1)). Like the command @kbd{o}, this command -prompts you for the name of the target folder and you can specify a -range (@pxref{Ranges}). Note that unlike the command @kbd{o}, the copy -takes place immediately. The original copy remains in the current -folder. - -@cindex junk mail -@cindex MH-Folder mode -@cindex MH-Folder Show mode -@cindex modes, MH-Folder -@cindex modes, MH-Folder Show -@cindex spam -@findex mh-toggle-showing -@kindex t - -The command @kbd{t} (@code{mh-toggle-showing}) switches between -MH-Folder mode and MH-Folder Show mode@footnote{For you Emacs wizards, -this is implemented as an Emacs minor mode.}. MH-Folder mode turns off -the associated show buffer so that you can perform operations on the -messages quickly without reading them. This is an excellent way to -prune out your junk mail or to refile a group of messages to another -folder for later examination. - -@cindex MH-Folder mode -@cindex MH-Show mode -@cindex modes, MH-Folder -@cindex modes, MH-Show -@cindex moving between messages -@kindex t -@vindex mh-recenter-summary-flag - -When you use @kbd{t} to toggle from MH-Folder Show mode to MH-Folder -mode, the MH-Show buffer is hidden and the MH-Folder buffer is left -alone. Setting @code{mh-recenter-summary-flag} to a non-@code{nil} -value causes the toggle to display as many scan lines as possible, -with the cursor at the middle. The effect of -@code{mh-recenter-summary-flag} is rather useful, but it can be -annoying on a slow network connection. - -@findex mh-visit-folder -@kindex F v -@vindex mh-large-folder - -When you want to read the messages that you have refiled into folders, -use the command @kbd{F v} (@code{mh-visit-folder}) to visit the -folder. You are prompted for the folder name. The folder buffer will -show just unseen messages if there are any; otherwise, it will show -all the messages in the buffer as long there are fewer than -@code{mh-large-folder} messages. If there are more, then you are -prompted for a range of messages to scan. You can provide a prefix -argument in order to specify a range of messages to show when you -visit the folder (@pxref{Ranges}). In this case, regions are not used -to specify the range and @code{mh-large-folder} is ignored. Note that -this command can also be used to create folders. If you specify a -folder that does not exist, you will be prompted to create it. - -@findex mh-search -@kindex F s - -If you forget where you've refiled your messages, you can find them -using @kbd{F s} (@code{mh-search}). @xref{Searching}. - -@cindex @command{procmail} -@cindex @samp{unseen} sequence -@cindex sequence, @samp{unseen} -@cindex Unix commands, @command{procmail} -@cindex unseen messages, viewing -@findex mh-index-new-messages -@kindex F n -@vindex mh-new-messages-folders - -If you use a program such as @command{procmail} to file your incoming -mail automatically, you can display new, unseen, messages using the -command @kbd{F n} (@code{mh-index-new-messages}). All messages in the -@samp{unseen} sequence from the folders in -@code{mh-new-messages-folders} are listed. However, this list of -folders can be overridden with a prefix argument: with a prefix -argument, enter a space-separated list of folders, or nothing to -search all folders. - -@cindex @samp{tick} sequence -@cindex sequence, @samp{tick} -@cindex ticked messages, viewing -@findex mh-index-ticked-messages -@kindex F ' -@vindex mh-ticked-messages-folders - -If you have ticked messages (@pxref{Sequences}), you can display them -using the command @kbd{F '} (@code{mh-index-ticked-messages}). All -messages in the @samp{tick} sequence from the folders in -@code{mh-ticked-messages-folders} are listed. With a prefix argument, -enter a space-separated list of folders, or nothing to search all -folders. - -@findex mh-index-sequenced-messages -@kindex F q -@vindex mh-new-messages-folders - -You can display messages in any sequence with the command @kbd{F q} -(@code{mh-index-sequenced-messages}). All messages from the folders in -@code{mh-new-messages-folders} in the sequence you provide are listed. -With a prefix argument, enter a space-separated list of folders at the -prompt, or nothing to search all folders. - -@vindex mh-new-messages-folders -@vindex mh-recursive-folders-flag -@vindex mh-ticked-messages-folders - -Set the options @code{mh-new-messages-folders} and -@code{mh-ticked-messages-folders} to @samp{Inbox} to search the -@samp{+inbox} folder or @samp{All} to search all of the top level -folders. Otherwise, list the folders that should be searched with the -@samp{Choose Folders} menu item. See @code{mh-recursive-folders-flag}. - -@cindex buffers, @file{*MH-E Folders*} -@cindex @file{*MH-E Folders*} -@findex mh-kill-folder -@findex mh-list-folders -@findex mh-pack-folder -@findex mh-rescan-folder -@findex mh-sort-folder -@kindex F k -@kindex F l -@kindex F p -@kindex F r -@kindex F S - -Other commands you can perform on folders include: @kbd{F l} -(@code{mh-list-folders}), to place a listing of all the folders in -your mail directory in a buffer called @file{*MH-E Folders*} -(@pxref{Miscellaneous}); @kbd{F k} (@code{mh-kill-folder}), to remove -a folder; @kbd{F S} (@code{mh-sort-folder}), to sort the messages by -date (see @command{sortm}(1) to see how to sort by other criteria); -@kbd{F p} (@code{mh-pack-folder}), to pack a folder, removing gaps -from the numbering sequence; and @kbd{F r} (@code{mh-rescan-folder}), -to rescan the folder, which is useful to grab all messages in your -@samp{+inbox} after processing your new mail for the first time. If -you don't want to rescan the entire folder, the commands @kbd{F r} or -@kbd{F p} will accept a range (@pxref{Ranges}). - -@kindex F p -@vindex mh-pack-folder-hook - -The command @kbd{F p} runs @code{mh-pack-folder-hook} after -renumbering the messages. A variable that is useful with this hook -is @code{mh-current-folder}. - -@kindex TAB -@vindex mh-recursive-folders-flag - -By default, operations on folders work only one level at a time. Set -@code{mh-recursive-folders-flag} to non-@code{nil} to operate on all -folders. This mostly means that you'll be able to see all your folders -when you press @key{TAB} when prompted for a folder name. - -@findex mh-search-p -@kindex k -@vindex mh-kill-folder-suppress-prompt-functions - -The hook @code{mh-kill-folder-suppress-prompt-functions} is an abnormal -hook run at the beginning of the command @kbd{k}. The hook functions -are called with no arguments and should return a non-@code{nil} value to -suppress the normal prompt when you remove a folder. This is useful -for folders that are easily regenerated. The default value of -@code{mh-search-p} suppresses the prompt on folders generated by -searching. - -@sp 1 -@center @strong{NOTE} - -@quotation -Use this hook with care. If there is a bug in your hook which returns -@code{t} on @samp{+inbox} and you press @kbd{k} by accident in the -@code{+inbox} folder, you will not be happy. -@end quotation -@sp 1 - -@cindex @command{sortm} -@cindex @file{.mh_profile} -@cindex files, @file{.mh_profile} -@cindex MH commands, @command{sortm} -@cindex MH profile component, @samp{sortm} -@cindex @samp{sortm} MH profile component -@kindex F S -@vindex mh-sortm-args - -The option @code{mh-sortm-args} holds extra arguments to pass on to -the command @command{sortm}@footnote{See the section -@uref{@value{MH-BOOK-HOME}/sorsor.html, Sorting Messages: sortm} in the -MH book.} when a prefix argument is used with @kbd{F S}. Normally -default arguments to @command{sortm} are specified in the MH profile. -This option may be used to provide an alternate view. For example, -@samp{'(\"-nolimit\" \"-textfield\" \"subject\")} is a useful setting. - -@cindex exiting -@cindex quitting -@findex mh-quit -@kindex q - -When you want to quit using MH-E and go back to editing, you can use -the @kbd{q} (@code{mh-quit}) command. This buries the buffers of the -current MH-E folder and restores the buffers that were present when -you first ran @kbd{M-x mh-rmail}. It also removes any MH-E working -buffers whose name begins with @samp{ *mh-} or @file{*MH-E } -(@pxref{Miscellaneous}). You can later restore your MH-E session by -selecting the @samp{+inbox} buffer or by running @kbd{M-x mh-rmail} -again. - -@findex mh-execute-commands -@kindex q -@vindex mh-before-quit-hook -@vindex mh-before-quit-hook@r{, example} -@vindex mh-quit-hook -@vindex mh-quit-hook@r{, example} - -The two hooks @code{mh-before-quit-hook} and @code{mh-quit-hook} are -called by @kbd{q}. The former one is called before the quit occurs, so -you might use it to perform any MH-E operations; you could perform -some query and abort the quit or call @code{mh-execute-commands}, for -example. The latter is not run in an MH-E context, so you might use it -to modify the window setup. If you find that @kbd{q} buries a lot of -buffers that you would rather remove, you can use both -@code{mh-before-quit-hook} and @code{mh-quit-hook} to accomplish that. - -@smalllisp -@group -(defvar my-mh-folder-buffer-to-delete nil - "Folder buffer that is being quit.") - -(defun my-mh-before-quit-hook () - "Save folder buffer that is to be deleted." - (setq my-mh-folder-buffer-to-delete (current-buffer))) - -(defun my-mh-quit-hook () - "Kill folder buffer rather than just bury it." - (set-buffer my-mh-folder-buffer-to-delete) - (if (get-buffer mh-show-buffer) - (kill-buffer mh-show-buffer)) - (kill-buffer (current-buffer))) - -@i{Kill MH-Folder buffer instead of burying it} -@end group -@end smalllisp - -@cindex folders, renaming -@cindex renaming folders -@findex dired -@findex dired-do-rename - -You can use dired to manipulate the folders themselves. For example, I -renamed my @samp{+out} folder to the more common @samp{+outbox} by -running dired on my mail directory (@kbd{M-x dired @key{RET} ~/Mail -@key{RET}}), moving my cursor to @samp{out} and using the command -@kbd{R} (@code{dired-do-rename}). - -@node Sending Mail -@chapter Sending Mail - -@cindex sending mail -@findex mh-smail - -You can send a mail message in several ways. You can call @kbd{M-x -mh-smail} directly, or from the command line like this: - -@cindex starting from command line - -@smallexample -$ @kbd{emacs -f mh-smail} -@end smallexample - -@findex goto-address-at-point -@vindex mail-user-agent - -There are some commands that need to send a mail message, such as -@code{goto-address-at-point}. You can configure Emacs to have these -commands use MH-E by setting the option @code{mail-user-agent} to -@samp{Emacs interface to MH}. - -@cindex @samp{Message} menu -@cindex menu, @samp{Message} - -From within MH-E's MH-Folder mode, other methods of sending mail are -available as well. These can also be found in the @samp{Message} menu. - -@table @kbd -@cindex @samp{Message > Edit Message Again} menu item -@cindex menu item, @samp{Message > Edit Message Again} -@kindex e -@findex mh-edit-again -@item e -Edit a message to send it again (@code{mh-edit-again}). -@c ------------------------- -@cindex @samp{Message > Re-edit a Bounced Message} menu item -@cindex menu item, @samp{Message > Re-edit a Bounced Message} -@kindex E -@findex mh-extract-rejected-mail -@item E -Edit a message that was returned by the mail system -(@code{mh-extract-rejected-mail}). -@c ------------------------- -@cindex @samp{Message > Forward Message...} menu item -@cindex menu item, @samp{Message > Forward Message...} -@kindex f -@findex mh-forward -@item f -Forward message (@code{mh-forward}). -@c ------------------------- -@cindex @samp{Message > Reply to Message...} menu item -@cindex menu item, @samp{Message > Reply to Message...} -@kindex r -@findex mh-reply -@item r -Reply to a message (@code{mh-reply}). -@c ------------------------- -@cindex @samp{Message > Compose a New Message} menu item -@cindex menu item, @samp{Message > Compose a New Message} -@kindex s -@findex mh-send -@item s -Compose a message (@code{mh-send}). -@c ------------------------- -@cindex @samp{Message > Redistribute Message...} menu item -@cindex menu item, @samp{Message > Redistribute Message...} -@kindex M-d -@findex mh-redistribute -@item M-d -Redistribute a message (@code{mh-redistribute}). -@c ------------------------- -@findex mh-smail -@item M-x mh-smail -Compose a message with the MH mail system. -@c ------------------------- -@findex mh-smail-other-window -@item M-x mh-smail-other-window -Compose a message with the MH mail system in other window. -@end table - -@cindex @samp{mh-sending-mail} customization group -@cindex customization group, @samp{mh-sending-mail} - -In addition, several options from the @samp{mh-sending-mail} -customization group are useful when sending mail or replying to mail. -They are summarized in the following table. - -@vtable @code -@item mh-compose-forward-as-mime-flag -On means that messages are forwarded as attachments (default: -@samp{on}). -@c ------------------------- -@item mh-compose-letter-function -Hook run when starting a new draft (default: @code{nil}). -@c ------------------------- -@item mh-compose-prompt-flag -On means prompt for header fields when composing a new draft (default: -@samp{off}). -@c ------------------------- -@item mh-forward-subject-format -Format string for forwarded message subject (default: @code{"%s: -%s"}). -@c ------------------------- -@item mh-insert-x-mailer-flag -On means append an @samp{X-Mailer:} header field to the header -(default: @samp{on}). -@c ------------------------- -@item mh-redist-full-contents-flag -On means the @command{dist} command needs entire letter for -redistribution (default: @samp{off}). -@c ------------------------- -@item mh-reply-default-reply-to -Sets the person or persons to whom a reply will be sent (default: -@samp{Prompt}). -@c ------------------------- -@item mh-reply-show-message-flag -On means the MH-Show buffer is displayed using @kbd{r} -(@code{mh-reply}) (default: @samp{on}). -@end vtable - -The following hooks are available. - -@vtable @code -@item mh-annotate-msg-hook -Hook run by @code{mh-annotate-msg} after annotation (default: -@code{nil}). -@c ------------------------- -@item mh-forward-hook -Hook run by @code{mh-forward} on a forwarded letter (default: -@code{nil}). -@c ------------------------- -@item mh-letter-mode-hook -Hook run by @code{mh-letter-mode} on a new letter (default: -@code{nil}). -@end vtable - -@findex mh-annotate-msg -@vindex mh-annotate-list -@vindex mh-annotate-msg-hook -@vindex mh-current-folder - -A hook that is called whenever a message is sent and after the scan -lines and message are annotated is @code{mh-annotate-msg-hook}. Hook -functions can access the current folder name with -@code{mh-current-folder} and obtain the message numbers of the -annotated messages with @code{mh-annotate-list}. - -The rest of the functions and options introduced here are explained in -more detail in the following sections. - -@menu -* Composing:: -* Replying:: -* Forwarding:: -* Redistributing:: -* Editing Again:: -@end menu - -@node Composing -@section Composing - -@cindex @file{.emacs} -@cindex MH-Folder mode -@cindex composing mail -@cindex draft -@cindex files, @file{.emacs} -@cindex modes, MH-Folder -@cindex sending mail -@findex mh-smail -@findex mh-smail-other-window - -Outside of an MH-Folder buffer, you must call either @kbd{M-x -mh-smail} or @kbd{M-x mh-smail-other-window} to compose a new message. -The former command always creates a two-window layout with the current -buffer on top and the draft on the bottom. Use the latter command if -you would rather preserve the window layout. You may find adding the -following key bindings to @file{~/.emacs} useful: - -@smalllisp -(global-set-key "\C-xm" 'mh-smail) -(global-set-key "\C-x4m" 'mh-smail-other-window) -@end smalllisp - -@cindex draft folder -@cindex MH-Letter mode -@cindex modes, MH-Letter -@findex mh-send -@kindex m - -From within a MH-Folder buffer, you can simply use the command @kbd{m} -(@code{mh-send}). However you invoke @code{mh-send}, your letter -appears in an Emacs buffer whose mode is MH-Letter (to see what the -buffer looks like, @pxref{Sending Mail Tour}). MH-Letter mode allows -you to edit your message, to check the validity of the recipients, to -insert attachments and other messages into your message, and to send -the message. We'll go more into depth about editing a -@dfn{draft}@footnote{I highly recommend that you use a @dfn{draft -folder} so that you can edit several drafts in parallel. To do so, -create a folder named @samp{+drafts} for example, and add the profile -component @samp{Draft-Folder: drafts} (see @code{mh-profile}(5)).} (a -message you're composing) in just a moment (@pxref{Editing Drafts}). - -@vindex mh-compose-prompt-flag - -If you prefer to be prompted for the recipient and subject fields -before the MH-Letter buffer appears, turn on the option -@code{mh-compose-prompt-flag}. - -@cindex header field, @samp{X-Mailer} -@cindex @samp{X-Mailer} header field -@vindex mh-insert-x-mailer-flag - -MH-E adds an @samp{X-Mailer:} header field to the header that includes -the version of MH-E and Emacs that you are using. If you don't want to -participate in our marketing, you can turn off the option -@code{mh-insert-x-mailer-flag}. - -@cindex @command{repl} -@cindex @file{components} -@cindex MH commands, @command{repl} -@cindex MH-Letter mode -@cindex Mail mode -@cindex files, @file{components} -@cindex modes, MH-Letter -@cindex modes, Mail -@vindex mail-mode-hook -@vindex mh-letter-mode-hook -@vindex text-mode-hook - -Two hooks are provided to run commands on your freshly created draft. -The first hook, @code{mh-letter-mode-hook}, allows you to do some -processing before editing a letter@footnote{Actually, because -MH-Letter mode inherits from Mail mode, the hooks -@code{text-mode-hook} and @code{mail-mode-hook} are run (in that -order) before @code{mh-letter-mode-hook}.}. For example, you may wish -to modify the header after @command{repl} has done its work, or you -may have a complicated @file{components} file and need to tell MH-E -where the cursor should go. Here's an example of how you would use -this hook. - -@findex mh-insert-signature@r{, example} - -@smalllisp -@group -(defvar letter-mode-init-done-flag nil - "Non-nil means one-time MH-E settings have been made.") - -(defun my-mh-letter-mode-hook () - "Prepare letter for editing." - (when (not letter-mode-init-done) ; @r{only need to bind the keys once} - (local-set-key "\C-ctb" 'add-enriched-text) - (local-set-key "\C-cti" 'add-enriched-text) - (local-set-key "\C-ctf" 'add-enriched-text) - (local-set-key "\C-cts" 'add-enriched-text) - (local-set-key "\C-ctB" 'add-enriched-text) - (local-set-key "\C-ctu" 'add-enriched-text) - (local-set-key "\C-ctc" 'add-enriched-text) - (setq letter-mode-init-done t)) - (save-excursion - (goto-char (point-max)) ; @r{go to end of message to} - (mh-insert-signature))) ; @r{insert signature} - -@i{Prepare draft for editing via mh-letter-mode-hook} - -@end group -@end smalllisp - -The function, @code{add-enriched-text} is defined in the example in -@ref{Adding Attachments}. - -@vindex mh-compose-letter-function -@vindex mh-letter-mode-hook - -The second hook, a function really, is -@code{mh-compose-letter-function}. Like @code{mh-letter-mode-hook}, it -is called just before editing a new message; however, it is the last -function called before you edit your message. The consequence of this -is that you can write a function to write and send the message for -you. This function is passed three arguments: the contents of the -@samp{To:}, @samp{Subject:}, and @samp{Cc:} header fields. - -@node Replying -@section Replying to Mail - -@cindex @command{mhl} -@cindex @file{mhl.reply} -@cindex MH commands, @command{mhl} -@cindex files, @file{mhl.reply} -@cindex replying -@findex mh-reply -@kindex r - -To compose a reply to a message, use the @kbd{r} (@code{mh-reply}) -command. - -When you reply to a message, you are first prompted with @samp{Reply -to whom?}. You have several choices here. - -@quotation -@multitable @columnfractions .20 .80 -@c @headitem Response @tab Reply Goes To -@c XXX @headitem not yet supported by SourceForge's texi2pdf. -@item @b{Response} @tab @b{Reply Goes To} -@c ------------------------- -@item @kbd{from} -@tab -The person who sent the message. This is the default, so @key{RET} is -sufficient. -@c ------------------------- -@item @kbd{to} -@tab -Replies to the sender, plus all recipients in the @samp{To:} header field. -@c ------------------------- -@item @kbd{cc}@*@kbd{all} -@tab -Forms a reply to the addresses in the @samp{Mail-Followup-To:} header -field if one exists; otherwise forms a reply to the sender, plus all -recipients. -@end multitable -@end quotation - -@cindex @command{repl} -@cindex MH commands, @command{repl} -@vindex mh-reply-default-reply-to - -Depending on your answer, @command{repl}@footnote{See the section -@uref{@value{MH-BOOK-HOME}/reprep.html, Replying to Messages: repl} in -the MH book.} is given a different argument to form your reply. -Specifically, a choice of @kbd{from} or none at all runs @samp{repl --nocc all}, and a choice of @kbd{to} runs @samp{repl -cc to}. Finally, -either @kbd{cc} or @kbd{all} runs @samp{repl -cc all -nocc me}. If you -find that most of the time you specify one of these choices when you -reply to a message, you can change the option -@code{mh-reply-default-reply-to} from its default value of -@samp{Prompt} to one of the choices listed above. You can always edit -the recipients in the draft. - -@cindex @samp{repl} MH profile component -@cindex MH profile component, @samp{repl} -@cindex MH-Letter mode -@cindex MH-Show mode -@cindex draft -@cindex modes, MH-Letter -@cindex modes, MH-Show - -Two windows are then created. One window contains the message to which -you are replying in an MH-Show buffer. Your draft, in MH-Letter mode -(@pxref{Editing Drafts}), is in the other window. If the reply draft -was not one that you expected, check the things that affect the -behavior of @command{repl} which include the @samp{repl:} profile -component and the @file{replcomps} and @file{replgroupcomps} files. - -If you supply a prefix argument (as in @kbd{C-u r}), the message you -are replying to is inserted in your reply after having first been run -through @command{mhl} with the format file @file{mhl.reply}. See -@command{mhl}(1) or the section -@uref{@value{MH-BOOK-HOME}/shomes.html#Usisho, Using mhl} in the MH -book to see how you can modify the default @file{mhl.reply} file. - -@vindex mh-yank-behavior - -Alternatively, you can customize the option @code{mh-yank-behavior} -and choose one of its @samp{Automatically} variants to do the same -thing. @xref{Inserting Letter}. If you do so, the prefix argument has -no effect. - -Another way to include the message automatically in your draft is to -use @samp{repl: -filter repl.filter} in your MH profile. - -@vindex mh-reply-show-message-flag - -If you include the message automatically, you can hide the MH-Show -buffer by turning off the option @code{mh-reply-show-message-flag}. - -If you wish to customize the header or other parts of the reply draft, -please see @command{repl}(1) and @code{mh-format}(5). - -@node Forwarding -@section Forwarding Mail - -@cindex @command{forw} -@cindex draft -@cindex forwarding -@cindex MH commands, @command{forw} -@findex mh-forward -@kindex f -@vindex mh-forward-hook - -To forward a message, use the @kbd{f} (@code{mh-forward}) command. You -are prompted for the @samp{To:} and @samp{cc:} recipients. You are -given a draft to edit that looks like it would if you had run the MH -command @command{forw}@footnote{See the section -@uref{@value{MH-BOOK-HOME}/forfor.html, Forwarding Messages: forw} in -the MH book.}. You can then add some text (@pxref{Editing Drafts}). -You can forward several messages by using a range (@pxref{Ranges}). -All of the messages in the range are inserted into your draft. The -hook @code{mh-forward-hook} is called on the draft. - -@cindex @file{.mh_profile} -@cindex files, @file{.mh_profile} -@cindex MH profile component, @samp{forw} -@cindex @samp{forw} MH profile component -@vindex mh-compose-forward-as-mime-flag - -By default, the option @code{mh-compose-forward-as-mime-flag} is on -which means that the forwarded messages are included as attachments. -These are inline attachments so the forwarded message should appear in -the body of your recipient's mail program. If you would prefer to -forward your messages verbatim (as text, inline), then turn off this -option. Forwarding messages verbatim works well for short, textual -messages, but your recipient won't be able to view any non-textual -attachments that were in the forwarded message. Be aware that if you -have @samp{forw: -mime} in your MH profile, then forwarded messages -will always be included as attachments regardless of the settings of -@code{mh-compose-forward-as-mime-flag}. - -@vindex mh-forward-subject-format - -The format of the @samp{Subject:} header field for forwarded messages -is controlled by the option @code{mh-forward-subject-format}. This -option is a string which includes two escapes (@samp{%s}). The first -@samp{%s} is replaced with the sender of the original message, and the -second one is replaced with the original @samp{Subject:}. The default -value of @code{"%s: %s"} takes a message with the header: - -@smallexample -@group -To: Bill Wohler -Subject: Re: 49er football -From: Greg DesBrisay -@end group -@end smallexample - -and creates a subject header field of: - -@smallexample -Subject: Greg DesBrisay: Re: 49er football -@end smallexample - -@node Redistributing -@section Redistributing Your Mail - -@cindex @command{dist} -@cindex MH commands, @command{dist} -@cindex redistributing -@findex mh-redistribute -@kindex M-d - -The command @kbd{M-d} (@code{mh-redistribute}) is similar in function -to forwarding mail, but it does not allow you to edit the message, nor -does it add your name to the @samp{From:} header field. It appears to -the recipient as if the message had come from the original sender. -When you run this command, you are prompted for the recipients. - -@findex mh-edit-again -@kindex e - -For more information on redistributing messages, see -@command{dist}(1). Also investigate the command @kbd{e} -(@code{mh-edit-again}) for another way to redistribute messages -(@pxref{Editing Again}). - -@cindex @command{send} -@cindex MH commands, @command{send} -@vindex mh-redist-full-contents-flag - -The option @code{mh-redist-full-contents-flag} must be turned on if -@command{dist}@footnote{See the section -@uref{@value{MH-BOOK-HOME}/disdis.html, Distributing Messages with -dist} in the MH book.} requires the whole letter for redistribution, -which is the case if @command{send}@footnote{See the section -@uref{@value{MH-BOOK-HOME}/sensen.html, Sending Some Mail: comp send} -in the MH book.} is compiled with the @sc{berk} option (which many -people abhor). If you find that MH will not allow you to redistribute -a message that has been redistributed before, turn off this option. - -The hook @code{mh-annotate-msg-hook} is run after annotating the -message and scan line (@pxref{Sending Mail}). - -@node Editing Again -@section Editing Old Drafts and Bounced Messages - -@cindex @file{draft} -@cindex files, @file{draft} -@cindex re-editing drafts -@findex mh-edit-again -@kindex F v drafts -@kindex e -@kindex n - -If you don't complete a draft for one reason or another, and if the -draft buffer is no longer available, you can pick your draft up again -with @kbd{e} (@code{mh-edit-again}). If you don't use a draft -folder, your last @file{draft} file will be used. If you use draft -folders, you'll need to visit the draft folder with @kbd{F v drafts -@key{RET}}, use @kbd{n} to move to the appropriate message, and then -use @kbd{e} to prepare the message for editing. - -@kindex e - -The @kbd{e} command can also be used to take messages that were sent -to you and to send them to more people. - -@cindex Mailer-Daemon -@findex mh-extract-rejected-mail -@kindex C-c C-c -@kindex E - -Don't use @kbd{e} to re-edit a message from a @i{Mailer-Daemon} who -complained that your mail wasn't posted for some reason or another. In -this case, use @kbd{E} (@code{mh-extract-rejected-mail}) to prepare -the message for editing by removing the @i{Mailer-Daemon} envelope and -unneeded header fields. Fix whatever addressing problem you had, and -send the message again with @kbd{C-c C-c}. - -@node Editing Drafts -@chapter Editing a Draft - -@cindex @samp{Letter} menu -@cindex MH-Letter mode -@cindex draft -@cindex editing draft -@cindex menu, @samp{Letter} -@cindex modes, MH-Letter - -When you edit a message that you want to send (called a @dfn{draft} in -this case), the mode used is MH-Letter. This mode provides several -commands in addition to the normal Emacs editing commands to help you -edit your draft. These can also be found in the @samp{Letter} menu. - -@table @kbd -@kindex SPC -@findex mh-letter-complete-or-space -@item @key{SPC} -Perform completion or insert space (@code{mh-letter-complete-or-space}). -@c ------------------------- -@kindex M-TAB -@findex mh-letter-complete -@item M-@key{TAB} -Perform completion on header field or word preceding point -(@code{mh-letter-complete}). -@c ------------------------- -@kindex , @r{(comma)} -@findex mh-letter-confirm-address -@item , (comma) -Flash alias expansion (@code{mh-letter-confirm-address}). -@c ------------------------- -@kindex TAB -@findex mh-letter-next-header-field-or-indent -@item @key{TAB} -Cycle to next field (@code{mh-letter-next-header-field-or-indent}). -@c ------------------------- -@kindex S-TAB -@findex mh-letter-previous-header-field -@item S-@key{TAB} -Cycle to the previous header field -(@code{mh-letter-previous-header-field}). -@c ------------------------- -@kindex C-c ? -@findex mh-help -@item C-c ? -Display cheat sheet for the MH-E commands (@code{mh-help}). -@c ------------------------- -@cindex @samp{Letter > Send This Draft} menu item -@cindex menu item, @samp{Letter > Send This Draft} -@kindex C-c C-c -@findex mh-send-letter -@item C-c C-c -Save draft and send message (@code{mh-send-letter}). -@c ------------------------- -@kindex C-c C-d -@findex mh-insert-identity -@item C-c C-d -Insert fields specified by the given identity -(@code{mh-insert-identity}). @xref{Identities}. -@c ------------------------- -@cindex @samp{Letter > Pull in All Compositions (MH)} menu item -@cindex menu item, @samp{Letter > Pull in All Compositions (MH)} -@kindex C-c C-e -@findex mh-mh-to-mime -@item C-c C-e -Compose @sc{mime} message from MH-style directives -(@code{mh-mh-to-mime}). -@c ------------------------- -@kindex C-c C-f C-a -@kindex C-c C-f a -@findex mh-to-field -@item C-c C-f C-a -@itemx C-c C-f a -Move to @samp{Mail-Reply-To:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-b -@kindex C-c C-f b -@item C-c C-f C-b -@itemx C-c C-f b -Move to @samp{Bcc:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-c -@kindex C-c C-f c -@item C-c C-f C-c -@itemx C-c C-f c -Move to @samp{Cc:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-d -@kindex C-c C-f d -@item C-c C-f C-d -@itemx C-c C-f d -Move to @samp{Dcc:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-f -@kindex C-c C-f f -@findex mh-to-fcc -@item C-c C-f C-f -@itemx C-c C-f f -Move to @samp{Fcc:} header field (@code{mh-to-fcc}). -@c ------------------------- -@kindex C-c C-f C-l -@kindex C-c C-f l -@item C-c C-f C-l -@itemx C-c C-f l -Move to @samp{Mail-Followup-To:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-m -@kindex C-c C-f m -@item C-c C-f C-m -@itemx C-c C-f m -Move to @samp{From:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-r -@kindex C-c C-f r -@item C-c C-f C-r -@itemx C-c C-f r -Move to @samp{Reply-To:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-s -@kindex C-c C-f s -@item C-c C-f C-s -@itemx C-c C-f s -Move to @samp{Subject:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-t -@kindex C-c C-f t -@item C-c C-f C-t -@itemx C-c C-f t -Move to @samp{To:} header field (@code{mh-to-field}). -@c ------------------------- -@cindex @samp{Letter > Insert a Message...} menu item -@cindex menu item, @samp{Letter > Insert a Message...} -@kindex C-c C-i -@findex mh-insert-letter -@item C-c C-i -Insert a message (@code{mh-insert-letter}). -@c ------------------------- -@kindex C-c C-m C-e -@findex mh-mml-secure-message-encrypt -@item C-c C-m C-e -Add tag to encrypt the message (@code{mh-mml-secure-message-encrypt}). -@c ------------------------- -@cindex @samp{Letter > Compose Forward...} menu item -@cindex menu item, @samp{Letter > Compose Forward...} -@kindex C-c C-m C-f -@kindex C-c C-m f -@findex mh-compose-forward -@item C-c C-m C-f -@itemx C-c C-m f -Add tag to forward a message (@code{mh-compose-forward}). -@c ------------------------- -@cindex @samp{Letter > Compose Get File (MH)...} menu item -@cindex menu item, @samp{Letter > Compose Get File (MH)...} -@kindex C-c C-m C-g -@kindex C-c C-m g -@findex mh-mh-compose-anon-ftp -@item C-c C-m C-g -@itemx C-c C-m g -Add tag to include anonymous ftp reference to a file -(@code{mh-mh-compose-anon-ftp}). -@c ------------------------- -@cindex @samp{Letter > Compose Insertion...} menu item -@cindex menu item, @samp{Letter > Compose Insertion...} -@kindex C-c C-m C-i -@kindex C-c C-m i -@findex mh-compose-insertion -@item C-c C-m C-i -@itemx C-c C-m i -Add tag to include a file such as an image or sound -(@code{mh-compose-insertion}). -@c ------------------------- -@cindex @samp{Letter > Pull in All Compositions (MML)} menu item -@cindex menu item, @samp{Letter > Pull in All Compositions (MML)} -@kindex C-c C-m C-m -@kindex C-c C-m m -@findex mh-mml-to-mime -@item C-c C-m C-m -@itemx C-c C-m m -Compose @sc{mime} message from MML tags (@code{mh-mml-to-mime}). -@c ------------------------- -@kindex C-c C-m C-n -@kindex C-c C-m n -@findex mh-mml-unsecure-message -@item C-c C-m C-n -@itemx C-c C-m n -Remove any secure message tags (@code{mh-mml-unsecure-message}). -@c ------------------------- -@kindex C-c C-m C-s -@findex mh-mml-secure-message-sign -@item C-c C-m C-s -Add tag to sign the message (@code{mh-mml-secure-message-sign}). -@c ------------------------- -@cindex @samp{Letter > Compose Compressed tar (MH)...} menu item -@cindex menu item, @samp{Letter > Compose Compressed tar (MH)...} -@kindex C-c C-m C-t -@kindex C-c C-m t -@findex mh-mh-compose-external-compressed-tar -@item C-c C-m C-t -@itemx C-c C-m t -Add tag to include anonymous ftp reference to a compressed tar file -(@code{mh-mh-compose-external-compressed-tar}). -@c ------------------------- -@cindex @samp{Letter > Revert to Non-MIME Edit (MH)} menu item -@cindex menu item, @samp{Letter > Revert to Non-MIME Edit (MH)} -@kindex C-c C-m C-u -@kindex C-c C-m u -@findex mh-mh-to-mime-undo -@item C-c C-m C-u -@itemx C-c C-m u -Undo effects of @kbd{C-c C-e} (@code{mh-mh-to-mime-undo}). -@c ------------------------- -@kindex C-c C-m C-x -@kindex C-c C-m x -@findex mh-mh-compose-external-type -@item C-c C-m C-x -@itemx C-c C-m x -Add tag to refer to a remote file -(@code{mh-mh-compose-external-type}). -@c ------------------------- -@kindex C-c C-m e e -@findex mh-mml-secure-message-encrypt -@item C-c C-m e e -Add tag to encrypt the message (@code{mh-mml-secure-message-encrypt}). -@c ------------------------- -@kindex C-c C-m e s -@findex mh-mml-secure-message-signencrypt -@item C-c C-m e s -Add tag to encrypt and sign the message@* -(@code{mh-mml-secure-message-signencrypt}). -@c ------------------------- -@kindex C-c C-m s e -@findex mh-mml-secure-message-signencrypt -@item C-c C-m s e -Add tag to encrypt and sign the message@* -(@code{mh-mml-secure-message-signencrypt}). -@c ------------------------- -@kindex C-c C-m s s -@findex mh-mml-secure-message-sign -@item C-c C-m s s -Add tag to sign the message (@code{mh-mml-secure-message-sign}). -@c ------------------------- -@cindex @samp{Letter > Split Current Line} menu item -@cindex menu item, @samp{Letter > Split Current Line} -@kindex C-c C-o -@findex mh-open-line -@item C-c C-o -Insert a newline and leave point before it (@code{mh-open-line}). -@c ------------------------- -@cindex @samp{Letter > Kill This Draft} menu item -@cindex menu item, @samp{Letter > Kill This Draft} -@kindex C-c C-q -@findex mh-fully-kill-draft -@item C-c C-q -Quit editing and delete draft message (@code{mh-fully-kill-draft}). -@c ------------------------- -@cindex @samp{Letter > Insert Signature} menu item -@cindex menu item, @samp{Letter > Insert Signature} -@kindex C-c C-s -@findex mh-insert-signature -@item C-c C-s -Insert signature in message (@code{mh-insert-signature}). -@c ------------------------- -@kindex C-c C-t -@findex mh-letter-toggle-header-field-display -@item C-c C-t -Toggle display of header field at point -(@code{mh-letter-toggle-header-field-display}). -@c ------------------------- -@cindex @samp{Letter > Check Recipient} menu item -@cindex menu item, @samp{Letter > Check Recipient} -@kindex C-c C-w -@findex mh-check-whom -@item C-c C-w -Verify recipients, showing expansion of any aliases -(@code{mh-check-whom}). -@c ------------------------- -@cindex @samp{Letter > Yank Current Message} menu item -@cindex menu item, @samp{Letter > Yank Current Message} -@kindex C-c C-y -@findex mh-yank-cur-msg -@item C-c C-y -Insert the current message into the draft buffer -(@code{mh-yank-cur-msg}). -@c ------------------------- -@kindex C-c M-d -@findex mh-insert-auto-fields -@item C-c M-d -Insert custom fields if recipient is found in -@code{mh-auto-fields-list} (@code{mh-insert-auto-fields}). -@xref{Identities}. -@end table - -@cindex @samp{mh-letter} customization group -@cindex customization group, @samp{mh-letter} - -Several options from the @samp{mh-letter} customization group are used -while editing a draft. - -@vtable @code -@item mh-compose-insertion -Type of @sc{mime} message tags in messages (default: @samp{MML} if -available; otherwise @samp{MH}). -@c ------------------------- -@item mh-compose-skipped-header-fields -List of header fields to skip over when navigating in draft (default: -@code{'("From"} @code{"Organization"} @code{"References"} -@code{"In-Reply-To"} @code{"X-Face"} @code{"Face"} -@code{"X-Image-URL"} @code{"X-Mailer")}. -@c ------------------------- -@item mh-compose-space-does-completion-flag -On means @key{SPC} does completion in message header (default: -@samp{off}). -@c ------------------------- -@item mh-delete-yanked-msg-window-flag -On means delete any window displaying the message (default: @samp{off}). -@c ------------------------- -@item mh-extract-from-attribution-verb -Verb to use for attribution when a message is yanked by @kbd{C-c C-y} -(default: @code{"wrote:"}). -@c ------------------------- -@item mh-ins-buf-prefix -String to put before each line of a yanked or inserted message -(default: @code{"> "}). -@c ------------------------- -@item mh-letter-complete-function -Function to call when completing outside of address or folder fields -(default: @code{ispell-complete-word}). -@c ------------------------- -@item mh-letter-fill-column -Fill column to use in MH-Letter mode (default: 72). -@c ------------------------- -@item mh-mml-method-default -Default method to use in security tags (default: @samp{PGP (MIME)} if -support for it is available; otherwise @samp{None}). -@c ------------------------- -@item mh-signature-file-name -Source of user's signature (default: @code{"~/.signature"}). -@c ------------------------- -@item mh-signature-separator-flag -On means a signature separator should be inserted (default: -@samp{on}). -@c ------------------------- -@item mh-x-face-file -File containing X-Face or Face header field to insert in outgoing mail. -(default: @code{"~/.face"}). -@c ------------------------- -@item mh-yank-behavior -Controls which part of a message is yanked by @kbd{C-c C-y} (default: -@samp{Body With Attribution}). -@end vtable - -The following hooks are available. - -@vtable @code -@item mail-citation-hook -Hook for modifying a citation just inserted in the mail buffer -(default: @code{nil}). -@c ------------------------- -@item mh-before-send-letter-hook -Hook run at the beginning of the @kbd{C-c C-c} command (default: -@samp{nil}). -@c ------------------------- -@item mh-mh-to-mime-hook -Hook run on the formatted letter by @kbd{C-c C-e} (default: -@samp{nil}). -@c ------------------------- -@item mh-insert-signature-hook -Hook run by @kbd{C-c C-s} after signature has been inserted (default: -@code{nil}). -@end vtable - -The following face is available. - -@vtable @code -@item mh-letter-header-field -Editable header field value face in draft buffers. -@end vtable - -The commands and options introduced here are explained in more -detail in the following sections. - -@menu -* Editing Message:: -* Inserting Letter:: -* Inserting Messages:: -* Signature:: -* Picture:: -* Adding Attachments:: -* Sending PGP:: -* Checking Recipients:: -* Sending Message:: -* Killing Draft:: -@end menu - -@node Editing Message -@section Editing the Message - -@cindex @samp{Bcc} header field -@cindex @samp{Cc} header field -@cindex @samp{Dcc} header field -@cindex @samp{From} header field -@cindex @samp{Mail-Followup-To} header field -@cindex @samp{Mail-Reply-To} header field -@cindex @samp{Reply-To} header field -@cindex @samp{Subject} header field -@cindex @samp{To} header field -@cindex editing header -@cindex header field, @samp{Bcc} -@cindex header field, @samp{Cc} -@cindex header field, @samp{Dcc} -@cindex header field, @samp{From} -@cindex header field, @samp{Mail-Followup-To} -@cindex header field, @samp{Mail-Reply-To} -@cindex header field, @samp{Reply-To} -@cindex header field, @samp{Subject} -@cindex header field, @samp{To} -@findex mh-to-field -@kindex C-c C-f C-t -@kindex C-c C-f t - -Because the header is part of the message, you can edit the header -fields as you wish. However, several convenience commands exist to -help you create and edit them. For example, the command @kbd{C-c C-f -C-t} (@code{mh-to-field}; alternatively, @kbd{C-c C-f t}) moves the -cursor to the @samp{To:} header field, creating it if necessary. The -commands for moving to the @samp{Cc:}, @samp{Subject:}, @samp{From:}, -@samp{Reply-To:}, @samp{Mail-Reply-To:}, @samp{Mail-Followup-To}, -@samp{Bcc:}, and @samp{Dcc:} header fields are similar. - -@findex mh-to-fcc -@kindex C-c C-f C-f -@kindex C-c C-f f - -One command behaves differently from the others, namely, @kbd{C-c C-f -C-f} (@code{mh-to-fcc}; alternatively, @kbd{C-c C-f f}). This command -will prompt you for the folder name in which to file a copy of the -draft. @xref{Folder Selection}. - -@findex indent-relative -@findex mh-letter-next-header-field-or-indent -@findex mh-letter-previous-header-field -@kindex TAB -@kindex S-TAB -@vindex mh-compose-skipped-header-fields -@vindex mh-letter-header-field - -Within the header of the message, the command@* @key{TAB} -(@code{mh-letter-next-header-field-or-indent}) moves between fields -that are highlighted with the face @code{mh-letter-header-field}, -skipping those fields listed in -@code{mh-compose-skipped-header-fields}. After the last field, this -command then moves point to the message body before cycling back to -the first field. If point is already past the first line of the -message body, then this command indents by calling -@code{indent-relative} with the given prefix argument. The command -@kbd{S-@key{TAB}} (@code{mh-letter-previous-header-field}) moves -backwards between the fields and cycles to the body of the message -after the first field. Unlike the command @key{TAB}, it will always -take point to the last field from anywhere in the body. - -@cindex alias completion -@cindex completion -@cindex spell check -@findex ispell-complete-word -@findex mh-letter-complete -@findex mh-letter-complete-or-space -@findex mh-letter-confirm-address -@kindex , @r{(comma)} -@kindex SPC -@kindex M-TAB -@vindex mh-alias-flash-on-comma -@vindex mh-compose-space-does-completion-flag -@vindex mh-letter-complete-function - -If the field contains addresses (for example, @samp{To:} or -@samp{Cc:}) or folders (for example, @samp{Fcc:}) then the command -@kbd{M-@key{TAB}} (@code{mh-letter-complete}) will provide alias -completion (@pxref{Aliases}). In the body of the message, -@kbd{M-@key{TAB}} runs @code{mh-letter-complete-function} instead, -which is set to @samp{'ispell-complete-word} by default. The command -@kbd{M-@key{TAB}} (@code{mh-letter-complete}) takes a prefix argument -that is passed to the @code{mh-letter-complete-function}. In addition, -turn on the option @code{mh-compose-space-does-completion-flag} to use -the command @key{SPC} (@code{mh-letter-complete-or-space}) to perform -completion in the header as well; use a prefix argument to specify -more than one space. Addresses are separated by a comma; when you -press the comma, the command @code{mh-letter-confirm-address} flashes -the alias expansion in the minibuffer if -@code{mh-alias-flash-on-comma} is turned on. - -@c XXX Document the replacement for the inaccessible 'long argument. - -@findex mh-letter-toggle-header-field-display -@kindex C-c C-t - -Use the command @kbd{C-c C-t} -@code{mh-letter-toggle-header-field-display} to display truncated -header fields. This command is a toggle so entering it again will hide -the field. This command takes a prefix argument: if negative then the -field is hidden, if positive then the field is displayed (for example, -@kbd{C-u C-c C-t}). - -Be sure to leave a row of dashes or a blank line between the header -and the body of the message. - -@vindex mh-letter-fill-column - -The body of the message is edited as you would edit any Emacs buffer -although there are a few commands and options to assist you. You can -change the fill column in MH-Letter mode with the option -@code{mh-letter-fill-column}. By default, this option is 72 to allow -others to quote your message without line wrapping. - -@cindex filling paragraphs -@cindex paragraphs, filling -@findex fill-paragraph -@kindex M-q -@vindex mh-ins-buf-prefix - -You'll often include messages that were sent from user agents that -haven't yet realized that paragraphs consist of more than a single -line. This makes for long lines that wrap in an ugly fashion. You'll -find that @kbd{M-q} (@code{fill-paragraph}) works well even on these -quoted messages, even if they are nested, just as long as all of the -quotes match the value of @code{mh-ins-buf-prefix} (@pxref{Inserting -Letter}). For example, let's assume you have the following in your -draft: - -@smallexample -@group -> Hopefully this gives you an idea of what I'm currently doing. I'm \ -not sure yet whether I'm completely satisfied with my setup, but \ -it's worked okay for me so far. -@end group -@end smallexample - -Running @kbd{M-q} on this paragraph produces: - -@smallexample -@group -> Hopefully this gives you an idea of what I'm currently doing. I'm not -> sure yet whether I'm completely satisfied with my setup, but it's -> worked okay for me so far. -@end group -@end smallexample - -@findex mh-open-line -@findex open-line -@kindex C-c C-o -@kindex C-o - -The command @kbd{C-c C-o} (@code{mh-open-line}) is similar to the -command @kbd{C-o} (@code{open-line}) in that it inserts a newline -after point. It differs in that it also inserts the right number of -quoting characters and spaces so that the next line begins in the same -column as it was. This is useful when breaking up paragraphs in -replies. For example, if this command was used when point was after -the first period in the paragraph above, the result would be this: - -@smallexample -@group -> Hopefully this gives you an idea of what I'm currently doing. - -> I'm not -> sure yet whether I'm completely satisfied with my setup, but it's -> worked okay for me so far. -@end group -@end smallexample - -@node Inserting Letter -@section Inserting Letter to Which You're Replying - -@cindex inserting messages -@cindex replying to messages -@cindex yanking messages -@findex mh-yank-cur-msg -@kindex C-c C-y -@vindex mh-ins-buf-prefix - -It is often useful to insert a snippet of text from a letter that -someone mailed to provide some context for your reply. The command -@kbd{C-c C-y} (@code{mh-yank-cur-msg}) does this by adding an -attribution, yanking a portion of text from the message to which -you're replying, and inserting @code{mh-ins-buf-prefix} (@samp{> }) -before each line. - -@smallexample -@group -Michael W Thelen wrote: - -> Hopefully this gives you an idea of what I'm currently doing. I'm not -> sure yet whether I'm completely satisfied with my setup, but it's -> worked okay for me so far. -@end group -@end smallexample - -@vindex mh-extract-from-attribution-verb - -The attribution consists of the sender's name and email address -followed by the content of the option -@code{mh-extract-from-attribution-verb}. This option can be set to -@samp{wrote:}, @samp{a écrit:}, and @samp{schrieb:}. You can also use -the @samp{Custom String} menu item to enter your own verb. - -@vindex mail-citation-hook -@vindex mh-ins-buf-prefix -@vindex mh-yank-behavior - -The prefix @code{"> "} is the default setting for the option -@code{mh-ins-buf-prefix}. I suggest that you not modify this option -since it is used by many mailers and news readers: messages are far -easier to read if several included messages have all been indented by -the same string. This prefix is not inserted if you use one of the -supercite flavors of @code{mh-yank-behavior} or you have added a -@code{mail-citation-hook} as described below. - -@vindex mh-delete-yanked-msg-window-flag - -You can also turn on the @code{mh-delete-yanked-msg-window-flag} -option to delete the window containing the original message after -yanking it to make more room on your screen for your reply. - -@cindex Emacs, packages, @samp{supercite} -@cindex @samp{supercite} package -@kindex r -@vindex mail-citation-hook -@vindex mh-yank-behavior - -You can control how the message to which you are replying is yanked -into your reply using @code{mh-yank-behavior}. To include the entire -message, including the entire header, use @samp{Body and -Header}@footnote{If you'd rather have the header cleaned up, use -@kbd{C-u r} instead of @kbd{r} when replying -(@pxref{Replying}).}@footnote{In the past you would use this setting -and set @code{mail-citation-hook} to @samp{supercite}, but this usage -is now deprecated in favor of the @samp{Invoke supercite} setting.}. -Use @samp{Body} to yank just the body without the header. To yank only -the portion of the message following the point, set this option to -@samp{Below Point}. - -Choose @samp{Invoke supercite}@footnote{@emph{Supercite} is a -full-bodied, full-featured, citation package that comes standard with -Emacs.} to pass the entire message and header through supercite. - -@vindex mh-extract-from-attribution-verb - -If the @samp{Body With Attribution} setting is used, then the message -minus the header is yanked and a simple attribution line is added at -the top using the value of the option -@code{mh-extract-from-attribution-verb}. This is the default. - -@kindex C-c C-y -@vindex mh-delete-yanked-msg-window-flag - -If the @samp{Invoke supercite} or @samp{Body With Attribution} -settings are used, the @samp{-noformat} argument is passed to the -@command{repl} program to override a @samp{-filter} or @samp{-format} -argument. These settings also have @samp{Automatically} variants that -perform the action automatically when you reply so that you don't need -to use @kbd{C-c C-y} at all. Note that this automatic action is only -performed if the show buffer matches the message being replied to. -People who use the automatic variants tend to turn on the option -@code{mh-delete-yanked-msg-window-flag} as well so that the show -window is never displayed. - -@vindex mh-yank-behavior - -If the show buffer has a region, the option @code{mh-yank-behavior} is -ignored unless its value is one of @samp{Attribution} variants in -which case the attribution is added to the yanked region. - -@findex trivial-cite -@vindex mail-citation-hook -@vindex mh-ins-buf-prefix -@vindex mh-yank-behavior - -If this isn't enough, you can gain full control over the appearance of -the included text by setting @code{mail-citation-hook} to a function -that modifies it. This hook is ignored if the option -@code{mh-yank-behavior} is set to one of the supercite flavors. -Otherwise, this option controls how much of the message is passed to -the hook. The function can find the citation between point and mark -and it should leave point and mark around the modified citation text -for the next hook function. The standard prefix -@code{mh-ins-buf-prefix} is not added if this hook is set. - -@cindex Emacs, packages, @samp{trivial-cite} -@cindex @samp{trivial-cite} package -@vindex mh-yank-behavior - -For example, if you use the hook function -@uref{https://www.emacswiki.org/emacs/TrivialCite, -@code{trivial-cite}} (which is NOT part of Emacs), set -@code{mh-yank-behavior} to @samp{Body and Header}. - -@node Inserting Messages -@section Inserting Messages - -@cindex inserting messages -@findex mh-insert-letter -@findex mh-yank-behavior -@kindex C-c C-i -@vindex mh-ins-buf-prefix -@vindex mh-invisible-header-fields-compiled -@vindex mh-yank-behavior - -Messages can be inserted with @kbd{C-c C-i} (@code{mh-insert-letter}). -This command prompts you for the folder and message number, which -defaults to the current message in that folder. It then inserts the -messages, indented by @code{mh-ins-buf-prefix} (@samp{> }) unless -@code{mh-yank-behavior} is set to one of the supercite flavors in -which case supercite is used to format the message. Certain -undesirable header fields (see -@code{mh-invisible-header-fields-compiled}) are removed before -insertion. - -If given a prefix argument (like @kbd{C-u C-c C-i}), the header is -left intact, the message is not indented, and @samp{> } is not -inserted before each line. This command leaves the mark before the -letter and point after it. - -@node Signature -@section Inserting Your Signature - -@cindex signature -@findex mh-insert-signature -@kindex C-c C-s - -You can insert your signature at the current cursor location with the -command @kbd{C-c C-s} (@code{mh-insert-signature}). - -@cindex files, @file{.signature} -@cindex @file{.signature} -@cindex vCard -@vindex mh-signature-file-name - -By default, the text of your signature is taken from the file -@file{~/.signature}. You can read from other sources by changing the -option @code{mh-signature-file-name}. This file may contain a -@dfn{vCard} in which case an attachment is added with the vCard. - -@findex mh-signature-separator-p -@vindex mh-signature-file-name -@vindex mh-signature-separator -@vindex mh-signature-separator-regexp - -The option @code{mh-signature-file-name} may also be a symbol, in -which case that function is called. You may not want a signature -separator to be added for you; instead you may want to insert one -yourself. Options that you may find useful to do this include -@code{mh-signature-separator} (when inserting a signature separator) -and @code{mh-signature-separator-regexp} (for finding said separator). -The function @code{mh-signature-separator-p}, which reports @code{t} -if the buffer contains a separator, may be useful as well. - -@cindex signature separator -@vindex mh-signature-separator-flag - -A signature separator (@code{"-- "}) will be added if the signature -block does not contain one and @code{mh-signature-separator-flag} is -on. It is not recommended that you change this option since various -mail user agents, including MH-E, use the separator to present the -signature differently, and to suppress the signature when replying or -yanking a letter into a draft. - -@vindex mh-insert-signature-hook -@vindex mh-signature-file-name - -The hook @code{mh-insert-signature-hook} is run after the signature is -inserted. Hook functions may access the actual name of the file or the -function used to insert the signature with -@code{mh-signature-file-name}. - -The signature can also be inserted using Identities. -@xref{Identities}. - -@node Picture -@section Inserting Your Picture - -@cindex @file{.face} -@cindex files, @file{.face} -@vindex mh-x-face-file - -You can insert your picture in the header of your mail message so that -recipients see your face in the @samp{From:} header field if their -mail user agent is sophisticated enough. In MH-E, this is done by -placing your image in the file named by the option -@code{mh-x-face-file} which is @file{~/.face} by default. - -@cindex @samp{Face} header field -@cindex @samp{X-Face} header field -@cindex @samp{X-Image-URL} header field -@cindex header field, @samp{Face} -@cindex header field, @samp{X-Face} -@cindex header field, @samp{X-Image-URL} - -If the file starts with either of the strings @samp{X-Face:}, -@samp{Face:} or @samp{X-Image-URL:} then the contents are added to the -message header verbatim. Otherwise it is assumed that the file -contains the value of the @samp{X-Face:} header field. - -@cindex @command{compface} -@cindex Unix commands, @command{compface} - -The @samp{X-Face:} header field, which is a low-resolution, black and -white image, can be generated using the -@uref{ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.Z, -@command{compface}} command. The @uref{https://www.dairiki.org/xface/, -@cite{Online X-Face Converter}} is a useful resource for quick -conversion of images into @samp{X-Face:} header fields. - -Use the @uref{https://quimby.gnus.org/circus/face/make-face, -@command{make-face}} script to convert a JPEG image to the higher -resolution, color, @samp{Face:} header field. - -The URL of any image can be used for the @samp{X-Image-URL:} field and -no processing of the image is required. - -@vindex mh-x-face-file - -To prevent the setting of any of these header fields, either set -@code{mh-x-face-file} to @code{nil}, or simply ensure that the file -defined by this option doesn't exist. - -@xref{Viewing}, to see how these header fields are displayed in MH-E. - -@node Adding Attachments -@section Adding Attachments - -@cindex @command{mhbuild} -@cindex @command{mhn} -@cindex MH commands, @command{mhbuild} -@cindex MH commands, @command{mhn} -@cindex MIME -@cindex multimedia mail - -MH-E has the capability to create multimedia messages. It uses the -@sc{mime} (Multipurpose Internet Mail Extensions) -protocol@footnote{@sc{mime} is defined in -@uref{https://www.rfc-editor.org/rfc/rfc2045.txt, RFC 2045}.} The -@sc{mime} protocol allows you to incorporate images, sound, video, -binary files, and even commands that fetch a file with @samp{ftp} when -your recipient reads the message! - -@kindex C-c C-m - -If you were to create a multimedia message with plain MH commands, you -would insert @command{mhbuild} or @command{mhn} directives (henceforth -called @dfn{MH-style directives} into your draft and use the -@command{mhbuild} command in nmh or @command{mhn} command in MH and -GNU mailutils to expand them. MH-E works in much the same way, -although it provides a handful of commands prefixed with @kbd{C-c C-m} -to insert the directives so you don't need to remember the syntax of -them. Remember: you can always add MH-style directives by -hand@footnote{See the section -@uref{@value{MH-BOOK-HOME}/usimim.html#SeMIMa, Sending MIME Mail} in -the MH book.}. - -@cindex MIME Meta Language (MML) -@cindex MML -@vindex mh-compose-insertion - -In addition to MH-style directives, MH-E also supports MML (@sc{mime} -Meta Language) tags@footnote{ -@ifinfo -@c Although the third argument should default to the -@c first, makeinfo goes to the wrong Info file without it being -@c different--it seems to be getting our own Composing node. -@xref{Composing,,Composing with MML,emacs-mime}. -@end ifinfo -@ifnotinfo -See the section Composing in -@uref{https://www.gnus.org/manual/emacs-mime.html, @cite{The Emacs MIME -Manual}}. -@end ifnotinfo -}. The option @code{mh-compose-insertion} can be used to choose -between them. By default, this option is set to @samp{MML} if it is -supported since it provides a lot more functionality. This option can -also be set to @samp{MH} if MH-style directives are preferred. - -@cindex media types -@cindex MIME, media types - -The MH-E @sc{mime} commands require a @dfn{media type} for each body -part or attachment. For example, a PDF document is of type -@samp{application/pdf} and an HTML document is of type -@samp{text/html}. Some commands fill in the media type for you, -whereas others require you to enter one. - -@cindex @command{file} -@cindex @file{/etc/mime.types} -@cindex files, @file{/etc/mime.types} -@cindex Unix commands, @command{file} -@findex mailcap-mime-types - -In the cases where MH-E can do so, it will determine the media type -automatically. It uses the @command{file} command to do this. Failing -that, the Emacs function @code{mailcap-mime-types} is used to provide -a list from which to choose. This function usually reads the file -@file{/etc/mime.types}. - -Whether the media type is chosen automatically, or you choose it from -a list, use the type that seems to match best the file that you are -including. In the case of binaries, the media type -@samp{application/x-executable} can be useful. If you can't find an -appropriate media type, use @samp{text/plain} for text messages and -@samp{application/octet-stream} for everything else. - -@cindex content description -@cindex MIME, content description - -You are also sometimes asked for a @dfn{content description}. This is -simply an optional brief phrase, in your own words, that describes the -object. If you don't care to enter a content description, just press -return and none will be included; however, a reader may skip over -multimedia fields unless the content description is compelling. - -You can also create your own @sc{mime} body parts. In the following -example, I describe how you can create and edit a @samp{text/enriched} -body part to liven up your plain text messages with boldface, -underlining, and italics. I include an Emacs function which inserts -enriched text tags. - -@smalllisp -@group -(defvar enriched-text-types '(("b" . "bold") ("i" . "italic") - ("u" . "underline") - ("s" . "smaller") ("B" . "bigger") - ("f" . "fixed") - ("c" . "center")) - "Alist of (final-character . tag) choices for add-enriched-text. -Additional types can be found in RFC 1563.") - -(defun add-enriched-text (begin end) - "Add enriched text tags around region. -The tag used comes from the list enriched-text-types and is -specified by the last keystroke of the command. When called from Lisp, -arguments are BEGIN and END@." - (interactive "r") - ;; @r{Set type to the tag indicated by the last keystroke.} - (let ((type (cdr (assoc (char-to-string (logior last-input-char ?@w{`})) - enriched-text-types)))) - (save-restriction ; @r{restores state from narrow-to-region} - (narrow-to-region begin end) ; @r{narrow view to region} - (goto-char (point-min)) ; @r{move to beginning of text} - (insert "<" type ">") ; @r{insert beginning tag} - (goto-char (point-max)) ; @r{move to end of text} - (insert "")))) ; @r{insert terminating tag} -@i{Emacs function for entering enriched text} - -@end group -@end smalllisp - -To use the function @code{add-enriched-text}, first add it to -@file{~/.emacs} and create key bindings for it (@pxref{Composing}). - -Then, in your plain text message, set the mark with @kbd{C-@@} or -@kbd{C-@key{SPC}}, type in the text to be highlighted, and type @kbd{C-c t -b}. This adds @samp{} where you set the mark and adds -@samp{} at the location of your cursor, giving you something -like: @samp{You should be very}. - -Before sending this message, use @kbd{C-c C-m C-m} -(@code{mh-mml-to-mime})@footnote{Use @kbd{C-c C-e} -(@code{mh-mh-to-mime}) if you're using MH-style directives.} to add -MIME header fields. Then replace @samp{text/plain} with -@samp{text/enriched} in the @samp{Content-Type:} header field. - -You may also be interested in investigating @code{sgml-mode}. - -@subheading Including Files - -@cindex attachments, inserting -@cindex images -@cindex MIME, images -@cindex MIME, sound -@cindex MIME, video -@cindex sound -@cindex video -@findex mh-compose-insertion -@kindex C-c C-m C-i -@kindex C-c C-m i -@vindex mh-compose-insertion - -Binaries, images, sound, and video can be inserted in your message -with the command @kbd{C-c C-m C-i} (@code{mh-compose-insertion}). You -are prompted for the filename containing the object, the media type if -it cannot be determined automatically, and a content description. If -you're using MH-style directives, you will also be prompted for -additional attributes. - -@subheading Forwarding Multimedia Messages - -@findex mh-compose-forward -@kindex C-c C-m C-f -@kindex C-c C-m f - -Mail may be forwarded with @sc{mime} using the command @kbd{C-c C-m -C-f} (@code{mh-compose-forward}). You are prompted for a content -description, the name of the folder in which the messages to forward -are located, and a range of messages, which defaults to the current -message in that folder. @xref{Ranges}. - -@subheading Including an FTP Reference - -@cindex @command{ftp} -@cindex MIME, @command{ftp} -@cindex Unix commands, @command{ftp} -@findex mh-mh-compose-anon-ftp -@kindex C-c C-m C-g -@kindex C-c C-m g - -You can have your message initiate an @command{ftp} transfer when the -recipient reads the message. To do this, use the command @kbd{C-c C-m -C-g} (@code{mh-mh-compose-anon-ftp}). You are prompted for the remote -host and filename, the media type, and the content description. - -@subheading Including tar Files - -@cindex @command{ftp} -@cindex @command{tar} -@cindex MIME, @command{ftp} -@cindex MIME, @command{tar} -@cindex Unix commands, @command{ftp} -@cindex Unix commands, @command{tar} -@findex mh-mh-compose-anon-ftp -@findex mh-mh-compose-external-compressed-tar -@kindex C-c C-m C-g -@kindex C-c C-m C-t -@kindex C-c C-m t - -If the remote file is a compressed tar file, you can use @kbd{C-c C-m -C-t} (@code{mh-mh-compose-external-compressed-tar}). Then, in addition -to retrieving the file via anonymous @emph{ftp} as per the command -@kbd{C-c C-m C-g} (@code{mh-mh-compose-anon-ftp}), the file will also -be uncompressed and untarred. You are prompted for the remote host and -filename and the content description. - -@subheading Including Other External Files - -@findex mh-mh-compose-external-type -@kindex C-c C-m C-x -@kindex C-c C-m x - -The command @kbd{C-c C-m C-x} (@code{mh-mh-compose-external-type}) is -a general utility for referencing external files. In fact, all of the -other commands that insert tags to access external files call this -command. You are prompted for the access type, remote host and -filename, and content type. If you provide a prefix argument, you are -also prompted for a content description, attributes, parameters, and a -comment. - -@subheading Previewing Multimedia Messages - -When you are finished editing a @sc{mime} message, it might look like this: - -@cartouche -@smallexample -3 t08/24 root received fax files on Wed Aug 24 11:00: -4+t08/24 To:wohler Test< -<#/part> ---:** @{draft@} All L8 (MH-Letter)---------------------------------- - -@end smallexample -@end cartouche -@i{MH-E @sc{mime} draft} - -@findex mh-mml-to-mime -@kindex C-c C-m C-m -@kindex C-c C-m m - -Typically, you send a message with attachments just like any other -message (@pxref{Sending Message}). - -@findex mh-mml-to-mime -@kindex C-c C-m C-m - -However, you may take a sneak preview of the @sc{mime} encoding if you -wish by running the command @kbd{C-c C-m C-m} (@code{mh-mml-to-mime}). -The following screen shows the @sc{mime} encoding specified by the -tags. You can see why mail user agents are usually built to hide these -details from the user. - -@cartouche -@smallexample -To: wohler -cc: -Subject: Test of MIME -X-Mailer: MH-E 8.1; nmh 1.1; GNU Emacs 23.1 -MIME-Version: 1.0 -Content-Type: multipart/mixed; boundary="=-=-=" --------- ---=-=-= - -Here is the SETI@@Home logo: - - ---=-=-= -Content-Type: image/x-xpm -Content-Disposition: inline; filename=setiathome.xpm -Content-Transfer-Encoding: base64 -Content-Description: SETI@@home logo - -LyogWFBNICovCnN0YXRpYyBjaGFyICogc2V0aWF0aG9tZV94cG1bXSA9IHsKIjQ1IDQ1IDc2N ---:-- @{draft@} Top L1 (MH-Letter)---------------------------------- - -@end smallexample -@end cartouche -@i{MH-E @sc{mime} draft ready to send} - -@cindex undo effects of @code{mh-mml-to-mime} - -This action can be undone by running @kbd{C-_} (@code{undo}). - -@cindex @command{mhbuild} -@cindex @command{mhn} -@cindex MH commands, @command{mhbuild} -@cindex MH commands, @command{mhn} -@cindex undo effects of @code{mh-mh-to-mime} -@findex mh-mh-to-mime -@findex mh-mh-to-mime-undo -@kindex C-c C-e -@kindex C-c C-m C-m -@kindex C-c C-m C-u -@kindex C-c C-m u - -If you're using MH-style directives, use @kbd{C-c C-e} -(@code{mh-mh-to-mime}) instead of @kbd{C-c C-m C-m}. This runs the -command @command{mhbuild} (@command{mhn}) on the message which expands -the tags@footnote{See the section -@uref{@value{MH-BOOK-HOME}/usimim.html#SeMIMa, Sending MIME Mail} in -the MH book.}. This action can be undone by running @kbd{C-c C-m C-u} -(@code{mh-mh-to-mime-undo}), which works by reverting to a backup -file. You are prompted to confirm this action, but you can avoid the -confirmation by adding an argument (for example, @kbd{C-u C-c C-m -C-u}). - -@kindex C-c C-e -@vindex mh-mh-to-mime-args - -If you wish to pass additional arguments to @command{mhbuild} -(@command{mhn}) to affect how it builds your message, use the option -@code{mh-mh-to-mime-args}. For example, you can build a consistency -check into the message by setting @code{mh-mh-to-mime-args} to -@samp{-check}. The recipient of your message can then run -@samp{mhbuild -check} on the message---@command{mhbuild} -(@command{mhn}) will complain if the message has been corrupted on the -way. The command @kbd{C-c C-e} only consults this option when given a -prefix argument (as in @kbd{C-u C-c C-e}). - -@kindex C-c C-e -@vindex mh-mh-to-mime-hook - -The hook @code{mh-mh-to-mime-hook} is called after the message has -been formatted by @kbd{C-c C-e}. - -@node Sending PGP -@section Signing and Encrypting Messages - -@cindex signing messages -@cindex encrypting messages -@cindex RFC 3156 - -MH-E can sign and encrypt messages as defined in -@uref{https://www.rfc-editor.org/rfc/rfc3156.txt, RFC 3156}. If you -should choose to sign or encrypt your message, use one of the -following commands to do so any time before sending your message. - -@findex mh-mml-secure-message-encrypt -@findex mh-mml-secure-message-sign -@findex mh-mml-secure-message-signencrypt -@kindex C-c C-m C-e -@kindex C-c C-m C-s -@kindex C-c C-m e e -@kindex C-c C-m e s -@kindex C-c C-m s e -@kindex C-c C-m s s - -The command @kbd{C-c C-m C-s} (@code{mh-mml-secure-message-sign}) -inserts the following tag: - -@smallexample -<#secure method=pgpmime mode=sign> -@end smallexample - -This is used to sign your message digitally. Likewise, the command -@kbd{C-c C-m C-e} (@code{mh-mml-secure-message-encrypt}) inserts the -following tag: - -@smallexample -<#secure method=pgpmime mode=encrypt> -@end smallexample - -This is used to encrypt your message. Finally, the command @kbd{C-c -C-m s e} (@code{mh-mml-secure-message-signencrypt}) inserts the -following tag: - -@smallexample -<#secure method=pgpmime mode=signencrypt> -@end smallexample - -@findex mh-mml-unsecure-message -@kindex C-c C-m C-n -@kindex C-c C-m n -@vindex mh-mml-method-default - -This is used to sign and encrypt your message. In each of these cases, -a proper multipart message is created for you when you send the -message. Use the command @kbd{C-c C-m C-n} -(@code{mh-mml-unsecure-message}) to remove these tags. Use a prefix -argument (as in @kbd{C-u C-c C-m s e}) to be prompted for one of the -possible security methods (see @code{mh-mml-method-default}). - -@vindex mh-mml-method-default - -The option @code{mh-mml-method-default} is used to select between a -variety of mail security mechanisms. The default is @samp{PGP (MIME)} -if it is supported; otherwise, the default is @samp{None}. Other -mechanisms include vanilla @samp{PGP} and @samp{S/MIME}. - -@node Checking Recipients -@section Checking Recipients - -@cindex @file{*MH-E Recipients*} -@cindex @command{whom} -@cindex MH commands, @command{whom} -@cindex buffers, @file{*MH-E Recipients*} -@cindex checking recipients -@cindex recipients, checking -@findex mh-check-whom -@kindex C-c C-w - -The command @kbd{C-c C-w} (@code{mh-check-whom}) expands aliases so -you can check the actual address(es) in the alias. A new buffer named -@file{*MH-E Recipients*} is created with the output of @command{whom} -(@pxref{Miscellaneous})@footnote{See the section -@uref{@value{MH-BOOK-HOME}/senove.html#WhaPro, What now?---and the -whatnow Program} in the MH book.}. - -@node Sending Message -@section Sending a Message - -@cindex buffers, @file{*MH-E Mail Delivery*} -@cindex @file{*MH-E Mail Delivery*} -@cindex sending mail -@findex mh-send-letter -@kindex C-c C-c - -When you are all through editing a message, you send it with the -command @kbd{C-c C-c} (@code{mh-send-letter}). You can give a prefix -argument (as in @kbd{C-u C-c C-c}) to monitor the first stage of the -delivery; this output can be found in a buffer called @file{*MH-E Mail -Delivery*} (@pxref{Miscellaneous}). - -@cindex sending mail -@cindex spell check -@findex ispell-message -@kindex C-c C-c -@vindex mh-before-send-letter-hook - -The hook @code{mh-before-send-letter-hook} is run at the beginning of -the command @kbd{C-c C-c}. For example, if you want to check your -spelling in your message before sending, add the function -@code{ispell-message}. - -@cindex @command{send} -@cindex MH commands, @command{send} -@vindex mh-send-prog - -In case the MH @command{send} program@footnote{See the section -@uref{@value{MH-BOOK-HOME}/sensen.html, Sending Some Mail: comp send} -in the MH book.} is installed under a different name, use -@code{mh-send-prog} to tell MH-E the name. - -The hook @code{mh-annotate-msg-hook} is run after annotating the -message and scan line (@pxref{Sending Mail}). - -@node Killing Draft -@section Killing the Draft - -@cindex killing draft -@findex kill-buffer -@findex mh-fully-kill-draft -@kindex C-c C-q -@kindex C-x k - -If for some reason you are not happy with the draft, you can use the -command @kbd{C-c C-q} (@code{mh-fully-kill-draft}) to kill the draft -buffer and delete the draft message. Use the command @kbd{C-x k} -(@code{kill-buffer}) if you don't want to delete the draft message. - -@node Aliases -@chapter Aliases - -@cindex aliases - -MH aliases are used in the same way in MH-E as they are in MH@. Any -alias listed as a recipient will be expanded when the message is sent. -This chapter discusses other things you can do with aliases in MH-E. - -@cindex MH-Letter mode -@cindex modes, MH-Letter - -The following commands are available in MH-Letter mode with the -exception of @code{mh-alias-reload} which can be called from anywhere. - -@table @kbd -@kindex SPC -@findex mh-letter-complete-or-space -@item @key{SPC} -Perform completion or insert space (@code{mh-letter-complete-or-space}). -@c ------------------------- -@kindex M-TAB -@findex mh-letter-complete -@item M-@key{TAB} -Perform completion on header field or word preceding point -(@code{mh-letter-complete}). -@c ------------------------- -@findex mh-alias-apropos -@item mh-alias-apropos -Show all aliases or addresses that match a regular expression. -@c ------------------------- -@findex mh-alias-grab-from-field -@item mh-alias-grab-from-field -Add alias for the sender of the current message -@c ------------------------- -@findex mh-alias-reload -@item mh-alias-reload -Reload MH aliases. -@end table - -@cindex @samp{mh-alias} customization group -@cindex customization group, @samp{mh-alias} - -The @samp{mh-alias} customization group contains options associated -with aliases. - -@vtable @code -@item mh-alias-completion-ignore-case-flag -On means don't consider case significant in MH alias completion -(default: @samp{on}). -@c ------------------------- -@item mh-alias-expand-aliases-flag -On means to expand aliases entered in the minibuffer (default: -@samp{off}). -@c ------------------------- -@item mh-alias-flash-on-comma -Specify whether to flash address or warn on translation (default: @samp{Flash -but Don't Warn If No Alias}). -@c ------------------------- -@item mh-alias-insert-file -Filename used to store a new MH-E alias (default: @samp{Use Aliasfile -Profile Component}). -@c ------------------------- -@item mh-alias-insertion-location -Specifies where new aliases are entered in alias files (default: -@samp{Alphabetical}). -@c ------------------------- -@item mh-alias-local-users -If @samp{on}, local users are added to alias completion (default: -@samp{on}). -@c ------------------------- -@item mh-alias-local-users-prefix -String prefixed to the real names of users from the password file -(default: @code{"local."}. -@c ------------------------- -@item mh-alias-passwd-gecos-comma-separator-flag -On means the GECOS field in the password file uses a comma separator -(default: @samp{on}). -@end vtable - -The following hook is available. - -@vtable @code -@item mh-alias-reloaded-hook -Hook run by @code{mh-alias-reload} after loading aliases (default: -@code{nil}). -@end vtable - -@subheading Adding Addresses to Draft - -You can use aliases when you are adding recipients to a message. - -@findex minibuffer-complete -@kindex TAB -@vindex mh-alias-expand-aliases-flag -@vindex mh-compose-prompt-flag - -In order to use minibuffer prompting for recipients and the subject -line in the minibuffer, turn on the option -@code{mh-compose-prompt-flag} (@pxref{Composing}), and use the -@key{TAB} (@code{minibuffer-complete}) command to complete aliases -(and optionally local logins) when prompted for the recipients. Turn -on the option @code{mh-alias-expand-aliases-flag} if you want these -aliases to be expanded to their respective addresses in the draft. - -@findex mh-letter-complete -@findex mh-letter-complete-or-space -@kindex SPC -@kindex M-TAB - -Otherwise, you can complete aliases in the header of the draft with -@kbd{M-@key{TAB}} (@code{mh-letter-complete}) or @key{SPC} -(@code{mh-letter-complete-or-space}). - -@vindex mh-alias-completion-ignore-case-flag - -As MH ignores case in the aliases, so too does MH-E@. However, you may -turn off the option @code{mh-alias-completion-ignore-case-flag} to -make case significant which can be used to segregate completion of -your aliases. You might use uppercase for mailing lists and lowercase -for people. For example, you might have: - -@smallexample -mark.baushke: Mark Baushke -MH-E: MH-E Mailing List -@end smallexample - -When this option is turned off, if you were to type @kbd{M} in the -@samp{To:} field and then @kbd{M-@key{TAB}}, then you'd get the list; -if you started with @kbd{m} and then entered @kbd{M-@key{TAB}}, then -you'd get Mark's address. Note that this option affects completion -only. If you were to enter @kbd{Mark.Baushke}, it would still be -identified with your @samp{mark.baushke} alias. - -@findex mh-alias-minibuffer-confirm-address -@findex mh-letter-confirm-address -@vindex mh-alias-flash-on-comma -@vindex mh-compose-prompt-flag - -To verify that the alias you've entered is valid, the alias will be -displayed in the minibuffer when you type a comma -(@code{mh-letter-confirm-address} or -@code{mh-alias-minibuffer-confirm-address} if the option -@code{mh-compose-prompt-flag} is turned on). @xref{Composing}. This -behavior can be controlled with the option -@code{mh-alias-flash-on-comma} which provides three choices: -@samp{Flash but Don't Warn If No Alias}, @samp{Flash and Warn If No -Alias}, and @samp{Don't Flash Nor Warn If No Alias}. - -For another way to verify the alias expansion, see @ref{Checking -Recipients}. - -@subheading Loading Aliases - -@cindex @command{ali} -@cindex @file{/etc/nmh/MailAliases} -@cindex @samp{Aliasfile} MH profile component -@cindex MH commands, @command{ali} -@cindex MH profile component, @samp{Aliasfile} -@cindex files, @file{/etc/nmh/MailAliases} - -MH-E loads aliases for completion and folder name hints from various -places. It uses the MH command @command{ali}@footnote{See the section -@uref{@value{MH-BOOK-HOME}/mh.html, MH Aliases} in the MH book.} to -read aliases from the files listed in the profile component -@samp{Aliasfile:} as well as system-wide aliases (for example, -@file{/etc/nmh/MailAliases}). - -@cindex @file{/etc/passwd} -@cindex files, @file{/etc/passwd} - -In addition, aliases are created from @file{/etc/passwd} entries with -a user ID larger than a magical number, typically 200. This can be a -handy tool on a machine where you and co-workers exchange messages. -These aliases have the form @samp{local.@var{first.last}} if a real -name is present in the password file. Otherwise, the alias will have -the form @samp{local.@var{login}}. - -@vindex mh-alias-local-users-prefix - -The prefix @samp{local.} can be modified via the option -@code{mh-alias-local-users-prefix}. This option can also be set to -@samp{Use Login}. - -For example, consider the following password file entry: - -@smallexample -psg:x:1000:1000:Peter S Galbraith,,,:/home/psg:/bin/tcsh -@end smallexample - -@vindex mh-alias-local-users-prefix - -The following settings of option @code{mh-alias-local-users-prefix} -will produce the associated aliases: - -@table @code -@item "local." -local.peter.galbraith -@c ------------------------- -@item "" -peter.galbraith -@c ------------------------- -@item Use Login -psg -@end table - -@vindex mh-alias-passwd-gecos-comma-separator-flag - -In the example above, commas are used to separate different values -within the so-called GECOS field. This is a fairly common usage. -However, in the rare case that the GECOS field in your password file -is not separated by commas and whose contents may contain commas, you -can turn the option @code{mh-alias-passwd-gecos-comma-separator-flag} -off. - -@cindex NIS, obtaining local aliases from -@cindex @samp{ypcat passwd} -@vindex mh-alias-local-users - -If you're on a system with thousands of users you don't know, and the -loading of local aliases slows MH-E down noticeably, then the local -alias feature can be disabled by turning off the option -@code{mh-alias-local-users}. This option also takes a string which is -executed to generate the password file. For example, use @samp{ypcat -passwd} to obtain the NIS password file. - -@findex mh-alias-reload -@vindex mh-alias-reloaded-hook - -Since aliases are updated frequently, MH-E reloads aliases -automatically whenever an alias lookup occurs if an alias source has -changed. However, you can reload your aliases manually by calling the -command @kbd{M-x mh-alias-reload} directly. This command runs -@code{mh-alias-reloaded-hook} after the aliases have been loaded. - -@subheading Adding Aliases - -In the past, you have manually added aliases to your alias file(s) -listed in your @samp{Aliasfile:} profile component. MH-E provides -other methods for maintaining your alias file(s). - -@findex mh-alias-add-alias - -You can use the @kbd{M-x mh-alias-add-alias} command which will prompt -you for the alias and address that you would like to add. If the alias -exists already, you will have the choice of inserting the new alias -before or after the old alias. In the former case, this alias will be -used when sending mail to this alias. In the latter case, the alias -serves as an additional folder name hint when filing messages -(@pxref{Folder Selection}). - -Earlier, the alias prefix @samp{local} was presented. You can use -other prefixes to organize your aliases or disambiguate entries. You -might use prefixes for locales, jobs, or activities. For example, I -have: - -@smallexample -@group -; Work -attensity.don.mitchell: Don Mitchell -isharp.don.mitchell: Don Mitchell -... -; Sport -diving.ken.mayer: Ken Mayer -sailing.mike.maloney: Mike Maloney -... -; Personal -ariane.kolkmann: Ariane Kolkmann -... -@end group -@end smallexample - -Using prefixes instead of postfixes helps you explore aliases during -completion. If you forget the name of an old dive buddy, you can enter -@samp{div} and then @key{SPC} to get a listing of all your dive buddies. - -@findex mh-alias-add-address-under-point -@findex mh-alias-grab-from-field - -An alias for the sender of the current message is added automatically -by clicking on the @samp{Grab From alias} tool bar button or by running -the @kbd{M-x mh-alias-grab-from-field} command. Aliases for other -recipients of the current message are added by placing your cursor -over the desired recipient and giving the @kbd{M-x -mh-alias-add-address-under-point} command. - -@vindex mh-alias-insert-file -@vindex mh-alias-insertion-location - -The options @code{mh-alias-insert-file} and -@code{mh-alias-insertion-location} controls how and where these aliases -are inserted. - -@vindex mh-alias-insert-file - -The default setting of option @code{mh-alias-insert-file} is @samp{Use -Aliasfile Profile Component}. This option can also hold the name of a -file or a list a file names. If this option is set to a list of file -names, or the @samp{Aliasfile:} profile component contains more than -one file name, MH-E will prompt for one of them. - -@vindex mh-alias-insertion-location - -The option @code{mh-alias-insertion-location} is set to -@samp{Alphabetical} by default. If you organize your alias file in -other ways, then the settings @samp{Top} and @samp{Bottom} might be -more appropriate. - -@subheading Querying Aliases - -@cindex regular expressions, @code{mh-alias-apropos} -@findex mh-alias-apropos - -If you can't quite remember an alias, you can use @kbd{M-x -mh-alias-apropos} to show all aliases or addresses that match a -regular expression -@ifnothtml -(@pxref{Regexps, , Syntax of Regular Expressions, emacs, The -GNU Emacs Manual}). -@end ifnothtml -@ifhtml -(see the section -@uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Regexps.html, -Syntax of Regular Expressions} in -@cite{The GNU Emacs Manual}). -@end ifhtml - -@node Identities -@chapter Identities - -@cindex identities -@cindex multiple personalities - -MH-E supports the concept of multiple personalities or identities. -This means that you can easily have a different header and signature -at home and at work. - -@cindex @samp{Identity} menu -@cindex menu, @samp{Identity} - -A couple of commands are used to insert identities in MH-Letter mode -which are also found in the @samp{Identity} menu. - -@table @kbd -@kindex C-c C-d -@findex mh-insert-identity -@item C-c C-d -Insert fields specified by given identity (@code{mh-insert-identity}). -@c ------------------------- -@cindex @samp{Identity > Insert Auto Fields} menu item -@cindex menu item, @samp{Identity > Insert Auto Fields} -@kindex C-c M-d -@findex mh-insert-auto-fields -@item C-c M-d -Insert custom fields if recipient found in @code{mh-auto-fields-list} -(@code{mh-insert-auto-fields}). -@end table - -@cindex @samp{mh-identity} customization group -@cindex customization group, @samp{mh-identity} - -The @samp{mh-identity} customization group contains the following -options. - -@vtable @code -@item mh-auto-fields-list -List of recipients for which header lines are automatically inserted -(default: @code{nil}). -@c ------------------------- -@item mh-auto-fields-prompt-flag -On means to prompt before sending if fields inserted (default: -@samp{on}) -@c ------------------------- -@item mh-identity-default -Default identity to use when @code{mh-letter-mode} is called (default: -@samp{None}). -@c ------------------------- -@item mh-identity-handlers -Handler functions for fields in @code{mh-identity-list}. -@c ------------------------- -@item mh-identity-list -List of identities (default: @code{nil}). -@end vtable - -Some of the common header fields that people change depending on the -context are the @samp{From:} and @samp{Organization:} fields, as well -as the signature. - -@vindex mh-identity-list - -This is done by customizing the option @code{mh-identity-list}. In the -customization buffer for this option, click on the @samp{INS} button -and enter a label such as @samp{Home} or @samp{Work}. Then click on -the @samp{INS} button with the label @samp{Add at least one item -below}. The @samp{Value Menu} has the following menu items: - -@table @samp -@cindex header field, @samp{From} -@cindex @samp{From} header field -@item From Field -Specify an alternate @samp{From:} header field. You must include a -valid email address. A standard format is @samp{First Last -}. If you use an initial with a period, then you -must quote your name as in @samp{"First I. Last" -}. -@c ------------------------- -@cindex header field, @samp{Organization} -@cindex @samp{Organization} header field -@item Organization Field -People usually list the name of the company where they work here. -@c ------------------------- -@item Other Field -Set any arbitrary header field and value here. Unless the header field -is a standard one, precede the name of your field's label with -@samp{X-}, as in @samp{X-Fruit-of-the-Day:}. -@c ------------------------- -@item Attribution Verb -This value overrides the setting of -@code{mh-extract-from-attribution-verb}. @xref{Inserting Letter}. -@c ------------------------- -@cindex signature -@vindex mh-signature-file-name -@item Signature -Set your signature with this item. You can specify the contents of -@code{mh-signature-file-name}, a file, or a function. -@xref{Signature}. -@c ------------------------- -@item GPG Key ID -Specify a different key to sign or encrypt messages. -@end table - -@cindex Identity menu -@cindex menu, Identity -@findex mh-insert-identity -@kindex C-c C-d - -You can select the identities you have added via the menu called -@samp{Identity} in the MH-Letter buffer. You can also use @kbd{C-c -C-d} (@code{mh-insert-identity}). To clear the fields and signature -added by the identity, select the @samp{None} identity. - -@cindex menu item, @samp{Identity > Customize Identities} -@cindex menu item, @samp{Identity > Save as Default} -@cindex menu item, @samp{Identity > Set Default for Session} -@cindex @samp{Identity > Customize Identities} menu item -@cindex @samp{Identity > Save as Default} menu item -@cindex @samp{Identity > Set Default for Session} menu item -@vindex mh-identity-default - -The @samp{Identity} menu contains two other items to save you from -having to set the identity on every message. The menu item @samp{Set -Default for Session} can be used to set the default identity to the -current identity until you exit Emacs. The menu item @samp{Save as -Default} sets the option @code{mh-identity-default} to the current -identity setting. You can also customize the option -@code{mh-identity-default} in the usual fashion. If you find that you -need to add another identity, the menu item @samp{Customize -Identities} is available for your convenience. - -@cindex regular expressions, @code{mh-auto-fields-list} -@vindex mh-auto-fields-list - -The option @code{mh-auto-fields-list} can also be used to set the -identity depending on the recipient to provide even more control. To -customize @code{mh-auto-fields-list}, click on the @samp{INS} button -and enter a regular expression for the recipient's address -@ifnothtml -(@pxref{Regexps, , Syntax of Regular Expressions, emacs, The -GNU Emacs Manual}). -@end ifnothtml -@ifhtml -(see the section -@uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Regexps.html, -Syntax of Regular Expressions} in -@cite{The GNU Emacs Manual}). -@end ifhtml -Click on the @samp{INS} button with the @samp{Add at least one item -below} label. The @samp{Value Menu} contains the following menu items: - -@table @samp -@item Identity -Select an identity from those configured in @code{mh-identity-list}. -All of the information for that identity will be added if the -recipient matches. -@c ------------------------- -@cindex @samp{Fcc} header field -@cindex header field, @samp{Fcc} -@item Fcc Field -Insert an @samp{Fcc:} header field with the folder you provide. When -you send the message, MH will put a copy of your message in this -folder. -@c ------------------------- -@cindex @samp{Mail-Followup-To} header field -@cindex header field, @samp{Mail-Followup-To} -@item Mail-Followup-To Field -Insert an @samp{Mail-Followup-To:} header field with the recipients -you provide. If the recipient's mail user agent supports this header -field@footnote{@samp{Mail-Followup-To:} is supported by nmh.}, then -their replies will go to the addresses listed. This is useful if their -replies go both to the list and to you and you don't have a mechanism -to suppress duplicates. If you reply to someone not on the list, you -must either remove the @samp{Mail-Followup-To:} field, or ensure the -recipient is also listed there so that he receives replies to your -reply. -@c ------------------------- -@item Other Field -Other header fields may be added using this menu item. -@end table - -@findex mh-insert-auto-fields -@kindex C-c M-d -@vindex mh-auto-fields-prompt-flag - -These fields can only be added after the recipient is known. Because -you can continue to add recipients as you edit the draft, MH-E waits -until the message is sent to perform the auto-insertions. This seems -strange at first, but you'll get used to it. There are two ways to -help you feel that the desired fields are added. The first is the -action when the message is sent: if any fields are added -automatically, you are given a chance to see and to confirm these -fields before the message is actually sent. You can do away with this -confirmation by turning off the option -@code{mh-auto-fields-prompt-flag}. The second method is manual: once -the header contains one or more recipients, you may run the command -@kbd{C-c M-d} (@code{mh-insert-auto-fields}) or choose the -@samp{Identity -> Insert Auto Fields} menu item to insert these fields -manually. However, if you use this command, the automatic insertion -when the message is sent is disabled. - -@vindex mh-auto-fields-list -@vindex mh-identity-list - -You should avoid using the same header field in -@code{mh-auto-fields-list} and @code{mh-identity-list} definitions -that may apply to the same message as the result is undefined. - -@vindex mh-identity-handlers -@vindex mh-identity-list - -The option @code{mh-identity-handlers} is used to change the way that -fields, signatures, and attributions in @code{mh-identity-list} are -added. To customize @code{mh-identity-handlers}, replace the name of -an existing handler function associated with the field you want to -change with the name of a function you have written. You can also -click on an @samp{INS} button and insert a field of your choice and -the name of the function you have written to handle it. - -@vindex mh-identity-list - -The @samp{Field} field can be any field that you've used in your -@code{mh-identity-list}. The special fields @samp{:attribution-verb}, -@samp{:signature}, or @samp{:pgg-default-user-id} are used for the -@code{mh-identity-list} choices @samp{Attribution Verb}, -@samp{Signature}, and @samp{GPG Key ID} respectively. - -The handler associated with the @samp{:default} field is used when no -other field matches. - -The handler functions are passed two or three arguments: the field -itself (for example, @samp{From}), or one of the special fields (for -example, @samp{:signature}), and the action @samp{'remove} or -@samp{'add}. If the action is @samp{'add}, an additional argument -containing the value for the field is given. - -@node Speedbar -@chapter The Speedbar - -@cindex folder navigation -@cindex speedbar -@findex mh-visit-folder -@findex speedbar -@kindex F v -@kindex mouse-2 - -You can also use the speedbar -@ifnothtml -(@pxref{Speedbar, , Speedbar Frames, emacs, The GNU Emacs Manual},) -@end ifnothtml -@ifhtml -(see the section -@uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Speedbar.html, -Speedbar Frames} in @cite{The GNU Emacs Manual}) -@end ifhtml -to view your folders. To bring up the speedbar, run @kbd{M-x speedbar -@key{RET}}. You will see a new frame appear with all of your MH -folders. Folders with unseen messages appear in boldface. Click on a -folder name with @kbd{mouse-2} to visit that folder in a similar -fashion to the command @kbd{F v} (@code{mh-visit-folder}) -(@pxref{Folders}). Click on the @samp{+} icon to expand and view the -sub-folders of that folder. - -The speedbar can be manipulated with the keyboard as well. Use the -Emacs navigational keys (like the arrow keys, or @kbd{C-n}) to move -the cursor over the desired folder and then use the shortcuts for the -menu items listed in the table below. - -@table @asis -@findex mh-speed-view -@item @samp{Visit Folder} (@key{RET}) -Visits the selected folder just as if you had used @kbd{F v} -(@code{mh-speed-view}). -@c ------------------------- -@findex mh-speed-expand-folder -@item @samp{Expand Nested Folders} (@kbd{+}) -Expands the selected folder in the speedbar, exposing the children -folders inside it (@code{mh-speed-expand-folder}). -@c ------------------------- -@findex mh-speed-contract-folder -@item @samp{Contract Nested Folders} (@kbd{-}) -Contracts or collapses the selected folder in the speedbar, hiding the -children folders inside it (@code{mh-speed-contract-folder}). -@c ------------------------- -@findex mh-speed-refresh -@item @samp{Refresh Speedbar} (@kbd{r}) -Regenerates the list of folders in the speedbar. Run this command if -you've added or deleted a folder, or want to update the unseen message -count before the next automatic update (@code{mh-speed-refresh}). -@end table - -@findex delete-frame -@kindex C-x 5 0 -@kindex mouse-3 - -You can click on @kbd{mouse-3} to bring up a context menu that -contains these items. Dismiss the speedbar with @kbd{C-x 5 0} -(@code{delete-frame}). - -@cindex @command{flists} -@cindex MH commands, @command{flists} -@cindex @samp{mh-speedbar} customization group -@cindex customization group, @samp{mh-speedbar} - -The MH-E speedbar uses the MH command @command{flists}@footnote{See -the section @uref{@value{MH-BOOK-HOME}/morseq.html#flist, Searching for -Sequences with flist} in the MH book.} to generate the list of -folders. The @samp{mh-speedbar} customization group contains the -following option which controls how often the speedbar calls -@command{flists}. - -@vtable @code -@item mh-speed-update-interval -Time between speedbar updates in seconds (default: 60). Set to 0 to -disable automatic update. -@end vtable - -You can modify the appearance of the folders in the speedbar by -customizing the following faces. - -@vtable @code -@item mh-speedbar-folder -Basic folder face. -@c ------------------------- -@item mh-speedbar-folder-with-unseen-messages -Folder face when folder contains unread messages. -@c ------------------------- -@item mh-speedbar-selected-folder -Selected folder face. -@c ------------------------- -@item mh-speedbar-selected-folder-with-unseen-messages -Selected folder face when folder contains unread messages. -@end vtable - -@node Menu Bar -@chapter The Menu Bar - -@cindex @samp{Folder} menu -@cindex @samp{Identity} menu -@cindex @samp{Letter} menu -@cindex @samp{Message} menu -@cindex @samp{Search} menu -@cindex @samp{Sequence} menu -@cindex Folder menu -@cindex Identity menu -@cindex Letter menu -@cindex MH-Folder mode -@cindex MH-Letter mode -@cindex MH-Search mode -@cindex Message menu -@cindex Search menu -@cindex Sequence menu -@cindex menu bar -@cindex menu, Folder -@cindex menu, Identity -@cindex menu, Letter -@cindex menu, Message -@cindex menu, Search -@cindex menu, Sequence -@cindex menu, @samp{Folder} -@cindex menu, @samp{Identity} -@cindex menu, @samp{Letter} -@cindex menu, @samp{Message} -@cindex menu, @samp{Search} -@cindex menu, @samp{Sequence} -@cindex modes, MH-Folder -@cindex modes, MH-Letter -@cindex modes, MH-Search - -For those of you who prefer to mouse and menu instead of using the -meta-coke-bottle-bucky keys, MH-E provides menu items for most of its -functions. The MH-Folder buffer adds the @samp{Folder}, -@samp{Message}, and @samp{Sequence} menus. The MH-Letter buffer adds -the @samp{Identity} and @samp{Letter} menus. The MH-Search buffer adds -the @samp{Search} menu. There's no need to list the actual items here, -as you can more easily see them for yourself, and the functions are -already described elsewhere in this manual. - -For a description of the menu bar, please -@ifnothtml -@xref{Menu Bar, , The Menu Bar, emacs, The GNU Emacs Manual}. -@end ifnothtml -@ifhtml -see the section -@uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Menu-Bar.html, -The Menu Bar} in @cite{The GNU Emacs Manual}. -@end ifhtml - -The Emacs manual describes how to get help for a particular -menu item. You can also look up a menu item in the index of this -manual in two ways: all of the menu items are listed alphabetically, -and you can also browse all of the items under the index entry -@samp{menu item}. - -@node Tool Bar -@chapter The Tool Bar - -@cindex tool bar - -Emacs also provides a graphical tool bar. For a description of the -tool bar, please -@ifnothtml -@xref{Tool Bars, , Tool Bars, emacs, The GNU Emacs Manual}. -@end ifnothtml -@ifhtml -see the section -@uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Tool-Bars.html, -Tool Bars} in @cite{The GNU Emacs Manual}. -@end ifhtml - -@cindex @samp{mh-tool-bar} customization group -@cindex customization group, @samp{mh-tool-bar} - -MH-E adds several icons to this tool bar; you can modify the MH-E -aspects of the tool bar via the @samp{mh-tool-bar} customization group. - -@vtable @code -@item mh-tool-bar-folder-buttons -List of buttons to include in MH-Folder tool bar (default: a checklist -too long to list here). -@c ------------------------- -@item mh-tool-bar-letter-buttons -List of buttons to include in MH-Letter tool bar (default: a checklist -too long to list here). -@c ------------------------- -@item mh-tool-bar-search-function -Function called by the tool bar search button (default: -@code{mh-search}). -@end vtable - -Icons for some of MH-E's functions are added to the tool bar. - -@vindex mh-tool-bar-folder-buttons -@vindex mh-tool-bar-letter-buttons - -In either case, you can select which of these functions you'd like to -see by customizing the options @code{mh-tool-bar-folder-buttons} and -@code{mh-tool-bar-letter-buttons}. As you probably guessed, the former -customizes the tool bar in MH-Folder mode and the latter in MH-Letter -mode. Both of these options present you with a list of functions; -check the functions whose icons you want to see and clear the check -boxes for those you don't. - -@findex mh-search -@vindex mh-tool-bar-search-function - -The function associated with the searching icon can be set via the -option @code{mh-tool-bar-search-function}. By default, this is set to -@code{mh-search}. @xref{Searching}. You can also choose @samp{Other -Function} from the @samp{Value Menu} and enter a function of your own -choosing. - -@node Searching -@chapter Searching Through Messages - -@cindex @samp{Search} menu -@cindex menu, @samp{Search} -@cindex searching -@findex mh-search -@kindex F s - -Earlier, the command @kbd{F s} (@code{mh-search}) was introduced which -helps you find messages that lie buried in your folders -(@pxref{Folders}). This chapter covers this command in more detail. -Several commands are used to compose the search criteria and to start -searching. A couple of them can be found in the @samp{Search} menu. - -@table @kbd -@kindex C-c ? -@findex mh-help -@item C-c ? -Display cheat sheet for the MH-E commands (@code{mh-help}). -@c ------------------------- -@cindex @samp{Search > Perform Search} menu item -@cindex menu item, @samp{Search > Perform Search} -@kindex C-c C-c -@findex mh-index-do-search -@item C-c C-c -Find messages using @code{mh-search-program} -(@code{mh-index-do-search}). -@c ------------------------- -@cindex @samp{Search > Search with pick} menu item -@cindex menu item, @samp{Search > Search with pick} -@kindex C-c C-p -@findex mh-pick-do-search -@item C-c C-p -Find messages using @command{pick} (@code{mh-pick-do-search}). -@c ------------------------- -@kindex C-c ? -@findex mh-help -@item C-c ? -Display cheat sheet for the MH-E commands (@code{mh-help}). -@c ------------------------- -@kindex C-c C-f C-a -@kindex C-c C-f a -@findex mh-to-field -@item C-c C-f a -@itemx C-c C-f C-a -Move to @samp{Mail-Reply-To:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-b -@kindex C-c C-f b -@item C-c C-f b -@itemx C-c C-f C-b -Move to @samp{Bcc:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-c -@kindex C-c C-f c -@item C-c C-f c -@itemx C-c C-f C-c -Move to @samp{Cc:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-d -@kindex C-c C-f d -@item C-c C-f d -@itemx C-c C-f C-d -Move to @samp{Dcc:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-f -@kindex C-c C-f f -@item C-c C-f f -@itemx C-c C-f C-f -Move to @samp{Fcc:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-l -@kindex C-c C-f l -@item C-c C-f l -@itemx C-c C-f C-l -Move to @samp{Mail-Followup-To:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-m -@kindex C-c C-f m -@item C-c C-f m -@itemx C-c C-f C-m -Move to @samp{From:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-r -@kindex C-c C-f r -@item C-c C-f r -@itemx C-c C-f C-r -Move to @samp{Reply-To:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-s -@kindex C-c C-f s -@item C-c C-f s -@itemx C-c C-f C-s -Move to @samp{Subject:} header field (@code{mh-to-field}). -@c ------------------------- -@kindex C-c C-f C-t -@kindex C-c C-f t -@item C-c C-f t -@itemx C-c C-f C-t -Move to @samp{To:} header field (@code{mh-to-field}). -@end table - -Another few commands are available in the MH-Folder buffer resulting -from a search. - -@table @kbd -@kindex TAB -@findex mh-index-next-folder -@item @key{TAB} -Jump to the next folder marker (@code{mh-index-next-folder}). -@c ------------------------- -@kindex S-TAB -@findex mh-index-previous-folder -@item S-@key{TAB} -Jump to the previous folder marker (@code{mh-index-previous-folder}). -@c ------------------------- -@kindex v -@findex mh-index-visit-folder -@item v -Visit original folder from where the message at point was found -(@code{mh-index-visit-folder}). -@end table - -@cindex @samp{mh-search} customization group -@cindex customization group, @samp{mh-search} - -There is one option from the @samp{mh-search} customization group used -in searching. - -@vtable @code -@item mh-search-program -Search program that MH-E shall use (default: @samp{Auto-detect}). -@end vtable - -The following hook is available. - -@vtable @code -@item mh-search-mode-hook -Hook run upon entry to @code{mh-search-mode} (default: @code{nil}). -@end vtable - -The following face is available. - -@vtable @code -@item mh-search-folder -Folder heading face in MH-Folder buffers created by searches. -@end vtable - -@findex mh-search-folder -@kindex F s - -The command @kbd{F s} (@code{mh-search-folder}) helps you find -messages in your entire corpus of mail. You can search for messages to -or from a particular person or about a particular subject. In fact, -you can also search for messages containing selected strings in any -arbitrary header field or any string found within the messages. - -@cindex @command{pick} -@cindex MH commands, @command{pick} - -Out of the box, MH-E uses @command{pick} to find messages. With a -little extra effort, you can set an indexing program which rewards you -with extremely quick results. The drawback is that sometimes the index -does not contain the words you're looking for. You can still use -@command{pick} in these situations. - -You are prompted for the folder to search. This can be @samp{all} to -search all folders. Note that the search works recursively on the -listed folder. - -@cindex MH-Search mode -@cindex modes, MH-Search - -Next, an MH-Search buffer appears where you can enter search criteria. - -@cartouche -@smallexample -From: -To: -Cc: -Date: -Subject: --------- -# - - - - - - - - ---:** search-pattern All L7 (MH-Search)--------------------------- -Type C-c C-c to search messages, C-c C-p to use pick, C-c ? for help -@end smallexample -@end cartouche -@i{Search window} - -@cindex @command{pick} -@cindex MH commands, @command{pick} - -Edit this template by entering your search criteria in an appropriate -header field that is already there, or create a new field yourself. If -the string you're looking for could be anywhere in a message, then -place the string underneath the row of dashes. - -As an example, let's say that we want to find messages from Ginnean -about horseback riding in the Kosciusko National Park (Australia) -during January, 1994. Normally we would start with a broad search and -narrow it down if necessary to produce a manageable amount of data, -but we'll cut to the chase and create a fairly restrictive set of -criteria as follows: - -@smallexample -@group -From: ginnean -To: -Cc: -Date: Jan 1994 -Subject: --------- -horse -kosciusko -@end group -@end smallexample - -@findex mh-to-field -@kindex C-c C-f C-t - -As with MH-Letter mode, MH-Search provides commands like @kbd{C-c C-f -C-t} (@code{mh-to-field}) to help you fill in the blanks. -@xref{Editing Message}. - -@kindex F s -@vindex mh-search-mode-hook - -If you find that you do the same thing over and over when editing the -search template, you may wish to bind some shortcuts to keys. This can -be done with the variable @code{mh-search-mode-hook}, which is called -when @kbd{F s} is run on a new pattern. - -@findex mh-index-do-search -@findex mh-pick-do-search -@kindex C-c C-c -@kindex C-c C-p - -To perform the search, type @kbd{C-c C-c} (@code{mh-index-do-search}). -Sometimes you're searching for text that is either not indexed, or -hasn't been indexed yet. In this case you can override the default -method with the pick method by running the command @kbd{C-c C-p} -(@code{mh-pick-do-search}). - -@cindex folders, @samp{+mhe-index} -@cindex @samp{+mhe-index} -@findex mh-index-next-folder -@findex mh-index-previous-folder -@kindex TAB -@kindex S-TAB -@vindex mh-search-folder - -The messages that are found are put in a temporary sub-folder of -@samp{+mhe-index} and are displayed in an MH-Folder buffer. This -buffer is special because it displays messages from multiple folders; -each set of messages from a given folder has a heading with the folder -name. The appearance of the heading can be modified by customizing the -face @code{mh-search-folder}. You can jump back and forth between the -headings using the commands @kbd{@key{TAB}} -(@code{mh-index-next-folder}) and @kbd{S-@key{TAB}} -(@code{mh-index-previous-folder}). - -@findex mh-index-visit-folder -@findex mh-rescan-folder -@kindex F r -@kindex v - -In addition, the command @kbd{v} (@code{mh-index-visit-folder}) can be -used to visit the folder of the message at point. Initially, only the -messages that matched the search criteria are displayed in the folder. -While the temporary buffer has its own set of message numbers, the -actual messages numbers are shown in the visited folder. Thus, the -command @kbd{v} is useful to find the actual message number of an -interesting message, or to view surrounding messages with the command -@kbd{F r} @code{mh-rescan-folder}. @xref{Folders}. - -@findex mh-kill-folder -@kindex F k - -Because this folder is temporary, you'll probably get in the habit of -killing it when you're done with @kbd{F k} (@code{mh-kill-folder}). -@xref{Folders}. - -@kindex F s - -You can regenerate the results by running @kbd{F s} with a prefix -argument. - -@cindex @command{procmail} -@cindex Unix commands, @command{procmail} -@cindex @samp{X-MHE-Checksum} header field -@cindex header field, @samp{X-MHE-Checksum} - -Note: This command uses an @samp{X-MHE-Checksum:} header field to -cache the MD5 checksum of a message. This means that if an incoming -message already contains an @samp{X-MHE-Checksum:} field, that message -might not be found by this command. The following @command{procmail} -recipe avoids this problem by renaming the existing header field: - -@smallexample -@group -:0 wf -| formail -R "X-MHE-Checksum" "X-Old-MHE-Checksum" -@end group -@end smallexample - -@xref{Limits}, for an alternative interface to searching. - -@section Configuring Indexed Searches - -@cindex @command{grep} -@cindex @command{mairix} -@cindex @command{namazu} -@cindex @command{pick} -@cindex @command{swish++} -@cindex @command{swish-e} -@cindex Unix commands, @command{grep} -@cindex Unix commands, @command{mairix} -@cindex Unix commands, @command{namazu} -@cindex Unix commands, @command{pick} -@cindex Unix commands, @command{swish++} -@cindex Unix commands, @command{swish-e} -@findex mh-search -@kindex F s -@vindex mh-search-program - -The command @kbd{F s} (@code{mh-search}) runs the command defined by -the option @code{mh-search-program}. The default value is -@samp{Auto-detect} which means that MH-E will automatically choose one -of @command{swish++}, @command{swish-e}, @command{mairix}, -@command{namazu}, @command{pick} and @command{grep} in that order. If, -for example, you have both @command{swish++} and @command{mairix} -installed and you want to use @command{mairix}, then you can set this -option to @samp{mairix}. - -The following sub-sections describe how to set up the various indexing -programs to use with MH-E. - -@subsection swish++ - -@cindex @command{swish++} -@cindex Unix commands, @command{swish++} - -In the examples below, replace @file{/home/user/Mail} with the path to -your MH directory. - -First create the directory @file{/home/user/Mail/.swish++}. Then -create the file @file{/home/user/Mail/.swish++/swish++.conf} with the -following contents: - -@smallexample -@group -IncludeMeta Bcc Cc Comments Content-Description From Keywords -IncludeMeta Newsgroups Resent-To Subject To -IncludeMeta Message-Id References In-Reply-To -IncludeFile Mail * -IndexFile /home/user/Mail/.swish++/swish++.index -@end group -@end smallexample - -Use the following command line to generate the swish index. Run this -daily from cron: - -@smallexample -@group -find /home/user/Mail -path /home/user/Mail/mhe-index -prune \ - -o -path /home/user/Mail/.swish++ -prune \ - -o -name "[0-9]*" -print \ - | index -c /home/user/Mail/.swish++/swish++.conf - -@end group -@end smallexample - -This command does not index the folders that hold the results of your -searches in @samp{+mhe-index} since they tend to be ephemeral and the -original messages are indexed anyway. - -@cindex @command{index} -@cindex Unix commands, @command{index} -@cindex @command{index++} -@cindex Unix commands, @command{index++} - -On some systems (Debian GNU/Linux, for example), use @command{index++} -instead of @command{index}. - -@subsection swish - -@cindex @command{swish-e} -@cindex Unix commands, @command{swish-e} - -In the examples below, replace @file{/home/user/Mail} with the path to -your MH directory. - -First create the directory @file{/home/user/Mail/.swish}. Then create -the file @file{/home/user/Mail/.swish/config} with the following -contents: - -@smallexample -@group -DefaultContents TXT* -IndexDir /home/user/Mail -IndexFile /home/user/Mail/.swish/index -IndexName "Mail Index" -IndexDescription "Mail Index" -IndexPointer "https://nowhere" -IndexAdmin "nobody" -#MetaNames automatic -IndexReport 3 -FollowSymLinks no -UseStemming no -IgnoreTotalWordCountWhenRanking yes -WordCharacters abcdefghijklmnopqrstuvwxyz0123456789- -BeginCharacters abcdefghijklmnopqrstuvwxyz -EndCharacters abcdefghijklmnopqrstuvwxyz0123456789 -IgnoreLimit 50 1000 -IndexComments 0 -FileRules filename contains \D -FileRules pathname contains /home/user/Mail/.swish -FileRules pathname contains /home/user/Mail/mhe-index -FileRules filename is index -@end group -@end smallexample - -This configuration does not index the folders that hold the results of -your searches in @samp{+mhe-index} since they tend to be ephemeral and -the original messages are indexed anyway. - -If there are any directories you would like to ignore, append lines -like the following to @file{config}: - -@smallexample -FileRules pathname contains /home/user/Mail/scripts -@end smallexample - -@cindex @command{swish-e} -@cindex Unix commands, @command{swish-e} - -Use the following command line to generate the swish index. Run this -daily from cron: - -@smallexample -swish-e -c /home/user/Mail/.swish/config -@end smallexample - -@subsection mairix - -@cindex @command{mairix} -@cindex Unix commands, @command{mairix} - -In the examples below, replace @file{~/Mail} with the path to your MH -directory. - -First create the directory @file{~/Mail/.mairix}. Then create the file -@file{~/Mail/.mairix/config} with the following contents: - -@smallexample -@group -base=~/Mail - -# List of folders that should be indexed. 3 dots at the end means there -# are subfolders within the folder -mh=archive...:inbox:drafts:news:sent:trash - -mformat=mh -database=~/Mail/.mairix/database -@end group -@end smallexample - -Use the following command line to generate the mairix index. Run this daily -from cron: - -@smallexample -mairix -f ~/Mail/.mairix/config -@end smallexample - -@subsection namazu - -@cindex @command{namazu} -@cindex Unix commands, @command{namazu} - -In the examples below, replace @file{/home/user/Mail} with the path to -your MH directory. - -First create the directory @file{/home/user/Mail/.namazu}. Then create -the file @file{/home/user/Mail/.namazu/mknmzrc} with the following -contents: - -@smallexample -@group -package conf; # Don't remove this line! -$ADDRESS = 'user@@localhost'; -$ALLOW_FILE = "[0-9]*"; -$EXCLUDE_PATH = "^/home/user/Mail/(mhe-index|spam)"; -@end group -@end smallexample - -This configuration does not index the folders that hold the results of -your searches in @samp{+mhe-index} since they tend to be ephemeral and -the original messages are indexed anyway. - -Use the following command line to generate the namazu index. Run this -daily from cron: - -@smallexample -mknmz -f /home/user/Mail/.namazu/mknmzrc -O /home/user/Mail/.namazu \ - -q /home/user/Mail -@end smallexample - -@subsection pick - -@cindex @command{pick} -@cindex MH commands, @command{pick} - -This search method does not require any setup. - -Read @command{pick}(1) or the section -@uref{@value{MH-BOOK-HOME}/finpic.html, Finding Messages with pick} in -the MH book to find out more about how to enter the criteria. - -@subsection grep - -@cindex @command{grep} -@cindex Unix commands, @command{grep} - -This search method does not require any setup. - -Unlike the other search methods, this method does not use the -MH-Search buffer. Instead, you simply enter a regular expression in -the minibuffer. For help in constructing regular expressions, see your -man page for @command{grep}. - -@node Threading -@chapter Viewing Message Threads - -@cindex threading - -MH-E groups messages by @dfn{threads} which are messages that are part -of the same discussion and usually all have the same @samp{Subject:} -header field. Other ways to organize messages in a folder include -limiting (@pxref{Limits}) or using full-text indexed searches -(@pxref{Searching}). - -@cindex root, in threads -@cindex siblings, in threads -@cindex ancestor, in threads - -A thread begins with a single message called a @dfn{root}. All replies -to the same message are @dfn{siblings} of each other. Any message that -has replies to it is an @dfn{ancestor} of those replies. - -There are several commands that you can use to navigate and operate on -threads. - -@table @kbd -@kindex T ? -@findex mh-prefix-help -@item T ? -Display cheat sheet for the commands of the current prefix in -minibuffer (@code{mh-prefix-help}). -@c ------------------------- -@kindex T o -@findex mh-thread-refile -@item T o -Refile (output) thread into folder (@code{mh-thread-refile}). -@c ------------------------- -@kindex T d -@findex mh-thread-delete -@item T d -Delete thread (@code{mh-thread-delete}). -@c ------------------------- -@kindex T t -@findex mh-toggle-threads -@item T t -Toggle threaded view of folder (@code{mh-toggle-threads}). -@c ------------------------- -@kindex T n -@findex mh-thread-next-sibling -@item T n -Display next sibling (@code{mh-thread-next-sibling}). -@c ------------------------- -@kindex T p -@findex mh-thread-previous-sibling -@item T p -Display previous sibling (@code{mh-thread-previous-sibling}). -@c ------------------------- -@kindex T u -@findex mh-thread-ancestor -@item T u -Display ancestor of current message (@code{mh-thread-ancestor}). -@end table - -@cindex @samp{mh-thread} customization group -@cindex customization group, @samp{mh-thread} - -The @samp{mh-thread} customization group contains one option. - -@vtable @code -@item mh-show-threads-flag -On means new folders start in threaded mode (default: @samp{off}). -@end vtable - -@findex mh-toggle-threads -@kindex T t -@vindex mh-large-folder -@vindex mh-show-threads-flag - -Threading large number of messages can be time consuming so the option -@code{mh-show-threads-flag} is turned off by default. If you turn on -this option, then threading will be done only if the number of -messages being threaded is less than @code{mh-large-folder}. In any -event, threading can be turned on (and off) with the command @kbd{T t} -(@code{mh-toggle-threads}). - -@findex mh-thread-ancestor -@findex mh-thread-next-sibling -@findex mh-thread-previous-sibling -@kindex T n -@kindex T p -@kindex T u - -There are a few commands to help you navigate threads. If you do not -care for the way a particular thread has turned, you can move up the -chain of messages with the command @kbd{T u} -(@code{mh-thread-ancestor}. At any point you can use @kbd{T n} -(@code{mh-thread-next-sibling} or @kbd{T p} -(@code{mh-thread-previous-sibling}) to jump to the next or previous -sibling, skipping the sub-threads. The command @kbd{T u} can also take -a prefix argument to jump to the message that started everything. - -@findex mh-delete-subject-or-thread -@findex mh-thread-delete -@findex mh-thread-refile -@kindex k -@kindex T d -@kindex T o - -There are threaded equivalents for the commands that delete and refile -messages. For example, @kbd{T o} (@code{mh-thread-refile}) refiles the -current message and all its children. Similarly, the command @kbd{T d} -(@code{mh-thread-delete}) deletes the current message and all its -children. These commands do not refile or delete sibling messages. -@xref{Navigating}, for a description of the similar command @kbd{k} -(@code{mh-delete-subject-or-thread}). - -@vindex mh-large-folder - -If you find that threading is too slow, it may be that you have -@code{mh-large-folder} set too high. Also, threading is one of the few -features of MH-E that really benefits from compiling. If you haven't -compiled MH-E, I encourage you to do so@footnote{If you're not sure if -MH-E has been byte-compiled, you could try running @samp{locate -mh-thread.elc} or otherwise find MH-E on your system and ensure that -@file{mh-thread.elc} exists. If you have multiple versions and you -find that one is compiled but the other is not, then go into your -@file{*scratch*} buffer in Emacs, enter @kbd{load-path C-j}, and -ensure that the byte-compiled version appears first in the -@code{load-path}. If you find that MH-E is not compiled and you -installed MH-E yourself, please refer to the installation directions -in the file @file{README} in the distribution.}. - -@node Limits -@chapter Limiting Display - -@cindex limits -@cindex filters - -Another way to organize messages in a folder besides threading -(@pxref{Threading}) or using full-text indexed searches -(@pxref{Searching}) is by limiting the folder display to messages that -are similar to the current message. - -@table @kbd -@kindex / ? -@findex mh-prefix-help -@item / ? -Display cheat sheet for the commands of the current prefix in -minibuffer (@code{mh-prefix-help}). -@c ------------------------- -@cindex @samp{Sequence > Narrow to Tick Sequence} menu item -@cindex menu item, @samp{Sequence > Narrow to Tick Sequence} -@kindex / ' -@findex mh-narrow-to-tick -@item / ' -Limit to messages in the @samp{tick} sequence -(@code{mh-narrow-to-tick}). -@c ------------------------- -@kindex / c -@findex mh-narrow-to-cc -@item / c -Limit to messages with the same @samp{Cc:} field -(@code{mh-narrow-to-cc}). -@c ------------------------- -@kindex / m -@findex mh-narrow-to-from -@item / m -Limit to messages with the same @samp{From:} field -(@code{mh-narrow-to-from}). -@c ------------------------- -@kindex / g -@findex mh-narrow-to-range -@item / g -Limit to range (@code{mh-narrow-to-range}). -@c ------------------------- -@cindex @samp{Sequence > Narrow to Subject Sequence} menu item -@cindex menu item, @samp{Sequence > Narrow to Subject Sequence} -@kindex / s -@findex mh-narrow-to-subject -@item / s -Limit to messages with the same @samp{Subject:} field -(@code{mh-narrow-to-subject}). -@c ------------------------- -@kindex / t -@findex mh-narrow-to-to -@item / t -Limit to messages with the same @samp{To:} field -(@code{mh-narrow-to-to}). -@c ------------------------- -@cindex @samp{Sequence > Widen from Sequence} menu item -@cindex menu item, @samp{Sequence > Widen from Sequence} -@kindex / w -@findex mh-widen -@item / w -Remove last restriction (@code{mh-widen}). -@end table - -All of the limiting commands above refine the display in some way. - -@cindex @command{pick} -@cindex MH commands, @command{pick} -@findex mh-narrow-to-cc -@findex mh-narrow-to-from -@findex mh-narrow-to-subject -@findex mh-narrow-to-to -@kindex / c -@kindex / m -@kindex / s -@kindex / t - -The commands @kbd{/ c} (@code{mh-narrow-to-cc}), @kbd{/ m} -(@code{mh-narrow-to-from}), @kbd{/ s} (@code{mh-narrow-to-subject}), -and @kbd{/ t} (@code{mh-narrow-to-to}) restrict the display to -messages matching the content of the respective field in the current -message. However, you can give any of these a prefix argument to edit -the @command{pick} expression used to narrow the view@footnote{See -@command{pick}(1) or the section -@uref{@value{MH-BOOK-HOME}/finpic.html, Finding Messages with pick} in -the MH book.}. - -@cindex @samp{tick} sequence -@cindex sequence, @samp{tick} -@cindex ticked messages, viewing -@findex mh-narrow-to-range -@findex mh-narrow-to-tick -@kindex / ' -@kindex / g - -You can also limit the display to messages in the @samp{tick} sequence -with the command @kbd{/ '} (@code{mh-narrow-to-tick}). -@xref{Sequences}, for information on putting message into the -@samp{tick} sequence. Use the @kbd{/ g} (@code{mh-narrow-to-range}) -command to limit the display to messages in a range (@pxref{Ranges}). - -@findex mh-widen -@kindex / w - -Each limit can be undone in turn with the @kbd{/ w} (@code{mh-widen}) -command. Give this command a prefix argument to remove all limits. - -@node Sequences -@chapter Using Sequences - -@cindex @samp{Sequence} menu -@cindex menu, @samp{Sequence} -@cindex sequences - -For the whole scoop on MH sequences, refer to -@samp{mh-sequence}(5)@footnote{See the section -@uref{@value{MH-BOOK-HOME}/morseq.html, More About Sequences} in the MH -book.}. As you've read, several of the MH-E commands can operate on a -sequence, which is a shorthand for a range or group of messages. For -example, you might want to forward several messages to a friend or -colleague. Here's how to manipulate sequences. These commands are also -available in the @samp{Sequence} menu. - -@table @kbd -@cindex @samp{Sequence > Toggle Tick Mark} menu item -@cindex menu item, @samp{Sequence > Toggle Tick Mark} -@kindex ' -@findex mh-toggle-tick -@item ' -Toggle tick mark of range (@code{mh-toggle-tick}). -@c ------------------------- -@kindex S ? -@findex mh-prefix-help -@item S ? -Display cheat sheet for the commands of the current prefix in -minibuffer (@code{mh-prefix-help}). -@c ------------------------- -@cindex @samp{Sequence > Narrow to Tick Sequence} menu item -@cindex menu item, @samp{Sequence > Narrow to Tick Sequence} -@kindex S ' -@findex mh-narrow-to-tick -@item S ' -Limit to ticked messages (@code{mh-narrow-to-tick}). -@c ------------------------- -@cindex @samp{Sequence > Delete Message from Sequence...} menu item -@cindex menu item, @samp{Sequence > Delete Message from Sequence...} -@kindex S d -@findex mh-delete-msg-from-seq -@item S d -Delete range from sequence (@code{mh-delete-msg-from-seq}). -@c ------------------------- -@cindex @samp{Sequence > Delete Sequence...} menu item -@cindex menu item, @samp{Sequence > Delete Sequence...} -@kindex S k -@findex mh-delete-seq -@item S k -Delete sequence (@code{mh-delete-seq}). -@c ------------------------- -@cindex @samp{Sequence > List Sequences in Folder...} menu item -@cindex menu item, @samp{Sequence > List Sequences in Folder...} -@kindex S l -@findex mh-list-sequences -@item S l -List all sequences in folder (@code{mh-list-sequences}). -@c ------------------------- -@cindex @samp{Sequence > Narrow to Sequence...} menu item -@cindex menu item, @samp{Sequence > Narrow to Sequence...} -@kindex S n -@findex mh-narrow-to-seq -@item S n -Restrict display to messages in sequence (@code{mh-narrow-to-seq}). -@c ------------------------- -@cindex @samp{Sequence > Add Message to Sequence...} menu item -@cindex menu item, @samp{Sequence > Add Message to Sequence...} -@kindex S p -@findex mh-put-msg-in-seq -@item S p -Add range to sequence (@code{mh-put-msg-in-seq}). -@c ------------------------- -@cindex @samp{Sequence > List Sequences for Message} menu item -@cindex menu item, @samp{Sequence > List Sequences for Message} -@kindex S s -@findex mh-msg-is-in-seq -@item S s -Display the sequences in which the current message appears -(@code{mh-msg-is-in-seq}). -@c ------------------------- -@cindex @samp{Sequence > Widen from Sequence} menu item -@cindex menu item, @samp{Sequence > Widen from Sequence} -@kindex S w -@findex mh-widen -@item S w -Remove last restriction (@code{mh-widen}). -@c ------------------------- -@findex mh-update-sequences -@item M-x mh-update-sequences -Flush MH-E's state out to MH@. -@end table - -@cindex @samp{mh-sequences} customization group -@cindex customization group, @samp{mh-sequences} - -The @samp{mh-sequences} customization group contains the options -associated with sequences. - -@vtable @code -@item mh-refile-preserves-sequences-flag -On means that sequences are preserved when messages are refiled -(default: @samp{on}). -@c ------------------------- -@item mh-tick-seq -The name of the MH sequence for ticked messages (default: @samp{'tick}). -@c ------------------------- -@item mh-update-sequences-after-mh-show-flag -On means flush MH sequences to disk after message is shown (default: -@samp{on}). -@item mh-allowlist-preserves-sequences-flag -On means that sequences are preserved when messages are allowlisted -(default: @samp{on}). -@end vtable - -The following hook is available. - -@vtable @code -@item mh-unseen-updated-hook -Hook run after the unseen sequence has been updated (default: @code{nil}). -@end vtable - -@cindex @command{pick} -@cindex MH commands, @command{pick} -@findex mh-put-msg-in-seq -@kindex S p - -To place a message in a sequence, use @kbd{S p} -(@code{mh-put-msg-in-seq}). Give @kbd{S p} a range and you can add all -the messages in a sequence to another sequence (for example, @kbd{C-u -S p SourceSequence @key{RET} DestSequence @key{RET}}, @pxref{Ranges}). - -@cindex @samp{tick} sequence -@cindex sequence, @samp{tick} -@cindex ticking messages -@findex mh-index-ticked-messages -@findex mh-toggle-tick -@kindex ' -@kindex F ' -@kindex S p - -One specific use of the @kbd{S p} command is @kbd{'} -(@code{mh-toggle-tick}) which adds messages to the @samp{tick} -sequence. This sequence can be viewed later with the @kbd{F '} -(@code{mh-index-ticked-messages}) command (@pxref{Folders}). - -@vindex mh-tick-seq - -You can customize the option @code{mh-tick-seq} if you already use the -@samp{tick} sequence for your own use. You can also disable all of the -ticking functions by choosing the @samp{Disable Ticking} item but -there isn't much advantage to that. - -@cindex MH-Folder mode -@cindex modes, MH-Folder -@findex mh-narrow-to-seq -@findex mh-narrow-to-tick -@findex mh-widen -@kindex S ' -@kindex S n -@kindex S w - -Once you've placed some messages in a sequence, you may wish to narrow -the field of view to just those messages in the sequence you've -created. To do this, use @kbd{S n} (@code{mh-narrow-to-seq}). You are -prompted for the name of the sequence. What this does is show only -those messages that are in the selected sequence in the MH-Folder -buffer. In addition, it limits further MH-E searches to just those -messages. To narrow the view to the messages in the @samp{tick} -sequence, use @kbd{S '} (@code{mh-narrow-to-tick}). When you want to -widen the view to all your messages again, use @kbd{S w} -(@code{mh-widen}). - -@cindex buffers, @file{*MH-E Sequences*} -@cindex @file{*MH-E Sequences*} -@findex mh-list-sequences -@findex mh-msg-is-in-seq -@kindex S l -@kindex S s - -You can see which sequences in which a message appears with the -command @kbd{S s} (@code{mh-msg-is-in-seq}). Use a prefix argument to -display the sequences in which another message appears (as in @kbd{C-u -42 S s @key{RET}}). Or, you can list all sequences in a selected -folder (default is current folder) with @kbd{S l} -(@code{mh-list-sequences}). The list appears in a buffer named -@file{*MH-E Sequences*} (@pxref{Miscellaneous}). - -@cindex MH profile component, @samp{Previous-Sequence} -@cindex @samp{cur} sequence -@cindex @samp{Previous-Sequence} MH profile component -@cindex sequence, @samp{cur} -@cindex sequence, @samp{Previous-Sequence} -@vindex mh-refile-preserves-sequences-flag - -If a message is in any sequence (except -@samp{Previous-Sequence:}@footnote{See @samp{mh-profile}(5)).} and -@samp{cur}) when it is refiled, then it will still be in those -sequences in the destination folder. If this behavior is not desired, -then turn off the option @code{mh-refile-preserves-sequences-flag}. - -@findex mh-delete-msg-from-seq -@findex mh-delete-seq -@kindex d -@kindex S d -@kindex S k - -If you want to remove a message (or range, @pxref{Ranges}) from a -sequence, use @kbd{S d} (@code{mh-delete-msg-from-seq}). If you want -to delete an entire sequence, use @kbd{S k} (@code{mh-delete-seq}). In -the latter case you are prompted for the sequence to delete. Note that -this deletes only the sequence, not the messages in the sequence. If -you want to delete the messages, use @kbd{C-u d} (@pxref{Reading -Mail}). - -@cindex @samp{Unseen-Sequence} MH profile component -@cindex @samp{cur} sequence -@cindex @samp{tick} sequence -@cindex MH profile component, @samp{Unseen-Sequence} -@cindex sequence, @samp{Unseen-Sequence} -@cindex sequence, @samp{cur} -@cindex sequence, @samp{tick} -@findex mh-update-sequences -@kindex q -@kindex x -@vindex mh-tick-seq -@vindex mh-update-sequences-after-mh-show-flag - -Three sequences are maintained internally by MH-E and pushed out to MH -when a message is shown. They include the sequence specified by your -@samp{Unseen-Sequence:} profile component, @samp{cur}, and the -sequence listed by the option @code{mh-tick-seq} which is @samp{tick} -by default. If you do not like this behavior, turn off the option -@code{mh-update-sequences-after-mh-show-flag}. You can then update the -state manually with the @kbd{x}, @kbd{q}, or @kbd{M-x -mh-update-sequences} commands. - -@vindex mh-seen-list -@vindex mh-unseen-updated-hook - -The hook @code{mh-unseen-updated-hook} is run after the unseen -sequence has been updated. The variable @code{mh-seen-list} can be -used by this hook to obtain the list of messages which were removed -from the unseen sequence. - -@cindex @command{mark} -@cindex MH commands, @command{mark} -@kindex S n -@kindex S w - -With the exceptions of @kbd{S n} and @kbd{S w}, the underlying MH -command dealing with sequences is @command{mark}@footnote{See the -section @uref{@value{MH-BOOK-HOME}/mmbwm.html, Make Message Bookmarks -with mark} in the MH book.}. - -@node Junk -@chapter Dealing With Junk Mail - -@cindex Marshall Rose -@cindex junk mail -@cindex spam - -Marshall Rose once wrote a paper on MH entitled, @cite{How to process -200 messages a day and still get some real work done}. This chapter -could be entitled, @cite{How to process 1000 spams a day and still get -some real work done}. - -@cindex blocklisting -@cindex ham -@cindex viruses -@cindex allowlisting -@cindex worms - -We use the terms @dfn{junk mail} and @dfn{spam} interchangeably for -any unwanted message which includes spam, @dfn{viruses}, and -@dfn{worms}. The opposite of spam is @dfn{ham}. The act of classifying -a sender as one who sends junk mail is called @dfn{blocklisting}; the -opposite is called @dfn{allowlisting}. - -@table @kbd -@kindex J ? -@findex mh-prefix-help -@item J ? -Display cheat sheet for the commands of the current prefix in -minibuffer (@code{mh-prefix-help}). -@c ------------------------- -@kindex J b -@findex mh-junk-blocklist -@item J b -Blocklist range as spam (@code{mh-junk-blocklist}). -@c ------------------------- -@kindex J a -@findex mh-junk-allowlist -@item J a -Allowlist range as ham (@code{mh-junk-allowlist}). -@c ------------------------- -@item @code{mh-spamassassin-identify-spammers} -Identify spammers who are repeat offenders. -@end table - -@cindex @samp{mh-junk} customization group -@cindex customization group, @samp{mh-junk} - -The following table lists the options from the @samp{mh-junk} -customization group. - -@vtable @code -@item mh-junk-background -If on, spam programs are run in background (default: @samp{off}). -@c ------------------------- -@item mh-junk-disposition -Disposition of junk mail (default: @samp{Delete Spam}). -@c ------------------------- -@item mh-junk-program -Spam program that MH-E should use (default: @samp{Auto-detect}). -@end vtable - -@cindex @samp{mh-sequences} customization group -@cindex customization group, @samp{mh-sequences} - -The following option in the @samp{mh-sequences} customization group is -also available. - -@vtable @code -@item mh-allowlist-preserves-sequences-flag -On means that sequences are preserved when messages are allowlisted -(default: @samp{on}). -@end vtable - -The following hooks are available. - -@vtable @code -@item mh-blocklist-msg-hook -Hook run by @kbd{J b} (@code{mh-junk-blocklist}) after marking each -message for blocklisting (default: @code{nil}). -@c ------------------------- -@item mh-allowlist-msg-hook -Hook run by @kbd{J a} (@code{mh-junk-allowlist}) after marking each -message for allowlisting (default @samp{nil}). -@end vtable - -The following faces are available. - -@vtable @code -@item mh-folder-blocklisted -Blocklisted message face. -@c ------------------------- -@item mh-folder-allowlisted -Allowlisted message face -@end vtable - -@cindex SpamProbe -@cindex SpamAssassin -@cindex bogofilter -@cindex spam filters, SpamProbe -@cindex spam filters, SpamAssassin -@cindex spam filters, bogofilter - -MH-E depends on @uref{https://spamassassin.apache.org/, SpamAssassin}, -@uref{https://bogofilter.sourceforge.net/, bogofilter}, or -@uref{https://spamprobe.sourceforge.net/, SpamProbe} to throw the dreck -away. This chapter describes briefly how to configure these programs -to work well with MH-E and how to use MH-E's interface that provides -continuing education for these programs. - -@vindex mh-junk-program - -The default setting of the option @code{mh-junk-program} is -@samp{Auto-detect} which means that MH-E will automatically choose one -of SpamAssassin, bogofilter, or SpamProbe in that order. If, for -example, you have both SpamAssassin and bogofilter installed and you -want to use bogofilter, then you can set this option to -@samp{Bogofilter}. - -@findex mh-junk-blocklist -@kindex J b -@vindex mh-junk-disposition - -The command @kbd{J b} (@code{mh-junk-blocklist}) trains the spam -program in use with the content of the range (@pxref{Ranges}) and then -handles the message(s) as specified by the option -@code{mh-junk-disposition}. By default, this option is set to -@samp{Delete Spam} but you can also specify the name of the folder -which is useful for building a corpus of spam for training purposes. - -@findex mh-junk-allowlist -@kindex J a - -In contrast, the command @kbd{J a} (@code{mh-junk-allowlist}) -reclassifies a range of messages (@pxref{Ranges}) as ham if it were -incorrectly classified as spam. It then refiles the message into the -@file{+inbox} folder. - -@cindex MH profile component, @samp{Previous-Sequence} -@cindex @samp{cur} sequence -@cindex @samp{Previous-Sequence} MH profile component -@cindex sequence, @samp{cur} -@cindex sequence, @samp{Previous-Sequence} -@vindex mh-allowlist-preserves-sequences-flag - -If a message is in any sequence (except @samp{Previous-Sequence:} and -@samp{cur}) when it is allowlisted, then it will still be in those -sequences in the destination folder. If this behavior is not desired, -then turn off the option @code{mh-allowlist-preserves-sequences-flag}. - -@cindex @file{*MH-E Log*} -@cindex buffers, @file{*MH-E Log*} -@findex call-process -@vindex mh-junk-background - -By default, the programs are run in the foreground, but this can be -slow when junking large numbers of messages. If you have enough memory -or don't junk that many messages at the same time, you might try -turning on the option @code{mh-junk-background}. @footnote{Note that -the option @code{mh-junk-background} is used as the @code{destination} -argument in the call to @code{call-process}. Therefore, turning on -this option means setting its value to @samp{0}. You can also set its -value to @samp{t} to direct the programs' output to the @file{*MH-E -Log*} buffer; this may be useful for debugging.} - -The following sections discuss the various counter-spam measures that -MH-E can work with. - -@cindex @file{.procmailrc} -@cindex files, @file{.procmailrc} - -@subheading SpamAssassin - -@cindex SpamAssassin -@cindex spam filters, SpamAssassin - -SpamAssassin is one of the more popular spam filtering programs. Get -it from your local distribution or from the -@uref{https://spamassassin.apache.org/, SpamAssassin web site}. - -To use SpamAssassin, add the following recipes to @file{~/.procmailrc}: - -@cindex @command{spamc} -@cindex @samp{X-Spam-Level} header field -@cindex @samp{X-Spam-Status} header field -@cindex header field, @samp{X-Spam-Level} -@cindex header field, @samp{X-Spam-Status} - -@smallexample -PATH=$PATH:/usr/bin/mh -MAILDIR=$HOME/`mhparam Path` - -# Fight spam with SpamAssassin. -: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/. -@end smallexample - -If you don't use @command{spamc}, use @samp{spamassassin -P -a}. - -Note that one of the recipes above throws away messages with a score -greater than or equal to 10. Here's how you can determine a value that -works best for you. - -First, run @samp{spamassassin -t} on every mail message in your -archive and use @command{gnumeric} to verify that the average plus the -standard deviation of good mail is under 5, the SpamAssassin default -for ``spam''. - -Using @command{gnumeric}, sort the messages by score and view the -messages with the highest score. Determine the score which encompasses -all of your interesting messages and add a couple of points to be -conservative. Add that many dots to the @samp{X-Spam-Level:} header -field above to send messages with that score down the drain. - -In the example above, messages with a score of 5--9 are set aside in -the @samp{+spam} folder for later review. The major weakness of -rules-based filters is a plethora of false positives so it is -worthwhile to check. - -@findex mh-junk-blocklist -@findex mh-junk-allowlist -@kindex J b -@kindex J a - -If SpamAssassin classifies a message incorrectly, or is unsure, you can -use the MH-E commands @kbd{J b} (@code{mh-junk-blocklist}) and -@kbd{J a} (@code{mh-junk-allowlist}). - -@cindex @command{sa-learn} -@cindex @file{.spamassassin/user_prefs} -@cindex files, @file{.spamassassin/user_prefs} - -The command @kbd{J b} (@code{mh-junk-blocklist}) adds a -@samp{blacklist_from} entry to @file{~/spamassassin/user_prefs}, -deletes the message, and sends the message to the Razor, so that -others might not see this spam. If the @command{sa-learn} command is -available, the message is also recategorized as spam. - -The command@kbd{J a} (@code{mh-junk-allowlist}) adds a -@samp{whitelist_from} rule to @samp{~/.spamassassin/user_prefs}. If -the @command{sa-learn} command is available, the message is also -recategorized as ham. - -Over time, you'll observe that the same host or domain occurs -repeatedly in the @samp{blacklist_from} entries, so you might think -that you could avoid future spam by blocklisting all mail from a -particular domain. The utility function -@code{mh-spamassassin-identify-spammers} helps you do precisely that. -This function displays a frequency count of the hosts and domains in -the @samp{blacklist_from} entries from the last blank line in -@file{~/.spamassassin/user_prefs} to the end of the file. This -information can be used so that you can replace multiple -@samp{blacklist_from} entries with a single wildcard entry such as: - -@smallexample -blacklist_from *@@*amazingoffersdirect2u.com -@end smallexample - -In versions of SpamAssassin (2.50 and on) that support a Bayesian -classifier, @kbd{J b} @code{(mh-junk-blocklist}) uses the program -@command{sa-learn} to recategorize the message as spam. Neither MH-E, -nor SpamAssassin, rebuilds the database after adding words, so you -will need to run @samp{sa-learn --rebuild} periodically. This can be -done by adding the following to your @file{crontab}: - -@smallexample -0 * * * * sa-learn --rebuild > /dev/null 2>&1 -@end smallexample - -@subheading Bogofilter - -@cindex bogofilter -@cindex spam filters, bogofilter - -Bogofilter is a Bayesian spam filtering program. Get it from your -local distribution or from the -@uref{https://bogofilter.sourceforge.net/, bogofilter web site}. - -Bogofilter is taught by running: - -@smallexample -bogofilter -n < good-message -@end smallexample - -on every good message, and - -@smallexample -bogofilter -s < spam-message -@end smallexample - -@cindex full training - -on every spam message. This is called a @dfn{full training}; three -other training methods are described in the FAQ that is distributed -with bogofilter. Note that most Bayesian filters need 1000 to 5000 of -each type of message to start doing a good job. - -To use bogofilter, add the following recipes to @file{~/.procmailrc}: - -@cindex @samp{X-Bogosity} header field -@cindex header field, @samp{X-Bogosity} - -@smallexample -PATH=$PATH:/usr/bin/mh -MAILDIR=$HOME/`mhparam Path` - -# Fight spam with Bogofilter. -:0fw -| bogofilter -3 -e -p - -:0: -* ^X-Bogosity: Yes, tests=bogofilter -spam/. - -:0: -* ^X-Bogosity: Unsure, tests=bogofilter -spam/unsure/. -@end smallexample - -@findex mh-junk-blocklist -@findex mh-junk-allowlist -@kindex J b -@kindex J a - -If bogofilter classifies a message incorrectly, or is unsure, you can -use the MH-E commands @kbd{J b} (@code{mh-junk-blocklist}) and -@kbd{J a} (@code{mh-junk-allowlist}) to update bogofilter's training. - -The @cite{Bogofilter FAQ} suggests that you run the following -occasionally to shrink the database: - -@smallexample -bogoutil -d wordlist.db | bogoutil -l wordlist.db.new -mv wordlist.db wordlist.db.prv -mv wordlist.db.new wordlist.db -@end smallexample - -The @cite{Bogofilter tuning HOWTO} describes how you can fine-tune -bogofilter. - -@subheading SpamProbe - -@cindex SpamProbe -@cindex spam filters, SpamProbe - -SpamProbe is a Bayesian spam filtering program. Get it from your local -distribution or from the @uref{https://spamprobe.sourceforge.net, -SpamProbe web site}. - -To use SpamProbe, add the following recipes to @file{~/.procmailrc}: - -@cindex @command{formail} -@cindex @samp{X-SpamProbe} header field -@cindex header field, @samp{X-SpamProbe} - -@smallexample -PATH=$PATH:/usr/bin/mh -MAILDIR=$HOME/`mhparam Path` - -# Fight spam with SpamProbe. -:0 -SCORE=| spamprobe receive - -:0 wf -| formail -I "X-SpamProbe: $SCORE" - -:0: -*^X-SpamProbe: SPAM -spam/. -@end smallexample - -@findex mh-junk-blocklist -@findex mh-junk-allowlist -@kindex J b -@kindex J a - -If SpamProbe classifies a message incorrectly, you can use the MH-E -commands @kbd{J b} (@code{mh-junk-blocklist}) and @kbd{J a} -(@code{mh-junk-allowlist}) to update SpamProbe's training. - -@subheading Other Things You Can Do - -There are a couple of things that you can add to @file{~/.procmailrc} -in order to filter out a lot of spam and viruses. The first is to -eliminate any message with a Windows executable (which is most likely -a virus). The second is to eliminate mail in character sets that you -can't read. - -@cindex @samp{Content-Transfer-Encoding} header field -@cindex @samp{Content-Type} header field -@cindex @samp{Subject} header field -@cindex header field, @samp{Content-Transfer-Encoding} -@cindex header field, @samp{Content-Type} -@cindex header field, @samp{Subject} - -@smallexample -PATH=$PATH:/usr/bin/mh -MAILDIR=$HOME/`mhparam Path` - -# -# Filter messages with w32 executables/virii. -# -# These attachments are base64 and have a TVqQAAMAAAAEAAAA//8AALg -# pattern. The string "this program cannot be run in MS-DOS mode" -# encoded in base64 is 4fug4AtAnNIbg and helps to avoid false -# positives (Roland Smith via Pete from the bogofilter mailing list). -# -:0 B: -* ^Content-Transfer-Encoding:.*base64 -* ^TVqQAAMAAAAEAAAA//8AALg -* 4fug4AtAnNIbg -spam/exe/. - -# -# Filter mail in unreadable character sets (from the Bogofilter FAQ). -# -UNREADABLE='[^?"]*big5|iso-2022-jp|ISO-2022-KR|euc-kr|gb2312|ks_c_5601-1987' - -:0: -* 1^0 $ ^Subject:.*=\?($UNREADABLE) -* 1^0 $ ^Content-Type:.*charset="?($UNREADABLE) -spam/unreadable/. - -:0: -* ^Content-Type:.*multipart -* B ?? $ ^Content-Type:.*^?.*charset="?($UNREADABLE) -spam/unreadable/. -@end smallexample - -@node Miscellaneous -@chapter Miscellaneous Commands, Variables, and Buffers - -This chapter covers the following command and the various MH-E -buffers, - -@ftable @code -@item mh-version -Display version information about MH-E and the MH mail handling -system. -@end ftable - -@cindex buffers, @file{*MH-E Info*} -@cindex MH-E version -@cindex @file{*MH-E Info*} -@cindex version -@findex mh-version - -One command worth noting is @kbd{M-x mh-version}. You can compare the -version this command prints to the latest release (@pxref{Getting -MH-E}). The output of @kbd{M-x mh-version}, found in a buffer named -@file{*MH-E Info*}, should usually be included with any bug report you -submit (@pxref{Bug Reports}). - -@subheading MH-E Buffers - -Besides the MH-Folder, MH-Show, and MH-Letter buffers, MH-E creates -several other buffers. They are: - -@table @samp -@cindex @file{*MH-E Folders*} -@cindex buffers, @file{*MH-E Folders*} -@findex mh-list-folders -@item *MH-E Folders* -@kindex F l -This buffer contains the output of @kbd{F l} (@code{mh-list-folders}). -@xref{Folders}. -@c ------------------------- -@cindex @file{*MH-E Help*} -@cindex buffers, @file{*MH-E Help*} -@findex mh-help -@item *MH-E Help* -@kindex ? -@kindex C-c ? -This buffer contains the output of @kbd{?} (@code{mh-help}) and -@kbd{C-c ?} in MH-Letter mode. @xref{Using This Manual}. -@c ------------------------- -@cindex @file{*MH-E Info*} -@cindex buffers, @file{*MH-E Info*} -@item *MH-E Info* -This buffer contains the output of @kbd{M-x mh-version @key{RET}}. -@c ------------------------- -@cindex @file{*MH-E Log*} -@cindex buffers, @file{*MH-E Log*} -@item *MH-E Log* -This buffer contains the last 100 lines of the output of the various -MH commands. -@c ------------------------- -@cindex @file{*MH-E Mail Delivery*} -@cindex buffers, @file{*MH-E Mail Delivery*} -@item *MH-E Mail Delivery* -This buffer contains the transcript of a mail delivery. @xref{Sending -Message}. -@c ------------------------- -@cindex @file{*MH-E Recipients*} -@cindex buffers, @file{*MH-E Recipients*} -@findex mh-check-whom -@item *MH-E Recipients* -@kindex C-c C-w -This buffer contains the output of @kbd{C-c C-w} -(@code{mh-check-whom}) and is killed when draft is sent. -@xref{Checking Recipients}. -@c ------------------------- -@cindex @file{*MH-E Sequences*} -@cindex buffers, @file{*MH-E Sequences*} -@item *MH-E Sequences* -This buffer contains the output of @kbd{S l} -(@code{mh-list-sequences}). @xref{Sequences}. -@c ------------------------- -@cindex @file{*mh-temp*} -@cindex buffers, @file{*mh-temp*} -@item *mh-temp* -This is a scratch, ephemeral, buffer used by MH-E functions. Note that -it is hidden because the first character in the name is a space. -You'll generally not have any need for this buffer. -@end table - -@node Scan Line Formats -@appendix Scan Line Formats - -@cindex scan line formats - -This appendix discusses how MH-E creates, parses, and manipulates scan -lines. If you have your own MH scan or inc format files, you -@strong{can} teach MH-E how to handle them, but it isn't easy as -you'll see. - -@cindex @samp{mh-scan-line-formats} customization group -@cindex customization group, @samp{mh-scan-line-formats} - -This table lists the options in the @samp{mh-scan-line-formats} -customization group. - -@vtable @code -@item mh-adaptive-cmd-note-flag -On means that the message number width is determined dynamically -(default: @samp{on}). -@c ------------------------- -@item mh-scan-format-file -Specifies the format file to pass to the scan program (default: -@samp{Use MH-E scan Format}). -@c ------------------------- -@item mh-scan-prog -Program used to scan messages (default: @code{"scan"}). -@end vtable - -@vindex mh-adaptive-cmd-note-flag - -There are a couple of caveats when creating your own scan format file. -First, MH-E will not work if your scan lines do not include message -numbers. It will work poorly if you don't dedicate a column for -showing the current message and notations. It is also best to keep the -first column empty to make room for the cursor and so that text isn't -obscured by the current message's overlay arrow when running in a -terminal. You won't be able to use the option -@code{mh-adaptive-cmd-note-flag} or the threading features -(@pxref{Threading}). - -@cindex message numbers -@findex mh-set-cmd-note -@vindex mh-adaptive-cmd-note-flag -@vindex mh-scan-format-file - -If you've created your own format to handle long message numbers, -you'll be pleased to know you no longer need it since MH-E adapts its -internal format based upon the largest message number if -@code{mh-adaptive-cmd-note-flag} is on (the default). If you prefer -fixed-width message numbers, turn off @code{mh-adaptive-cmd-note-flag} -and call @code{mh-set-cmd-note} with the width specified by your -format file (see @code{mh-scan-format-file}). For example, the default -width is 4, so you would use @samp{(mh-set-cmd-note 4)}. - -@vindex mh-adaptive-cmd-note-flag -@vindex mh-scan-format-file -@vindex mh-scan-format-mh -@vindex mh-scan-format-nmh - -The default setting for @code{mh-scan-format-file} is @samp{Use MH-E -scan Format}. This means that the format string will be taken from -either @code{mh-scan-format-mh} or @code{mh-scan-format-nmh} depending -on whether MH or nmh (or GNU mailutils MH) is in use. This setting -also enables you to turn on the option -@code{mh-adaptive-cmd-note-flag}. You can also set this option to -@samp{Use Default scan Format} to get the same output as you would get -if you ran @command{scan} from the shell. If you have a format file -that you want MH-E to use but not MH, you can set this option to -@samp{Specify a scan Format File} and enter the name of your format -file. - -@vindex mh-scan-format-file -@vindex mh-scan-format-mh -@vindex mh-scan-format-nmh - -The scan format that MH-E uses when @code{mh-scan-format-file} is set -to its default of @samp{Use MH-E scan Format} is held in the variables -@code{mh-scan-format-nmh} and @code{mh-scan-format-mh} depending on -whether you are using nmh (or GNU mailutils MH) or not. Typically, you -create your own format files rather than modifying these variables. -The value of @code{mh-scan-format-nmh} is: - -@smallexample -(concat - "%4(msg)" - "%<(cur)+%| %>" - "%<@{replied@}-" - "%?(nonnull(comp@{to@}))%<(mymbox@{to@})t%>" - "%?(nonnull(comp@{cc@}))%<(mymbox@{cc@})c%>" - "%?(nonnull(comp@{bcc@}))%<(mymbox@{bcc@})b%>" - "%?(nonnull(comp@{newsgroups@}))n%>" - "%<(zero) %>" - "%02(mon@{date@})/%02(mday@{date@})%<@{date@} %|*%>" - "%<(mymbox@{from@})%<@{to@}To:%14(decode(friendly@{to@}))%>%>" - "%<(zero)%17(decode(friendly@{from@}))%> " - "%(decode@{subject@})%<@{body@}<<%@{body@}%>") -@end smallexample - -@cindex decoding RFC 2047 -@cindex RFC 2047, decoding -@vindex mh-scan-format-mh - -The setting for @code{mh-scan-format-mh} is similar, except that MH -doesn't have the function @code{decode} (which is used to decode RFC -2047 encodings). - -@cindex notations, scan line -@cindex scan line notations - -These strings are passed to the @command{scan} program via the -@option{-format} argument. The formats are identical to the defaults -except that additional hints for fontification have been added to the -existing notations in the fifth column (remember that in Emacs, the -columns start at 0). The values of the fifth column, in priority -order, are: @samp{-} if the message has been replied to, @samp{t} if -an address in the @samp{To:} field matches one of the mailboxes of the -current user, @samp{c} if the @samp{Cc:} field matches, @samp{b} if -the @samp{Bcc:} field matches, and @samp{n} if a non-empty -@samp{Newsgroups:} field is present. - -@cindex @command{scan} -@cindex MH commands, @command{scan} -@vindex mh-progs -@vindex mh-scan-prog - -The name of the program that generates a listing of one line per -message is held in @code{mh-scan-prog} (default: @code{"scan"}). -Unless this variable contains an absolute pathname, it is assumed to -be in the @code{mh-progs} directory (@pxref{Getting Started}). You may -link another program to @command{scan} (see @samp{mh-profile}(5)) to -produce a different type of listing@footnote{See the section -@uref{@value{MH-BOOK-HOME}/faswsprs.html, Find and Specify with scan -pick Ranges Sequences} in the MH book.}. - -@cindex regular expressions, scan line formats -@findex mh-set-cmd-note -@findex setq - -If you change the format of the scan lines you'll need to tell MH-E -how to parse the new format. As you will see, quite a lot of variables -are involved to do that. Use @kbd{M-x apropos @key{RET} -mh-scan.*regexp @key{RET}} to obtain a list of these variables. You -will also have to call @code{mh-set-cmd-note} if your notations are -not in column 4 (columns in Emacs start with 0). Note that unlike most -of the user options described in this manual, these are variables and -must be set with @code{setq} instead of in a customization buffer. For -help with regular expressions, see -@ifnothtml -@ref{Regexps, , Syntax of Regular Expressions, emacs, The -GNU Emacs Manual}. -@end ifnothtml -@ifhtml -section -@uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Regexps.html, -Syntax of Regular Expressions} in @cite{The GNU Emacs Manual}. -@end ifhtml - -The first variable has to do with pruning out garbage. - -@vtable @code -@cindex @command{inc} -@cindex MH commands, @command{inc} -@cindex @command{scan} -@cindex MH commands, @command{scan} -@item mh-scan-valid-regexp -This regular expression describes a valid scan line. This is used to -eliminate error messages that are occasionally produced by -@command{inc}@footnote{See the section -@uref{@value{MH-BOOK-HOME}/reapre.html, Reading Mail: inc show next -prev} in the MH book.} or @command{scan} (default: @code{"^ *[0-9]"}). -@end vtable - -Next, many variables control how the scan lines are parsed. - -@vtable @code -@vindex mh-folder-body -@vindex mh-folder-font-lock-keywords -@item mh-scan-body-regexp -This regular expression matches the message body fragment. Note that -the default setting of @code{mh-folder-font-lock-keywords} expects -this expression to contain at least one parenthesized expression which -matches the body text as in the default of -@code{"\\(<<\\([^\n]+\\)?\\)"}. If this regular expression is not -correct, the body fragment will not be highlighted with the face -@code{mh-folder-body}. -@c ------------------------- -@vindex mh-folder-cur-msg-number -@vindex mh-folder-font-lock-keywords -@vindex mh-note-cur -@item mh-scan-cur-msg-number-regexp -This regular expression matches the current message. It must match -from the beginning of the line. Note that the default setting of -@code{mh-folder-font-lock-keywords} expects this expression to contain -at least one parenthesized expression which matches the message number -as in the default of @w{@code{"^\\( *[0-9]+\\+\\).*"}}. This -expression includes the leading space and current message marker -@samp{+} within the parenthesis since it looks better to highlight -these items as well. The highlighting is done with the face -@code{mh-folder-cur-msg-number}. This regular expression should be -correct as it is needed by non-fontification functions. See also -@code{mh-note-cur}. -@c ------------------------- -@vindex mh-folder-date -@vindex mh-folder-font-lock-keywords -@vindex mh-scan-sent-to-me-sender-regexp -@item mh-scan-date-regexp -This regular expression matches a valid date. It must @strong{not} be -anchored to the beginning or the end of the line. Note that the -default setting of @code{mh-folder-font-lock-keywords} expects this -expression to contain only one parenthesized expression which matches -the date field as in the default of -@code{"\\([0-9][0-9]/[0-9][0-9]\\)"}. If this regular expression is -not correct, the date will not be highlighted with the face -@code{mh-folder-date}. -@c ------------------------- -@vindex mh-folder-deleted -@vindex mh-folder-font-lock-keywords -@vindex mh-note-deleted -@item mh-scan-deleted-msg-regexp -This regular expression matches deleted messages. It must match from -the beginning of the line. Note that the default setting of -@code{mh-folder-font-lock-keywords} expects this expression to contain -at least one parenthesized expression which matches the message number -as in the default of @code{"^\\( *[0-9]+\\)D"}. This expression -includes the leading space within the parenthesis since it looks -better to highlight it as well. The highlighting is done with the face -@code{mh-folder-deleted}. This regular expression should be correct as -it is needed by non-fontification functions. See also -@code{mh-note-deleted}. -@c ------------------------- -@vindex mh-folder-font-lock-keywords -@vindex mh-folder-msg-number -@item mh-scan-good-msg-regexp -This regular expression matches ``good'' messages. It must match from -the beginning of the line. Note that the default setting of -@code{mh-folder-font-lock-keywords} expects this expression to contain -at least one parenthesized expression which matches the message number -as in the default of @w{@code{"^\\( *[0-9]+\\)[^D^0-9]"}}. This -expression includes the leading space within the parenthesis since it -looks better to highlight it as well. The highlighting is done with -the face @code{mh-folder-msg-number}. This regular expression should -be correct as it is needed by non-fontification functions. -@c ------------------------- -@vindex mh-scan-format-file -@item mh-scan-msg-format-regexp -This regular expression finds the message number width in a scan -format. Note that the message number must be placed in a parenthesized -expression as in the default of @code{"%\\([0-9]*\\)(msg)"}. This -variable is only consulted if @code{mh-scan-format-file} is set to -@samp{Use MH-E scan Format}. -@c ------------------------- -@vindex mh-scan-format-file -@item mh-scan-msg-format-string -This is a format string for the width of the message number in a scan -format. Use @samp{0%d} for zero-filled message numbers. This variable -is only consulted if @code{mh-scan-format-file} is set to @samp{Use -MH-E scan Format} (default: @code{"%d"}). -@c ------------------------- -@item mh-scan-msg-number-regexp -This regular expression extracts the message number. It must match -from the beginning of the line. Note that the message number must be -placed in a parenthesized expression as in the default of @w{@code{"^ -*\\([0-9]+\\)"}}. -@c ------------------------- -@item mh-scan-msg-overflow-regexp -This regular expression matches overflowed message numbers (default: -@code{"^[?0-9][0-9]"}). -@c ------------------------- -@item mh-scan-msg-search-regexp -This regular expression matches a particular message. It is a format -string; use @samp{%d} to represent the location of the message number -within the expression as in the default of @code{"^[^0-9]*%d[^0-9]"}. -@c ------------------------- -@vindex mh-folder-address -@vindex mh-folder-font-lock-keywords -@vindex mh-folder-to -@item mh-scan-rcpt-regexp -This regular expression specifies the recipient in messages you sent. -Note that the default setting of @code{mh-folder-font-lock-keywords} -expects this expression to contain two parenthesized expressions. The -first is expected to match the @samp{To:} that the default scan format -file generates. The second is expected to match the recipient's name -as in the default of @code{"\\(To:\\)\\(..............\\)"}. If this -regular expression is not correct, the @samp{To:} string will not be -highlighted with the face @code{mh-folder-to} and the recipient will not be -highlighted with the face @code{mh-folder-address}. -@c ------------------------- -@vindex mh-folder-font-lock-keywords -@vindex mh-folder-refiled -@vindex mh-note-refiled -@item mh-scan-refiled-msg-regexp -This regular expression matches refiled messages. It must match from -the beginning of the line. Note that the default setting of -@code{mh-folder-font-lock-keywords} expects this expression to contain -at least one parenthesized expression which matches the message number -as in the default of @w{@code{"^\\( *[0-9]+\\)\\^"}}. This expression -includes the leading space within the parenthesis since it looks -better to highlight it as well. The highlighting is done with the face -@code{mh-folder-refiled}. This regular expression should be correct as -it is needed by non-fontification functions. See also -@code{mh-note-refiled}. -@c ------------------------- -@vindex mh-folder-font-lock-keywords -@vindex mh-folder-sent-to-me-sender -@vindex mh-mh-folder-sent-to-me-hint -@vindex mh-scan-format-nmh -@item mh-scan-sent-to-me-sender-regexp -This regular expression matches messages sent to us. Note that the -default setting of @code{mh-folder-font-lock-keywords} expects this -expression to contain at least two parenthesized expressions. The -first should match the fontification hint (see -@code{mh-scan-format-nmh}) and the second should match the user name -as in the default of -@w{@code{"^ *[0-9]+.\\([bct]\\).....[ ]*\\(..................\\)"}}. -If this regular expression is not correct, the notation hints will not -be highlighted with the face @code{mh-mh-folder-sent-to-me-hint} and -the sender will not be highlighted with the face -@code{mh-folder-sent-to-me-sender}. -@c ------------------------- -@vindex mh-folder-followup -@vindex mh-folder-font-lock-keywords -@vindex mh-folder-subject -@item mh-scan-subject-regexp -This regular expression matches the subject. It must match from the -beginning of the line. Note that the default setting of -@samp{mh-folder-font-lock-keywords} expects this expression to contain -at least three parenthesized expressions. The first is expected to -match the @samp{Re:} string, if any, and is highlighted with the face -@code{mh-folder-followup}. The second matches an optional bracketed -number after @samp{Re:}, such as in @samp{Re[2]:} (and is thus a -sub-expression of the first expression). The third is expected to -match the subject line itself which is highlighted with the face -@code{mh-folder-subject}. For example, the default is -@w{@code{"^ *[0-9]+........[ ]*...................}}@* -@w{@code{\\([Rr][Ee]\\(\\[[0-9]+\\]\\)?:\\s-*\\)*\\([^<\n]*\\)"}}. -This regular expression should be correct as it is needed by -non-fontification functions. Note that this example is broken up on -two lines for readability, but is actually a single string. -@end vtable - -Finally, there are a slew of variables that control how MH-E annotates -the scan lines. - -@vtable @code -@findex mh-set-cmd-note -@vindex mh-adaptive-cmd-note-flag -@item mh-cmd-note -Column for notations (default: 4). This variable should be set with -the function @code{mh-set-cmd-note}. This variable may be updated -dynamically if @code{mh-adaptive-cmd-note-flag} is on. The following -variables contain the notational characters. Note that columns in -Emacs start with 0. -@c ------------------------- -@item mh-note-copied -Messages that have been copied are marked by this character (default: -@code{?C}). -@c ------------------------- -@vindex mh-scan-cur-msg-number-regexp -@item mh-note-cur -The current message (in MH, not in MH-E) is marked by this character -(default: @code{?+}). See also @code{mh-scan-cur-msg-number-regexp}. -@c ------------------------- -@vindex mh-scan-deleted-msg-regexp -@item mh-note-deleted -Messages that have been deleted are marked by this character (default: -@code{?D}). See also @code{mh-scan-deleted-msg-regexp}. -@c ------------------------- -@item mh-note-dist -Messages that have been redistributed are marked by this character -(default: @code{?R}). -@c ------------------------- -@item mh-note-forw -Messages that have been forwarded are marked by this character -(default: @code{?F}). -@c ------------------------- -@item mh-note-printed -Messages that have been printed are marked by this character (default: -@code{?P}). -@c ------------------------- -@vindex mh-scan-refiled-msg-regexp -@item mh-note-refiled -Messages that have been refiled are marked by this character (default: -@code{?^}). See also @code{mh-scan-refiled-msg-regexp}. -@c ------------------------- -@item mh-note-repl -Messages that have been replied to are marked by this character -(default: @code{?-}). -@c ------------------------- -@item mh-note-seq -Messages in a user-defined sequence are marked by this character -(default: @code{?%}). Messages in the @samp{search} sequence are -marked by this character as well. -@end vtable - -For example, let's say I have the following in @file{scan.format} -which displays the sender, the subject, and the message number. This -format places a @samp{+} after the message number for the current -message according to MH; it also uses that column for notations. - -@smallexample -%20(decode(friendly@{from@})) %50(decode@{subject@}) %4(msg)%<(cur)+%| %> -@end smallexample - -@vindex mh-adaptive-cmd-note-flag -@vindex mh-scan-format-file -@vindex mh-scan-format-file@r{, example} - -The first thing you have to do is tell MH-E to use this file. -Customize @code{mh-scan-format-file} and set its value to @samp{Use -Default scan Format}. If you didn't get already turn off -@code{mh-adaptive-cmd-note-flag}, you'll need to do that first. - -Next, tell MH-E what a valid scan line looks like so that you can at -least display the output of scan in your MH-Folder buffer. - -@vindex mh-scan-valid-regexp@r{, example} - -@smalllisp -(setq mh-scan-valid-regexp "[0-9]+[+D^ ]$") -@end smalllisp - -Now, in order to get rid of the @samp{Cursor not pointing to message} -message, you need to tell MH-E how to access the message number. You -should also see why MH-E requires that you include a message number in -the first place. - -@vindex mh-scan-msg-number-regexp@r{, example} -@vindex mh-scan-msg-search-regexp@r{, example} - -@smalllisp -(setq mh-scan-msg-number-regexp "^.* \\([0-9]+\\)[+D^ ]$") -(setq mh-scan-msg-search-regexp " %d[+D^ ]$") -@end smalllisp - -In order to get the next and previous commands working, add this. - -@vindex mh-scan-good-msg-regexp@r{, example} - -@smalllisp -(setq mh-scan-good-msg-regexp "^.* \\([0-9]+\\)[+D^ ]$") -@end smalllisp - -Note that the current message isn't marked with a @samp{+} when moving -between the next and previous messages. Here is the code required to -get this working. - -@vindex set-mh-cmd-note@r{, example} -@vindex mh-scan-cur-msg-number-regexp@r{, example} - -@smalllisp -(set-mh-cmd-note 76) -(setq mh-scan-cur-msg-number-regexp "^.* \\([0-9]+\\)\\+$") -@end smalllisp - -Finally, add the following to delete and refile messages. - -@vindex mh-scan-deleted-msg-regexp@r{, example} -@vindex mh-scan-refiled-msg-regexp@r{, example} - -@smalllisp -(setq mh-scan-deleted-msg-regexp "^.* \\([0-9]+\\)D$") -(setq mh-scan-refiled-msg-regexp "^.* \\([0-9]+\\)\\^$") -@end smalllisp - -This is just a bare minimum; it's best to adjust all of the regular -expressions to ensure that MH-E and highlighting perform well. - -@node Procmail -@appendix Reading Mailing Lists Effectively - -@cindex @command{procmail} -@cindex @command{slocal} -@cindex Gnus -@cindex MH commands, @command{slocal} -@cindex Unix commands, @command{procmail} -@cindex mailing lists, reading - -This appendix explains how to use procmail, which can -file mail from mailing lists into folders which can then -be read easily with MH-E@footnote{The MH equivalent, @command{slocal}, -can be used as well, but procmail was more flexible and more packages -exist for procmail than for slocal.}. Unfortunately, procmail is no -longer recommended due to its security vulnerabilities. -Some mailing lists have such -high traffic that Gnus must be used and I discuss how to use Gnus -side-by-side with MH-E. - -@cindex @file{.procmailrc} -@cindex files, @file{.procmailrc} - -First, I'll describe how to put mail from your mailing lists directly -into an MH folder using @command{procmail}. First, add the following -to @file{~/.procmailrc}. While the logging variables aren't strictly -necessary, they are extremely useful. - -@smallexample -[1] # Update PATH so procmail can find myrcvstore, rcvstore and mhparam. -[2] PATH=$PATH:/usr/lib/mh:/usr/bin/mh:$HOME/bin -[3] -[4] # Point LOGFILE at the actual log file. -[5] LOGFILE=$HOME/.procmail.log -[6] -[7] # This setting provides just the right amount of information. -[8] LOGABSTRACT=all -[9] -[10] # Uncomment the following line to see how your patterns match. -[11] #VERBOSE=yes -[12] -[13] # Place mail sent to any MH-E mailing list in +mh-e. -[14] :0 w: mh-e$LOCKEXT -[15] * ^TO.*mh-e-.*@@.*sourceforge.net -[16] | myrcvstore -create +mh-e -@end smallexample - -@cindex @command{rcvstore} -@cindex MH commands, @command{rcvstore} - -Line 14 creates a lock file in your mail directory based upon the name -of the folder. This is done because @command{rcvstore} does not -perform locking. While this lock file will prevent @command{procmail} -from writing to a folder concurrently, there is a slight chance that -you might lose a message if you're performing operations on a folder -at the same time @command{rcvstore} is placing a message there. You -have been warned. Now that that disclaimer is out of the way, note -that I've been using this set-up for over a decade and haven't lost -anything to my knowledge@footnote{See -@uref{https://savannah.nongnu.org/bugs/?func=detailbug&bug_id=4361&group_id=2166, -Savannah issue #4361} to see if @command{rcvstore} locking is still an -issue.}. - -@cindex @samp{Unseen-Sequence} MH profile component -@cindex MH profile component, @samp{Unseen-Sequence} - -Line 16 uses the following script, @code{myrcvstore}, to massage the -message as described in the comment and file the message in the given -folder@footnote{The @samp{-create} argument wasn't always the default -to @command{rcvstore}.}. - -@smallexample -#! /bin/sh - -# Accepts a message on standard input and passes it through rcvstore -# after first passing it through any filters. All arguments are passed -# on to rcvstore. - -# Force the "From user date" to become part of header. One reason this -# is done is because the presence of the From field confuses dist so -# that dist adds a new header, rather than using the existing header. -# Note that this should not be done for any message that goes into a -# Gnus incoming file (Gnus will thrown an error) nor should it be -# applied to any message that goes to the system mailbox because the -# entire mailbox will be incorporated as a single message. -formail -c -z -R 'From ' X-Envelope-From: | -rcvstore $@@ -@end smallexample - -If your version of @command{rcvstore} doesn't add messages to the -@samp{unseen} sequence by default, add the following line to your MH -profile: - -@smallexample -Unseen-Sequence: unseen -@end smallexample - -Now view your new messages with the speedbar (@pxref{Speedbar}) or with -@kbd{F n} (@code{mh-index-new-messages}). @xref{Folders}. - -If you're on a mailing list that is so voluminous that it is -impossible to read every message, it usually better to read the -mailing list like a newsgroup in a news reader. Emacs has a built-in -newsreader called Gnus. The remainder of this appendix talks about how -to use Gnus with an MH message store. - -This table contains a list of Gnus options that you will have to -modify. Note that for them to become accessible, you'll have to load -@file{nnml.el} first. This can be done with @kbd{M-x load-library -@key{RET} nnml @key{RET}}. - -@vtable @code -@item gnus-secondary-select-methods -Select the @samp{nnml} value. This select method uses directories for -folders and individual files for messages, just like MH@. You do not -have to set an address. -@c ------------------------- -@item mail-sources -Select the @samp{Several files in a directory} value, check the -@samp{Path} box and enter @file{~/Mail} to tell Gnus where to find -your mail. -@c ------------------------- -@vindex mail-user-agent -@item message-mail-user-agent -In order to send mail within Gnus using MH-E, set this option to -@samp{mail-user-agent} and set the @code{mail-user-agent} option to -@samp{Emacs interface to MH}. -@c ------------------------- -@item nnmail-keep-last-article -Since Gnus keeps track of which messages you have read, it would be -bad if Gnus expired the last message, for example, message 100, and -@command{rcvstore} gave the next new message number 1. Gnus would then -ignore it since it thinks that you've read messages 1--100. Turning on -this option ensures that the last message is never removed thereby -eliminating this problem. -@end vtable - -Next add the following to @file{~/.procmailrc}. If you don't subscribe -to the GnuCash mailing list, substitute one to which you are -subscribed. - -@smallexample -PATH=$PATH:/usr/bin/mh -MAILDIR=$HOME/`mhparam Path` -# Place mail sent to the GnuCash mailing list in gnucash.spool, where -# Gnus will pick it up. -:0: -* ^TO.*gnucash.*@@.*gnucash.org -gnucash.spool -@end smallexample - -Wait for some messages to appear in @file{gnucash.spool} and run Gnus -with @kbd{M-x gnus @key{RET}}. To view the folder created in the -example above, you would tell Gnus about it the first time only with -@kbd{G m gnucash @key{RET} nnml @key{RET}}. In MH-E, this folder is -known as @samp{+gnucash}. - -@node Odds and Ends -@appendix Odds and Ends - -This appendix covers a few topics that don't fit elsewhere. Here I -tell you how to report bugs and how to get on the MH-E mailing lists. -I also point out some additional sources of information. - -@menu -* Bug Reports:: -* Mailing Lists:: -* MH FAQ and Support:: -* Getting MH-E:: -@end menu - -@node Bug Reports -@appendixsec Bug Reports - -@cindex bugs -@cindex SourceForge -@findex mh-version - -Bug reports should be filed at -@uref{https://sourceforge.net/p/mh-e/bugs/, SourceForge}. You need to -be a SourceForge user to submit bug reports, but this is easy enough -to do that it shouldn't be a restriction for you. Please include the -output of @kbd{M-x mh-version} (@pxref{Miscellaneous}) in any bug -report you send unless you're 110% positive we won't ask for it. - -@node Mailing Lists -@appendixsec MH-E Mailing Lists - -@cindex SourceForge -@cindex mailing lists - -There are several mailing lists for MH-E@. They are @i{mh-e-users at -lists.sourceforge.net}, @i{mh-e-announce at lists.sourceforge.net}, -and @i{mh-e-devel at lists.sourceforge.net}. You can subscribe or view -the archives at @uref{https://sourceforge.net/p/mh-e/mailman/, -SourceForge}. Do not report bugs on these lists; please submit them -via SourceForge (@pxref{Bug Reports}). - -@node MH FAQ and Support -@appendixsec MH FAQ and Support - -@cindex FAQ -@cindex MH FAQ - -The article @uref{https://www.newt.com/faq/mh.html, @cite{MH Frequently -Asked Questions (FAQ) with Answers}} appears monthly in the newsgroup -@samp{comp.mail.mh}. While very little is there that deals with MH-E -specifically, there is an incredible wealth of material about MH -itself which you will find useful. - -@cindex support - -You can find FAQs on MH-E by searching for @i{labels:support} on the -@uref{https://sourceforge.net/p/mh-e/bugs/search/?q=labels%3Asupport, -Tickets} page on SourceForge. If you don't find the answer to your -question, file a ticket and your question will become a new FAQ! - -@node Getting MH-E -@appendixsec Getting MH-E - -@cindex MH-E, obtaining -@cindex getting MH-E -@cindex obtaining MH-E - -Since MH-E 8.6 was released in 2016, its development migrated to the -Emacs repository. MH-E is now only supported in the version of Emacs -in which it appears. Old releases of MH-E are still available for -download at @uref{https://sourceforge.net/projects/mh-e/files/, -SourceForge}. - -@cindex files, @samp{MH-E-NEWS} -@cindex files, @samp{README} -@cindex news -@cindex @samp{MH-E-NEWS} -@cindex @samp{README} -@findex mh-version - -After you download and extract the MH-E tarball, read the -@file{README} file and @file{MH-E-NEWS}. These correspond to the -release notes and change log mentioned above. The file @file{README} -contains instructions on installing MH-E@. If you're already running -Emacs, please quit that session and start again to load in the new -MH-E@. Check that you're running the new version with the command -@kbd{M-x mh-version}. - -@cindex contributed software -@cindex manual -@cindex documentation - -In addition to the mh-e package, the -@uref{https://sourceforge.net/projects/mh-e/files/, SourceForge} site -also contains doc and contrib packages. The former is the latest -release of this manual, and the latter contains a few contributed -packages you might find useful. - -@node History -@appendix History of MH-E - -@cindex Bill Wohler -@cindex Brian Reid -@cindex Gildea, Stephen -@cindex Jim Larus -@cindex Larus, Jim -@cindex MH-E, versions -@cindex Reid, Brian -@cindex SourceForge -@cindex Stephen Gildea -@cindex Wohler, Bill -@cindex history of MH-E -@cindex versions of MH-E - -MH-E was originally written by Brian Reid in 1983 and has changed -hands several times since then. Jim Larus wanted to do something -similar for GNU Emacs, and ended up completely rewriting it that same -year. In 1989, Stephen Gildea picked it up and added many -improvements. Bill Wohler then took over in 2000 and moved its -development to @uref{https://sourceforge.net/, SourceForge}. -Since 2016, MH-E development occurs within the Emacs repository. - -@menu -* From Brian Reid:: -* From Jim Larus:: -* From Stephen Gildea:: -* From Bill Wohler:: -@end menu - -@node From Brian Reid -@appendixsec From Brian Reid - -@cindex Brian Reid -@cindex Reid, Brian - -One day in 1983 I got the flu and had to stay home from work for three -days with nothing to do. I used that time to write MHE@. The -fundamental idea behind MHE was that it was a ``puppeteer'' driving -the MH programs underneath it. MH had a model that the editor was -supposed to run as a sub-process of the mailer, which seemed to me at -the time to be the tail wagging the dog. So I turned it around and -made the editor drive the MH programs. I made sure that the UCI people -(who were maintaining MH at the time) took in my changes and made them -stick. - -Today, I still use my own version of MHE because I don't at all like -the way that GNU MH-E works and I've never gotten to be good enough at -hacking Emacs Lisp to make GNU MH-E do what I want. The Gosling-emacs -version of MHE and the GNU Emacs version of MH-E have almost nothing -in common except similar names. They work differently, have different -conceptual models, and have different key bindings@footnote{After -reading this article, I questioned Brian about his version of MHE, and -received some great ideas for improving MH-E such as a dired-like -method of selecting folders; and removing the prompting when sending -mail, filling in the blanks in the draft buffer instead. I passed them -on to Stephen Gildea, the current maintainer, and he was excited about -the ideas as well. Perhaps one day, MH-E will again resemble MHE -(draft form editing was introduced in version 7.4).}. - -Brian Reid, June 1994 - -@node From Jim Larus -@appendixsec From Jim Larus - -@cindex Jim Larus -@cindex Larus, Jim - -Brian Reid, while at CMU or shortly after going to Stanford wrote a -mail reading program called MHE for Gosling Emacs. It had much the -same structure as MH-E (i.e., invoked MH programs), though it was -simpler and the commands were slightly different. Unfortunately, I no -longer have a copy so the differences are lost in the mists of time. - -In '82--83, I was working at BBN and wrote a lot of mlisp code in -Gosling Emacs to make it look more like Tennex Emacs. One of the -packages that I picked up and improved was Reid's mail system. In '83, -I went back to Berkeley. About that time, Stallman's first version of -GNU Emacs came out and people started to move to it from Gosling Emacs -(as I recall, the transition took a year or two). I decided to port -Reid's MHE and used the mlisp to Emacs Lisp translator that came with -GNU Emacs. It did a lousy job and the resulting code didn't work, so I -bit the bullet and rewrote the code by hand (it was a lot smaller and -simpler then, so it took only a day or two). - -Soon after that, MH-E became part of the standard Emacs distribution -and suggestions kept dribbling in for improvements. MH-E soon reached -sufficient functionality to keep me happy, but I kept on improving it -because I was a graduate student with plenty of time on my hands and -it was more fun than my dissertation. In retrospect, the one thing -that I regret is not writing any documentation, which seriously -limited the use and appeal of the package. - -@cindex @command{xmh}, in MH-E history - -In '89, I came to Wisconsin as a professor and decided not to work on -MH-E@. It was stable, except for minor bugs, and had enough -functionality, so I let it be for a few years. Stephen Gildea of BBN -began to pester me about the bugs, but I ignored them. In 1990, he -went off to the X Consortium, said good bye, and said that he would -now be using @command{xmh}. A few months later, he came back and said -that he couldn't stand @command{xmh} and could I put a few more bug fixes -into MH-E@. At that point, I had no interest in fixing MH-E, so I gave -the responsibility of maintenance to him and he has done a fine job -since then. - -Jim Larus, June 1994 - -@node From Stephen Gildea -@appendixsec From Stephen Gildea - -@cindex Gildea, Stephen -@cindex Stephen Gildea - -In 1987 I went to work for Bolt Beranek and Newman, as Jim had before -me. In my previous job, I had been using RMAIL, but as my folders tend -to run large, I was frustrated with the speed of RMAIL@. However, I -stuck with it because I wanted the GNU Emacs interface. I am very -familiar and comfortable with the Emacs interface (with just a few -modifications of my own) and dislike having to use applications with -embedded editors; they never live up to Emacs. - -MH is the mail reader of choice at BBN, so I converted to it. Since I -didn't want to give up using an Emacs interface, I started using MH-E@. -As is my wont, I started hacking on it almost immediately. I first -used version 3.4m. One of the first features I added was to treat the -folder buffer as a file-visiting buffer: you could lock it, save it, -and be warned of unsaved changes when killing it. I also worked to -bring its functionality a little closer to RMAIL@. Jim Larus was very -cooperative about merging in my changes, and my efforts first appeared -in version 3.6, distributed with Emacs 18.52 in 1988. Next I decided -MH-E was too slow and optimized it a lot. Version, 3.7, distributed -with Emacs 18.56 in 1990, was noticeably faster. - -When I moved to the X Consortium I became the first person there to -not use xmh. (There is now one other engineer there using MH-E@.) About -this point I took over maintenance of MH-E from Jim and was finally -able to add some features Jim hadn't accepted, such as the backward -searching undo. My first release was 3.8 (Emacs 18.58) in 1992. - -Now, in 1994, we see a flurry of releases, with both 4.0 and 5.0. -Version 4.0 added many new features, including background folder -collection and support for composing @sc{mime} messages. (Reading -@sc{mime} messages remains to be done, alas.) While writing this book, -Bill Wohler gave MH-E its closest examination ever, uncovering bugs -and inconsistencies that required a new major version to fix, and so -version 5 was released. - -Stephen Gildea, June 1994 - -@node From Bill Wohler -@appendixsec From Bill Wohler - -@cindex Wohler, Bill -@cindex Bill Wohler - -The preface originally included the following text which I use to -begin my story: - -@quotation -But it's important to note a brief history of MH-E. - -@w{Version 3} was prevalent through the @w{Emacs 18} and early -@w{Emacs 19} years. Then @w{Version 4} came out (@w{Emacs 19.23}), -which introduced several new and changed commands. Next, @w{Version -5.0} was released, which fixed some bugs and incompatibilities, and -was incorporated into @w{Emacs 19.29}. -@end quotation - -After a long break, Stephen handed the reins over to me in 2000. I -moved the project to a new site called SourceForge and organized a -great team of developers. Our first release in late 2001 was version -6. It appeared around the time of Emacs 21.2 and had menus and tool -bar buttons. - -Then, indexed searches, improved MIME handling, a speedbar, multiple -identities, alias completion, an index view of unseen messages, spam -software support, Face and X-Image-URL header field support, Fcc -completion, arbitrary range handling, and draft form editing were -introduced in the version 7 series around the time of Emacs 21.4 -(2004). Still, Emacs itself contained version 5 of MH-E released back -in 1994. - -Version 8 development was mostly driven by the rewrite of the manual. -It also brought GNU mailutils MH support, S/MIME support, picon -support, and an improved interface for hiding header fields. The CVS -repository was migrated from SourceForge to Savannah (only for those -files that were already part of Emacs) and the software was completely -reorganized to push back two decades of entropy. Version 8 appeared in -Emacs 22.1 in 2006. - -Development was then quiet for a couple of years. Emacs 23.1, which is -due out in 2009, will contain version 8.1. This version includes a few -new features and several bug fixes. - -Bill Wohler, August 2008 - -@node GFDL -@appendix GNU Free Documentation License -@include doclicense.texi - -@node GPL -@appendix GNU General Public License -@include gpl.texi - -@node Key Index -@unnumbered Key (Character) Index -@printindex ky - -@node Command Index -@unnumbered Command Index -@printindex fn - -@node Option Index -@unnumbered Option (Variable) Index -@printindex vr - -@node Concept Index -@unnumbered Concept Index -@printindex cp - -@bye - -@c Ispell Helpers -@c -@c The following are words that ispell should ignore that would not -@c normally be in a dictionary (global or personal). Be careful not to -@c include words here that could potentially be typos of other words -@c (such as url, elisp, or MHE). -@c -@c LocalWords: CTRL ESC SPC f's -@c LocalWords: addr Aliasfile alist -@c LocalWords: Baushke Bcc BBN Beranek bogofilter bogofilter's -@c LocalWords: cmd CMU contrib cron -@c LocalWords: DesBrisay Dcc devel dir dired docstring filll forw -@c LocalWords: GECOS Gildea Gildea's Ginnean GnuCash goto htm -@c LocalWords: ImageMagick inbox ispell keychain -@c LocalWords: Larus licensor LocalWords lookup lpr -@c LocalWords: makeinfo mairix mbox mh mhbuild mhl mhpath mlisp -@c LocalWords: MML msg multipart -@c LocalWords: Namazu NIS nenscript nnml num -@c LocalWords: packmbox passphrase pathname prev procmail prog repl -@c LocalWords: slocal sortm SpamAssassin spammers SpamProbe SpamProbe's -@c LocalWords: sublicense supercite speedbar -@c LocalWords: Tennex texi texinfo Thelen thelenm -@c LocalWords: UCI undeleted whatnow wohler xmh ypcat -@c -@c See https://oreillymedia.github.io/production-resources/styleguide/. -@c See https://en.wikipedia.org/. -@c -@c Note the lowercase mh which is needed to avoid hits in the -@c functions and variables. Occasionally, check for accidental -@c inclusion of mh in text by uncommenting the following and executing -@c it with C-x C-e. You want to see "Search failed" -@c (let ((case-fold-search nil)) -@c (goto-char (point-min)) -@c (search-forward-regexp "^mh\\( \\|$\\)")) -@c -@c An extremely useful setting for texinfo-mode-hook is: -@c (add-to-list -@c 'ispell-skip-region-alist -@c (list -@c (concat "\\(@\\(small\\)?\\(example\\|lisp\\)" -@c "\\(@\\([irw]\\|code\\|var\\){[^}]+}\\|" -@c "@[@{}.]\\|" -@c "[^@]\\|" -@c "@\\(end \\)?group\\|" -@c "@\\(end \\)?cartouche\\)+" -@c "@end \\(small\\)?\\(example\\|lisp\\)\\|" -@c "@\\(code\\|command\\|file\\|kbd\\|sc\\){[^}]+}\\|" -@c "^@end [a-z]+$\\|" -@c "^@\\([fv]\\|print\\)index .*$\\|" -@c "@uref{[^,]+,\\|" -@c "@[a-z]+\\|" -@c "/[a-z.]+[/}]\\)"))))) -@c -@c Cross References -@c -@c See existing cross-references to the Emacs manual and the Emacs -@c Lisp manual (search for ``GNU Emacs Manual'' and ``GNU -@c Emacs Lisp Reference Manual'' respectively). - -@c @ftable Sorting -@c -@c As per index (sort of): Punctuation, keyboard characters (such as -@c RET and BS) upper and lowercase mixed (lower comes before -@c uppercase), control characters go with uppercase C, meta characters -@c go with uppercase M. -@c In some cases, the sort isn't strictly ASCII. -@c For example, SPC (mh-page-msg) reads better before BS -@c (mh-previous-page) and . (mh-show) is better before , -@c (mh-header-display). - -@c @vtable Sorting -@c -@c Alphabetical, pull hooks into their own table. - -@c Local Variables: -@c sentence-end-double-space: nil -@c End: diff --git a/etc/edt-user.el b/etc/edt-user.el deleted file mode 100644 index 0813a97856d..00000000000 --- a/etc/edt-user.el +++ /dev/null @@ -1,168 +0,0 @@ -;;; edt-user.el --- Sample user customizations for Emacs EDT emulation -*- lexical-binding: t -*- - -;; Copyright (C) 1986, 1992-1993, 2000-2024 Free Software Foundation, -;; Inc. - -;; Author: Kevin Gallagher -;; Keywords: emulations - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; This is an example of the `edt-user.el' file that you can use -;; to customize the Emacs EDT emulation mode. Copy this file to -;; somewhere in your `load-path', and edit it as desired. -;; See Info node `edt' for more details. - -;; ==================================================================== - - -;;; Code: - -;;;; -;;;; Setup user custom EDT key bindings. -;;;; - -(defun edt-setup-user-bindings () - "Assigns user custom EDT Emulation keyboard bindings." - - ;; PF1 (GOLD), PF2, PF3, PF4 - ;; - ;; This file MUST contain a binding of PF1 to edt-user-gold-map. So - ;; DON'T CHANGE OR DELETE THE REGULAR KEY BINDING OF PF1 BELOW! - ;; (However, you may change the GOLD-PF1 binding, if you wish.) - (edt-bind-function-key "PF1" 'edt-user-gold-map 'edt-mark-section-wisely) - (edt-bind-function-key "PF2" 'query-replace 'other-window) - (edt-bind-function-key "PF4" 'edt-delete-entire-line 'edt-undelete-line) - - ;; EDT Keypad Keys - (edt-bind-function-key "KP1" 'edt-word-forward 'edt-change-case) - (edt-bind-function-key "KP3" 'edt-word-backward 'edt-copy) - (edt-bind-function-key "KP6" 'edt-cut-or-copy 'yank) - (edt-bind-function-key "KP8" 'edt-scroll-window 'fill-paragraph) - (edt-bind-function-key "KP9" 'open-line 'edt-eliminate-all-tabs) - (edt-bind-function-key "KPP" - 'edt-toggle-select 'edt-line-to-middle-of-window) - (edt-bind-function-key "KPE" 'edt-change-direction 'overwrite-mode) - - ;; GOLD bindings for regular keys. - (edt-bind-gold-key "a" 'edt-append) - (edt-bind-gold-key "A" 'edt-append) - (edt-bind-gold-key "h" 'edt-electric-user-keypad-help) - (edt-bind-gold-key "H" 'edt-electric-user-keypad-help) - - ;; Control bindings for regular keys. - ;;; Leave binding of C-c as original prefix key. - (edt-bind-key "\C-j" 'edt-duplicate-word) - (edt-bind-key "\C-k" 'edt-define-key) - (edt-bind-gold-key "\C-k" 'edt-restore-key) - (edt-bind-key "\C-l" 'edt-learn) - ;;; Leave binding of C-m to newline. - (edt-bind-key "\C-n" 'edt-set-screen-width-80) - (edt-bind-key "\C-o" 'open-line) - (edt-bind-key "\C-p" 'fill-paragraph) - ;;; Leave binding of C-r to isearch-backward. - ;;; Leave binding of C-s to isearch-forward. - (edt-bind-key "\C-t" 'edt-display-the-time) - (edt-bind-key "\C-v" 'redraw-display) - (edt-bind-key "\C-w" 'edt-set-screen-width-132) - ;;; Leave binding of C-x as original prefix key. -) - -;;; -;;; LK-201 KEYBOARD USER EDT KEYPAD HELP -;;; - -(defun edt-user-keypad-help () - " - USER EDT Keypad Active - - +----------+----------+----------+----------+ - F7: Copy Rectangle |Prev Line |Next Line |Bkwd Char |Frwd Char | - F8: Cut Rect Overstrike | (UP) | (DOWN) | (LEFT) | (RIGHT) | - G-F8: Paste Rect Overstrike |Window Top|Window Bot|Bkwd Sent |Frwd Sent | - F9: Cut Rect Insert +----------+----------+----------+----------+ - G-F9: Paste Rect Insert - F10: Cut Rectangle -G-F10: Paste Rectangle - F11: ESC +----------+----------+----------+----------+ - F12: Beginning of Line | GOLD |Query Repl| FNDNXT |Del Ent L | -G-F12: Delete Other Windows | (PF1) | (PF2) | (PF3) | (PF4) | - F13: Delete to Begin of Word |Mark Wisel|Other Wind| FIND | UND L | - HELP: Keypad Help +----------+----------+----------+----------+ -G-HELP: Emacs Help | PAGE |Scroll Win|Open Line | DEL W | - DO: Execute extended command | (7) | (8) | (9) | (-) | - C-a: Beginning of Line |Ex Ext Cmd|Fill Parag|Elim Tabs | UND W | - C-b: Backward Character +----------+----------+----------+----------+ - C-d: Delete Character | ADVANCE | BACKUP | CUT/COPY | DEL C | - C-e: End of Line | (4) | (5) | (6) | (,) | - C-f: Forward Character | BOTTOM | TOP | Yank | UND C | - C-g: Keyboard Quit +----------+----------+----------+----------+ -G-C-g: Keyboard Quit | Fwd Word | EOL | Bwd Word | Change | - C-h: Electric Emacs Help | (1) | (2) | (3) | Direction| -G-C-h: Emacs Help | CHNGCASE | DEL EOL | COPY | | - C-i: Indent for Tab +---------------------+----------+ (ENTER) | - C-j: Duplicate Word | LINE |SELECT/RES| | - C-k: Define Key | (0) | (.) | Toggle | -G-C-k: Restore Key | Open Line |Center Lin|Insrt/Over| - C-l: Learn +---------------------+----------+----------+ - C-n: Set Screen Width 80 - C-o: Open Line +----------+----------+----------+ - C-p: Fill Paragraph | FNDNXT | Yank | CUT | - C-q: Quoted Insert | (FIND)) | (INSERT) | (REMOVE) | - C-r: Isearch Backward | FIND | | COPY | - C-s: Isearch Forward +----------+----------+----------+ - C-t: Display the Time |SELECT/RES|SECT BACKW|SECT FORWA| - C-u: Universal Argument | (SELECT) |(PREVIOUS)| (NEXT) | - C-v: Redraw Display | | | | - C-w: Set Screen Width 132 +----------+----------+----------+ - C-z: Suspend Emacs -G-C-\\: Split Window - - G-a: Append to Kill Buffer - G-b: Buffer Menu - G-c: Compile - G-d: Delete Window - G-e: Exit - G-f: Find File - G-g: Find File Other Window - G-h: Keypad Help - G-i: Insert File - G-k: Toggle Capitalization Word - G-l: Lowercase Word or Region - G-m: Save Some Buffers - G-n: Next Error - G-o: Switch Windows - G-q: Quit - G-r: Revert File - G-s: Save Buffer - G-u: Uppercase Word or Region - G-v: Find File Other Window - G-w: Write file - G-y: EDT Emulation OFF - G-z: Switch to Default EDT Key Bindings - G-2: Split Window - G-%: Go to Percentage - G- : Undo (GOLD Spacebar) - G-=: Go to Line - G-\\=`: What line - G-/: Query-Replace" - - (interactive) - (describe-function 'edt-user-keypad-help)) - -;;; edt-user.el ends here diff --git a/lisp/calculator.el b/lisp/calculator.el deleted file mode 100644 index ef1e6d8dbc3..00000000000 --- a/lisp/calculator.el +++ /dev/null @@ -1,1622 +0,0 @@ -;;; calculator.el --- a calculator for Emacs -*- lexical-binding: t -*- - -;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc. - -;; Author: Eli Barzilay -;; Keywords: tools, convenience - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; A calculator for Emacs. -;; Why should you reach for your mouse to get xcalc (calc.exe, gcalc or -;; whatever), when you have Emacs running already? -;; -;; You can bind this to a key by adding this to your Init file: -;; -;; (global-set-key [(control return)] 'calculator) -;; -;; Written by Eli Barzilay, eli@barzilay.org - -;;; Customization: - -(defgroup calculator nil - "Simple Emacs calculator." - :prefix "calculator" - :version "21.1" - :group 'tools - :group 'applications) - -(defcustom calculator-electric-mode nil - "Run `calculator' electrically, in the echo area. -Electric mode saves some place but changes the way you interact with the -calculator." - :type 'boolean) - -(defcustom calculator-use-menu t - "Make `calculator' create a menu. -Note that this requires easymenu. Must be set before loading." - :type 'boolean) - -(defcustom calculator-bind-escape nil - "If non-nil, set escape to exit the calculator." - :type 'boolean) - -(defcustom calculator-unary-style 'postfix - "Value is either `prefix' or `postfix'. -This determines the default behavior of unary operators." - :type '(choice (const prefix) (const postfix)) - :group 'calculator) - -(defcustom calculator-prompt "Calc=%s> " - "The prompt used by the Emacs calculator. -It should contain a \"%s\" somewhere that will indicate the i/o radixes; -this will be a two-character string as described in the documentation -for `calculator-mode'." - :type 'string) - -(defcustom calculator-number-digits 3 - "The calculator's number of digits used for standard display. -Used by the `calculator-standard-display' function - it will use the -format string \"%.NC\" where this number is N and C is a character given -at runtime." - :type 'integer) - -(defcustom calculator-radix-grouping-mode t - "Use digit grouping in radix output mode. -If this is set, chunks of `calculator-radix-grouping-digits' characters -will be separated by `calculator-radix-grouping-separator' when in radix -output mode is active (determined by `calculator-output-radix')." - :type 'boolean) - -(defcustom calculator-radix-grouping-digits 4 - "The number of digits used for grouping display in radix modes. -See `calculator-radix-grouping-mode'." - :type 'integer) - -(defcustom calculator-radix-grouping-separator "'" - "The separator used in radix grouping display. -See `calculator-radix-grouping-mode'." - :type 'string) - -(defcustom calculator-remove-zeros t - "Non-nil value means delete all redundant zero decimal digits. -If this value is not t and not nil, redundant zeros are removed except -for one. -Used by the `calculator-remove-zeros' function." - :type '(choice (const t) (const leave-decimal) (const nil))) - -(defcustom calculator-displayer '(std ?n) - "A displayer specification for numerical values. -This is the displayer used to show all numbers in an expression. Result -values will be displayed according to the first element of -`calculator-displayers'. - -The displayer is a symbol, a string or an expression. A symbol should -be the name of a one-argument function, a string is used with a single -argument and an expression will be evaluated with the variable `num' -bound to whatever should be displayed. If it is a function symbol, it -should be able to handle special symbol arguments, currently `left' and -`right' which will be sent by special keys to modify display parameters -associated with the displayer function (for example to change the number -of digits displayed). - -An exception to the above is the case of the list (std C [G]) where C is -a character and G is an optional boolean, in this case the -`calculator-standard-displayer' function will be used with these as -arguments." - :type '(choice (function) (string) (sexp) - (list (const std) character) - (list (const std) character boolean))) - -(defcustom calculator-displayers - '(((std ?n) "Standard display, decimal point or scientific") - (calculator-eng-display "Eng display") - ((std ?f t) "Standard display, decimal point with grouping") - ((std ?e) "Standard display, scientific") - ("%S" "Emacs printer")) - "A list of displayers. -Each element is a list of a displayer and a description string. The -first element is the one which is currently used, this is for the -display of result values not values in expressions. A displayer -specification is the same as the values that can be stored in -`calculator-displayer'. - -`calculator-rotate-displayer' rotates this list." - :type 'sexp) - -(defcustom calculator-paste-decimals t - "If non-nil, convert pasted integers so they have a decimal point. -This makes it possible to paste big integers since they will be read as -floats, otherwise the Emacs reader will fail on them." - :type 'boolean) -(make-obsolete-variable 'calculator-paste-decimals - "it is no longer used." "26.1") - -(defcustom calculator-copy-displayer nil - "If non-nil, this is any value that can be used for -`calculator-displayer', to format a string before copying it with -`calculator-copy'. If nil, then `calculator-displayer's normal value is -used." - :type 'boolean) - -(defcustom calculator-2s-complement nil - "If non-nil, show negative numbers in 2s complement in radix modes. -Otherwise show as a negative number." - :type 'boolean) - -(defcustom calculator-mode-hook nil - "List of hook functions for `calculator-mode' to run. -Note: if `calculator-electric-mode' is on, then this hook will get -activated in the minibuffer -- in that case it should not do much more -than local key settings and other effects that will change things -outside the scope of calculator related code." - :type 'hook) - -(defcustom calculator-user-registers nil - "An association list of user-defined register bindings. -Each element in this list is a list of a character and a number that -will be stored in that character's register. - -For example, use this to define the golden ratio number: - (setq calculator-user-registers \\='((?g . 1.61803398875))) -before you load calculator." - :type '(repeat (cons character number)) - :set (lambda (_ val) - (when (boundp 'calculator-registers) - (setq calculator-registers - (append val calculator-registers))) - (setq calculator-user-registers val))) - -(defcustom calculator-user-operators nil - "A list of additional operators. -This is a list in the same format as specified in the documentation for -`calculator-operators', that you can use to bind additional calculator -operators. It is probably not a good idea to modify this value with -`customize' since it is too complex... - -Examples: - -* A very simple one, adding a postfix \"x-to-y\" conversion keys, using - t as a prefix key: - - (setq calculator-user-operators - \\='((\"tf\" cl-to-fr (+ 32 (/ (* X 9) 5)) 1) - (\"tc\" fr-to-cl (/ (* (- X 32) 5) 9) 1) - (\"tp\" kg-to-lb (/ X 0.453592) 1) - (\"tk\" lb-to-kg (* X 0.453592) 1) - (\"tF\" mt-to-ft (/ X 0.3048) 1) - (\"tM\" ft-to-mt (* X 0.3048) 1))) - -* Using a function-like form is simple: use `X' for the argument (`Y' - for a second one in case of a binary operator), `TX' is a truncated - version of `X' and `F' for a recursive call. Here is a [very - inefficient] Fibonacci number operator: - - (add-to-list \\='calculator-user-operators - \\='(\"F\" fib - (if (<= TX 1) 1 (+ (F (- TX 1)) (F (- TX 2)))))) - - Note that this will be either postfix or prefix, according to - `calculator-unary-style'." - :type '(repeat (list string symbol sexp integer integer))) - -;;;===================================================================== -;;; Code: - -(require 'cl-lib) - -;;;--------------------------------------------------------------------- -;;; Variables - -(defvar calculator-initial-operators - '(;; "+"/"-" have keybindings of their own, not calculator-ops - ("=" = identity 1 -1) - (nobind "+" + + 2 4) - (nobind "-" - - 2 4) - (nobind "+" + + -1 9) - (nobind "-" - - -1 9) - ("(" \( identity -1 -1) - (")" \) identity +1 10) - ;; normal keys - ("|" or (logior TX TY) 2 2) - ("#" xor (logxor TX TY) 2 2) - ("&" and (logand TX TY) 2 3) - ("*" * * 2 5) - ("/" / / 2 5) - ("\\" div (/ TX TY) 2 5) - ("%" rem (% TX TY) 2 5) - ("L" log log 2 6) - ("S" sin (sin DX) x 6) - ("C" cos (cos DX) x 6) - ("T" tan (tan DX) x 6) - ("IS" asin (D (asin X)) x 6) - ("IC" acos (D (acos X)) x 6) - ("IT" atan (D (atan X)) x 6) - ("Q" sqrt sqrt x 7) - ("^" ^ calculator-expt 2 7) - ("!" ! calculator-fact x 7) - (";" 1/ (/ 1 X) 1 7) - ("_" - - 1 8) - ("~" ~ (lognot TX) x 8) - (">" repR calculator-repR 1 8) - ("<" repL calculator-repL 1 8) - ("v" avg (/ (apply '+ L) (length L)) 0 8) - ("l" tot (apply '+ L) 0 8) - ) - "A list of initial operators. -This is a list in the same format as `calculator-operators'. Whenever -`calculator' starts, it looks at the value of this variable, and if it -is not empty, its contents is prepended to `calculator-operators' and -the appropriate key bindings are made. - -This variable is then reset to nil. Don't use this if you want to add -user-defined operators, use `calculator-user-operators' instead.") - -(defvar calculator-operators nil - "The calculator operators, each a list with: - -1. The key(s) that is bound to for this operation, a string that is - used with `kbd'; - -2. The displayed symbol for this function; - -3. The function symbol, or a form that uses the variables `X' and `Y', - (if it is a binary operator), `TX' and `TY' (truncated integer - versions), `DX' (converted to radians if degrees mode is on), `D' - (function for converting radians to degrees if deg mode is on), `L' - (list of saved values), `F' (function for recursive iteration calls) - and evaluates to the function value -- these variables are capital; - -4. The function's arity, optional, one of: 2 => binary, -1 => prefix - unary, +1 => postfix unary, 0 => a 0-arg operator func (note that - using such a function replaces the currently entered number, if any), - non-number (the default) => postfix or prefix as determined by - `calculator-unary-style'; - -5. The function's precedence -- should be in the range of 1 (lowest) to - 9 (highest) (optional, defaults to 1); - -It is possible have a unary prefix version of a binary operator if it -comes later in this list. If the list begins with the symbol `nobind', -then no key binding will take place -- this is only used for predefined -keys. - -Use `calculator-user-operators' to add operators to this list, see its -documentation for an example.") - -(defvar calculator-stack nil - "Stack contents -- operations and operands.") - -(defvar calculator-curnum nil - "Current number being entered (as a string).") - -(defvar calculator-stack-display nil - "Cons of the stack and its string representation.") - -(defvar calculator-char-radix - '((?D . nil) (?B . bin) (?O . oct) (?H . hex) (?X . hex)) - "A table to convert input characters to corresponding radix symbols.") - -(defvar calculator-output-radix nil - "The mode for display, one of: nil (decimal), `bin', `oct' or `hex'.") - -(defvar calculator-input-radix nil - "The mode for input, one of: nil (decimal), `bin', `oct' or `hex'.") - -(defvar calculator-deg nil - "Non-nil if trig functions operate on degrees instead of radians.") - -(defvar calculator-saved-list nil - "A list of saved values collected.") - -(defvar calculator-saved-ptr 0 - "The pointer to the current saved number.") - -(defvar calculator-add-saved nil - "Bound to t when a value should be added to the saved-list.") - -(defvar calculator-display-fragile nil - "When non-nil, we see something that the next digit should replace.") - -(defvar calculator-buffer nil - "The current calculator buffer.") - -(defvar calculator-eng-extra nil - "Internal value used by `calculator-eng-display'.") - -(defvar calculator-eng-tmp-show nil - "Internal value used by `calculator-eng-display'.") - -(defvar calculator-last-opXY nil - "The last binary operation and its arguments. -Used for repeating operations in calculator-repR/L.") - -(defvar calculator-registers ; use user-bindings first - (append calculator-user-registers - (list (cons ?e float-e) (cons ?p float-pi))) - "The association list of calculator register values.") - -(defvar calculator-restart-other-mode nil - "Used to hack restarting with the electric mode changed.") - -;;;--------------------------------------------------------------------- -;;; Key bindings - -(defun calculator-define-key (key cmd map) - ;; Arranges for unbound alphabetic keys to be used as their un/shifted - ;; versions if those are bound (mimics the usual Emacs global bindings). - ;; FIXME: We should adjust Emacs's native "fallback to unshifted binding" - ;; such that it can also be used here, rather than having to use a hack like - ;; this one. - (let* ((key (if (stringp key) (kbd key) key)) - (omap (keymap-parent map))) - (define-key map key cmd) - ;; "other" map, used for case-flipped bindings - (unless omap - (setq omap (make-sparse-keymap)) - (suppress-keymap omap t) - (set-keymap-parent map omap)) - (let ((m omap)) - ;; Bind all case-flipped versions. - (dotimes (i (length key)) - (let* ((c (aref key i)) - (k (vector c)) - (b (lookup-key m k)) - (defkey (lambda (x) - (define-key m k x) - (when (and (characterp c) - (or (<= ?A c ?Z) (<= ?a c ?z))) - (define-key m (vector (logxor 32 c)) x))))) - (cond ((= i (1- (length key))) - ;; Prefer longer sequences. - (unless (keymapp b) (funcall defkey cmd))) - ((keymapp b) (setq m b)) - (t (let ((sub (make-sparse-keymap))) - (funcall defkey sub) - (setq m sub))))))))) - -(defvar calculator-mode-map - (let ((map (make-sparse-keymap))) - (suppress-keymap map t) - (dolist (x '((calculator-digit - "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" - "d" "f" "" "" "" "" "" - "" "" "" "" "") - (calculator-open-paren "[") - (calculator-close-paren "]") - (calculator-op-or-exp "+" "-" - "" "") - (calculator-op "" "") - (calculator-decimal "." "") - (calculator-exp "e") - (calculator-dec/deg-mode "D") - (calculator-set-register "s") - (calculator-get-register "g") - (calculator-radix-mode "H" "X" "O" "B") - (calculator-radix-input-mode "iD" "iH" "iX" "iO" "iB") - (calculator-radix-output-mode "oD" "oH" "oX" "oO" "oB") - (calculator-rotate-displayer "'") - (calculator-rotate-displayer-back "\"") - (calculator-displayer-prev "{") - (calculator-displayer-next "}") - (calculator-saved-up "" "C-p") - (calculator-saved-down "" "C-n") - (calculator-quit "q" "C-g") - (calculator-enter "" "" - "" "" - "RET" "LFD") - (calculator-save-on-list "SPC" "") - (calculator-clear-saved "C-c" "") - (calculator-save-and-quit "" "") - (calculator-paste "" "" - "" "" "C-y") - (calculator-clear "" "DEL" "C-d") - (calculator-help "h" "?" "" "") - (calculator-copy "" "") - (calculator-backspace "") - )) - ;; reverse the keys so earlier definitions come last -- makes the - ;; more sensible bindings visible in the menu - (dolist (k (reverse (cdr x))) - (calculator-define-key k (car x) map))) - (if calculator-bind-escape - (progn (calculator-define-key "ESC" 'calculator-quit map) - (calculator-define-key "" 'calculator-quit map)) - (calculator-define-key "ESC ESC ESC" 'calculator-quit map)) - ;; make C-h work in text-mode - (unless window-system - (calculator-define-key "C-h" 'calculator-backspace map)) - ;; set up a menu - (when (and calculator-use-menu (not (boundp 'calculator-menu))) - (let ((radix-selectors - (mapcar (lambda (x) - `([,(nth 0 x) - (calculator-radix-mode ,(nth 2 x)) - :style radio - :keys ,(nth 2 x) - :selected - (and - (eq calculator-input-radix ',(nth 1 x)) - (eq calculator-output-radix ',(nth 1 x)))] - [,(concat (nth 0 x) " Input") - (calculator-radix-input-mode ,(nth 2 x)) - :keys ,(concat "i" (downcase (nth 2 x))) - :style radio - :selected - (eq calculator-input-radix ',(nth 1 x))] - [,(concat (nth 0 x) " Output") - (calculator-radix-output-mode ,(nth 2 x)) - :keys ,(concat "o" (downcase (nth 2 x))) - :style radio - :selected - (eq calculator-output-radix ',(nth 1 x))])) - '(("Decimal" nil "D") - ("Binary" bin "B") - ("Octal" oct "O") - ("Hexadecimal" hex "H")))) - (op (lambda (name key) - `[,name (calculator-op ,key) :keys ,key]))) - (easy-menu-define - calculator-menu map "Calculator menu." - `("Calculator" - ["Help" - (let ((last-command 'calculator-help)) (calculator-help)) - :keys "?"] - "---" - ["Copy" calculator-copy] - ["Paste" calculator-paste] - "---" - ["Electric mode" - (progn (calculator-quit) - (setq calculator-restart-other-mode t) - (run-with-timer 0.1 nil (lambda () (message nil))) - ;; the message from the menu will be visible, - ;; couldn't make it go away... - (calculator)) - :active (not calculator-electric-mode)] - ["Normal mode" - (progn (setq calculator-restart-other-mode t) - (calculator-quit)) - :active calculator-electric-mode] - "---" - ("Functions" - ,(funcall op "Repeat-right" ">") - ,(funcall op "Repeat-left" "<") - "------General------" - ,(funcall op "Reciprocal" ";") - ,(funcall op "Log" "L") - ,(funcall op "Square-root" "Q") - ,(funcall op "Factorial" "!") - "------Trigonometric------" - ,(funcall op "Sinus" "S") - ,(funcall op "Cosine" "C") - ,(funcall op "Tangent" "T") - ,(funcall op "Inv-Sinus" "IS") - ,(funcall op "Inv-Cosine" "IC") - ,(funcall op "Inv-Tangent" "IT") - "------Bitwise------" - ,(funcall op "Or" "|") - ,(funcall op "Xor" "#") - ,(funcall op "And" "&") - ,(funcall op "Not" "~")) - ("Saved List" - ["Eval+Save" calculator-save-on-list] - ["Prev number" calculator-saved-up] - ["Next number" calculator-saved-down] - ["Delete current" calculator-clear - :active (and calculator-display-fragile - calculator-saved-list - (= (car calculator-stack) - (nth calculator-saved-ptr - calculator-saved-list)))] - ["Delete all" calculator-clear-saved] - "---" - ,(funcall op "List-total" "l") - ,(funcall op "List-average" "v")) - ("Registers" - ["Get register" calculator-get-register] - ["Set register" calculator-set-register]) - ("Modes" - ["Radians" - (progn - (when (or calculator-input-radix calculator-output-radix) - (calculator-radix-mode "D")) - (when calculator-deg (calculator-dec/deg-mode))) - :keys "D" - :style radio - :selected (not (or calculator-input-radix - calculator-output-radix - calculator-deg))] - ["Degrees" - (progn - (when (or calculator-input-radix calculator-output-radix) - (calculator-radix-mode "D")) - (unless calculator-deg (calculator-dec/deg-mode))) - :keys "D" - :style radio - :selected (and calculator-deg - (not (or calculator-input-radix - calculator-output-radix)))] - "---" - ,@(mapcar 'car radix-selectors) - ("Separate I/O" - ,@(mapcar (lambda (x) (nth 1 x)) radix-selectors) - "---" - ,@(mapcar (lambda (x) (nth 2 x)) radix-selectors))) - ("Decimal Display" - ,@(mapcar (lambda (d) - (vector (cadr d) - ;; Note: inserts actual object here - `(calculator-rotate-displayer ',d))) - calculator-displayers) - "---" - ["Change Prev Display" calculator-displayer-prev] - ["Change Next Display" calculator-displayer-next]) - "---" - ["Copy+Quit" calculator-save-and-quit] - ["Quit" calculator-quit])))) - map) - "The calculator key map.") - -;;;--------------------------------------------------------------------- -;;; Startup and mode stuff - -(define-derived-mode calculator-mode fundamental-mode "Calculator" - ;; this help is also used as the major help screen - "A [not so] simple calculator for Emacs. - -This calculator is used in the same way as other popular calculators -like xcalc or calc.exe -- but using an Emacs interface. - -Expressions are entered using normal infix notation, parens are used as -normal. Unary functions are usually postfix, but some depends on the -value of `calculator-unary-style' (if the style for an operator below is -specified, then it is fixed, otherwise it depends on this variable). -`+' and `-' can be used as either binary operators or prefix unary -operators. Numbers can be entered with exponential notation using `e', -except when using a non-decimal radix mode for input (in this case `e' -will be the hexadecimal digit). - -Here are the editing keys: -* \\`RET' \\`=' evaluate the current expression -* \\`C-' copy the whole current expression to the `kill-ring' -* \\`C-' evaluate, save result the `kill-ring' and exit -* \\`' paste a number if the one was copied (normally) -* \\`' \\`C-d' clear last argument or whole expression (hit twice) -* \\`' delete a digit or a previous expression element -* \\`h' \\`?' pop-up a quick reference help -* \\`ESC' \\`q' exit (\\`ESC' can be used if `calculator-bind-escape' is - non-nil, otherwise use three consecutive \\`ESC's) - -These operators are pre-defined: -* `+' `-' `*' `/' the common binary operators -* `\\' `%' integer division and remainder -* `_' `;' postfix unary negation and reciprocal -* `^' `L' binary operators for x^y and log(x) in base y -* `Q' `!' unary square root and factorial -* `S' `C' `T' unary trigonometric operators: sin, cos and tan -* `|' `#' `&' `~' bitwise operators: or, xor, and, not - -The trigonometric functions can be inverted if prefixed with an `I', see -below for the way to use degrees instead of the default radians. - -Two special postfix unary operators are `>' and `<': whenever a binary -operator is performed, it is remembered along with its arguments; then -`>' (`<') will apply the same operator with the same right (left) -argument. - -hex/oct/bin modes can be set for input and for display separately. -Another toggle-able mode is for using degrees instead of radians for -trigonometric functions. -The keys to switch modes are (both \\`H' and \\`X' are for hex): -* \\`D' switch to all-decimal mode, or toggle degrees/radians -* \\`B' \\`O' \\`H' \\`X' binary/octal/hexadecimal modes for input & display -* \\`i' \\`o' followed by one of \\`D' \\`B' \\`O' \\`H' \\`X' (case - insensitive) sets only the input or display radix mode -The prompt indicates the current modes: -* \"==\": decimal mode (using radians); -* \"D=\": decimal mode using degrees; -* \"?=\": ? is B/O/H, the radix for both input and output; -* \"=?\": ? is B/O/H, the display radix (with decimal input); -* \"??\": ? is D/B/O/H, 1st char for input radix, 2nd for display. - -Also, the quote key can be used to switch display modes for decimal -numbers (double-quote rotates back), and the two brace characters -\(\"{\" and \"}\" change display parameters that these displayers use, -if they handle such). If output is using any radix mode, then these -keys toggle digit grouping mode and the chunk size. - -Values can be saved for future reference in either a list of saved -values, or in registers. - -The list of saved values is useful for statistics operations on some -collected data. It is possible to navigate in this list, and if the -value shown is the current one on the list, an indication is displayed -as \"[N]\" if this is the last number and there are N numbers, or -\"[M/N]\" if the M-th value is shown. -* \\`SPC' evaluate the current value as usual, but also adds - the result to the list of saved values -* \\`l' \\`v' computes total / average of saved values -* \\`' \\`C-p' browse to the previous value in the list -* \\`' \\`C-n' browse to the next value in the list -* \\`' \\`C-d' remove current value from the list (if it is on it) -* \\`C-' \\`C-c' delete the whole list - -Registers are variable-like place-holders for values: -* \\`s' followed by a character attach the current value to that character -* \\`g' followed by a character fetches the attached value - -There are many variables that can be used to customize the calculator. -Some interesting customization variables are: -* `calculator-electric-mode' use only the echo-area electrically. -* `calculator-unary-style' set most unary ops to pre/postfix style. -* `calculator-user-registers' to define user-preset registers. -* `calculator-user-operators' to add user-defined operators. -See the documentation for these variables, and \"calculator.el\" for -more information. - -\\{calculator-mode-map}") - -(declare-function Electric-command-loop "electric" - (return-tag &optional prompt inhibit-quitting - loop-function loop-state)) - -;;;###autoload -(defun calculator () - "Run the Emacs calculator. -See the documentation for `calculator-mode' for more information." - (interactive) - (when calculator-restart-other-mode - (setq calculator-electric-mode (not calculator-electric-mode))) - (when calculator-initial-operators - (calculator-add-operators calculator-initial-operators) - (setq calculator-initial-operators nil) - ;; don't change this since it is a customization variable, - ;; its set function will add any new operators - (calculator-add-operators calculator-user-operators)) - (setq calculator-buffer (get-buffer-create "*calculator*")) - (if calculator-electric-mode - (save-window-excursion - (require 'electric) (message nil) ; hide load message - (let ((old-buf (window-buffer (minibuffer-window))) - (echo-keystrokes 0) - (garbage-collection-messages nil)) ; no gc msg when electric - (set-window-buffer (minibuffer-window) calculator-buffer) - (select-window (minibuffer-window)) - (calculator-reset) - (calculator-update-display) - (use-local-map calculator-mode-map) - (run-hooks 'calculator-mode-hook) - (unwind-protect - (catch 'calculator-done - (Electric-command-loop - 'calculator-done - ;; can't use 'noprompt, bug in electric.el - (lambda () 'noprompt) - nil - (lambda (_x _y) (calculator-update-display)))) - (set-window-buffer (minibuffer-window) old-buf) - (kill-buffer calculator-buffer)))) - (progn - (cond - ((not (get-buffer-window calculator-buffer)) - (let ((window-min-height 2)) - ;; maybe leave two lines for our window because of the - ;; normal `raised' mode line - (select-window (split-window-below - (if (calculator-need-3-lines) -3 -2))) - (switch-to-buffer calculator-buffer))) - ((not (eq (current-buffer) calculator-buffer)) - (select-window (get-buffer-window calculator-buffer)))) - (calculator-mode) - (setq buffer-read-only t) - (calculator-reset) - (message "Hit `?' For a quick help screen."))) - (when (and calculator-restart-other-mode calculator-electric-mode) - (calculator))) - -(defun calculator-need-3-lines () - ;; If the mode line might interfere with the calculator buffer, use 3 - ;; lines instead. - (let* ((dh (face-attribute 'default :height)) - (mh (face-attribute 'mode-line :height))) - ;; if the mode line is shorter than the default, stick with 2 lines - ;; (it may be necessary to check how much shorter) - (and (not (or (and (integerp dh) (integerp mh) (< mh dh)) - (and (numberp mh) (not (integerp mh)) (< mh 1)))) - (or ;; if the mode line is taller than the default, use 3 lines - (and (integerp dh) (integerp mh) (> mh dh)) - (and (numberp mh) (not (integerp mh)) (> mh 1)) - ;; if the mode line has a box with non-negative line-width, - ;; use 3 lines - (let* ((bx (face-attribute 'mode-line :box)) - (lh (plist-get bx :line-width))) - ;; Value of `:line-width' can be either a number or a cons. - (and bx (or (not lh) (> (if (consp lh) (cdr lh) lh) 0)))) - ;; if the mode line has an overline, use 3 lines - (not (memq (face-attribute 'mode-line :overline) - '(nil unspecified))))))) - -(defun calculator-message (string &rest arguments) - "Same as `message', but also handle electric mode." - (apply 'message string arguments) - (when calculator-electric-mode (sit-for 1) (message nil))) - -;;;--------------------------------------------------------------------- -;;; Operators - -(defun calculator-op-arity (op) - "Return OP's arity. -Current results are one of 2 (binary), +1 (postfix), -1 (prefix), or -0 (nullary)." - (let ((arity (nth 3 op))) - (cond ((numberp arity) arity) - ((eq calculator-unary-style 'postfix) +1) - (t -1)))) - -(defun calculator-op-prec (op) - "Return OP's precedence for reducing when inserting into the stack. -Defaults to 1." - (or (nth 4 op) 1)) - -(defun calculator-add-operators (more-ops) - "This function handles operator addition. -Adds MORE-OPS to `calculator-operator', called initially to handle -`calculator-initial-operators' and `calculator-user-operators'." - (let ((added-ops nil)) - (dolist (op more-ops) - (unless (eq (car op) 'nobind) - (calculator-define-key (car op) 'calculator-op calculator-mode-map)) - (push (if (eq (car op) 'nobind) (cdr op) op) - added-ops)) - ;; added-ops come first, but in correct order - (setq calculator-operators - (append (nreverse added-ops) calculator-operators)))) - -;;;--------------------------------------------------------------------- -;;; Display stuff - -(defun calculator-reset () - "Reset calculator variables." - (unless calculator-restart-other-mode - (setq calculator-stack nil - calculator-curnum nil - calculator-stack-display nil - calculator-display-fragile nil)) - (setq calculator-restart-other-mode nil) - (calculator-update-display)) - -(defun calculator-get-display () - "Return a string to display. -The result should not exceed the screen width." - (let* ((in-r (and calculator-input-radix - (char-to-string - (car (rassq calculator-input-radix - calculator-char-radix))))) - (out-r (and calculator-output-radix - (char-to-string - (car (rassq calculator-output-radix - calculator-char-radix))))) - (prompt (format calculator-prompt - (cond ((or in-r out-r) - (concat (or in-r "=") - (if (equal in-r out-r) "=" - (or out-r "D")))) - (calculator-deg "D=") - (t "==")))) - (expr - (concat (cdr calculator-stack-display) - (cond - ;; entering a number - (calculator-curnum (concat calculator-curnum "_")) - ;; showing a result - ((and (= 1 (length calculator-stack)) - calculator-display-fragile) - nil) - ;; waiting for a number or an operator - (t "?")))) - (trim (+ (length expr) (length prompt) 1 (- (window-width))))) - (concat prompt (if (<= trim 0) expr (substring expr trim))))) - -(defun calculator-string-to-number (str) - "Convert STR to number according to `calculator-input-radix'." - (if calculator-input-radix - (string-to-number str (cadr (assq calculator-input-radix - '((bin 2) (oct 8) (hex 16))))) - ;; parse numbers similarly to calculators - ;; (see tests in test/lisp/calculator-tests.el) - (let ((str (replace-regexp-in-string "\\.\\([^0-9].*\\)?$" ".0\\1" str))) - (float (string-to-number str))))) - -(defun calculator-push-curnum () - "Push the numeric value of the displayed number to the stack." - (when calculator-curnum - (push (calculator-string-to-number calculator-curnum) - calculator-stack) - (setq calculator-curnum nil))) - -(defun calculator-rotate-displayer (&optional new-disp) - "Switch to the next displayer on the `calculator-displayers' list. -Can be called with an optional argument NEW-DISP to force rotation to -that argument. -If radix output mode is active, toggle digit grouping." - (interactive) - (cond - (calculator-output-radix - (setq calculator-radix-grouping-mode - (not calculator-radix-grouping-mode)) - (calculator-message - "Digit grouping mode %s." - (if calculator-radix-grouping-mode "ON" "OFF"))) - (t - (setq calculator-displayers - (if (and new-disp (memq new-disp calculator-displayers)) - (let ((tmp nil)) - (while (not (eq (car calculator-displayers) new-disp)) - (push (pop calculator-displayers) tmp)) - (setq calculator-displayers - (nconc calculator-displayers (nreverse tmp)))) - (nconc (cdr calculator-displayers) - (list (car calculator-displayers))))) - (calculator-message - "Using %s." (cadr (car calculator-displayers))))) - (calculator-enter)) - -(defun calculator-rotate-displayer-back () - "Like `calculator-rotate-displayer', but rotates modes back. -If radix output mode is active, toggle digit grouping." - (interactive) - (calculator-rotate-displayer (car (last calculator-displayers)))) - -(defun calculator-displayer-prev () - "Send the current displayer function a `left' argument. -This is used to modify display arguments (if the current displayer -function supports this). -If radix output mode is active, increase the grouping size." - (interactive) - (if calculator-output-radix - (progn (setq calculator-radix-grouping-digits - (1+ calculator-radix-grouping-digits)) - (calculator-enter)) - (when (car calculator-displayers) - (let ((disp (caar calculator-displayers))) - (cond ((symbolp disp) (funcall disp 'left)) - ((and (consp disp) (eq 'std (car disp))) - (calculator-standard-displayer 'left))))))) - -(defun calculator-displayer-next () - "Send the current displayer function a `right' argument. -This is used to modify display arguments (if the current displayer -function supports this). -If radix output mode is active, decrease the grouping size." - (interactive) - (if calculator-output-radix - (progn (setq calculator-radix-grouping-digits - (max 2 (1- calculator-radix-grouping-digits))) - (calculator-enter)) - (when (car calculator-displayers) - (let ((disp (caar calculator-displayers))) - (cond ((symbolp disp) (funcall disp 'right)) - ((and (consp disp) (eq 'std (car disp))) - (calculator-standard-displayer 'right))))))) - -(defun calculator-remove-zeros (numstr) - "Get a number string NUMSTR and remove unnecessary zeros. -The behavior of this function is controlled by -`calculator-remove-zeros'." - (let* ((s (if (not (eq calculator-remove-zeros t)) numstr - ;; remove all redundant zeros leaving an integer - (replace-regexp-in-string - "\\.0+\\([eE].*\\)?$" "\\1" numstr))) - (s (if (not calculator-remove-zeros) s - ;; remove zeros, except for first after the "." - (replace-regexp-in-string - "\\(\\..[0-9]*?\\)0+\\([eE].*\\)?$" "\\1\\2" s)))) - s)) - -(defun calculator-groupize-number (str n sep &optional fromleft) - "Return the input string STR with occurrences of SEP that separate -every N characters starting from the right, or from the left if -FROMLEFT is true." - (let* ((len (length str)) (i (/ len n)) (j (% len n)) - (r (if (or (not fromleft) (= j 0)) '() - (list (substring str (- len j)))))) - (while (> i 0) - (let* ((e (* i n)) (e (if fromleft e (+ e j)))) - (push (substring str (- e n) e) r)) - (setq i (1- i))) - (when (and (not fromleft) (> j 0)) - (push (substring str 0 j) r)) - (mapconcat 'identity r sep))) - -(defun calculator-standard-displayer (num &optional char group-p) - "Standard display function, used to display NUM. -Its behavior is determined by `calculator-number-digits' and the given -CHAR argument (both will be used to compose a format string). If the -char is \"n\" then this function will choose one between %f or %e, this -is a work around %g jumping to exponential notation too fast. - -It will also split digit sequences into comma-separated groups -and/or remove redundant zeros. - -The special `left' and `right' symbols will make it change the current -number of digits displayed (`calculator-number-digits')." - (if (symbolp num) - (cond ((eq num 'left) - (when (> calculator-number-digits 0) - (setq calculator-number-digits - (1- calculator-number-digits)) - (calculator-enter))) - ((eq num 'right) - (setq calculator-number-digits - (1+ calculator-number-digits)) - (calculator-enter))) - (let* ((s (if (eq char ?n) - (let ((n (abs num))) - (if (or (and (< 0 n) (< n 0.001)) (< 1e8 n)) ?e ?f)) - char)) - (s (format "%%.%s%c" calculator-number-digits s)) - (s (calculator-remove-zeros (format s num))) - (s (if (or (not group-p) (string-match-p "[eE]" s)) s - (replace-regexp-in-string - "\\([0-9]+\\)\\(?:\\..*\\|$\\)" - (lambda (_) (calculator-groupize-number - (match-string 1 s) 3 ",")) - s nil nil 1)))) - s))) - -(defun calculator-eng-display (num) - "Display NUM in engineering notation. -The number of decimal digits used is controlled by -`calculator-number-digits', so to change it at runtime you have to use -the `left' or `right' when one of the standard modes is used." - (if (symbolp num) - (cond ((eq num 'left) - (setq calculator-eng-extra - (if calculator-eng-extra (1+ calculator-eng-extra) 1)) - (let ((calculator-eng-tmp-show t)) (calculator-enter))) - ((eq num 'right) - (setq calculator-eng-extra - (if calculator-eng-extra (1- calculator-eng-extra) -1)) - (let ((calculator-eng-tmp-show t)) (calculator-enter)))) - (let ((exp 0)) - (unless (= 0 num) - (while (< (abs num) 1.0) - (setq num (* num 1000.0)) (setq exp (- exp 3))) - (while (> (abs num) 999.0) - (setq num (/ num 1000.0)) (setq exp (+ exp 3))) - (when (and calculator-eng-tmp-show - (not (= 0 calculator-eng-extra))) - (let ((i calculator-eng-extra)) - (while (> i 0) - (setq num (* num 1000.0)) (setq exp (- exp 3)) - (setq i (1- i))) - (while (< i 0) - (setq num (/ num 1000.0)) (setq exp (+ exp 3)) - (setq i (1+ i)))))) - (unless calculator-eng-tmp-show (setq calculator-eng-extra nil)) - (let ((str (format (format "%%.%sf" calculator-number-digits) - num))) - (concat (let ((calculator-remove-zeros - ;; make sure we don't leave integers - (and calculator-remove-zeros 'x))) - (calculator-remove-zeros str)) - "e" (number-to-string exp)))))) - -(defun calculator-number-to-string (num) - "Convert NUM to a displayable string." - (cond - ;; operators are printed here, the rest is for numbers - ((not (numberp num)) (prin1-to-string (nth 1 num) t)) - ;; %f/%e handle these, but avoid them in radix or in user displayers - ((and (floatp num) (isnan num)) "NaN") - ((<= 1.0e+INF num) "Inf") - ((<= num -1.0e+INF) "-Inf") - (calculator-output-radix - ;; print with radix -- for binary, convert the octal number - (let* ((fmt (if (eq calculator-output-radix 'hex) "%x" "%o")) - (str (if calculator-2s-complement num (abs num))) - (str (format fmt (truncate str))) - (bins '((?0 "000") (?1 "001") (?2 "010") (?3 "011") - (?4 "100") (?5 "101") (?6 "110") (?7 "111"))) - (str (if (not (eq calculator-output-radix 'bin)) str - (replace-regexp-in-string - "^0+\\(.\\)" "\\1" - (apply 'concat (mapcar (lambda (c) - (cadr (assq c bins))) - str))))) - (str (if (not calculator-radix-grouping-mode) str - (calculator-groupize-number - str calculator-radix-grouping-digits - calculator-radix-grouping-separator)))) - (upcase (if (or calculator-2s-complement (>= num 0)) str - (concat "-" str))))) - ((stringp calculator-displayer) (format calculator-displayer num)) - ((symbolp calculator-displayer) (funcall calculator-displayer num)) - ((eq 'std (car-safe calculator-displayer)) - (apply 'calculator-standard-displayer - num (cdr calculator-displayer))) - ((listp calculator-displayer) - (eval `(let ((num ',num)) ,calculator-displayer) t)) - ;; nil (or bad) displayer - (t (prin1-to-string num t)))) - -(defun calculator-update-display (&optional force) - "Update the display. -If optional argument FORCE is non-nil, don't use the cached string." - (set-buffer calculator-buffer) - ;; update calculator-stack-display - (when (or force (not (eq (car calculator-stack-display) - calculator-stack))) - (setq calculator-stack-display - (cons calculator-stack - (if calculator-stack - (concat - (let ((calculator-displayer - (if (and calculator-displayers - (= 1 (length calculator-stack))) - ;; customizable display for a single value - (caar calculator-displayers) - calculator-displayer))) - (mapconcat 'calculator-number-to-string - (reverse calculator-stack) - " ")) - " " - (and calculator-display-fragile - calculator-saved-list - ;; Hack: use `eq' to compare the number: it's a - ;; flonum, so `eq' means that its the actual - ;; number rather than a computation that had an - ;; equal result (eg, enter 1,3,2, use "v" to see - ;; the average -- it now shows "2" instead of - ;; "2 [3]"). - (eq (car calculator-stack) - (nth calculator-saved-ptr - calculator-saved-list)) - (if (= 0 calculator-saved-ptr) - (format "[%s]" (length calculator-saved-list)) - (format "[%s/%s]" - (- (length calculator-saved-list) - calculator-saved-ptr) - (length calculator-saved-list))))) - "")))) - (let ((inhibit-read-only t)) - (erase-buffer) - (insert (calculator-get-display))) - (set-buffer-modified-p nil) - (goto-char (if calculator-display-fragile - (1+ (length calculator-prompt)) - (1- (point))))) - -;;;--------------------------------------------------------------------- -;;; Stack computations - -(defun calculator-reduce-stack-once (prec) - "Worker for `calculator-reduce-stack'." - (cl-flet ((check (ar op) (and (listp op) - (<= prec (calculator-op-prec op)) - (= ar (calculator-op-arity op)))) - (call (op &rest args) (apply 'calculator-funcall - (nth 2 op) args))) - (pcase calculator-stack - ;; reduce "... ( x )" --> "... x" - (`((,_ \) . ,_) ,(and X (pred numberp)) (,_ \( . ,_) . ,rest) - (cons X rest)) - ;; reduce "... x op y" --> "... r", r is the result - (`(,(and Y (pred numberp)) - ,(and O (pred (check 2))) - ,(and X (pred numberp)) - . ,rest) - (cons (call O X Y) rest)) - ;; reduce "... op x" --> "... r" for prefix op - (`(,(and X (pred numberp)) ,(and O (pred (check -1))) . ,rest) - (cons (call O X) rest)) - ;; reduce "... x op" --> "... r" for postfix op - (`(,(and O (pred (check +1))) ,(and X (pred numberp)) . ,rest) - (cons (call O X) rest)) - ;; reduce "... op" --> "... r" for 0-ary op - (`(,(and O (pred (check 0))) . ,rest) - (cons (call O) rest)) - ;; reduce "... y x" --> "... x" - ;; (needed for 0-ary ops: replace current number with result) - (`(,(and X (pred numberp)) ,(and _Y (pred numberp)) . ,rest) - (cons X rest)) - (_ nil)))) ; nil = done - -(defun calculator-reduce-stack (prec) - "Reduce the stack using top operators as long as possible. -PREC is a precedence -- reduce everything with higher precedence." - (let ((new nil)) - (while (setq new (calculator-reduce-stack-once prec)) - (setq calculator-stack new)))) - -(defun calculator-funcall (f &optional X Y) - "If F is a symbol, evaluate (F X Y). -Otherwise, it should be a list, evaluate it with X, Y bound to the -arguments." - ;; remember binary ops for calculator-repR/L - (when Y (setq calculator-last-opXY (list f X Y))) - (if (symbolp f) - (cond ((and X Y) (funcall f X Y)) - (X (funcall f X)) - (t (funcall f))) - ;; f is an expression - (let ((TX (and X (calculator-truncate X))) - (TY (and Y (calculator-truncate Y))) - (DX (if (and X calculator-deg) (degrees-to-radians X) X)) - (L calculator-saved-list) - (fF `(calculator-funcall ',f x y)) - (fD '(if calculator-deg (radians-to-degrees x) x))) - (eval `(cl-flet ((F (&optional x y) ,fF) (D (x) ,fD)) - (let ((X ,X) (Y ,Y) (DX ,DX) (TX ,TX) (TY ,TY) (L ',L)) - ,f)) - t)))) - -;;;--------------------------------------------------------------------- -;;; Input interaction - -(defun calculator-last-input (&optional keys) - "Return the last key sequence used to invoke this command, or the input KEYS. -Uses the `function-key-map' translate keypad numbers to plain -ones." - (let* ((inp (or keys (this-command-keys))) - (inp (or (and (arrayp inp) (not (stringp inp)) - (lookup-key function-key-map inp)) - inp))) - (if (or (not inp) (stringp inp) (not (arrayp inp)) - (catch 'done ; any non-chars? - (dotimes (i (length inp)) - (unless (characterp (aref inp i)) (throw 'done t))) - nil)) - inp - (concat inp)))) - -(defun calculator-clear-fragile (&optional op) - "Clear the fragile flag if it was set, then maybe reset all. -OP is the operator (if any) that caused this call." - (when (and calculator-display-fragile - (or (not op) (memq (calculator-op-arity op) '(-1 0)))) - ;; reset if last calc finished, and now get a num or prefix or 0-ary - ;; op - (calculator-reset)) - (setq calculator-display-fragile nil)) - -(defun calculator-digit () - "Enter a single digit." - (interactive) - (let ((inp (aref (calculator-last-input) 0))) - (when (and (or calculator-display-fragile - (not (numberp (car calculator-stack)))) - (<= inp (pcase calculator-input-radix - ('nil ?9) ('bin ?1) ('oct ?7) (_ 999)))) - (calculator-clear-fragile) - (setq calculator-curnum - (concat (if (equal calculator-curnum "0") "" - calculator-curnum) - (list (upcase inp)))) - (calculator-update-display)))) - -(defun calculator-decimal () - "Enter a decimal period." - (interactive) - (when (and (not calculator-input-radix) - (or calculator-display-fragile - (not (numberp (car calculator-stack)))) - (not (and calculator-curnum - (string-match-p "[.eE]" calculator-curnum)))) - ;; enter the period on the same condition as a digit, only if no - ;; period or exponent entered yet - (calculator-clear-fragile) - (setq calculator-curnum (concat (or calculator-curnum "0") ".")) - (calculator-update-display))) - -(defun calculator-exp () - "Enter an exponent, or an \"E\" digit in hex input mode." - (interactive) - (cond - (calculator-input-radix (calculator-digit)) - ((and (or calculator-display-fragile - (not (numberp (car calculator-stack)))) - (not (and calculator-curnum - (string-match-p "[eE]" calculator-curnum)))) - ;; same condition as above, also no E so far - (calculator-clear-fragile) - (setq calculator-curnum (concat (or calculator-curnum "1") "e")) - (calculator-update-display)))) - -(defun calculator-op (&optional keys) - "Enter an operator on the stack, doing all necessary reductions. -Optional string argument KEYS will force using it as the keys entered." - (interactive) - (catch 'op-error - (let* ((last-inp (calculator-last-input keys)) - (op (assoc last-inp calculator-operators))) - (calculator-clear-fragile op) - (calculator-push-curnum) - (when (and (= 2 (calculator-op-arity op)) - (not (numberp (car calculator-stack)))) - ;; we have a binary operator but no number -- search for a - ;; prefix version - (setq op (assoc last-inp (cdr (memq op calculator-operators)))) - (unless (and op (= -1 (calculator-op-arity op))) - (calculator-message "Binary operator without a first operand") - (throw 'op-error nil))) - (calculator-reduce-stack - (cond ((eq (nth 1 op) '\() 10) - ((eq (nth 1 op) '\)) 0) - (t (calculator-op-prec op)))) - (when (let ((hasnum (numberp (car calculator-stack)))) - (pcase (calculator-op-arity op) - (-1 hasnum) - ((or 1 2) (not hasnum)))) - (calculator-message "Incomplete expression") - (throw 'op-error nil)) - (push op calculator-stack) - (calculator-reduce-stack (calculator-op-prec op)) - (when (and (= (length calculator-stack) 1) - (numberp (car calculator-stack))) - ;; the display is fragile if it contains only one number - (setq calculator-display-fragile t) - (when calculator-add-saved ; add number to the saved-list - (push (car calculator-stack) - (nthcdr calculator-saved-ptr calculator-saved-list)))) - (calculator-update-display)))) - -(defun calculator-op-or-exp () - "Either enter an operator or a digit. -Used with +/- for entering them as digits in numbers like 1e-3 (there is -no need for negative numbers since these are handled by unary -operators)." - (interactive) - (if (and (not calculator-input-radix) - (not calculator-display-fragile) - calculator-curnum - (string-match-p "[eE]$" calculator-curnum)) - (calculator-digit) - (calculator-op))) - -;;;--------------------------------------------------------------------- -;;; Input/output modes (not display) - -(defun calculator-dec/deg-mode () - "Set decimal mode for display & input, if decimal, toggle deg mode." - (interactive) - (calculator-push-curnum) - (if (or calculator-input-radix calculator-output-radix) - (setq calculator-input-radix nil - calculator-output-radix nil) - ;; already decimal -- toggle degrees mode - (setq calculator-deg (not calculator-deg))) - (calculator-update-display t)) - -(defun calculator-radix-mode (&optional keys) - "Set input and display radix modes. -Optional string argument KEYS will force using it as the keys entered." - (interactive) - (calculator-radix-input-mode keys) - (calculator-radix-output-mode keys)) - -(defun calculator-radix-input-mode (&optional keys) - "Set input radix modes. -Optional string argument KEYS will force using it as the keys entered." - (interactive) - (calculator-push-curnum) - (setq calculator-input-radix - (let ((inp (calculator-last-input keys))) - (cdr (assq (upcase (aref inp (1- (length inp)))) - calculator-char-radix)))) - (calculator-update-display)) - -(defun calculator-radix-output-mode (&optional keys) - "Set display radix modes. -Optional string argument KEYS will force using it as the keys entered." - (interactive) - (calculator-push-curnum) - (setq calculator-output-radix - (let ((inp (calculator-last-input keys))) - (cdr (assq (upcase (aref inp (1- (length inp)))) - calculator-char-radix)))) - (calculator-update-display t)) - -;;;--------------------------------------------------------------------- -;;; Saved values list - -(defun calculator-save-on-list () - "Evaluate current expression, put result on the saved values list." - (interactive) - (let ((calculator-add-saved t)) ; marks the result to be added - (calculator-enter))) - -(defun calculator-clear-saved () - "Clear the list of saved values in `calculator-saved-list'." - (interactive) - (setq calculator-saved-list nil - calculator-saved-ptr 0) - (calculator-update-display t)) - -(defun calculator-saved-move (n) - "Go N elements up the list of saved values. -Interactively, N is the prefix numeric argument and defaults to 1." - (interactive "p") - (when (and calculator-saved-list - (or (null calculator-stack) calculator-display-fragile)) - (setq calculator-saved-ptr - (max (min (+ n calculator-saved-ptr) - (length calculator-saved-list)) - 0)) - (if (nth calculator-saved-ptr calculator-saved-list) - (setq calculator-stack (list (nth calculator-saved-ptr - calculator-saved-list)) - calculator-display-fragile t) - (calculator-reset)) - (calculator-update-display))) - -(defun calculator-saved-up () - "Go up the list of saved values." - (interactive) - (calculator-saved-move +1)) - -(defun calculator-saved-down () - "Go down the list of saved values." - (interactive) - (calculator-saved-move -1)) - -;;;--------------------------------------------------------------------- -;;; Misc functions - -(defun calculator-open-paren () - "Equivalents of `(' use this." - (interactive) - (calculator-op "(")) - -(defun calculator-close-paren () - "Equivalents of `)' use this." - (interactive) - (calculator-op ")")) - -(defun calculator-enter () - "Evaluate current expression." - (interactive) - (calculator-op "=")) - -(defun calculator-backspace () - "Backward delete a single digit or a stack element." - (interactive) - (if calculator-curnum - (setq calculator-curnum - (if (> (length calculator-curnum) 1) - (substring calculator-curnum - 0 (1- (length calculator-curnum))) - nil)) - (setq calculator-stack (cdr calculator-stack))) - (calculator-update-display)) - -(defun calculator-clear () - "Clear current number." - (interactive) - (setq calculator-curnum nil) - (cond - ;; if the current number is from the saved-list remove it - ((and calculator-display-fragile - calculator-saved-list - (= (car calculator-stack) - (nth calculator-saved-ptr calculator-saved-list))) - (if (= 0 calculator-saved-ptr) - (setq calculator-saved-list (cdr calculator-saved-list)) - (let ((p (nthcdr (1- calculator-saved-ptr) - calculator-saved-list))) - (setcdr p (cddr p)) - (setq calculator-saved-ptr (1- calculator-saved-ptr)))) - (if calculator-saved-list - (setq calculator-stack - (list (nth calculator-saved-ptr calculator-saved-list))) - (calculator-reset))) - ;; reset if fragile or double clear - ((or calculator-display-fragile (eq last-command this-command)) - (calculator-reset))) - (calculator-update-display)) - -(defun calculator-copy () - "Copy current number to the `kill-ring'." - (interactive) - (let ((calculator-displayer - (or calculator-copy-displayer calculator-displayer)) - (calculator-displayers - (if calculator-copy-displayer nil calculator-displayers))) - (calculator-enter) - ;; remove trailing spaces and an index - (let ((s (cdr calculator-stack-display))) - (when s - (kill-new (replace-regexp-in-string - "^\\([^ ]+\\) *\\(\\[[0-9/]+\\]\\)? *$" "\\1" s)))))) - -(defun calculator-put-value (val) - "Paste VAL as if entered. -Used by `calculator-paste' and `get-register'." - (when (and (numberp val) - ;; (not calculator-curnum) - (or calculator-display-fragile - (not (numberp (car calculator-stack))))) - (calculator-clear-fragile) - (setq calculator-curnum - (let ((calculator-displayer "%S") - (calculator-radix-grouping-mode nil) - (calculator-output-radix calculator-input-radix)) - (calculator-number-to-string val))) - (calculator-update-display))) - -(defun calculator-paste (arg) - "Paste a value from the `kill-ring'. - -With a prefix argument, paste the raw string as a sequence of key -presses, which can be used to paste expressions. Note that this -is literal; examples: spaces will store values, pasting \"1+2\" -will not produce 3 if it's done you're entering a number or after -a multiplication." - (interactive "P") - (let ((str (current-kill 0))) - (if arg - (setq unread-command-events - `(,@(listify-key-sequence str) ,@unread-command-events)) - (calculator-put-value (calculator-string-to-number str))))) - -(defun calculator-register-read-with-preview (prompt) - "Similar to `register-read-with-preview' but for calculator registers." - (let ((register-alist calculator-registers) - (register-preview-delay 1) - (register-preview-function - (lambda (r) - (format "%s: %s\n" - (single-key-description (car r)) - (calculator-number-to-string (cdr r)))))) - (register-read-with-preview prompt))) - -(defun calculator-set-register (reg) - "Set a register value for REG." - (interactive (list (calculator-register-read-with-preview - "Register to store value into: "))) - (let* ((as (assq reg calculator-registers)) - (val (progn (calculator-enter) (car calculator-stack)))) - (if as - (setcdr as val) - (push (cons reg val) calculator-registers)) - (calculator-message "[%c] := %S" reg val))) - -(defun calculator-get-register (reg) - "Get a value from a register REG." - (interactive (list (calculator-register-read-with-preview - "Register to get value from: "))) - (calculator-put-value (cdr (assq reg calculator-registers)))) - -(declare-function electric-describe-mode "ehelp" ()) - -(defun calculator-help () - ;; this is used as the quick reference screen you get with `h' - "Quick reference: -* numbers/operators/parens/./e - enter expressions - + - * / \\(div) %(rem) _(-X,postfix) ;(1/X,postfix) ^(exp) L(og) - Q(sqrt) !(fact) S(in) C(os) T(an) |(or) #(xor) &(and) ~(not) -* >/< repeats last binary operation with its 2nd (1st) arg as postfix op -* I inverse the next trig function \ -* \\='/\"/{/} - display/display args -* D - switch to all-decimal, or toggle deg/rad mode -* B/O/H/X - binary/octal/hex mode for i/o (both H and X are for hex) -* i/o - prefix for D/B/O/X - set only input/output modes -* enter/= - evaluate current expr. * s/g - set/get a register -* space - evaluate & save on list * l/v - list total/average -* up/down/C-p/C-n - browse saved * C-delete - clear all saved -* C-insert - copy whole expr. * C-return - evaluate, copy, exit -* insert - paste a number * backspace- delete backwards -* delete - clear argument or list value or whole expression (twice) -* escape/q - exit." - (interactive) - (if (eq last-command 'calculator-help) - (let ((mode-name "Calculator") - (major-mode 'calculator-mode) - (win (selected-window))) - (require 'ehelp) - (if (not calculator-electric-mode) - (describe-mode) - (electric-describe-mode)) - (select-window win) - (message nil)) - (let ((one (one-window-p t)) - (win (selected-window)) - (help-buf (get-buffer-create "*Help*"))) - (save-window-excursion - (with-output-to-temp-buffer "*Help*" - (princ (documentation 'calculator-help))) - (when one (shrink-window-if-larger-than-buffer - (get-buffer-window help-buf))) - (message "`%s' again for more help, %s." - (calculator-last-input) - "any other key continues normally") - (select-window win) - (sit-for 360)) - (select-window win)))) - -(defun calculator-quit () - "Quit calculator." - (interactive) - (set-buffer calculator-buffer) - (let ((inhibit-read-only t)) (erase-buffer)) - (unless calculator-electric-mode - (ignore-errors - (while (get-buffer-window calculator-buffer) - (delete-window (get-buffer-window calculator-buffer))))) - (kill-buffer calculator-buffer) - (message "Calculator done.") - (if calculator-electric-mode - (throw 'calculator-done nil) ; will kill the buffer - (setq calculator-buffer nil))) - -(defun calculator-save-and-quit () - "Quit the calculator, saving the result on the `kill-ring'." - (interactive) - (calculator-enter) - (calculator-copy) - (calculator-quit)) - -(defun calculator-repR (x) - "Repeat the last binary operation with its second argument and X. -To use this, apply a binary operator (evaluate it), then call this." - (if calculator-last-opXY - ;; avoid rebinding calculator-last-opXY - (let ((calculator-last-opXY calculator-last-opXY)) - (calculator-funcall - (car calculator-last-opXY) x (nth 2 calculator-last-opXY))) - x)) - -(defun calculator-repL (x) - "Repeat the last binary operation with its first argument and X. -To use this, apply a binary operator (evaluate it), then call this." - (if calculator-last-opXY - ;; avoid rebinding calculator-last-opXY - (let ((calculator-last-opXY calculator-last-opXY)) - (calculator-funcall - (car calculator-last-opXY) (nth 1 calculator-last-opXY) x)) - x)) - -(defun calculator-expt (x y) - "Compute X^Y, dealing with errors appropriately." - (condition-case nil - (expt x y) - (overflow-error - ;; X and Y must be integers, as expt silently returns floating-point - ;; infinity on floating-point overflow. - (if (or (natnump x) (zerop (logand y 1))) - 1.0e+INF - -1.0e+INF)))) - -(defun calculator-fact (x) - "Simple factorial of X." - (cond ((>= x 1.0e+INF) x) - ((or (and (floatp x) (isnan x)) (< x 0)) 0.0e+NaN) - ((>= (calculator-expt (/ x 3.0) x) 1.0e+INF) 1.0e+INF) - (t (let ((x (truncate x)) (r 1.0)) - (while (> x 0) (setq r (* r x) x (1- x))) - r)))) - -(defun calculator-truncate (n) - "Truncate N, return 0 in case of overflow." - (condition-case nil (truncate n) (range-error 0))) - - -(provide 'calculator) - -;;; calculator.el ends here diff --git a/lisp/cus-dep.el b/lisp/cus-dep.el index 1ba9cb11292..87938715270 100644 --- a/lisp/cus-dep.el +++ b/lisp/cus-dep.el @@ -39,18 +39,6 @@ ldefs-boot\\|cus-load\\|finder-inf\\|esh-groups\\|subdirs\\)\\.el$\\)" (require 'loaddefs-gen) -;; Hack workaround for bug#14384. -;; Define defcustom-mh as an alias for defcustom, etc. -;; Only do this in batch mode to avoid messing up a normal Emacs session. -;; Alternative would be to load mh-e when making cus-load. -;; (Would be better to split just the necessary parts of mh-e into a -;; separate file and only load that.) -(when (and noninteractive) - (mapc (lambda (e) (let ((sym (intern (format "%s-mh" e)))) - (or (fboundp sym) - (defalias sym e)))) - '(defcustom defface defgroup))) - (defun custom--get-def (expr) (if (not (memq (car-safe expr) '( define-minor-mode define-globalized-minor-mode))) diff --git a/lisp/ebuff-menu.el b/lisp/ebuff-menu.el deleted file mode 100644 index 7ea5249a71f..00000000000 --- a/lisp/ebuff-menu.el +++ /dev/null @@ -1,269 +0,0 @@ -;;; ebuff-menu.el --- electric-buffer-list mode -*- lexical-binding: t -*- - -;; Copyright (C) 1985-1986, 1994, 2001-2024 Free Software Foundation, -;; Inc. - -;; Author: Richard Mlynarik -;; Maintainer: emacs-devel@gnu.org -;; Keywords: convenience - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Who says one can't have typeout windows in GNU Emacs? The entry -;; point, `electric-buffer-list' works like ^r select buffer from the -;; ITS Emacs lunar or tmacs libraries. - -;;; Code: - -(require 'electric) - -(defvar electric-buffer-menu-mode-map - (let ((map (make-keymap))) - (fillarray (car (cdr map)) #'Electric-buffer-menu-undefined) - (define-key map "\e" nil) - (define-key map "\C-z" #'suspend-frame) - (define-key map "v" #'Electric-buffer-menu-mode-view-buffer) - (define-key map "\C-c" nil) - (define-key map "\C-c\C-c" #'Electric-buffer-menu-quit) - (define-key map "\C-]" #'Electric-buffer-menu-quit) - (define-key map "q" #'Electric-buffer-menu-quit) - (define-key map " " #'Electric-buffer-menu-select) - (define-key map "\C-m" #'Electric-buffer-menu-select) - (define-key map "\C-l" #'recenter) - (define-key map "s" #'Buffer-menu-save) - (define-key map "S" #'tabulated-list-sort) - (define-key map "d" #'Buffer-menu-delete) - (define-key map "k" #'Buffer-menu-delete) - (define-key map "\C-d" #'Buffer-menu-delete-backwards) - ;; (define-key map "\C-k" #'Buffer-menu-delete) - (define-key map "\177" #'Buffer-menu-backup-unmark) - (define-key map "~" #'Buffer-menu-not-modified) - (define-key map "u" #'Buffer-menu-unmark) - (define-key map "\M-\177" #'Buffer-menu-unmark-all-buffers) - (define-key map "U" #'Buffer-menu-unmark-all) - (dotimes (i 10) - (define-key map (char-to-string i) #'digit-argument) - (define-key map (concat "\e" (char-to-string i)) #'digit-argument)) - (define-key map "-" #'negative-argument) - (define-key map "\e-" #'negative-argument) - (define-key map "m" #'Buffer-menu-mark) - (define-key map "\C-u" #'universal-argument) - (define-key map "\C-p" #'previous-line) - (define-key map "\C-n" #'next-line) - (define-key map "p" #'previous-line) - (define-key map "n" #'next-line) - (define-key map "\C-v" #'scroll-up-command) - (define-key map "\ev" #'scroll-down-command) - (define-key map ">" #'scroll-right) - (define-key map "<" #'scroll-left) - (define-key map "\e\C-v" #'scroll-other-window) - (define-key map "\e>" #'end-of-buffer) - (define-key map "\e<" #'beginning-of-buffer) - (define-key map "\e\e" nil) - (define-key map "\e\e\e" #'Electric-buffer-menu-quit) - ;; This binding prevents the "escape => ESC" function-key-map mapping from - ;; kicking in! - ;; (define-key map [escape escape escape] #'Electric-buffer-menu-quit) - (define-key map [mouse-2] #'Electric-buffer-menu-mouse-select) - map)) - -(put 'Electric-buffer-menu-quit :advertised-binding "\C-c\C-c") -(put 'Electric-buffer-menu-select :advertised-binding " ") - -(defvar electric-buffer-menu-mode-hook nil - "Normal hook run by `electric-buffer-menu-mode'.") - -;;;###autoload -(defun electric-buffer-list (arg) - "Pop up the Buffer Menu in an \"electric\" window. -If you type SPC or RET (`Electric-buffer-menu-select'), that -selects the buffer at point and quits the \"electric\" window. -Otherwise, you can move around in the Buffer Menu, marking -buffers to be selected, saved or deleted; these other commands -are much like those of `Buffer-menu-mode'. - -Run hooks in `electric-buffer-menu-mode-hook' on entry. - -\\ -\\[keyboard-quit] or \\[Electric-buffer-menu-quit] -- exit buffer menu, returning to previous window and buffer - configuration. If the very first character typed is a space, it - also has this effect. -\\[Electric-buffer-menu-select] -- select buffer of line point is on. - Also show buffers marked with m in other windows, - deletes buffers marked with \"D\", and saves those marked with \"S\". -\\[Buffer-menu-mark] -- mark buffer to be displayed. -\\[Buffer-menu-not-modified] -- clear modified-flag on that buffer. -\\[Buffer-menu-save] -- mark that buffer to be saved. -\\[Buffer-menu-delete] or \\[Buffer-menu-delete-backwards] -- mark that buffer to be deleted. -\\[Buffer-menu-unmark] -- remove all kinds of marks from current line. -\\[Buffer-menu-unmark-all] -- remove all kinds of marks from all lines. -\\[Electric-buffer-menu-mode-view-buffer] -- view buffer, returning when done. -\\[Buffer-menu-backup-unmark] -- back up a line and remove marks." - (interactive "P") - (let (select buffer) - (save-window-excursion - (setq buffer (list-buffers-noselect arg)) - (Electric-pop-up-window buffer) - (unwind-protect - (let ((header header-line-format)) - (set-buffer buffer) - (electric-buffer-menu-mode) - (setq header-line-format header) - (goto-char (point-min)) - (if (search-forward "\n." nil t) - (forward-char -1)) - (electric-buffer-update-highlight) - (setq select - (catch 'electric-buffer-menu-select - (message "<<< Type SPC or RET to bury the buffer list >>>") - (push (read-event) unread-command-events) - (let ((start-point (point)) - (first (progn (goto-char (point-min)) - (unless Buffer-menu-use-header-line - (forward-line 2)) - (point))) - (last (progn (goto-char (point-max)) - (forward-line -1) - (point))) - (goal-column 0)) - ;; Use start-point if it is meaningful. - (goto-char (if (or (< start-point first) - (> start-point last)) - first - start-point)) - (Electric-command-loop 'electric-buffer-menu-select - nil - t - 'electric-buffer-menu-looper - (cons first last)))))) - (set-buffer buffer) - (Buffer-menu-mode) - (bury-buffer) ;Get rid of window, if dedicated. - (message ""))) - (when select - (set-buffer buffer) - (goto-char select) - (let ((opoint (point-marker))) - (Buffer-menu-execute) - (goto-char (point-min)) - (if (prog1 (search-forward "\n>" nil t) - (goto-char opoint) - (set-marker opoint nil)) - (Buffer-menu-select) - (switch-to-buffer (Buffer-menu-buffer t))))))) - -(defun electric-buffer-menu-looper (state condition) - (cond ((and condition - (not (memq (car condition) '(buffer-read-only - end-of-buffer - beginning-of-buffer)))) - (signal (car condition) (cdr condition))) - ((< (point) (car state)) - (goto-char (point-min)) - (unless Buffer-menu-use-header-line - (forward-line 2))) - ((> (point) (cdr state)) - (goto-char (point-max)) - (forward-line -1) - (if (pos-visible-in-window-p (point-max)) - (recenter -1)))) - (electric-buffer-update-highlight)) - -(define-derived-mode electric-buffer-menu-mode Buffer-menu-mode - "Electric Buffer Menu" - "Toggle Electric Buffer Menu mode in this buffer. -With a prefix argument ARG, enable Long Lines mode if ARG is -positive, and disable it otherwise. If called from Lisp, enable -the mode if ARG is omitted or nil. - -Electric Buffer Menu mode is a minor mode which is automatically -enabled and disabled by the \\[electric-buffer-list] command. -See the documentation of `electric-buffer-list' for details." - (setq mode-line-buffer-identification "Electric Buffer List")) - -;; generally the same as Buffer-menu-mode-map -;; (except we don't indirect to global-map) -(put 'Electric-buffer-menu-undefined 'suppress-keymap t) - -(defun Electric-buffer-menu-exit () - (interactive) - (setq unread-command-events - (nconc (listify-key-sequence (this-command-keys)) - unread-command-events)) - ;; for robustness - (condition-case () - (throw 'electric-buffer-menu-select nil) - (error (Buffer-menu-mode) - (other-buffer)))) - -(defun Electric-buffer-menu-select () - "Leave Electric Buffer Menu, selecting buffers and executing changes. -Save buffers marked \"S\". Delete buffers marked \"K\". -Select buffer at point and display buffers marked \">\" in other windows." - (interactive) - (throw 'electric-buffer-menu-select (point))) - -(defun Electric-buffer-menu-mouse-select (event) - (interactive "e") - (select-window (posn-window (event-end event))) - (set-buffer (window-buffer)) - (goto-char (posn-point (event-end event))) - (throw 'electric-buffer-menu-select (point))) - -(defun Electric-buffer-menu-quit () - "Leave Electric Buffer Menu, restoring previous window configuration. -Skip execution of select, save, and delete commands." - (interactive) - (throw 'electric-buffer-menu-select nil)) - -(defun Electric-buffer-menu-undefined () - (interactive) - (ding) - (message "%s" - (substitute-command-keys "\ -Type \\[Electric-buffer-menu-quit] to exit, \ -\\[Electric-buffer-menu-select] to select.")) - (sit-for 4)) - -(defun Electric-buffer-menu-mode-view-buffer () - "View buffer on current line in Electric Buffer Menu. -Return to Electric Buffer Menu when done." - (interactive) - (let ((bufnam (Buffer-menu-buffer nil))) - (if bufnam - (view-buffer bufnam) - (ding) - (message "Buffer %s does not exist!" bufnam) - (sit-for 4)))) - -(defvar electric-buffer-overlay nil) - -(defun electric-buffer-update-highlight () - (when (derived-mode-p 'electric-buffer-menu-mode) - ;; Make sure we have an overlay to use. - (or electric-buffer-overlay - (setq-local electric-buffer-overlay - (make-overlay (point) (point)))) - (move-overlay electric-buffer-overlay - (line-beginning-position) - (line-end-position)) - (overlay-put electric-buffer-overlay 'face 'highlight))) - -(provide 'ebuff-menu) - -;;; ebuff-menu.el ends here diff --git a/lisp/ehelp.el b/lisp/ehelp.el deleted file mode 100644 index a5ddb915ede..00000000000 --- a/lisp/ehelp.el +++ /dev/null @@ -1,437 +0,0 @@ -;;; ehelp.el --- bindings for electric-help mode -*- lexical-binding: t -*- - -;; Copyright (C) 1986, 1995, 2000-2024 Free Software Foundation, Inc. - -;; Author: Richard Mlynarik -;; (according to ack.texi and authors.el) -;; Maintainer: emacs-devel@gnu.org -;; Keywords: help, extensions - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; This package provides a pre-packaged `Electric Help Mode' for -;; browsing Emacs help screens. There is one entry point, -;; `with-electric-help'; all you have to give it is a no-argument -;; function that generates the actual text of the help into the current -;; buffer. - -;; To make this the default, you must do -;; (define-key global-map "\C-h" 'ehelp-command) -;; (define-key global-map [help] 'ehelp-command) -;; (define-key global-map [f1] 'ehelp-command) - -;;; Code: - -(require 'electric) - -(defvar electric-help-form-to-execute nil) - -(defgroup electric-help () - "Electric help facility." - :version "21.1" - :group 'help) - -(defcustom electric-help-shrink-window t - "If set, adjust help window sizes to buffer sizes when displaying help." - :type 'boolean - :group 'electric-help) - -(defcustom electric-help-mode-hook nil - "Hook run by `with-electric-help' after initializing the buffer." - :type 'hook - :group 'electric-help) - -(put 'electric-help-undefined 'suppress-keymap t) - -(defvar electric-help-map - (let ((map (make-keymap))) - ;; FIXME fragile. Should derive from help-mode-map in a smarter way. - (set-keymap-parent map button-buffer-map) - ;; allow all non-self-inserting keys - search, scroll, etc, but - ;; let M-x and C-x exit ehelp mode and retain buffer: - (suppress-keymap map) - (define-key map "\C-u" 'electric-help-undefined) - (define-key map [?\C-0] 'electric-help-undefined) - (define-key map [?\C-1] 'electric-help-undefined) - (define-key map [?\C-2] 'electric-help-undefined) - (define-key map [?\C-3] 'electric-help-undefined) - (define-key map [?\C-4] 'electric-help-undefined) - (define-key map [?\C-5] 'electric-help-undefined) - (define-key map [?\C-6] 'electric-help-undefined) - (define-key map [?\C-7] 'electric-help-undefined) - (define-key map [?\C-8] 'electric-help-undefined) - (define-key map [?\C-9] 'electric-help-undefined) - (define-key map (if (characterp help-char) - (char-to-string help-char) - (vector help-char)) - 'electric-help-help) - (define-key map "?" 'electric-help-help) - (define-key map " " 'scroll-up) - (define-key map [?\S-\ ] 'scroll-down) - (define-key map "\^?" 'scroll-down) - (define-key map "." 'beginning-of-buffer) - (define-key map "<" 'beginning-of-buffer) - (define-key map ">" 'end-of-buffer) - ;(define-key map "\C-g" 'electric-help-exit) - (define-key map "Q" 'electric-help-exit) - (define-key map "q" 'electric-help-exit) - ;;a better key than this? - (define-key map "R" 'electric-help-retain) - (define-key map "r" 'electric-help-retain) - (define-key map "\ex" 'electric-help-execute-extended) - (define-key map "\C-x" 'electric-help-ctrl-x-prefix) - map) - "Keymap defining commands available in `electric-help-mode'.") - -(defvar-local electric-help-orig-major-mode nil) - -(defun electric-help-mode () - "`with-electric-help' temporarily places its buffer in this mode. -\(On exit from `with-electric-help', the original `major-mode' is restored.)" - (setq buffer-read-only t) - (setq electric-help-orig-major-mode major-mode) - (setq mode-name "Help") - (setq major-mode 'help-mode) - (setq mode-line-buffer-identification '(" Help: %b")) - (use-local-map electric-help-map) - (add-hook 'mouse-leave-buffer-hook 'electric-help-retain) - (view-mode -1) - ;; this is done below in with-electric-help - ;(run-hooks 'electric-help-mode-hook) - ) - -;;;###autoload -(defun with-electric-help (thunk &optional buffer noerase minheight) - "Pop up an \"electric\" help buffer. -THUNK is a function of no arguments which is called to initialize the -contents of BUFFER. BUFFER defaults to `*Help*'. BUFFER will be -erased before THUNK is called unless NOERASE is non-nil. THUNK will -be called while BUFFER is current and with `standard-output' bound to -the buffer specified by BUFFER. - -If THUNK returns nil, we display BUFFER starting at the top, and shrink -the window to fit. If THUNK returns non-nil, we don't do those things. - -After THUNK has been called, this function \"electrically\" pops up a -window in which BUFFER is displayed and allows the user to scroll -through that buffer in `electric-help-mode'. The window's height will -be at least MINHEIGHT if this value is non-nil. - -If THUNK returns nil, we display BUFFER starting at the top, and -shrink the window to fit if `electric-help-shrink-window' is non-nil. -If THUNK returns non-nil, we don't do those things. - -When the user exits (with `electric-help-exit', or otherwise), the help -buffer's window disappears (i.e., we use `save-window-excursion'), and -BUFFER is put back into its original major mode." - (setq buffer (get-buffer-create (or buffer "*Help*"))) - (let ((one (one-window-p t)) - (config (current-window-configuration)) - (bury nil) - (electric-help-form-to-execute nil)) - (unwind-protect - (save-excursion - (when one - (goto-char (window-start))) - (let ((pop-up-windows t)) - (pop-to-buffer buffer)) - (with-current-buffer buffer - (when (and minheight (< (window-height) minheight)) - (enlarge-window (- minheight (window-height)))) - (electric-help-mode) - (setq buffer-read-only nil) - (unless noerase - (erase-buffer))) - (let ((standard-output buffer)) - (unless (funcall thunk) - (set-buffer buffer) - (set-buffer-modified-p nil) - (goto-char (point-min)) - (when (and one electric-help-shrink-window) - (shrink-window-if-larger-than-buffer)))) - (set-buffer buffer) - (run-hooks 'electric-help-mode-hook) - (setq buffer-read-only t) - (if (eq (car-safe (electric-help-command-loop)) 'retain) - (setq config (current-window-configuration)) - (setq bury t)) - ;; Remove the hook. - (when (memq 'electric-help-retain mouse-leave-buffer-hook) - (remove-hook 'mouse-leave-buffer-hook 'electric-help-retain))) - (message "") - (set-buffer buffer) - (setq buffer-read-only nil) - - ;; Restore the original major mode saved by `electric-help-mode'. - ;; We should really get a usable *Help* buffer when retaining - ;; the electric one with `r'. The problem is that a simple - ;; call to `help-mode' won't cut it; e.g. RET is bound wrong - ;; afterwards (`View-scroll-line-forward' instead of `help-follow'). - ;; That's because Help mode should be set with `with-help-window' - ;; instead of the direct call to `help-mode'. But at least - ;; RET works correctly on links after using `help-mode'. - ;; This is satisfactory enough. - (condition-case () - (funcall (or electric-help-orig-major-mode 'fundamental-mode)) - (error nil)) - - (set-window-configuration config) - (when bury - ;;>> Perhaps this shouldn't be done, - ;; so that when we say "Press space to bury" we mean it - (replace-buffer-in-windows buffer) - ;; must do this outside of save-window-excursion - (bury-buffer buffer)) - (if (functionp electric-help-form-to-execute) - (funcall electric-help-form-to-execute) - (eval electric-help-form-to-execute))))) - -(defun electric-help-command-loop () - (catch 'exit - (if (pos-visible-in-window-p (point-max)) - (progn (message "%s" (substitute-command-keys "<<< Press Space to bury the help buffer, Press \\[electric-help-retain] to retain it >>>")) - (let ((ev (read-event))) - (if (equal ev ?\s) - (throw 'exit t) - (push ev unread-command-events))))) - (let (up down both neither - (standard (and (eq (key-binding " " nil t) - 'scroll-up) - (eq (key-binding "\^?" nil t) - 'scroll-down) - (eq (key-binding "q" nil t) - 'electric-help-exit) - (eq (key-binding "r" nil t) - 'electric-help-retain)))) - (Electric-command-loop - 'exit - (lambda () - (sit-for 0) ;necessary if last command was end-of-buffer or - ;beginning-of-buffer - otherwise pos-visible-in-window-p - ;will yield a wrong result. - (let ((min (pos-visible-in-window-p (point-min))) - (max (pos-visible-in-window-p (1- (point-max))))) - (cond (isearch-mode 'noprompt) - ((and min max) - (cond (standard "Press q to exit, r to retain ") - (neither) - (t (setq neither (substitute-command-keys "Press \\[electric-help-exit] to exit, \\[electric-help-retain] to retain "))))) - (min - (cond (standard "Press SPC to scroll, q to exit, r to retain ") - (up) - (t (setq up (substitute-command-keys "Press \\[scroll-up] to scroll, \\[electric-help-exit] to exit, \\[electric-help-retain] to retain "))))) - (max - (cond (standard "Press DEL to scroll back, q to exit, r to retain ") - (down) - (t (setq down (substitute-command-keys "Press \\[scroll-down] to scroll back, \\[electric-help-exit] to exit, \\[electric-help-retain] to retain "))))) - (t - (cond (standard "Press SPC to scroll, DEL to scroll back, q to exit, r to retain ") - (both) - (t (setq both (substitute-command-keys "Press \\[scroll-up] to scroll, \\[scroll-down] to scroll back, \\[electric-help-exit] to exit, \\[electric-help-retain] to retain ")))))))) - t)))) - - - -;(defun electric-help-scroll-up (arg) -; ">>>Doc" -; (interactive "P") -; (if (and (null arg) (pos-visible-in-window-p (point-max))) -; (electric-help-exit) -; (scroll-up arg))) - -(defun electric-help-exit () - "Exit `with-electric-help', restoring the previous window/buffer configuration. -\(The *Help* buffer will be buried.)" - (interactive) - ;; Make sure that we don't throw twice, even if two events cause - ;; calling this function: - (if (memq 'electric-help-retain mouse-leave-buffer-hook) - (progn - (remove-hook 'mouse-leave-buffer-hook 'electric-help-retain) - (throw 'exit t)))) - -(defun electric-help-retain () - "Exit `with-electric-help', retaining the current window/buffer configuration. -\(The *Help* buffer will not be selected, but \\[switch-to-buffer-other-window] RET -will select it.)" - (interactive) - ;; Make sure that we don't throw twice, even if two events cause - ;; calling this function: - (if (memq 'electric-help-retain mouse-leave-buffer-hook) - (progn - (remove-hook 'mouse-leave-buffer-hook 'electric-help-retain) - (throw 'exit '(retain))))) - - -(defun electric-help-undefined () - (interactive) - (error "%s is undefined -- Press %s to exit" - (mapconcat 'single-key-description (this-command-keys) " ") - (if (eq (key-binding "q" nil t) 'electric-help-exit) - "q" - (substitute-command-keys "\\[electric-help-exit]")))) - - -;>>> this needs to be hairified (recursive help, anybody?) -(defun electric-help-help () - (interactive) - (if (and (eq (key-binding "q" nil t) 'electric-help-exit) - (eq (key-binding " " nil t) 'scroll-up) - (eq (key-binding "\^?" nil t) 'scroll-down) - (eq (key-binding "r" nil t) 'electric-help-retain)) - (message "SPC scrolls up, DEL scrolls down, q exits burying help buffer, r exits") - (message "%s" (substitute-command-keys "\\[scroll-up] scrolls up, \\[scroll-down] scrolls down, \\[electric-help-exit] exits burying help buffer, \\[electric-help-retain] exits"))) - (sit-for 2)) - - -;;;###autoload -(defun electric-helpify (fun &optional name) - (let ((name (or name "*Help*"))) - (if (save-window-excursion - ;; kludge-o-rama - (let* ((p (symbol-function 'help-print-return-message)) - (b (get-buffer name)) - (m (buffer-modified-p b))) - (and b (not (get-buffer-window b)) - (setq b nil)) - (unwind-protect - (progn - (message "%s..." (capitalize (symbol-name fun))) - ;; with-output-to-temp-buffer marks the buffer as unmodified. - ;; kludging excessively and relying on that as some sort - ;; of indication leads to the following abomination... - ;;>> This would be doable without such icky kludges if either - ;;>> (a) there were a function to read the interactive - ;;>> args for a command and return a list of those args. - ;;>> (To which one would then just apply the command) - ;;>> (The only problem with this is that interactive-p - ;;>> would break, but that is such a misfeature in - ;;>> any case that I don't care) - ;;>> It is easy to do this for emacs-lisp functions; - ;;>> the only problem is getting the interactive spec - ;;>> for subrs - ;;>> (b) there were a function which returned a - ;;>> modification-tick for a buffer. One could tell - ;;>> whether a buffer had changed by whether the - ;;>> modification-tick were different. - ;;>> (Presumably there would have to be a way to either - ;;>> restore the tick to some previous value, or to - ;;>> suspend updating of the tick in order to allow - ;;>> things like momentary-string-display) - (and b - (with-current-buffer b - (set-buffer-modified-p t))) - (fset 'help-print-return-message 'ignore) - (call-interactively fun) - (and (get-buffer name) - (get-buffer-window (get-buffer name)) - (or (not b) - (not (eq b (get-buffer name))) - (not (buffer-modified-p b))))) - (fset 'help-print-return-message p) - (and b (buffer-name b) - (with-current-buffer b - (set-buffer-modified-p m)))))) - (with-electric-help 'ignore name t)))) - - - -;; This is to be bound to M-x in ehelp mode. Retains ehelp buffer and then -;; continues with execute-extended-command. -(defun electric-help-execute-extended (_prefixarg) - (interactive "p") - (setq electric-help-form-to-execute - (lambda () - (with-suppressed-warnings ((interactive-only - execute-extended-command)) - (execute-extended-command nil)))) - (electric-help-retain)) - -;; This is to be buond to C-x in ehelp mode. Retains ehelp buffer and then -;; continues with ctrl-x prefix. -(defun electric-help-ctrl-x-prefix (_prefixarg) - (interactive "p") - (setq electric-help-form-to-execute - (lambda () - (message nil) - (setq unread-command-events - (append unread-command-events '(?\C-x))))) - (electric-help-retain)) - - -(defun electric-describe-key () - (interactive) - (electric-helpify 'describe-key)) - -(defun electric-describe-mode () - (interactive) - (electric-helpify 'describe-mode)) - -(defun electric-view-lossage () - (interactive) - (electric-helpify 'view-lossage)) - -(defun electric-describe-function () - (interactive) - (electric-helpify 'describe-function)) - -(defun electric-describe-variable () - (interactive) - (electric-helpify 'describe-variable)) - -(defun electric-describe-bindings () - (interactive) - (electric-helpify 'describe-bindings)) - -(defun electric-describe-syntax () - (interactive) - (electric-helpify 'describe-syntax)) - -(defun electric-command-apropos () - (interactive) - (electric-helpify 'command-apropos "*Apropos*")) - -;(define-key help-map "a" 'electric-command-apropos) - -(defun electric-apropos () - (interactive) - (electric-helpify 'apropos)) - - -;;;; ehelp-map - -(defvar ehelp-map - (let ((map (copy-keymap help-map))) - (substitute-key-definition 'apropos 'electric-apropos map) - (substitute-key-definition 'command-apropos 'electric-command-apropos map) - (substitute-key-definition 'describe-key 'electric-describe-key map) - (substitute-key-definition 'describe-mode 'electric-describe-mode map) - (substitute-key-definition 'view-lossage 'electric-view-lossage map) - (substitute-key-definition 'describe-function 'electric-describe-function map) - (substitute-key-definition 'describe-variable 'electric-describe-variable map) - (substitute-key-definition 'describe-bindings 'electric-describe-bindings map) - (substitute-key-definition 'describe-syntax 'electric-describe-syntax map) - map)) - -;;;###(autoload 'ehelp-command "ehelp" "Prefix command for ehelp." t 'keymap) -(defalias 'ehelp-command ehelp-map) -(put 'ehelp-command 'documentation "Prefix command for ehelp.") - -(provide 'ehelp) - -;;; ehelp.el ends here diff --git a/lisp/electric.el b/lisp/electric.el index d02bcb4735b..eaa65f86f37 100644 --- a/lisp/electric.el +++ b/lisp/electric.el @@ -39,137 +39,6 @@ ;;; Code: -;; This loop is the guts for non-standard modes which retain control -;; until some event occurs. It is a `do-forever', the only way out is -;; to throw. It assumes that you have set up the keymap, window, and -;; everything else: all it does is read commands and execute them - -;; providing error messages should one occur (if there is no loop -;; function - which see). The required argument is a tag which should -;; expect a value of nil if the user decides to punt. The second -;; argument is the prompt to be used: if nil, use "->", if 'noprompt, -;; don't use a prompt, if a string, use that string as prompt, and if -;; a function of no variable, it will be evaluated in every iteration -;; of the loop and its return value, which can be nil, 'noprompt or a -;; string, will be used as prompt. Given third argument non-nil, it -;; INHIBITS quitting unless the user types C-g at toplevel. This is -;; so user can do things like C-u C-g and not get thrown out. Fourth -;; argument, if non-nil, should be a function of two arguments which -;; is called after every command is executed. The fifth argument, if -;; provided, is the state variable for the function. If the -;; loop-function gets an error, the loop will abort WITHOUT throwing -;; (moral: use unwind-protect around call to this function for any -;; critical stuff). The second argument for the loop function is the -;; conditions for any error that occurred or nil if none. - -(defun Electric-command-loop (return-tag - &optional prompt inhibit-quitting - loop-function loop-state) - - (let (cmd - (err nil) - (inhibit-quit inhibit-quitting) - (prompt-string prompt)) - (while t - (if (functionp prompt) - (setq prompt-string (funcall prompt))) - (if (not (stringp prompt-string)) - (setq prompt-string (unless (eq prompt-string 'noprompt) "->"))) - (setq cmd (read-key-sequence prompt-string)) - (setq last-command-event (aref cmd (1- (length cmd))) - this-command (key-binding cmd t) - cmd this-command) - (if (or (prog1 quit-flag (setq quit-flag nil)) - (eq last-input-event ?\C-g)) - (progn (setq unread-command-events nil - prefix-arg nil) - ;; If it wasn't canceling a prefix character, then quit. - (if (or (= (length (this-command-keys)) 1) - (not inhibit-quit)) ; safety - (progn (ding) - (message "Quit") - (throw return-tag nil)) - (setq cmd nil)))) - (setq current-prefix-arg prefix-arg) - (if cmd - (condition-case conditions - (progn (command-execute cmd) - (setq last-command this-command) - (if (or (prog1 quit-flag (setq quit-flag nil)) - (eq last-input-event ?\C-g)) - (progn (setq unread-command-events nil) - (if (not inhibit-quit) - (progn (ding) - (message "Quit") - (throw return-tag nil)) - (ding))))) - (buffer-read-only (if loop-function - (setq err conditions) - (ding) - (message "Buffer is read-only") - (sit-for 2))) - (beginning-of-buffer (if loop-function - (setq err conditions) - (ding) - (message "Beginning of Buffer") - (sit-for 2))) - (end-of-buffer (if loop-function - (setq err conditions) - (ding) - (message "End of Buffer") - (sit-for 2))) - (error (if loop-function - (setq err conditions) - (ding) - (message "Error: %s" - (if (eq (car conditions) 'error) - (car (cdr conditions)) - (prin1-to-string conditions))) - (sit-for 2)))) - (ding)) - (if loop-function (funcall loop-function loop-state err)))) - (ding) - (throw return-tag nil)) - -;; This function is like pop-to-buffer, sort of. -;; The algorithm is -;; If there is a window displaying buffer -;; Select it -;; Else if there is only one window -;; Split it, selecting the window on the bottom with height being -;; the lesser of max-height (if non-nil) and the number of lines in -;; the buffer to be displayed subject to window-min-height constraint. -;; Else -;; Switch to buffer in the current window. -;; -;; Then if max-height is nil, and not all of the lines in the buffer -;; are displayed, grab the whole frame. -;; -;; Returns selected window on buffer positioned at point-min. - -(defun Electric-pop-up-window (buffer &optional max-height) - (let* ((win (or (get-buffer-window buffer) (selected-window))) - (buf (get-buffer buffer)) - (one-window (one-window-p t)) - (pop-up-windows t) - (pop-up-frames nil)) - (if (not buf) - (error "Buffer %s does not exist" buffer) - (cond ((and (eq (window-buffer win) buf)) - (select-window win)) - (one-window - (pop-to-buffer buffer) - (setq win (selected-window))) - (t - (switch-to-buffer buf))) - ;; Don't shrink the window, but expand it if necessary. - (goto-char (point-min)) - (unless (= (point-max) (window-end win t)) - ;; This call is executed even if the window existed before, was - ;; reused, ... contradicting a claim in the comment before this - ;; function. - (fit-window-to-buffer win max-height nil nil nil t)) - win))) - ;;; Electric keys. (defgroup electricity () diff --git a/lisp/emulation/edt-lk201.el b/lisp/emulation/edt-lk201.el deleted file mode 100644 index 09e834503bf..00000000000 --- a/lisp/emulation/edt-lk201.el +++ /dev/null @@ -1,59 +0,0 @@ -;;; edt-lk201.el --- enhanced EDT keypad mode emulation for LK-201 keyboards -*- lexical-binding: t -*- - -;; Copyright (C) 1986, 1992-1993, 1995, 2001-2024 Free Software -;; Foundation, Inc. - -;; Author: Kevin Gallagher -;; Keywords: emulations -;; Package: edt - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; See Info node `edt' for more details. - -;; ==================================================================== - -;;;; -;;;; KEY TRANSLATIONS -;;;; - -;; Associate EDT keynames with Emacs terminal function vector names. -;; (Function key vector names for LK-201 are found in lisp/term/lk201.el.) -;; -;; F1 - F5 are not available on many DEC VT series terminals. -;; However, this is not always the case. So support for F1 - F5 is -;; provided here and in lisp/term/lk201.el. - -;;; Code: - -(defconst *EDT-keys* - '(("KP0" . [kp-0]) ("KP1" . [kp-1]) ("KP2" . [kp-2]) ("KP3" . [kp-3]) - ("KP4" . [kp-4]) ("KP5" . [kp-5]) ("KP6" . [kp-6]) ("KP7" . [kp-7]) - ("KP8" . [kp-8]) ("KP9" . [kp-9]) ("KP," . [kp-separator]) - ("KP-" . [kp-subtract]) ("KPP" . [kp-decimal]) ("KPE" . [kp-enter]) - ("PF1" . [kp-f1]) ("PF2" . [kp-f2]) ("PF3" . [kp-f3]) ("PF4" . [kp-f4]) - ("UP" . [up]) ("DOWN" . [down]) ("RIGHT" . [right]) ("LEFT" . [left]) - ("FIND" . [find]) ("INSERT" . [insert]) ("REMOVE" . [delete]) - ("SELECT" . [select]) ("PREVIOUS" . [prior]) ("NEXT" . [next]) - ("F1" . [f1]) ("F2" . [f2]) ("F3" . [f3]) ("F4" . [f4]) ("F5" . [f5]) - ("F6" . [f6]) ("F7" . [f7]) ("F8" . [f8]) ("F9" . [f9]) ("F10" . [f10]) - ("F11" . [f11]) ("F12" . [f12]) ("F13" . [f13]) ("F14" . [f14]) - ("HELP" . [help]) ("DO" . [menu]) ("F17" . [f17]) ("F18" . [f18]) - ("F19" . [f19]) ("F20" . [f20]))) - -;;; edt-lk201.el ends here diff --git a/lisp/emulation/edt-mapper.el b/lisp/emulation/edt-mapper.el deleted file mode 100644 index 00b7ab82cea..00000000000 --- a/lisp/emulation/edt-mapper.el +++ /dev/null @@ -1,523 +0,0 @@ -;;; edt-mapper.el --- create an EDT LK-201 map file for X-Windows Emacs -*- lexical-binding: t; -*- - -;; Copyright (C) 1994-1995, 2000-2024 Free Software Foundation, Inc. - -;; Author: Kevin Gallagher -;; Keywords: emulations -;; Package: edt - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: -;; - -;; [Part of the GNU Emacs EDT Emulation.] - -;; This Emacs Lisp program can be used to create an Emacs Lisp file -;; that defines the mapping of the user's keyboard to the LK-201 -;; keyboard function keys and keypad keys (around which EDT has been -;; designed). Please read the "Usage" AND "Known Problems" sections -;; below before attempting to run this program. (The design of this -;; file, edt-mapper.el, was heavily influenced by tpu-mapper.el.) - -;; Version 4.0 contains the following enhancements: - -;; 1. If you access a workstation using an X Server, note that the -;; initialization file generated by edt-mapper.el will now -;; contain the name of the X Server vendor. This is a -;; convenience for those who have access to their Unix account -;; from more than one type of X Server. Since different X -;; Servers typically require different EDT emulation -;; initialization files, edt-mapper.el will now generate these -;; different initialization files and save them with different -;; names. - -;; 2. Also, edt-mapper.el is now capable of binding an ASCII key -;; sequence, providing the ASCII key sequence prefix is already -;; known by Emacs to be a prefix. As a result, some -;; terminal/keyboard/window system configurations, which don't -;; have a complete set of sensible function key map bindings, can -;; still be configured for EDT Emulation. - - -;; Usage: - -;; Simply load this file into Emacs and run the function edt-mapper, -;; using the following command. - -;; emacs -q -l edt-mapper -f edt-mapper - -;; The "-q" option prevents loading of your init file (commands -;; therein might confuse this program). - -;; An instruction screen showing the typical LK-201 terminal -;; functions keys will be displayed, and you will be prompted to -;; press the keys on your keyboard which you want to emulate the -;; corresponding LK-201 keys. - -;; Finally, you will be prompted for the name of the file to store -;; the key definitions. If you chose the default, it will be found -;; and loaded automatically when the EDT emulation is started. If -;; you specify a different file name, you will need to set the -;; variable "edt-keys-file" before starting the EDT emulation. -;; Here's how you might go about doing that in your init file: - -;; (setq edt-keys-file (expand-file-name "~/.my-emacs-keys")) - - -;; Known Problems: - -;; Sometimes, edt-mapper will ignore a key you press, and just -;; continue to prompt for the same key. This can happen when your -;; window manager sucks up the key and doesn't pass it on to Emacs, -;; or it could be an Emacs bug. Either way, there's nothing that -;; edt-mapper can do about it. You must press RETURN, to skip the -;; current key and continue. Later, you and/or your local Emacs guru -;; can try to figure out why the key is being ignored. - -;;; History: -;; - -;; Version 4.0 2000 Added 2 New Features - -;;; Code: - -;;; -;;; Determine Window System, and X Server Vendor (if appropriate). -;;; -(define-obsolete-variable-alias 'edt-window-system 'window-system "27.1") - -(defconst edt-xserver (when (eq window-system 'x) - (declare-function x-server-vendor "xfns.c" - (&optional terminal)) - ;; The Cygwin window manager has a `/' in its - ;; name, which breaks the generated file name of - ;; the custom key map file. Replace `/' with a - ;; `-' to work around that. - (replace-regexp-in-string "[ /]" "-" - (x-server-vendor))) - "Indicates X server vendor name, if applicable.") - - -;;; -;;; Key variables -;;; - -;; FIXME some/all of these should be let-bound, not global. -(defvar edt-key nil) -(defvar edt-enter nil) -(defvar edt-return nil) -(defvar edt-key-seq nil) -(defvar edt-enter-seq nil) -(defvar edt-return-seq nil) -(defvar edt-term nil) - -;; To silence the byte-compiler -(defvar EDT-key-name) -(defvar edt-save-function-key-map) - -;;; -;;; Key mapping functions -;;; -(defun edt-map-key (ident descrip) - (interactive) - (setq edt-key (read-key-sequence (format "Press %s%s: " ident descrip))) - (cond ((not (equal edt-key edt-return)) - (set-buffer "Keys") - (insert (if (vectorp edt-key) - (format " (\"%s\" . %s)\n" ident edt-key) - (format " (\"%s\" . \"%s\")\n" ident edt-key))) - (set-buffer "Directions")) - ;; bogosity to get next prompt to come up, if the user hits ! - ;; check periodically to see if this is still needed... - (t - (set-buffer "Keys") - (insert (format " (\"%s\" . \"\" )\n" ident)) - (set-buffer "Directions"))) - edt-key) - -(defun edt-mapper () - (if noninteractive - (user-error "edt-mapper cannot be loaded in batch mode")) - ;; Determine Terminal Type (if appropriate). - (if (and window-system (not (eq window-system 'tty))) - (setq edt-term nil) - (setq edt-term (getenv "TERM"))) - ;; - ;; Implements a workaround for a feature that was added to simple.el. - ;; - ;; Many function keys have no Emacs functions assigned to them by - ;; default. A subset of these are typically assigned functions in the - ;; EDT emulation. This includes all the keypad keys and a some others - ;; like Delete. - ;; - ;; Logic in simple.el maps some of these unassigned function keys to - ;; ordinary typing keys. Where this is the case, a call to - ;; read-key-sequence, below, does not return the name of the function - ;; key pressed by the user but, instead, it returns the name of the - ;; key to which it has been mapped. It needs to know the name of the - ;; key pressed by the user. As a workaround, we assign a function to - ;; each of the unassigned function keys of interest, here. These - ;; assignments override the mapping to other keys and are only - ;; temporary since, when edt-mapper is finished executing, it causes - ;; Emacs to exit. - ;; - (mapc - (lambda (function-key) - (if (not (lookup-key (current-global-map) function-key)) - (define-key (current-global-map) function-key #'forward-char))) - '([kp-0] [kp-1] [kp-2] [kp-3] [kp-4] - [kp-5] [kp-6] [kp-7] [kp-8] [kp-9] - [kp-space] - [kp-tab] - [kp-enter] - [kp-multiply] - [kp-add] - [kp-separator] - [kp-subtract] - [kp-decimal] - [kp-divide] - [kp-equal] - [backspace] - [delete] - [tab] - [linefeed] - [clear])) - ;; - ;; Make sure the window is big enough to display the instructions, - ;; except where window cannot be re-sized. - ;; - (if (and window-system (not (eq window-system 'tty))) - (set-frame-size (selected-frame) 80 36)) - ;; - ;; Create buffers - Directions and Keys - ;; - (if (not (get-buffer "Directions")) (generate-new-buffer "Directions")) - (if (not (get-buffer "Keys")) (generate-new-buffer "Keys")) - ;; - ;; Put header in the Keys buffer - ;; - (set-buffer "Keys") - (insert "\ -;; -;; Key definitions for the EDT emulation within GNU Emacs -;; - -\(defconst *EDT-keys* - '( - ") - - ;; - ;; Display directions - ;; - (switch-to-buffer "Directions") - (if (and window-system (not (eq window-system 'tty))) - (insert " - EDT MAPPER - - You will be asked to press keys to create a custom mapping (under a - Window Manager) of your keypad keys and function keys so that they can - emulate the LK-201 keypad and function keys or the subset of keys found - on a VT-100 series terminal keyboard. (The LK-201 keyboard is the - standard keyboard attached to VT-200 series terminals, and above.) - - Sometimes, edt-mapper will ignore a key you press, and just continue to - prompt for the same key. This can happen when your window manager sucks - up the key and doesn't pass it on to Emacs, or it could be an Emacs bug. - Either way, there's nothing that edt-mapper can do about it. You must - press RETURN, to skip the current key and continue. Later, you and/or - your local system guru can try to figure out why the key is being ignored. - - Start by pressing the RETURN key, and continue by pressing the keys - specified in the mini-buffer. If you want to entirely omit a key, - because your keyboard does not have a corresponding key, for example, - just press RETURN at the prompt. - -") - (insert " - EDT MAPPER - - You will be asked to press keys to create a custom mapping of your - keypad keys and function keys so that they can emulate the LK-201 - keypad and function keys or the subset of keys found on a VT-100 - series terminal keyboard. (The LK-201 keyboard is the standard - keyboard attached to VT-200 series terminals, and above.) - - If you are using a real LK-201 keyboard, you should map the keys - exactly as they are on the keyboard. - - Start by pressing the RETURN key, and continue by pressing the keys - specified in the mini-buffer. If you want to entirely omit a key, - because your keyboard does not have a corresponding key, for example, - just press RETURN at the prompt. - -")) - - (delete-other-windows) - - ;; - ;; Save for future reference. - ;; - ;; For Emacs running in a Window System, first hide bindings in - ;; function-key-map. - ;; - (if window-system - (progn - (setq edt-save-function-key-map function-key-map) - (setq function-key-map (make-sparse-keymap)))) - (setq edt-return (read-key-sequence "Hit carriage-return to continue ")) - - ;; - ;; Remove prefix-key bindings to F1 and F2 in global-map so they can be - ;; bound in the EDT Emulation mode. - ;; - (global-unset-key [f1]) - (global-unset-key [f2]) - - ;; - ;; Display Keypad Diagram and Begin Prompting for Keys - ;; - (set-buffer "Directions") - (delete-region (point-min) (point-max)) - (if (and window-system (not (eq window-system 'tty))) - (insert " - - PRESS THE KEY SPECIFIED IN THE MINIBUFFER BELOW. - - Here's a picture of the standard LK-201 keypad for reference: - - ________________________ _______________________________ - | HELP | DO | | F17 | F18 | F19 | F20 | - | | | | | | | | - |_______|________________| |_______|_______|_______|_______| - ________________________ _______________________________ - | FIND |INSERT |REMOVE | | PF1 | PF2 | PF3 | PF4 | - | | | | | | | | | - |_______|________|_______| |_______|_______|_______|_______| - |SELECT |PREVIOUS|NEXT | | KP7 | KP8 | KP9 | KP- | - | | | | | | | | | - |_______|________|_______| |_______|_______|_______|_______| - | UP | | KP4 | KP5 | KP6 | KP, | - | | | | | | | - _______|________|_______ |_______|_______|_______|_______| - | LEFT | DOWN | RIGHT | | KP1 | KP2 | KP3 | | - | | | | | | | | | - |_______|________|_______| |_______|_______|_______| KPE | - | KP0 | KPP | | - | | | | - |_______________|_______|_______| - - REMEMBER: JUST PRESS RETURN TO SKIP MAPPING A KEY. - -") - (progn - (insert " - GENERATING A CUSTOM CONFIGURATION FILE FOR TERMINAL TYPE: ") - (insert (format "%s." edt-term)) - (insert " - - PRESS THE KEY SPECIFIED IN THE MINIBUFFER BELOW. - - ________________________ _______________________________ - | HELP | DO | | F17 | F18 | F19 | F20 | - |_______|________________| |_______|_______|_______|_______| - ________________________ _______________________________ - | FIND |INSERT |REMOVE | | PF1 | PF2 | PF3 | PF4 | - |_______|________|_______| |_______|_______|_______|_______| - |SELECT |PREVIOUS| NEXT | | KP7 | KP8 | KP9 | KP- | - |_______|________|_______| |_______|_______|_______|_______| - | UP | | KP4 | KP5 | KP6 | KP, | - _______|________|_______ |_______|_______|_______|_______| - | LEFT | DOWN | RIGHT | | KP1 | KP2 | KP3 | | - |_______|________|_______| |_______|_______|_______| KPE | - | KP0 | KPP | | - |_______________|_______|_______| - - REMEMBER: JUST PRESS RETURN TO SKIP MAPPING A KEY."))) - - - - (set-buffer "Keys") - (insert " -;; -;; Arrows -;; -") - (set-buffer "Directions") - - (edt-map-key "UP" " - The Up Arrow Key") - (edt-map-key "DOWN" " - The Down Arrow Key") - (edt-map-key "LEFT" " - The Left Arrow Key") - (edt-map-key "RIGHT" " - The Right Arrow Key") - - - (set-buffer "Keys") - (insert " -;; -;; PF keys -;; -") - (set-buffer "Directions") - - (edt-map-key "PF1" " - The PF1 (GOLD) Key") - (edt-map-key "PF2" " - The Keypad PF2 Key") - (edt-map-key "PF3" " - The Keypad PF3 Key") - (edt-map-key "PF4" " - The Keypad PF4 Key") - - (set-buffer "Keys") - (insert " -;; -;; KP0-9 KP- KP, KPP and KPE -;; -") - (set-buffer "Directions") - - (edt-map-key "KP0" " - The Keypad 0 Key") - (edt-map-key "KP1" " - The Keypad 1 Key") - (edt-map-key "KP2" " - The Keypad 2 Key") - (edt-map-key "KP3" " - The Keypad 3 Key") - (edt-map-key "KP4" " - The Keypad 4 Key") - (edt-map-key "KP5" " - The Keypad 5 Key") - (edt-map-key "KP6" " - The Keypad 6 Key") - (edt-map-key "KP7" " - The Keypad 7 Key") - (edt-map-key "KP8" " - The Keypad 8 Key") - (edt-map-key "KP9" " - The Keypad 9 Key") - (edt-map-key "KP-" " - The Keypad - Key") - (edt-map-key "KP," " - The Keypad , Key") - (edt-map-key "KPP" " - The Keypad . Key") - (edt-map-key "KPE" " - The Keypad Enter Key") - ;; Save the enter key - (setq edt-enter edt-key) - (setq edt-enter-seq edt-key-seq) - - - (set-buffer "Keys") - (insert " -;; -;; Editing keypad (FIND, INSERT, REMOVE) -;; (SELECT, PREVIOUS, NEXT) -;; -") - (set-buffer "Directions") - - (edt-map-key "FIND" " - The Find key on the editing keypad") - (edt-map-key "INSERT" " - The Insert key on the editing keypad") - (edt-map-key "REMOVE" " - The Remove key on the editing keypad") - (edt-map-key "SELECT" " - The Select key on the editing keypad") - (edt-map-key "PREVIOUS" " - The Prev Scr key on the editing keypad") - (edt-map-key "NEXT" " - The Next Scr key on the editing keypad") - - (set-buffer "Keys") - (insert " -;; -;; F1-14 Help Do F17-F20 -;; -") - (set-buffer "Directions") - - (edt-map-key "F1" " - F1 Function Key") - (edt-map-key "F2" " - F2 Function Key") - (edt-map-key "F3" " - F3 Function Key") - (edt-map-key "F4" " - F4 Function Key") - (edt-map-key "F5" " - F5 Function Key") - (edt-map-key "F6" " - F6 Function Key") - (edt-map-key "F7" " - F7 Function Key") - (edt-map-key "F8" " - F8 Function Key") - (edt-map-key "F9" " - F9 Function Key") - (edt-map-key "F10" " - F10 Function Key") - (edt-map-key "F11" " - F11 Function Key") - (edt-map-key "F12" " - F12 Function Key") - (edt-map-key "F13" " - F13 Function Key") - (edt-map-key "F14" " - F14 Function Key") - (edt-map-key "HELP" " - HELP Function Key") - (edt-map-key "DO" " - DO Function Key") - (edt-map-key "F17" " - F17 Function Key") - (edt-map-key "F18" " - F18 Function Key") - (edt-map-key "F19" " - F19 Function Key") - (edt-map-key "F20" " - F20 Function Key") - - (set-buffer "Directions") - (delete-region (point-min) (point-max)) - (insert " - ADDITIONAL FUNCTION KEYS - - Your keyboard may have additional function keys which do not correspond - to any LK-201 keys. The EDT Emulation can be configured to recognize - those keys, since you may wish to add your own key bindings to those keys. - - For example, suppose your keyboard has a keycap marked \"Line Del\" and - you wish to add it to the list of keys which can be customized by the EDT - Emulation. First, assign a unique single-word name to the key for use by - the EDT Emulation, for example, \"linedel\". Then, at the \"EDT Key - Name:\" prompt, enter \"linedel\", followed by a press of the RETURN key. - Finally, when prompted, press the \"Line Del\" key. You now will be able - to bind functions to \"linedel\" and \"Gold-linedel\" in edt-user.el in - just the same way you can customize bindings of the LK-201 function and - keypad keys. - - When you are done, just press RETURN at the \"EDT Key Name:\" prompt. -") - (switch-to-buffer "Directions") - ;; - ;; Add support for extras keys - ;; - (set-buffer "Keys") - (insert "\ -;; -;; Extra Keys -;; -") - ;; - ;; Restore function-key-map. - ;; - (if window-system - (setq function-key-map edt-save-function-key-map)) - (setq EDT-key-name "") - (while (not - (string-equal (setq EDT-key-name (read-string "EDT Key Name: ")) "")) - (edt-map-key EDT-key-name "")) - - ;; - ;; No more keys to add, so wrap up. - ;; - (set-buffer "Keys") - (insert "\ - ) - ) -") - - ;; - ;; Save the key mapping program - ;; - ;; - ;; Save the key mapping file - ;; - (let ((file (concat - "~/.edt-gnu" - (if edt-term (concat "-" edt-term)) - (if edt-xserver (concat "-" edt-xserver)) - (if window-system (concat "-" (upcase (symbol-name window-system)))) - "-keys"))) - (set-visited-file-name - (read-file-name (format-prompt "Save key mapping to file" file) - nil file))) - (save-buffer) - - (message "That's it! Press any key to exit") - (sit-for 600) - (kill-emacs t)) - -;;; edt-mapper.el ends here diff --git a/lisp/emulation/edt-pc.el b/lisp/emulation/edt-pc.el deleted file mode 100644 index 33179f84d0b..00000000000 --- a/lisp/emulation/edt-pc.el +++ /dev/null @@ -1,89 +0,0 @@ -;;; edt-pc.el --- enhanced EDT keypad mode emulation for PC 101 keyboards -*- lexical-binding: t -*- - -;; Copyright (C) 1986, 1994-1995, 2001-2024 Free Software Foundation, -;; Inc. - -;; Author: Kevin Gallagher -;; Keywords: emulations -;; Package: edt - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; See Info node `edt' for more details. - -;; ==================================================================== - -;;;; -;;;; KEY TRANSLATIONS -;;;; - -;; Associate EDT keynames with Emacs terminal function vector names. -;; -;; To emulate the DEC LK-201 keypad keys on the PC 101 keyboard, -;; NumLock must be ON. -;; -;; The PC keypad keys are mapped to the corresponding DEC LK-201 -;; keypad keys according to the corresponding physical position on -;; the keyboard. Thus, the physical position of the PC keypad key -;; determines its function, not the PC keycap name. -;; -;; There are two LK-201 keypad keys needing special handling: PF1 and -;; the keypad comma key. -;; -;; PF1: -;; Most PC software does not see a press of the NumLock key. A TSR -;; program distributed with MS-Kermit to support its VT-100 emulation -;; solves this problem. The TSR, called GOLD, causes a press of the -;; keypad NumLock key to look as if the PC F1 key were pressed. So -;; the PC F1 key is mapped here to behave as the PF1 (GOLD) key. -;; Then with GOLD loaded, the NumLock key will behave as the GOLD key. -;; -;; By the way, with GOLD loaded, you can still toggle numlock on/off. -;; GOLD binds this to Shift-NumLock. -;; -;; Keypad Comma: -;; There is no physical PC keypad key to correspond to the LK-201 -;; keypad comma key. So, the EDT Emulation is configured below to -;; ignore attempts to bind functions to the keypad comma key. -;; -;; Finally, F2 through F12 are also available for making key bindings -;; in the EDT Emulation on the PC. F1 is reserved for the GOLD key, -;; so don't attempt to bind anything to it. Also, F13, F14, HELP, DO, -;; and F17 through F20 do not exist on the PC, so the EDT emulation is -;; configured below to ignore attempts to bind functions to those keys. -;; - -;;; Code: - -(defconst *EDT-keys* - '(("KP0" . [kp-0]) ("KP1" . [kp-1]) ("KP2" . [kp-2]) ("KP3" . [kp-3]) - ("KP4" . [kp-4]) ("KP5" . [kp-5]) ("KP6" . [kp-6]) ("KP7" . [kp-7]) - ("KP8" . [kp-8]) ("KP9" . [kp-9]) ("KP," . "" ) - ("KP-" . [kp-add]) ("KPP" . [kp-decimal]) ("KPE" . [kp-enter]) - ("PF1" . [f1]) ("PF2" . [kp-divide]) ("PF3" . [kp-multiply]) - ("PF4" . [kp-subtract]) - ("UP" . [up]) ("DOWN" . [down]) ("RIGHT" . [right]) ("LEFT" . [left]) - ("FIND" . [insert]) ("INSERT" . [home]) ("REMOVE" . [prior]) - ("SELECT" . [delete]) ("PREVIOUS" . [end]) ("NEXT" . [next]) - ("F1" . "" ) ("F2" . [f2]) ("F3" . [f3]) ("F4" . [f4]) ("F5" . [f5]) - ("F6" . [f6]) ("F7" . [f7]) ("F8" . [f8]) ("F9" . [f9]) ("F10" . [f10]) - ("F11" . [f11]) ("F12" . [f12]) ("F13" . "" ) ("F14" . "" ) - ("HELP" . "" ) ("DO" . "" ) ("F17" . "" ) ("F18" . "" ) - ("F19" . "" ) ("F20" . "" ))) - -;;; edt-pc.el ends here diff --git a/lisp/emulation/edt-vt100.el b/lisp/emulation/edt-vt100.el deleted file mode 100644 index a34f6f2a19d..00000000000 --- a/lisp/emulation/edt-vt100.el +++ /dev/null @@ -1,50 +0,0 @@ -;;; edt-vt100.el --- enhanced EDT keypad mode emulation for VT series terminals -*- lexical-binding: t -*- - -;; Copyright (C) 1986, 1992-1993, 1995, 2002-2024 Free Software -;; Foundation, Inc. - -;; Author: Kevin Gallagher -;; Keywords: emulations -;; Package: edt - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; See Info node `edt' for more details. - -;; ==================================================================== - - -;;; Code: - -;; Get keyboard function key mapping to EDT keys. -(load "edt-lk201" nil t) - -;; The following functions are called by the EDT screen width commands defined -;; in edt.el. - -(declare-function vt100-wide-mode "../term/vt100" (&optional arg)) - -(defun edt-set-term-width-80 () - "Set terminal width to 80 columns." - (vt100-wide-mode -1)) - -(defun edt-set-term-width-132 () - "Set terminal width to 132 columns." - (vt100-wide-mode 1)) - -;;; edt-vt100.el ends here diff --git a/lisp/emulation/edt.el b/lisp/emulation/edt.el deleted file mode 100644 index 8853e2bf1fe..00000000000 --- a/lisp/emulation/edt.el +++ /dev/null @@ -1,2535 +0,0 @@ -;;; edt.el --- enhanced EDT keypad mode emulation for GNU Emacs -*- lexical-binding: t; -*- - -;; Copyright (C) 1986, 1992-1995, 2000-2024 Free Software Foundation, -;; Inc. - -;; Author: Kevin Gallagher -;; Keywords: emulations - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - - - -;;; Commentary: -;; - -;; This is Version 4.0 of the EDT Emulation for Emacs. -;; It comes with special functions which replicate nearly all of EDT's -;; keypad mode behavior. It sets up default keypad and function key -;; bindings which closely match those found in EDT. Support is -;; provided so that users may reconfigure most keypad and function key -;; bindings to their own liking. - -;; NOTE: Version 4.0 contains several enhancements. See the -;; Enhancement section below for the details. - -;; Getting Started: - -;; To start the EDT Emulation, first start Emacs and then enter -;; -;; M-x edt-emulation-on -;; -;; to begin the emulation. After initialization is complete, the -;; following message will appear below the status line informing you -;; that the emulation has been enabled: "Default EDT keymap active". - -;; You can have the EDT Emulation start up automatically, each time -;; you initiate a GNU Emacs session, by adding the following line to -;; your init file: -;; -;; (add-hook 'emacs-startup-hook 'edt-emulation-on) - -;; IMPORTANT: Be sure to read the Info node `edt' for more details. -;; It contains very helpful user information. - -;; The EDT emulation consists of the following files: -;; -;; edt.texi - User manual -;; edt-user.el - Sample Customization File (located in Emacs -;; distribution etc directory) -;; edt.el - EDT Emulation Functions and Default Configuration -;; edt-lk201.el - Built-in support for DEC LK-201 Keyboards -;; edt-vt100.el - Built-in support for DEC VT-100 (and above) terminals -;; edt-pc.el - Built-in support for PC 101 Keyboards under MS-DOS -;; edt-mapper.el - Create an EDT LK-201 Map File for Keyboards Without -;; Built-in Support - -;; Enhancements: - -;; Version 4.0 contains the following enhancements: - -;; 1. Scroll margins at the top and bottom of the window are now -;; supported. (The design was copied from tpu-extras.el.) By -;; default, this feature is enabled, with the top margin set to -;; 10% of the window and the bottom margin set to 15% of the -;; window. To change these settings, you can invoke the function -;; edt-set-scroll-margins in your init file. For example, the -;; following line -;; -;; (edt-set-scroll-margins "20%" "25%") -;; -;; sets the top margin to 20% of the window and the bottom margin -;; to 25% of the window. To disable this feature, set each -;; margin to 0%. You can also invoke edt-set-scroll-margins -;; interactively while EDT Emulation is active to change the -;; settings for that session. -;; -;; NOTE: Another way to set the scroll margins is to use the -;; Emacs customization feature to set the following two variables -;; directly: -;; -;; edt-top-scroll-margin and edt-bottom-scroll-margin -;; -;; Enter the Emacs `customize' command. First select the Editing -;; group and then select the Emulations group. Finally, select -;; the Edt group and follow the directions. -;; -;; 2. The SUBS command is now supported and bound to GOLD-Enter by -;; default. (This design was copied from tpu-edt.el.) Note, in -;; earlier versions of EDT Emulation, GOLD-Enter was assigned to -;; the Emacs function `query-replace'. The binding of -;; `query-replace' has been moved to GOLD-/. If you prefer to -;; restore `query-replace' to GOLD-Enter, then use an EDT user -;; customization file, edt-user.el, to do this. -;; See Info node `edt' for more details. - -;; 3. If you access a workstation using an X Server, observe that -;; the initialization file generated by edt-mapper.el will now -;; contain the name of the X Server vendor. This is a -;; convenience for those who have access to their Unix account -;; from more than one type of X Server. Since different X -;; Servers typically require different EDT emulation -;; initialization files, edt-mapper.el will now generate these -;; different initialization files and save them with different -;; names. Then, the correct initialization file for the -;; particular X server in use is loaded correctly automatically. - -;; 4. Also, edt-mapper.el is now capable of binding an ASCII key -;; sequence, providing the ASCII key sequence prefix is already -;; known by Emacs to be a prefix. As a result of providing this -;; support, some terminal/keyboard/window system configurations, -;; which don't have a complete set of sensible function key -;; bindings built into Emacs in `function-key-map', can still be -;; configured for use with EDT Emulation. (Note: In a few rare -;; circumstances this does not work properly. In particular, it -;; does not work if a subset of the leading ASCII characters in a -;; key sequence are recognized by Emacs as having an existing -;; binding. For example, if the keypad 7 (KP-7) key generates -;; the sequence \"Ow\" and \"O\" is already bound to a -;; function, pressing KP-7 when told to do so by edt-mapper.el -;; will result in edt-mapper.el incorrectly mapping \"O\" to -;; KP-7 and \"w\" to KP-8. If something like this happens to -;; you, it is probably a bug in the support for your keyboard -;; within Emacs OR a bug in the Unix termcap/terminfo support for -;; your terminal OR a bug in the terminal emulation software you -;; are using.) - -;; 5. The edt-quit function (bound to GOLD-q by default) has been -;; modified to warn the user when file-related buffer -;; modifications exist. It now cautions the user that those -;; modifications will be lost if the user quits without saving -;; those buffers. - - -;;; History: -;; -;; Version 4.0 2000 Added New Features and Fixed a Few Bugs -;; - - -;;; Code: - -;;; Electric Help functions are used for keypad help displays. A few -;;; picture functions are used in rectangular cut and paste commands. - -(require 'ehelp) -(require 'picture) - -;;;; -;;;; VARIABLES and CONSTANTS -;;;; - -(defgroup edt nil - "Emacs emulating EDT." - :prefix "edt-" - :group 'emulations) - -;; To silence the byte-compiler -(defvar *EDT-keys*) -(defvar edt-default-global-map) -(defvar edt-last-copied-word) -(defvar edt-learn-macro-count) -(defvar edt-orig-page-delimiter) -(defvar edt-orig-transient-mark-mode) -(defvar edt-rect-start-point) -(defvar edt-user-global-map) -(defvar rect-start-point) - -;;; -;;; User Configurable Variables -;;; - -(defcustom edt-keep-current-page-delimiter nil - "Emacs MUST be restarted for a change in value to take effect! -Non-nil leaves Emacs value of `page-delimiter' unchanged within EDT -Emulation. If set to nil (the default), the `page-delimiter' variable -is set to \"\\f\" when edt-emulation-on is first invoked. This -setting replicates EDT's page delimiter behavior. The original value -is restored when edt-emulation-off is called." - :type 'boolean) - -(defcustom edt-use-EDT-control-key-bindings nil - "Emacs MUST be restarted for a change in value to take effect! -Non-nil causes the control key bindings to be replaced with EDT -bindings. If set to nil (the default), EDT control key bindings are -not used and the current Emacs control key bindings are retained for -use within the EDT emulation." - :type 'boolean) - -(defcustom edt-word-entities '(?\t) - "Specifies the list of EDT word entity characters. -The default list, (?\\t), contains just the TAB character, which -emulates EDT. Characters are specified in the list using their -decimal ASCII values. A question mark, followed by the actual -character, can be used to indicate the numerical value of the -character, instead of the actual decimal value. So, ?A means the -numerical value for the letter A, ?/ means the numerical value for /, -etc. Several unprintable and special characters have special -representations, which you can also use: - - ?\\b specifies BS, C-h - ?\\t specifies TAB, C-i - ?\\n specifies LFD, C-j - ?\\v specifies VTAB, C-k - ?\\f specifies FF, C-l - ?\\r specifies CR, C-m - ?\\e specifies ESC, C-[ - ?\\\\ specifies \\ - -In EDT Emulation movement-by-word commands, each character in the list -will be treated as if it were a separate word." - :type '(repeat integer)) - -(defcustom edt-top-scroll-margin 10 - "Scroll margin at the top of the screen. -Interpreted as a percent of the current window size with a default -setting of 10%. If set to 0, top scroll margin is disabled." - :type 'integer) - -(defcustom edt-bottom-scroll-margin 15 - "Scroll margin at the bottom of the screen. -Interpreted as a percent of the current window size with a default -setting of 15%. If set to 0, bottom scroll margin is disabled." - :type 'integer) - -;;; -;;; Internal Variables -;;; - -(defvar edt-last-deleted-lines "" - "Last text deleted by the EDT emulation DEL L command.") - -(defvar edt-last-deleted-words "" - "Last text deleted by the EDT emulation DEL W command.") - -(defvar edt-last-deleted-chars "" - "Last text deleted by the EDT emulation DEL C command.") - -(defvar edt-find-last-text "" - "Last text found by the EDT emulation FIND command.") - -(defvar edt-match-beginning-mark (make-marker) - "Used internally by the EDT emulation SUBS command.") - -(defvar edt-match-end-mark (make-marker) - "Used internally by the EDT emulation SUBS command.") - -(defvar edt-last-replaced-key-definition nil - "Key definition replaced with `edt-define-key' or `edt-learn' command.") - -(defvar edt-direction-string "" - "String indicating current direction of movement.") - -(defvar edt-select-mode nil - "Non-nil means select mode is active.") - -(defvar edt-select-mode-current "" - "Text displayed in mode line to indicate the state of EDT select mode. -When select mode is inactive, it is set to an empty string.") - -(defconst edt-select-mode-string " Select" - "Used in mode line to indicate select mode is active.") - -(defconst edt-forward-string " ADVANCE" - "Direction string in mode line to indicate forward movement.") - -(defconst edt-backward-string " BACKUP" - "Direction string in mode line to indicate backward movement.") - -(defvar edt-default-map-active nil - "Non-nil indicates that default EDT emulation key bindings are active. -nil means user-defined custom bindings are active.") - -(defvar edt-user-map-configured nil - "Non-nil indicates that user custom EDT key bindings are configured. -This means that an edt-user.el file was found in the user's `load-path'.") - -(defvar edt-term nil - "Specifies the terminal type, if applicable.") - -;;; -;;; Emacs version identifiers - currently referenced by -;;; -;;; o edt-emulation-on o edt-load-keys -;;; -(defconst edt-xserver (when (eq window-system 'x) - (declare-function x-server-vendor "xfns.c" - (&optional terminal)) - ;; The Cygwin window manager has a `/' in its - ;; name, which breaks the generated file name of - ;; the custom key map file. Replace `/' with a - ;; `-' to work around that. - (replace-regexp-in-string "[ /]" "-" - (x-server-vendor))) - "Indicates X server vendor name, if applicable.") - -(defvar edt-keys-file nil - "User's custom keypad and function keys mappings to emulate LK-201 keyboard.") - -(defvar edt-last-copied-word nil - "Last word that the user copied.") - - -;;;; -;;;; EDT Emulation Commands -;;;; - -;; Almost all of EDT's keypad mode commands have equivalent Emacs -;; function counterparts. But many of these counterparts behave -;; somewhat differently in Emacs. -;; -;; So, the following Emacs functions emulate, where practical, the -;; exact behavior of the corresponding EDT keypad mode commands. In -;; a few cases, the emulation is not exact, but it should be close -;; enough for most EDT die-hards. -;; - -;;; -;;; PAGE -;;; -;; Emacs uses the regexp assigned to page-delimiter to determine what -;; marks a page break. This is normally "^\f", which causes the -;; edt-page command to ignore form feeds not located at the beginning -;; of a line. To emulate the EDT PAGE command exactly, -;; page-delimiter is set to "\f" when EDT emulation is turned on, and -;; restored to its original value when EDT emulation is turned off. -;; But this can be overridden if the EDT definition is not desired by -;; placing -;; -;; (setq edt-keep-current-page-delimiter t) -;; -;; in your init file. - -(defun edt-page-forward (num) - "Move forward to just after next page delimiter. -Argument NUM is the number of page delimiters to move." - (interactive "p") - (edt-check-prefix num) - (if (eobp) - (error "End of buffer") - (progn - (forward-page num) - (if (eobp) - (edt-line-to-bottom-of-window) - (edt-line-to-top-of-window))))) - -(defun edt-page-backward (num) - "Move backward to just after previous page delimiter. -Argument NUM is the number of page delimiters to move." - (interactive "p") - (edt-check-prefix num) - (if (bobp) - (error "Beginning of buffer") - (progn - (backward-page num) - (edt-line-to-top-of-window)))) - -(defun edt-page (num) - "Move in current direction to next page delimiter. -Argument NUM is the number of page delimiters to move." - (interactive "p") - (if (equal edt-direction-string edt-forward-string) - (edt-page-forward num) - (edt-page-backward num))) - -;;; -;;; SECT -;;; -;; EDT defaults a section size to be 16 lines of its one and only -;; 24-line window. That's two-thirds of the window at a time. The -;; EDT SECT commands moves the cursor, not the window. -;; -;; This emulation of EDT's SECT moves the cursor approximately -;; two-thirds of the current window at a time. - -(defun edt-sect-forward (num) - "Move cursor forward two-thirds of a window's number of lines. -Argument NUM is the number of sections to move." - (interactive "p") - (edt-check-prefix num) - (edt-line-forward (* (* (/ (- (window-height) 1) 3) 2) num))) - - -(defun edt-sect-backward (num) - "Move cursor backward two-thirds of a window. -Argument NUM is the number of sections to move." - (interactive "p") - (edt-check-prefix num) - (edt-line-backward (* (* (/ (- (window-height) 1) 3) 2) num))) - -(defun edt-sect (num) - "Move in current direction a full window. -Argument NUM is the number of sections to move." - (interactive "p") - (if (equal edt-direction-string edt-forward-string) - (edt-sect-forward num) - (edt-sect-backward num))) - -;;; -;;; BEGINNING OF LINE -;;; -;; EDT's beginning-of-line command is not affected by current -;; direction, for some unknown reason. - -(defun edt-beginning-of-line (num) - "Move backward to next beginning of line mark. -Argument NUM is the number of BOL marks to move." - (interactive "p") - (edt-check-prefix num) - (let ((beg (edt-current-line))) - (if (bolp) - (forward-line (* -1 num)) - (progn - (setq num (1- num)) - (forward-line (* -1 num)))) - (edt-top-check beg num))) - - -;;; -;;; EOL (End of Line) -;;; - -(defun edt-end-of-line-forward (num) - "Move forward to next end of line mark. -Argument NUM is the number of EOL marks to move." - (interactive "p") - (edt-check-prefix num) - (let ((beg (edt-current-line))) - (forward-char) - (end-of-line num) - (edt-bottom-check beg num))) - - -(defun edt-end-of-line-backward (num) - "Move backward to next end of line mark. -Argument NUM is the number of EOL marks to move." - (interactive "p") - (edt-check-prefix num) - (let ((beg (edt-current-line))) - (end-of-line (1- num)) - (edt-top-check beg num))) - - -(defun edt-end-of-line (num) - "Move in current direction to next end of line mark. -Argument NUM is the number of EOL marks to move." - (interactive "p") - (if (equal edt-direction-string edt-forward-string) - (edt-end-of-line-forward num) - (edt-end-of-line-backward num))) - -;;; -;;; WORD -;;; -;; This one is a tad messy. To emulate EDT's behavior everywhere in -;; the file (beginning of file, end of file, beginning of line, end -;; of line, etc.) it takes a bit of special handling. -;; -;; The variable edt-word-entities contains a list of characters which -;; are to be viewed as distinct words wherever they appear in the -;; buffer. This emulates the EDT line mode command SET ENTITY WORD. - - -(defun edt-one-word-forward () - "Move forward to first character of next word." - (interactive) - (if (eobp) - (error "End of buffer")) - (if (eolp) - (forward-char) - (progn - (if (memq (following-char) edt-word-entities) - (forward-char) - (while (and - (not (eolp)) - (not (eobp)) - (not (eq ?\ (char-syntax (following-char)))) - (not (memq (following-char) edt-word-entities))) - (forward-char))) - (while (and - (not (eolp)) - (not (eobp)) - (eq ?\ (char-syntax (following-char))) - (not (memq (following-char) edt-word-entities))) - (forward-char))))) - -(defun edt-one-word-backward () - "Move backward to first character of previous word." - (interactive) - (if (bobp) - (error "Beginning of buffer")) - (if (bolp) - (backward-char) - (progn - (backward-char) - (while (and - (not (bolp)) - (not (bobp)) - (eq ?\ (char-syntax (following-char))) - (not (memq (following-char) edt-word-entities))) - (backward-char)) - (if (not (memq (following-char) edt-word-entities)) - (while (and - (not (bolp)) - (not (bobp)) - (not (eq ?\ (char-syntax (preceding-char)))) - (not (memq (preceding-char) edt-word-entities))) - (backward-char)))))) - -(defun edt-word-forward (num) - "Move forward to first character of next word. -Argument NUM is the number of words to move." - (interactive "p") - (edt-check-prefix num) - (while (> num 0) - (edt-one-word-forward) - (setq num (1- num)))) - -(defun edt-word-backward (num) - "Move backward to first character of previous word. -Argument NUM is the number of words to move." - (interactive "p") - (edt-check-prefix num) - (while (> num 0) - (edt-one-word-backward) - (setq num (1- num)))) - -(defun edt-word (num) - "Move in current direction to first character of next word. -Argument NUM is the number of words to move." - (interactive "p") - (if (equal edt-direction-string edt-forward-string) - (edt-word-forward num) - (edt-word-backward num))) - -;;; -;;; CHAR -;;; - -(defun edt-character (num) - "Move in current direction to next character. -Argument NUM is the number of characters to move." - (interactive "p") - (edt-check-prefix num) - (if (equal edt-direction-string edt-forward-string) - (forward-char num) - (backward-char num))) - -;;; -;;; LINE -;;; -;; When direction is set to BACKUP, LINE behaves just like BEGINNING -;; OF LINE in EDT. So edt-line-backward is not really needed as a -;; separate function. - -(defun edt-line-backward (num) - "Move backward to next beginning of line mark. -Argument NUM is the number of BOL marks to move." - (interactive "p") - (edt-beginning-of-line num)) - -(defun edt-line-forward (num) - "Move forward to next beginning of line mark. -Argument NUM is the number of BOL marks to move." - (interactive "p") - (edt-check-prefix num) - (let ((beg (edt-current-line))) - (forward-line num) - (edt-bottom-check beg num))) - -(defun edt-line (num) - "Move in current direction to next beginning of line mark. -Argument NUM is the number of BOL marks to move." - (interactive "p") - (if (equal edt-direction-string edt-forward-string) - (edt-line-forward num) - (edt-line-backward num))) - -;;; -;;; UP and DOWN Arrows -;;; - -(defun edt-next-line (num) - "Move cursor down one line. -Argument NUM is the number of lines to move." - (interactive "p") - (edt-check-prefix num) - (let ((beg (edt-current-line))) - ;; We're deliberately using next-line instead of forward-line. - (with-no-warnings (next-line num)) - (edt-bottom-check beg num))) - -(defun edt-previous-line (num) - "Move cursor up one line. -Argument NUM is the number of lines to move." - (interactive "p") - (edt-check-prefix num) - (let ((beg (edt-current-line))) - ;; We're deliberately using previous-line instead of forward-line. - (with-no-warnings (previous-line num)) - (edt-top-check beg num))) - - -;;; -;;; TOP -;;; - -(defun edt-top () - "Move cursor to the beginning of buffer." - (interactive) - (goto-char (point-min))) - -;;; -;;; BOTTOM -;;; - -(defun edt-bottom () - "Move cursor to the end of buffer." - (interactive) - (goto-char (point-max)) - (edt-line-to-bottom-of-window)) - -(defmacro edt-with-position (&rest body) - "Execute BODY with some position-related variables bound." - `(let* ((beg (edt-current-line)) - (height (window-height)) - (top-percent - (if (zerop edt-top-scroll-margin) 10 edt-top-scroll-margin)) - (bottom-percent - (if (zerop edt-bottom-scroll-margin) 15 edt-bottom-scroll-margin)) - (top-margin (/ (* height top-percent) 100)) - (bottom-up-margin (1+ (/ (* height bottom-percent) 100))) - (bottom-margin (max beg (- height bottom-up-margin 1))) - (top (save-excursion (move-to-window-line top-margin) (point))) - (bottom (save-excursion (move-to-window-line bottom-margin) (point))) - (far (save-excursion - (goto-char bottom) - (line-beginning-position (1- height))))) - (ignore top far) - ,@body)) - -;;; -;;; FIND -;;; - -(defun edt-find-forward (&optional find) - "Find first occurrence of a string in forward direction and save it. -Optional argument FIND is t is this function is called from `edt-find'." - (interactive) - (or find - (setq edt-find-last-text (read-string "Search forward: "))) - (edt-with-position - (when (search-forward edt-find-last-text) ; FIXME noerror? - (search-backward edt-find-last-text) - (edt-set-match) - (if (> (point) far) - (let ((left (save-excursion (forward-line height)))) - (recenter (if (zerop left) - top-margin - (- left bottom-up-margin)))) - (and (> (point) bottom) (recenter bottom-margin)))))) - -(defun edt-find-backward (&optional find) - "Find first occurrence of a string in the backward direction and save it. -Optional argument FIND is t if this function is called from `edt-find'." - (interactive) - (or find - (setq edt-find-last-text (read-string "Search backward: "))) - (edt-with-position - (if (search-backward edt-find-last-text) - (edt-set-match)) - (and (< (point) top) (recenter (min beg top-margin))))) - -(defun edt-find () - "Find first occurrence of string in current direction and save it." - (interactive) - (setq edt-find-last-text (read-string "Search: ")) - (if (equal edt-direction-string edt-forward-string) - (edt-find-forward t) - (edt-find-backward t))) - - -;;; -;;; FNDNXT -;;; - -(defun edt-find-next-forward () - "Find next occurrence of a string in forward direction." - (interactive) - (edt-with-position - (forward-char 1) - (if (search-forward edt-find-last-text nil t) - (progn - (search-backward edt-find-last-text) - (edt-set-match) - (if (> (point) far) - (let ((left (save-excursion (forward-line height)))) - (recenter (if (zerop left) top-margin - (- left bottom-up-margin)))) - (and (> (point) bottom) (recenter bottom-margin)))) - (backward-char 1) - (error "Search failed: \"%s\"" edt-find-last-text)))) - -(defun edt-find-next-backward () - "Find next occurrence of a string in backward direction." - (interactive) - (edt-with-position - (if (not (search-backward edt-find-last-text nil t)) - (error "Search failed: \"%s\"" edt-find-last-text) - (edt-set-match) - (and (< (point) top) (recenter (min beg top-margin)))))) - -(defun edt-find-next () - "Find next occurrence of a string in current direction." - (interactive) - (if (equal edt-direction-string edt-forward-string) - (edt-find-next-forward) - (edt-find-next-backward))) - -;;; -;;; APPEND -;;; - -(defun edt-append () - "Append this kill region to last killed region." - (interactive "*") - (edt-check-selection) - (append-next-kill) - (kill-region (mark) (point)) - (message "Selected text APPENDED to kill ring")) - -;;; -;;; DEL L -;;; - -(defun edt-delete-line (num) - "Delete from cursor up to and including the end of line mark. -Argument NUM is the number of lines to delete." - (interactive "*p") - (edt-check-prefix num) - (let ((beg (point))) - (forward-line num) - (if (not (eq (preceding-char) ?\n)) - (insert "\n")) - (setq edt-last-deleted-lines - (buffer-substring beg (point))) - (delete-region beg (point)))) - -;;; -;;; DEL EOL -;;; - -(defun edt-delete-to-end-of-line (num) - "Delete from cursor up to but excluding the end of line mark. -Argument NUM is the number of lines to delete." - (interactive "*p") - (edt-check-prefix num) - (let ((beg (point))) - (forward-char 1) - (end-of-line num) - (setq edt-last-deleted-lines - (buffer-substring beg (point))) - (delete-region beg (point)))) - -;;; -;;; SELECT -;;; - -(defun edt-select-mode (arg) - "Turn EDT select mode off if ARG is nil; otherwise, turn EDT select mode on. -In select mode, selected text is highlighted." - (if arg - (progn - (setq-local edt-select-mode 'edt-select-mode-current) - (setq rect-start-point (window-point))) - (progn - (kill-local-variable 'edt-select-mode))) - (force-mode-line-update)) - -(defun edt-select () - "Set mark at cursor and start text selection." - (interactive) - (set-mark-command nil)) - -(defun edt-reset () - "Cancel text selection." - (interactive) - (deactivate-mark)) - -;;; -;;; CUT -;;; - -(defun edt-cut () - "Deletes selected text but copies to kill ring." - (interactive "*") - (edt-check-selection) - (kill-region (mark) (point)) - (message "Selected text CUT to kill ring")) - -;;; -;;; DELETE TO BEGINNING OF LINE -;;; - -(defun edt-delete-to-beginning-of-line (num) - "Delete from cursor to beginning of line. -Argument NUM is the number of lines to delete." - (interactive "*p") - (edt-check-prefix num) - (let ((beg (point))) - (edt-beginning-of-line num) - (setq edt-last-deleted-lines - (buffer-substring (point) beg)) - (delete-region beg (point)))) - -;;; -;;; DEL W -;;; - -(defun edt-delete-word (num) - "Delete from cursor up to but excluding first character of next word. -Argument NUM is the number of words to delete." - (interactive "*p") - (edt-check-prefix num) - (let ((beg (point))) - (edt-word-forward num) - (setq edt-last-deleted-words (buffer-substring beg (point))) - (delete-region beg (point)))) - -;;; -;;; DELETE TO BEGINNING OF WORD -;;; - -(defun edt-delete-to-beginning-of-word (num) - "Delete from cursor to beginning of word. -Argument NUM is the number of words to delete." - (interactive "*p") - (edt-check-prefix num) - (let ((beg (point))) - (edt-word-backward num) - (setq edt-last-deleted-words (buffer-substring (point) beg)) - (delete-region beg (point)))) - -;;; -;;; DEL C -;;; - -(defun edt-delete-character (num) - "Delete character under cursor. -Argument NUM is the number of characters to delete." - (interactive "*p") - (edt-check-prefix num) - (setq edt-last-deleted-chars - (buffer-substring (point) (min (point-max) (+ (point) num)))) - (delete-region (point) (min (point-max) (+ (point) num)))) - -;;; -;;; DELETE CHAR -;;; - -(defun edt-delete-previous-character (num) - "Delete character in front of cursor. -Argument NUM is the number of characters to delete." - (interactive "*p") - (edt-check-prefix num) - (setq edt-last-deleted-chars - (buffer-substring (max (point-min) (- (point) num)) (point))) - (delete-region (max (point-min) (- (point) num)) (point))) - -;;; -;;; UND L -;;; - -(defun edt-undelete-line () - "Undelete previous deleted line(s)." - (interactive "*") - (point-to-register 1) - (insert edt-last-deleted-lines) - (register-to-point 1)) - -;;; -;;; UND W -;;; - -(defun edt-undelete-word () - "Undelete previous deleted word(s)." - (interactive "*") - (point-to-register 1) - (insert edt-last-deleted-words) - (register-to-point 1)) - -;;; -;;; UND C -;;; - -(defun edt-undelete-character () - "Undelete previous deleted character(s)." - (interactive "*") - (point-to-register 1) - (insert edt-last-deleted-chars) - (register-to-point 1)) - -;;; -;;; REPLACE -;;; - -(defun edt-replace () - "Replace marked section with last CUT (killed) text." - (interactive "*") - (if (edt-check-match) - (replace-match (car kill-ring-yank-pointer)) - (progn - (exchange-point-and-mark) - (let ((beg (point))) - (exchange-point-and-mark) - (delete-region beg (point))) - (yank)))) - -;;; -;;; SUBS -;;; - -(defun edt-substitute (num) - "Replace the selected region with the contents of the CUT buffer and. -Repeat the most recent FIND command. (The Emacs kill ring is used as -the CUT buffer.) -Argument NUM is the repeat count. A positive value indicates the of times -to repeat the substitution. A negative argument means replace all occurrences -of the search text." - (interactive "p") - (cond ((or edt-select-mode (edt-check-match)) - (while (and (not (= num 0)) (or edt-select-mode (edt-check-match))) - (edt-replace) - (edt-find-next) - (setq num (1- num)))) - (t - (error "No selection active")))) - -(defun edt-set-match nil - "Set markers at match beginning and end." - ;; Add one to beginning mark so it stays with the first character of - ;; the string even if characters are added just before the string. - (setq edt-match-beginning-mark (copy-marker (1+ (match-beginning 0)))) - (setq edt-match-end-mark (copy-marker (match-end 0)))) - -(defun edt-unset-match nil - "Unset match beginning and end markers." - (set-marker edt-match-beginning-mark nil) - (set-marker edt-match-end-mark nil)) - -(defun edt-match-beginning nil - "Return the location of the last match beginning." - (1- (marker-position edt-match-beginning-mark))) - -(defun edt-match-end nil - "Return the location of the last match end." - (marker-position edt-match-end-mark)) - -(defun edt-check-match nil - "Return t if point is between edt-match markers. -Otherwise sets the edt-match markers to nil and returns nil." - ;; make sure 1- marker is in this buffer - ;; 2- point is at or after beginning marker - ;; 3- point is before ending marker, or in the case of - ;; zero length regions (like bol, or eol) that the - ;; beginning, end, and point are equal. - (cond ((and - (equal (marker-buffer edt-match-beginning-mark) (current-buffer)) - (>= (point) (1- (marker-position edt-match-beginning-mark))) - (or - (< (point) (marker-position edt-match-end-mark)) - (and (= (1- (marker-position edt-match-beginning-mark)) - (marker-position edt-match-end-mark)) - (= (marker-position edt-match-end-mark) (point))))) t) - (t - (edt-unset-match) nil))) - -(defun edt-show-match-markers nil - "Show the values of the match markers." - (interactive) - (if (markerp edt-match-beginning-mark) - (let ((beg (marker-position edt-match-beginning-mark))) - (message "(%s, %s) in %s -- current %s in %s" - (if beg (1- beg) nil) - (marker-position edt-match-end-mark) - (marker-buffer edt-match-end-mark) - (point) (current-buffer))))) - - -;;; -;;; ADVANCE -;;; - -(defun edt-advance () - "Set movement direction forward. -Also, execute command specified if in Minibuffer." - (interactive) - (setq edt-direction-string edt-forward-string) - (force-mode-line-update) - (if (string-equal " *Minibuf" - (substring (buffer-name) 0 (min (length (buffer-name)) 9))) - (exit-minibuffer))) - - -;;; -;;; BACKUP -;;; - -(defun edt-backup () - "Set movement direction backward. -Also, execute command specified if in Minibuffer." - (interactive) - (setq edt-direction-string edt-backward-string) - (force-mode-line-update) - (if (string-equal " *Minibuf" - (substring (buffer-name) 0 (min (length (buffer-name)) 9))) - (exit-minibuffer))) - - -;;; -;;; CHNGCASE -;;; -;; This function is based upon Jeff Kowalski's case-flip function in his -;; tpu.el. - -(defun edt-change-case (num) - "Change the case of specified characters. -If text selection IS active, then characters between the cursor and mark are -changed. If text selection is NOT active, there are two cases. First, if the -current direction is ADVANCE, then the prefix number of character(s) under and -following cursor are changed. Second, if the current direction is BACKUP, then -the prefix number of character(s) before the cursor are changed. Accepts a -positive prefix for the number of characters to change, but the prefix is -ignored if text selection is active. -Argument NUM is the numbers of consecutive characters to change." - (interactive "*p") - (edt-check-prefix num) - (if edt-select-mode - (let ((end (max (mark) (point))) - (point-save (point))) - (goto-char (min (point) (mark))) - (while (not (eq (point) end)) - (funcall (if (<= ?a (following-char)) - 'upcase-region 'downcase-region) - (point) (1+ (point))) - (forward-char 1)) - (goto-char point-save)) - (progn - (if (string= edt-direction-string edt-backward-string) - (backward-char num)) - (while (> num 0) - (funcall (if (<= ?a (following-char)) - 'upcase-region 'downcase-region) - (point) (1+ (point))) - (forward-char 1) - (setq num (1- num)))))) - -;;; -;;; DEFINE KEY -;;; - -(defun edt-define-key () - "Assign an interactively-callable function to a specified key sequence. -The current key definition is saved in `edt-last-replaced-key-definition'. -Use `edt-restore-key' to restore last replaced key definition." - (interactive) - (let (edt-function - edt-key-definition) - (setq edt-key-definition - (read-key-sequence "Press the key to be defined: ")) - (if (string-equal "\C-m" edt-key-definition) - (message "Key not defined") - (progn - (setq edt-function (read-command "Enter command name: ")) - (if (string-equal "" edt-function) - (message "Key not defined") - (progn - (setq edt-last-replaced-key-definition - (lookup-key (current-global-map) edt-key-definition)) - (define-key (current-global-map) - edt-key-definition edt-function))))))) - -;;; -;;; FORM FEED INSERT -;;; - -(defun edt-form-feed-insert (num) - "Insert form feed character at cursor position. -Argument NUM is the number of form feeds to insert." - (interactive "*p") - (edt-check-prefix num) - (while (> num 0) - (insert ?\f) - (setq num (1- num)))) - -;;; -;;; TAB INSERT -;;; - -(defun edt-tab-insert (num) - "Insert tab character at cursor position. -Argument NUM is the number of tabs to insert." - (interactive "*p") - (edt-check-prefix num) - (while (> num 0) - (insert ?\t) - (setq num (1- num)))) - -;;; -;;; Check Prefix -;;; - -(defun edt-check-prefix (num) - "Indicate error if prefix is not positive. -Argument NUM is the prefix value tested." - (if (<= num 0) - (error "Prefix must be positive"))) - -;;; -;;; Check Selection -;;; - -(defun edt-check-selection () - "Indicate error if EDT selection is not active." - (if (not edt-select-mode) - (error "Selection NOT active"))) - -;;; -;;; Scroll Margins -;;; - -(defun edt-top-check (beg lines) - "Enforce scroll margin at the top of screen. -Argument BEG is the starting line number before cursor was moved. -Argument LINES is the number of lines the cursor moved toward the top." - (let ((margin (/ (* (window-height) edt-top-scroll-margin) 100))) - (cond ((< beg margin) (recenter beg)) - ((< (- beg lines) margin) (recenter margin))))) - -(defun edt-bottom-check (beg lines) - "Enforce scroll margin at the bottom of screen. -Argument BEG is the starting line number before cursor was moved. -Argument LINES is the number of lines the cursor moved toward the bottom." - (let* ((height (window-height)) - (margin (+ 1 (/ (* height edt-bottom-scroll-margin) 100))) - ;; subtract 1 from height because it includes mode line - (difference (- height margin 1))) - (cond ((> beg difference) (recenter beg)) - ((> (+ beg lines) difference) (recenter (- margin)))))) - -(defun edt-current-line nil - "Return the vertical position of point in the selected window. -Top line is 0. Counts each text line only once, even if it wraps." - (+ (count-lines (window-start) (point)) (if (= (current-column) 0) 1 0) -1)) - -;;;###autoload -(defun edt-set-scroll-margins (top bottom) - "Set scroll margins. -Argument TOP is the top margin in number of lines or percent of window. -Argument BOTTOM is the bottom margin in number of lines or percent of window." - (interactive - "sEnter top scroll margin (N lines or N%% or RETURN for current value): \ -\nsEnter bottom scroll margin (N lines or N%% or RETURN for current value): ") - ;; set top scroll margin - (or (string= top "") - (if (string= "%" (substring top -1)) - (setq edt-top-scroll-margin (string-to-number top)) - (setq edt-top-scroll-margin - (/ (1- (+ (* (string-to-number top) 100) (window-height))) - (window-height))))) - ;; set bottom scroll margin - (or (string= bottom "") - (if (string= "%" (substring bottom -1)) - (setq edt-bottom-scroll-margin (string-to-number bottom)) - (setq edt-bottom-scroll-margin - (/ (1- (+ (* (string-to-number bottom) 100) (window-height))) - (window-height))))) - ;; report scroll margin settings if running interactively - (and (called-interactively-p 'interactive) - (message "Scroll margins set. Top = %s%%, Bottom = %s%%" - edt-top-scroll-margin edt-bottom-scroll-margin))) - - -;;;; -;;;; ENHANCEMENTS AND ADDITIONS FOR EDT KEYPAD MODE -;;;; - -;;; -;; Several enhancements and additions to EDT keypad mode commands are -;; provided here. Some of these have been motivated by similar -;; TPU/EVE and EVE-Plus commands. Others are new. - -;;; -;;; CHANGE DIRECTION -;;; - -(defun edt-change-direction () - "Toggle movement direction." - (interactive) - (if (equal edt-direction-string edt-forward-string) - (edt-backup) - (edt-advance))) - -;;; -;;; TOGGLE SELECT -;;; - -(defun edt-toggle-select () - "Toggle to start (or cancel) text selection." - (interactive) - (if edt-select-mode - (edt-reset) - (edt-select))) - -;;; -;;; SENTENCE -;;; - -(defun edt-sentence-forward (num) - "Move forward to start of next sentence. -Argument NUM is the positive number of sentences to move." - (interactive "p") - (edt-check-prefix num) - (edt-with-position - (if (eobp) - (error "End of buffer") - (forward-sentence num) - (forward-word 1) - (backward-sentence)) - (if (> (point) far) - (let ((left (save-excursion (forward-line height)))) - (recenter (if (zerop left) top-margin (- left bottom-up-margin)))) - (and (> (point) bottom) (recenter bottom-margin))))) - -(defun edt-sentence-backward (num) - "Move backward to next sentence beginning. -Argument NUM is the positive number of sentences to move." - (interactive "p") - (edt-check-prefix num) - (edt-with-position - (if (eobp) - (error "End of buffer") - (backward-sentence num)) - (and (< (point) top) (recenter (min beg top-margin))))) - -(defun edt-sentence (num) - "Move in current direction to next sentence. -Argument NUM is the positive number of sentences to move." - (interactive "p") - (if (equal edt-direction-string edt-forward-string) - (edt-sentence-forward num) - (edt-sentence-backward num))) - -;;; -;;; PARAGRAPH -;;; - -(defun edt-paragraph-forward (num) - "Move forward to beginning of paragraph. -Argument NUM is the positive number of paragraphs to move." - (interactive "p") - (edt-check-prefix num) - (edt-with-position - (while (> num 0) - (forward-paragraph (+ num 1)) - (start-of-paragraph-text) - (if (eolp) - (forward-line 1)) - (setq num (1- num))) - (if (> (point) far) - (let ((left (save-excursion (forward-line height)))) - (recenter (if (zerop left) top-margin (- left bottom-up-margin)))) - (and (> (point) bottom) (recenter bottom-margin))))) - -(defun edt-paragraph-backward (num) - "Move backward to beginning of paragraph. -Argument NUM is the positive number of paragraphs to move." - (interactive "p") - (edt-check-prefix num) - (edt-with-position - (while (> num 0) - (start-of-paragraph-text) - (setq num (1- num))) - (and (< (point) top) (recenter (min beg top-margin))))) - -(defun edt-paragraph (num) - "Move in current direction to next paragraph. -Argument NUM is the positive number of paragraphs to move." - (interactive "p") - (if (equal edt-direction-string edt-forward-string) - (edt-paragraph-forward num) - (edt-paragraph-backward num))) - -;;; -;;; RESTORE KEY -;;; - -(defun edt-restore-key () - "Restore last replaced key definition. -Definition is stored in `edt-last-replaced-key-definition'." - (interactive) - (if edt-last-replaced-key-definition - (progn - (let (edt-key-definition) - (setq edt-key-definition - (read-key-sequence "Press the key to be restored: ")) - (if (string-equal "\C-m" edt-key-definition) - (message "Key not restored") - (progn - (define-key (current-global-map) - edt-key-definition edt-last-replaced-key-definition) - (message "Key definition for %s has been restored." - edt-key-definition))))) - (error "No replaced key definition to restore!"))) - -;;; -;;; WINDOW TOP -;;; - -(defun edt-window-top () - "Move the cursor to the top of the window." - (interactive) - (let ((start-column (current-column))) - (move-to-window-line 0) - (move-to-column start-column))) - -;;; -;;; WINDOW BOTTOM -;;; - -(defun edt-window-bottom () - "Move the cursor to the bottom of the window." - (interactive) - (let ((start-column (current-column))) - (move-to-window-line (- (window-height) 2)) - (move-to-column start-column))) - -;;; -;;; SCROLL WINDOW LINE -;;; - -(defun edt-scroll-window-forward-line () - "Move window forward one line leaving cursor at position in window." - (interactive) - (scroll-up 1)) - -(defun edt-scroll-window-backward-line () - "Move window backward one line leaving cursor at position in window." - (interactive) - (scroll-down 1)) - -(defun edt-scroll-line () - "Move window one line in current direction." - (interactive) - (if (equal edt-direction-string edt-forward-string) - (edt-scroll-window-forward-line) - (edt-scroll-window-backward-line))) - -;;; -;;; SCROLL WINDOW -;;; -;; Scroll a window (less one line) at a time. Leave cursor in center of -;; window. - -(defun edt-scroll-window-forward (num) - "Scroll forward one window in buffer, less one line. -Argument NUM is the positive number of windows to move." - (interactive "p") - (edt-check-prefix num) - (scroll-up (- (* (window-height) num) 2)) - (edt-line-forward (/ (- (window-height) 1) 2))) - -(defun edt-scroll-window-backward (num) - "Scroll backward one window in buffer, less one line. -Argument NUM is the positive number of windows to move." - (interactive "p") - (edt-check-prefix num) - (scroll-down (- (* (window-height) num) 2)) - (edt-line-backward (/ (- (window-height) 1) 2))) - -(defun edt-scroll-window (num) - "Scroll one window in buffer, less one line, in current direction. -Argument NUM is the positive number of windows to move." - (interactive "p") - (if (equal edt-direction-string edt-forward-string) - (edt-scroll-window-forward num) - (edt-scroll-window-backward num))) - -;;; -;;; LINE TO BOTTOM OF WINDOW -;;; - -(defun edt-line-to-bottom-of-window () - "Move the current line to the bottom of the window." - (interactive) - (recenter -1)) - -;;; -;;; LINE TO TOP OF WINDOW -;;; - -(defun edt-line-to-top-of-window () - "Move the current line to the top of the window." - (interactive) - (recenter 0)) - -;;; -;;; LINE TO MIDDLE OF WINDOW -;;; - -(defun edt-line-to-middle-of-window () - "Move window so line with cursor is in the middle of the window." - (interactive) - (recenter '(4))) - -;;; -;;; GOTO PERCENTAGE -;;; - -(defun edt-goto-percentage (num) - "Move to specified percentage in buffer from top of buffer. -Argument NUM is the percentage into the buffer to move." - (interactive "NGoto-percentage: ") - (if (or (> num 100) (< num 0)) - (error "Percentage %d out of range 0 < percent < 100" num) - (goto-char (/ (* (point-max) num) 100)))) - -;;; -;;; FILL REGION -;;; - -(defun edt-fill-region () - "Fill selected text." - (interactive "*") - (edt-check-selection) - (fill-region (point) (mark))) - -;;; -;;; INDENT OR FILL REGION -;;; - -(defun edt-indent-or-fill-region () - "Fill region in text modes, indent region in programming language modes." - (interactive "*") - (if (string= paragraph-start "$\\|\f") - (indent-region (point) (mark) nil) - (fill-region (point) (mark)))) - - -(declare-function c-mark-function "cc-cmds" ()) -;;; -;;; MARK SECTION WISELY -;;; - -(defun edt-mark-section-wisely () - "Mark the section in a manner consistent with the `major-mode'. -Uses `mark-defun' for Emacs-Lisp and Lisp, and for Fortran, -`c-mark-function' for C, -and `mark-paragraph' for other modes." - (interactive) - (if edt-select-mode - (progn - (edt-reset)) - (progn - (cond ((or (eq major-mode 'emacs-lisp-mode) - (eq major-mode 'fortran-mode) - (eq major-mode 'lisp-mode)) - (mark-defun) - (message "Lisp defun selected")) - ((eq major-mode 'c-mode) - (c-mark-function) - (message "C function selected")) - (t (mark-paragraph) - (message "Paragraph selected")))))) - -;;; -;;; COPY -;;; - -(defun edt-copy () - "Copy selected region to kill ring, but don't delete it!" - (interactive) - (edt-check-selection) - (copy-region-as-kill (mark) (point)) - (edt-reset) - (message "Selected text COPIED to kill ring")) - -;;; -;;; CUT or COPY -;;; - -(defun edt-cut-or-copy () - "Cuts (or copies) selected text to kill ring. -Cuts selected text if `buffer-read-only' is nil. -Copies selected text if `buffer-read-only' is t." - (interactive) - (if buffer-read-only - (edt-copy) - (edt-cut))) - -;;; -;;; DELETE ENTIRE LINE -;;; - -(defun edt-delete-entire-line () - "Delete entire line regardless of cursor position in the line." - (interactive "*") - (beginning-of-line) - (edt-delete-line 1)) - -;;; -;;; DUPLICATE LINE -;;; - -(defun edt-duplicate-line (num) - "Duplicate the line of text containing the cursor. -Argument NUM is the number of times to duplicate the line." - (interactive "*p") - (edt-check-prefix num) - (let ((old-column (current-column)) - (count num)) - (edt-delete-entire-line) - (edt-undelete-line) - (while (> count 0) - (edt-undelete-line) - (setq count (1- count))) - (edt-line-forward num) - (move-to-column old-column))) - -;;; -;;; DUPLICATE WORD -;;; - -(defun edt-duplicate-word() - "Duplicate word (or rest of word) found directly above cursor, if any." - (interactive "*") - (let ((start (point)) - (start-column (current-column))) - (forward-line -1) - (move-to-column start-column) - (if (and (not (equal start (point))) - (not (eolp))) - (progn - (if (and (equal ?\t (preceding-char)) - (< start-column (current-column))) - (backward-char)) - (let ((beg (point))) - (edt-one-word-forward) - (setq edt-last-copied-word (buffer-substring beg (point)))) - (forward-line) - (move-to-column start-column) - (insert edt-last-copied-word)) - (progn - (if (not (equal start (point))) - (forward-line)) - (move-to-column start-column) - (error "Nothing to duplicate!"))))) - -;;; -;;; KEY NOT ASSIGNED -;;; - -(defun edt-key-not-assigned () - "Displays message that key has not been assigned to a function." - (interactive) - (error "Key not assigned")) - -;;; -;;; TOGGLE CAPITALIZATION OF WORD -;;; - -(defun edt-toggle-capitalization-of-word () - "Toggle the capitalization of the current word and move forward to next." - (interactive "*") - (edt-one-word-forward) - (edt-one-word-backward) - (edt-change-case 1) - (edt-one-word-backward) - (edt-one-word-forward)) - -;;; -;;; ELIMINATE ALL TABS -;;; - -(defun edt-eliminate-all-tabs () - "Convert all tabs to spaces in the entire buffer." - (interactive "*") - (untabify (point-min) (point-max)) - (message "TABS converted to SPACES")) - -;;; -;;; DISPLAY THE TIME -;;; - -(defun edt-display-the-time () - "Display the current time." - (interactive) - (message "%s" (current-time-string))) - -;;; -;;; LEARN -;;; - -(defun edt-learn () - "Learn a sequence of key strokes to bind to a key." - (interactive) - (if (eq defining-kbd-macro t) - (edt-remember) - (start-kbd-macro nil))) - -;;; -;;; REMEMBER -;;; - -(defun edt-remember () - "Store the sequence of key strokes started by `edt-learn' to a key." - (interactive) - (if (eq defining-kbd-macro nil) - (error "Nothing to remember!") - (progn - (end-kbd-macro nil) - (let (edt-key-definition) - (setq edt-key-definition - (read-key-sequence "Enter key for binding: ")) - (if (string-equal "\C-m" edt-key-definition) - (message "Key sequence not remembered") - (progn - (setq edt-learn-macro-count (+ edt-learn-macro-count 1)) - (setq edt-last-replaced-key-definition - (lookup-key (current-global-map) - edt-key-definition)) - (define-key (current-global-map) edt-key-definition - (name-last-kbd-macro - (intern (concat "last-learned-sequence-" - (int-to-string edt-learn-macro-count))))))))))) - -;;; -;;; EXIT -;;; - -(defun edt-exit () - "Save current buffer, ask to save other buffers, and then exit Emacs." - (interactive) - (save-buffer) - (save-buffers-kill-emacs)) - -;;; -;;; QUIT -;;; - -(defun edt-quit () - "Quit Emacs without saving buffer modifications. -Warn user that modifications will be lost." - (interactive) - (let ((list (buffer-list)) - (working t)) - (while (and list working) - (let ((buffer (car list))) - (if (and (buffer-file-name buffer) (buffer-modified-p buffer)) - (if (edt-y-or-n-p - "Modifications will not be saved, continue quitting? ") - (kill-emacs) - (setq working nil))) - (setq list (cdr list)))) - (if working (kill-emacs)))) - -;;; -;;; SPLIT WINDOW -;;; - -(defun edt-split-window () - "Split current window and place cursor in the new window." - (interactive) - (split-window) - (other-window 1)) - -;;; -;;; COPY RECTANGLE -;;; - -(defun edt-copy-rectangle () - "Copy a rectangle of text between mark and cursor to register." - (interactive) - (edt-check-selection) - (copy-rectangle-to-register 3 (region-beginning) (region-end) nil) - (edt-reset) - (message "Selected rectangle COPIED to register")) - -;;; -;;; CUT RECTANGLE -;;; - -(defun edt-cut-rectangle-overstrike-mode () - "Cut a rectangle of text between mark and cursor to register. -Replace cut characters with spaces and moving cursor back to -upper left corner." - (interactive "*") - (edt-check-selection) - (setq edt-rect-start-point (region-beginning)) - (picture-clear-rectangle-to-register (region-beginning) (region-end) 3) - (set-window-point (get-buffer-window (window-buffer)) edt-rect-start-point) - (message "Selected rectangle CUT to register")) - -(defun edt-cut-rectangle-insert-mode () - "Cut a rectangle of text between mark and cursor to register. -Move cursor back to upper left corner." - (interactive "*") - (edt-check-selection) - (setq edt-rect-start-point (region-beginning)) - (picture-clear-rectangle-to-register (region-beginning) (region-end) 3 t) - (fixup-whitespace) - (set-window-point (get-buffer-window (window-buffer)) edt-rect-start-point) - (message "Selected rectangle CUT to register")) - -(defun edt-cut-rectangle () - "Cut a rectangular region of text to register. -If overwrite mode is active, cut text is replaced with whitespace." - (interactive "*") - (if overwrite-mode - (edt-cut-rectangle-overstrike-mode) - (edt-cut-rectangle-insert-mode))) - -;;; -;;; PASTE RECTANGLE -;;; - -(defun edt-paste-rectangle-overstrike-mode () - "Paste a rectangular region of text from register, replacing text at cursor." - (interactive "*") - (picture-yank-rectangle-from-register 3)) - -(defun edt-paste-rectangle-insert-mode () - "Paste previously deleted rectangular region, inserting text at cursor." - (interactive "*") - (picture-yank-rectangle-from-register 3 t)) - -(defun edt-paste-rectangle () - "Paste a rectangular region of text. -If overwrite mode is active, existing text is replace with text from register." - (interactive) - (if overwrite-mode - (edt-paste-rectangle-overstrike-mode) - (edt-paste-rectangle-insert-mode))) - -;;; -;;; DOWNCASE REGION -;;; - -(defun edt-lowercase () - "Change specified characters to lower case. -If text selection IS active, then characters between the cursor and -mark are changed. If text selection is NOT active, there are two -situations. If the current direction is ADVANCE, then the word under -the cursor is changed to lower case and the cursor is moved to rest at -the beginning of the next word. If the current direction is BACKUP, -the word prior to the word under the cursor is changed to lower case -and the cursor is left to rest at the beginning of that word." - (interactive "*") - (if edt-select-mode - (progn - (downcase-region (mark) (point))) - (progn - ;; Move to beginning of current word. - (if (and - (not (bobp)) - (not (eobp)) - (not (bolp)) - (not (eolp)) - (not (eq ?\ (char-syntax (preceding-char)))) - (not (memq (preceding-char) edt-word-entities)) - (not (memq (following-char) edt-word-entities))) - (edt-one-word-backward)) - (if (equal edt-direction-string edt-backward-string) - (edt-one-word-backward)) - (let ((beg (point))) - (edt-one-word-forward) - (downcase-region beg (point))) - (if (equal edt-direction-string edt-backward-string) - (edt-one-word-backward))))) - -;;; -;;; UPCASE REGION -;;; - -(defun edt-uppercase () - "Change specified characters to upper case. -If text selection IS active, then characters between the cursor and -mark are changed. If text selection is NOT active, there are two -situations. If the current direction is ADVANCE, then the word under -the cursor is changed to upper case and the cursor is moved to rest at -the beginning of the next word. If the current direction is BACKUP, -the word prior to the word under the cursor is changed to upper case -and the cursor is left to rest at the beginning of that word." - (interactive "*") - (if edt-select-mode - (progn - (upcase-region (mark) (point))) - (progn - ;; Move to beginning of current word. - (if (and - (not (bobp)) - (not (eobp)) - (not (bolp)) - (not (eolp)) - (not (eq ?\ (char-syntax (preceding-char)))) - (not (memq (preceding-char) edt-word-entities)) - (not (memq (following-char) edt-word-entities))) - (edt-one-word-backward)) - (if (equal edt-direction-string edt-backward-string) - (edt-one-word-backward)) - (let ((beg (point))) - (edt-one-word-forward) - (upcase-region beg (point))) - (if (equal edt-direction-string edt-backward-string) - (edt-one-word-backward))))) - -;;; -;;; Functions used in loading LK-201 key mapping file. -;;; -(defvar edt-last-answer nil - "Most recent response to `edt-y-or-n-p'.") - -(defun edt-y-or-n-p (prompt &optional not-yes) - "Prompt for a y or n answer with positive default. -Like Emacs `y-or-n-p', also accepts space as y and DEL as n. -Argument PROMPT is the prompt string. -Optional argument NOT-YES changes the default to negative." - (message "%s[%s]" prompt (if not-yes "n" "y")) - (let ((doit t)) - (while doit - (setq doit nil) - (let ((ans (read-char))) - (cond ((or (= ans ?y) (= ans ?Y) (= ans ?\ )) - (setq edt-last-answer t)) - ((or (= ans ?n) (= ans ?N) (= ans ?\C-?)) - (setq edt-last-answer nil)) - ((= ans ?\r) (setq edt-last-answer (not not-yes))) - (t - (setq doit t) (beep) - (message "Please answer y or n. %s[%s]" - prompt (if not-yes "n" "y"))))))) - edt-last-answer) - -;;; -;;; INITIALIZATION COMMANDS. -;;; - -(declare-function edt-mapper "edt-mapper" ()) - -;;; -;;; Function used to load LK-201 key mapping file generated by edt-mapper.el. -;;; -(defun edt-load-keys (file) - "Load the LK-201 key mapping FILE generated by edt-mapper.el. -If FILE is nil, which is the normal case, try to load a default file. -The default file names are based upon the window system and terminal -type. If a default file does not exist, ask user if one should be -created." - (interactive "fKey definition file: ") - (cond (file - (setq file (expand-file-name file))) - (edt-keys-file - (setq file (expand-file-name edt-keys-file))) - (t - (setq file - (expand-file-name - (concat - "~/.edt-gnu" - (if edt-term (concat "-" edt-term)) - (if edt-xserver (concat "-" edt-xserver)) - (if window-system - (concat "-" (upcase (symbol-name window-system)))) - "-keys"))))) - (cond ((file-readable-p file) - (load-file file)) - (t - (switch-to-buffer "*scratch*") - (erase-buffer) - (insert " - - Ack!! You're running the Enhanced EDT Emulation without loading an - EDT key mapping file. To create an EDT key mapping file, run the - edt-mapper program. It is safest to run it from an Emacs loaded - without any of your own customizations found in your init file, etc. - The reason for this is that some user customizations confuse edt-mapper. - You can do this by quitting Emacs and then invoking Emacs again as - follows: - - emacs -q -l edt-mapper -f edt-mapper - - [NOTE: If you do nothing out of the ordinary in your init file, and - the search for edt-mapper is successful, you can try running it now.] - - The library edt-mapper includes these same directions on how to - use it! Perhaps it's lying around here someplace. \n ") - (let ((path (locate-library - "edt-mapper" - nil (append (list default-directory) load-path)))) - (if path - (progn - (insert (format - "Ah yes, there it is, in \n\n %s \n\n" path)) - (if (edt-y-or-n-p "Do you want to run it now? ") - (progn - (load-file path) - (edt-mapper)) - (error "EDT Emulation not configured"))) - (insert (substitute-command-keys - "Nope, I can't seem to find it. :-(\n\n")) - (sit-for 20) - (error "EDT Emulation not configured")))))) - -;;; -;;; Turning the EDT Emulation on and off. -;;; - -;;;###autoload -(defun edt-emulation-on () - "Turn on EDT Emulation." - (interactive) - ;; If using pc window system (MS-DOS), set terminal type to pc. - ;; If not a window system, get terminal type. - (if (eq window-system 'pc) - (setq edt-term "pc") - (if (not window-system) - (setq edt-term (getenv "TERM")))) - ;; Look for a terminal configuration file for this terminal type. - ;; Otherwise, load the user's custom configuration file. - (if (or (not window-system) (memq window-system '(pc tty))) - (progn - ;; Load terminal-specific configuration file, if it exists for this - ;; terminal type. Note: All DEC VT series terminals are supported - ;; by the same terminal configuration file: edt-vt100.el. - (if (string-equal "vt" (substring edt-term 0 (min (length edt-term) 2))) - (setq edt-term "vt100")) - (let ((term edt-term) - hyphend) - (while (and term - (not (load (concat "edt-" term) t t))) - ;; Strip off last hyphen and what follows, then try again - (if (setq hyphend (string-match "[-_][^-_]+$" term)) - (setq term (substring term 0 hyphend)) - (setq term nil))) - ;; If no terminal-specific configuration file exists, load user's - ;; custom EDT terminal configuration file. - ;; If this is a pc running MS-DOS, then custom configuration files - ;; are not supported. So, if the file is missing, issue an error - ;; message. - (if (null term) - (if (equal edt-term "pc") - (error "Unable to find EDT terminal specific file edt-pc.el") - (edt-load-keys nil)) - (setq edt-term term)))) - (edt-load-keys nil)) - ;; Make highlighting of selected text work properly for EDT commands. - (setq edt-orig-transient-mark-mode - (default-value 'transient-mark-mode)) - (add-hook 'activate-mark-hook - (lambda () - (edt-select-mode t))) - (add-hook 'deactivate-mark-hook - (lambda () - (edt-select-mode nil))) - ;; Load user's EDT custom key bindings file, if it exists. - ;; Otherwise, use the default bindings. - (if (load "edt-user" t t) - (edt-user-emulation-setup) - (edt-default-emulation-setup))) - -(defun edt-emulation-off() - "Select original global key bindings, disabling EDT Emulation." - (interactive) - (use-global-map global-map) - (if (not edt-keep-current-page-delimiter) - (setq page-delimiter edt-orig-page-delimiter)) - (setq edt-direction-string "") - (setq edt-select-mode-current nil) - (edt-reset) - (force-mode-line-update t) - (setq-default transient-mark-mode edt-orig-transient-mark-mode) - (message "Original key bindings restored; EDT Emulation disabled")) - -(defun edt-default-menu-bar-update-buffers () - ;; Update edt-default-global-map with latest copy of - ;; `global-buffers-menu-map' each time `menu-bar-update-buffers' - ;; updates global-map. - (define-key edt-default-global-map [menu-bar buffer] - (cons "Buffers" global-buffers-menu-map))) - -(defun edt-user-menu-bar-update-buffers () - ;; We need to update edt-user-global-map with latest copy of - ;; `global-buffers-menu-map' each time `menu-bar-update-buffers' - ;; updates global-map. - (define-key edt-user-global-map [menu-bar buffer] - (cons "Buffers" global-buffers-menu-map))) - -(defun edt-default-emulation-setup (&optional user-setup) - "Setup emulation of DEC's EDT editor. -Optional argument USER-SETUP non-nil means called from function -`edt-user-emulation-setup'." - ;; Setup default EDT global map by copying global map bindings. - ;; This preserves ESC and C-x prefix bindings and other bindings we - ;; wish to retain in EDT emulation mode keymaps. It also permits - ;; customization of these bindings in the EDT global maps without - ;; disturbing the original bindings in global-map. - (fset 'edt-default-ESC-prefix (copy-keymap 'ESC-prefix)) - (setq edt-default-global-map (copy-keymap (current-global-map))) - (define-key edt-default-global-map "\e" 'edt-default-ESC-prefix) - (define-prefix-command 'edt-default-gold-map) - (edt-setup-default-bindings) - ;; If terminal has additional function keys, the terminal-specific - ;; initialization file can assign bindings to them via the optional - ;; function edt-setup-extra-default-bindings. - (if (fboundp 'edt-setup-extra-default-bindings) - (edt-setup-extra-default-bindings)) - ;; Variable needed by edt-learn. - (setq edt-learn-macro-count 0) - ;; Display EDT text selection active within the mode line - (or (assq 'edt-select-mode minor-mode-alist) - (setq minor-mode-alist - (cons '(edt-select-mode edt-select-mode) minor-mode-alist))) - ;; Display EDT direction of motion within the mode line - (or (assq 'edt-direction-string minor-mode-alist) - (setq minor-mode-alist - (cons - '(edt-direction-string edt-direction-string) minor-mode-alist))) - (if user-setup - (progn - (setq edt-user-map-configured t) - (fset 'edt-emulation-on (symbol-function 'edt-select-user-global-map))) - (progn - (fset 'edt-emulation-on (symbol-function 'edt-select-default-global-map)) - (edt-select-default-global-map))) - ;; Keep the menu bar Buffers menu up-to-date in edt-default-global-map. - (add-hook 'menu-bar-update-hook #'edt-default-menu-bar-update-buffers)) - -(defun edt-user-emulation-setup () - "Setup user custom emulation of DEC's EDT editor." - ;; Initialize EDT default bindings. - (edt-default-emulation-setup t) - ;; Setup user EDT global map by copying default EDT global map bindings. - (fset 'edt-user-ESC-prefix (copy-keymap 'edt-default-ESC-prefix)) - (setq edt-user-global-map (copy-keymap edt-default-global-map)) - (define-key edt-user-global-map "\e" 'edt-user-ESC-prefix) - ;; If terminal has additional function keys, the user's initialization - ;; file can assign bindings to them via the optional - ;; function edt-setup-extra-default-bindings. - (define-prefix-command 'edt-user-gold-map) - (fset 'edt-user-gold-map (copy-keymap 'edt-default-gold-map)) - ;; This is a function that the user can define for custom bindings. - ;; See Info node `edt' for more details, and sample edt-user.el file. - (if (fboundp 'edt-setup-user-bindings) - (edt-setup-user-bindings)) - (edt-select-user-global-map) - ;; Keep the menu bar Buffers menu up-to-date in edt-user-global-map. - (add-hook 'menu-bar-update-hook #'edt-user-menu-bar-update-buffers)) - -(defun edt-select-default-global-map() - "Select default EDT emulation key bindings." - (interactive) - (transient-mark-mode 1) - (use-global-map edt-default-global-map) - (if (not edt-keep-current-page-delimiter) - (progn - (setq edt-orig-page-delimiter page-delimiter) - (setq page-delimiter "\f"))) - (setq edt-default-map-active t) - (edt-advance) - (setq edt-select-mode-current 'edt-select-mode-string) - (edt-reset) - (message "Default EDT keymap active")) - -(defun edt-select-user-global-map() - "Select user EDT emulation custom key bindings." - (interactive) - (if edt-user-map-configured - (progn - (transient-mark-mode 1) - (use-global-map edt-user-global-map) - (if (not edt-keep-current-page-delimiter) - (progn - (setq edt-orig-page-delimiter page-delimiter) - (setq page-delimiter "\f"))) - (setq edt-default-map-active nil) - (edt-advance) - (setq edt-select-mode-current 'edt-select-mode-string) - (edt-reset) - (message "User EDT custom keymap active")) - (error "User EDT custom keymap NOT configured!"))) - -(defun edt-switch-global-maps () - "Toggle between default EDT keymap and user EDT keymap." - (interactive) - (if edt-default-map-active - (edt-select-user-global-map) - (edt-select-default-global-map))) - -;; -;; Functions used to set up DEFAULT bindings to EDT emulation functions. -;; - -(defun edt-bind-function-key-default (function-key binding gold-binding) - "Binds LK-201 function keys to default bindings in the EDT Emulator. -Argument FUNCTION-KEY is the name of the function key or keypad function key. -Argument BINDING is the Emacs function to be bound to . -Argument GOLD-BINDING is the Emacs function to be bound to GOLD ." - (let ((key (cdr (assoc function-key *EDT-keys*)))) - (if (and key (not (equal key ""))) - (progn - (define-key edt-default-global-map key binding) - (define-key 'edt-default-gold-map key gold-binding))))) - -(defun edt-bind-key-default (key binding) - "Bind key sequences to default bindings in the EDT Emulator. -Argument KEY is the name of a standard key or a function key. -Argument BINDING is the Emacs function to be bound to ." - (define-key edt-default-global-map key binding)) - -(defun edt-bind-gold-key-default (key gold-binding) - "Binds key sequences to default bindings in the EDT Emulator. -Argument KEY is the name of a standard key or a function key. -Argument GOLD-BINDING is the Emacs function to be bound to GOLD ." - (define-key 'edt-default-gold-map key gold-binding)) - -;; -;; Functions used to set up USER CUSTOM bindings to EDT emulation functions. -;; -(defun edt-bind-function-key (function-key binding gold-binding) - "Binds LK-201 function keys to custom bindings in the EDT Emulator. -Argument FUNCTION-KEY is the name of the function key or keypad function key. -Argument BINDING is the Emacs function to be bound to . -Argument GOLD-BINDING is the Emacs function to be bound to GOLD ." - (let ((key (cdr (assoc function-key *EDT-keys*)))) - (if (and key (not (equal key ""))) - (progn - (define-key edt-user-global-map key binding) - (define-key 'edt-user-gold-map key gold-binding))))) - -(defun edt-bind-key (key binding) - "Bind standard key sequences to custom bindings in the EDT Emulator. -Argument KEY is the name of a key. It can be a standard key or a function key. -Argument BINDING is the Emacs function to be bound to ." - (define-key edt-user-global-map key binding)) - -(define-obsolete-function-alias 'edt-bind-standard-key #'edt-bind-key "28.1") - -(defun edt-bind-gold-key (key gold-binding) - "Binds standard key sequences to custom bindings in the EDT Emulator. -Argument KEY is the name of a standard key or a function key. -Argument GOLD-BINDING is the Emacs function to be bound to GOLD ." - (define-key 'edt-user-gold-map key gold-binding)) - -(defun edt-setup-default-bindings () - "Assigns default EDT Emulation keyboard bindings." - - ;; Function Key Bindings: Regular and GOLD. - - ;; VT100/VT200/VT300 PF1 (GOLD), PF2, PF3, PF4 Keys - (edt-bind-function-key-default "PF1" - 'edt-default-gold-map 'edt-mark-section-wisely) - (edt-bind-function-key-default "PF2" - 'edt-electric-keypad-help 'describe-function) - (edt-bind-function-key-default "PF3" 'edt-find-next 'edt-find) - (edt-bind-function-key-default "PF4" 'edt-delete-line 'edt-undelete-line) - - ;; VT100/VT200/VT300 Arrow Keys - (edt-bind-function-key-default "UP" 'edt-previous-line 'edt-window-top) - (edt-bind-function-key-default "DOWN" 'edt-next-line 'edt-window-bottom) - (edt-bind-function-key-default "LEFT" 'backward-char 'edt-sentence-backward) - (edt-bind-function-key-default "RIGHT" 'forward-char 'edt-sentence-forward) - - ;; VT100/VT200/VT300 Keypad Keys - (edt-bind-function-key-default "KP0" 'edt-line 'open-line) - (edt-bind-function-key-default "KP1" 'edt-word 'edt-change-case) - (edt-bind-function-key-default "KP2" - 'edt-end-of-line 'edt-delete-to-end-of-line) - (edt-bind-function-key-default "KP3" 'edt-character 'quoted-insert) - (edt-bind-function-key-default "KP4" 'edt-advance 'edt-bottom) - (edt-bind-function-key-default "KP5" 'edt-backup 'edt-top) - (edt-bind-function-key-default "KP6" 'edt-cut 'yank) - (edt-bind-function-key-default "KP7" 'edt-page 'execute-extended-command) - (edt-bind-function-key-default "KP8" 'edt-sect 'edt-fill-region) - (edt-bind-function-key-default "KP9" 'edt-append 'edt-replace) - (edt-bind-function-key-default "KP-" 'edt-delete-word 'edt-undelete-word) - (edt-bind-function-key-default "KP," - 'edt-delete-character 'edt-undelete-character) - (edt-bind-function-key-default "KPP" 'edt-select 'edt-reset) - (edt-bind-function-key-default "KPE" 'other-window 'edt-substitute) - - ;; VT200/VT300 Function Keys - ;; (F1 through F5, on the VT220, are not programmable, so we skip - ;; making default bindings to those keys. - (edt-bind-function-key-default "FIND" 'edt-find-next 'edt-find) - (edt-bind-function-key-default "INSERT" 'yank 'edt-key-not-assigned) - (edt-bind-function-key-default "REMOVE" 'edt-cut 'edt-copy) - (edt-bind-function-key-default "SELECT" - 'edt-toggle-select 'edt-key-not-assigned) - (edt-bind-function-key-default "NEXT" - 'edt-sect-forward 'edt-key-not-assigned) - (edt-bind-function-key-default "PREVIOUS" - 'edt-sect-backward 'edt-key-not-assigned) - (edt-bind-function-key-default "F6" - 'edt-key-not-assigned 'edt-key-not-assigned) - (edt-bind-function-key-default "F7" - 'edt-copy-rectangle 'edt-key-not-assigned) - (edt-bind-function-key-default "F8" - 'edt-cut-rectangle-overstrike-mode 'edt-paste-rectangle-overstrike-mode) - (edt-bind-function-key-default "F9" - 'edt-cut-rectangle-insert-mode 'edt-paste-rectangle-insert-mode) - (edt-bind-function-key-default "F10" 'edt-cut-rectangle 'edt-paste-rectangle) - ;; Under X, the F11 key can be bound. If using a VT-200 or higher terminal, - ;; the default emacs terminal support causes the VT F11 key to seem as if it - ;; is an ESC key when in emacs. - (edt-bind-function-key-default "F11" - 'edt-key-not-assigned 'edt-key-not-assigned) - (edt-bind-function-key-default "F12" - 'edt-beginning-of-line 'delete-other-windows) ;BS - (edt-bind-function-key-default "F13" - 'edt-delete-to-beginning-of-word 'edt-key-not-assigned) ;LF - (edt-bind-function-key-default "F14" - 'edt-key-not-assigned 'edt-key-not-assigned) - (edt-bind-function-key-default "HELP" - 'edt-electric-keypad-help 'edt-key-not-assigned) - (edt-bind-function-key-default "DO" - 'execute-extended-command 'edt-key-not-assigned) - (edt-bind-function-key-default "F17" - 'edt-key-not-assigned 'edt-key-not-assigned) - (edt-bind-function-key-default "F18" - 'edt-key-not-assigned 'edt-key-not-assigned) - (edt-bind-function-key-default "F19" - 'edt-key-not-assigned 'edt-key-not-assigned) - (edt-bind-function-key-default "F20" - 'edt-key-not-assigned 'edt-key-not-assigned) - - ;; Control key bindings: Regular and GOLD - ;; - ;; Standard EDT control key bindings conflict with standard Emacs - ;; control key bindings. Normally, the standard Emacs control key - ;; bindings are left unchanged in the default EDT mode. However, if - ;; the variable edt-use-EDT-control-key-bindings is set to true - ;; before invoking edt-emulation-on for the first time, then the - ;; standard EDT bindings (with some enhancements) as defined here are - ;; used, instead. - (if edt-use-EDT-control-key-bindings - (progn - (edt-bind-key-default "\C-a" 'edt-key-not-assigned) - (edt-bind-key-default "\C-b" 'edt-key-not-assigned) - ;; Leave binding of C-c to an Emacs prefix key. - (edt-bind-key-default "\C-d" 'edt-key-not-assigned) - (edt-bind-key-default "\C-e" 'edt-key-not-assigned) - (edt-bind-key-default "\C-f" 'edt-key-not-assigned) - ;; Leave binding of C-g to the Emacs keyboard-quit - (edt-bind-key-default "\C-h" 'edt-beginning-of-line) - (edt-bind-key-default "\C-i" 'edt-tab-insert) - (edt-bind-key-default "\C-j" 'edt-delete-to-beginning-of-word) - (edt-bind-key-default "\C-k" 'edt-define-key) - (edt-bind-gold-key-default "\C-k" 'edt-restore-key) - (edt-bind-key-default "\C-l" 'edt-form-feed-insert) - ;; Leave binding of C-m to newline. - (edt-bind-key-default "\C-n" 'edt-set-screen-width-80) - (edt-bind-key-default "\C-o" 'edt-key-not-assigned) - (edt-bind-key-default "\C-p" 'edt-key-not-assigned) - (edt-bind-key-default "\C-q" 'edt-key-not-assigned) - ;; Leave binding of C-r to isearch-backward. - ;; Leave binding of C-s to isearch-forward. - (edt-bind-key-default "\C-t" 'edt-display-the-time) - (edt-bind-key-default "\C-u" 'edt-delete-to-beginning-of-line) - (edt-bind-key-default "\C-v" 'redraw-display) - (edt-bind-key-default "\C-w" 'edt-set-screen-width-132) - ;; Leave binding of C-x as original prefix key. - (edt-bind-key-default "\C-y" 'edt-key-not-assigned) - ;; Leave binding of C-z to suspend-emacs. - ) - ) - - ;; GOLD bindings for a few keys. - (edt-bind-gold-key-default "\C-g" 'keyboard-quit); Just in case. - (edt-bind-gold-key-default "\C-\\" 'split-window-below) - - ;; GOLD bindings for regular keys. - (edt-bind-gold-key-default "a" 'edt-key-not-assigned) - (edt-bind-gold-key-default "A" 'edt-key-not-assigned) - (edt-bind-gold-key-default "b" 'buffer-menu) - (edt-bind-gold-key-default "B" 'buffer-menu) - (edt-bind-gold-key-default "c" 'compile) - (edt-bind-gold-key-default "C" 'compile) - (edt-bind-gold-key-default "d" 'delete-window) - (edt-bind-gold-key-default "D" 'delete-window) - (edt-bind-gold-key-default "e" 'edt-exit) - (edt-bind-gold-key-default "E" 'edt-exit) - (edt-bind-gold-key-default "f" 'find-file) - (edt-bind-gold-key-default "F" 'find-file) - (edt-bind-gold-key-default "g" 'find-file-other-window) - (edt-bind-gold-key-default "G" 'find-file-other-window) - (edt-bind-gold-key-default "h" 'edt-electric-keypad-help) - (edt-bind-gold-key-default "H" 'edt-electric-keypad-help) - (edt-bind-gold-key-default "i" 'insert-file) - (edt-bind-gold-key-default "I" 'insert-file) - (edt-bind-gold-key-default "j" 'edt-key-not-assigned) - (edt-bind-gold-key-default "J" 'edt-key-not-assigned) - (edt-bind-gold-key-default "k" 'edt-toggle-capitalization-of-word) - (edt-bind-gold-key-default "K" 'edt-toggle-capitalization-of-word) - (edt-bind-gold-key-default "l" 'edt-lowercase) - (edt-bind-gold-key-default "L" 'edt-lowercase) - (edt-bind-gold-key-default "m" 'save-some-buffers) - (edt-bind-gold-key-default "M" 'save-some-buffers) - (edt-bind-gold-key-default "n" 'next-error) - (edt-bind-gold-key-default "N" 'next-error) - (edt-bind-gold-key-default "o" 'switch-to-buffer-other-window) - (edt-bind-gold-key-default "O" 'switch-to-buffer-other-window) - (edt-bind-gold-key-default "p" 'edt-key-not-assigned) - (edt-bind-gold-key-default "P" 'edt-key-not-assigned) - (edt-bind-gold-key-default "q" 'edt-quit) - (edt-bind-gold-key-default "Q" 'edt-quit) - (edt-bind-gold-key-default "r" 'revert-buffer) - (edt-bind-gold-key-default "R" 'revert-buffer) - (edt-bind-gold-key-default "s" 'save-buffer) - (edt-bind-gold-key-default "S" 'save-buffer) - (edt-bind-gold-key-default "t" 'edt-key-not-assigned) - (edt-bind-gold-key-default "T" 'edt-key-not-assigned) - (edt-bind-gold-key-default "u" 'edt-uppercase) - (edt-bind-gold-key-default "U" 'edt-uppercase) - (edt-bind-gold-key-default "v" 'find-file-other-window) - (edt-bind-gold-key-default "V" 'find-file-other-window) - (edt-bind-gold-key-default "w" 'write-file) - (edt-bind-gold-key-default "W" 'write-file) - (edt-bind-gold-key-default "x" 'edt-key-not-assigned) - (edt-bind-gold-key-default "X" 'edt-key-not-assigned) - (edt-bind-gold-key-default "y" 'edt-emulation-off) - (edt-bind-gold-key-default "Y" 'edt-emulation-off) - (edt-bind-gold-key-default "z" 'edt-switch-global-maps) - (edt-bind-gold-key-default "Z" 'edt-switch-global-maps) - (edt-bind-gold-key-default "1" 'delete-other-windows) - (edt-bind-gold-key-default "!" 'edt-key-not-assigned) - (edt-bind-gold-key-default "2" 'edt-split-window) - (edt-bind-gold-key-default "@" 'edt-key-not-assigned) - (edt-bind-gold-key-default "3" 'edt-key-not-assigned) - (edt-bind-gold-key-default "#" 'edt-key-not-assigned) - (edt-bind-gold-key-default "4" 'edt-key-not-assigned) - (edt-bind-gold-key-default "$" 'edt-key-not-assigned) - (edt-bind-gold-key-default "5" 'edt-key-not-assigned) - (edt-bind-gold-key-default "%" 'edt-goto-percentage) - (edt-bind-gold-key-default "6" 'edt-key-not-assigned) - (edt-bind-gold-key-default "^" 'edt-key-not-assigned) - (edt-bind-gold-key-default "7" 'edt-key-not-assigned) - (edt-bind-gold-key-default "&" 'edt-key-not-assigned) - (edt-bind-gold-key-default "8" 'edt-key-not-assigned) - (edt-bind-gold-key-default "*" 'edt-key-not-assigned) - (edt-bind-gold-key-default "9" 'edt-key-not-assigned) - (edt-bind-gold-key-default "(" 'edt-key-not-assigned) - (edt-bind-gold-key-default "0" 'edt-key-not-assigned) - (edt-bind-gold-key-default ")" 'edt-key-not-assigned) - (edt-bind-gold-key-default " " 'undo) - (edt-bind-gold-key-default "," 'edt-key-not-assigned) - (edt-bind-gold-key-default "<" 'edt-key-not-assigned) - (edt-bind-gold-key-default "." 'edt-key-not-assigned) - (edt-bind-gold-key-default ">" 'edt-key-not-assigned) - (edt-bind-gold-key-default "/" 'query-replace) - (edt-bind-gold-key-default "?" 'edt-key-not-assigned) - (edt-bind-gold-key-default "\\" 'edt-key-not-assigned) - (edt-bind-gold-key-default "|" 'edt-key-not-assigned) - (edt-bind-gold-key-default ";" 'edt-key-not-assigned) - (edt-bind-gold-key-default ":" 'edt-key-not-assigned) - (edt-bind-gold-key-default "'" 'edt-key-not-assigned) - (edt-bind-gold-key-default "\"" 'edt-key-not-assigned) - (edt-bind-gold-key-default "-" 'edt-key-not-assigned) - (edt-bind-gold-key-default "_" 'edt-key-not-assigned) - (edt-bind-gold-key-default "=" 'goto-line) - (edt-bind-gold-key-default "+" 'edt-key-not-assigned) - (edt-bind-gold-key-default "[" 'edt-key-not-assigned) - (edt-bind-gold-key-default "{" 'edt-key-not-assigned) - (edt-bind-gold-key-default "]" 'edt-key-not-assigned) - (edt-bind-gold-key-default "}" 'edt-key-not-assigned) - (edt-bind-gold-key-default "`" 'what-line) - (edt-bind-gold-key-default "~" 'edt-key-not-assigned) -) - -;;; -;;; DEFAULT EDT KEYPAD HELP -;;; - -;; -;; Upper case commands in the keypad diagram below indicate that the -;; emulation should look and feel very much like EDT. Lower case -;; commands are enhancements and/or additions to the EDT keypad -;; commands or are native Emacs commands. -;; - -(defun edt-keypad-help () - "DEFAULT EDT Keypad Active. - - F7: Copy Rectangle +----------+----------+----------+----------+ - F8: Cut Rect Overstrike |Prev Line |Next Line |Bkwd Char |Frwd Char | - G-F8: Paste Rect Overstrike | (UP) | (DOWN) | (LEFT) | (RIGHT) | - F9: Cut Rect Insert |Window Top|Window Bot|Bkwd Sent |Frwd Sent | - G-F9: Paste Rect Insert +----------+----------+----------+----------+ - F10: Cut Rectangle -G-F10: Paste Rectangle - F11: ESC - F12: Beginning of Line +----------+----------+----------+----------+ -G-F12: Delete Other Windows | GOLD | HELP | FNDNXT | DEL L | - F13: Delete to Begin of Word | (PF1) | (PF2) | (PF3) | (PF4) | - HELP: Keypad Help |Mark Wisel|Desc Funct| FIND | UND L | -G-HELP: Emacs Help +----------+----------+----------+----------+ - DO: Execute extended command | PAGE | SECT | APPEND | DEL W | - C-g: Keyboard Quit | (7) | (8) | (9) | (-) | -G-C-g: Keyboard Quit |Ex Ext Cmd|Fill Regio| REPLACE | UND W | - C-h: Beginning of Line +----------+----------+----------+----------+ -G-C-h: Emacs Help | ADVANCE | BACKUP | CUT | DEL C | - C-i: Tab Insert | (4) | (5) | (6) | (,) | - C-j: Delete to Begin of Word | BOTTOM | TOP | Yank | UND C | - C-k: Define Key +----------+----------+----------+----------+ -G-C-k: Restore Key | WORD | EOL | CHAR | Next | - C-l: Form Feed Insert | (1) | (2) | (3) | Window | - C-n: Set Screen Width 80 | CHNGCASE | DEL EOL |Quoted Ins| ! - C-r: Isearch Backward +---------------------+----------+ (ENTER) | - C-s: Isearch Forward | LINE | SELECT | ! - C-t: Display the Time | (0) | (.) | SUBS | - C-u: Delete to Begin of Line | Open Line | RESET | | - C-v: Redraw Display +---------------------+----------+----------+ - C-w: Set Screen Width 132 - C-z: Suspend Emacs +----------+----------+----------+ -G-C-\\: Split Window | FNDNXT | Yank | CUT | - | (FIND) | (INSERT) | (REMOVE) | - G-b: Buffer Menu | FIND | | COPY | - G-c: Compile +----------+----------+----------+ - G-d: Delete Window |SELECT/RES|SECT BACKW|SECT FORWA| - G-e: Exit | (SELECT) |(PREVIOUS)| (NEXT) | - G-f: Find File | | | | - G-g: Find File Other Window +----------+----------+----------+ - G-h: Keypad Help - G-i: Insert File - G-k: Toggle Capitalization Word - G-l: Downcase Region - G-m: Save Some Buffers - G-n: Next Error - G-o: Switch to Next Window - G-q: Quit - G-r: Revert File - G-s: Save Buffer - G-u: Upcase Region - G-v: Find File Other Window - G-w: Write file - G-y: EDT Emulation OFF - G-z: Switch to User EDT Key Bindings - G-1: Delete Other Windows - G-2: Split Window - G-%: Go to Percentage - G- : Undo (GOLD Spacebar) - G-=: Go to Line - G-`: What line - G-/: Query-Replace" - - (interactive) - (describe-function 'edt-keypad-help)) - -(defun edt-electric-helpify (fun) - (let ((name "*Help*")) - (if (save-window-excursion - (let* ((p (symbol-function 'help-print-return-message)) - (b (get-buffer name)) - (m (buffer-modified-p b))) - (and b (not (get-buffer-window b)) - (setq b nil)) - (unwind-protect - (progn - (message "%s..." (capitalize (symbol-name fun))) - (and b - (with-current-buffer b - (set-buffer-modified-p t))) - (fset 'help-print-return-message #'ignore) - (call-interactively fun) - (and (get-buffer name) - (get-buffer-window (get-buffer name)) - (or (not b) - (not (eq b (get-buffer name))) - (not (buffer-modified-p b))))) - (fset 'help-print-return-message p) - (and b (buffer-name b) - (with-current-buffer b - (set-buffer-modified-p m)))))) - (with-electric-help 'delete-other-windows name t)))) - -(defun edt-electric-keypad-help () - "Display default EDT bindings." - (interactive) - (edt-electric-helpify 'edt-keypad-help)) - -(defun edt-electric-user-keypad-help () - "Display user custom EDT bindings." - (interactive) - (edt-electric-helpify 'edt-user-keypad-help)) - -;;; -;;; EDT emulation screen width commands. -;; -;; Some terminals require modification of terminal attributes when -;; changing the number of columns displayed, hence the fboundp tests -;; below. These functions are defined in the corresponding terminal -;; specific file, if needed. - -(defun edt-set-screen-width-80 () - "Set screen width to 80 columns." - (interactive) - (if (fboundp 'edt-set-term-width-80) - (edt-set-term-width-80)) - (set-frame-width nil 80) - (message "Terminal width 80")) - -(defun edt-set-screen-width-132 () - "Set screen width to 132 columns." - (interactive) - (if (fboundp 'edt-set-term-width-132) - (edt-set-term-width-132)) - (set-frame-width nil 132) - (message "Terminal width 132")) - -(defconst edt-version "4.0" "EDT Emulation version number.") -(make-obsolete-variable 'edt-version 'emacs-version "28.1") - -(provide 'edt) - -;;; edt.el ends here diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el index b62e11b2649..85d75f385f7 100644 --- a/lisp/emulation/viper.el +++ b/lisp/emulation/viper.el @@ -395,7 +395,6 @@ widget." sh-mode ksh-mode csh-mode gnus-article-mode - mh-show-mode ) "Major modes that require Vi command state." :type '(repeat symbol)) @@ -413,7 +412,6 @@ widget." recentf-dialog-mode occur-mode - mh-folder-mode gnus-group-mode gnus-summary-mode @@ -475,7 +473,6 @@ unless it is coming up in a wrong Viper state." (internal-ange-ftp-mode vi-state viper-comint-mode-modifier-map) (dired-mode emacs-state viper-dired-modifier-map) (tar-mode emacs-state viper-slash-and-colon-map) - (mh-folder-mode emacs-state viper-slash-and-colon-map) (gnus-group-mode emacs-state viper-gnus-modifier-map) (gnus-summary-mode emacs-state viper-gnus-modifier-map) (Info-mode emacs-state viper-slash-and-colon-map) @@ -951,7 +948,6 @@ Two differences: (viper-set-emacs-state-searchstyle-macros nil 'dired-mode) ; dired (viper-set-emacs-state-searchstyle-macros nil 'tar-mode) ; tar - (viper-set-emacs-state-searchstyle-macros nil 'mh-folder-mode) ; mhe (viper-set-emacs-state-searchstyle-macros nil 'gnus-group-mode) ; gnus (viper-set-emacs-state-searchstyle-macros nil 'gnus-summary-mode) (viper-set-emacs-state-searchstyle-macros nil 'Info-mode) ; info diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el index a9274e7c60d..0fa1cfb256b 100644 --- a/lisp/eshell/em-pred.el +++ b/lisp/eshell/em-pred.el @@ -141,84 +141,6 @@ The format of each entry is :type '(repeat (cons character sexp)) :risky t) -(defvar eshell-predicate-help-string - "Eshell predicate quick reference: - - - follow symbolic references for predicates after the `-' - ^ invert sense of predicates after the `^' - -FILE TYPE: - / directories s sockets - . regular files p named pipes - * executable (files only) @ symbolic links - - %x file type == `x' (as by ls -l; so `c' = char device, etc.) - -PERMISSION BITS (for owner/group/world): - r/A/R readable s setuid - w/I/W writable S setgid - x/E/X executable t sticky bit - -OWNERSHIP: - U owned by effective uid - G owned by effective gid - u(UID|\\='user\\=') owned by UID/user - g(GID|\\='group\\=') owned by GID/group - -FILE ATTRIBUTES: - l[+-]N +/-/= N links - a[Mwhms][+-](N|\\='FILE\\=') access time +/-/= N months/weeks/hours/mins/secs - (days if unspecified) if FILE specified, - use as comparison basis; so a+\\='file.c\\=' - shows files accessed before file.c was - last accessed - m[Mwhms][+-](N|\\='FILE\\=') modification time... - c[Mwhms][+-](N|\\='FILE\\=') change time... - L[kmp][+-]N file size +/-/= N Kb/Mb/blocks - -EXAMPLES: - *(^@) all non-dot files which are not symlinks - .#*(^@) all files which are not symbolic links - **/.#*(*) all executable files, searched recursively - ***/*~f*(-/) recursively (though not traversing symlinks), - find all directories (or symlinks referring to - directories) whose names do not begin with f. - e*(*Lk+50) executables 50k or larger beginning with `e'") - -(defvar eshell-modifier-help-string - "Eshell modifier quick reference: - -FOR SINGLE ARGUMENTS, or each argument of a list of strings: - E evaluate again - L lowercase - U uppercase - C capitalize - h dirname - t basename - e file extension - r strip file extension - q escape special characters - - S split string at any whitespace character - S/PAT/ split string at each occurrence of PAT - -FOR LISTS OF ARGUMENTS: - o sort alphabetically - O reverse sort alphabetically - u uniq list (typically used after :o or :O) - R reverse list - - j join list members, separated by a space - j/PAT/ join list members, separated by PAT - i/PAT/ exclude all members not matching PAT - x/PAT/ exclude all members matching PAT - - s/pat/match/ substitute PAT with MATCH - gs/pat/match/ substitute PAT with MATCH for all occurrences - -EXAMPLES: - *.c(:o) sorted list of .c files") - (defvar eshell-pred-delimiter-pairs '((?\( . ?\)) (?\[ . ?\]) @@ -235,29 +157,12 @@ respectively.") (defvar eshell-error-if-no-glob) ; Defined in em-glob.el. -(defvar-keymap eshell-pred-mode-map - "C-c M-q" #'eshell-display-predicate-help - "C-c M-m" #'eshell-display-modifier-help) - ;;; Functions: -(defun eshell-display-predicate-help () - (interactive) - (with-electric-help - (lambda () - (insert eshell-predicate-help-string)))) - -(defun eshell-display-modifier-help () - (interactive) - (with-electric-help - (lambda () - (insert eshell-modifier-help-string)))) - (define-minor-mode eshell-pred-mode "Minor mode for the eshell-pred module. -\\{eshell-pred-mode-map}" - :keymap eshell-pred-mode-map) +\\{eshell-pred-mode-map}") (defun eshell-pred-initialize () ;Called from `eshell-mode' via intern-soft! "Initialize the predicate/modifier code." diff --git a/lisp/finder.el b/lisp/finder.el index c33369a74ca..2c4844e8814 100644 --- a/lisp/finder.el +++ b/lisp/finder.el @@ -149,7 +149,6 @@ would otherwise be.") ("leim" . emacs) ("ja-dic" . emacs) ("quail" . emacs) - ("mh-e" . mh-e) ("obsolete" . emacs) ;; This should really be ("nxml" . nxml-mode), because nxml-mode.el ;; is the main file for the package. Then we would not need an diff --git a/lisp/gnus/gnus-dired.el b/lisp/gnus/gnus-dired.el index f21d84b40c6..9a9b92e0269 100644 --- a/lisp/gnus/gnus-dired.el +++ b/lisp/gnus/gnus-dired.el @@ -69,9 +69,6 @@ See `mail-user-agent' for more information." :type '(radio (function-item :tag "Default Emacs mail" :format "%t\n" sendmail-user-agent) - (function-item :tag "Emacs interface to MH" - :format "%t\n" - mh-e-user-agent) (function-item :tag "Gnus Message package" :format "%t\n" message-user-agent) diff --git a/lisp/gnus/gnus-mh.el b/lisp/gnus/gnus-mh.el deleted file mode 100644 index 0035ff26a25..00000000000 --- a/lisp/gnus/gnus-mh.el +++ /dev/null @@ -1,120 +0,0 @@ -;;; gnus-mh.el --- mh-e interface for Gnus -*- lexical-binding: t; -*- - -;; Copyright (C) 1994-2024 Free Software Foundation, Inc. - -;; Author: Masanobu UMEDA -;; Lars Magne Ingebrigtsen -;; Keywords: news - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;;; Send mail using mh-e. - -;; The following mh-e interface is all cooperative works of -;; tanaka@flab.fujitsu.CO.JP (TANAKA Hiroshi), kawabe@sra.CO.JP -;; (Yoshikatsu Kawabe), and shingu@casund.cpr.canon.co.jp (Toshiaki -;; SHINGU). - -;;; Code: - -(require 'gnus) -(require 'mh-e) -(require 'mh-comp) -(require 'gnus-msg) -(require 'gnus-sum) - -(defvar mh-lib-progs) - -(defcustom gnus-rcvstore-options nil - "Options that are passed to rcvstore, or nil. -These are used when saving articles to an MH folder." - :version "26.1" - :group 'gnus-article - :type '(repeat string)) - -(defun gnus-summary-save-article-folder (&optional arg) - "Append the current article to an mh folder. -If N is a positive number, save the N next articles. -If N is a negative number, save the N previous articles. -If N is nil and any articles have been marked with the process mark, -save those articles instead." - (interactive "P" gnus-summary-mode) - (require 'gnus-art) - (let ((gnus-default-article-saver 'gnus-summary-save-in-folder)) - (gnus-summary-save-article arg))) - -(defun gnus-summary-save-in-folder (&optional folder) - "Save this article to MH folder (using `rcvstore' in MH library). -Optional argument FOLDER specifies folder name." - ;; Thanks to yuki@flab.Fujitsu.JUNET and ohm@kaba.junet. - (mh-find-path) - (let ((folder - (cond ((and (eq folder 'default) - gnus-newsgroup-last-folder) - gnus-newsgroup-last-folder) - (folder folder) - (t (mh-prompt-for-folder - "Save article in" - (funcall gnus-folder-save-name gnus-newsgroup-name - gnus-current-headers gnus-newsgroup-last-folder) - t)))) - (errbuf (gnus-get-buffer-create " *Gnus rcvstore*")) - ;; Find the rcvstore program. - (exec-path (cond - ((and (boundp 'mh-lib-progs) mh-lib-progs) - (cons mh-lib-progs exec-path)) - (mh-lib (cons mh-lib exec-path)) - (t exec-path)))) - (with-current-buffer gnus-original-article-buffer - (save-restriction - (widen) - (unwind-protect - (apply - #'call-process-region - (point-min) (point-max) "rcvstore" nil errbuf nil folder - gnus-rcvstore-options) - (set-buffer errbuf) - (if (zerop (buffer-size)) - (message "Article saved in folder: %s" folder) - (message "%s" (buffer-string))) - (kill-buffer errbuf)))) - (setq gnus-newsgroup-last-folder folder))) - -(defun gnus-Folder-save-name (newsgroup _headers &optional last-folder) - "Generate folder name from NEWSGROUP, HEADERS, and optional LAST-FOLDER. -If variable `gnus-use-long-file-name' is nil, it is +News.group. -Otherwise, it is like +news/group." - (or last-folder - (concat "+" - (if gnus-use-long-file-name - (gnus-capitalize-newsgroup newsgroup) - (gnus-newsgroup-directory-form newsgroup))))) - -(defun gnus-folder-save-name (newsgroup _headers &optional last-folder) - "Generate folder name from NEWSGROUP, HEADERS, and optional LAST-FOLDER. -If variable `gnus-use-long-file-name' is nil, it is +news.group. -Otherwise, it is like +news/group." - (or last-folder - (concat "+" - (if gnus-use-long-file-name - newsgroup - (gnus-newsgroup-directory-form newsgroup))))) - -(provide 'gnus-mh) - -;;; gnus-mh.el ends here diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index d85a9333f25..be0993b5499 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -740,16 +740,14 @@ The headers should be delimited by a line whose contents match the variable `mail-header-separator'. Valid values include `message-send-mail-with-sendmail' -`message-send-mail-with-mh', `message-send-mail-with-qmail', -`message-smtpmail-send-it', `smtpmail-send-it', -`feedmail-send-it' and `message-send-mail-with-mailclient'. The -default is system dependent and determined by the function -`message-send-mail-function'. +`message-send-mail-with-qmail', `message-smtpmail-send-it', +`smtpmail-send-it', `feedmail-send-it' and +`message-send-mail-with-mailclient'. The default is system dependent +and determined by the function `message-send-mail-function'. See also `send-mail-function'." :type '(radio (function-item message--default-send-mail-function) (function-item message-send-mail-with-sendmail) - (function-item message-send-mail-with-mh) (function-item message-send-mail-with-qmail) (function-item message-smtpmail-send-it) (function-item :doc "Use SMTPmail package." smtpmail-send-it) @@ -1382,9 +1380,6 @@ actually occur." 'message-mail 'message-send-and-exit 'message-kill-buffer 'message-send-hook) -(defvar message-mh-deletable-headers '(Message-ID Date Lines Sender) - "If non-nil, delete the deletable headers before feeding to mh.") - (defvar message-send-method-alist '((news message-news-p message-send-via-news) (mail message-mail-p message-send-via-mail)) @@ -1893,9 +1888,6 @@ For more about mail user agents, see Info node `(emacs)Mail Methods'" (function-item :tag "Default Emacs mail" :format "%t\n" sendmail-user-agent) - (function-item :tag "Emacs interface to MH" - :format "%t\n" - mh-e-user-agent) (function :tag "Other")) :version "21.1" :group 'message) @@ -2079,8 +2071,6 @@ You must have the \"hashcash\" binary installed, see `hashcash-program'." (autoload 'gnus-request-post "gnus-int") (autoload 'gnus-server-string "gnus") (autoload 'message-setup-toolbar "messagexmas") -(autoload 'mh-new-draft-name "mh-comp") -(autoload 'mh-send-letter "mh-comp") (autoload 'nndraft-request-associate-buffer "nndraft") (autoload 'nndraft-request-expire-articles "nndraft") (autoload 'nnvirtual-find-group-art "nnvirtual") @@ -5160,26 +5150,6 @@ to find out how to use this." ;; should never happen (_ (error "qmail-inject reported unknown failure")))) -(defvar mh-previous-window-config) - -(defun message-send-mail-with-mh () - "Send the prepared message buffer with mh." - (let ((mh-previous-window-config nil) - (name (mh-new-draft-name))) - (setq buffer-file-name name) - ;; MH wants to generate these headers itself. - (when message-mh-deletable-headers - (let ((headers message-mh-deletable-headers)) - (while headers - (goto-char (point-min)) - (when (re-search-forward - (concat "^" (symbol-name (car headers)) ": *") nil t) - (delete-line)) - (pop headers)))) - (run-hooks 'message-send-mail-hook) - ;; Pass it on to mh. - (mh-send-letter))) - (defun message-use-send-mail-function () (run-hooks 'message-send-mail-hook) (funcall send-mail-function)) diff --git a/lisp/hexl.el b/lisp/hexl.el index 9f25900e844..a42283cfdc3 100644 --- a/lisp/hexl.el +++ b/lisp/hexl.el @@ -141,8 +141,7 @@ as that will override any bit grouping options set here." (define-key map "\C-e" 'hexl-end-of-line) (define-key map "\C-f" 'hexl-forward-char) - (if (not (memq (key-binding (char-to-string help-char)) - '(help-command ehelp-command))) + (if (not (eq (key-binding (char-to-string help-char)) 'help-command)) (define-key map (char-to-string help-char) 'undefined)) (define-key map "\C-k" 'undefined) diff --git a/lisp/info-look.el b/lisp/info-look.el index cb124297d50..a115da8a20e 100644 --- a/lisp/info-look.el +++ b/lisp/info-look.el @@ -1065,7 +1065,6 @@ Return nil if there is nothing appropriate in the buffer near point." ("info" "Index") ("mairix" "(mairix-el)Variable Index" "(mairix-el)Function Index") ("message" "Index") - ("mh" "(mh-e)Option Index" "(mh-e)Command Index") ("newsticker" "Index") ("octave" "(octave-mode)Variable Index" "(octave-mode)Lisp Function Index") ("org" "Variable Index" "Command and Function Index") diff --git a/lisp/info.el b/lisp/info.el index 4b02c9db263..236b8b350b4 100644 --- a/lisp/info.el +++ b/lisp/info.el @@ -4727,7 +4727,7 @@ Advanced commands: (defvar Info-file-list-for-emacs - '("ediff" "eudc" "forms" "gnus" "info" ("Info" . "info") ("mh" . "mh-e") + '("ediff" "eudc" "forms" "gnus" "info" ("Info" . "info") "sc" "message" ("dired" . "dired-x") "viper" "vip" "idlwave" ("c" . "ccmode") ("c++" . "ccmode") ("objc" . "ccmode") ("java" . "ccmode") ("idl" . "ccmode") ("pike" . "ccmode") diff --git a/lisp/mail/supercite.el b/lisp/mail/supercite.el index 245af9da685..84d6b8df9f4 100644 --- a/lisp/mail/supercite.el +++ b/lisp/mail/supercite.el @@ -1457,8 +1457,6 @@ non-nil." "Does nothing. Use this instead of nil to get a blank header." ()) -(declare-function mh-in-header-p "mh-utils" ()) - (defun sc-no-blank-line-or-header () "Similar to `sc-no-header' except it removes the preceding blank line." (and (not (bobp)) @@ -1467,9 +1465,7 @@ non-nil." (or (= (point) (save-excursion (rfc822-goto-eoh) - (line-beginning-position 2))) - (and (eq major-mode 'mh-letter-mode) - (mh-in-header-p)))) + (line-beginning-position 2))))) (progn (forward-line) (kill-line)))) diff --git a/lisp/mh-e/ChangeLog.1 b/lisp/mh-e/ChangeLog.1 deleted file mode 100644 index 10a19fdc49f..00000000000 --- a/lisp/mh-e/ChangeLog.1 +++ /dev/null @@ -1,11441 +0,0 @@ -2005-09-30 Bill Wohler - - * mh-customize.el (mh-refile-msg, mh-tool-bar-reply-from) - (mh-tool-bar-reply-to, mh-tool-bar-reply-all) - (mh-alias-grab-from-field, mh-pack-folder): Image files moved to - etc/images/mail so added "mail/" prefix. - (mh-reply): Ditto. Also renamed reply2.* to reply.*. - (mh-rescan-folder): Ditto. Renamed image file to refresh.* since - it can be used in the general sense. Does not have "mail/" - prefix. - -2005-09-29 Bill Wohler - - Merged in changes from CVS Emacs including: - - * mh-mime.el (mh-compose-forward, mh-mhn-compose-forw): - * mh-comp.el (mh-insert-letter): - * mh-utils.el (mh-prompt-for-folder): - Follow convention for reading with the minibuffer. Emilio C. Lopes - 2005-09-24. - -2005-09-26 Bill Wohler - - * mh-e.el (desktop-buffer-mode-handlers): Only add to this list if - the variable exists. Not present pre-version 22. - - Merged in changes from CVS Emacs including: - - * mh-print.el (mh-ps-print-msg-show): Fix misplaced parenthesis in - previous change. Juanma Barranquero 2005-09-19 - - * mh-alias.el (mh-alias-ali): Fix `message' call: first arg - should be a format spec. - - * mh-print.el (mh-ps-spool-buffer, mh-ps-spool-a-msg) - (mh-ps-print-msg, mh-ps-print-msg-show): Ditto. - - * mh-mime.el (mh-toggle-mh-decode-mime-flag): Ditto. - - * mh-index.el (mh-index-sequenced-messages): Ditto. - - * mh-e.el (mh-refile-or-write-again, mh-page-msg): Ditto. - - * mh-junk.el (mh-junk-blacklist, mh-junk-whitelist) - (mh-spamassassin-blacklist, mh-spamassassin-whitelist): Ditto. D - Goel 2005-09-18. - - * mh-customize.el: Do not use face-alias compatibility for - faces that did not appear in the previous Emacs release. Dan - Nicolaescu 2005-08-15. - - * mh-e.el: Add handler to desktop-buffer-mode-handlers. - (mh-restore-desktop-buffer): Remove autoload cookie. - (mh-folder-mode): Add autoload cookie. Lars Hansen - 2005-08-10. - - Update FSF's address in GPL notices Lute Kamstra - 2005-07-04 . - - * mh-customize.el (mh-folder-body-face, mh-folder-cur-msg-face) - (mh-folder-cur-msg-number-face): New backward-compatibility - aliases for renamed faces. Lute Kamstra 2005-06-17. - - * mh-customize.el (mh-folder-body, mh-folder-cur-msg) - (mh-folder-cur-msg-number, mh-folder-date, mh-folder-followup) - (mh-folder-msg-number, mh-folder-refiled, mh-folder-subject) - (mh-folder-tick, mh-folder-to, mh-index-folder) - (mh-letter-header-field, mh-show-cc, mh-show-date) - (mh-show-header, mh-show-pgg-good, mh-show-pgg-unknown) - (mh-show-pgg-bad, mh-show-signature, mh-show-to, mh-show-from) - (mh-show-xface, mh-speedbar-folder, mh-speedbar-selected-folder) - (mh-speedbar-folder-with-unseen-messages) - (mh-speedbar-selected-folder-with-unseen-messages) - (mh-folder-msg-number, mh-folder-subject, mh-folder-followup) - (mh-folder-subject): Remove "-face" suffix from face names. - (mh-folder-body, mh-folder-cur-msg, mh-folder-cur-msg-number) - (mh-folder-date-face, mh-folder-followup-face) - (mh-folder-msg-number-face, mh-folder-refiled-face) - (mh-folder-subject-face, mh-folder-tick-face, mh-folder-to-face) - (mh-index-folder-face, mh-letter-header-field-face) - (mh-show-cc-face, mh-show-date-face, mh-show-header-face) - (mh-show-pgg-good-face, mh-show-pgg-unknown-face) - (mh-show-pgg-bad-face, mh-show-signature-face, mh-show-to-face) - (mh-show-from-face, mh-show-xface-face, mh-speedbar-folder-face) - (mh-speedbar-selected-folder-face) - (mh-speedbar-folder-with-unseen-messages-face) - (mh-speedbar-selected-folder-with-unseen-messages-face): - New backward-compatibility aliases for renamed faces. - (mh-folder-body-face, mh-folder-cur-msg-face) - (mh-folder-cur-msg-number-face, mh-folder-date-face) - (mh-folder-followup-face, mh-folder-msg-number-face) - (mh-folder-deleted-face, mh-folder-refiled-face) - (mh-folder-subject-face, mh-folder-address-face) - (mh-folder-scan-format-face, mh-folder-to-face) - (mh-index-folder-face, mh-show-cc-face, mh-show-date-face) - (mh-show-header-face, mh-show-pgg-good-face) - (mh-show-pgg-unknown-face, mh-show-pgg-bad-face) - (mh-show-to-face, mh-show-from-face, mh-show-subject-face) - (mh-speedbar-folder-with-unseen-messages) - (mh-speedbar-selected-folder-with-unseen-messages): - Use renamed MH-E faces. - - * mh-utils.el (mh-letter-font-lock-keywords) - (mh-face-display-function): Use renamed MH-E faces. - * mh-speed.el (mh-folder-speedbar-buttons) - (mh-speed-update-current-folder, mh-speed-normal-face) - (mh-speed-bold-face, mh-speed-add-buttons) - (mh-speed-invalidate-map): Likewise. - * mh-mime.el (mh-signature-highlight): Likewise. Miles Bader - 2005-06-17. - - * mh-comp.el (mh-send-sub): - * mh-identity.el (mh-identity-field-handler): - * mh-mime.el (mh-secure-message): - Don't use `format' on `error' arguments. Juanma - Barranquero 2005-06-16. - - * mh-mime.el (mh-secure-message): Follow error conventions. - Juanma Barranquero 2005-06-14. - -2005-09-24 Bill Wohler - - * mh-unit.el (mh-unit): Changed lm-verify test to Emacs 22. - -2005-09-22 Bill Wohler - - * Makefile: Incorporated ideas from Clemens Fruhwirth to - generalize mh-loaddefs.el to make it work for both GNU Emacs and - XEmacs. - (EMACS_OPTIONS, XEMACS_OPTIONS): Use double-dash for all long - options. - (EMACS_LOADDEFS_COOKIE): New variable for generate-autoload-cookie - setting. Obsoletes XEMACS_LOADDEFS_COOKIE. - (EMACS_EXPORT_MH_LOADDEFS): New variable for GNU Emacs commands to - rebuild mh-loaddefs.el. - (XEMACS_EXPORT_MH_LOADDEFS): New variable for XEmacs commands to - rebuild mh-loaddefs.el. Obsoletes XEMACS_LOADDEFS_FILE and - XEMACS_LOADDEFS_PKG_NAME. - (MH-E-LOADDEFS-SRC): New variable which is set to $(MH-E-SRC) on - GNU Emacs, and adds $(MH-E-XEMACS-SRC) on XEmacs. - (all): Modify EMACS_EXPORT_MH_LOADDEFS and MH-E-LOADDEFS-SRC on - XEMacs. - (mh-loaddefs.el): Now depends on $(MH-E-LOADDEFS-SRC) and has - generic compile command that works on both GNU Emacs XEmacs. - (xemacs): Depend on autoloads instead of deleted loaddefs-xemacs. - (loaddefs-xemacs): Deleted. - -2005-08-10 Lars Hansen - - * mh-e.el: Add handler to desktop-buffer-mode-handlers. - (mh-restore-desktop-buffer): Remove autoload cookie. - (mh-folder-mode): Add autoload cookie. - -2005-07-19 Bill Wohler - - * README (INSTALL): Added info for Mac users. - -2005-07-16 Satyaki Das - - * mh-comp.el (mh-font-lock-field-data): Fix a bug where the - function would return t but match-data was being set to nil - (closes SF #1241017). - -2005-07-12 Jeffrey C Honig - - * mh-customize.el (mh-invisible-header-fields-internal) - (mh-invisible-header-fields-internal): Add Received-SPF header and - X-Gmail- prefixes seen from Gmail. - -2005-06-08 Peter S Galbraith - - * mh-comp.el (mh-insert-auto-fields): Insert identity regardless of - whether one was already set, since if one used a default identity - it would never be overridden (closes SF #1204506). - -2005-06-02 Bill Wohler - - * mh-customize.el (mh-customize): Use customization group mh-e. - - * mh-init.el (mh-path): Use customization group mh-e. Thanks to - Peter Whaite for these patches (closes SF #1213716). - -2005-06-01 Bill Wohler - - * mh-mime.el (mh-compose-forward): Only use mh-sent-from-msg as a - default message if it's a number (as is done elsewhere). - Otherwise, an error is thrown if this function is called from a - draft created by mh-forward since this variable is a list. Also - added a space after the "Messages [%s]:" prompt. - -2005-05-30 Jeffrey C Honig - - * mh-mime.el (mh-compose-forward): Allow insertion of multiple - forwarded messages by range (including sequences). For the sent - folder the default message presented is the sent message. For - other folders, the default message is "cur", if it exists. - -2005-05-28 Bill Wohler - - * mh-e.el (Version, mh-version): Added +cvs to version. - -2005-05-28 Bill Wohler - - Released MH-E version 7.84. - - * MH-E-NEWS, README: Updated for release 7.84. - - * mh-e.el (Version, mh-version): Updated for release 7.84. - -2005-05-28 Bill Wohler - - * mh-e.el, mh-comp.el: Don't autoload Info-goto-node. It's not - used, and if it were, the code should use the info function - instead. - - Use full year in copyright notices (for example, 2005, not 05). - - * Makefile (mh-loaddefs.el, mh-e-autoloads.el): Added 2005 to - copyright notice. - - * mh-inc.el: Use three ;;; to precede Local Variables to be - consistent with other files. Will have to ask Stefan Monnier why - he changed it. - - * README: This version of MH-E to appear in GNU Emacs 22.1, not - 21.5. - - * ChangeLog: The * in a ChangeLog entry must only be used before a - filename. - - Fixed compilation warnings in CVS Emacs. This included using - "public" functions instead of "private" ones (info instead of - Info-goto-node, view-mode-enter instead of view-mode), and - removing a customization group that didn't have a parent group. In - addition, string-to-int was recently deprecated; use - string-to-number instead. - - * mh-customize.el (Info-goto-node): Deleted autoload. - (mh-e): Deleted mh group. Use single mh-e group instead. - (mh-tool-bar-folder-help, mh-tool-bar-letter-help): Use info - instead of Info-goto-node. - - * mh-e.el (mh-read-msg-list): string-to-int deprecated; use - string-to-number. - - * mh-funcs.el (mh-list-folders): Use view-mode-enter instead of - view-mode. - - * mh-seq.el (mh-list-sequences): Use view-mode-enter instead of - view-mode. - - * mh-utils.el (mh-get-msg-num): string-to-int deprecated; use - string-to-number. - - Merged in changes from CVS Emacs including: - - * mh-utils.el (mh-show-mode): - * mh-pick.el (mh-pick-mode): Remove spurious run-hooks. Lute - Kamstra 2005-05-26. - -2005-05-25 Bill Wohler - - Merged in changes from CVS Emacs including: - - * mh-customize.el (mh-speedbar-selected-folder-face): Special case - high number of colors displays. Dan Nicolaescu - 2005-04-08. - - * mh-e.el, mh-identity.el, mh-mime.el: Replace `legal' with - `valid'. Replace `illegal' with `invalid'. Werner Lemberg - 2005-03-25. - - * mh-inc.el (mh-inc-spool-list): Correctly declare the external - var. Stefan 2004-09-07. - -2005-05-18 Bill Wohler - - * mh-comp.el (mh-reply): Mention use of mh-repl-group-formfile in - docstring. - -2005-05-05 Bill Wohler - - * mh-e.el (Version, mh-version): Added +cvs to release number. - -2005-05-05 Bill Wohler - - Released MH-E version 7.83. - - * MH-E-NEWS, README: Updated for release 7.83. - - * mh-e.el (Version, mh-version): Updated for release 7.83. - -2005-05-05 Bill Wohler - - * README: To appear in Emacs 21.5, since 21.4 was released (but - without the latest MH-E). - - * release-utils (usage): Added --variable-changes. - -2005-05-04 Bill Wohler - - * mh-customize.el (*-face): Made docstrings consistent. - - * mh-seq.el (mh-pick-args-list): Extracted function for turning - string of pick arguments to list. Fixed list so that multi-word - arguments were put in a single string (closes SF #1122655). - (mh-edit-pick-expr): Use it. - - * mh-unit.el (mh-unit): Since 21.4 sneaked out but didn't contain - updated lm-verify, don't run lm-verify on versions before 21.5. - (mh-unit-test-pick-args-list): Added. - - * mh-customize.el (mh-yank-from-start-of-msg): Use headline - capitalization. Changed wording of some choices to be more consistent. - (mh-invisible-header-fields-internal): Added fields from usa.net. - -2005-04-24 Satyaki Das - - * mh-mime.el (mh-mime-security-button-face): New function which - determines the face to use to colorize encrypted or signed emails. - (mh-insert-mime-security-button): Modified to colorize the button - differently based on whether the signature was valid or not, - whether the decryption was successful or not, etc. - - * mh-customize.el (mh-show-pgg-good-face) - (mh-show-pgg-unknown-face, mh-show-pgg-bad-face): Faces added to - highlight buttons introduced for encrypted or signed MIME parts. - -2005-03-19 Bill Wohler - - * mh-customize.el (mh-mml-method-default): Sorted alphabetically. - (mh-insert-x-mailer-flag, mh-reply-show-message-flag): Moved from - mh-letter group to mh-sending-mail group. The writing of the - documentation revealed that these options were misplaced. - -2005-03-17 Bill Wohler - - * mh-customize.el (mh-junk-background): Put in alphabetical order. - Synced with manual. - (mh-junk-program): Use double-quotes on non-symbols. - - * mh-pick.el (mh-search-folder): Synced docstrings with manual. - - * mh-index.el (mh-index-search, mh-pick-execute-search) - (mh-grep-execute-search, mh-mairix-execute-search) - (mh-swish-execute-search, mh-swish++-execute-search) - (mh-namazu-execute-search): Synced docstrings with manual. Note - that I'm now grabbing the output of an Info buffer which is why - the indents on the examples has changed a bit. If we all use that - methodology in the future, we shouldn't produce as many gratuitous - diffs. I also noticed that `grep' and `search' became links to - unrelated things, so let's use double-quotes for quoting - non-symbols in the docstrings. - - * mh-customize.el (mh-index-new-messages-folders) - (mh-index-ticked-messages-folders): Synced docstrings with manual. - -2005-02-16 Satyaki Das - - * mh-index.el (mh-swish-execute-search): Simplify the indexing - recipe for swish. Thanks to Eric Jensen for the suggestion. - -2005-02-11 Satyaki Das - - * mh-index.el (mh-swish-execute-search) - (mh-swish++-execute-search): Make the indexing recipes better. - (mh-swish-next-result): The indexer might find matches in files - that aren't messages. Make the function handle that case - gracefully. - -2005-02-07 Bill Wohler - - * mh-customize.el (mh-inc-prog, mh-inc-spool-list): Synced - docstrings with manual. - -2005-02-06 Bill Wohler - - * mh-junk.el (mh-spamassassin-blacklist): Removed trailing - whitespace. - - * mh-e.el (mh-refile-or-write-again): Checkdoc fix. - - * mh-identity.el (mh-identity-list-set) - (mh-identity-field-handler, mh-identity-handler-gpg-identity) - (mh-identity-handler-signature) - (mh-identity-handler-attribution-verb) - (mh-identity-handler-default, mh-identity-handler-top): Docstring - editing. - - * mh-customize.el (mh-identity-list, mh-auto-fields-list) - (mh-identity-default, mh-identity-handlers): Synced docstrings - with manual. - -2005-02-03 Bill Wohler - - * mh-xemacs.el (define-behavior 'mh): Moved Ben's code here from - mh-e.el and added standard documentation. - - * mh-e.el: Received patch from Ben Wing to add - define-behavior on XEmacs. - -2005-01-28 Jeffrey C Honig - - * mh-customize.el (mh-invisible-header-fields-internal): Added - X-Evolution header added by Evolution mai client. - -2005-01-18 Bill Wohler - - * mh-customize.el (mh-invisible-header-fields-internal): Added - DomainKey-Signature (http://antispam.yahoo.com/domainkeys/). - There's a Comment field that goes with it, but I thought it was - too general to add. - -2005-01-06 Bill Wohler - - * mh-junk.el (mh-spamassassin-blacklist): Fixed typo to fix an - error when junking spamassassin mail when mh-junk-background is - turned on. - -2004-12-25 Satyaki Das - - * mh-utils.el (mh-show-unquote-From): Make the buffer writable - before trying to change it (closes SF #1089870). - - * mh-comp.el (mh-complete-word): Fix a typo in a variable - name (closes SF #1089870) - -2004-11-28 Jeffrey C Honig - - * mh-comp.el (mh-complete-word): Kill the *Completions* buffer in - any cases where we believe we are done with it. Not perfect, but - better than just leaving it around. - -2004-11-08 Satyaki Das - - * mh-acros.el (mh-funcall-if-exists): In XEmacs, presence of a - function at compile time doesn't guarantee its existence at run - time. So make the macro handle that situation better. - -2004-11-05 Satyaki Das - - * mh-acros.el (advice): Load advice, since it isn't loaded in - XEmacs causing compilation problems. - -2004-10-24 Satyaki Das - - * mh-index.el (mh-mairix-execute-search) - (mh-mairix-regexp-builder): Update the interface to mairix so that - it will work with versions of mairix 0.12 and later. - - * mh-funcs.el (mh-rmf-daemon): Avoid using - beginning-of-buffer since it clobbers the mark and it was pointed - out on the Emacs developers list to be the wrong thing to do. - - * mh-e.el (mh-inc-folder): Only remove the window on the show - buffer. This means if the user has BBDB enabled then the window - displaying BBDB information isn't clobbered. - (mh-refile-or-write-again): Don't use the function - interactive-p. There was a long thread on the Emacs developers - list where it was pointed out that it is incorrect to use this - function most of the time. - - * mh-comp.el (autoload): Don't set auto-mode-alist. This could - screw things up for users that don't use MH-E (closes SF #1032353). - -2004-10-13 Satyaki Das - - * mh-e.el (mh-refile-or-write-again): Generalize the function to - work on a range of messages (closes SF #1046330). - -2004-09-02 Satyaki Das - - * mh-e.el (mh-process-commands): The concurrent execution of mark - and refile can cause problems since both the commands change the - current folder. This change avoids that by getting rid of the - concurrency. Another change covers the corner case where we refile - messages to a previously empty folder. Before the modification - sequences weren't preserved even if the appropriate flag was - set. That is no longer the case. - -2004-08-26 Satyaki Das - - * mh-e.el (mh-get-new-mail): Also, update the unseen sequence from - disk. Otherwise, the new messages aren't highlighted. - - * mh-seq.el (mh-thread-inc): Fix a bug which appears when inc is - run in a narrowed folder. The user sequence notation was getting - lost. The change fixes that. - - * mh-e.el (mh-get-new-mail): Make inc more efficient by reusing - the existing user sequence notation and deleted/refiled notation. - -2004-08-24 Bill Wohler - - * mh-e.el (Version, mh-version): Added +cvs to release number. - -2004-08-24 Bill Wohler - - Released MH-E version 7.82. - - * MH-E-NEWS, README: Updated for release 7.82. - - * mh-e.el (Version, mh-version): Updated for release 7.82. - -2004-08-24 Bill Wohler - - * mh-init.el (mh-variant-set): Change MH to mh as that's what is - emitted by `mh-variant-mh-info' (closes SF #1014781). - (mh-variant-p): Add mu-mh to docstring. - -2004-08-23 Satyaki Das - - * mh-acros.el (mh-require-cl): Remove unneeded autoloads. - (require): Add an advice to the function so that at compile time - the uncompiled file is loaded. This avoids compilation problems - when built in the Emacs tree. - - * mh-mime.el (mh-identity-pgg-default-user-id): Defvar the - variable, to avoid compiler warnings. - - * mh-e.el (mh-seq): Load mh-seq since functions defined there are - used here. Without this, the state mh-seq.elc would be loaded. - - * mh-customize.el (mh-init, mh-identity): Load mh-init and - mh-identity at compile time manually, before the corresponding - stale elc files get autoloaded. - -2004-08-21 Bill Wohler - - * mh-e.el (Version, mh-version): Add +cvs to release number. - -2004-08-21 Bill Wohler - - Released MH-E version 7.81. - - * MH-E-NEWS, README: Updated for release 7.81. - - * mh-e.el (Version, mh-version): Updated for release 7.81. - -2004-08-21 Bill Wohler - - * release-utils (variable_changes): Check for checked-out - directory before proceeding. Remove temporary files. - Rename --variable-update flag to --variable-changes. - -2004-08-16 Mark D. Baushke - - * mh-mime.el (mh-toggle-mh-decode-mime-flag: New function. - * mh-e.el (mh-help-messages): Add [;] help string for it. - (mh-folder-mode-map): Add ";" key binding for it. - -2004-08-15 Satyaki Das - - * mh-acros.el (mh-defstruct): Distinguishing structures created - by mh-defstruct just based on the number of fields is not - sufficient, since both the mh-thread-message and - mh-thread-container structures have the same length. - -2004-08-15 Mark D. Baushke - - * mh-customize.el (mh-identity-handlers): Use ":default" instead of - "default" to avoid problems with "Default:" as a user defined field. - * mh-identity.el (mh-identity-field-handler): Ditto. - -2004-08-15 Bill Wohler - - * mh-e.el (Version, mh-version): Added +cvs to release number. - -2004-08-15 Bill Wohler - - Released MH-E version 7.4.80. - - * MH-E-NEWS, README: Updated for release 7.4.80. - - * mh-e.el (Version, mh-version): Updated for release 7.4.80. - -2004-08-15 Bill Wohler - - * mh-funcs.el, mh-gnus.el, mh-inc.el, mh-init.el, mh-junk.el, - mh-pick.el, mh-print.el, mh-xemacs.el: Added 2004 to Copyright. - - * mh-acros.el, mh-alias.el: Checkdoc fixes. - -2004-08-12 Satyaki Das - - * mh-acros.el (cl): Load cl in this file. That is all right, since - this file is only used at compile time, and so cl doesn't get - loaded at run time. This avoids problems with stale *.elc files - present in the Emacs source tree during compilation. - (mh-defstruct): Modify it to make it more CL like and in the - process simplify it a bit. This makes the argument list of the - constructor compatible with the previous version, thereby avoiding - a compilation error when an old version of mh-seq.elc is present. - - * mh-seq.el (mh-thread-id-container, mh-thread-get-message) - (mh-thread-get-message-container): Revert back to the CL style - of using keyword arguments, since the mh-defstruct now produces - code compatible to such usage. - -2004-08-11 Satyaki Das - - * mh-acros.el (mh-defstruct, mh-require-cl): Checkdoc fixes. - - * mh-utils.el (message-tokenize-header, message-fetch-field): Add - autoloads. - (mh-folder-completing-read): Make the folder completion look - better with CVS Emacs. - - * mh-init.el (mh-variant-set): Remove dead code. - -2004-08-11 Bill Wohler - - * *.el: Use the following at the top of each file which seems to - do a good job of suppressing compilation warnings in 21.3 and CVS - Emacs (21.4). This replaces (require 'cl) or (require - 'utils) (mh-require-cl) calls: - - (eval-when-compile (require 'mh-acros)) - (mh-require-cl) - -2004-08-10 Bill Wohler - - * release-utils (DESCRIPTION): Added one. - (FILES, SEE ALSO, VERSION): Deleted empty and incorrect sections. - - * mh-e.el (mh-colors-available-p): Call x-display-color-cells with - mh-funcall-if-exists since it no longer seems to be defined in - GNU Emacs 21.4. - -2004-08-10 Satyaki Das - - * mh-speed.el (mh-process-kill-without-query, mh-speed-flists): - Avoid a compiler warning in versions of Emacs where - process-kill-without-query is a deprecated function. - - * mh-seq.el (mh-thread-message, mh-thread-container): Use - mh-defstruct instead of defstruct. - (mh-thread-id-container, mh-thread-get-message-container) - (mh-thread-get-message): Use the slightly different structure - constructor function. - - * mh-acros.el (mh-defstruct): New macro which is a partial - replacement of the defstruct in CL. - (no-byte-compile): Don't compile the file since it isn't loaded at - run time, so efficiency isn't an issue. - - * mh-utils.el (mh-buffer-data): Use mh-defstruct instead of - defstruct. - -2004-08-09 Satyaki Das - - * mh-funcs.el, mh-junk.el, mh-print.el: Use mh-require-cl to avoid - compilation warnings in Emacs-21.3. - - * mh-acros.el (mh-require-cl): Add autoloads of CL functions used. - -2004-08-09 Bill Wohler - - * mh-customize.el (mh-show-use-xface-flag): Mention that `fetch' and - `curl' are supported as well. - -2004-08-08 Bill Wohler - - * mh-xemacs.el (mh-xemacs-has-toolbar-flag): Checkdoc fixes. - - * mh-mime.el (mh-display-with-external-viewer): Checkdoc fixes. - - * mh-identity.el (mh-identity-attribution-verb-end): Stripped - trailing space; checkdoc fixes. - - * mh-e.el (mh-restore-desktop-buffer): Checkdoc fixes. - - * mh-customize.el (mh-inc-spool-list) - (mh-compose-forward-as-mime-flag, defcustom): Stripped trailing - space; checkdoc fixes. - - * mh-comp.el (mh-reply): Stripped trailing space. - - * mh-unit.el (mh-unit-files): Added mh-acros.el and mh-gnus.el. - (mh-unit): Don't lm-verify pre-21.4. Save buffers before killing - since we might have done some editing. - - * import-emacs: Deleted. Functionality subsumed by release-utils. - - * release-utils: New script. Performs import-emacs functionality - and displays new and deleted options. - - * Makefile (import-emacs): Call release-utils instead of - import-emacs. - - * mh-funcs.el (mh-undo-folder): Removed deprecated `ignore' - argument. - - * mh-e.el (mh-scan-date-regexp): Deleted as Peter claims it is - obsolete. - (mh-folder-font-lock-keywords): Removed reference to deleted - variable `mh-scan-date-regexp'. - - * mh-customize.el (mh-auto-fields-prompt-flag): Made reference to - `mh-auto-fields-lists'. - (mh-forward-hook): Fixed docstring typo. - -2004-08-07 Bill Wohler - - * mh-acros.el: New file. Currently holds macros needed by - mh-customize.el but is planned to hold all macros to avoid - dependency problems when compiling. - - * mh-utils.el (mh-xemacs-flag): Defined in mh-customize.el now. - (mh-require-cl, mh-do-in-gnu-emacs, mh-do-in-xemacs) - (mh-funcall-if-exists, mh-make-local-hook, mh-mark-active-p): - Moved to new file mh-acros.el. - - * mh-customize.el: Require mh-acros and cl only when compiling and - mh-loaddefs at runtime instead of mh-utils. - (mh-xemacs-flag): Define it here instead of mh-utils.el. - - * Makefile (MH-E-SRC): Added mh-acros.el. - - * mh-gnus.el (default-enable-multibyte-characters): Don't define - any more. It doesn't seem to be needed. - - * mh-customize.el (mh-junk-background): New variable. If on, spam - programs are run in background. Running in foreground can be slow. - Defaults to nil to spare machines with little memory. - - * mh-junk.el (mh-spamassassin-blacklist, mh-bogofilter-blacklist) - (mh-bogofilter-whitelist, mh-spamprobe-blacklist) - (mh-spamprobe-whitelist): Use new option mh-junk-background. - -2004-07-25 Satyaki Das - - * mh-utils.el (mh-folder-completing-read): In recent CVS Emacs, - the first letter of the possible choices in the completion buffer - is highlighted. The change is needed for this feature to work - during folder name completion. This is not entirely sufficient, - since the leading "+" in folder names is still mishandled. A patch - is required in Emacs itself to address that. - -2004-07-22 Mark D. Baushke - - * mh-e.el (recursive-load-depth-limit): Move - recursive-load-depth-limit code to ... - * mh-utils.el (recursive-load-depth-limit): ... here to avoid - problems compiling mh-utils.el and mh-alias.el with gnus-5.10.6 - under emacs-21.1. Use eval-and-compile instead of eval-when. - -2004-07-20 Bill Wohler - - * mh-customize.el (mh-invisible-header-fields-internal): Added - header fields emitted by T-Mobile picture phones (X-Mms-*, and - commented out X-Operator field saying it's like X-Mailer). - -2004-07-12 Bill Wohler - - * mh-gnus.el: Set local variables indent-tabs-mode and - sentence-end-double-space to nil. - - * mh-customize.el: Checkpoint from option docstring updates and - manual synchronization from last summer. For the options listed - below, docstring was usually completely rewritten. Use "on" - instead of "t" in docstring to match what is seen in customization - buffer. Use headline capitalization. Standardize on "Auto-detect" - text when option has that capability. - (mh): Since we work on more than one type of Emacs, use Emacs - instead of GNU Emacs. Prefer GNU mailutils over GNU Mailutils. - (mh-variant): s/Autodetect at startup/Auto-detect/. - (mh-alias-insertion-location): s/Sorted - alphabetically/Alphabetical/. s/At the top of file/Top/. s/At the - bottom of file/Bottom/. - (mh-alias-local-users-prefix): s/Use login instead of real - name/Use Login/. - (mh-identity-list): Sorted values by fields, attribution, - signature, GPG key. - (mh-auto-fields-list): Missing quote. - (mh-compose-insertion): s/Use Gnus/Gnus/. s/Use mhn/mhn/. - (mh-compose-space-does-completion-flag): s/SPACE//. - (mh-extract-from-attribution-verb): Since we have French, added - German too ;-). - (mh-letter-complete-function): Mention default in docstring. - (mh-invisible-header-fields-internal): Added X-ELNK-Trace from - Earthlink. - (mh-alias-flash-on-comma, mh-alias-insert-file) - (mh-alias-passwd-gecos-comma-separator-flag) - (mh-recenter-summary-flag, mh-default-folder-for-message-function) - (mh-default-folder-must-exist-flag, mh-index-program) - (mh-index-ticked-messages-folders, mh-ins-buf-prefix) - (mh-delete-yanked-msg-window-flag, mh-identity-default): See - summary above. - - * mh-init.el (mh-variant-set, mh-sys-path, mh-variant-mu-mh-info): - Prefer GNU mailutils over GNU Mailutils MH. - - * mh-comp.el (sc-cite-original, mh-smail, mh-smail-batch) - (mh-edit-again, mh-extract-rejected-mail, mh-forward) - (mh-smail-other-window, mh-reply, mh-send, mh-send-other-window): - Use `mh-send' instead of \\[mh-send]] since links in the docstring - are more useful than a key sequence in these cases. Use "See also" - instead of "See also documentation for". - - Merged in 7.4.4 changes, described below. - - * mh-e.el (Version, mh-version): Set to 7.4.4+cvs. - -2004-07-10 Bill Wohler - - Released MH-E version 7.4.4. - - * MH-E-NEWS, README: Updated for release 7.4.4. - - * mh-e.el (Version, mh-version): Updated for release 7.4.4. - - This patch release contains the following patches: - - * mh-xemacs.el: New file from concatenation of mh-xemacs-compat.el - and mh-xemacs-icons.el which were removed since their names - exceeded DOS 8+3 limits. - - * Makefile: - (mh-e-autoloads.el): Add target to make `mh-e-autoloads.el', a - file containing usual entry commands into MH-E to be used for users - installing MH-E separately from Emacs. - (XEMACS_LOADDEFS_FILE): New. Used to generate mh-loaddefs.el - in XEmacs. - (XEMACS_LOADDEFS_COOKIE): Ditto. - (XEMACS_LOADDEFS_PKG_NAME): Ditto. - (XEMACS_OPTIONS): Add '-no-autoloads' to give a cleaner build - environment. - (MH-E-SRC): Moved mh-xemacs.el to new variable MH-E-XEMACS-SRC. - (MH-E-XEMACS-SRC): New variable to hold XEmacs source files. - (MH-E-XEMACS-OBJ): New variable to hold XEmacs object files. - (clean): Moved XEmacs-specific code to clean-xemacs. - (xemacs): Added clean-xemacs prerequisite. Moved down to XEmacs - section of file. Add target to build mh-loaddefs.el in XEmacs. - (loaddefs-xemacs): New rule to build mh-loaddefs.el in XEmacs. - (clean-xemacs): New target to remove XEmacs-specific files. - (compile-xemacs): New. It allows for the '-no-autoloads' option - and byte-compiles all the source files with a single instance of - XEmacs. - (dist): Added $(MH-E-XEMACS-SRC) to tarball. - (AUTO_PRELOADS): Removed, in favor of 'AUTOLOAD_PACKAGE_NAME' and - 'AUTOLOAD_FILE'. - (AUTOLOAD_PACKAGE_NAME): New. - (AUTOLOAD_FILE): New. - (all): Don't set $EMACS_HOME if building with XEmacs. - (xemacs): Use 'compile-xemacs' instead of 'compile'. - (auto-autoloads.elc): Use new $AUTOLOAD_* vars and allow for - '-no-autoloads'. - (custom-load.elc): Allow for '-no-autoloads'. - - * mh-e.el: Don't require mh-xemacs-compat which no longer exists. - The XEmacs stuff gets required by mh-customize.el which is - required by mh-utils.el which is required by mh-e.el. This all - happens before mh-xemacs-compat was required, so all should be - well. - (mh-restore-desktop-buffer): Move from desktop.el. Add Parameters. - (mh-restore-desktop-buffer): Delete with-no-warnings. - (mh-folder-mode): Bind desktop-save-buffer to t. - (Courtesy Lars Hansen). - - * mh-alias.el (mh-assoc-ignore-case): New macro to use - assoc-string when available (Emacs 21.4+); assoc-ignore-case - otherwise. - (mh-alias-reload, mh-alias-expand, - mh-alias-minibuffer-confirm-address): Use it. - - * mh-seq.el: Added mh-autoload to mh-read-seq-default. - - * mh-utils.el (mh-require-cl): The Emacs coding conventions - require that the cl package not be required at runtime. However, - the cl package in versions of Emacs prior to 21.4 left cl routines - in their macro expansions. Use mh-require-cl to provide the cl - routines in the best way possible (closes SF #930012). - (require 'mouse): To shush compiler. - - Use new function mh-require-cl throughout. - - Add arch taglines (courtesy Miles Bader). - - * mh-unit.el (mh-unit-files): Replaced mh-xemacs-compat.el and - mh-xemacs-icons.el with mh-xemacs.el. - - * import-emacs: Also grab the ChangeLog. - - * *.pbm: Regenerated using GIMP to be consistent with other Emacs - icons. - 1. Edit .xpm image in GIMP. - 2. Image > Mode > Indexed. Check Use Black/White Palette and No - Color Dithering. - 3. File > Save As file.xbm. - 4. Run xbmtopbm < file.xbm > file.pbm. - Thanks to jan.h.d@swipnet.se for the help. - -2004-07-07 Stephen Gildea - - * mh-customize.el (mh-invisible-header-fields-internal): - Add X-Greylist, X-Source*, and X-WebTV-Signature. - Replace specific X-Spam-* headers with general pattern. - -2004-06-15 Bill Wohler - - * README: Vladimir Ivanovic reports that mh-rmail works with - XEmacs 21.5.17, so updated requirements text accordingly (closes - SF #644321). - -2004-05-12 Satyaki Das - - * mh-utils.el (mh-mail-header-end): Replace call to - rfc822-goto-eoh with something that allows From_ lines in the mail - header. - -2004-04-26 Lars Hansen - - * mh-e.el (mh-folder-mode): Bind desktop-save-buffer to t. - -2004-04-22 Lars Hansen - - * mh-e.el (mh-restore-desktop-buffer): Delete with-no-warnings. - -2004-04-21 Lars Hansen - - * mh-e.el (mh-restore-desktop-buffer): Move from desktop.el. - Add Parameters. - -2004-04-14 Bill Wohler - - * mh-utils.el (mh-show-mouse): s/EVENT/event/. Thanks to John Paul - Wallington for pointing this out. - -2004-04-12 Satyaki Das - - * mh-e.el (mh-folder-size-flist): Add -showzero option so that the - parsing code doesn't get confused by the presence of -noshowzero - in the user's .mh_profile (closes SF #933954). - -2004-04-07 Satyaki Das - - * mh-mime.el (mh-insert-mime-button) - (mh-insert-mime-security-button): Add evaporate property to - overlays used in MIME part buttons. This avoids problems with - CVS Emacs. - -2004-03-16 Satyaki Das - - * mh-e.el (mh-folder-from-address): Go to the end of buffer if the - re-search-forward fails (closes SF #917096). - -2004-02-02 Satyaki Das - - * mh-customize.el (mh-compose-forward-as-mime-flag): New user - customizable variable that controls whether messages are forwarded - as MIME attachments (closes SF #827203). - - * mh-comp.el (mh-forward): Call forw with -mime option only if - mh-compose-forward-as-mime-flag is non-nil. - -2003-12-26 Jeffrey C Honig - - * mh-junk.el (mh-junk-blacklist, mh-junk-whitelist) - (mh-spamassassin-blacklist, mh-spamassassin-blacklist) - (mh-spamassassin-blacklist, mh-spamassassin-whitelist) - (mh-spamassassin-whitelist, mh-bogofilter-blacklist) - (mh-spamprobe-blacklist): Add progress messages. Change "Couldn't" - to "Unable" in error messages. Run bogofilter and spamprobe in - the foreground to prevent a large number of processes from - swamping the system. - -2003-12-25 Satyaki Das - - * mh-e.el (mh-prompt-for-refile-folder): Marking the whole folder - and then refiling all messages throws an error, since this - function expects point to be on a valid scan line. The change - relaxes this requirement, thereby avoiding the above problem. - -2003-12-14 Satyaki Das - - * mh-comp.el (mh-ascii-buffer-p): New function that checks if a - buffer is entirely composed of ASCII. - (mh-send-letter): Encode the draft if it contains non-ASCII - characters. - -2003-12-12 Satyaki Das - - * mh-customize.el (mh-invisible-headers): Keep only unique fields - in list of header fields to hide. This avoids problems in XEmacs. - -2003-12-10 Satyaki Das - - * mh-seq.el (mh-thread-print-scan-lines): The imenu index was not - getting created for threaded index buffers. The change fixes this. - - * mh-index.el (mh-index-insert-folder-headers): Always create the - imenu index. - (mh-index-create-imenu-index): Set which-func-mode to t. If - which-function-mode is turned on after the folder buffer has been - prepared, display of the folder info was being inhibited. The - change fixes that. - -2003-12-09 Satyaki Das - - * mh-comp.el (mh-letter-mode): Setup mh-mail-header-separator - based on draft contents. - (mh-letter-mode, mh-letter-mail-header-end-marker) - (mh-letter-header-end): Remove use of the variable - mh-letter-mail-header-end-marker. Instead use - mh-mail-header-separator. This avoids problems in font locking - draft buffers (closes SF #855479). - -2003-12-09 Satyaki Das - - * mh-index.el (mh-index-insert-folder-headers): Modified so that - imenu--index-alist is updated. - (mh-index-create-imenu-index): New function that generates an - index usable by imenu. This adds which-func-mode support to index - folders (closes SF #855520). - - * mh-e.el (which-func, which-func-modes): Tell which-func that - mh-folder-mode supports it. - (mh-folder-mode): Add support for imenu. - -2003-11-22 Peter S Galbraith - - * Makefile: renamed mh-startup.el to mh-e-autoloads.el - - * README: renamed mh-startup.el to mh-e-autoloads.el - - * .cvsignore: Added mh-e-autoloads.el - -2003-11-18 Bill Wohler - - Released MH-E version 7.4.3. - - * MH-E-NEWS, README: Updated for release 7.4.3. - - * mh-e.el (Version, mh-version): Updated for release 7.4.3. - - This patch release contains the following two patches: - - * mh-identity.el (mh-identity-make-menu): Removed condition on - mh-auto-fields-list. Use it to enable or disable menu item - instead. - - * mh-customize.el (mh-identity-list): Removed defvar and moved - defcustom before mh-auto-fields-list so that defvar wouldn't - clobber user's customization settings. - -2003-11-17 Jeffrey C Honig - - * mh-print.el (mh-print-msg): Do not print a message on deprecated - usage, the bindings have been removed. - - * mh-e.el (mh-folder-mode-map): Remove "l" binding for - mh-print-msg. - - * mh-utils.el (mh-show-mode-map): Remove "l" binding for - mh-print-msg. - -2003-11-16 Satyaki Das - - * mh-comp.el (mh-beginning-of-word): Use the function - mh-mail-abbrev-make-syntax-table instead of the function - mail-abbrev-make-syntax-table. - - * mh-gnus.el (mh-mail-abbrev-make-syntax-table): Add a wrapper - function that calls mail-abbrev-make-syntax-table if available. - This is needed so that MH-E built with CVS Emacs will work with - released versions of Emacs21 and vice versa. - -2003-11-14 Peter S Galbraith - - * mh-customize.el (mh-invisible-header-fields-internal): Add - "X-NAI-Spam-" and "X-Spam-Report:". - -2003-11-14 Mark D. Baushke - - * mh-customize.el (mh-invisible-header-fields-internal): - Add X-AntiAbuse and X-MailScanner. - (Patch from Stephen Gildea.) - -2003-11-13 Peter S Galbraith - - * mh-identity.el (mh-identity-handler-attribution-verb): New - function. A new Identity handler for the attribution verb (e.g. - "wrote:") to allow for different identities to use different - languages. - (mh-identity-insert-attribution-verb): New function. Insert the - attribution verb, placing special markers so it can be deleted and - replaced later. - (mh-identity-attribution-verb-start): New variable. Holds the - marker for the start of the attribution verb. - (mh-identity-attribution-verb-end): New variable. Holds the - marker for the end of the attribution verb. - - * mh-customize.el (mh-identity-handlers): Add new - ":attribution-verb" tag for the attribution-verb handler. - (mh-identity-list): Idem. - - * mh-comp.el (mh-yank-cur-msg): Insert attribution verb using - mh-identity-insert-attribution-verb. - (mh-extract-from-attribution): Extract only the name from the From - line, without appending `mh-extract-from-attribution-verb' since - markers need to be inserted around that now. - -2003-11-12 Bill Wohler - - * mh-e.el (mh-rmail, mh-nmail): Well, actually, we run in both GNU - Emacs and XEmacs, so removed the "GNU" in the docstrings unless - one is strictly talking about GNU Emacs. - - * mh-comp.el (mh-smail, mh-smail-batch, mh-smail-other-window): - Ditto. - -2003-11-11 Bill Wohler - - * mh-customize.el (mh-customize): Minor docstring change. - (mh, mh-e): The short description for MH-E is: The GNU Emacs - Interface to the MH Mail System. Therefore, updated docstrings - accordingly. - - * mh-comp.el (mh-smail, mh-smail-batch, mh-smail-other-window): - Ditto. - - * mh-e.el (mh-rmail, mh-nmail): Ditto. - -2003-11-10 Satyaki Das - - * mh-mime.el (mh-mml-to-mime): In case errors happen in - mml-to-mime, restore contents of the draft buffer (closes SF - #839303). - -2003-11-07 Bill Wohler - - * mh-customize.el (mh-letter-mode-hook): Moved to mh-sending-mail - group (where it is now documented in the manual). - (mh-pick-mode-hook): Moved to mh-index group (where it is now - documented in the manual). - - * mh-loaddefs.el: Deleted per our discussion on mh-e-devel. No - more conflicts! No more check-ins! Anyone pulling CVS MH-E is - expected to compile. This file shall be added to the tarball so - that users of the distribution are not. - -2003-11-07 Mark D. Baushke - - * mh-loaddefs.el: Regenerated. - - * mh-customize.el (mh-forward-hook): Define new hook. - * mh-comp.el (mh-forward): Use it. - -2003-11-07 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-utils.el (mh-show-toggle-mime-buttons) - (mh-show-display-with-external-viewer): New interactive functions - callable from the show buffer. - (mh-show-mime-map): Add bindings for "K t" and "K e". - (mh-show-msg): Propagate change to - mh-display-buttons-for-inline-parts-flag to the show buffer. - - * mh-mime.el (mh-display-with-external-viewer): New interactive - function to display MIME parts with external viewer (closes SF - #839318). - - * mh-e.el (mh-folder-mode): Make the variable - mh-display-buttons-for-inline-parts-flag buffer-local so that - display of MIME buttons can be toggled. - (mh-toggle-mime-buttons): New interactive function to toggle - display of MIME buttons. - (mh-mime-map): Modified to add bindings for "K t" and "K e". - -2003-11-04 Steve Youngs - - * Makefile (XEMACS_LOADDEFS_FILE): New. Used to generate - mh-loaddefs.el in XEmacs. - (XEMACS_LOADDEFS_COOKIE): Ditto. - (XEMACS_LOADDEFS_PKG_NAME): Ditto. - (xemacs): Add target to build mh-loaddefs.el in XEmacs. - (clean-xemacs): Remove `mh-loaddefs.el*'. - (loaddefs-xemacs): New rule to build mh-loaddefs.el in XEmacs. - -2003-11-02 Peter S Galbraith - - * mh-init.el (mh-variant-set-variant): Reset `mh-x-mailer-string' - when we select an MH variant. - -2003-11-02 Jeffrey C Honig - - * mh-loaddefs.el: Regenerated. - - * mh-funcs.el (mh-print-msg): Move to mh-print.el. - - * mh-e.el (mh-folder-mode-map): Add mh-print-msg ("l") back, it - will print a message that this usage is deprecated. - - * mh-print.el (require, mh-ps-print-msg, mh-ps-print-msg-file): - Require mh-funcs for mh-note-printed. PS print functions were not - setting the printed notation. Move mh-print-msg here for - consistency. Print message if mh-print-msg invoked via deprecated - key binding. - -2003-11-01 Peter S Galbraith - - * Makefile: Add target to make `mh-startup.el', a file containing - usual entry commands into MH-E to be used for users installing - MH-E separately from Emacs. - - * README: Document the above for users. - -2003-10-29 Jeffrey C Honig - - * mh-utils.el (mh-show-ps-print-map): Add "?" and "l" to - mh-show-ps-print-map. - - * mh-e.el (mh-ps-print-map, mh-help-messages): Add "?" and "l" to - mh-ps-print-map. Add "l" to help message. - -2003-10-27 Bill Wohler - - * Makefile (MH-E-SRC): Moved mh-xemacs.el to new variable - MH-E-XEMACS-SRC. - (MH-E-XEMACS-SRC): New variable to hold XEmacs source files. - (MH-E-XEMACS-OBJ): New variable to hold XEmacs object files. - (clean): Moved XEmacs-specific code to clean-xemacs. - (xemacs): Added clean-xemacs prerequisite. Moved down to - XEmacs section of file. - (clean-xemacs): New target to remove XEmacs-specific files. - (compile-xemacs): Added $(MH-E-XEMACS-SRC) prerequisite. - (dist): Added $(MH-E-XEMACS-SRC) to tarball. - -2003-10-27 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-index.el (mh-indexer-choices): Remove option for the non-free - glimpse indexer (closes SF #831276). - (mh-glimpse-binary, mh-glimpse-directory) - (mh-glimpse-execute-search, mh-glimpse-next-result): Functions - and variables to implement glimpse support are removed. - - * mh-customize.el (mh-index-program): Remove option for glimpse. - -2003-10-24 Satyaki Das - - * mh-customize.el: Remove top-level test for toolbar enabled - XEmacs since it is not needed. - (mh-tool-bar-define): Add test for XEmacs toolbar in the functions - mh-toolbar-init, mh-tool-bar-letter-buttons-set and - mh-tool-bar-folder-buttons-set. This enables proper compilation - irrespective of whether the XEmacs was built with toolbar support - or not. - - * mh-comp.el (mh-letter-mode): Remove conditional since it is not - needed. - - * mh-e.el (mh-folder-mode): Same as above. - - * mh-utils.el (mh-show-mode): Same as above. - - * mh-xemacs.el (mh-xemacs-icon-map): Remove condition on toolbar - presence since we want the build to work if XEmacs without - toolbars is used during compilation. - -2003-10-23 Bill Wohler - - * mh-customize.el: The Great Reorganization. Sorted groups - alphabetically. Aligned variables in customization groups with - manual sections. Group docstrings changed to match manual chapter - titles. - -2003-10-22 Satyaki Das - - * mh-speed.el (timer): Avoid compiler warning in XEmacs. - -2003-10-22 Steve Youngs - - * Makefile (XEMACS_OPTIONS): Add '-no-autoloads' to give a cleaner - build environment. - (AUTO_PRELOADS): Removed, in favor of 'AUTOLOAD_PACKAGE_NAME' and - 'AUTOLOAD_FILE'. - (AUTOLOAD_PACKAGE_NAME): New. - (AUTOLOAD_FILE): New. - (all): Don't set $EMACS_HOME if building with XEmacs. - (xemacs): Use 'compile-xemacs' instead of 'compile'. - (auto-autoloads.elc): Use new $AUTOLOAD_* vars and allow for - '-no-autoloads'. - (custom-load.elc): Allow for '-no-autoloads'. - (compile-xemacs): New. It allows for the '-no-autoloads' option - and byte-compiles all the source files with a single instance of - XEmacs. - - * mh-e.el (mh-folder-mode): Only load the toolbar in XEmacs if - toolbar support is available. - - * mh-comp.el (mh-letter-mode): Only load the toolbar in XEmacs if - toolbar support is available. - - * mh-customize.el: Require 'mh-xemacs' at toplevel when - 'mh-xemacs-flag' is non-nil. - Wrap all the toolbar code in a test that is true if using - GNU/Emacs or a toolbar-enabled XEmacs. - - * mh-print.el (mh-ps-spool-a-msg): Comment out - `clean-message-header-flag' because it isn't used anywhere. - - * mh-utils.el (mh-show-mode): Only load the toolbar in XEmacs if - toolbar support is available. - - * mh-xemacs.el: Autoload `regexp-opt', `customize-group', - `view-mode', `with-electric-help', `pp', `sort-numeric-fields', - `reverse-region', and `goto-address' at compile time. - (mh-xemacs-has-toolbar-flag): New. This is non-nil when XEmacs - has toolbar support. - (mh-xemacs-toolbar-*-icon): Use it. - -2003-10-21 Mark D. Baushke - - * mh-identity.el (mh-identity-field-handler): Fields that begin - with ":" must have an mh-identity-handler defined or the user - gets an error. - -2003-10-17 Peter S Galbraith - - * mh-customize.el (mh-identity-list): This change affects users! - The keyword "signature" becomes ":signature". The recently added - keyword "pgg-default-user-id" becomes ":pgg-default-user-id". - (mh-auto-fields-list): The keyword "Identity" becomes ":identity". - (mh-identity-handlers): Idem for signature and pgg-default-user-id. - - * mh-comp.el (mh-insert-auto-fields): Idem for Identity. - -2003-10-17 Peter S Galbraith - - * mh-xemacs.el: Add eval-and-compile call to (load "toolbar" t t) to - make sure `toolbar-make-button-list' is defined. We can't use - require because Emacs doesn't have this library. - -2003-10-16 Bill Wohler - - * mh-customize.el (mh-signature-file-name) - (mh-letter-insert-signature-hook): Merge docstring with manual. - - * mh-comp.el (mh-file-is-vcard-p): Checkdoc fix. - (mh-insert-signature): Merge docstring with manual. - - * mh-customize.el (mh-junk): Changed manual link in defgroup from - Customizing mh-e to Junk. - (mh-junk-function-alist): Moved SpamAssassin to first in list on - the hunch that it is the most popular and should be chosen if - other anti-spam programs exist. - (mh-junk-mail-folder): Since the variable can accept values other - than folder names, renamed to mh-junk-disposition to more - accurately reflect the content. Merge docstring with manual. - (mh-junk-program): Moved SpamAssassin to the top of the menu for - the same reason presented in mh-junk-function-alist. Also, fixed - case of spam programs to match official usage. Merge docstring - with manual. - - * mh-junk.el (mh-junk-blacklist): - s/mh-junk-mail-folder/mh-junk-disposition/. Merge docstring with - manual. - (mh-junk-whitelist): Merge docstring with manual. - (mh-bogofilter-blacklist): No longer suggest using automatic - classification so use -s instead of -Ns. - (mh-bogofilter-whitelist): No longer suggest using automatic - classification so use -n instead of -Sn. - (mh-spamassassin-blacklist, mh-spamassassin-whitelist): Merge - docstring with manual. Moved spamassassin functions to top of file - so functions appear in same order that they are presented in menu. - -2003-10-09 Peter S Galbraith - - * mh-customize.el (mail-citation-hook): Moved from mh-comp.el and - made into a defcustom. - -2003-10-09 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-comp.el (mh-get-header-field): Add autoload cookie. - - * mh-utils.el (mh-show-ps-print-toggle-mime) - (mh-show-ps-print-toggle-color, mh-show-ps-print-toggle-faces) - (mh-show-ps-print-msg-file, mh-show-ps-print-msg) - (mh-show-ps-print-msg-show): New interactive functions callable - from the show buffer. - (mh-show-ps-print-map): New key map for printing. - - * mh-e.el (mh-folder-mode-map): Remove key binding for - mh-print-msg. - (mh-ps-print-map): Add new key map for printing. - - * Makefile (MH-E-SRC): Add mh-print.el. - -2003-10-07 Satyaki Das - - * mh-utils.el (mh-x-image-url-fetch-image): In XEmacs, - make-temp-file is not present. So to avoid security problems, use - a temporary file in the user's home directory. This avoids issues - in creating files in a world-writable directory. - - * mh-mime.el (mh-signature-highlight): In Emacs, arrange for the - overlay to be freed when it is no longer needed. Also, implement - signature highlighting in XEmacs. - -2003-10-05 Satyaki Das - - * mh-mime.el (mh-mime-display, mh-mm-inline-message): Respect the - value of `mm-verify-option' and `mm-decrypt-option'. - (mh-mime-display-security): Rearrange code a bit to avoid too many - new lines being inserted when message verification/decryption is - carried out while the message is being read. Also use the - point-m{in|ax}-marker functions to make the function easier to read. - (mh-mime-security-press-button): Extend the function so that the - user can verify/decrypt messages while reading them. - - * mh-gnus.el (mm-possibly-verify-or-decrypt): Added to avoid - compiler warning with old Gnus. - - * mh-utils.el (mh-x-image-url-sane-p): New function which checks - if the URL in X-Image-URL is something we can handle. - (mh-x-image-url-display): Don't display image if the URL looks - malformed. - -2003-10-04 Mark D. Baushke - - * mh-comp.el (mh-letter-menu): Simplify menu heading. - -2003-10-03 Mark D. Baushke - - * mh-mime.el (mh-mml-query-cryptographic-method): Avoid - revisionist history and still provide a good default. - - * mh-comp.el (mh-letter-menu): Remove the Disable Security - parenthetical comment. - - * mh-loaddefs.el: Regenerated. - - * mh-customize.el (mh-mml-method-default): What method should be - used in secure directives. - - * mh-mime.el (mh-secure-message): New function used to generate - the mml security tags. - (mh-mml-unsecure-message): New wrapper function around - mml-unsecure-messages. - (mh-mml-secure-message-sign-pgpmime): Remove function. - (mh-mml-secure-message-encrypt-pgpmime): Ditto. - (mh-mml-cryptographic-method-history): New variable. - (mh-mml-query-cryptographic-method): New function. - (mh-mml-secure-message-encrypt): Ditto. - (mh-mml-secure-message-signencrypt): Ditto. - (mh-mml-secure-message-sign): Ditto. - - * mh-comp.el (mh-letter-menu, mh-letter-mode-help-messages) - (mh-letter-mode-map): Update to use new functions. - -2003-09-26 Satyaki Das - - * mh-seq.el (mh-interactive-range): The function has been - extended so that it now takes a default result to return if no - interactive prefix arg is given and no region is active. - - * mh-e.el (mh-add-sequence-notation): If transient-mark-mode is - on, then the active region is deactivated based on whether a user - sequence or a internal sequence is being notated. The change - removes this inconsistency. - (mh-catchup, mh-folder-map): A new interactive function to mark - messages as read has been added and bound to "F c" in the folder - mode. - - * mh-utils.el (mh-show-catchup, mh-show-folder-map): New - interactive function callable from show mode buffers has been - bound to "F c". - -2003-09-24 Bill Wohler - - * mh-customize.el (mh-clean-message-header-flag) - (mh-invisible-header-fields-default, mh-invisible-header-fields): - Merge docstring with manual. - -2003-09-24 Mark D. Baushke - - * mh-junk.el (mh-junk-blacklist): Junked messages should be put - into the mh-seen-list to avoid propagating the unseen sequence - into the spam folder. - - * mh-loaddefs.el: Regenerated. - - * mh-mime.el (mh-mml-secure-message-sign-pgpmime): Add an optional - dontsign argument to remove an existing secure message directive. - Update the docstring -- this function does not allow for - encrypt/sign, just sign directives. - - * mh-mime.el (mh-mml-secure-message-sign-pgpmime): Use - mml-insert-tag directly to provide a sender if - mh-identity-pgg-default-user-id is set. - (mh-mml-secure-message-encrypt-pgpmime): Use mml-insert-tag - directly to provide a sender if this message is to be both signed - and encrypted and mh-identity-pgg-default-user-id is set. - -2003-09-23 Bill Wohler - - * mh-alias.el (Commentary): Removed as it is now in the manual. - (mh-alias-system-aliases): Moved here from mh-customize.el. By - definition, "system" definitions are not user-visible, and user - filenames are in the Aliasfile: profile component, so this - variable really shouldn't be a defcustom. - (mh-alias-tstamp, mh-alias-filenames, mh-alias-reload) - (mh-alias-add-alias, mh-alias-grab-from-field) - (mh-alias-add-address-under-point, mh-alias-apropos): Merge - docstring with manual. - (mh-alias-reload-maybe): Minor comment update. - (mh-alias-insert-file): Merge docstring with manual. Removed - "[press TAB]" from prompt since users should know about completion - and space can be used as well. - (mh-alias-for-from-p): No longer returns a surprising result (t if - there was **not** an alias for the From field) if the From header - field is missing. This function now returns what you would expect - a function of this name to return. Renamed from - mh-alias-from-has-no-alias-p since negatives in the function name - make logic harder to follow. - (mh-alias-add-alias-to-file): Merge docstring with manual. - Improved verbiage of prompt. Aliases are now inserted "[b]efore" - or "[a]fter" the existing alias instead of "[i]nsert" or - "[a]ppend." Note how the new usage flows better. - - * mh-customize.el (mh-alias): Changed manual link in defgroup from - Customizing mh-e to Aliases. - (mh-alias-grab-from-field button): mh-alias-from-has-no-alias-p - renamed to mh-alias-for-from-p and no longer returns surprising - value if there isn't a From field. Therefore, enable button if - there is a From header field and mh-alias-for-from-p returns nil. - (mh-letter-complete-function) - (mh-alias-completion-ignore-case-flag, mh-alias-flash-on-comma) - (mh-alias-insert-file, mh-alias-insertion-location) - (mh-alias-local-users, mh-alias-local-users-prefix) - (mh-alias-passwd-gecos-comma-separator-flag): Merge docstring with - manual. - (mh-alias-system-aliases): Moved to mh-alias.el. - - * mh-comp.el (mh-letter-complete-function-alist): Removed comment - about making this customizable since I didn't think it seemed - appropriate in the manual. - (mh-letter-complete): Merge docstring with manual. - -2003-09-23 Satyaki Das - - * mh-speed.el (mh-speed-flists): When exiting emacs, don't ask if - the flists process should be killed. - - * mh-e.el (mh-folder-message-menu): Enable undo menu entry only - if something can be undone. - - * mh-customize.el (undo): Enable undo button only if something - can be undone. - -2003-09-22 Peter S Galbraith - - * mh-customize.el (mh-identity-handlers): New defcustom. Alist of - Handler functions for mh-identity (downcased) fields. - (mh-identity-list): Add support for pgg-default-user-id. - - * mh-identity.el (mh-insert-identity): Modified to use - `mh-identity-handlers', adding hacking flexibility for those who - might need it. - (mh-identity-field-handler): New function. Return the handler for - a FIELD or nil if none set. The field name is downcased. - (mh-identity-handler-gpg-identity): New function; handler for pgg - pgp identities. It sets a buffer-local value for - `mh-pgg-default-user-id' which must be handled by mh-send-letter. - (mh-identity-pgg-default-user-id): New buffer-local variable to - hold the requested key ID. - (mh-identity-handler-signature): New function; handler t insert - and remove signature files. - (mh-identity-handler-default): New function; the default handler - to insert or remove generic field. - (mh-identity-handler-top): Insert a field at the top of the - header. - (mh-identity-handler-bottom): Insert a field at the bottom of the - header. - (mh-header-field-delete): Make more robust wrt the field having a - trailing colon or not. - (mh-identity-make-menu): Add a "Customize Identities" menu entry. - - * mh-loaddefs.el: Regenerated. - -2003-09-21 Peter S Galbraith - - * mh-init.el (mh-variant-set): Bug fix for mh-variant long names - with version numbers. - - * mh-e.el (mh-scan-format): patch from Sergey Poznyakoff. - GNU mailutils now supports the %(decode) format - -2003-09-20 Satyaki Das - - * mh-gnus.el (mh-mm-text-html-renderer): New function to query - which HTML renderer is being used by Gnus. - - * mh-mime.el (mh-signature-highlight): Renderers used to display - HTML parts garble the signature separator in various ways. The - function has been modified to take that into account. - (mh-mime-display-single, mh-mm-display-part): Pass the new - optional argument to `mh-signature-highlight'. - -2003-09-19 Mark D. Baushke - - * mh-mime.el (mh-have-file-command, mh-file-mime-type): Made an - mh-autoload as they are used in mh-comp.el. - - * mh-loaddefs.el: Regenerated. - -2003-09-18 Peter S Galbraith - - * mh-comp.el (mh-insert-fields): Make sure field has a colon. - -2003-09-18 Satyaki Das - - * mh-seq.el (mh-toggle-tick): Don't hardcode the name of the tick - sequencence in the function. This would have caused improper - highlighting of the tick sequence if the user had changed its - name. - -2003-09-15 Satyaki Das - - * mh-e.el (mh-folder-message-menu): Fix a little bug which shows - up as a problem during compilation (closes SF #806577). - -2003-09-15 Mark D. Baushke - - * mh-customize.el (mh-invisible-header-fields-internal): Added - a new field for GNU mailutils per Sergey Poznyakoff. - -2003-09-09 Satyaki Das - - * mh-utils.el (vcard): Unconditionally load vcard.el, if - available, so that vcards are always inlined. - -2003-09-09 Peter S Galbraith - - * mh-mime.el (mh-file-mime-type-substitutions): Add entry to - convert text/plain .vcf files to text/x-vcard. - (mh-mime-content-types): Add text/x-vcard. - -2003-09-09 Bill Wohler - - * mh-comp.el (mh-rejected-letter-start): Added strings for qmail - and exim (addresses SF #404965). - -2003-09-09 Satyaki Das - - * mh-gnus.el (mm-inline-text-vcard): Make vcard display work with - Gnus-5.9. The extra file vcard.el is still needed. - - * mh-mime.el (mh-signature-highlight): New function that - highlights message signatures. - (mh-mm-display-part, mh-mime-display-single): Highlight signatures - using `mh-signature-highlight' (closes SF #802722). More work is - needed for XEmacs. - (mh-mime-display): Highlight signature in non-MIME email too. - - * mh-customize.el (mh-show-signature-face): New face used to - display message signature. - -2003-09-08 Peter S Galbraith - - * mh-e.el (mh-version): Do something sensible when - mh-variant-in-use is undefined. - * mh-junk.el (mh-spamassassin-blacklist) - (mh-spamassassin-whitelist): Change options to be compatible with - old version of spamassassin (V2.20). - -2003-09-07 Mark D. Baushke - - * mh-mime.el (mh-access-types): Per RFC 2049, the "afs" - access-type for message/external-body has been removed. - Update the comments to reference the current MIME RFCs - 2045, 2046 and 2049 rather than the obsolete RFC 1521. - -2003-09-05 Peter S Galbraith - - * mh-e.el (mh-version): Bumped version number to 7.4.2+cvs. - -2003-09-04 Satyaki Das - - * mh-utils.el (mh-picon-directory-list, mh-picon-directory): The - mh-picon-directory-list variable supersedes mh-picon-directory. - (mh-picon-existing-directory-list): New variable that contains - the list of picon directories that actually exist. - (mh-picon-set-directory-list): New function to update - mh-picon-existing-directory-list from mh-picon-directory-list. - (mh-picon-get-image): The function has been modified to search a - list of possible picon source directories. The regexp to extract - the username from the email address has been made smarter so that - it can recognize email addresses of the form user+random@foo.net - and extract "user" from there. - (mh-picon-file-contents): The file type recognition code has been - moved from mh-picon-get-image into this function. - (mh-picon-generate-path): The function has been generalized so - that searching multiple paths is now feasible. - - * mh-pick.el, mh-e.el: Checkdoc fixes. - -2003-09-02 Satyaki Das - - * mh-identity.el (eval-when): It seems that the mh-comp-loaded - code isn't required any more. - -2003-08-30 Satyaki Das - - * mh-init.el (mh-variant-set): Replace `error' with `message' so - that Emacs CVS will compile without errors if no MH variant is - present. - -2003-08-29 Satyaki Das - - * mh-init.el (mh-variant-set): Add interactive spec to the - function. - - * mh-mime.el (mh-mhn-compose-external-type): Optional arguments - are prompted for only if prefix arg is given. - -2003-08-29 Mark D. Baushke - - * mh-mime.el (mh-mhn-compose-external-type): Modified to be - interactive and prompts for many of the fields. Made an - mh-autoload. - (mh-access-types): New table derived from RFC2017, RFC1521 and - RFC1738, used in a completing-read in - mh-mhn-compose-external-type. - - * mh-loaddefs.el: Regenerated. - -2003-08-26 Satyaki Das - - * mh-utils.el (mh-picon-image-types, mh-picon-get-image): Avoid - compiler warnings. - (mh-sub-folders-actual): Parsing of the output from folders has - been modified, so that it also works for MH (closes SF #792300). - - * mh-junk.el (mh-spamassassin-whitelist): Avoid calling - ietf-drums-parse-address if it isn't present. - (mh-spamassassin-identify-spammers): Avoid use of puthash so that - Emacs20 doesn't complain. - - * mh-e.el (mh-colors-available-p): Wrap call to - display-color-cells in a mh-funcall-if-exists to avoid compiler - warning in Emacs20. - -2003-08-25 Satyaki Das - - * mh-e.el (mh-colors-available-flag, mh-folder-mode): New - variable to track if colors are available and it is set - appropriately in mh-folder-mode. - (mh-colors-available-p, mh-colors-in-use-p): Two functions to - check whether colors are available and if they are actually being - used. - (mh-add-sequence-notation): Just changing a scan line doesn't - make font-lock refontify the line in Emacs20. So explicitly - refontify the scan line in such a situation. - (mh-internal-seq): If colors aren't being used then treat the - tick sequence like a normal user sequence. - - * mh-seq.el (mh-put-msg-in-seq): Do font-lock highlighting after - the messages have been added to the sequence. - (mh-toggle-tick): Modified so that highlighting of the ticked - messages will be properly done. If font-lock isn't being used or - if colors aren't supported by the Emacs where MH-E is running, - then the `%' character is used to annotate ticked messages. - - * mh-utils.el (mh-picon-image-types): Since Emacs20 doesn't have - image-type-available-p, wrap calls to that function in - ignore-errors. - (mh-add-msgs-to-seq): Do the font-lock highlighting after the - messages have been added. - -2003-08-24 Bill Wohler - - * Makefile (MH-E-SRC): Replaced mh-xemacs-compat.el and - mh-xemacs-icons.el with mh-xemacs.el. - - * mh-e.el: Don't require mh-xemacs-compat which no longer exists. - The XEmacs stuff gets required by mh-customize.el which is - required by mh-utils.el which is required by mh-e.el. This all - happens before mh-xemacs-compat was required, so all should be - well. - - * mh-unit.el (mh-unit-files): Replaced mh-xemacs-compat.el and - mh-xemacs-icons.el with mh-xemacs.el. - - * mh-xemacs.el: New file from concatenation of mh-xemacs-compat.el - and mh-xemacs-icons.el which were removed since their names - exceeded DOS 8+3 limits. - - * mh-customize.el (mh-compose-skipped-header-fields): Use - uppercase for field names. - -2003-08-21 Bill Wohler - - * mh-customize.el (mh-sequences): Introduced new customization - group for sequences. - (mh-refile-preserves-sequences-flag, mh-tick-seq) - (mh-update-sequences-after-mh-show-flag): Moved option from - mh-folder to mh-sequences group. Synced docstring with manual. - (mh-index-ticked-messages-folders): Since mh-tick-seq is - customizable, use it instead of tick in the docstring. - - * mh-index.el (mh-index-ticked-messages): Since mh-tick-seq is - customizable, use it instead of tick in the docstring. - - * mh-seq.el (mh-msg-is-in-seq): Can now specify an alternate - message number with a prefix argument. - (mh-narrow-to-tick): Since mh-tick-seq is customizable, use it - instead of tick in the docstring. Also, use mh-tick-seq instead of - tick in warning message. - -2003-08-20 Peter S Galbraith - - * mh-customize.el: setq mh-variant to 'none when byte-compiling, - since we don't care what MH variant (if any) is on the system at - that point. - - * mh-init.el (mh-variant-set): Don't probe for MH variant when - mh-variant is set to'none (during byte-compilation). - -2003-08-19 Peter S Galbraith - - * mh-pick.el (mh-pick-single-dash): New defconst. Search - components that are supported by single-dash option in - pick. - (mh-pick-regexp-builder): Use `mh-pick-single-dash' and adapt - patch from Sergey Poznyakoff. - - * mh-comp.el (mh-reply): mu-mh supports `repl -group', thanks to - Sergey Poznyakof. - - * mh-init.el: checkdoc fixes. - -2003-08-19 Bill Wohler - - * mh-seq.el (mh-edit-pick-expr): Renamed from mh-read-pick-regexp - since the new name is more indicative of what the function does. - Prompt now says "Pick expression" instead of "Pick regexp". - (mh-narrow-to-subject): Rewrote function to behave like other - similar functions. - (mh-narrow-to-header-field, mh-narrow-to-range) - (mh-narrow-to-tick): s/regexp/pick-expr/. - (mh-widen, mh-narrow-to-from, mh-narrow-to-cc, mh-narrow-to-to): - Synced docstrings with manual - -2003-08-19 Bill Wohler - - Released MH-E version 7.4.2. - - * MH-E-NEWS, README: Updated for release 7.4.2. - - * mh-e.el (Version, mh-version): Updated for release 7.4.2. - - * mh-e.el (mh-folder-size, mh-folder-size-folder) - (mh-folder-size-flist): If flist is not present use folder to find - the number of messages in the folder. Also the .mh_sequences file - is read to find the number of unseen messages (patch from 1.349 - and branched for 7.4.2, closes SF #791021). - - * mh-utils.el (mh-flists-present-flag, mh-find-progs): Introduce a - new variable to test for the presence of the flists program and - set it in mh-find-progs. - (mh-collect-folder-names): Use folders instead of flists. One - advantage is that folders is available on MH while flists is not. - Another is that if an explicit -sequence argument isn't given and - Unseen-Sequence profile is not present then flists croaks while - folders doesn't. - (mh-collect-folder-names-filter): Don't consider folder names that - start with a `.' character. This is needed since the folders - command doesn't filter them out like flists does. - (patches from 1.307 and 1.309 and branched for 7.4.2, closes SF - #791021). - -2003-08-18 Bill Wohler - - * mh-index.el (mh-index-sequenced-messages) - (mh-index-new-messages, mh-index-ticked-messages): Updated - docstrings from manual (closes SF #718833). - - * mh-customize.el (mh-variant): Checkdoc fix. - (mh-index-new-messages-folders): Don't mention defvar in - docstring, use `+inbox' instead. - (mh-index-ticked-messages-folders): Don't mention defvar in - docstring, use `tick' instead. - - * mh-comp.el (mh-repl-group-formfile): Checkdoc fix. - -2003-08-18 Peter S Galbraith - - * mh-init.el (mh-variant-set, mh-sys-path, mh-variant-info): Add - support for GNU mailutils. - (mh-variant-mu-mh-info): New function to detect mu-mh and return - info about it for `mh-variants'. - - * mh-e.el (mh-regenerate-headers): mu-mh has different error - message for a invalid message list. - -2003-08-18 Peter S Galbraith - - * mh-customize.el (mh-e): New defgroup. Sort of an alias for the - 'mh group that a user might be more likely to find. - -2003-08-18 Bill Wohler - - * mh-comp.el (mh-insert-auto-fields-done-local): Docstring tweak. - (mh-compose-and-send-mail): Do not call mh-insert-auto-fields. - This should be done only once in mh-send-letter. - -2003-08-18 Peter S Galbraith - - * mh-comp.el (mh-letter-mode): Call `mh-find-path unconditionally, - like elsewhere in MH-E. - - * mh-utils.el (mh-find-path): Run setup code only if - `mh-find-path-run' is nil such that this is only done once. - Also remove the `setq' for `read-mail-command' and `mail-user-agent'. - -2003-08-18 Peter S Galbraith - - * mh-e.el: require 'mh-utils first - - * mh-customize.el (mh-variant): defcustom moved here. - - * mh-init.el (mh-variants): Made an mh-autoload. - -2003-08-18 Peter S Galbraith - - * Makefile (MH-E-SRC): Added mh-init.el to MH-E-SRC. - - * mh-utils.el (mh-find-progs): Deleted. Make obsolete by mh-init.el. - (mh-find-path): Call `mh-variants' instead of now obsolete - `mh-find-progs'. - (mh-path-search): Deleted. Was only used by `mh-find-progs'. - - * mh-e.el: require mh-init.el. - (mh-version): Use simpler `mh-variant-in-use'. - (mh-scan-format): Use (mh-variant-p 'nmh) instead of mh-nmh-flag. - - * mh-comp.el (mh-insert-x-mailer): Use simpler `mh-variant-in-use'. - - * mh-utils.el (mh-progs, mh-lib, mh-lib-progs) - (mh-flists-present-flag): Moved to mh-init.el. - (mh-nmh-flag): Deleted. Use (mh-variant-p 'nmh) instead. - - * mh-comp.el (mh-repl-group-formfile, mh-forward, mh-reply) - (mh-send-letter): Use (mh-variant-p 'nmh) instead of mh-nmh-flag. - - * mh-mime.el (mh-edit-mhn, mh-mime-save-parts): Use (mh-variant-p - 'nmh) instead of mh-nmh-flag. - -2003-08-16 Bill Wohler - - * mh-customize.el (mh-folder-selection): New group to hold - variables described in Folder Selection section in manual. - (mh-default-folder-list, mh-default-folder-must-exist-flag, - mh-default-folder-prefix): Moved to mh-folder-selection group. - Updated docstrings per manual update. - (mh-default-folder-for-message-function): New defcustom. Was a - defvar in mh-utils.el. Updated docstring per manual update. - - * mh-utils.el (mh-default-folder-for-message-function): Moved to - mh-customize.el. - - * mh-e.el (mh-folder-from-address, mh-prompt-for-refile-folder): - Updated docstrings per manual update. - - * mh-unit.el (mh-unit-files): Added mh-init.el. - -2003-08-16 Peter S Galbraith - - * mh-init.el: New file. Code to initialize the MH-E back-end. - Highlights: - (mh-variant): New defcustom. Users may customize `mh-variant' to - switch between available variants. - (mh-variants): Available MH variants are described in this variable. - (mh-variant-in-use, mh-variant-p): Developers may check which - variant is currently in use with the variable `mh-variant-in-use' - or the function `mh-variant-p'. - -2003-08-15 Bill Wohler - - * mh-customize.el (mh-auto-fields-list): The manual uses Fcc - instead of fcc, so I've changed the user-visible text - accordingly. I've left the const alone for backwards - compatibility. - -2003-08-14 Bill Wohler - - * mh-identity.el (mh-insert-identity): Changed signature deletion - test to test for both markers, rather than testing to see if the - start marker is bound. Since the start marker is defined in this - file, it should always be bound. Suggestion by Satyaki. - - * mh-comp.el (mh-send-letter): Go to the top of the draft so that - the user can see which header fields have been inserted. I think - this is more important than leaving point alone or going to the - end to see the signature since Mail-Followup-To or Bcc or cc could - have some deleterious effects. - - * mh-customize.el (mh-auto-fields-prompt-flag): New variable. - Non-nil means to prompt before sending if fields inserted. - - * mh-comp.el (mh-insert-auto-fields): Now return t if fields - inserted; otherwise nil. - (mh-send-letter): Deleted obsolete documentation about adding - X-Mailer and X-Face. Prompt before sending if auto fields added - and mh-auto-fields-prompt-flag is t. - - * mh-customize.el (mh-identity-list): Allow signature to come from - mh-signature-file-name. In this case, the "signature" value is set - to nil. This might not be the best implementation. Suggestions - welcome. - - * mh-identity.el (mh-insert-identity): Now that the signature can - be a nil value, moved test higher up in cond so that the test for - a nil value would not be executed first prevening signature - handling. Handle nil signature value by calling - mh-insert-signature with no arguments which means to use - mh-signature-file-name. - - * mh-comp.el (mh-insert-signature): Changed text of message if no - signature inserted. - - * mh-customize.el (mh-identity-list): Changed "Signature" constant - back to "signature" so it *won't* be backwards-incompatible any - more. I discovered one could use the :tag keyword to get headline - captalization in the menu. - - * mh-identity.el (mh-insert-identity): Ditto. - - * mh-identity.el (mh-identity-make-menu): Always build menu. - Always create Insert Auto Fields menu item. Just don't enable it - if mh-auto-fields-list is nil. Enable radio buttons always. Make - None a radio button choice with the other identities. - - * mh-comp.el (mh-letter-menu): Removed cond on fboundp - 'easy-menu-define. We don't do this elsewhere. - -2003-08-13 Bill Wohler - - * mh-identity.el (mh-identity-make-menu, mh-insert-identity): Use - headline capitalization in menu items. Even the internal names are - exposed in the customize interface, so they need to be uppercase - too. - (mh-insert-identity): Rather than goto-char to - mh-identity-signature-start before deleting, simply pass it to - delete-region. When setting markers, use point-min-marker and - point-max-marker instead of moving point. Set marker type of - mh-identity-signature-start to t to fix a bug where changing - identity deleted user's text. - - * mh-customize.el (mh-identity-list, mh-auto-fields-list): - Reworked docstring. Use headline capitalization. Commented out - implementation details for later deletion or resurrection upon - popular demand. N.B. If your mh-identity-list contains "signature" - then you will need to either edit your .emacs file manually, or - delete your existing "signature" which will become a regular field - with this change and create a new signature. I figured I could get - away with this since 8.0 is a major release, and coinciding with - the manual update will be a MAJOR release. I apologize profusely - that I didn't catch this before it was released. - (mh-identity-default): Use headline capitalization in example. - -2003-08-12 Jeffrey C Honig - - * mh-customize.el (mh-alias-reloaded-hook): Define - `mh-alias-reloaded-hook'. - - * mh-alias.el (mh-alias-reload): Run `mh-alias-reloaded-hook' - after reloading the aliases. - -2003-08-12 Mark D. Baushke - - * mh-comp.el (mh-insert-signature): Use functionp to avoid - the possibility of doing a funcall on a void function. - -2003-08-12 Bill Wohler - - * mh-customize.el (mh-identity): Point group manual link to new - Identities section. - (mh-signature-separator-flag): New variable which can be used to - suppress the output of the signature separator. - - * mh-comp.el (mh-insert-signature): Use - mh-signature-separator-flag. - - * mh-identity.el (mh-insert-identity): If the identity's signature - file didn't exist, an fboundp error was thrown. This was fixed by - removing signature tests that were redundant and out of date with - the tests in mh-insert-signature. Removed second signature - condition as it is now handled in the first signature condition. - -2003-08-12 Peter S Galbraith - - * mh-identity.el (mh-insert-identity): Don't insert new lines on - signatures anymore. - - * mh-comp.el (mh-insert-signature): Make sure signature file is - readable before trying to insert it. - -2003-08-11 Bill Wohler - - * mh-comp.el (mh-insert-signature): Unconditionally insert a - newline so that signatures are inserted consistently, and so that - there isn't any text after the cursor so that the user can start - typing his message immediately. Use new variable and function - mh-signature-separator and mh-signature-separator-p. - - * mh-customize.el (mh-delete-yanked-msg-window-flag): Checkdoc - fix. - (mh-signature-file-name): Updated docstring now that this variable - can be a function. Added cross-references to - mh-signature-separator, mh-signature-separator-regexp, and - mh-signature-separator-p which might be used in such functions. - - * mh-identity.el (mh-insert-identity): Don't include signature if - signature separator already present. Useful when running - mh-edit-again. - - * mh-mime.el (mh-inline-vcard-p): Use mh-signature-separator-p. - - * mh-utils.el (mh-signature-separator-regexp): New variable - containing "^-- $" which should be used when looking for the - signature separator. - (mh-signature-separator): New variable containing "-- \n" which - should be used when inserting the signature separator. - (mh-signature-separator-p): New function that returns non-nil if - mh-signature-separator-regexp is found in the buffer. - -2003-08-09 Satyaki Das - - * mh-utils.el (mh-x-image-scaling-function): Variable that - contains function used to scale images. Possible choices are - mh-x-image-scale-with-convert and mh-x-image-scale-with-pnm. - (mh-convert-executable): Removed. - (mh-x-image-scale-with-pnm, mh-x-image-scale-with-convert): New - functions that scale images using pnm tools or ImageMagick. - (mh-x-image-scale-and-display, mh-x-image-url-display): Use - mh-x-image-scaling-function instead of mh-convert-executable. - -2003-08-08 Peter S Galbraith - - * mh-comp.el (mh-insert-signature): Bug fix. Handle case of nil - `mh-signature-file-name' and hooks correctly. - - * mh-identity.el (mh-insert-identity): Refactor to use - mh-insert-signature - - * mh-comp.el (mh-signature-separator-p): Removed. - - * mh-comp.el (mh-insert-signature): Merge MIME awareness from - mh-insert-identity into this command. Allow - `mh-signature-file-name' to be a function to call. See if "-- " - needs to be inserted only after hooks have run. - -2003-08-07 Bill Wohler - - * mh-customize.el (mh-compose-skipped-header-fields): Added - X-Image-URL. - (mh-autoload): Removed cookies. They aren't necessary in - mh-e.el, mh-utils.el, or mh-customize.el. - - * mh-e.el (mh-autoload): Removed cookies. They aren't necessary in - mh-e.el, mh-utils.el, or mh-customize.el. - - * mh-identity.el (mh-insert-identity): Made regexp for signature - separator more explicit. Hmmm, maybe we should create - mh-signature-separator-regexp... - - * mh-index.el (mh-replace-string): Moved to mh-utils.el. - - * mh-utils.el (mh-replace-string): Moved here from mh-index.el. - (mh-autoload): Removed cookies. They aren't necessary in mh-e.el, - mh-utils.el, or mh-customize.el. - - * mh-comp.el (mh-insert-signature): Added file argument to insert - a file other than mh-signature-file-name. Insert signature - separator, unless file already contains one. - -2003-08-06 Satyaki Das - - * mh-e.el (mh-folder-size, mh-folder-size-folder) - (mh-folder-size-flist): If flist is not present use folder to - find the number of messages in the folder. Also the .mh_sequences - file is read to find the number of unseen messages. - - * mh-utils.el (mh-flists-present-flag, mh-find-progs): Introduce - a new variable to test for the presence of the flists program and - set it in mh-find-progs. - -2003-08-06 Peter S Galbraith - - * mh-customize.el: Change the order of `mh-identity-list' and - `mh-auto-fields-list' and remove byte-compilation defvar for - `mh-identity-list'. This fixes a customization bug for - `mh-identity-list', where it wasn't set correctly. - - * mh-identity.el (mh-identity-make-menu): mh-auto-fields-list may - not be bound yet when initially loaded. - -2003-08-06 Bill Wohler - - * mh-alias.el (mh-alias-add-address-under-point): Removed trailing - period from messages. The conventions say that errors should not - end with a period and that "Foo...done" messages should not end in - a period, but they aren't explicit about messages in general. - Given what the conventions *do* say, and because most of our - messages don't end with a period, let's just say that messages in - general don't end in a period, just like error messages. - - * mh-comp.el (mh-extract-rejected-mail, mh-letter-mode-message): - Ditto. - - * mh-e.el (mh-refile-a-msg): Ditto. - - * mh-funcs.el (mh-undo-folder): Ditto. - - * mh-mime.el (mh-mime-save-parts): Ditto. - - * mh-seq.el (mh-subject-to-sequence-unthreaded) - (mh-narrow-to-subject, mh-delete-subject): Ditto. - - * mh-index.el (mh-index-sequenced-messages) - (mh-index-new-messages, mh-index-ticked-messages): Discovered that - in general we should only use question marks in yes-or-no-p or - y-or-n-p prompts, but not in other prompts that use - completing-read and offer defaults. In these cases, use colons - instead (closes SF #730470). - - * mh-mime.el (mh-mime-save-parts): Ditto. - - * mh-utils.el (mh-prompt-for-folder): Ditto. - - * mh-alias.el (mh-alias-apropos): Multiple messages are usually - shown one at a time rather than appended. Send output to - mh-aliases-buffer instead of *Help*. - (mh-alias-local-users): Checkdoc fix. - - * mh-funcs.el (mh-undo-folder): Removed commented-out code since - its deadline had expired. - - * mh-utils.el (mh-aliases-buffer): New buffer name, used in - mh-aliases.el. - -2003-08-06 Satyaki Das - - * mh-utils.el (mh-x-image-url-cache-canonicalize): Make this - function work for XEmacs too. - (mh-collect-folder-names): Use folders instead of flists. One - advantage is that folders is available on MH while flists is not. - Another is that if an explicit -sequence argument isn't given and - Unseen-Sequence profile is not present then flists croaks while - folders doesn't. - (mh-collect-folder-names-filter): Don't consider folder names that - start with a `.' character. This is needed since the folders - command doesn't filter them out like flists does. - - * mh-index.el (mh-replace-string): Add autoload for it. - -2003-08-05 Satyaki Das - - * mh-mime.el (mh-compose-forward, mh-mhn-compose-forw) - (mh-mml-forward-message): The variable mh-sent-from-msg can be a - list. So check that the value is really a number before using it - like one. - - * mh-comp.el (mh-insert-letter): Same as above. - - * mh-utils.el (mh-picon-get-image): Make the code that finds the - address of the sender more robust. - (mh-face-display-function): Make it work with XEmacs. - (mh-picon-image-types): A new variable that stores what image - types can be used. - -2003-08-05 Satyaki Das - - * mh-customize.el (mh-tool-bar-define): Make the save button such - that is activated only if the buffer needs to saved. - - * mh-utils.el (mh-face-display-function, mh-picon-get-image): Some - domains, for instance cs.cmu.edu, don't have xpm files. So we need - to search for all three files. The change does that. - (mh-picon-file-contents): A utility function to return the - contents of a file as a string. - (mh-picon-get-image): Write it as a loop to make it simpler. - (mh-x-image-set-download-state): Make the link simpler. - -2003-08-04 Satyaki Das - - * mh-utils.el (mh-x-image-url-display): Don't bother to try to - download image if we don't have the necessary tools to display - it. - (mh-face-display-function): Add preliminary support for "domain" - picons. - (mh-picon-get-image, mh-picon-generate-path): Functions to find - best match for domain in the From header field. - - * mh-e.el (mh-previous-unread-msg): If some of the messages in the - unseen sequence are not present in the folder buffer then calling - this function gets stuck and can't skip over them. The change - fixes this. - (mh-next-unread-msg): Same as above. - -2003-08-04 Bill Wohler - - * mh-utils.el (mh-show-mode): Added cross reference to - mh-folder-mode in docstring (closes SF #728638). Added - \\{mh-show-mode-map} to show keymap. - - * mh-e.el (mh-folder-mode): Added information about ranges to - docstring (closes SF #728638). - - * mh-speed.el (mh-speed-refresh): New function that calls - mh-speed-flists and mh-invalidate-map. - (mh-folder-speedbar-key-map): Replaced keybindings for - mh-speed-invalidate-map and mh-speed-flists with a single binding - for mh-speed-refresh. - (mh-folder-speedbar-menu-items): Replaced menu items for Run - Flists and Invalidate Cached Folders with the single menu item - Refresh Speedbar in order to simplify the UI. - - * mh-customize.el (mh-fetch-x-image-url): Added DOS as another - reason not to set this to t. - -2003-08-04 Satyaki Das - - * mh-e.el (mh-scan-folder): Handle ranges from user input properly. - -2003-08-03 Satyaki Das - - * mh-utils.el (mh-find-msg-get-num): Removed. If threading isn't - present, the messages are sorted by index. So `mh-goto-msg' was - implemented as a binary search and this function was used in that - implementation. So this isn't needed any more. - (mh-msg-search-pat): Removed. Before the advent of message - threading, this function was used to generate a regexp used to - search for a particular message. It isn't used anymore. The - variable `mh-scan-msg-number-regexp' should be updated and used in - `mh-goto-msg' instead of hardcoding the regexp in the code. Then - we might be able to better support other scan line formats in the - future. - - * mh-seq.el (mh-map-to-seq-msgs, mh-notate-seq): Removed. These - functions were used to notate user sequences. But calling - `mh-goto-msg' inside of a loop is inefficient. So the sequence - notation code was rewritten thereby making these functions - redundant. - (mh-copy-line-to-point): Removed. This function was used in the - implementation the now removed function `mh-copy-seq-to-point'. - That function was problematic and was replaced by the less general - `mh-copy-seq-to-eob'. This makes `mh-copy-line-to-point' - redundant. - (mh-region-to-msg-list): Removed since this is a special case of - the more general `mh-range-to-msg-list'. - - * mh-loaddefs.el: Regenerated. - -2003-08-03 Jeffrey C Honig - - * mh-customize.el (mh-invisible-header-fields-default): Added - several new fields to hide. Sorted the list with sort-lines. - -2003-08-03 Peter S Galbraith - - * mh-customize.el (mh-invisible-headers): Variable renamed to - `mh-invisible-header-fields-compiled'. - (mh-invisible-headers): Implement above change. - - * mh-utils.el (mh-display-msg): Idem. - - * mh-mime.el (mh-mm-inline-message): Idem. - - * mh-comp.el (mh-insert-letter): Idem. - -2003-08-03 Bill Wohler - - * mh-speed.el (mh-folder-speedbar-menu-items): Added separator - between standard and MH-E menu items. Use headline capitalization - in menu items. - - * mh-utils.el (mh-temp-fetch-buffer): New constant to hold - buffer name for wget output. - (mh-x-image-url-fetch-image): Use mh-temp-fetch-buffer instead - of hard-coded buffer name. Use make-temp-file to avoid race - conditions and subsequent security issues raised in make-temp-name - docstring. - -2003-08-03 Satyaki Das - - * mh-utils.el (mh-wget-executable, mh-wget-choice, mh-wget-option) - (mh-x-image-url-fetch-image): Support the use of `curl' and - `fetch' as alternatives to `wget'. - (mh-wget-choice): Change order of search. - (mh-x-image-url-fetch-image): Rename buffer. - -2003-08-03 Satyaki Das - - * mh-utils.el (mh-x-image-set-download-state) - (mh-x-image-get-download-state): Specially named symbolic links - are used to keep track of whether a X-Image-URL header field needs - to downloaded the next time it is seen. These functions get and - set the symlinks appropriately. - (mh-x-image-url-fetch-image): Simplified since the query has been - moved to `mh-x-image-url-display'. Also if wget isn't present then - try again next time since the user might install wget before - trying once more. - (mh-x-image-scale-and-display): Handle absence of the `convert' - program better. If it isn't present then we will try to display - the image the next time it is encountered. Also use the -geometry - option to convert since the -resize option isn't present in older - versions. - (mh-x-image-url-display): Move all the code that decides whether - an X-Image-URL header field will be fetched in this function. Also - remember the user's decision so that if the image couldn't be - fetched the first time, we will try to fetch it later on without - asking again. - -2003-08-02 Peter S Galbraith - - * mh-alias.el (mh-alias-local-users): Exclude all aliases already - in mh-alias-alist from `ali' (closes SF #772595). - -2003-08-01 Satyaki Das - - * mh-utils.el (mh-x-image-display, mh-x-image-url-display): Avoid - a race. The X-Image-URL is displayed asynchronously. Suppose a - message with a image is shown with `mh-show'. If a different - message is displayed before the image can be fetched, then the new - message will have the image displayed. With this change the race - is less likely to happen. - -2003-08-01 Peter S Galbraith - - * mh-inc.el (mh-inc-spool-map): Fix what `mh-inc-spool-map-help' - must look like as a fake `mh-help-messages' in order to work - correctly in mh-help. - -2003-07-31 Bill Wohler - - * mh-inc.el (mh-inc-spool-map): Use mh-help instead of - mh-ephem-message in order to display help in its own buffer - instead of minibuffer. - - * mh-utils.el (mh-help-buffer): New variable to hold the name of - the MH-E help buffer name. - - * mh-funcs.el (mh-help, mh-prefix-help): Use with-electric-help to - display help messages. I observed a friend with a vision - disability and the 5 seconds the help appeared on the screen was - not long enough for him to lock on it. I've therefore changed the - help function to display the help in its own buffer called *MH-E - Help* (closes SF #493740 and SF #656631). - - * mh-customize.el (mh-fetch-x-image-url): Changed default from nil - to 'ask. Updated docstring from manual. - (mh-invisible-header-fields-internal): Added X-Image-URL. - (mh-show-use-xface-flag): Updated docstring from manual. - (mh-x-face-file): Ditto. - - * mh-mime.el (mh-mhn-compose-external-type): Don't insert the - directory parameter if it's nil. The mhbuild man page indicates - that this parameter is optional, so this should be fine. - - * mh-comp.el (mh-letter-mode-map): Added keybindings for - mh-mhn-compose-anon-ftp and - mh-mhn-compose-external-compressed-tar. - (mh-letter-menu): Uncommented menu items for same. - -2003-07-30 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-pick.el (mh-do-pick-search): Removed since the function - `mh-pick-do-search' performs the same action as this function. - - * mh-index.el (mh-index-update-unseen): Removed since the - generalized sequence synchronization code that keeps sequences in - index folders in sync with the sequences in the source folders - makes this function redundant. - - * mh-e.el (mh-folder-unseen-seq-name, mh-folder-unseen-seq-list): - Removed. These two functions were used in the unseen sequence - highlighting before the sequence highlighting code was - generalized. In any event calls to the function - `mh-folder-unseen-seq-name' can be replaced by the variable - `mh-unseen-seq' and calls to `mh-folder-unseen-seq-list' can be - replaced with (cdr (assoc mh-unseen-seq mh-seq-list)). - (mh-unmark-all-headers): Removed since this function has been - superseded by mh-remove-all-notation. - (mh-map-over-seqs): Removed since we now have the generalized - iteration over message ranges (the `mh-iterate-on-range' macro) - that can be used instead. - (mh-notate-if-in-one-seq): Removed. This function was used for - changing the `%' notation for user sequences. It can't be used for - that purpose any more, since we have a different scheme now. - - * mh-unit.el (mh-unit-tests): Removed since it isn't needed any - more. - (mh-unit): Run all function that start with the string - "mh-unit-test-". - -2003-07-30 Bill Wohler - - * mh-customize.el (mh-invisible-header-fields): Checkdoc fix. - - * mh-utils.el (mh-x-image-url-cache-canonicalize): Shortened using - example in files.el:make-backup-file-name-1. - (mh-face-display-function): Added X-Image-URL to docstring. - - * mh-unit.el (mh-unit-x-image-url-cache-canonicalize): New - function to test mh-x-image-url-cache-canonicalize since it lent - itself well to unit testing. Had to start somewhere! - (mh-unit-equal): New function that throws an error if RESULT - doesn't equal EXPECTED. - (mh-unit): Call mh-unit-x-image-url-cache-canonicalize. - -2003-07-29 Satyaki Das - - * mh-unit.el (mh-unit-update-call-graph): Make the function work - better with dotted lists, that is lists of the form (a b c . d) - where `d' isn't nil. With this we are able to avoid marking some - functions as unused even though they are actually used in alists. - -2003-07-28 Peter S Galbraith - - * mh-comp.el (mh-insert-letter): Remove `mh-visible-headers' - operation. - - * mh-mime.el (mh-mm-inline-message): Same. - - * mh-utils.el (mh-display-msg): Same. - (mh-clean-msg-header): Make a note of above change. - - * mh-customize.el (mh-invisible-header-fields-internal): Renamed - from prior `mh-invisible-header-fields-default'. - (mh-invisible-header-fields-default): Renamed from prior - `mh-invisible-header-fields-default-override'. - (mh-invisible-header-fields): Renamed from prior - `mh-invisible-header-fields-user'. - (mh-visible-headers): Removed! We use invisible fields only now. - (mh-visible-header-fields): Removed! - -2003-07-28 Peter S Galbraith - - * mh-customize.el (mh-invisible-header-fields-default): Added 3 - new fields to hide. - -2003-07-28 Satyaki Das - - * mh-utils.el (mh-show): Add an extra argument to the function so - that interactive use will always force redisplay of the message. - - * mh-mime.el (mh-mime-display, mh-mm-inline-message): Bind the - variables `mm-verify-option' and `mm-decrypt-option' so that - verification and decryption of mail can happen without any - additional tinkering. - -2003-07-25 Peter S Galbraith - - * mh-customize.el (mh-invisible-header-fields-default): New defvar - holding default fields to hide. This replaces the old - `mh-invisible-header-fields' defcustom. - (mh-invisible-header-fields-user): New defcustom. Users add - fields to suppress that we didn't include in - `mh-invisible-header-fields-default'. This could be named simply - `mh-invisible-header-fields' and it wouldn't really break anything - for users who have customized it to a long list now redundant with - `mh-invisible-header-fields-default'. - (mh-invisible-header-fields-default-override): New defcustom. - Users check off the fields they want displayed from what we - included in `mh-invisible-header-fields-default'. - (mh-invisible-headers): Function adapted to new variables. - -2003-07-25 Satyaki Das - - * mh-e.el (mh-inc-folder): If the user is in a different folder - displaying a message and runs mh-inc-folder, then the folder - changes to +inbox but the show window continues to display the - message in the old folder. The change fixes this. - (mh-visit-folder): Make the handling of the show window similar to - that of mh-inc-folder. - -2003-07-24 Satyaki Das - - * mh-e.el (mh-folder-message-menu, mh-folder-folder-menu): Use the - predicate mh-outstanding-commands-p instead of its expansion. - Also use the same label in both menus. - (mh-outstanding-commands-p): Generalized so that it will work in - mh-show-mode buffers as well. - - * mh-customize.el (mh-tool-bar-define): Enable tool-bar button for - mh-execute-commands only if there are pending deletes or refiles. - -2003-07-19 Satyaki Das - - * mh-utils.el (mh-show-msg): If a unseen message is first marked - for deletion/refiling and then displayed, the bold highlighting - does not go away. This change fixes that. - - * mh-seq.el (mh-msg-is-in-seq): Fix a bug in the function. If any - message was marked for refiling, then the function would have you - believe that every message in the folder is being refiled. - -2003-07-17 Bill Wohler - - * mh-e.el: Removed email address for Stephen Gildea's in Change - Log at his request (damn spammers). Removed other email addresses - while I was at it since the SourceForge URL should be sufficient - contact information. - - (mh-scan-format-*mh): Fixed typo in comment above these variables. - These variables are used if mh-scan-format-file is t, not nil. - Also mh-scan-format-file is no longer "above" (courtesy Stephen - Gildea). - -2003-07-17 Satyaki Das - - * mh-mime.el (mh-mhn-quote-unescaped-sharp): New function that - quotes `#' characters in the first column that aren't part of a - MHN directive. - (mh-mhn-directive-present-p): Generalized to allow the function - to search for MHN directives in a part of the buffer. - (mh-edit-mhn): Quote unescaped `#' characters in the draft (closes - SF #762464). - -2003-07-16 Satyaki Das - - * mh-alias.el (mh-alias-read-address-map): If - mh-alias-flash-on-comma is nil when mh-alias is loaded, then - setting mh-alias-flash-on-comma to t later on doesn't turn on - address completion display till Emacs is restarted. The change - fixes this. - -2003-07-15 Bill Wohler - - * mh-utils.el (mh-cmd-note): Cleaned up docstring (changed phrase - to sentences). Moved to Scan Line Formats section. - (mh-scan-msg-number-regexp) - (mh-scan-msg-overflow-regexp, mh-scan-msg-format-regexp) - (mh-scan-msg-format-string, mh-scan-msg-search-regexp): Cleaned up - docstrings (changed phrases to sentences). - (mh-note-seq): Cleaned up docstring (changed phrase to sentences). - Also, this variable is now a character and not a string. Moved to - Scan Line Formats section. - - * mh-funcs.el (mh-note-copied, mh-note-printed): Cleaned up - docstrings (changed phrases to sentences). Also, these variables - are now characters and not strings. - - * mh-e.el (mh-scan-format-mh, mh-scan-format-nmh): Filled. I was - hoping to quote the hint `t' but checkdoc wouldn't let me. - (mh-note-deleted, mh-note-refiled, mh-note-cur): Moved to Scan - Line Formats section. - (mh-scan-good-msg-regexp, mh-scan-deleted-msg-regexp) - (mh-scan-refiled-msg-regexp, mh-scan-valid-regexp) - (mh-scan-cur-msg-number-regexp, mh-scan-date-regexp) - (mh-scan-rcpt-regexp, mh-scan-body-regexp) - (mh-scan-subject-regexp, mh-scan-format-regexp): Cleaned - up docstrings (changed phrases to sentences). - (mh-scan-cur-msg-regexp): Marked this variable as obsolete; it - should be removed for 8.0. - - * mh-comp.el (mh-note-repl, mh-note-forw, mh-note-dist): Cleaned - up docstrings (changed phrases to sentences). Also, these - variables are now characters and not strings. - -2003-07-15 Satyaki Das - - * mh-index.el (mh-index-update-single-msg) - (mh-index-create-sequences): Handle the situation where there are - copies of the exact same message correctly. - -2003-07-15 Satyaki Das - - * mh-seq.el (mh-thread-update-scan-line-map): Modified since - notation is already a character. - - * mh-utils.el (mh-note-seq): Convert from string to character. - (mh-notate): Modified since characters are used to notate instead - of strings of length one. - - * mh-comp.el (mh-note-repl, mh-note-forw, mh-note-dist): Convert - from string to characters. - - * mh-e.el (mh-note-deleted, mh-note-refiled, mh-note-cur): Same as - above (closes SF #770772). - (mh-unmark-all-headers): Modified since mh-note-* variables are - now characters. - (mh-remove-sequence-notation): The mh-notate function remembers - the previous notation. Before the change to the mh-note-* - variables, mh-notate would only remember the change if a string - was used to notate the message. Now mh-notate is always called - with a character notation. So the deletion has to take place - explicitly. - -2003-06-28 Bill Wohler - - * mh-mime.el (mh-mhn-directive-present-p): If shell comments are - present that have a space after the # but no content, then this - function would throw an error. This has been fixed (closes SF - #762458). - -2003-06-27 Satyaki Das - - * mh-index.el (mh-index-search): Use the new and improved - mh-index-new-folder. - (mh-index-new-folder): Improved so that redoing the same search - will reuse the old index folder. - (mh-index-folder-search-regexp): New function which that extracts - out the search expression that produced the index folder. - -2003-06-24 Bill Wohler - - * mh-e.el (Version, mh-version): Set to 7.4.1+cvs. - -2003-06-25 Bill Wohler - - Released MH-E version 7.4.1. - - * MH-E-NEWS, README: Updated for release 7.4.1. - - * mh-e.el (Version, mh-version): Updated for release 7.4.1. - -2003-06-25 Bill Wohler - - * mh-unit.el (require 'cl): Added. Needed when compiling - separately. - - * Makefile (clean): Now a double-colon rule. Added a second clean - target to remove mh-unit.elc. - (compile): Removed mh-unit.elc. - (mh-unit.elc): New target used to compile mh-unit. - -2003-06-24 Bill Wohler - - * mh-e.el (Version, mh-version): Set to 7.4+cvs. - -2003-06-24 Bill Wohler - - Released MH-E version 7.4. - - * MH-E-NEWS, README: Updated for release 7.4. - - * mh-e.el (Version, mh-version): Updated for release 7.4. - -2003-06-24 Bill Wohler - - * mh-alias.el (mh-alias-gecos-name, mh-alias-local-users) - (mh-alias-suggest-alias): s/gcos/gecos. The original acronym was - GECOS but was later renamed to GCOS (see - http://info.astrian.net/jargon/terms/g/GCOS.html). But the term - really needs to match the field named pw_gecos in struct passwd in - /usr/include/pwd.h - - * mh-customize.el (mh-letter-faces): New group to house - mh-letter-header-field-face. - (mh-interpret-number-as-range-flag) - (mh-kill-folder-suppress-prompt-hook): Use "you" instead of "the - user" to make text more friendly. - (mh-index-ticked-messages-folders, mh-visible-headers) - (mh-visible-header-fields): Alphabetized. - (mh-alias-passwd-gcos-comma-separator-flag): Alphabetized and - s/gcos/gecos. - (mh-alias-local-users-prefix): Fixed docstring. Prefixes are - prepended, not appended. Additional checkdoc fix. - (mh-letter-header-field-face): Set group to new group - mh-letter-faces and moved option into this group. - - * mh-index.el (mh-index-sequenced-messages): Improved wording of - docstring and mentioned use of prefix argument. - - * mh-seq.el (mh-widen): Made docstring more accurate (hopefully!). - -2003-06-18 Satyaki Das - - * mh-index.el (mh-replace-string): Modified to preserve case of - replacement text. - (mh-index-parse-search-regexp): Preserve case of search terms. - This is needed to take advantage of the acronym indexing in - swish++ (closes SF #755718). - -2003-06-13 Satyaki Das - - * mh-utils.el (mh-show-index-sequenced-messages): Interactive - function callable from the show buffer. - (mh-show-folder-map): Add key binding for "F q". - - * mh-e.el (mh-folder-map): Same as above. - - * mh-index.el (mh-index-sequenced-messages): Add interactive spec - to the function (closes SF #718833). - -2003-06-13 Bill Wohler - - * mh-index.el (mh-flists-execute): Needed to expand mhpath too. - -2003-06-12 Satyaki Das - - * mh-index.el (mh-flists-execute): Modified so that flists - present in mh-progs is called. - -2003-06-07 Jeffrey C Honig - - * mh-comp.el (mh-forward, mh-forward): Use (mh-mail-header-end) to - find the end of headers instead of doing an re-search-forward - based on mh-mail-header-separator. - -2003-06-06 Satyaki Das - - * mh-comp.el (mh-letter-toggle-header-field-display): Make the - function callable from the show buffer. This means that the - buffer is temporarily made writable and the modification status - of the buffer restored to the original value. - -2003-06-06 Peter S Galbraith - - * mh-utils.el (mh-address-mail-regexp): Bug fix! It wasn't a true - copy of the goto-addr variable. My modification only recognized - addresses with one dot after the @. Sorry about that. - -2003-06-05 Satyaki Das - - * mh-utils.el (mh-replace-in-string): Move comment into doc - string to satisfy checkdoc. - - * mh-alias.el (mh-alias-apropos): Checkdoc fix. - -2003-06-05 Bill Wohler - - * mh-customize.el (mh-identity-list): Fixed typo in docstring. - -2003-06-05 Peter S Galbraith - - * mh-comp.el (mh-letter-complete-function-alist): Add bcc an reply-to. - -2003-06-04 Peter S Galbraith - - * mh-comp.el (mh-letter-complete-function-alist): Add dcc. - -2003-06-03 Peter S Galbraith - - * mh-utils.el (mh-replace-in-string): New function name instead of - `dired-replace-in-string'. - * mh-alias.el (mh-alias-gcos-name): Use it. - - * mh-alias.el (mh-alias-apropos): New command. Show all aliases - that match REGEXP either in name or content. - - * mh-alias.el (mh-alias-suggest-alias): Add no-comma-swap optional - arg. - (mh-alias-canonicalize-suggestion): Change a comma to a period in - created aliases. - (mh-alias-local-users): Call `mh-alias-suggest-alias' with - `no-comma-swap' arg set to t. - - * mh-alias.el (mh-alias-local-users): Fix case of nil - `mh-alias-passwd-gcos-comma-separator-flag'. - - * mh-alias.el (mh-alias-gcos-name): Fix for case of empty gcos - name field. - (mh-alias-local-users): Fix same. - - * mh-alias.el (mh-alias-canonicalize-suggestion): Replace use by - verbose `replace-regexp' by a looped `replace-match' - -2003-06-02 Peter S Galbraith - - * mh-utils.el (dired-replace-in-string): Bind if not already - defined. Borrowed from dired.el - - * mh-alias.el (mh-alias-gcos-name): switch to using - dired-replace-in-string. - -2003-06-02 Satyaki Das - - * mh-utils.el (mh-letter-font-lock-keywords): Fontify header - fields in the draft buffer that aren't skipped when navigating - with TAB (or S-TAB). - - * mh-customize.el (mh-clean-message-header-flag) - (mh-invisible-headers, mh-invisible-header-fields) - (mh-alias-passwd-gcos-comma-separator-flag): Checkdoc fix. - (mh-letter-header-field-face): New face to fontify the header - fields. - - * mh-comp.el (mh-insert-auto-fields-done-local): Checkdoc fix. - (mh-letter-mode, mh-letter-mail-header-end-marker): Remember the - end of the message header in a marker. This is used to fontify the - header fields. - (mh-font-lock-field-data, mh-letter-header-end): Functions used - to fontify message header fields. - - * mh-alias.el (mh-alias-gcos-name): Checkdoc fix. - -2003-06-02 Peter S Galbraith - - * mh-alias.el (mh-alias-gcos-name): New function. Return a usable - address string from a GCOS-NAME and USERNAME. - (mh-alias-local-users): Use it. - - * mh-customize.el (mh-alias-passwd-gcos-comma-separator-flag): New - defcustom. Whether the gcos field in the passwd file uses comma as - a separator. - - * mh-customize.el (mh-alias-local-users-prefix): New - defcustom. String to append to the real names of users from the - passwd file. If nil, use the username string unmodified instead of - the real name from the gcos field of the passwd file. - - * mh-alias.el (mh-alias-local-users): Use it to generate aliases - which by default are now the real name prefixed by "local." - -2003-06-01 Peter S Galbraith - - * mh-comp.el (mh-modify-header-field): Bug fix. Calling with - a value that was already inserted causes it to get inserted a - second time. I have wrapped the value around \b word delimiters. - Hope there are no side effects for other code. - - * mh-comp.el (mh-insert-auto-fields): Attempt regardless of - `mh-insert-auto-fields-done-local' flag in interactive use. - - * mh-comp.el (mh-insert-auto-fields-done-local): Keep track of - whether `mh-insert-auto-fields' was called in a buffer. - (mh-insert-auto-fields): Set it and use it. Also, don't enter an - identity if one was already entered manually. - (mh-send-letter): Call `mh-insert-auto-fields' again when sending - message. - (mh-compose-and-send-mail): Call `mh-insert-auto-fields' _after_ - `mh-letter-mode' so `mh-identity-local' doesn't get cleared by the - mode invocation. - -2003-06-01 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-seq.el (mh-thread-parse-scan-line): The value of - mh-scan-field-from-start-offset was hardcoded in one place. The - change fixes that. - - * mh-utils.el (mh-show-mode): Setup mh-show-mode to display - ellipsis for truncated header fields and to skip over them quickly. - (mh-clean-msg-header): Make another pass over the message header - fields truncating long headers. - - * mh-comp.el (mh-letter-complete): Remove unnecessary autoload. - (mh-letter-toggle-header-field-display): Take into account that - an empty line can also end the message header. The function was - originally written with the draft buffer in mind. - -2003-06-01 Mark D. Baushke - - * mh-comp.el (mh-letter-mode-map): Do not steal C-t. Use C-c C-t - for the mh-letter-toggle-header-field-display command. - -2003-05-31 Peter S Galbraith - - * mh-customize.el (mh-visible-headers): Changed to a defvar that - will be set using new `mh-visible-headers' function using - `mh-visible-header-fields' as input. - (mh-visible-headers): New function, described above. - (mh-visible-header-fields): New defcustom. The UI to set - `mh-visible-headers'. - (mh-invisible-header-fields-set): Deleted. Code merged into - defcustom since it's so short. - -2003-05-31 Satyaki Das - - * mh-comp.el (mh-letter-toggle-header-field-display): Extended to - truncate headers if they are too long. - (mh-letter-truncate-header-field): Make code that would be - duplicated into a function. - (mh-letter-hide-all-skipped-fields): Modified so that fields that - are important are hidden if they are too long. - -2003-05-31 Satyaki Das - - * mh-utils.el ("tool-bar"): Since tool-bar isn't available on - XEmacs, requiring it causes problems. So load it instead. - (mh-do-at-event-location): New macro to do stuff at location of - events. This has been refactored out of mh-push-button. - - * mh-mime.el (mh-push-button): Simplified since it now uses the - mh-do-at-event-location macro. - - * mh-comp.el (mh-hidden-header-keymap): Keymap to make mouse - clicks on header toggle its display. - (mh-letter-toggle-header-field-display-button): Interactive - function to toggle header display when mouse button is clicked. - -2003-05-31 Peter S Galbraith - - * mh-e.el (mh-folder-mode): Remove conditional on tool-bar-mode. - - * mh-comp.el (mh-letter-mode): Same. - - * mh-utils.el (mh-show-mode): Same. - -2003-05-30 Satyaki Das - - * mh-utils.el (tool-bar): Load tool-bar explicitly. This avoids - problems with incorrect initialization of tool-bar-map otherwise. - -2003-05-30 Peter S Galbraith - - * mh-comp.el (mh-modify-header-field): Minor fix of spaces for - when an entry already existed. - (mh-insert-auto-fields): Make interactive. Add optional `quiet' - arg for use when called systematically on every buffer. Won't be - used interactively for more verbose output. - (mh-letter-mode-map): Add \C-c\M-d keybinding for - mh-insert-auto-fields. - - * mh-identity.el (mh-identity-make-menu): Add a menu entry in - Identity menu for mh-insert-auto-fields. - - * mh-customize.el (mh-invisible-header-fields): Add entries for - `Envelope-to' and `X-Original-To'. - -2003-05-30 Satyaki Das - - * mh-comp.el (mh-letter-mode): Skip over invisible text quickly. - -2003-05-30 Satyaki Das - - * mh-comp.el (mh-letter-mode): Use text properties to achieve - invisibility. This is more portable and the same code can be used - for all Emacs versions. - (mh-letter-toggle-header-field-display): Rewritten to use text - properties. - (mh-dead-overlay-p, mh-letter-hidden-header-fields)): Removed. - -2003-05-29 Satyaki Das - - * mh-comp.el (mh-letter-hidden-header-fields, mh-letter-mode): Add - a hash table, initialized it in mh-letter-mode, to remember the - overlays introduced to hide long headers fields. - (mh-insert-x-mailer): checkdoc fix. - (mh-compose-and-send-mail): Hide unimportant message header - fields. - (mh-letter-header-field-regexp, mh-letter-header-field-at-point) - (mh-letter-next-header-field, mh-letter-previous-header-field): - Add a variable that contains the header-field name regexp and use - it instead of the regexp directly. - (mh-letter-toggle-header-field-display, mh-letter-mode-map): Add - new key binding in mh-letter-mode that toggles display of long - header fields, in mh-letter-mode. - (mh-dead-overlay-p): A predicate which checks if a given header - field has an active overlay hiding it. - (mh-letter-hide-all-skipped-fields): New function that shortens - uninteresting headers. - -2003-05-29 Eric Ding - - * mh-comp.el (mh-letter-next-header-field-or-indent): Call - indent-relative rather than indent-for-tab-command. - -2003-05-29 Satyaki Das - - * mh-comp.el (mh-letter-complete-or-space): The meaning of the - customizable variable was reversed. Also make the doc string more - accurate. - -2003-05-28 Satyaki Das - - * mh-customize.el (mh-compose-skipped-header-fields): New - customizable variable that lists headers that are skipped. - (mh-compose-space-does-completion-flag): Option to do completion - with space (closes SF #745634). - - * mh-comp.el (mh-insert-x-mailer): Check the value of - mh-insert-x-mailer-flag in this function instead of in its caller. - (mh-compose-and-send-mail, mh-send-letter): Insert X-Mailer and - X-Face headers when the draft is first presented to the user - instead of when the mail is sent (closes SF #745624). - (mh-letter-complete-or-space): Allow for this key binding to be - overridden. - (mh-letter-next-header-field): Fix a problem with multiline header - fields. - (mh-letter-next-header-field, mh-letter-previous-header-field): - Make these functions skip unwanted header fields. - (mh-letter-skipped-header-field-p): New predicate that checks if a - header field is to be skipped. - - * mh-seq.el (mh-thread-inc): Inc'ing email in threaded mode was - causing duplication of the current notation. The change fixes that. - -2003-05-28 Satyaki Das - - * mh-comp.el (mh-beginning-of-word): Generalize it to skip - arbitrary number of words. - (mh-letter-complete-or-space): New interactive function that - allows space character to be used for completion. - (mh-letter-mode-map): Add key binding to allow space to be used - for completion. - -2003-05-27 Satyaki Das - - * mh-customize.el (mh-compose-prompt-flag): Customizable variable - that controls whether the user is prompted when composing a draft. - It replaces mh-dont-prompt-for-address-flag (closes SF #745622). - - * mh-comp.el (mh-letter-next-header-field): If the point is in - the header field name, then go the start of the header field - instead of the next field. - (mh-interactive-read-address, mh-interactive-read-string) - (mh-letter-adjust-point): Use mh-compose-prompt-flag instead of - mh-dont-prompt-for-address-flag. - -2003-05-27 Satyaki Das - - * mh-customize.el (mh-tool-bar-define): Fix incorrect usage of - set-specifier (closes SF #745655). Also the button enabling code - interacts poorly with font-lock in XEmacs. So disable that. - -2003-05-26 Satyaki Das - - * mh-e.el (mh-folder-from-address): The function - message-fetch-field expects that the buffer is narrowed to the - mail header. The change makes sure that this is indeed the case. - - * mh-mime.el (mh-add-missing-mime-version-header) - (mh-decode-message-body): Same as above. - -2003-05-25 Satyaki Das - - * mh-alias.el (mh-alias-minibuffer-confirm-address): Modified to - use mh-beginning-of-word. - - * mh-comp.el (mh-letter-confirm-address): Calling - mh-alias-reload-maybe can be expensive. So do it only if we really - need to. - -2003-05-25 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-comp.el (mh-letter-confirm-address): Load aliases if not yet - loaded. - - * mh-alias.el (mh-alias-reload-maybe): Autoload it since it is - used in mh-comp.el. - -2003-05-24 Satyaki Das - - * mh-comp.el (mh-letter-skip-leading-whitespace-in-header-field): - New function to skip leading space and tab characters when placing - point in a header field. - (mh-letter-next-header-field, mh-letter-previous-header-field): - Skip leading whitespace when using TAB to navigate to header - fields. - (mh-letter-confirm-address): New interactive function that - displays the last expansion of the last alias when "," is typed. - (mh-letter-mode-map): Add key binding for "," (closes SF #745634). - -2003-05-23 Satyaki Das - - * mh-comp.el (mh-edit-again, mh-forward, mh-send) - (mh-send-other-window, mh-send-sub): Modified so that if - mh-dont-prompt-for-address-flag is non-nil, then MH-E won't prompt - for addresses to send mail to and instead directly jump to the - draft (closes SF #745622). - (mh-letter-complete-function-alist): An alist that is used to - decide which completion function to use in which header. This - variable should probably be customizable. - (mh-letter-complete): Now uses mh-letter-complete-function-alist. - (mh-letter-header-field-at-point, mh-letter-next-header-field) - (mh-letter-next-header-field-or-indent) - (mh-letter-previous-header-field): Commands for easier navigation - to header fields. - (mh-dont-prompt-for-address-flag): Variable which controls - whether MH-E prompts for addresses. - (mh-interactive-read-address, mh-interactive-read-string): Two - functions to ask user for input depending on the value of the - above flag. - (mh-letter-adjust-point): New function that sets point to the - first header field. - (mh-letter-mode-map): Add key bindings for TAB and S-TAB (closes - SF #745627). - -2003-05-23 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-comp.el (mh-complete-word): New function which is - approximately equivalent to mail-abbrev-complete-alias. - (mh-beginning-of-word): Refactor repeated code into its own - function. - (mh-folder-expand-at-point): Make Fcc completion work in XEmacs - by not using mail-abbrev-complete-alias. - - * mh-alias.el (mh-alias-letter-expand-alias): Make alias - expansion work in XEmacs. Replace the use of the function - mail-abbrev-complete-alias, which isn't present in XEmacs. - - * mh-mime.el (mh-mml-to-mime): If a MIME message is created - immediately after starting MH-E then invoking mh-mml-to-mime - causes an error because "message" isn't being loaded. The change - works around this problem. - (mh-mime-maybe-display-alternatives): Give better indication of - which MIME parts are alternatives. - -2003-05-22 Satyaki Das - - * mh-e.el (mh-add-sequence-notation, mh-remove-sequence-notation): - Just delete and add the same character in the scan line to make - font-lock refontify it. The previous trick of removing all text - properties didn't work in XEmacs. - - * mh-seq.el (mh-put-msg-in-seq): Complain if the user tries to - create an invalid MH sequence. - - * mh-mime.el (mh-mime-display-alternative): Modified to - optionally display alternatives as buttons. - (mh-mime-maybe-display-alternatives): New function which displays - alternative MIME parts as buttons. - (mh-mime-save-part): Initially mh-mime-save-parts-directory is - nil and calling file-name-as-directory with nil arg leads to an - error. So fall back on the default-directory in that case. - - * mh-customize.el (mh-display-buttons-for-alternatives-flag): New - customizable variable that controls display of the alternative - MIME parts (closes SF #741288). - -2003-05-22 Peter S Galbraith - - * mh-customize.el (mh-invisible-header-fields): Commented out - "User-Agent:". It's similar to X-Mailer, so display it. - -2003-05-21 Satyaki Das - - * mh-customize.el (mh-tool-bar-define): Add an optional argument - to the button description that can dynamically enable/disable - buttons. - (mh-tool-bar-define): The alias grabbing button is disabled if the - current message doesn't have a From header or if the sender is - already in the user's alias. This functionality was inadvertently - lost when the Emacs/XEmacs toolbar unification took place. - -2003-05-20 Satyaki Das - - * mh-unit.el (mh-unit-construct-call-graph): Be more aggressive - and flag interactive functions that aren't autoloaded or have no - key bindings. - (mh-unit-interactive-function-p): Remove now unused function. - (mh-unit, mh-unit-construct-call-graph): Replace mh-files with - mh-unit-files. - -2003-05-20 Bill Wohler - - * mh-unit.el (mh-prune-trailing-spaces): Renamed to - mh-unit-prune-trailing-spaces to clean up the namespace. - (mh-files): Renamed to mh-unit-files. Ditto. - (mh-unit): Checkdoc fix. - - * mh-index.el (mh-index-p): Added autoload cookie since mh-index-p - is used by mh-customize.el. This calls for another mh-unit test - that looks for mh-autoloads for functions that are no longer used - in other files. - - * mh-loaddefs.el: Regenerated. - -2003-05-20 Satyaki Das - - * mh-unit.el (mh-unit-construct-call-graph): Factor out the code - to read the lisp files to a separate function. Also change it to - construct a function call-graph. Autoloaded functions are taken - into account. - (mh-unit-find-all-used-functions, mh-unit-called-functions) - (mh-unit-find-all-unused-functions): Find all unused functions by - computing a fixed point starting from the set of top level - functions. - (mh-unit-analyze-block): Removed. - (mh-unit-update-call-graph): mh-unit-functions-called was renamed - with modifications to update the function call graph. - -2003-05-19 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-utils.el (mh-notate): Modified to keep track of notation - that was replaced when sequence notation is added. Thus when the - sequence is deleted, the original notation is recovered. - (mh-add-msgs-to-seq): Modified to work with the new sequence - notation code. - - * mh-seq.el (mh-delete-seq, mh-put-msg-in-seq): Simplified since - we don't need to handle tick and unseen sequences specially any - more. - (mh-narrow-to-seq): Don't need to call mh-notate-user-sequences - since mh-copy-seq-to-eob already does that. - (mh-widen): Remove sequence notation, so that notation when - messages are replied to aren't lost. - (mh-copy-seq-to-eob): Simplified with the use of - mh-iterate-on-range. - (mh-thread-inc): This function doesn't need to notate user - sequences since its callers already do that. - (mh-thread-parse-scan-line): Simplified since mh-note-seq doesn't - appear in scan lines it is given as arguments. - (mh-thread-update-scan-line-map): Remove the test, since its - caller already does the required check. - (mh-thread-folder): Simplified by the use of mh-iterate-on-range. - (mh-tick-add-overlay, mh-tick-remove-overlay, mh-notate-tick): - These functions aren't needed any more, since overlays aren't used - any more. Also overlays aren't portable to XEmacs, so nasty - conditional code that used overlays in Emacs and extents in XEmacs - have been eliminated. - (mh-toggle-tick): Generalize it to work on a range of messages - like the other interactive messages. - - * mh-funcs.el (mh-undo-folder): Use mh-remove-all-notation - instead of mh-unmark-all-headers. - - * mh-e.el (mh-folder-font-lock-keywords): The entry for unseen - sequence highlighting is now done by the macro. - (mh-generate-sequence-font-lock): New macro to highlight any - arbitrary sequence. This macro is invoked twice to get the - highlighting for unseen and tick sequences. - (mh-sequence-notation-history, mh-folder-mode): New variable that - keeps track of the old notation when a message is notated with - mh-note-seq. - (mh-regenerate-headers, mh-get-new-mail): Add appropriate calls to - mh-notate-user-sequences and mh-remove-all-notation. - (mh-unmark-all-headers): Add comment that this function shouldn't - be used any more. - (mh-add-sequence-notation, mh-remove-sequence-notation): New - functions to notate message with mh-note-seq and to remove it. - (mh-remove-all-notation): Simplified to use mh-iterate-on-range. - (mh-process-commands): Use mh-remove-all-notation instead of - mh-unmark-all-headers. - (mh-notate-user-sequences, mh-delete-msg-from-seq): Simplified - since the tick and unseen sequences don't need special handling - any more. - (mh-internal-seq): Make it possible to dynamically change what - sequences are treated as internal (internal means font lock is - used to highlight the sequence). - (mh-clear-text-properties): Removed since it isn't needed - anymore. - -2003-05-19 Satyaki Das - - * mh-unit.el (mh-unit-analyze-block, mh-unit-interactive-function-p) - (mh-unit-find-all-unused-functions): Change argument name bl to - block. - -2003-05-19 Satyaki Das - - * mh-unit.el (mh-unit-find-all-unused-functions): New interactive - function to find all unused functions in MH-E. - (mh-unit-analyze-block, mh-unit-interactive-function-p) - (mh-unit-functions-called): Functions used by - mh-unit-find-all-unused-functions do its job. - - * Makefile (compile): Byte-compile mh-unit.el, since the analysis - to find unused code runs faster when compiled. - -2003-05-18 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-seq.el (mh-notate-deleted-and-refiled): Add autoload - declaration since this function is used in mh-index.el. - - * mh-e.el, mh-customize.el, mh-utils.el: Adjust require/provide - statements so that mh-e.el isn't loaded twice. - -2003-05-15 Satyaki Das - - * mh-utils.el (mh-defun-show-buffer): Arrange for the current - line in the folder buffer to be highlighted even when we are in - the show buffer. - -2003-05-14 Satyaki Das - - * mh-seq.el (mh-read-range): Allow this to work on invalid - sequences that only MH-E knows about. - - * mh-index.el (mh-create-sequence-map, mh-index-add-to-sequence) - (mh-index-delete-from-sequence): Don't consider sequences that - aren't valid MH sequences. - - * mh-e.el (mh-valid-seq-p): New predicate to check if a symbol - could be a MH sequence. - (mh-undefine-sequence, mh-define-sequence): Don't execute "mark" - unless the sequence name is a valid MH sequence. - - * mh-utils.el (mh-exec-cmd): In case an error happens in the - call-process and non-strings are present in ARGS, then the error - message isn't properly displayed. The change fixes this. - -2003-05-14 Peter S Galbraith - - * mh-mime.el (mh-mime-save-part): Bug Fix: Make sure - `mm-default-directory' gets a trailing "/" if - `mh-mime-save-parts-directory' doesn't have one. Otherwise the - default in the prompt of `mh-mm-save-part' will be wrong. Perhaps - `mh-mm-save-part' needs to do this check itself. - -2003-05-14 Satyaki Das - - * mh-index.el (mh-unpropagated-sequences): New function and - variable to keep track of sequences that shouldn't be propagated. - (mh-create-sequence-map, mh-index-add-to-sequence) - (mh-index-delete-from-sequence): Use mh-unpropagated-sequences to - stop changes to some sequences being reflected back to the source - folders. - -2003-05-13 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-e.el (mh-process-commands): Preserve sequences when messages - are refiled (closes SF #737128). - - * mh-index.el (mh-create-sequence-map) - (mh-index-create-sequences): Refactor code that is reused into a - new function. - - * mh-customize.el (mh-refile-preserves-sequences-flag): New - customizable flag that controls whether sequences are preserved - when messages are refiled. - -2003-05-13 Eric Ding - - * mh-e.el (mh-scan-format): The argument for scan format files - should be -form, not -format. - -2003-05-13 Satyaki Das - - * mh-seq.el (mh-widen): The scan line map stack was not being - properly updated when ALL-FLAG is non-nil. The change fixes that. - - * mh-e.el (mh-reset-threads-and-narrowing): The change resets the - scan line map stack. - -2003-05-12 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-seq.el (mh-thread-scan-line-map-stack) - (mh-thread-old-scan-line-map): Instead of the old scan line map, - now we need to maintain a stack of scan line maps. - (mh-narrow-to-seq): Modified so that multiple level of narrowings - can be done. We now maintain a stack of old views instead of - hiding the old scan lines. This makes it possible to have - multiple levels of narrowings. - (mh-widen): A optional prefix arg was added to allow undoing all - narrowing. - (mh-read-seq-default, mh-read-range): Don't use - mh-narrowed-to-seq, since it doesn't exist any more. - (mh-thread-initialize-hash, mh-thread-initialize): The - mh-thread-initialize function has been refactored. - (mh-thread-update-scan-line-map): Maintain notations in the stack - of scan line maps. - (mh-notate-tick, mh-toggle-tick): Simplified, since we don't have - mh-narrowed-to-seq any more. This means there is a slight loss of - functionality. Earlier if we narrowed to the tick sequence the - ticked messages weren't highlighted. This feature isn't present - any more. - - * mh-e.el (mh-execute-commands, mh-reset-threads-and-narrowing) - (mh-folder-sequence-menu, mh-get-new-mail): Use - mh-folder-view-stack instead of the now removed - mh-narrowed-to-seq. - (mh-narrowed-to-seq, mh-tick-seq-changed-when-narrowed-flag): - These variables have been removed. - (mh-folder-view-stack): New variable to keep track of a stack of - narrowings. - (mh-execute-commands, mh-get-new-mail): Add extra argument to - mh-widen so that all narrowings are undone. - - * Makefile (MH-E-SRC, MH-E-OTHERS): Move mh-gnus.el from MH-E-SRC - to MH-E-OTHERS so that it isn't byte compiled. - -2003-05-10 Satyaki Das - - * mh-seq.el (mh-read-seq): Improve the function a bit by adding - history to the sequence prompt. - -2003-05-09 Satyaki Das - - * mh-gnus.el: New file that won't be byte-compiled. From now on - having different Gnus versions at run-time and compile-time won't - cause errors in MH-E. - - * mh-mime.el (mh-small-show-buffer-p, mh-display-smileys) - (mh-display-emphasis): Handle all legal values of - font-lock-maximum-size. The existing code assumed didn't consider - the case where it could be an alist. - (mh-small-image-p): Simplified, so that aliasing XEmacs functions - in Emacs isn't necessary any more. - (mh-mm-display-part): Remove unnecessary call to fboundp. The - mh-funcall-if-exists does that for us any way. - (mh-defun-compat, gnus-local-map-property, mm-merge-handles) - (mm-set-handle-multipart-parameter, mm-readable-p) - (mm-long-lines-p, mm-keep-viewer-alive-p, mm-destroy-parts) - (mh-mm-save-part, mm-handle-multipart-ctl-parameter): These - compatibility functions have been moved to mh-gnus.el. - - * Makefile (MH-E-SRC): Add mh-gnus.el. - - * mh-seq.el (mh-narrow-to-header-field) - (mh-current-message-header-field): Checkdoc fixes. - - * mh-e.el (mh-undefine-sequence): Since mh-coalesce-msg-list - returns a list, apply is needed. - -2003-05-09 Noel Cragg (tiny change) - - * mh-junk.el (mh-spamassassin-blacklist): Separate "--local" and - "--no-rebuild" arguments to call-process. - [Patch committed by satyaki] - -2003-05-08 Satyaki Das - - * mh-seq.el (mh-translate-range): Take into account different - semantics of split-string in Emacs and XEmacs. - (mh-read-pick-regexp, mh-narrow-to-from, mh-narrow-to-cc) - (mh-narrow-to-to, mh-narrow-to-header-field) - (mh-current-message-header-field, mh-narrow-to-range): New - narrowing functions that can select messages based on different - message headers. - - * mh-utils.el (mh-show-limit-map): Add new narrowing functions - callable from the show buffer. - - * mh-e.el (mh-help-messages): Add help text for new functions. - (mh-limit-map): Add new narrowing functions (closes SF #732823). - -2003-05-07 Satyaki Das - - * mh-utils.el (mh-collect-folder-names): Use mh-exec-daemon to - run flists. This means we don't have to remember to expand the MH - executable in the mh-progs path. - (mh-exec-cmd-daemon): Return the new process object produced. - -2003-05-06 Satyaki Das - - * mh-e.el (mh-folder-font-lock-unseen): Use mh-seq-list to do - unseen sequence highlighting instead of reading the .mh_sequences - file from disk every time. - -2003-05-05 Satyaki Das - - * mh-utils.el (mh-show-sequence-map): Add key binding for S' - (closes SF #732825). - - * mh-e.el (mh-sequence-map): Ditto. - (mh-help-messages): Updated for S'. - -2003-05-04 Satyaki Das - - * mh-index.el (mh-index-write-data): The with-temp-buffer macro - is a bit better than write-file, so use that instead. - -2003-05-03 Satyaki Das - - * mh-index.el (mh-index-update-maps, mh-index-search) - (mh-index-sequenced-messages): Write index data to disk. This - allows us to recover index folder information if Emacs is - restarted, or the index folder is visited after the buffer has - been killed (closes SF #701762). - (mh-index-write-data, mh-index-read-data) - (mh-index-write-hashtable, mh-index-read-hashtable): Functions to - store and read index data information to disk. - (mh-index-insert-folder-headers, mh-index-group-by-folder): We - can no longer use object identity to compare strings, since they - might have been read back from disk. - - * mh-e.el (mh-index-data-file): New variable that stores the name - of the file that keeps track of index folder data. - (mh-make-folder): Read index folder data if available. - - * mh-utils.el (mh-show, mh-summary-height, mh-modify): Make - checkdoc happy. - - * mh-seq.el (mh-tick-add-overlay): Rearrange code to make code - more uniform. - - * mh-loaddefs.el: Regenerated. - -2003-05-02 Satyaki Das - - * mh-seq.el (mh-tick-add-overlay): If a message with a short scan - line is ticked, then the highlighting didn't extend to the right - margin. This change fixes that. - -2003-05-01 Bill Wohler - - * mh-e.el (mh-help-messages): Added brackets around / and - downcased limit to be consistent with other commands with - punctuation keybindings. Don't document aliases. - -2003-05-01 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-seq.el (mh-read-range): Fix comment. - -2003-04-30 Mark D. Baushke - - * mh-e.el (mh-help-messages): Better documentation for the F map. - -2003-04-30 Satyaki Das - - * mh-utils.el (mh-find-path): Cache folder names so that - folder name completion is always fast. - (mh-flists-partial-line, mh-flists-process): Variables used for - pre-caching folder names. - (mh-collect-folder-names, mh-collect-folder-names-filter) - (mh-populate-sub-folders-cache): Functions to pre-cache folder - names. - (mh-exec-cmd): Produce more info in *MH-E Log*. - - * mh-index.el (mh-index-search): Call the correct function. - (mh-index-sequenced-messages): If folders is nil, then all mail - is searched. The change restores that. - -2003-04-30 Peter S Galbraith - - * mh-customize.el (mh-summary-height): Move variable integer out - of defcustom, and instead specify that `nil' means to calculate - that size dynamically. Fixes SF #723267. - - * mh-utils.el (mh-summary-height): New function. Return ideal - mh-summary-height value for current frame height. - (mh-show-msg): Use it. - -2003-04-30 Mark D. Baushke - - * mh-index.el (mh-index-ticked-messages): Fix prompt and - description string. - (mh-index-new-messages): Ditto. - - * mh-loaddefs.el: Regenerated. - - * mh-index.el (mh-index-sequenced-messages): Renamed from - mh-index-new-messages with minor argument change. - (mh-index-new-messages): Implement by calling - mh-index-sequenced-messages with the appropriate arguments. - (mh-index-ticked-messages): New function. Does the same thing as - mh-index-new-messages, but on its own set of folders and using the - mh-tick-seq instead of mh-unseen-seq. - - * mh-e.el (mh-folder-map): Add "F'" to the map for - mh-index-ticked-messages. - (mh-help-messages): Replace broken [t]hread with [n]ew messages. - - * mh-customize.el (mh-index-ticked-messages-folders): New user - customizable flag that controls the folders to be searched by - mh-index-ticked-messages. - - * mh-utils.el (mh-show-index-ticked-messages): Wrapper for - mh-index-ticked-messages. - (mh-show-folder-map): Add "F'" to the map for - mh-index-ticked-messages. - -2003-04-30 Satyaki Das - - * mh-index.el (mh-index-search): The old cur in the source folder - might not exist. This could cause mh-exec-cmd to fail. So don't - add an error message in that case. - -2003-04-29 Satyaki Das - - * mh-e.el (mh-folder-from-address): Modified to allow multiple - Cc: headers to work properly. - (mh-inc-folder, mh-visit-folder): Fix an off by one error. - - * mh-utils.el (mh-notate): Update the scan line map. This fixes a - tiny bug. In threaded view, if a message is replied to then the - message is notated with a "-". Now if inc is done then the "-" - added is lost. The change fixes this. - - * mh-seq.el (mh-translate-range): Use the correct function. - (mh-thread-update-scan-line-map): New function that updates the - scan line map when a message is notated. - -2003-04-28 Satyaki Das - - * mh-index.el (mh-index-parse-search-regexp): Avoid compiler - warning in GNU Emacs 21.3. - - * mh-seq.el (mh-widen): Ditto. - -2003-04-28 Satyaki Das - - * mh-customize.el (mh-interpret-number-as-range-flag): New user - customizable flag that controls whether a single number, N is - interpreted as the range last:N. - - * mh-seq.el (mh-read-range): Generalize it for use when reading - range to scan. - (mh-interactive-range): Modified to use the new mh-read-range. - - * mh-speed.el (mh-speed-view): Use mh-read-range instead of the - now removed mh-read-msg-range function. - - * mh-funcs.el (mh-pack-folder): Ditto. - - * mh-e.el (mh-rescan-folder, mh-visit-folder): Ditto. - (mh-read-msg-range): Removed. - - * mh-loaddefs.el: Regenerated - -2003-04-27 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-seq.el (mh-range-completion-function): Fix checkdoc warning. - (mh-iterate-on-range): Mention that the macro can iterate over a - MH message range too. - -2003-04-27 Bill Wohler - - * mh-unit.el (mh-unit): As it turns out, lm-crack-copyright has - been updated to handle multiple-line copyrights in 21.3, so - updated code to run lm-verify only if user has 21.3 or greater. - Delete buffers after use, unless user already had buffer open. - -2003-04-27 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-index.el (mh-index-search): The MH command "refile" changes - cur. The change restores cur in source folders. - (mh-index-new-messages): Use the appropriate arguments for - mh-read-seq. - - * mh-seq.el (mh-read-seq-default, mh-read-seq): Restore these - functions to just read sequence names. - (mh-range-seq-names, mh-range-history, mh-range-completion-map) - (mh-range-completion-function, mh-read-range): New function which - reads MH range with completion and history. - (mh-interactive-range): Use mh-read-range instead of - mh-read-seq-default. - (mh-put-msg-in-seq): Change documentation about MH message range. - - * mh-junk.el (mh-junk-blacklist, mh-junk-whitelist): Change - documentation about MH message range. - - * mh-funcs.el (mh-copy-msg, mh-print-msg): Ditto. - - * mh-e.el (mh-delete-msg, mh-delete-msg-no-motion) - (mh-refile-msg, mh-undo, mh-delete-msg-from-seq): Ditto. - - * mh-comp.el (mh-forward): Ditto. - -2003-04-26 Satyaki Das - - * mh-comp.el, mh-e.el, mh-funcs.el, mh-junk.el, mh-seq.el: - Replace msg-or-seq with range everywhere. - - * mh-loaddefs.el: Regenerated. - -2003-04-25 Satyaki Das - - * mh-e.el (mh-index-sequence-search-flag, mh-folder-mode): New - local variable to remember that a folder buffer contains results - from a sequence search. This is needed so that "C-u F i" will work - as expected. - (mh-visit-folder): Create sequences in the index folder. - (mh-process-commands, mh-delete-msg-from-seq): If speedbar is on - then update the speedbar message counts immediately. - (mh-delete-msg-from-seq): Make the code faster by calling "mark" - just once. Also update source folder sequence if messages are - being deleted from a sequence in an index folder. - (mh-undefine-sequence): Simplified to remove the speedbar updating - code. Also DTRT and don't change any sequence when called with an - empty list of messages. - (mh-refile-msg, mh-delete-msg): Move to next message only if the - current message has been deleted or refiled, as the case may be. - - * mh-utils.el (mh-show-msg): Update the message counts in the - speedbar, if it is on, immediately. - (mh-speed-flists-active-p, mh-speed-flists-inhibit-flag): A new - flag has been added which inhibits updating of the speedbar. This - is used to avoid needless speedbar updates when - mh-execute-commands is called in index folders. - - * mh-speed.el (mh-speed-flists): Extended so that multiple - folders can be given as arguments. Also the code that kept track - of the current folder, needed since flists adds an extra ?+ char - at the end of the current folder name, wasn't entirely correct. - That has also been fixed. - - * mh-seq.el (mh-delete-seq, mh-put-msg-in-seq): Modified so that - sequence in source folder is updated if we delete a sequence in an - index folder. - (mh-read-seq, mh-read-seq-default, mh-translate-range) - (mh-interactive-msg-or-seq): The mh-interactive-msg-or-seq - function can read in an arbitrary MH message range. - (mh-iterate-on-msg-or-seq): The macro has been extended to work on - a MH range. - (mh-subject-to-sequence, mh-subject-to-sequence-unthreaded) - (mh-subject-to-sequence-threaded, mh-thread-find-msg-subject): Fix - the mh-subject-to-sequence function so that it will work in - threaded folders too. - (mh-tick-add-overlay): Fix a leak of overlays. - (mh-toggle-tick): Ticking, or unticking, messages in the index - folder is propagated to the source folders (closes SF #709664). - - * mh-index.el (mh-flists-results-folder, mh-flists-sequence) - (mh-flists-called-flag): New variables to implement searching for - arbitrary sequences. - (mh-index-generate-pretty-name): Updated so that folder names are - generated for flists search that can take any sequence name. - (mh-index-search): Since sequences are now properly maintained the - unseen-flag argument isn't needed and hence removed. Also redoing - a sequence search with "C-u F i" is handled correctly. Finally - the speedbar is updated to reflect the new index folder created. - (mh-index-create-sequences): New function that creates sequences - in the index folder. - (mh-index-matching-source-msgs, mh-index-execute-commands): - Improved so that scan lines for refiled/deleted messages are - removed from the source folders as well. - (mh-index-add-to-sequence, mh-index-delete-from-sequence): New - functions to update sequences in source folder to reflect changes - in index folder. - (mh-index-quote-for-shell): A utility function to that quotes - characters with special meaning to /bin/sh. - (mh-flists-execute, mh-index-new-messages): Updated to search for - arbitrary sequences (closes SF #718833). - - * mh-loaddefs.el: Regenerated. - -2003-04-25 Bill Wohler - - * mh-customize.el (mh-kill-folder-suppress-prompt-hook): New hook - used by mh-kill-folder to suppress the prompt. - - * mh-funcs.el (mh-kill-folder): Suppress prompt not if - mh-index-data is non-nil, but if any functions in - mh-kill-folder-suppress-prompt-hook return non-nil. - - * mh-index.el (mh-index-p): New function with returns non-nil if - the current folder was generated by an index search for use by - mh-kill-folder-suppress-prompt-hook - - * mh-unit.el (mh-unit): Commented out lm-verify step until code - updated to handle split Copyright lines. - - * mh-e.el (mh-version): Set to 7.3+cvs. - -2003-04-24 Bill Wohler - - 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 - - * 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 - - * mh-unit.el (mh-files): Fix the list of files to check. - -2003-04-24 Bill Wohler - - * 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 - - * 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 - - * mh-utils.el (mh-normalize-folder-name): Make the completion - code work properly with XEmacs. This change is needed 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * mh-utils.el (mh-do-in-gnu-emacs, mh-do-in-xemacs): Add - indentation hooks for the macros. - -2003-04-11 Bill Wohler - - * 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 - - * mh-seq.el (mh-iterate-on-msg-or-seq): Add a missed comma. - -2003-04-10 Satyaki Das - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * mh-loaddefs.el: Regenerated. - * mh-funcs.el (mh-ephem-message): autoload. - -2003-04-04 Peter S Galbraith - - * mh-e.el (mh-folder-from-address): Minor Fix. Wrong ending of - `when' block. - -2003-04-04 Satyaki Das - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * mh-xemacs-toolbar.el (mh-xemacs-toolbar-*-icon): Use original - 24x24 icons, changing background only. - -2003-03-27 Satyaki Das - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 be 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * mh-customize.el (mh-invisible-header-fields): Added X-Bogosity - for bogofilter. - -2003-03-21 Satyaki Das - - * 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): An 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 - - * 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 - - * mh-customize.el (mh-invisible-header-fields): Added - X-Spam-Checker-Version. - (mh-auto-fields-list): checkdoc fix. - -2003-03-12 Satyaki Das - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * mh-mime.el (mh-mime-security-button-map): Use 'mh-push-button' - in XEmacs as well. - -2003-03-07 Satyaki Das - - * 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 - - * mh-xemacs-compat.el (mh-modeline-logo): New constant holding the - modeline image. - (mh-modeline-glyph): Use it. - -2003-03-08 Steve Youngs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * mh-xemacs-compat.el (replace-regexp-in-string): Remove the - definition since it isn't used any more. - -2003-02-20 Peter S Galbraith - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 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 - - * 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 - - * 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 - - * 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 - - * 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ä - - * mh-comp.el: Add autoloaded auto-mode-alist association. - -2003-02-13 Satyaki Das - - * mh-utils.el (mh-face-display-function): Make the XEmacs part a - little simpler. - -2003-02-14 Steve Youngs - - * 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 honor 'mh-show-xface-face' - when using internal xface image support. - -2003-02-12 Peter S Galbraith - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * mh-customize.el (mh-invisible-header-fields): Add - "X-Notes-Item:" which is generated by Lotus Notes Domino. See - URL for details on how Domino - users may disable (restore the default) generation of these headers. - -2003-02-10 Satyaki Das - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - Released MH-E version 7.2. - - * MH-E-NEWS, README: Updated for release 7.2. - - * mh-e.el (Version, mh-version): Updated for release 7.2. - -2003-02-03 Bill Wohler - - * Makefile (dist): mkdir needs to happen *before* files are - copied. - - * MH-E-NEWS: Fixed some awkward verbiage. - -2003-02-02 Bill Wohler - - * mh-customize.el (mh-invisible-headers): Surround regexp-opt - expression in parens to avoid problems viewing certain messages. - -2003-01-30 Satyaki Das - - * mh-speed.el (mh-speed-flists): Search for flists in mh-progs. - The original was inadvertently searching for flists in the user's - path. - -2003-01-27 Bill Wohler - - * mh-customize.el (mh-default-folder-must-exist-flag): Changed - default to t according to the principle of least surprise. - -2003-01-26 Bill Wohler - - * mh-utils.el: Checkdoc fixes. - - * mh-pick.el (mh-do-search, mh-search-folder): Checkdoc fixes. - - * mh-loaddefs.el: Regenerated (lm-verify fixes). - - * mh-index.el (mh-mairix-next-result): Checkdoc fixes. - - * mh-alias.el: lm-verify fix. - - * Makefile (MH-E-SRC): Added ChangeLog, now that Emacs has a - lisp/mh-e directory. - (MH-E-ETC-ETC): Removed ChangeLog. - (dist): Moved creation of mail directory next to copy of files - into mail directory. - (install-emacs): Copy $(MH-E-SRC) into new directory - $(EMACS_HOME/lisp/mh-e. - (MH-E-SRC): Moved ChangeLog into new variable MH-E-OTHERS and - include MH-E-LOADDEFS there too. - (mh-loaddefs.el): Added lines so that lm-verify passes. - (dist, install-emacs): Use MH-E-OTHERS instead of MH-E-LOADDEFS. - -2003-01-26 Jeffrey C Honig - - * mh-comp.el (mh-tidy-draft-buffer, mh-compose-and-send-mail): - Rename mh-kill-draft-hook to mh-tidy-draft-buffer. - -2003-01-25 Jeffrey C Honig - - * mh-utils.el (mh-exec-cmd, mh-exec-cmd-daemon) - (mh-process-daemon): Use mh-log-buffer for the output of commands - from mh-exec-cmd. - - * mh-utils.el (mh-temp-folders-buffer): Sequences and folders - lose the -temp from their buffer names as they are interesting to - the user. - - * mh-seq.el (mh-list-sequences): New name, mh-sequences-buffer as - it is intended to be interesting to the user. - - * mh-funcs.el (mh-list-folders): New name, mh-folders-buffer as it - is intended to be interesting to the user. - - * mh-comp.el (mh-check-whom, mh-compose-and-send-mail): Use - mh-recipients-buffer constant. Add a kill buffer hook to delete - the recipients buffer when a draft buffer is killed. - -2003-01-25 Satyaki Das - - * mh-customize.el (mh-customize): New interactive argument - deletes other windows. - (mh-tool-bar-show-set, mh-tool-bar-letter-set) - (mh-tool-bar-folder-set): Modified so that clicking the customize - and help buttons deletes the other windows in the frame. - - * mh-mime.el (mh-mm-inline-message): Remove unused code. - - * mh-seq.el (mh-notate-deleted-and-refiled): Fix a small bug where - the wrong notation was being used. - (mh-toggle-threads): The function had a bug if you did the - following starting from an unthreaded wide folder: - (1) Create a sequence with S p - (2) Narrow to new sequence with S n - (3) Thread narrowed folder with T t - (4) Kill sequence with S k - (5) Unthread narrowed folder with T t - At this point we would have an empty folder. The change fixes - this. - (mh-toggle-threads): Fix documentation. - - * mh-customize.el (mh-invisible-header-fields): Add - X-MHE-Checksum to invisible headers. - - * mh-comp.el (mh-insert-x-mailer): Slightly more informative - X-Mailer header. - -2003-01-24 Satyaki Das - - * mh-e.el (mh-header-display): Modified so that quoted-printable - or base64 encoded messages are left untouched. - - * mh-utils.el (mh-decode-content-transfer-encoded-message): Munge - the Content-Transfer-Encoding header so that the MIME decoding - routines of Gnus doesn't get confused. - (mh-display-msg): Use insert-file-contents-literally so that - display will work for non-ascii. - - * mh-mime.el (mh-mime-display): Use charset info to decode - message file (closes SF #655123). - -2003-01-24 Bill Wohler - - * mh-alias.el (mh-alias-add-alias-to-file): Removed period from - error message and added parens around error function. - -2003-01-24 Satyaki Das - - * mh-customize.el (mh-decode-quoted-printable-flag): Removed. - (mh-decode-content-transfer-encoded-message-flag): This replaces - mh-decode-quoted-printable-flag. - - * mh-utils.el (mh-decode-content-transfer-encoded-message): New - function which handles messages that are encoded as base64 or - quoted-printable (closes SF #674190). - (mh-decode-quoted-printable): Removed. - (mh-display-msg): Use mh-decode-content-transfer-encoded-message - instead of mh-decode-quoted-printable. - -2003-01-23 Satyaki Das - - * mh-seq.el (mh-thread-generate-scan-lines): Fix a little bug - that would occasionally cause angles ('<' and '>') to appear at - root level. - -2003-01-21 Satyaki Das - - * mh-seq.el (mh-notate-cur): Enable overlay arrow display in text - mode too. - - * mh-e.el (mh-folder-mode): Initialize overlay-arrow-string so - that a '>' is displayed in text mode. - -2003-01-20 Satyaki Das - - * mh-utils.el (mh-scan-msg-overflow-regexp): Change the variable - so that a space is always maintained in the beginning of the scan - line. - - * mh-seq.el (mh-notate-seq, mh-notate-cur): Make the functions - faster by cutting down on the use of mh-goto-msg. - (mh-toggle-threads): Add call to mh-notate-cur, since inserting - the folder names in a search results folder screws up the - location of the overlay arrow. - - * mh-index.el (mh-index-delete-folder-headers): Position the - point on a message line if possible. - - * mh-funcs.el (mh-copy-msg): Use the mh-iterate macro to make the - function faster. - - * mh-e.el (mh-scan-folder): Reuse mh-notate-deleted-and-refiled. - - * mh-loaddefs.el: Regenerated. - - * mh-utils.el (mh-add-msgs-to-seq): Add a new parameter that - suppresses the annotation of the sequence since it is - inefficient. - - * mh-seq.el (mh-delete-seq): Speed up the part of the function - that removes the sequence notation. - (mh-put-msg-in-seq, mh-notate-deleted-and-refiled): Use - mh-iterate-on-messages-in-region to make the function fasters when - operating on regions. The key idea is to loop over the folder - buffer exactly once and do all annotations. The existing algo - would walk over the buffer multiple times thereby slowing things - down. - (mh-iterate-on-messages-in-region): Added an extra parameter which - is bound to the message index as the loop is executed. - (mh-region-to-msg-list, mh-thread-delete, mh-thread-refile): Use - the new mh-iterate-on-messages-in-region macro. - - * mh-e.el (mh-delete-msg-no-motion, mh-refile-msg, mh-undo): Same - as above. - (mh-notate-user-sequences): Change algorithm to make notating of - user sequences fast. - -2003-01-19 Satyaki Das - - * mh-logo.xpm: New image file that contains the MH-E logo. - Change foreground color to the blue in the MH-E logo. - - * Makefile (MH-E-IMG): Add mh-logo.xpm to list of image files. - - * mh-utils.el (mh-show-buffer-mode-line-buffer-id): Adjust it to - keep space in the beginning for the logo. - (mh-logo-cache): New variable that caches the logo image file - location. - (mh-logo-display): Display the MH-E logo on the mode line. - (mh-display-msg): Display logo in mh-show-mode. - - * mh-e.el (mh-make-folder-mode-line): Display logo in - mh-folder-mode. - - * mh-comp.el (mh-compose-and-send-mail): Display logo in - mh-letter-mode. - - * mh-loaddefs.el: Regenerated. - - * mh-seq.el (mh-iterate-on-messages-in-region): New macro to - iterate on all messages in a region. - (mh-region-to-msg-list): Simplified since it uses - mh-iterate-on-messages-in-region now. - - * mh-e.el (mh-delete-msg, mh-refile-msg): Change interactive spec - to pass the region that is to be deleted when appropriate. - (mh-delete-msg-no-motion, mh-refile-msg, mh-undo): Operate on - regions directly without creating the list of messages to be - deleted/refiled. - (mh-delete-a-msg, mh-refile-a-msg, mh-undo-msg): The msg - parameter in these functions can now be nil. If so, the current - message is deleted, refiled or undone respectively. Avoids the - use of mh-goto-msg in this case and speeds up operations on - regions quite a bit. - -2003-01-19 Peter S Galbraith - - * mh-alias.el (mh-read-address): Bug Fix. In XEmacs and Emacs20, - it would always prompt using "To: " instead of using the command - argument (closes SF #670913). - -2003-01-19 Satyaki Das - - * mh-utils.el (mh-folder-completion-function): If there is a - +foo/bar folder and the user types foo//bar then the completion - function would say a match happened without showing the - normalized folder name. This change fixes that. - -2003-01-18 Satyaki Das - - * mh-e.el (mh-rmail): Modified so that new and unseen messages - are shown (closes SF #667542). - -2003-01-17 Satyaki Das - - * mh-index.el (mh-index-generate-pretty-name): Generate nicer - names. In particular all '-' characters are removed. - -2003-01-16 Satyaki Das - - * mh-customize.el (mh-index-program): Documentation fix. - - * mh-loaddefs.el: Regenerated. - - * mh-customize.el (mh-index-program): Add choices for mairix and - pick. - - * mh-index.el (mh-indexer-choices): Add search interfaces for - mairix and pick. - (mh-index-search): Add links for mairix and pick. - (mh-index-pick-folder, mh-pick-binary): Variables needed to - implement pick support. - (mh-pick-execute-search, mh-pick-next-result): New functions to - implement pick support. - (mh-mairix-binary, mh-mairix-directory, mh-mairix-folder): New - variables for mairix support. - (mh-mairix-execute-search, mh-mairix-next-result) - (mh-mairix-regexp-builder, mh-mairix-convert-to-sop*): New - functions for mairix. - - * mh-funcs.el (mh-kill-folder): Move message to the end. - - * mh-e.el (mh-folder-mode): Make overlay-arrow-position and - overlay-arrow-string local variables so that the arrow will - remain even if some other folder is visited. - (mh-remove-cur-notation, mh-remove-all-notation): The test isn't - required any more since overlay-arrow-position is local. - (mh-goto-cur-msg): Remove overlay arrow if current message - doesn't exist. - - * mh-seq.el (mh-notate-cur): Don't need to set - overlay-arrow-string any more since it is local and has been set - at initialization. - -2003-01-15 Satyaki Das - - * mh-speed.el (mh-speed-current-folder): Keep track of current - folder when flists is called. - (mh-speed-flists, mh-speed-parse-flists-output): Try to avoid - ambiguity when folders are present with + at the end of the name. - Unfortunately it can't always be avoided. - - * mh-e.el (mh-folder-size): Remove the unnecessary error check. - (mh-parse-flist-output-line): Add extra argument which - occasionally avoid problems with folder names that end with '+'. - - * mh-utils.el (mh-sub-folders-actual): Fix the folder name - parsing so that it doesn't get confused by trailing '+' chars in - the folder name. - -2003-01-14 Satyaki Das - - * mh-utils.el (mh-normalize-folder-name): Enhanced so that it can - now handle ".." and "." correctly during folder name completion. - (mh-normalize-folder-name): Avoid error in boundary condition - where the folder string is empty. - -2003-01-14 Mark D. Baushke - - * mh-e.el (mh-visit-folder): Pass `current-prefix-arg' to - the `mh-read-msg-range' function as the optional - always-prompt-flag. - -2003-01-14 Satyaki Das - - * mh-utils.el (mh-normalize-folder-name): New function that - normalizes folder names. - (mh-sub-folders): Use mh-normalize-folder-name. Also the function - has been modified so that a trailing slash is only added if the - folder potentially has subfolders. - (mh-sub-folders-actual): Simplified since the folder has already - been normalized in mh-sub-folders. - (mh-remove-from-sub-folders-cache): Modified so that the cached - results of two of the folders ancestors are invalidated. - (mh-folder-completion-map): Ugly hack to make the error go away - when minibuffer-complete-word is called. - (mh-folder-completion-function): The completion function will now - be more selective in adding '/' at the end of completed folder - names. - (mh-folder-completing-read): The folder name is normalized before - return. The minibuffer-local-completion-map is shadowed to avoid - error with SPC (bound to minibuffer-complete-word). We really - need a better solution. - -2003-01-13 Bill Wohler - - * mh-seq.el: Edited comment and docstring text to conform with RFC - 2822 terminology. Message-ID is the header field. It contains a - message identifier. - -2003-01-13 Satyaki Das - - * mh-utils.el (mh-sub-folders): Add an argument that returns - sub-folders with a / character appended at the end. - (mh-folder-completion-function): Modify the function so that one - tab is now sufficient to complete the folder name and add a - trailing /. - (mh-folder-completing-read): Remove the trailing / that the - completion function now adds to the folder name. Also multiple / - characters in the folder input are removed. So if the user inputs - +foo///bar//baz///// then that will be converted to +foo/bar/baz. - This will improve the performance of caching. - - * mh-seq.el (mh-notate-cur): Check that a valid current message - exists before trying to notate (closes SF #667331). - (mh-message-id-regexp): New variable to store regexp to recognize - message-ids. - (mh-thread-generate): Use mh-message-id-regexp to filter out non - message-id's from the References: header. - -2003-01-12 Satyaki Das - - * mh-seq.el (mh-notate-cur): Disable overlay-arrow display if we - aren't on a graphic display. - -2003-01-11 Satyaki Das - - * mh-seq.el (mh-notate-cur): New function to notate the current - message. The marker in the fringe is updated too. - (mh-narrow-to-seq, mh-widen, mh-thread-inc, mh-thread-folder): Use - the specialized function mh-notate-cur instead of mh-notate-seq. - - * mh-e.el (mh-arrow-marker): New buffer local variable to store - the position where the marker in the fringe is going to be - displayed (closes SF #664824). - (mh-folder-mode): Create a marker for the fringe. - (mh-update-sequences, mh-get-new-mail, mh-goto-cur-msg): Call the - specialized function mh-notate-cur instead of mh-notate-seq or - mh-notate. - (mh-remove-cur-notation, mh-remove-all-notation): Reset the - overlay-arrow-position if needed. - - * mh-loaddefs.el: Regenerated. - -2003-01-10 Satyaki Das - - * mh-utils.el (mh-remove-from-sub-folders-cache): Modified so that - creating nested folders doesn't produce inconsistent results. - (mh-prompt-for-folder): Remove call of mh-folder-list-change-hook. - - * mh-funcs.el (mh-kill-folder): Don't ask for confirmation if - called on a folder holding index search results. Also the now - removed mh-folder-list-change-hook is called no more. - - * mh-customize.el (mh-auto-folder-collect-flag) - (mh-folder-list-change-hook): Removed. - - * mh-loaddefs.el: Regenerated. - -2003-01-10 Bill Wohler - - * mh-customize.el (mh-default-folder-must-exist-flag): New - variable to suppress suggested folder if the folder doesn't - already exist (closes SF #657096). - (mh-default-folder-list): New variable that - holds mapping between an address and the desired folder for - filing (closes SF #657096). - (mh-default-folder-prefix, mh-default-folder-must-exist-flag): In - docstring, refer to documentation for mh-prompt-for-refile-folder - and mh-folder-from-address. - (mh-highlight-citation-p, mh-compose-insertion) - (mh-insert-mail-followup-to-list, mh-index-program) - (mh-identity-default): Fixed case of tags. - - * mh-e.el (mh-folder-from-address): Use new variable - mh-default-folder-must-exist-flag to return nil if this variable - is t and the folder doesn't already exist. In addition, can now - look up a default folder in the new variable - mh-default-folder-list (closes SF #657096). - (mh-prompt-for-refile-folder): In docstring, refer to - documentation in mh-folder-from-address. - - * mh-index.el (mh-swish-execute-search): Changed \..* to \\..* in - the FileRules filename in the sample config file. Otherwise, the - users don't see the backslash at all, and no files are indexed! - (closes SF #665888). - -2003-01-10 Satyaki Das - - * mh-seq.el (mh-thread-folder): Get headers for exactly the - messages that are present. If only messages 1-10 and 3800-3900 - are being shown then we will now scan exactly those messages and - not the full range from 1-3900 as was being done earlier. - (mh-toggle-threads): When converting from threaded to normal view - only the messages present in the buffer are scanned. Earlier all - messages from the minimum to the maximum would be scanned (closes - SF #626117). - - * mh-pick.el (mh-search-folder): Fix typo. - (mh-pick-do-search): Fix bug from cut and paste. Also set window - config properly. - - * mh-utils.el (mh-prompt-for-folder): Add new argument to allow - it to accept + as a folder name. This allows the user to search - all folders when "Fs" is used. - - * mh-pick.el (mh-search-folder): Fix interactive spec of function. - (mh-pick-do-search): Rewritten to call pick in one go. This will - make adding pick as a default index search program easier. Also - pick now accepts the same query syntax as the index search - programs (closes SF #664816). - (mh-next-pick-field): Removed. - (mh-pick-parse-search-buffer): New function to parse the search - buffer. - (mh-pick-construct-regexp, mh-pick-regexp-builder): New function - to produce a pick query from the parsed representation. - - * mh-index.el (mh-index-do-search): Refactor the search pattern - parser into a new function and use that instead. - - * mh-loaddefs.el: Regenerated. - -2003-01-10 Satyaki Das - - * mh-loaddefs.el: Regenerated. - - * mh-utils.el (mh-remove-from-sub-folders-cache) - (mh-prompt-for-folder): Replace mh-update-sub-folders-cache with - mh-remove-from-sub-folders-cache. - (mh-exec-cmd-daemon): Mention set-process-filter in documentation. - - * mh-pick.el (mh-searching-function): New buffer local variable - that keeps track of the default searching function to be used. - (mh-pick-mode): Make mh-searching-function buffer local. - (mh-search-folder): Set mh-searching-function to use pick. - (mh-search-folder, mh-pick-menu, mh-pick-mode-help-messages) - (mh-pick-mode, mh-do-pick-search, mh-pick-do-search): Rename - mh-do-pick-search to mh-pick-do-search. But keep - mh-do-pick-search as a deprecated function. - (mh-do-search): New interactive function that performs the - default search. - (mh-pick-mode-map): Update keymap. - - * mh-index.el (mh-index-search): Set mh-searching-function to do - index search. - (mh-index-new-folder): Replace mh-update-sub-folders-cache with - mh-remover-from-sub-folders-cache. - - * mh-funcs.el (mh-kill-folder): Same as above. - - * mh-index.el (mh-index-evaluate, mh-swish++-regexp-builder): - Checkdoc fixes. - - * mh-customize.el: Fixes to make byte compiler in CVS Emacs - perfectly happy. - -2003-01-09 Bill Wohler - - * mh-e.el (mh-folder-from-address): New function that proposes the - name of a folder with an alias for the address in the current message. - (mh-prompt-for-refile-folder): Use it (closes SF #657096). - - * mh-customize.el (mh-default-folder-prefix): New variable used by - mh-folder-from-address. - (mh-invisible-header-fields): Edited docstring. - - * mh-alias.el (mh-alias-address-to-alias): Added ;;;###mh-autoload - cookie (used by mh-folder-from-address in mh-e.el). Edited text in - comment. - - * mh-utils.el: Provided naming conventions for buffer and buffer - variable names. - (mh-temp-folders-buffer): Renamed buffer to " *mh-folders*". - (mh-temp-sequences-buffer): Renamed buffer to " *mh-sequences*". - (mh-info-buffer): Renamed from mh-temp-info-buffer. - (mh-log-buffer): New buffer variable to hold name of "*MH-E Log*" - buffer which is expected to be used for the output of MH commands. - Perhaps we always create this buffer at initialization and append - to it rather than erase it each time? - - * mh-e.el (mh-quit): Loop over all buffers and delete MH-E - temporary and working buffers. As long as the buffer naming - conventions are followed, new buffers will be automatically - killed. - (mh-version): Renamed mh-temp-info-buffer to mh-info-buffer. - - * mh-comp.el (mh-insert-x-mailer): Renamed mh-temp-info-buffer to - mh-info-buffer. - -2003-01-09 Satyaki Das - - * mh-e.el (mh-folder-size): If the user doesn't have a - Unseen-Sequence definition in .mh_profile then an error was - produced. This change fixes that. - - * mh-seq.el (mh-thread-generate): Replace the *mh-thread* buffer - with a temporary buffer which is cleaned up when the function - exits. - - * mh-e.el (mh-prompt-for-refile-folder): New function which - refactors out the intelligent folder guessing code from - mh-refile-msg. - (mh-refile-msg): Use mh-prompt-for-refile-folder. - - * mh-seq.el (mh-thread-refile): Use mh-prompt-for-refile-folder to - do the same intelligent destination folder guessing as - mh-refile-msg (closes SF #664829). - - * mh-utils.el (mh-folder-list, mh-make-folder-list-process) - (mh-folder-list-temp, mh-folder-list-partial-line) - (mh-set-folder-list): Removed. - (mh-sub-folders-cache, mh-sub-folders, mh-sub-folders-actual): - Moved over from mh-speed.el to implement hierarchical completion. - (mh-update-sub-folders-cache): Utility function called when - new folders are created or folders are removed. - (mh-folder-completion-function): New function is the folder name - completion function used in completing-read. - (mh-folder-completing-read): A thin wrapper function that is used - instead of completing-read directly. In the future we might want - to allow the user a customizable variable which will turn off - folders based completion. - (mh-prompt-for-folder): Use mh-folder-completing-read to read in - the folder name with hierarchical completion (closes SF #664821). - - * mh-speed.el (mh-speed-folders, mh-speed-folders-cache) - (mh-speed-folders-actual): Moved to mh-utils.el as mh-sub-folders, - mh-sub-folders-cache and mh-sub-folders-actual respectively. - (mh-speed-invalidate-map, mh-speed-invalidate-map) - (mh-speed-add-folder): Use the new names. - - * mh-funcs.el (mh-kill-folder): Remove code that used to update - mh-folder-list which is no longer present. Instead - mh-update-sub-folders-cache is called. - - * mh-index.el (mh-index-new-folder): Same as above. - -2003-01-08 Satyaki Das - - * mh-utils.el (mh-exec-cmd-daemon): An argument was added which - controls what is done with the process output. - - * mh-funcs.el (mh-kill-folder): Use mh-previous-window-config to - restore window configuration. Also the call to mh-exec-cmd-daemon - only displays output if an error happened (closes SF #664828). - (mh-rmf-daemon): Check rmf output and display it only if - something went wrong. - (mh-print-msg): Pass in nil argument to mh-exec-cmd-daemon. - - * mh-comp.el (mh-redistribute, mh-send-letter): Pass in nil - argument to mh-exec-cmd-daemon so that the functions will behave - as before. - - * mh-pick.el (mh-search-folder): The current window config is - stored. - (mh-make-pick-template): Make the message headers read-only. - (mh-pick-mode-help-messages): Update help message. - (mh-do-pick-search): Fix problem when buffer isn't showing any - messages. - (mh-next-pick-field): Use buffer-substring-no-properties is - better. - (mh-pick-mode-map): Add key bindings (partially addresses - SF #664816) - - * mh-index.el (mh-indexer-choices): Add a new field for each - index program choice. If it is non-nil then it is the name of a - function that given a lisp expression to search for generates a - pattern that is acceptable to the search program. - (mh-index-regexp-builder): New variable that stores the function - to be used to convert from the lisp expression syntax to - something that the search program understands. - (mh-index-generate-pretty-name): Generalized so that it can take - a list of strings as input. - (mh-index-search): Modified so that if the configured program has - a corresponding regexp-builder then a search buffer like pick - search is produced. Otherwise the previous behavior is maintained. - (mh-index-do-search): New interactive function that takes the - contents of the search buffer, generates an appropriate query and - produces the search results buffer by calling mh-index-search. - (mh-replace-string, mh-index-parse-search-regexp) - (mh-index-add-implicit-ops, mh-index-evaluate): New functions - which parses the infix search expression that the user enters. A - parse tree from which queries for different search programs can - be produced is produced. - (mh-swish++-regexp-builder, mh-swish++-print-regexp): Takes the - internal form of the query and produces input suitable for - swish++. - - * mh-loaddefs.el: Regenerated. - -2003-01-08 Bill Wohler - - * Makefile (emacs-logs): New target for viewing CVS Emacs logs. - Useful to see if an Emacs developer has changed MH-E. - - * MH-E-NEWS: Fixed case of MH-E in the "Changes" title. - - * mh-utils.el (mh-temp-info-buffer): New variable to hold name of - buffer that contains version info. - - * mh-e.el (mh-version): Use mh-temp-info-buffer instead of - mh-temp-buffer since version information was getting clobbered by - the aliasing code before it could be seen (closes SF #664467). - (mh-quit): Delete mh-temp-info-buffer. - - * mh-comp.el (mh-insert-x-mailer): Use mh-temp-info-buffer to find - version info instead of mh-temp-buffer. You kind of need this - patch to send mail. - -2003-01-07 Bill Wohler - - * mh-e.el (Version, mh-version): Set to 7.1+cvs. - -2003-01-07 Bill Wohler - - Released MH-E version 7.1. - - * MH-E-NEWS, README: Updated for release 7.1. - - * mh-e.el (Version, mh-version): Updated for release 7.1. - -2003-01-07 Bill Wohler - - * mh-customize.el (mh-auto-folder-collect-flag, - mh-alias-system-aliases, mh-alias-insert-file): Edited docstrings. - - * Makefile (MH-E-IMG): Added alias.pbm and alias.xpm. - - * mh-alias.el (mh-alias-insert-file, mh-alias-add-alias): Fixed - checkdoc warnings. - -2003-01-07 Satyaki Das - - * mh-utils.el (mh-search-from-end): New function that is used to - replace our usage of the CL function search. - (font-lock): The library is loaded to avoid compilation warning - in CVS Emacs. - - * mh-speed.el (mh-speed-goto-folder, mh-speed-add-folder) - (mh-speed-extract-folder-name, mh-speed-invalidate-map): Use - mh-search-from-end instead of search. - - * mh-seq.el (mh-thread-remove-parent-link): Use loop instead of - remove*. - (mh-thread-process-in-reply-to): Use mh-search-from-end instead - of search. - - * mh-index.el (mh-md5-parser): Fix name of function. - (mh-index-update-single-msg, mh-index-update-maps): Avoid using - destructuring-bind since Emacs-20.7 can't handle this particular - usage. - (mh-namazu-next-result): Use mh-search-from-end instead of - search. - - * mh-e.el (recursive-load-depth-limit): Add a defvar since CVS - emacs which doesn't have the variable defined causes a compiler - warning. - (mh-refile-a-msg): Rewritten to avoid using pushnew. - (mh-undo-msg): Use loop instead of remove-if. - - * mh-comp.el (mh-show-buffer-message-number): Use - mh-search-from-end instead of search. - -2003-01-01 Satyaki Das - - * mh-e.el (mh-visit-folder): Modified so that if RANGE is nil then - all messages are displayed. Documentation modified so that this is - explicitly stated. - (mh-visit-folder): Really fix it this time. - -2003-01-01 Mark D. Baushke - - * mh-alias.el (mh-alias-from-has-no-alias-p): Needs the - mh-autoload comment or mh-customize may have problems finding the - function. - - * mh-loaddefs.el: Regenerated. - -2002-12-28 Satyaki Das - - * mh-index.el (mh-namazu-execute-search): Fix bug in documentation. - -2002-12-28 Bill Wohler - - * mh-comp.el (mh-letter-mode): Mention mh-compose-insertion - variable in docstring, explain how to expand directives, and - don't mention mh-mhn-compose-insertion which isn't used directly - any more. - (mh-send-letter): Mention that X-Mailer and X-Face are inserted - automatically so that a user isn't tempted to do so himself in - mh-before-send-letter-hook. - (mh-insert-letter): Use "variable" prefix for mh-invisible-headers - now that we have both a function and a variable. Clarified - language a bit. - -2002-12-26 Satyaki Das - - * mh-utils.el (mh-show-xface-function): Only load x-face-e21 if - the emacs is not XEmacs. - - * mh-index.el (mh-index-new-folder): The folder created should - always be added to mh-folder-list. Otherwise folder name - completion doesn't find the new folder created. - -2002-12-24 Satyaki Das - - * mh-customize.el (mh-clean-message-header-flag) - (mh-visible-headers, mh-invisible-headers) - (mh-invisible-header-fields-set): Reworded to satisfy checkdoc. - - * mh-loaddefs.el: Regenerated. - - * mh-e.el (mh-inc-folder, mh-visit-folder, mh-read-msg-range): - Handle nil value of mh-large-folder properly. - - * mh-customize.el (mh-tool-bar-show-set, mh-tool-bar-letter-set) - (mh-tool-bar-folder-set, mh-tool-bar-folder-buttons) - (mh-invisible-headers, mh-invisible-header-fields-set): Checkdoc - fixes. - (mh-large-folder): Updated to allow for infinity. If - mh-large-folder is nil then all folders are deemed small. - -2002-12-23 Satyaki Das - - * mh-e.el (mh-inc-folder, mh-visit-folder): Emit a message if - threading was suppressed because the number of messages exceed - mh-large-folder. - -2002-12-23 Peter S Galbraith - - * mh-utils.el (mh-invisible-headers): Deleted. Moved to - mh-customize.el - - * mh-customize.el (mh-invisible-header-fields): New - defcustom. Simple user interface to change mh-invisible-headers. - (mh-invisible-header-fields-set): New function called when - mh-invisible-header-fields is set. - (mh-invisible-headers): New function. Does the actual work of - building the variable mh-invisible-headers from - mh-invisible-header-fields. - (mh-invisible-headers): defvar moved from mh-utils.el - -2002-12-22 Satyaki Das - - * mh-speed.el (mh-speed-folder-size): Removed. Something very - similar appears as mh-folder-size. - (mh-speed-view): Simplified since the range selection logic has - been moved to mh-read-msg-range. - (mh-speed-parse-flists-output-line): Moved to mh-e.el as - mh-parse-flist-output-line. - - * mh-funcs.el (mh-pack-folder): Use the new mh-read-msg-range. - - * mh-e.el (mh-rescan-folder): Use the new mh-read-msg-range. - (mh-parse-flist-output-line): Moved from mh-speed.el where this - function was called mh-speed-parse-flists-output-line. - (mh-folder-size): Renamed from mh-speed-folder-size. The function - has been made more general and can be called from any buffer and - not just the speedbar buffer. - (mh-visit-folder): Use the new mh-read-msg-range (addresses SF - #655891). - (mh-read-msg-range): Rewritten. - -2002-12-21 Satyaki Das - - * mh-seq.el (mh-delete-subject-or-thread): New interactive - function that intelligently deletes messages based on threading, - if the folder is threaded, or on subject if folder isn't threaded. - - * mh-utils.el (mh-show-delete-subject-or-thread): New interactive - function, callable from the show buffer, to intelligently delete - messages based on threading info or subject. - (mh-show-mode-map): Change binding of "k" to call - mh-show-delete-subject-or-thread. - - * mh-e.el (mh-folder-mode-map): Change binding of "k" to call - mh-delete-subject-or-thread. - - * mh-comp.el (mh-letter-mode-map): Add key binding for - mh-insert-identity. - - * mh-loaddefs.el: Regenerated. - -2002-12-21 Peter S Galbraith - - * mh-customize.el (mh-tool-bar-letter-set): Bug fix. The - `tool-bar-add-item-from-menu' items were broken. I can't use my - constants there. - -2002-12-21 Peter S Galbraith - - * mh-alias.el (mh-alias-insert-file): Bug fix. I never checked - that an AliasFile entry existed in .mh_profile. - -2002-12-21 Peter S Galbraith - - * mh-customize.el (mh-alias-insertion-location): New defustom. - Specifies where new aliases are entered in alias files. - - * mh-alias.el (mh-alias-add-alias-to-file): Use it. - -2002-12-21 Peter S Galbraith - - * mh-alias.el (mh-alias-add-alias-to-file): If ALIAS matches - exactly, prompt to [i]nsert before old value or [a]ppend after it. - (mh-alias-insert-file): Make sure we don't edit the passwd file. - Add optional argument for alias; If ALIAS is specified and it - already exists, try to return the file that contains it. - (mh-alias-which-file-has-alias): New function. Return the name of - writable file which defines ALIAS from list FILE-LIST. - (mh-alias-add-alias): Remove prompts for case of alias already - defined; done in mh-alias-add-alias-to-file. - -2002-12-21 Satyaki Das - - * mh-speed.el (mh-speed-folders-actual): Fix bug in parsing of - folder names that have spaces in them. The original function would - truncate the folder name at the first space. - (mh-speed-flists): Add -sequence option to flists. This guards - against the user specifying something other than the unseen - sequence in his .mh_profile. - (mh-speed-parse-flists-output-line): New function that parses a - single line in the output of flists to find the folder name and - the counts of unseesn and total messages. - (mh-speed-parse-flists-output): Fix parsing bug which truncates - the folder names at the first space. - - * mh-index.el (mh-index-generate-pretty-name): New function which - generates a nicer name for the search results. It trims white - space at the beginning and end and replaces white space with - underscores within the search regexp. - (mh-index-search): Use mh-index-generate-pretty-name. - - * mh-loaddefs.el: Regenerated. - -2002-12-20 Satyaki Das - - * mh-index.el (mh-index-new-folder): Add new folder to - mh-folder-list to enable name completion. - (mh-glimpse-execute-search, mh-swish-execute-search) - (mh-swish++-execute-search): Fix documentation. - - * mh-seq.el (mh-thread-generate): Fixed a stupid bug where the wrong - folder could get 'scan'ed when generating the threaded view. - - * mh-index.el (mh-index-search): If optional prefix arg is given - then the search in the current index buffer is redone. - (mh-glimpse-execute-search, mh-swish-execute-search) - (mh-namazu-execute-search): Documentation fixes. - - * mh-e.el (mh-index-previous-search): New buffer local variable - stores parameters of search that created the buffer. - (mh-folder-mode): Make mh-index-previous-search buffer local. - (mh-visit-folder): Tweak the function so that only a single window - with the folder buffer is shown if mh-showing-mode is nil. - - * mh-loaddefs.el: Regenerated. - -2002-12-19 Peter S Galbraith - - * mh-alias.el (mh-alias-add-alias): Bug fix. - -2002-12-19 Peter S Galbraith - - * mh-alias.el (mh-alias-add-alias): New interactive command. Add - ALIAS for ADDRESS in personal alias file. - (mh-alias-grab-from-field): New interactive command. Add ALIAS for - ADDRESS in personal alias file. - (mh-alias-add-address-under-point): New interactive - command. Insert an alias for email address under point. - (mh-alias-suggest-alias): New function. Suggest an alias for STRING. - (mh-alias-insert-file): New function. Return the alias file to - write a new entry in. - (mh-alias-address-to-alias): New function. Return the ADDRESS - alias if defined, or nil. - (mh-alias-from-has-no-alias-p): New function. Return t is From has - no current alias set. Used as tool-bar button enable function. - (mh-alias-add-alias-to-file): New function. Add ALIAS for ADDRESS - in alias FILE without alias check or prompts. - - * alias.xpm, alias.pbm: New tool-bar icon for - mh-alias-grab-from-field. - - * mh-e.el (mh-folder-line-matches-show-buffer-p): New function. - Return t if the message under point in folder-mode is in the show - buffer. - - * mh-utils.el (mh-goto-address-find-address-at-point): New - function copied from goto-addr.el, which we don't want to - force-load on users. Find e-mail address around or before point. - (mh-address-mail-regexp): New defvar. A regular expression - probably matching an e-mail address. - - * mh-customize.el (mh-alias-insert-file): New defcustom. - Filename to use to store new MH-E aliases. - (mh-tool-bar-folder-buttons): Enable mh-tool-bar-item-alias icon. - - * mh-comp.el (mh-extract-from-header-value): New function. - Extract From: string from header. - -2002-12-19 Satyaki Das - - * mh-index.el (mh-index-update-single-msg): New defvar controls - max number of command line args. - (mh-index-execute): New function which is to be used - instead of xargs so that we don't give the shell too many command - line args. - (mh-index-update-maps): Use mh-index-execute instead of xargs. - (mh-index-search): Remove unused code. Also the first message in - folder buffer is made current. - -2002-12-18 Peter S Galbraith - - * mh-loaddefs.el: Regenerated. - - * mh-comp.el (mh-letter-tool-bar-map): Moved to mh-customize.el - - * mh-e.el (mh-folder-tool-bar-map): Moved to mh-customize.el - - * mh-utils.el (mh-get-msg-num): autoloaded. - (mh-show-tool-bar-map): Moved to mh-customize.el - - * mh-customize.el (mh-tool-bar-item-*): 33 new defconsts for - tool-bar setup and customization. - (mh-tool-bar-folder-buttons-set): New function to setup the - tool-bar after customization. - (mh-tool-bar-folder-buttons): New defcustom to specify which icons - appears in the tool-bar. - (mh-tool-bar-letter-buttons-set): New function to setup the - tool-bar after customization. - (mh-tool-bar-letter-buttons): New defcustom to specify which icons - appears in the tool-bar. - (mh-tool-bar-show-set): New function to setup mh-letter-tool-bar-map. - (mh-tool-bar-letter-set): New function to setup - mh-letter-tool-bar-map. - -2002-12-18 Satyaki Das - - * mh-e.el (mh-folder-mode-map): Change entries for "\t", "\M-\t" - and backtab to call mh-index-next-folder and - mh-index-previous-folder as appropriate. - - * mh-index.el (mh-index-next-folder, mh-index-previous-folder): - New interactive functions which jumps to search results of next - and previous folders respectively. - - * mh-loaddefs.el: Regenerated. - - * mh-index.el (mh-index-delete-folder-headers): Arrange for - mh-goto-cur-msg to just go to the current message. - - * mh-e.el (mh-visit-folder): Since mh-scan-folder erases the whole - buffer anyway, we don't need to delete the folder headers. Also - index-data is non-nil only when the buffer folder doesn't exist. - So we need to call mh-make-folder. - (mh-folder-mode): Fix bug in that mh-index-checksum-origin-map was - not being made buffer local! - -2002-12-17 Satyaki Das - - * mh-e.el (mh-visit-folder): Fix bug. - - * mh-index.el (mh-md5sum-buffer): Buffer from which md5sum is run. - (mh-index-folder-first, mh-index-folder-last) - (mh-index-original-msg-list): Convenience macros aren't needed - anymore since the data structure has been changed. - (mh-index-update-single-msg): New function to update maps that - relate MD5 checksums to actual messages and vice-versa for a - single message. - (mh-index-update-maps): Do the above for all messages. If some - messages don't have MD5 checksums, they are annotated with the - result of md5sum. - (mh-index-search): Updated for the new version of mh-index-data. - (mh-msg-exists-p): New function to test a message exists. - (mh-index-insert-folder-headers): Updated for new mh-index-data. - (mh-index-delete-folder-headers): New function used to eliminate - original folder names from the buffer and make it look like a - plain folder buffer. This is used from mh-process-commands. - (mh-index-visit-folder): Use new version of mh-index-data. - (mh-index-match-checksum): New function which checks if the - X-MHE-Checksum header of a message matches. - (mh-index-execute-commands): New function that rmm's the original - messages. Then after mh-execute-commands executes it will seem - that the original messages were executed upon. This completes the - fix of SF #623321. - (mh-checksum-buffer): Renamed from mh-md5sum-buffer. - (mh-checksum-cmd, mh-checksum-parser): New globals to allow - different checksum programs to be used. - (mh-checksum-choose): New functions to find a checksum program. - (mh-openssl-parser, mh-md5sum-parser, mh-md5-parser): Functions to - parse the output of md5, md5sum and openssl. - (mh-index-update-maps): Use checksum parsing function. - (mh-index-search): Set checksum choice. Add a call to recenter, - otherwise the window point in the index buffer doesn't get set - properly. - - * mh-funcs.el (mh-pack-folder, mh-sort-folder): Enable these - functions in folders created by index search. - - * mh-e.el (mh-index-msg-checksum-map) - (mh-index-checksum-origin-map): New buffer local variables that - keep track of message checksums (used to implement - refiling/deletion for folders created by index folders). - (mh-last-msg): Make the function behave like mh-first-msg. - (mh-visit-folder): Add new optional argument which initializes - folders created by mh-index-search. - (mh-folder-mode): Make the variables mh-index-msg-checksum-map and - mh-index-checksum-origin-map buffer local. - (mh-process-commands): Call mh-index-execute-commands when called - from an index search buffer. This will reflect the changes being - made in the search folder to the original folders. - - * mh-loaddefs.el: Regenerated. - -2002-12-16 Satyaki Das - - * mh-index.el (mh-index-insert-folder-headers): Fix a bug which - caused the folder buffer to be marked as modified after rescanning - an index folder. - -2002-12-15 Satyaki Das - - * mh-e.el (mh-visit-folder): The function should insert folder - names if it is visiting a folder created by index search. - - * mh-index.el (mh-index-insert-folder-headers): The function now - maintains the old value of buffer-modified-p and temporarily makes - the buffer writable. - - * mh-utils.el (mh-show-index-visit-folder): New interactive - function callable from show buffer that displays search results - from one folder. - (mh-show-mode-map): Key binding for "v". - - * mh-speed.el: Fix credits. - (mh-index-folder-speedbar-buttons) - (mh-index-show-speedbar-buttons) - (mh-index-folder-speedbar-key-map) - (mh-index-show-speedbar-key-map) - (mh-index-folder-speedbar-menu-items) - (mh-index-show-speedbar-menu-items): Removed since the modes - mh-index-folder-mode and mh-index-show-mode no longer exist. - (mh-speed-extract-folder-name): Remove the bits about - mh-index-folder-mode and mh-index-show-mode. - - * mh-seq.el (mh-copy-seq-to-eob): Updated to work properly with - index search results. - (mh-region-to-msg-list): Skip over non-scan lines. - (mh-thread-inc, mh-thread-add-spaces, mh-thread-folder): Skip - non-scan lines when populating mh-thread-scan-line-map. - (mh-thread-folder, mh-toggle-threads): Move the check for buffer - modification from mh-thread-folder to mh-toggle-threads. - (mh-toggle-threads): When returning to unthreaded view insert the - folder names if called from a index folder. - - * mh-index.el: Fix credits and update commentary. - (font-lock-defaults, mh-index-buffer, mh-index-show-buffer) - (mh-index-ma-x-msg-index, mh-index-other-buffer) - (mh-index-matches, mh-index-previous-window-configuration) - (mh-index-current-msg, mh-index-folder-mode-keymap) - (mh-index-button-map, mh-index-folder-mode-help-messages): Remove - eliminated variables. - (mh-index-folder): New variable sets the MH folder under which the - index searches are stored. - (mh-index-folder-first, mh-index-folder-last) - (mh-index-original-msg-list): Convenience macros used to pull data - elements out of a list. If needed setf can be used to change them - as well. - (mh-index-search): Rewritten to create real folders where all the - normal folder operation. This partially fixes SF #623321 (refiles - and deletes doesn't work on original messages). - (mh-index-find-max-width, mh-index-search-again) - (mh-index-insert-scan, mh-index-callback, mh-index-search) - (mh-index-notate, mh-index-show, mh-index-header-display) - (mh-index-next, mh-index-folder-mode, mh-index-show-mode): - Functions, macros and modes removed. - (mh-folder-exists-p): New function to check if a folder exists. - (mh-index-new-folder): Generate a new folder name from a given - base string that mimics the way emacs generates buffer names. - (mh-index-insert-folder-headers): Insert folder names among the - search results. - (mh-index-visit-folder): New interactive function to show the - search results of one individual folder. - (mh-swish++-execute-search): Update documentation. - - * mh-funcs.el (mh-pack-folder, mh-sort-folder): Disable these - functions if index search results are being viewed. - - * mh-e.el (mh-folder-font-lock-keywords): Add highlight for - folder. - (mh-index-data): New buffer local variable that will be used to - store info about index search results. - (mh-rescan-folder): Implement rescanning for index search results. - (mh-folder-mode): Make mh-index-data buffer local. - (mh-remove-all-notation): Modified to take into account not all - lines in the folder buffer are normal scan lines. - (mh-folder-mode-map): Add key binding for "v" to jump to original - folder narrowed to search results. - - * mh-customize.el (mh-index-folder-face): Make it bold so that it - will look like before. - - * mh-loaddefs.el: Regenerated. - -2002-12-12 Satyaki Das - - * mh-seq.el (mh-map-to-seq-msgs): Modified so that it can be given - a list of messages in addition to a sequence. - (mh-region-to-sequence, mh-region-to-msg-list): The function - mh-region-to-msg-list replaces mh-region-to-sequence. The new - function avoids creating a dummy sequence in MH-E. - (mh-thread-delete, mh-thread-refile, mh-put-msg-in-seq): Modified - to use mh-region-to-msg-list. - - * mh-funcs.el (mh-copy-msg): Modified to use mh-region-to-msg-list. - - * mh-e.el (mh-delete-msg, mh-refile-msg, mh-undo): Modified to use - mh-region-to-msg-list. - - * mh-comp.el (mh-forward): Modified to use mh-region-to-msg-list. - The buffer-local variable mail-header-separator is no longer - bound. This fixes a bug where the default value of - mail-header-separator gets used if mh-forward is called in a fresh - emacs session. - (mh-annotate-msg): Update this so that it will handle message - lists too. - (mh-insert-letter): Make the test stronger. Since %d is being used - the argument better be an integer. - - * mh-loaddefs.el: Regenerated. - -2002-12-11 Satyaki Das - - * mh-funcs.el (mh-copy-msg): Add support for transient-mark-mode. - If mark is active and transient-mark-mode is enabled then all the - messages in the region are copied. - - * mh-seq.el (mh-list-sequences): Use mh-coalesce-msg-list to print - messages in sequence nicely. The prompt for the folder is removed - (the current folder is always used) and the output is made nicer - by not overflowing the screen width. - - * mh-loaddefs.el: Regenerated. - -2002-12-09 Satyaki Das - - * mh-comp.el (mh-letter-complete): Checkdoc fix. - - * mh-seq.el (mh-thread-current-indentation-level): New function - which returns the thread indentation level of current message. - (mh-thread-next-sibling, mh-thread-previous-sibling): New - interactive functions to jump to the next and previous siblings in - thread tree respectively. - (mh-thread-immediate-ancestor): New function to jump to ancestor - of current message in thread tree. - (mh-thread-ancestor): New interactive function to jump to - immediate ancestor or to root message of current thread depending - on optional argument. - - * mh-utils.el (mh-show-thread-ancestor) - (mh-show-thread-next-sibling, mh-show-thread-previous-sibling): - Interactive functions callable from the show buffer. - (mh-show-thread-map): Bindings for Tu, Tp and Tn. - - * mh-e.el (mh-thread-map): Bindings for Tu, Tp and Tn. - - * mh-loaddefs.el: Regenerated. - -2002-12-09 Satyaki Das - - * mh-seq.el (mh-region-to-sequence): Change name of region - sequence created to 'mhe-region. This avoids any chance of - collision with actual MH sequences. - (mh-put-msg-in-seq, mh-thread-delete, mh-thread-refile): Change - name of region sequence used to 'mhe-region. Also delete the - 'mhe-region sequence when done. - - * mh-e.el (mh-delete-msg, mh-refile-msg, mh-undo): Same as above. - - * mh-comp.el (mh-forward): Same as above. - - * mh-loaddefs.el: Regenerated. - -2002-12-08 Bill Wohler - - * mh-alias.el: Edited documentation. Broke up file into 2 - sections: Alias Loading and Alias Expansion. Made terminology - consistent (replaced expand, substitute, and translate with - expand). - (mh-alias-reload): Brought message in line with coding conventions - and made more concise too. - (mh-alias-translate): Renamed to mh-alias-expand. - (mh-alias-substitute-aliases-flag): Renamed to - mh-alias-expand-aliases-flag. - (mh-alias-reload-local-users): Renamed to mh-alias-local-users. - Now just returns an alist of local users rather than have - side-effects. - (mh-alias-reload): Set timestamp at beginning of function to catch - edge case when alias added just after ali runs. Changed logic to - reflect return value of mh-alias-local-users. - - * mh-customize.el (mh-alias-substitute-aliases-flag): Renamed to - mh-alias-expand-aliases-flag. - (mh-alias-local-users): Fixed documentation. - - * mh-loaddefs.el: Regenerated - -2002-12-08 Satyaki Das - - * mh-e.el (require): Load Gnus at compile time so that the - constant gnus-version is defined when MH-E is being compiled. - (mh-macro-expansion-time-gnus-version, mh-run-time-gnus-version): - Use the constant gnus-version instead of the function gnus-version - to find out about gnus version information. - (gnus-version): Remove the autoload since it is not needed any - more. - -2002-12-08 Bill Wohler - - * mh-e.el (mh-version): Moved compilation information in front of - Emacs information. The idea is that you start at MH-E and move - outwards. Show N/A if Gnus not compiled (be explicit). Matched - coding style with other output statements. (Aside: not that - efficiency matters here, but fewer calls to format have to be - faster, right? ;-). Matched output style of old output to new - statement--liked Satyaki's indentation better ;-). - -2002-12-08 Satyaki Das - - * mh-e.el (gnus-version): Autoload the function for use in - mh-version. - (mh-macro-expansion-time-gnus-version): New macro that finds the - Gnus version at macro expansion time. - (mh-run-time-gnus-version): New function to find the Gnus version - at run time. - (mh-version): Add information about Gnus versions available at - compile time and run time. - -2002-12-07 Peter S Galbraith - - * mh-alias.el (mh-alias-ali): Add optional argument. if USER is - t, then assume ALIAS is an address and call ali with option -user. - - * mh-alias.el (mh-alias-filenames): if ARG is t, appends list of - files from `mh-alias-system-aliases' to output list obtained from - mhparam output user list only. - (mh-alias-tstamp): Use it. - -2002-12-05 Satyaki Das - - * mh-mime.el (mh-inline-vcard-p): A new function which decides if - a vcard should be displayed inline. - (mh-mime-display-single): Use mh-inline-vcard-p to display - attached vcard as a signature if no other signature is present - (this partially addresses SF #649216). - -2002-12-05 Peter S Galbraith - - * mh-comp.el (mh-send-letter): Edits docs for mh-mml-to-mime - getting run if variable `mh-mml-compose-insert-flag' is set. - (mh-get-header-field): use buffer-substring-no-properties instead - of buffer-substring. - -2002-12-04 Peter S Galbraith - - * mh-loaddefs.el: Regenerated. - - * mh-customize.el (mh-customize): Add ;;;###mh-autoload tag. - -2002-12-04 Peter S Galbraith - - * mh-loaddefs.el: Regenerated. - - * mh-comp.el (mh-letter-complete): New command to do alias or word - completion in letter-mode. - (mh-letter-mode-map): Add \M-\t binding for mh-letter-complete. - - * mh-alias.el (mh-alias-letter-mode-expand-alias-hook): Obsolete. - Replaced by mh-letter-complete command. - (mh-alias-reload-maybe): New function to rebuild alias table if - out of date. - (mh-alias-letter-expand-alias): No longer interactive. Use - mh-letter-complete instead. - -2002-12-04 Peter S Galbraith - - * mh-customize.el (mh-letter-complete-function): New defcustom. - Function to call when completing outside of fields specified to - aliases. - - * mh-alias.el (mh-alias-filenames): - s/mh-mhparam-component/mh-profile-component/ - (mh-profile-component): Move to mh-utils.el and make interactive. - (mh-read-address): Make it autoloaded. - - * mh-loaddefs.el: Regenerated. - - * mh-comp.el (mh-read-address): Removed. Replaced by mh-alias - version. - - * mh-utils.el (mh-profile-component): Moved from mh-alias.el. - -2002-12-04 Satyaki Das - - * mh-seq.el (mh-msg-is-in-seq): Formatting change. - - * mh-index.el (mh-index-insert-scan): Remove unused variable. - -2002-12-04 Bill Wohler - - * mh-loaddefs.el: Regenerated. - - * Makefile (MH-E-SRC): Moved mh-loaddefs.el into MH-E-LOADDEFS as - this was causing a cycle. - (MH-E-LOADDEFS): New variable to house mh-loaddefs.el. - (emacs): Reintroduced autoloads. - (autoloads): We're baaa-aack! - (dist, install-emacs): Use MH-E-LOADDEFS. - - * mh-comp.el (mh-customize): Moved to mh-customize.el. - - * mh-customize.el (mh-customize): Moved here from mh-comp. Makes - more sense, doesn't it? - - * mh-alias.el, mh-comp.el, mh-e.el, mh-index.el, mh-mime.el, - mh-pick.el, mh-speed.el: Added mh-autoload cookie to all - interactive functions. - -2002-12-04 Satyaki Das - - * Makefile (world): Remove target. - (mh-loaddefs.el): Add comment that only GNU Emacs can be used to - regenerate mh-loaddefs.el. - - * mh-make.el: Removed. - -2002-12-04 Mark D. Baushke - - * mh-e.el (recursive-load-depth-limit): Only modify the limit - if it is an integer. - -2002-12-04 Peter S Galbraith - - * mh-utils.el (mh-header-field-beginning): New function. Move to - the beginning of the current header field. - -2002-12-04 Satyaki Das - - * mh-make.el (mh-files): Read in the MH-E filenames from the - environment variable where the Makefile puts it. - (mh-generate-autoloads, step2): Simplified since we now have the - complete file names. - - * Makefile (world): Pass the MH-E files into the script, so that - the filenames don't need to be repeated in the script. - -2002-12-04 Bill Wohler - - * mh-loaddefs.el: New file. Check in automatically generated file - and include in package for the benefit of those who don't want to - or can't compile. - - * Makefile (MH-E-SRC): Added mh-loaddefs.el now that it is checked - in and will be packaged. - (emacs): Removed autoloads. Adding mh-loaddefs.el to MH-E-SRC is - sufficient to build it. - (compile): Depend on MH-E-SRC instead of MH-E-OBJ and pass $? into - emacs so that Emacs is only invoked once to compile files. This - speeds things up by a factor of 3. It would be nice to only pass - those files that have been modified, but Emacs 21.4 will have - batch-byte-compile-if-not-done which we might be able to copy into - mh-make.el (or my proposed mh-e-dev.el which would be more - general-purpose). - (.SUFFIXES): Removed. Now that compile works directly on the - sources, the implicit rule is obsolete. - (autoloads): Deleted. See emacs change above. - -2002-12-03 Bill Wohler - - * Makefile (MH-E-SRC, emacs): - -2002-12-03 Satyaki Das - - * mh-make.el (mh-emacs): Make failing condition more strict. - (mh-loaddefs-end): Remove redundant statement. - - * Makefile (world): A little typo. The bug didn't seem to make any - difference though. - - * mh-make.el: New script that compiles MH-E. - (mh-loaddefs-beginning, mh-loaddefs-end): Don't save the autoloads - file in between. Only save at the end. - (mh-emacs-generate-autoloads, mh-xemacs-generate-autoloads) - (mh-generate-autoloads): Replace the separate functions in Emacs - and XEmacs with one that works in both variants. This simplifies - the script a lot. - (mh-generate-autoloads): doc fix. - - * Makefile (world): New target which works for both GNU Emacs and - XEmacs. - -2002-12-03 Peter S Galbraith - - * mh-alias.el (mh-mhparam-component): Don't raise error if call to - mhparam fails. - - * mh-alias.el (mh-alias-letter-expand-alias): Build alias table if - not already available. - -2002-12-03 Bill Wohler - - * mh-customize.el (mh-show-threads-flag): Alphabetized. - -2002-12-03 Jeffrey C Honig - - * Makefile: Moved .PHONY rule after all rule for compatibility - with BSD/OS's old pmake. - -2002-12-03 Mark D. Baushke - - * mh-e.el (mh-get-new-mail): Simplify no-new-mail test. - (mh-add-cur-notation): Remove unnecessary function. - -2002-12-03 Peter S Galbraith - - * mh-identity.el (mh-identity-make-menu): Check if - 'mh-letter-mode-map' is bound, since this code also gets run when - mh-customize.el is loaded at startup. - -2002-12-03 Satyaki Das - - * mh-customize.el (mh-show-threads-flag): New customizable - variable which controls if new folders start of in threaded mode - (closes SF #646794). - - * mh-e.el (mh-rescan-folder): Fix the function so that threading - is preserved across rescans. - (mh-visit-folder, mh-inc-folder): The folder is threaded if it was - already threaded or if mh-show-threads-flag is non-nil and the - number of scan lines is fewer than mh-large-folders (closes SF - #646794). - -2002-12-02 Mark D. Baushke - - * mh-e.el (mh-add-cur-notation): New function to mark the - current message with the mh-note-cur character. - (mh-get-new-mail): Use mh-add-cur-notation to undo the work of - mh-remove-cur-notation if there was no new mail (closes SF #647681). - - * mh-e.el (mh-set-cmd-note): Do not update the default mh-cmd-note - value (closes SF #643701). - -2002-12-02 Peter S Galbraith - - * mh-alias.el (mh-alias-reload): Renamed from mh-alias-learn-aliases. - (mh-alias-load-local-users): Renamed from mh-alias-learn-local-users. - (mh-alias-passwd-alist): New variable, holding aliases extracted - from the passwd file. - (mh-alias-tstamp): New variable storing the timestamp for alias - list generation. - (mh-read-address, mh-alias-reload, mh-alias-reload-local-users): - Complete rewrite. - (mh-alias-minibuffer-confirm-address): Use mh-alias-translate. - (mh-alias-translate): New function. Return translation for alias, - checking if in blind or passwd list. - (mh-alias-letter-expand-alias): Rewrite using - mail-abbrev-complete-alias from mailabbrev.el. - (mh-alias-expand-alias-map): New variable. - (mh-alias-ali): New function. Return formatted string of - translated ALIAS from ali. - (mh-mhparam-component): New function. Return COMPONENT value from - mhparam, or nil if unset. - (mh-alias-filenames): New function. Provide list of alias - filenames from mhparam, or nil if none are set. - - * mh-customize.el (mh-alias-display-blind-name-on-completion-flag): - Obsoleted. - (mh-alias-timestamp): Renamed to mh-alias-system-aliases. - -2002-12-02 Bill Wohler - - * Makefile (mh-loaddefs.el): Suppress creation of backup file. - -2002-12-02 Mark D. Baushke - - * Makefile (mh-loaddefs.el): Simplify rule. - - * Makefile (clean): Remove mh-loaddefs.el* for good measure. - ($(MH-E-OBJ)): Depend on mh-loaddefs.el to compile these. - (autoloads, mh-loaddefs.el): Revamp rules. - (mh-loaddefs.el-tail, autoloads-gen): Remove rules. - - * mh-e.el (recursive-load-depth-limit): Do not try to - bump the value unless the variable exists. - - * mh-e.el (recursive-load-depth-limit): Bump value of - recursive-load-depth-limit to 50 to allow emacs 21.1 which - normally has a default value of 10 to be able to compile MH-E. - -2002-12-02 Satyaki Das - - * mh-funcs.el (mh-pack-folder, mh-sort-folder): Fix the functions - so that threading is preserved (needed for SF #646794). - - * mh-identity.el (mh-identity-signature-start) - (mh-identity-signature-end): Checkdoc fixes. - - * mh-e.el (mh-previous-unread-msg, mh-next-unread-msg): Checkdoc - fixes. - -2002-12-01 Satyaki Das - - * mh-identity.el (compile): Make mh-identity.el compile without - warnings. - - * mh-e.el (mh-previous-unread-msg, mh-next-unread-msg): New - interactive functions that go to next and previous unread - messages (closes SF #630328). - (mh-folder-mode-map): Add key bindings for M-n and M-p to - mh-folder-mode-map. - - * mh-utils.el (mh-show-next-unread-msg) - (mh-show-previous-unread-msg): New interactive functions that go - to the next and previous unread messages respectively. These are - callable from the show buffer. - (mh-show-mode-map): Add key bindings for M-n and M-p to - mh-show-mode-map. - -2002-12-01 Bill Wohler - - * mh-mime.el (mh-defun-compat): Make it indent like a defun. - - * mh-index.el (mh-defun-index): Make it indent like a defun. - - * mh-customize.el: New file (closes SF #643722). - - * Makefile (MH-E-SRC): Added mh-customize.el (closes SF #643722). - - * mh-speed.el, mh-pick.el, mh-mime.el, mh-index.el, mh-e.el, - mh-comp.el: Moved all defgroups, defcustoms, and deffaces to - mh-customize.el (closes SF #643722). - - * mh-utils.el (mh-xemacs-flag): Moved here from below since - needed by mh-customize.el. - (mh-customize): Required. mh-invisible-headers) - (mh-bury-show-buffer-flag, mhl-formfile): - Moved all defgroups, defcustoms, and deffaces to mh-customize.el - (closes SF #643722) . - - * mh-identity.el (mh-comp-loaded): New variable in a desperate - attempt to prevent an infinite loop. - (eval-when-compile): Was able to remove these defvars as they are - now predefined in mh-loaddefs and mh-customize. - (mh-identity-list-set): Added ;;;###mh-autoload cookie. - Moved all defgroups, defcustoms, and deffaces to mh-customize.el - (closes SF #643722). - - * mh-alias.el (mh-e): Require this, as it needs defcustoms, which - is in mh-customize which is required by mh-utils which is required - by mh-e. - Moved all defgroups, defcustoms, and deffaces to mh-customize.el - (closes SF #643722). - -2002-11-30 Satyaki Das - - * mh-e.el (mh-thread-map): Add key bindings "Td" and "To" (closes - SF #630493). - (mh-help-messages): Update help message for prefix map. - (mh-help-messages): Doc fix. - (mh-help-messages): Really fix it. - - * mh-utils.el (mh-show-thread-delete, mh-show-thread-refile): New - interactive functions corresponding to mh-thread-delete and - mh-thread-refile callable from the show buffer. - (mh-show-thread-map): Add key bindings for "Td" "To". - - * mh-seq.el (mh-narrow-to-seq, mh-put-msg-in-seq, mh-rename-seq) - (mh-narrow-to-subject, mh-delete-subject, mh-toggle-threads): Add - mh-autoload cookies. - (mh-thread-find-children): New function which finds the region - containing all children of a message. - (mh-thread-delete): New interactive function that marks for - deletion the current message and its children. - (mh-thread-refile): New interactive function that marks for - refiling the current message and its children. - -2002-11-30 Bill Wohler - - * mh-funcs.el, mh-identity.el, mh-index.el, mh-pick.el, mh-seq.el: - Removed MH-E autoloads. These are now provided by mh-loaddefs.el. - Added ;;;###mh-autoload tag to selected functions so that - autoloads for those functions can be automatically created in - mh-loaddefs.el (closes half of SF #643722). - - * mh-mime.el (mh-buffer-data): Moved to mh-utils where it is used. - Added ;;;###mh-autoload tag to selected functions so that - autoloads for those functions can be automatically created in - mh-loaddefs.el (closes half of SF #643722).. - - * mh-utils.el (mh-loaddefs): Added require. - (mh-buffer-data): Moved here from mh-mime.el as it is used in - mh-display-msg. - (mh-set-cmd-note): Moved to mh-e.el. - Removed MH-E autoloads. These are now provided by mh-loaddefs.el. - Added ;;;###mh-autoload tag to selected functions so that - autoloads for those functions can be automatically created in - mh-loaddefs.el (closes half of SF #643722).. - - * mh-e.el (mh-set-cmd-note): Moved here from mh-utils.el since it - uses mh-scan-format-file which is defined here. - Removed MH-E autoloads. These are now provided by mh-loaddefs.el. - Added ;;;###mh-autoload tag to selected functions so that - autoloads for those functions can be automatically created in - mh-loaddefs.el (closes half of SF #643722).. - - * mh-comp.el, mh-speed.el (mh-utils): Removed require. mh-utils is - provided via mh-e.el. - Removed MH-E autoloads. These are now provided by mh-loaddefs.el. - Added ;;;###mh-autoload tag to selected functions so that - autoloads for those functions can be automatically created in - mh-loaddefs.el (closes half of SF #643722).. - - * Makefile (emacs): Add dependency on autoloads. - (clean): Remove mh-loaddefs.el too. - (autoloads): New target. Builds mh-loaddefs.el. - (mh-loaddefs.el): New target. Initializes mh-loaddefs.el. - (mh-loaddefs.el-tail): New target. Appends to mh-loaddefs.el. - (autoloads-gen): Runs batch-update-autoloads to populate - mh-loaddefs.el (closes half of SF #643722).. - (auto-autoloads.elc): Renamed from autoloads to be explicit about - file that's created. - (custom-load.elc): Ditto. - -2002-11-30 Satyaki Das - - * mh-seq.el (mh-thread-last-ancestor): New variable which keeps - track of oldest ancestor of last message. If due to narrowing the - common ancestor of two messages is lost then one of them is - promoted to be the parent of the other. This variable helps in - this process. - (mh-thread-generate-scan-lines): Group messages which belong to - the same thread tree, even if a common ancestor is no longer - present. - (mh-thread-folder, mh-copy-seq-to-eob, mh-thread-inc): Bind - mh-thread-last-ancestor to nil when calling - mh-thread-generate-scan-lines. - - * mh-mime.el (font-lock): Font-lock required at compile time to - avoid warning about font-lock-maximum-size. - (mh-display-smileys, mh-display-emphasis): Show graphical smileys - and emphasis only if message isn't too large. - - * mh-e.el (mh-visit-folder): Revisiting a buried folder which has - been threaded or narrowed confuses MH-E. Even though the folder is - displayed as not threaded and not narrowed, MH-E still believes - the folder is in the previous state. This can cause problems when - trying to narrow/thread the folder. The change fixes this. - - * mh-mime.el (mh-mime-display-alternative): The setting of - mh-display-buttons-for-inline-parts-flag was not being used when - displaying one of the alternatives. This change fixes that. - - * mh-comp.el (mh-show-buffer-message-number): Replace subseq with - substring. - (mh-filter-out-non-text): When filtering out MIME buttons from - yanked text, the last line of the MIME part was getting lost. The - fix avoids that and removes only the last new line instead. - -2002-11-29 Peter S Galbraith - - * Makefile (MH-E-SRC): Add mh-alias. - - * mh-alias.el: Assign copyright to FSF instead of myself. - (mh-read-address): Add support for emacs-21's - completing-read-multiple to prompt for multiple entries. - (mh-alias-PC-complete-address): Deleted. - (mh-alias-learn-aliases): Use mh-exec-cmd-quiet instead of old kludge. - (mh-alias-letter-mode-expand-alias-hook): Simplify. - (mh-alias-hostname): Deleted. - (mh-alias-substitute-aliases-flag): Change default to nil. - (mh-alias-display-blind-name-on-completion-flag) Change default to - nil. - (mh-alias-alist): Now holds alias values. - (mh-alias-lowercase-alist): Deleted. - (mh-alias-minibuffer-confirm-address, mh-alias-learn-aliases) - (mh-alias-learn-local-users, mh-alias-letter-expand-alias): Use - new mh-alias-alist instead of old mh-alias-lowercase-alist. - - * mh-alias.el: Moved from contrib/ directory. Now part of MH-E! - - * Makefile (MH-E-SRC): Add mh-identity. - - * mh-identity.el (mh-compose-and-send-mail, mh-insert-identity) - (mh-identity-make-menu, mh-identity-default, mh-identity-menu): - Moved to mh-comp.el. - - * mh-comp.el (mh-compose-and-send-mail): Add mh-identity support. - (mh-insert-identity, mh-identity-make-menu, mh-identity-default) - (mh-identity-menu): Added from mh-identity.el - -2002-11-29 Bill Wohler - - * mh-comp.el, mh-e.el, mh-funcs.el, mh-identity.el, mh-index.el, - mh-mime.el, mh-pick.el, mh-seq.el, mh-speed.el, mh-utils.el: - Ran indent-region, reformatted long lines, ran untabify. - (indent-tabs-mode): Set file local variable to nil. - -2002-11-29 Bill Wohler - - Released MH-E version 7.0. - - * mh-e.el (Version, mh-version): Updated for release 7.0. - - * mh-comp.el (subseq, search): Require cl instead of autoloading - these due to compilation warnings in CVS Emacs. - -2002-11-23 Bill Wohler - - * MH-E-NEWS: Emphasize the renaming of the variables at the top of - the notes. - -2002-11-22 Satyaki Das - - * mh-utils.el (mh-show-mode-map): Remove binding for RET since it - is not needed and the binding is more useful to toggle display of - MIME parts. - - * mh-mime.el (mh-mime-button-commands): Remove bindings for "i" - and "o" from MIME buttons. - (mh-insert-mime-button): Change comment to reflect change in - button key map. - -2002-11-21 Bill Wohler - - Released MH-E version 6.1.91. - - * mh-e.el (Version, mh-version): Updated for release 6.1.91. - - * MH-E-NEWS: Inline HTML parts supported with Gnus 5.10, not 5.9. - -2002-11-21 Mark D. Baushke - - * mh-comp.el (mh-letter-insert-signature-hook): This should be in - customize-group mh-compose. - -2002-11-21 Satyaki Das - - * mh-utils.el (load): Load mm-view.el here so that - mm-inline-text-html would be defined if available. - (mh-mm-inline-media-tests): If mm-inline-text-html is available - then use it, otherwise fall back on using mm-inline-text (closes - SF #641482). - - * mh-mime.el (load): Remove the load of mm-view here since it - happens in mh-utils.el now. - -2002-11-15 Bill Wohler - - Released MH-E version 6.1.90. - - * README (Compile): New section. Users must now compile MH-E due - to the vagaries of the various versions of gnus. - - * Makefile (MH-E-IMG): Added reply-all.pbm, reply-all.xpm, - reply-from.pbm, reply-from.xpm, reply-to.pbm, reply-to.xpm. - (MH-E-ETC-ETC): Added Makefile and README. - (dist): Depend on all, so clean happens. Don't add .elc files to - tarball as they are built upon installation now. - -2002-11-15 Satyaki Das - - * mh-e.el (mh-process-commands): Fix a bug in mh-execute-commands. - If called in threaded mode, cur was always getting set to the last - message in the folder. - -2002-11-14 Bill Wohler - - * mh-e.el (Version, mh-version): Updated for release 6.1.90. - - * MH-E-NEWS, README: Updated for release 7.0. - - * mh-utils.el (mh-index-search): Added full docstring which new - users will need before they run a search! - (mh-swish++-execute-search, mh-swish-execute-search, - mh-namazu-execute-search mh-glimpse-execute-search): Added - autoloads with full docstrings for the same reason! - - * mh-e.el (mh-limit-map): Removed / / alias for - mh-narrow-to-subject. - - * mh-utils.el (mh-show-thread-map): Removed / / alias for - mh-show-narrow-to-subject. - - * mh-seq.el (mh-delete-subject): Checkdoc fix. - - * mh-e.el (mh-help-messages): Added / prefix character to help - string. Tweaked / helpstring a little. - -2002-11-14 Mark D. Baushke - - * mh-utils.el (mh-set-cmd-note): Fix nitpick by adding one to the - width for cosmetic reasons. - -2002-11-14 Peter S Galbraith - - * mh-identity.el (mh-insert-identity): Fix a few things undone by - Jeff's patch. - (mml-insert-tag): Add autoload. - -2002-11-13 Mark D. Baushke - - * mh-identity.el (mh-insert-identity): A value of either nil or - "" should cause the field to be removed. - (mh-identity-list): Update the docstring. - -2002-11-13 Peter S Galbraith - - * mh-e.el (mh-limit-map): New key map for limits (subject for now). - * mh-utils.el (mh-show-limit-map): Same. - - * mh-seq.el (mh-delete-subject): Renamed from - mh-delete-subject-sequence. - (mh-narrow-to-subject): Renamed from mh-narrow-to-subject-sequence. - (mh-next-unseen-subject-sequence): Removed. :-( - * mh-e.el: Use 'em - * mh-seq.el: Use 'em. - -2002-11-13 Mark D. Baushke - - * mh-e.el (mh-alt-show): New defalias for mh-show. - (mh-alt-refile-msg): New defalias for mh-refile-msg. - (mh-alt-send): New defalias for mh-send. - (mh-folder-mode-map): Use mh-alt-show, mh-alt-refile-msg and - mh-alt-send for the alias bindings. - (mh-alt-visit-folder): New defalias for mh-visit-folder. - (mh-folder-map): Use it. - (mh-folder-message-menu): Revert previous change. - -2002-11-13 Peter S Galbraith - - * mh-e.el (mh-folder-message-menu): Make key binding "o" appear in - menu for mh-refile-msg. - -2002-11-13 Satyaki Das - - * mh-seq.el (mh-thread-generate-scan-lines): In threaded view, - scan lines of duplicate messages were too long. The change fixes - that. - -2002-11-13 Bill Wohler - - * mh-utils.el (mh-adaptive-cmd-note-flag): Improved grammar in - docstring. - - * mh-speed.el (mh-speed-run-flists-flag): While documenting this - variable in the release notes, I was unsure what would happen if - set to nil. So, I clarified the docstring and indicated - implications of setting this variable to nil, and offered manual - workaround. - -2002-11-13 Satyaki Das - - * mh-index.el (mh-index-quit): Fix documentation and run - mh-before-quit-hook and mh-quit-hook. - -2002-11-13 Bill Wohler - - * mh-utils.el (with-mh-folder-updating): Renamed local variable - mh-save-modification-flag to save-modification-flag. - -2002-11-12 Bill Wohler - - * mh-index.el (mh-index-keymap): Renamed to - mh-index-folder-mode-keymap to be a closer to the usual keymap - naming convention. Since we want our own keymap and not inherit - the one in mh-folder-mode, we need to use a suffix other than - -map. - - * mh-e.el (mh-folder-sequence-menu): s/Msg/Message. - s/Seq/Sequence. - (mh-folder-message-menu): s/Msg/Message. Removed redundant refile - item. - (mh-folder-folder-menu): Aligned symbols. - - * mh-index.el (mh-index-folder-message-menu): s/Msg/Message. - - * mh-utils.el (mh-show-sequence-menu): s/Msg/Message. - s/Seq/Sequence. - (mh-show-message-menu): s/Msg/Message. Removed redundant refile - item. - (mh-show-folder-menu): Aligned symbols. - -2002-11-12 Satyaki Das - - * mh-index.el (mh-index-matches, mh-index-current-match): Remove - these variables since they were only used for glimpse and grep. - Now the functionality of all the indexing programs will be - uniform. - (mh-index-search, mh-index-insert-scan, mh-defun-index) - (mh-index-show): Simplify functions since matches are no longer - shown. - (mh-index-parse-match): Remove function. - - * mh-e.el (mh-scan-cmd-note-width, mh-scan-destination-width) - (mh-scan-date-width, mh-scan-date-flag-width) - (mh-scan-from-mbox-width, mh-scan-from-mbox-sep-width): New - variables to keep track of the widths of the different fields in - the scan lines. - (mh-scan-field-from-start-offset, mh-scan-field-from-end-offset) - (mh-scan-field-subject-start-offset): Offsets that are computed - from the scan line widths. - - * mh-seq.el (mh-copy-seq-to-eob, mh-thread-inc) - (mh-thread-parse-scan-line): Use new variables that remember the - various offsets in place of integer constants. - (mh-thread-generate-scan-lines): Space shouldn't be added here! - -2002-11-12 Bill Wohler - - * mh-e.el (mh-scan-format-mh, mh-scan-format-nmh): Noted that the - first column is column number 0 and changed "sixth column" to - "fifth column" accordingly. - - * mh-index.el (mh-index-folder-mode): Clarified method of replying - in mode documentation. - (mh-index-folder-tool-bar-map): s/mh-e/MH-E/. - - * mh-e.el (mh-generate-new-cmd-note): Try not to mention internal - variable mh-cmd-note in docstrings. - - * mh-utils.el (mh-adaptive-cmd-note-flag): Set default value to t. - Reworded docstring so it doesn't mention internal variable - mh-cmd-note. Added information about using fixed-width message - numbers. - (mh-cmd-note): Mention mh-set-cmd-note in docstring. Also suggest - that it is updated dynamically only if mh-scan-format-file is t. - (mh-set-cmd-note): Grammar fix in docstring. - (mh-cmd-note): Noted that the first column is column number 0. - - * mh-e.el (mh-scan-format-file): Added information about - mh-set-cmd-note and mh-adaptive-cmd-note-flag to docstring. - - * mh-index.el (mh-index-keymap): Added bindings for i - (mh-inc-folder), m (mh-send alias), and s (mh-send) since these - appear to be supported and are found in the toolbar. - (mh-index-folder-key-map): Ditto for f (mh-visit-folder alias), o - (mh-visit-folder) alias, and v (mh-visit-folder). - (mh-index-folder-mode-help-messages): Changes for above. - (mh-index-folder-message-menu, mh-index-folder-folder-menu): New - menus. I decided to delete the unavailable items since graying out - implies that the user can do something to access them. In this - case, that's not the case. Well, that's not entirely true--the - user could write code for those functions ;-). - (mh-index-folder-mode): Use new menus. - - * mh-utils.el (mh-prompt-for-folder): Added optional argument - default-string which can be used in case the string for default - isn't intuitive enough. - - * mh-index.el (mh-index-search): Made default prompt more - intuitive (I hope!). - -2002-11-11 Peter S Galbraith - - * mh-identity.el (mh-header-field-delete): Remove save-excursion. - Strange that this worked for me before... Thanks to Jeff for the - patch. - (mh-insert-identity): Numerous tweaks and fixes from Jeff who also - adds a nicer-looking MIME header for signatures inserted after - MIME insertions. - -2002-11-11 Satyaki Das - - * mh-seq.el (mh-thread-parse-scan-line): Generalize this function - so that it can take a string containing the scan-line as argument - in addition to using the line at point. - (mh-thread-add-spaces): New function to pad each scan line to the - appropriate length. This is called when mh-cmd-note is increased. - - * mh-e.el (mh-generate-new-cmd-note): Make this work on a threaded - folder by using mh-thread-add-spaces to pad the pre-existing lines - in mh-thread-scan-line-map appropriately. - (mh-thread-add-spaces): Autoload from mh-seq. - -2002-11-11 Mark D. Baushke - - * mh-index.el: Fix checkdoc nit. - - * mh-mime.el (mh-display-buttons-for-inline-parts-flag): Renamed - from mh-display-buttons-for-inline-parts. - (mh-mime-display-single): Use it. - This addresses part of SF #627015. - - * mh-e.el (mh-print-background-flag): Renamed from - mh-print-background. - * mh-funcs.el (mh-print-msg): Use it. - This addresses part of SF #627015. - - * mh-comp.el (mh-delete-yanked-msg-window-flag): Renamed from - mh-delete-yanked-msg-window. - (mh-yank-from-start-of-msg, mh-yank-cur-msg): Use it. - This addresses part of SF #627015. - - * mh-utils.el (mh-update-sequences-after-mh-show-flag): Renamed - from mh-update-sequences-after-mh-show. - (mh-show-msg): Use it. - This addresses part of SF #627015. - - * mh-utils.el (mh-decode-quoted-printable-flag): Renamed from - mh-decode-quoted-printable. - (mh-display-msg, mh-decode-quoted-printable-have-mimedecode): - Use it. - This addresses part of SF #627015. - - * mh-utils.el (mh-recursive-folders-flag): Renamed from - mh-recursive-folders. - (mh-make-folder-list-background): Use it. - * mh-funcs.el (mh-list-folders): Ditto. - This addresses part of SF #627015. - - * mh-utils.el (mh-auto-folder-collect-flag): Renamed from - mh-auto-folder-collect. - (mh-find-path): Use it. - This addresses part of SF #627015. - - * mh-utils.el (mh-decode-mime-flag): Renamed from - mh-decode-mime. - * mh-utils.el (mh-show-mode, mh-show-xface) - (mh-decode-quoted-printable, mh-display-msg, mh-display-msg): Use it. - * mh-mime.el (mh-graphical-smileys-flag) - (mh-graphical-emphasis-flag): Ditto. - * mh-index.el (mh-index-search, mh-index-show): Ditto. - * mh-e.el (mh-header-display): Ditto. - This addresses part of SF #627015. - - * mh-e.el (mh-make-folder-mode-line): Use save-window-excursion - to get back to the current message. - -2002-11-10 Satyaki Das - - * mh-index.el (mh-index-keymap, mh-index-page-msg) - (mh-index-folder-tool-bar-map): Replace mh-index-scroll-up with - mh-index-page-msg. - (mh-index-keymap, mh-index-previous-page): Replace - mh-index-scroll-down with mh-index-previous-page. - -2002-11-09 Satyaki Das - - * mh-index.el (autoload/require): Load mh-mime when mh-index.el is - loaded. This fixes the infinite load loop. I am not sure what the - actual problem is. Also removed the nop requires/autoloads. - (mh-defun-index): Use the right argument for mh-recenter. - Otherwise it misbehaves for the default value of - mh-summary-height. - - * mh-e.el (mh-goto-next-button): Fix infinite loop when S-Tab was - used on first line of index folder buffer. - -2002-11-09 Peter S Galbraith - - * mh-index.el (mh-index-folder-tool-bar-map): Tool-bar for - mh-index-mode. - (mh-index-folder-mode): Use it. - (mh-index-keymap): Added mouse-2 binding, like in regular - folder-mode. - -2002-11-08 Satyaki Das - - * mh-index.el (mh-index-folder-mode): Fix doc string for major - mode. It was pointing to the wrong keymap. - (mh-index-show-mode): Fix doc string for mode. Also add mh-help - support. - - * mh-comp.el (mh-forward, mh-yank-cur-msg): Use new macro - mh-mark-active-p instead. This does the right thing for different - variants of Emacs. - (mh-yank-cur-msg): Add a space between sexprs. - - * mh-utils.el (mh-mark-active-p): New macro which papers over - differences between GNU Emacs and XEmacs. The variables mark-active - and transient-mark-mode are used in GNU Emacs while zmacs-regions - and region-active-p are used in XEmacs. - - * mh-seq.el (mh-put-msg-in-seq, mh-thread-ancestor-p): Use - mh-mark-active-p as above. - - * mh-e.el (mh-delete-msg, mh-refile-msg, mh-undo): Use - mh-mark-active-p as above. - -2002-11-06 Peter S Galbraith - - * mh-comp.el (mh-yank-cur-msg): Fix for XEmacs. It didn't work - with a selected region, and left the inserted text selected (in - reverse video). I didn't use SF patch #402315 to implement this. - -2002-11-05 Peter S Galbraith - - * mh-utils.el (mh-show-tool-bar-map): Change call to - mh-tool-bar-search-command such that user can customize it for the - current session. - - * mh-e.el (mh-folder-tool-bar-map): Same. - -2002-11-05 Bill Wohler - - * mh-utils.el, mh-e.el (mh-tool-bar-search-function): Renamed from - mh-tool-bar-search-command. - - * mh-index.el (mh-index-search): Backed out previous change to - prompt. There ain't no folder named "all." - - * mh-utils.el (mh-tool-bar-search-command): Added mh-search-folder - and mh-index-search to the docstring so that user can easily click - on them for more information. - - * mh-pick.el (mh-search-folder): Mention that this function uses - the MH pick command to give the user more information when - choosing between mh-search-folder and mh-index-folder. - - * mh-index.el (mh-index-search): Edited the docstring. Direct the - user to mh-index-program if necessary. - (mh-index-program): Edited this docstring too. Viewing the help - in a *Help* buffer really exposes grammatical flaws. - -2002-11-05 Peter S Galbraith - - * mh-utils.el (mh-tool-bar-search-command): New defcustom to set - what search function to use in tool-bar. - (mh-show-tool-bar-map): Use it. - - * mh-e.el (mh-folder-tool-bar-map): Use it. - -2002-11-05 Bill Wohler - - * mh-index.el (mh-index-search): Changed default prompt from "+" - to "all". mh-prompt-for-folder doesn't seem to mind. - - * mh-e.el (mh-folder-folder-menu): Added menu entry for - mh-index-search. - - * mh-utils.el (mh-show-folder-menu): Added menu entry for - mh-index-search. - - * mh-index.el: Added commentary on supported search engines and - for getting started (initializing database). - -2002-11-04 Satyaki Das - - * mh-index.el (mh-index-keymap, mh-index-folder-key-map): Move key - binding of "i" to "Fi". - (mh-index-folder-mode-help-messages): Change help message to - reflect above change. - -2002-11-04 Bill Wohler - - * mh-index.el (mh-index-program, mh-indexer): Swapped names since - the former seems like a better user variable name. If you've - customized mh-indexer, be sure to toss it out and customize - mh-index-program. - -2002-11-04 Satyaki Das - - * mh-index.el (mh-indexer-choices): Not having the quotes in the - binary names is a bit nicer since that maintains uniformity with - the other names. - (mh-index-choose): Use symbol-value instead of eval. Eval should - be avoided except when it can't be :-). - -2002-11-04 Bill Wohler - - * mh-index.el (mh-index-program): New variable to hold the name of - the indexer that was found; use this instead of clobbering - user-customizable variable mh-indexer. - (mh-index-search): Use it. Added comments to keep others from - doing what I had done (fortunately, I caught myself before - checking it in ;-). - (mh-index-choose): Set mh-index-program instead of mh-indexer. - Update docstring to describe side-effects. - - * mh-index.el (mh-indexer): Added swish++ to docstring. Chances - are good that if someone has both swish++ and swish, they want to - use the much faster, much smaller swish, so move it up in the - list. - (mh-indexer-choices): Ditto for rationale for moving swish++ up in - priority over swish. Also, use -binary symbols instead of - hard-coding binary names. This allows package installers to - customize the location of the binaries in site-lisp and still have - the auto-detection code work. It also allows one to have alternate - binary names (see mh-swish++-binary). - (mh-index-search): Ditto (moving swish++ up). - (mh-swish++-binary): Look for search++, then search. The rationale - is that a package maintainer may rename search to search++ if - search is already in use (e.g., Debian) so try it first. - (mh-swish++-execute-search): Replaced Satyaki's path with dummy - path in docstring. Also removed RecurseSubdirs since this is the - default. Added comment that index might be named index++ on some - systems (e.g., Debian). - (mh-index-choose): Updated to work with new mh-indexer-choices. - -2002-11-04 Peter S Galbraith - - * mh-identity.el (mh-identity-list-set): Don't call easy-menu-add - here, since that adds the menu to the Customize buffer in XEmacs. - -2002-11-04 Peter S Galbraith - - * mh-comp.el (mh-mhn-compose-insert-flag) - (mh-mml-compose-insert-flag): Removed eval-when-compile defvar. - - * mh-mime.el (mh-mhn-compose-insert-flag) - (mh-mml-compose-insert-flag): Move variables to mh-utils.el. - Fixes mh-letter-menu for XEmacs. - -2002-11-04 Eric Ding - - * mh-comp.el (mh-rejected-letter-start): add another string - -2002-11-04 Eric Ding - - * mh-comp.el (mh-rejected-letter-start): regexp-opt doesn't take - regexps as args, only regular strings - -2002-11-04 Peter S Galbraith - - * mh-comp.el (mh-insert-mail-followup-to): Don't modify a - pre-existing M-F-T field. If a nmh replgroupcomps propagates a - M-F-T field in a message reply, then we have to have it alone. - -2002-11-02 Bill Wohler - - * mh-comp.el, mh-e.el, mh-funcs.el, mh-identity.el, mh-index.el, - mh-mime.el, mh-pick.el, mh-seq.el, mh-speed.el, mh-utils.el, - mh-xemacs-compat.el: Added Local Variables section. Defined - sentence-end-double-space to be nil so that those who might not - buy my setting of this variable can at least run checkdoc without - a whole lot of noise. - -2002-11-02 Peter S Galbraith - - * mh-identity.el: New file. Multiple Identify support for MH-E. - Used to easily set different fields such as From and Organization, - as well as different signature files. This file won't be included - with V7.0. - -2002-11-02 Bill Wohler - - * mh-mime.el (mh-mm-save-part): New function to wrap mm-save-part - from Gnus 5.10 to make it explicit which code has been - commandeered. - (mh-mime-save-part): Call mh-mm-save-part instead of cut-n-pasted - code from Gnus 5.10. - -2002-11-02 Peter S Galbraith - - * mh-comp.el (mh-yank-from-start-of-msg): Edit docstring to - mention related variables mh-reply-show-message-flag and - mh-delete-yanked-msg-window. - (mh-reply): Change the "Reply to whom" prompt. - -2002-11-01 Bill Wohler - - * mh-e.el (mh-show-hook): Moved to mh-utils.el where it is used. - (mh-folder-list-change-hook): Converted this from defvar in other - files to defcustom here. It is called, not documented as - obsolete, and might as well be documented. - (mh-inc-folder, mh-quit, mh-delete-a-msg, mh-refile-a-msg, - mh-process-commands, mh-update-unseen): Added missing - documentation about hook, or made verbiage about hook consistent - throughout, even if the function isn't interactive. - - * mh-utils.el (mh-folder-list-change-hook): Moved defvar to mh-e - and made it a defcustom. - (mh-show-mode-hook): Put it back in (actually, it was in mh-e.el, - but this is the place where it is called). - (mh-show-hook): Moved here from mh-e.el since it's called here. - (mh-show-mode): Call mh-show-mode-hook. - (mh-show-mode, mh-show-msg, mh-find-path, mh-prompt-for-folder, - mh-prompt-for-folder, mh-set-folder-list): Added missing - documentation about hook, or made verbiage about hook consistent - throughout, even if the function isn't interactive. - - * mh-comp.el (mh-send-letter): Made verbiage about hook consistent - throughout. - (mh-insert-prefix-string): Made docstring more descriptive of what - is going on. - - * mh-funcs.el (mh-kill-folder): Added missing documentation about - hook. - - * mh-index.el (mh-index-show-hook): Moved defvar to defcustom. - (mh-index-show): Made verbiage about hook consistent throughout. - - * mh-mime.el (mh-edit-mhn-hook): Moved defvar to defcustom. - (mh-edit-mhn): Added missing documentation about hook. - - * mh-pick.el (mh-pick-mode): Made verbiage about hook consistent - throughout. Call the damn hook. - -2002-11-01 Satyaki Das - - * mh-comp.el (mh-insert-mail-followup-to-list): Fix typo so that - it will look right in info. - - * mh-index.el (mh-index-search): Change argument name from - new-buffer-p to new-buffer-flag. - (mh-index-search-again, mh-index-search): New index-buffers were - being named *mh-index*<2>, *m-index*<2><2> and so on. This problem - is fixed. - (mh-index-scroll-up, mh-index-scroll-down): Scrolling in index - show buffers (after the first one) was broken. - (mh-index-quit): Bury show buffer instead of killing it. Killing - it, without killing the corresponding folder buffer, can cause - confusion with two folder buffers trying to display in the same - show buffer. - - * mh-seq.el (mh-thread-prune-containers): Rewritten without - recursion. Also removed the top-level-p argument since it isn't - required anymore. - (mh-thread-sort-containers): New function factored out from - previous definition of mh-thread-prune-containers. It sorts - message containers in ascending order wrt their message indices. - (mh-thread-generate): Use new mh-thread-prune-containers. - - * mh-e.el (mh-remove-all-notation): Fix the test. It was testing - at the wrong place! - -2002-10-31 Bill Wohler - - * Makefile, README, import-emacs, mh-comp.el, mh-e.el, - mh-funcs.el, mh-index.el, mh-mime.el, mh-pick.el, mh-seq.el, - mh-speed.el, mh-utils.el: Replaced mh-e with MH-E. - -2002-10-31 Satyaki Das - - * mh-seq.el (mh-thread-parse-scan-line): Modified to remove user - sequence notation and leave notation for other things alone. This - ensures that threading doesn't lose notations for replied-to - messages. - - * mh-e.el (mh-inc-folder): Remove call to mh-widen here and - instead do it in mh-get-new-mail. This way the widening happens - only if new mail is incorporated. - (mh-generate-new-cmd-note): The function now returns the point - from which the new messages start. This will allow threading to do - the right thing. - (mh-get-new-mail): Always call mh-remove-cur-notation. Otherwise - adaptive scan mode leaves two messages marked as current in - certain cases. Fix indentation of if statement. If there are - messages to be incorporated, the folder is widened. If mh-cmd-note - changes set start-of-inc correctly. - (mh-remove-all-notation): Change this function to only remove user - sequence notation and leave notation for replied-to messages and - similar notation alone. This means operations like narrowing to - subject sequence and widening don't lose notations. - -2002-10-31 Bill Wohler - - * mh-comp.el (mh-insert-mail-followup-to-list): Fixed typo in - docstring and other minor edits. Checkdoc removed trailing spaces. - (mh-insert-signature): Checkdoc flagged docstring. Reverted to - previous value. Added specific name of hook that is run. - (mh-regexp-in-field-p, mh-insert-letter): Checkdoc removed - trailing spaces. - -2002-10-31 Jeffrey C Honig - - * mh-e.el (mh-show-mode-hook): Remove the unused - mh-show-mode-hook, mh-show-hook is the one that is used. - - * mh-utils.el (mh-show-mode): Change the documentation to refer to - mh-show-hook instead of the unused mh-show-mode-hook. - -2002-10-31 Peter S Galbraith - - * mh-comp.el (mh-insert-mail-followup-to-list): Set default to nil - and include example in doc string. - -2002-10-31 Satyaki Das - - * mh-index.el (mh-indexer): Add customization choice for swish++. - (mh-indexer-choices): Add swish++ choice. - (mh-index-search): Change doc to reflect addition of swish++ option. - (mh-swish++-binary, mh-swish++-directory): New variables for - swish++ interface. - (mh-swish++-execute-search): New function to execute swish++ - search. - (mh-swish++-next-result): Function aliased to mh-swish-next-result - since the result format of swish++ is the same as that of swish-e. - (mh-index-search): Always overwrite window-configuration with new - value. This is needed since we don't kill the index-buffer when - quitting which means the window configuration wasn't getting set - properly. - (mh-index-search-again): If index buffer is reused, reset the old - window config to its original value. - -2002-10-30 Bill Wohler - - * Makefile (emacs, xemacs): New targets. - (all): Use these targets instead of calling specific targets. - (.PHONY): Added emacs, xemacs, autoloads, custom-loads. Broke up - target and moved pieces into their own sections. - -2002-10-30 Peter S Galbraith - - * mh-utils.el (mh-show-font-lock-keywords): Wrap an - 'eval-and-compile around its defvar, otherwise byte-compilation - fails on `mh-show-font-lock-keywords-with-cite'. - -2002-10-29 Jeffrey C Honig - - * mh-comp.el (mh-letter-insert-signature-hook) - (mh-insert-signature): Add a hook to be called before inserting - the signature. Do not attempt to insert the signature if - mh-insert-signature-file-name is nil. - -2002-10-29 Peter S Galbraith - - * mh-e.el (mh-inc-folder): Call mh-widen when mh-narrowed-to-seq - (Closes SF #629233: inc in narrowed folder suboptimal) - - * mh-comp.el (mh-insert-letter): Stop using mhl to include a - message before it mangles the header, and supercite fails - (Closes SF #629153: mh-insert-letter uses mhl?). - (mh-insert-prefix-string): Leave point at beginning instead of - end, since that's what sc-cite-original does. - (mh-yank-cur-msg): Adjust for mh-insert-prefix-string change. - -2002-10-30 Steve Youngs - - * mh-e.el (mh-folder-mode): Check for 'font-lock-auto-fontify' - when in XEmacs so we don't do font-locking unconditionally. - - * mh-utils.el (mh-show-mode): Ditto. - -2002-10-29 Peter S Galbraith - - * mh-e.el (mh-folder-refiled-face, mh-folder-cur-msg-number-face) - (mh-folder-to-face, mh-folder-body-face): Define faces instead of - copying them from font-lock faces. This mh-e will look the same - in XEmacs as it does in Emacs. - * mh-utils.el (mh-show-cc-face, mh-show-date-face) - (mh-show-header-face): Ditto. - -2002-10-29 Jeffrey C Honig - - * mh-comp.el (mh-send-letter): I meant to use - mh-goto-header-field, not mh-get-header-field. The former returns - nil if the header is not found and doesn't need a conditional. - -2002-10-29 Peter S Galbraith - - * mh-comp.el (mh-forward): Bug fix. Change 'kill-line for a - 'delete-region, because I don't want that text yanked with C-y. - - * mh-seq.el (mh-put-msg-in-seq): Add support for selected - region (Closes SF feature request #630324). - -2002-10-28 Satyaki Das - - * mh-seq.el (mh-thread-prune-subject): Make the regexp a little - general so that a subject of the form "Re[218]: howdy" would be - properly pruned. - - * mh-mime.el (mh-mime-save-part): Copy function definition of - mm-save-part from cvs gnus since that function is buggy in gnus - that comes with emacs21.2. - -2002-10-28 Peter S Galbraith - - * mh-e.el (mh-scan-subject-regexp): Add an expression to match an - optional bracketed number after "Re", such as in "Re[2]:". - (Patch by Satyaki; I checked it and applied). - (mh-folder-font-lock-subject): Adapt to new mh-scan-subject-regexp. - * mh-seq.el (mh-subject-to-sequence): Ditto. - - * mh-e.el (mh-folder-sequence-menu): Remove "Toggle Subject - Thread" from menu. mh-toggle-threads is in the Folder menu. - - * mh-e.el (mh-folder-sequence-menu): Minor menu text edits. - - * mh-utils.el (mh-show-update-sequences): Added to - mh-defun-show-buffer builds; needed for menu. - (mh-show-sequence-menu, mh-show-message-menu) - (mh-show-folder-menu): 3 new menus in mh-show-mode-map that mirror - the menus used in mh-folder-mode. - (mh-show-mode): easy-menu-add the 3 menus. - -2002-10-28 Satyaki Das - - * mh-utils.el (mh-goto-msg): Fix the regexp to search so that we - go to the right message. In a threaded folder message 2 may be - present after 26 and the previous regexp would go to 26 when we - really wanted to go to 2! - - * mh-seq.el (mh-widen): Add call to mh-recenter to make it like - mh-narrow-to-seq. - -2002-10-28 Bill Wohler - - * mh-utils.el (mh-show-mime-save-parts): Deleted definition. - (mh-show-mime-map, tool-bar-map): Use mh-mime-save-parts instead - of mh-show-mime-save-parts. - -2002-10-28 Peter S Galbraith - - * mh-comp.el (mh-letter-tool-bar-map): tool-bar-add-item key name - bug fix. - * mh-utils.el (mh-show-tool-bar-map): Same. - * mh-e.el (mh-folder-tool-bar-map, mh-folder-seq-tool-bar-map): Same - -2002-10-27 Satyaki Das - - * mh-seq.el (mh-toggle-threads): Add call to mh-recenter to make - its behavior like that of mh-narrow-to-seq. - -2002-10-27 Bill Wohler - - * mh-mime.el (mh-mime-save-parts): Renamed from - mh-store-mime-parts for consistency with mh-mime-save-part. Fixed - bug whereby mh-mime-save-parts-directory was not getting - initialized properly from a string-valued - mh-mime-save-parts-default-directory. - (mh-mime-save-parts-default-directory): Ditto. Check your - customizations! - (mh-mime-save-parts-directory): Ditto. - - * mh-utils.el (mh-show-mime-save-parts): Renamed from - mh-store-mime-parts. - (mh-show-mime-map): Added keybinding "K a" for - mh-show-mime-save-parts. - - * mh-e.el (mh-mime-save-parts) Renamed from mh-store-mime-parts. - (mh-mime-map): Added keybinding "K a" for mh-mime-save-parts. - (mh-help-messages): Added help for "K a". - -2002-10-27 Peter S Galbraith - - * mh-comp.el (mh-search-addr-regexp, mh-regexp-in-field-p): Rename - the first to the second (and recode a bit). - (mh-insert-mail-followup-to): Use it. - -2002-10-27 Bill Wohler - - * mh-utils.el (mh-invisible-headers): Backed out change. Removed - Mail-Followup-To due to objections from Peter and Mark. - -2002-10-27 Satyaki Das - - * mh-seq.el (mh-msg-is-in-seq): Modified to show info about - whether the message being queried about has been marked to be - deleted or refiled. - - * mh-mime.el (mh-insert-mime-security-button): Make - pressed-details a local. - -2002-10-27 Steve Youngs - - * .cvsignore: New file. - -2002-10-26 Steve Youngs - - * mh-seq.el (mh-notate-deleted-and-refiled): Don't bind local - variable 'dest', it isn't used anywhere. - - * mh-pick.el (mh-do-pick-search): Don't bind local variable - 'finding-messages', it isn't used anywhere. - - * mh-utils.el: Byte-compiler warning suppression. - (mh-gnus-article-highlight-citation): Rather than redefining - 'gnus-cite-face-list', just re-order it. - (mh-show-mode): Force turning on font-lock in XEmacs. - - * mh-seq.el: Byte-compiler warning suppression. - - * mh-index.el: Byte-compiler warning suppression. - - * mh-comp.el: Byte-compiler warning suppression. - - * mh-xemacs-compat.el: Add defaliases for 'timerp' & - 'cancel-timer' to the equivalent 'itimer' functions. - (rfc822): Require it for 'rfc822-goto-eoh'. - Byte-compiler warning suppression. - - * mh-e.el (mh-folder-mode): Force turning on font-lock in XEmacs. - (mh-toggle-threads): Remove duplicate autoload. - Byte-compiler warning suppression. - (mh-folder-unseen-seq-list): Use 'with-temp-buffer' to fix a bug - in XEmacs when font-lock is on. - (mh-folder-unseen-seq-name): Ditto. - -2002-10-27 Mark D. Baushke - - * Makefile: Reorganize to allow for building also compiling for - XEmacs too. Sanitize so that it will work using least-common - denominator versions of 'make'. Tested using GNU make, Solaris make, - and Berkely make. - (all): Use recursive invocation based on the emacs or xemacs - executable passed on the 'make EMACS=xemacs' command line. - (XEMACS_OPTIONS): The incantation to be passed to an xemacs editor - to compile things properly. - (AUTO_PRELOADS): Magic XEmacs glue. - (clean): Ditto. - (autoloads): Ditto. - (custom-loads): Ditto. - -2002-10-26 Satyaki Das - - * mh-e.el (mh-last-msg): Add call to mh-recenter. - -2002-10-26 Peter S Galbraith - - * mh-comp.el (mh-search-addr-regexp, mh-re-search-to-cc): Remove - `mh-re-search-to-cc' in favor of more generalized new function - `mh-search-addr-regexp'. - (mh-insert-mail-followup-to): Use it. - -2002-10-26 Satyaki Das - - * mh-seq.el (mh-copy-seq-to-eob): Avoid rethreading when the - folder is already threaded. This is more efficient and also avoids - problems when the folder is widened. - (mh-thread-inc): Don't try to restore the point to original - location since mh-inc-folder from where this is called changes - point location after calling this function. - - * mh-e.el (mh-make-folder-mode-line): Fix a small bug where the - test was wrong. - -2002-10-26 Peter S Galbraith - - * mh-comp.el (mh-insert-mail-followup-to): Fix for new defcustom. - -2002-10-26 Satyaki Das - - * mh-seq.el (mh-notate-deleted-and-refiled): Remove unused binding - of dest. The problem was pointed out by Steve as well. - - * mh-e.el (mh-toggle-threads): Remove duplicate autoload as - pointed out by Steve. - -2002-10-26 Bill Wohler - - * mh-utils.el (mh-invisible-headers): Added Mail-Followup-To. - -2002-10-26 Peter S Galbraith - - * mh-comp.el (mh-insert-mail-followup-to-list): Change defvar to - defcustom. - -2002-10-25 Satyaki Das - - * mh-e.el (mh-remove-all-notation): New function that removes all - notation. - - * mh-seq.el (mh-narrow-to-seq): When hiding the original folder - remove all notation. This avoids stale notation hanging around. - Also changes in show buffer and position in folder buffer are - avoided if possible. - (mh-widen): When widening the scan-lines are notated based on the - current state of the folder. This means any changes made when the - folder was narrowed are shown consistently. - (mh-notate-deleted-and-refiled): Update the documentation. - (mh-thread-parse-scan-line): For some reason the ASCII value of - the space character was being used here. This is fixed. - (mh-thread-inc, mh-toggle-threads): Avoid change of point in - folder and message being displayed in shown buffer. - - * mh-utils.el (mh-recenter): Rewrite mh-recenter to show fewer - blank lines when point is towards the end of the folder buffer. - -2002-10-25 Peter S Galbraith - - * mh-comp.el (mh-insert-mail-followup-to-flag): New boolean - defcustom to 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'." - (mh-insert-mail-followup-to-list): New defvar. List of addresses - for which a Mail-Followup-To field is inserted. - (mh-re-search-to-cc): New function. Search for REGEXP in To: and - Cc: fields. - (mh-insert-mail-followup-to): New function. Insert - Mail-Followup-To: if To or Cc match `mh-insert-mail-followup-to-list'. - (mh-compose-and-send-mail): Call mh-insert-mail-followup-to if - mh-insert-mail-followup-to-flag is true. - -2002-10-25 Mark D. Baushke - - * mh-utils.el (mh-show-maximum-size): New variable to control - the display of large messages. - (mh-display-msg): Use it (Closes SF #488696). - - * mh-seq.el (mh-toggle-threads): Checkdoc fix. - - * mh-e.el (mh-reset-threads-and-narrowing): Checkdoc fix. - - * mh-comp.el (mh-insert-x-mailer-flag): Renamed from - mh-insert-x-mailer-p. Update docstring. - (mh-send-letter): Use it. - (mh-reply-show-message-flag): Renamed from - mh-reply-show-message-p. Update docstring. - (mh-reply): Use it. - This addresses part of SF #627015. - - * mh-e.el (mh-recenter-summary-flag): Renamed from - mh-recenter-summary-p. Update docstring. - (mh-set-scan-mode): Use it. - This addresses part of SF #627015. - -2002-10-25 Satyaki Das - - * mh-e.el (mh-reset-threads-and-narrowing): New function which - resets all thread and narrowing state to completely unthreaded and - widened state. As a side effect, the folder buffer is erased. - (mh-rescan-folder): Reset threads and narrowing state. - - * mh-funcs.el (mh-pack-folder-1): Reset threads and narrowing state. - - * mh-seq.el (mh-copy-seq-to-eob): Change mh-view-ops after - threading is over so that if user aborts threading, it doesn't - leave mh-e in an inconsistent state. - (mh-toggle-threads): Use mh-scan-folder to populate the folder - buffer instead of mh-rescan-folder which resets threading and - narrowing state. - -2002-10-24 Bill Wohler - - * mh-e is completely checkdoc clean now. - - * mh-utils.el (mh-clean-message-header-flag): Renamed from - mh-clean-message-header. - (mh-bury-show-buffer-flag): Renamed from mh-bury-show-buffer. - (mh-show-use-goto-addr-flag): Renamed from mh-show-use-goto-addr. - This addresses part of SF #627015. - - * mh-mime.el (mh-clean-message-header-flag): Renamed from - mh-clean-message-header. - Checkdoc fixes. This addresses part of SF #627015. - - * mh-index.el (mh-clean-message-header-flag): Renamed from - mh-clean-message-header. This addresses part of SF #627015. - - * mh-funcs.el (mh-do-not-confirm-flag): Renamed from - mh-do-not-confirm. This addresses part of SF #627015. - - * mh-e.el (mh-do-not-confirm-flag): Renamed from - mh-do-not-confirm. - (mh-clean-message-header-flag): Renamed from - mh-clean-message-header. - This addresses part of SF #627015. - - * mh-comp.el: checkdoc fixes. - -2002-10-24 Satyaki Das - - * mh-seq.el (mh-copy-seq-to-eob): Rewritten to scan the headers - fresh instead of yanking from buffer. This is needed to get - correct threading in copied sequence. - (mh-thread-inc, mh-thread-update-scan-line-map) - (mh-thread-parse-scan-line): Eliminate the use, and hence the - definition of, the kludgy mh-thread-update-scan-line-map. Instead - the functions mh-notate-deleted-and-refiled and - mh-notate-user-sequences are used to get the message marks right. - (mh-thread-generate-scan-lines): Updated to allow the thread tree - to be used in a narrowed folder buffer. - (mh-thread-folder, mh-toggle-threads): Remove - mh-folder-threaded-view-flag. - (mh-thread-old-scan-line-map): New buffer-local variable that - remembers the original scan-line map so that the sequence thread, - narrow, widen will work. - (mh-narrow-to-seq, mh-widen): Remember the scan-line map when - narrowing and restore it when widening. - - * mh-e.el (mh-folder-threaded-view-flag, mh-folder-folder-menu) - (mh-regenerate-headers, mh-get-new-mail) - (mh-make-folder-mode-line, mh-process-commands) - (mh-delete-scan-msgs): Remove mh-folder-threaded-view-flag. - Instead (memq 'unthread mh-view-ops) is used to test if the folder - is threaded. - - * mh-mime.el (mh-display-emphasis): Shadow article-goto-body here - since we want to do emphasis on the whole of the region and not - just after the first blank line. - (mh-mm-display-part): When displaying a text part show smilies and - emphasis. - - * mh-index.el (mh-index-insert-scan): Attempt to keep number of - args to scan small if there are lots of adjacent matches. - (mh-index-quit): Bury index-buffer on quit instead of killing it. - This behavior is more like that of mh-quit. - - * mh-seq.el (mh-widen): If folder was threaded after narrowing - then make mh-widen undo the threading instead of erroring out. - -2002-10-24 Peter S Galbraith - - * mh-seq.el (mh-toggle-threads): Add a cond (as suggested by - Satyaki) to properly unthread a narrowed-to-sequence. - - * mh-seq.el (mh-thread-generate-scan-lines): Fix threading - breakage from partial switch to mh-container-real-child-flag and - to dupl-flag. - - * mh-comp.el (mh-yank-cur-msg): Bug fix: specify - (eq t mh-yank-from-start-of-msg) when that's what we want. - -2002-10-24 Mark D. Baushke - - * mh-seq.el (mh-thread-prune-subject): Renamed subject-pruned-p as - subject-pruned-flag. - (mh-thread-inc): Renamed old-buffer-modified-p as - old-buffer-modified-flag. - (mh-thread-generate-scan-lines): Renamed dupl-p as dupl-flag. - This addresses part of SF #627015. - - * mh-index.el (mh-index-advance): Renamed backward-p - local variable as backward-flag. - (mh-index-next-button): Renamed backward-p - argument as backward-flag. - (mh-index-show): Renamed display-headers-p argument as - display-headers-flag. - This addresses part of SF #627015. - - * mh-e.el (mh-scan-format, mh-version): Use mh-nmh-flag. - (mh-folder-mime-action): Renamed include-security-p - argument as include-security-flag. - (mh-goto-next-button, mh-next-button): Renamed backward-p - argument as backward-flag. - (mh-get-new-mail): Renamed new-mail-p local variable as - new-mail-flag. - (mh-goto-cur-msg): Renamed minimal-changes-p argument as - minimal-changes-flag. - (redraw-needed-flag): Renamed redraw-needed-p local variable as - redraw-needed-flag. - (mh-seq-containing-msg): Renamed include-internal-p argument as - include-internal-flag. - (mh-page-msg): Use mh-page-to-next-msg-flag. - This addresses part of SF #627015. - - * mh-mime.el (mh-mhn-compose-insert-flag): Renamed from - mh-mhn-compose-insert-p. Make it buffer-local. - (mh-mhn-compose-type, mh-mhn-compose-external-type, - mh-mhn-compose-forw, mh-edit-mhn): Use mh-mhn-compose-insert-flag. - (mh-mml-to-mime, mh-mml-secure-message-encrypt-pgpmime, - mh-mime-display-part, mh-mime-display-single): Use - mh-gnus-pgp-support-flag renamed from mh-gnus-pgp-support-p. - (mh-mime-display-single): Renamed small-image-p local - variable as small-image-flag. - (mh-mime-inline-part): Renamed local variable inserted-p as - inserted-flag. - (mh-mime-inline-part): Renamed local variable displayed-p as - displayed-flag. - This addresses part of SF #627015. - - * mh-comp.el (mh-letter-menu, mh-letter-mode, mh-send-letter): - mh-mhn-compose-insert-flag. - (mh-repl-group-formfile, mh-forward): Use mh-nmh-flag - renamed from mh-nmh-p. - (mh-reply, mh-insert-x-mailer, mh-send-letter): Use mh-nmh-flag. - (mh-letter-mode-map): Use mh-gnus-pgp-support-flag renamed from - mh-gnus-pgp-support-p. - (mh-mml-secure-message-sign-pgpmime): Use - mh-gnus-pgp-support-flag. - This addresses part of SF #627015. - - * mh-utils.el (mh-page-to-next-msg-flag): Renamed from - mh-page-to-next-msg-p. - (mh-show-msg): Use mh-page-to-next-msg-flag. - (mh-gnus-pgp-support-flag): Renamed from - mh-gnus-pgp-support-p. - (mh-show-font-lock-fontify-region): Fix docstring per checkdoc. - (with-mh-folder-updating): Renamed argument - save-modification-flag-p as mh-save-modification-flag. - (mh-prompt-for-folder): Renamed new-file-p local - variable as new-file-flag. - This addresses part of SF #627015. - -2002-10-24 Mark D. Baushke - - * mh-comp.el (mh-forward): Fix mh-mml-compose-insert-p reference - in last commit to be mh-mml-compose-insert-flag. - (mh-mml-compose-insert-flag): Move defvar to fix compiler warning. - -2002-10-24 Jeffrey C Honig - - * mh-comp.el (mh-forward): Add support for transient-mark mode. - When using nmh, always specify -mime so as to preserve the - original message(s). If mh-compose-insertion is 'gnus, convert - the mhbuild format forwarding directives into MML. - -2002-10-24 Eric Ding - - * mh-comp.el (mh-send-letter): Fix for earlier change that added - "-mime" for bcc'ed MIME mail; still doesn't work with nmh 1.0, but - at least no longer triggered for every outgoing message! - -2002-10-24 Peter S Galbraith - - * mh-comp.el (mh-yank-cur-msg): Fix selected regions for supercite - (see text below). - - * mh-comp.el (mh-yank-cur-msg): Fix for supercite. Someone played - with the point and mark setting prior to the call to - 'mh-insert-prefix-string and that broke supercite. I put comments - to make it obvious to future coders why those settings exists. - Note that supercite is still broken when a region is selected in - the show buffer. Presumably it's been like that for a long time. - We need to insert the header as well as the selected region oin - that case. I'll submit an SF bug. - -2002-10-24 Jeffrey C Honig - - * mh-comp.el (mh-yank-from-start-of-msg, mh-reply): Use -noformat - flag to reply when 'autosupercite or 'autoattrib are specified to - prevent duplicate cites of the body of a message. - -2002-10-23 Satyaki Das - - * mh-utils.el (font-lock-default-fontify-region): Add autoload to - avoid compiler warning. - -2002-10-23 Peter S Galbraith - - * mh-comp.el (mh-letter-mode): set fill-paragraph-function to our - own 'mh-fill-paragraph-function instead of simply - 'mail-mode-fill-paragraph (because it doesn't handle a non-nil - fill-prefix correctly). - (mh-fill-paragraph-function): New function for mh-letter-mode - fill-paragraph-function in order to handle non-nil fill-prefix. - Call sendmail's mail-mode-fill-paragraph if in the mail header, - else call default fill-paragraph with fill-prefix set to nil. - (Closes SF #489927) - - * mh-comp.el (mh-letter-mode): Let's use font-lock even if gnus is - used in show-mode. The reason is that gnus uses static text - properties which are not appropriate for a buffer that will be - edited. So the choice here is either fontify the citations and - header or the header only. - - * mh-utils.el (mh-show-font-lock-fontify-region): Limit font-lock - in mh-show-mode to the header. Used when mh-highlight-citation-p - is set to gnus, leaving the body to be dealt with by gnus - highlighting. This fixes gnus text emphasis in mh-show-mode. - (mh-show-mode): In font-lock-defaults, set - font-lock-fontify-region-function to mh-show-font-lock-fontify-region. - -2002-10-23 Bill Wohler - - * mh-mime.el (mh-mml-attach-file): Prompt for disposition should - be Disposition, not Content-Type. The Content-Type has been - determined automatically. - -2002-10-23 Mark D. Baushke - - * MH-E-NEWS: - s/mh-adaptive-cmd-note/mh-adaptive-cmd-note-flag/ - s/mh-show-use-xface/mh-show-use-xface-flag/ - s/mh-tool-bar-reply-3-buttons/mh-tool-bar-reply-3-buttons-flag/ - This addresses part of SF #627015. - - * mh-comp.el: - s/mh-mml-compose-insert-p/mh-mml-compose-insert-flag/ - s/mh-xemacs-p/mh-xemacs-flag/ - (mh-letter-menu): Use mh-mml-compose-insert-flag. - (mh-insert-x-mailer): Use mh-xemacs-flag. - (mh-mml-compose-insert-flag): Renamed from - mh-mml-compose-insert-p. - (mh-send-letter): Use mh-mml-compose-insert-flag. - This addresses part of SF #627015. - - * mh-e.el: - s/mh-folder-threaded-view-p/mh-folder-threaded-view-flag/ - s/mh-adaptive-cmd-note/mh-adaptive-cmd-note-flag/ - s/mh-xemacs-p/mh-xemacs-flag/ - (mh-folder-threaded-view-flag): Renamed from - mh-folder-threaded-view-p. Make it buffer local. - (mh-folder-tool-bar-map): Use mh-tool-bar-reply-3-buttons-flag. - (mh-remove-xemacs-horizontal-scrollbar): Use mh-xemacs-flag. - (mh-make-folder, mh-regenerate-headers, mh-get-new-mail): Use - mh-adaptive-cmd-note-flag. - (mh-folder-folder-menu, mh-regenerate-headers, mh-get-new-mail, - mh-make-folder-mode-line, mh-process-commands, - mh-delete-scan-msgs): Use mh-folder-threaded-view-flag. - This addresses part of SF #627015. - - * mh-index.el: - s/mh-adaptive-cmd-note/mh-adaptive-cmd-note-flag/ - (mh-index-search): Use mh-adaptive-cmd-note-flag. - This addresses part of SF #627015. - - * mh-mime.el: - s/mh-mml-compose-insert-p/mh-mml-compose-insert-flag/ - s/mh-xemacs-p/mh-xemacs-flag/ - (mh-mml-compose-insert-flag): Renamed from - mh-mml-compose-insert-p. Make it buffer local. - (mh-mml-attach-file, mh-mml-secure-message-sign-pgpmime, - mh-mml-secure-message-encrypt-pgpmime): Use it. - (gnus-local-map-property): Use mh-xemacs-flag. - This addresses part of SF #627015. - - * mh-seq.el: - s/mh-folder-threaded-view-p/mh-folder-threaded-view-flag/ - (mh-thread-generate, mh-thread-folder, mh-toggle-threads): Use - mh-folder-threaded-view-flag. - This addresses part of SF #627015. - - * mh-speed.el: - s/mh-speed-run-flists-p/mh-speed-run-flists-flag/ - s/mh-speed-refresh-p/mh-speed-refresh-flag/ - (mh-speed-run-flists-flag): Renamed from mh-speed-run-flists-p. - (mh-folder-speedbar-buttons): Use it. - (mh-speed-refresh-flag): Renamed from mh-speed-refresh-p. - (mh-speed-update-current-folder, mh-speed-invalidate-map, - mh-speed-add-folder): Use it. - This addresses part of SF #627015. - - * mh-utils.el: - s/mh-xemacs-p/mh-xemacs-flag/ - s/mh-tool-bar-reply-3-buttons/mh-tool-bar-reply-3-buttons-flag/ - s/mh-show-use-xface/mh-show-use-xface-flag/ - (mh-xemacs-flag): Renamed from mh-xemacs-p. - (mh-show-xface-function): Use it. - (mh-tool-bar-reply-3-buttons-flag): Renamed from - mh-tool-bar-reply-3-buttons. - (mh-show-tool-bar-map): Use it. - (mh-adaptive-cmd-note-flag): Renamed from mh-adaptive-cmd-note. - (mh-cmd-note): Use it in description. - (mh-show-use-xface-flag): Renamed from mh-show-use-xface. Use - mh-xemacs-flag. - (mh-show-xface): Use mh-show-use-xface-flag. - This addresses part of SF #627015. - -2002-10-23 Bill Wohler - - * Makefile (all): Rather than have to run "make clean all" all the - time, make the default target do a clean so all you have to say is - "make". - - * mh-e.el (mh-folder-map): Moved "t (mh-toggle-threads)" to T - prefix. - -2002-10-22 Satyaki Das - - * mh-index.el (mh-indexer-choices, mh-swish-binary): The - executable swish-e can be used to search (just like swish-search). - However the Makefile in swish-e-2.2.2 doesn't install - swish-search. So it is preferable to use swish-e. - -2002-10-22 Bill Wohler - - * mh-comp.el (mh-letter-mode-map): Added aliases for keybindings. - For example, you now have "C-c C-m C-i" in addition to "C-c C-m - i". - -2002-10-22 Mark D. Baushke - - * mh-mime.el (mh-graphical-smileys-flag): Renamed from - mh-graphical-smileys-p. - (mh-display-smileys): Use it. - (mh-graphical-emphasis-flag): Renamed from mh-graphical-emphasis-p. - (mh-display-emphasis): Use it. This addresses part of SF #627015. - -2002-10-22 Satyaki Das - - * mh-mime.el (mh-insert-mime-security-button): A message is - produced if PGP decryption/verification fails. This addresses - SF# 627025. - -2002-10-21 Bill Wohler - - * mh-seq.el (mh-widen): Checkdoc removed the period in the error. - The info node (elisp) Coding Conventions says: "An error message - should start with a capital letter but should not end with a - period." - - * mh-e.el, mh-utils.el (mh-tool-bar-reply-3-buttons): Moved - defcustom to mh-utils because I got an error about a nil value for - mh-tool-bar-reply-3-buttons when I fired up mh-rmail. - - * mh-comp.el, mh-funcs.el, mh-mime.el, mh-pick.el: Moved (provide) - to the end of the file to be consistent with most other files (see - additional rationale in mh-e.el description below). - - * mh-e.el: Had to remove eval-when-compile from the (require 'cl) - here too (because the remove-if generated a warning in CVS Emacs). - Moved (provide) to the end of the file to be consistent with most - other files. My guess is that this is good to keep a feature from - being "provided" if the file craps out while being loaded. - -2002-10-21 Satyaki Das - - * mh-utils.el (mh-reply, Info-goto-node): Add autoloads to avoid - compiler warnings. - (mh-tool-bar-reply-3-buttons): Add defvar to avoid compiler - warning. - - * mh-seq.el (mh-narrow-to-seq): Remember that a narrowing has - occurred. - (mh-valid-view-change-operation-p): New function that checks if - the widening or unthreading that we are about to perform is - allowed. - (mh-widen): Check if widening is applicable. - (mh-thread-inc, mh-thread-folder): Use delete-region instead of - erase-buffer. This means if the buffer is narrowed then the hidden - parts aren't removed. This allows widening of the folder later on. - (mh-toggle-threads): Maintain mh-view-ops. - - * mh-e.el (mh-view-ops, mh-folder-mode): New buffer-local variable - that keeps track of the sequence in which threading and narrowing - of the folder buffer has been carried out. This is needed so that - narrowing followed by threading (or vice versa) behaves in a - reasonable manner. - (mh-regenerate-headers): Use delete-region instead of - erase-buffer. - (mh-make-folder-mode-line): Change mh-first-msg-num and - mh-last-msg-num conservatively. This might show a larger range in - the mode-line but allows the unthreading to not miss messages - present initially. - -2002-10-21 Bill Wohler - - * mh-mime.el (mh-graphical-emphasis-p): Added _underline_ to the - docstring, as well as the source of the strings, - gnus-emphasis-alist. - (mh-graphical-emphasis-p, mh-graphical-smileys-p): Set the default - to t. - -2002-10-21 Peter S Galbraith - - * mh-utils.el (mh-show-mode): Invoke new toolbar. - (mh-show-tool-bar-map): New tool-bar for mh-show-mode, similar to - mh-letter-mode. - -2002-10-21 Satyaki Das - - * mh-utils.el (mh-display-msg): Call the smiley display function - after the call to mh-show-mode. This is needed since mh-show-mode - kills all buffer-local variables and resets the variable that - controls display of graphical smileys. - -2002-10-21 Bill Wohler - - * mh-e.el (mh-folder-mime-action): Change mime to MIME in message. - - * mh-comp.el (mh-mml-to-mime autoload): Ditto. - -2002-10-21 Mark D. Baushke - - * mh-mime.el (smiley-region): Use load for a non-fatal dependency - on the smiley library. - -2002-10-21 Jeffrey C Honig - - * mh-comp.el (mh-forward): Search for a blank line as well as - mail-header-separator. - (mh-letter-mode): Search for a blank line as well as - mail-header-separator. - (mh-send-letter): The default BCC encapsulation will make a MIME - message unreadable. If we are running nmh and the letter contains - a Bcc: and a Content-Type: field, add the -mime switch to the - arguments to send. - -2002-10-21 Peter S Galbraith - - * mh-utils.el: Add a mh-defun-show-buffer call to define - mh-show-pack-folder. - -2002-10-21 Peter S Galbraith - - * mh-mime.el (mh-store-mime-parts): Simplify code a bit. - - * mh-e.el (mh-help-messages): Update help message for changed - keybindings. - -2002-10-21 Satyaki Das - - * mh-speed.el (mh-speed-invalidate-map): Invalidate - mh-speed-folders-cache before it is used by mh-speed-folders. Also - fix indentation of if statement. - (mh-speed-folder-size): The folder name should be extracted from - the speedbar buffer and not from the temp buffer has was happening - before. - (mh-speed-folder-size): Harden the function some more. It - shouldn't produce errors any more unless flist really didn't work. - -2002-10-21 Bill Wohler - - * mh-seq.el (mh-put-msg-in-seq): Formatting only. The reason I was - in there is because I was trying to use mh-put-msg-in-seq and - mh-msg-is-in-seq non-interactively and found that although the - docstring says it uses the current message by default, I got - errors if I passed in nil for the message. Is this expected, or is - this a bug? I suppose the fix would be to make the arguments - optional, right? This would cause the arguments in - mh-put-msg-in-seq to be reversed, however. Might be a backwards - compatibility problem. - - * mh-speed.el (mh-speed-view): Convert default size to string - before passing it to read-string. This was done because XEmacs - can't handle a numeric value for the default. - -2002-10-20 Satyaki Das - - * mh-utils.el (mh-show-mode-map, mh-show-folder-map) - (mh-show-sequence-map, mh-show-thread-map, mh-show-extract-map) - (mh-show-digest-map, mh-show-mime-map): Interactive functions - callable in show buffer are now prefixed with mh-show. - - * mh-seq.el (mh-notate-deleted-and-refiled): Take into account the - changes to mh-refile-list and the removal of the 'deleted - sequence. - (mh-toggle-threads): Changing from threaded to normal view doesn't - try to push out message refiles and deletions to MH. - - * mh-e.el (mh-rescan-folder, mh-scan-folder): Add a new optional - argument to both functions that prevents them from carrying out - pending refiles and deletes. - (mh-undo): Remove dead code. - (mh-delete-a-msg, mh-undo-msg): Get rid of the 'deleted sequence. - The same information is present in mh-delete-list any way. - (mh-refile-a-msg, mh-undo-msg, mh-process-commands): Change the - semantics of mh-refile-list to make it self-contained. This - variable now contains a list of lists. The first element of each - sublist is the destination folder name. The remaining elements are - the messages that are to be refiled to the destination folder. - (mh-toggle-threads, mh-folder-folder-menu): Use mh-toggle-threads - instead of mh-thread-folder. - -2002-10-20 Peter S Galbraith - - * mh-mime.el (mh-store-mime-parts): Bug fix? Make this command - work when in the show buffer, and not just in the folder buffer - pointing to a message. - -2002-10-20 Peter S Galbraith - - * mh-seq.el (mh-narrow-to-subject-sequence): Renamed from - mh-narrow-to-subject-thread. - (mh-subject-to-sequence): Renamed from mh-subject-thread-to-sequence. - (mh-delete-subject-sequence): Renamed from mh-delete-subject-thread. - (mh-next-unseen-subject-sequence): Renamed from - mh-next-unseen-subject-thread. - (mh-toggle-subject-thread): Removed. :-( - - * mh-e.el: s/subject-thread/subject-sequence/ - (mh-thread-map): Bind mh-widen to "w". - - * mh-utils.el: s/subject-thread/subject-sequence/ - (mh-show-thread-map): Bind mh-widen to "w". - -2002-10-20 Satyaki Das - - * mh-seq.el (mh-thread-folder): This function is no longer - interactive. The mh-toggle-threads is the interactive function - that gets called by the user. Also the already computed values in - mh-first-msg-num and mh-last-msg-num are used instead of - recomputing the first and last message indices in the current - folder. - (mh-toggle-threads): New interactive function that toggles - threaded view of the folder. - - * mh-utils.el (mh-letter-toggle-threads): New interactive function - which toggles thread view from show buffer. This function replaces - mh-letter-thread-folder. - (mh-show-folder-map): Use mh-letter-toggle-threads instead of - mh-letter-thread-folder. - - * mh-e.el (mh-folder-map): Use mh-toggle-threads instead of - mh-thread-folder. - -2002-10-20 Bill Wohler - - * mh-e.el (mh-scan-folder): Formatting only. - (mh-goto-cur-msg): Removed call to mh-last-msg in those cases - where there isn't a current message. Since I've started using the - speedbar to read my mh-e mail, I've had to use M-< every time to - go to the beginning of the new messages. Very annoying! Thus, if - there isn't a current message, the cursor is left alone, which - sounds like the right thing to do anyway. - -2002-10-19 Peter S Galbraith - - * mh-seq.el (mh-subject-thread-to-sequence): Bug fix. After - making the 'subject sequence real, I now have to delete it globally. - - * mh-seq.el (mh-toggle-subject-thread): Make toggle back to full - scan exactly mh-widen (removed moving to current message). - - * mh-seq.el (mh-subject-thread-to-sequence): Make 'subject - sequence a real one, exported to MH. This means you can, for - example, mh-forward it. But it also shows up with a mark in the - scan output. (Closes SF #489445). - -2002-10-19 Bill Wohler - - * mh-speed.el (mh-speed-view): If there weren't any unseen - messages, and you specified a string (a sequence like "last") when - prompted for the number of messages to display, you got an error. - This has been fixed. - -2002-10-19 Mark D. Baushke - - * mh-e.el (mh-last-destination-folder): Destination of last refile - command. - (mh-last-destination-write): Destination of last write command. - (mh-refile-msg): Use 'mh-last-destination-folder and update both it - and 'mh-last-destination. - (mh-write-msg-to-file): Use 'mh-last-destination-write and update - both it and 'mh-last-destination (Closes SF #580772). - -2002-10-19 Bill Wohler - - * mh-comp.el (mh-yank-from-start-of-msg): Changed default to - 'attribution. - (mh-letter-mode-map): Removed commented-out keybindings as well as - alias "C-c C-m a (mh-compose-insertion)." Prefer "C-c C-m i." - - * mh-utils.el: Removed autoload of help. It no longer appears to - be necessary in cvs Emacs (21.4). - -2002-10-18 Bill Wohler - - * mh-e.el (mh-execute-commands): Doc fix. - (mh-compat-write-file-hook): Renamed to - mh-write-file-functions-compat. - (mh-folder-mode): Add mh-write-file-functions-compat instead of - mh-compat-write-file-hook - -2002-10-18 Peter S Galbraith - - * mh-utils.el (mh-invisible-headers-show-xface): Killed this - variable. - (mh-invisible-headers): Use 'mh-show-use-xface instead of - 'mh-invisible-headers-show-xface to determine whether to render - the X-Face header line visible or not. - -2002-10-18 Satyaki Das - - * mh-e.el (mh-compat-write-file-hook, mh-folder-mode): Use the new - macro mh-compat-write-file-hook to use write-file-functions for - Emacs 21.4 and local-write-file-hooks for older versions. - -2002-10-18 Mark D. Baushke - - * mh-utils.el (mh-invisible-headers): Add more anti-spam headers. - -2002-10-18 Peter S Galbraith - - * mh-mime.el (mh-mml-forward-message): mml-attach-file constructs - a malformed composition if the description string is empty, so - test for that and call mml-attach-file without that argument if - it's an empty string (closes SF #625168). - -2002-10-17 Satyaki Das - - * mh-index.el (mh-index-keymap): Removed extra binding of " ". - (mh-index-folder-mode-help-messages): Made the cheat sheet entry - of quit like the others. - (mh-index-search): If space was pressed in the index buffer before - a search result has been shown with ".", the old show buffer would - be scrolled. This is confusing since the index and show buffer - contents are contradictory. Killing the show buffer here avoids - this problem. - (mh-index-configure-windows): Refine the window configuration - logic. Avoid the two window view unless there is a message being - displayed in the show buffer. - (mh-index-scroll-up): Rewrite this function. The old version had a - bizarre problem where the show buffer wouldn't be scrolled if the - speedbar was present. - (mh-index-scroll-down): Rewritten because of similar reason as - above. - -2002-10-17 Peter S Galbraith - - * mh-comp.el (mh-reply): Add an undo boundary in the undo list - before calling 'mh-yank-cur-msg (closes SF #623693). - -2002-10-17 Satyaki Das - - * mh-e.el (mh-folder-mode): Use local-write-file-hooks instead of - write-file-hooks. This is required for XEmacs and also the right - thing according to GNU Emacs21 documentation. - -2002-10-16 Satyaki Das - - * mh-seq.el (mh-thread-generate): Get threading to work correctly - on partial folders. The fix here disregards messages that aren't - already present in the buffer. - (mh-thread-folder): When querying scan about thread info try to - avoid asking about messages that aren't present in the folder - buffer. A more efficient fix would be to ask scan about just the - messages that are present instead of a range of messages. However - that runs the risk of sending long command lines to scan. Another - change was to populate the mh-scan-line-map early so that the - change in mh-thread-generate would work. - (mh-thread-generate-scan-lines): In case duplicates are present - make one of them the pseudo parent of the rest. This makes it look - prettier if there are multiple duplicates at top level. - - * mh-comp.el (mh-edit-again): If a buffer in show-mode is being - reused then reinsert message file. This should fix SF #624283. - - * mh-mime.el (mh-mm-display-part): Make sure mh-display-part is - always called when we want to remove the displayed MIME part. - -2002-10-16 Bill Wohler - - * mh-speed.el (mh-speed-folder-size): checkdoc fix. - (mh-speed-view): Tweaked output to mirror gnus verbiage. Offer - to view number of messages in folder rather than mh-large-folder. - Replaced (intern mh-unseen-seq) with mh-unseen-seq since the - former was generating errors. - -2002-10-15 Satyaki Das - - * mh-speed.el (mh-large-folder): New customizable variable to - control mh-e's perception of large folders. - (mh-speed-folder-size): New function which computes the size of - folder on current line. - (mh-speed-view): Modified to handle large folders. If the folder - being clicked has unseen messages then only those messages are - shown. Otherwise if number of messages in folder is larger than - mh-large-folders then the user is asked for the number of messages - to be shown. If the folder satisfies neither of the above cases - then it is displayed in its entirety - -2002-10-15 Bill Wohler - - * mh-index.el (mh-index-keymap): Use gnus-define-keys. Sorted. - Noticed that there were two key bindings for SPACE... - - * mh-speed.el (mh-folder-speedbar-key-map): Ditto (except for the - dup SPACE binding). - - Completed help in other modes: - - * mh-utils.el (mh-xemacs-p): Fixed doc. - (mh-show-mode-map, mh-show-folder-map, mh-show-sequence-map) - (mh-show-thread-map, mh-show-extract-map): Added binding for - mh-help. - - * mh-pick.el (mh-search-folder): Added startup help message. - (mh-pick-mode-help-messages): New variable that contains help - messages for pick buffer. - (mh-pick-mode): Set local buffer variable mh-help-messages to - mh-pick-mode-help-messages. - - * mh-index.el (mh-index-keymap): Added binding for mh-help. - (mh-index-folder-mode-help-messages): New variable that contains - help messages for MH Index buffer. - (mh-index-folder-mode): Set local buffer variable mh-help-messages - to mh-index-mode-help-messages. - - * mh-funcs.el (mh-help, mh-prefix-help): Call - substitute-command-keys on the help messages. - - * mh-e.el (mh-help-messages): Added ,. Ran C-M-q. - (mh-help): This autoload doc is now used for more than just the - MH-Folder, so drop that specific text. - - * mh-comp.el (mh-edit-again, mh-extract-rejected-mail) - (mh-forward, mh-reply, mh-send-sub): Call mh-letter-mode-message - to display a help message at startup. - (mh-letter-mode): Set local buffer variable mh-help-messages to - mh-letter-mode-help-messages. - (mh-letter-mode-help-messages): New variable with help messages - for the MH-Letter buffer. - (mh-letter-mode-message): New function that displays a startup - help message. - (mh-letter-mode-map): Added binding for mh-help. Sorted. - -2002-10-15 Satyaki Das - - * mh-speed.el (mh-speedbar-selected-folder-with-unseen-messages-face) - (mh-speedbar-folder-face, mh-speedbar-selected-folder-face) - (mh-speedbar-folder-with-unseen-messages-face): New faces for mh-e - speedbar. - (mh-folder-speedbar-buttons, mh-speed-update-current-folder) - (mh-speed-add-buttons): Use the new faces. - (mh-speed-normal-face, mh-speed-bold-face): Functions to convert - to bold face and back to normal face. - (mh-speed-set-face): Removed. - (mh-speed-highlight): Modified to allow it to be used instead of - mh-speed-set-face. Also changes were made to fontify folders with - unread messages. - (mh-speed-parse-flists-output, mh-speed-parse-flists-output) - (mh-speed-invalidate-map): Use mh-speed-highlight instead of - mh-speed-set-face. - -2002-10-15 Bill Wohler - - * mh-mime.el, mh-seq.el, mh-speed.el, mh-utils.el: It appears that - the cl package has been restructured in 21.4 in such a way that - the use of eval-when-compile no longer suppresses warnings when - compiling so that (require 'cl) must be called directly (maybe - this is a bug in 21.4 ;-). Thus the autoloads of cl are no longer - needed. Now compiles clean under 21.4. - - * mh-e.el (mh-folder-mode): The use of local-write-file-hooks is - deprecated in Emacs 21.4, so use add-hook write-file-functions (or - write-file-hook for older versions) with the LOCAL argument - instead. Now compiles clean under 21.4. - - * mh-comp.el (mh-yank-cur-msg): Push a mark at the opposite end of - the included text to make it easy to jump or delete to the other - end of the included text. - -2002-10-15 Satyaki Das - - * mh-comp.el (mh-insert-prefix-string): Remove the erroneous use - of set-mark and other related functions. - -2002-10-14 Bill Wohler - - * mh-comp.el (mh-yank-from-start-of-msg): Fixed documentation. It - isn't ignored if there is a region. It is still used for the - attribution. - (mh-yank-cur-msg): Removed unnecessary push-mark when snarfing the - entire message. Move the cursor to the end of the snarfed message - if there is a region. In this case, push a mark so user can pop to - the beginning of the snarfed fragment. - (mh-insert-prefix-string): This calls set-mark which I find - suspect since I found that my last user mark was deleted after - yanking a message. Added a comment to this effect. Will probably - add a bug report... - - * README (Installed, Supported versions): To appear in GNU Emacs - 21.3; supported on Emacs 21, 20.7 and XEmacs 21. - - * mh-funcs.el (mh-concat-list): Deleted. Use mapconcat instead. - (mh-help, mh-prefix-help): Use mapconcat instead of mh-concat-list. - (mh-ephem-message): Use "%s" in message. - - * mh-funcs.el (mh-concat-list): New function to concatenate a list - of strings into a single string. I would have thought elisp - already contained a function like this, but I couldn't find it. - (mh-ephem-message): New function to display a message in the - minibuffer ephemerally. minibuffer-message seemed like the right - function, but it writes to the current buffer oddly enough. - (mh-help, mh-prefix-help): New functions to display command - cheat sheets in the minibuffer (closes SF #493740). It would be - nice to refactor these two into a single function if possible. - - * mh-e.el (mh-folder-mode-map, mh-folder-map, mh-sequence-map) - (mh-thread-map, mh-extract-map): Added ? keybinding for `mh-help' - and `mh-prefix-help' (closes SF #493740). - (mh-help-messages): New variable to hold various help messages. - (mh-help, mh-prefix-help): Autoload from mh-funcs.el. - -2002-10-13 Bill Wohler - - * mh-index.el (mh-glimpse-directory, mh-swish-directory, - mh-namazu-directory): New variables that hold the name of the - configuration and indexing directory. All are now hidden `.' - directories. - - * mh-e.el, mh-funcs.el, mh-index.el, mh-mime.el, mh-pick.el, - mh-seq.el, mh-xemacs-compat.el (Docstrings): Converted comments to - docstrings, reworded some docstrings to conform to Emacs - documentation conventions, and eliminated all checkdoc warnings - (except for -flag, which we'll fix after 6.2 is released). - -2002-10-13 Satyaki Das - - * mh-index.el (mh-swish-next-result): Fix a bug in a corner case - where the lack of a trailing "/" caused the function to wrongly - filter out correct hits. This should fix SF #622679. - -2002-10-12 Steve Youngs - - * mh-utils.el (mh-xemacs-p): Simplify it, don't test for - 'defvaralias' and don't use 'running-xemacs'. - -2002-10-11 Bill Wohler - - * mh-comp.el: (Docstrings): Eliminated all checkdoc warnings by - converting comments to docstrings and rewording some docstrings to - conform to Emacs documentation conventions. - -2002-10-11 Steve Youngs - - * mh-utils.el (mh-xemacs-p): New. - (mh-show-use-xface): Use it. - (mh-show-xface-function): Ditto. - - * mh-e.el (toplevel): Ditto. - (mh-remove-xemacs-horizontal-scrollbar): Ditto. - (mh-folder-mode-map): Ditto. - - * mh-comp.el (mh-insert-x-mailer): Ditto. - - * mh-mime.el (gnus-local-map-property): Ditto. - (mh-mml-to-mime): Move (require 'mh-utils) to toplevel. - (mh-prompt-for-folder): Autoloading this not needed because - mh-utils is now required at toplevel. - (mh-show-xface): Ditto. - (mh-show-addr): Ditto. - -2002-10-11 Bill Wohler - - * Makefile (EMACS_HOME): Set default to $(TOP)/../emacs so it - would be useful. - - * mh-utils.el (mh-invisible-headers): Added various spam header - fields. - (mh-path-search): Removed argument `func-p' and related code. It - was not documented and no one used it. - (Docstrings): Converted comments to docstrings, reworded some - docstrings to conform to Emacs documentation conventions, and - basically eliminated all checkdoc warnings (except for -flag - warnings). - -2002-10-11 Satyaki Das - - * mh-seq.el (mh-thread-generate): Kill dead code. - -2002-10-10 Satyaki Das - - * mh-seq.el (mh-region-to-sequence): Don't include point-max in - region (closes SF #621632). - - * mh-utils.el (mh-defun-show-buffer): Fix call of - frame-first-window to work with XEmacs. Also avoid warning about - cur-buffe-name in XEmacs. - (mh-modify, mh-goto-msg): Remove dead code. - - * mh-speed.el (mh-speed-toggle, mh-speed-add-buttons): Remove dead - code. - - * mh-seq.el (mh-subject-thread-to-sequence, mh-thread-get-message, - mh-thread-generate, mh-thread-folder): Remove dead code. - - * mh-mime.el (mh-mm-inline-message): Remove dead code. - - * mh-index.el (mh-index-search): Remove dead code. - - * mh-comp.el (mh-open-line): Remove dead code. - - * mh-e.el (mh-folder-mode): Use the macro - mh-remove-xemacs-horizontal-scrollbar to avoid compiler-warning in - Emacs. - (mh-remove-xemacs-horizontal-scrollbar): New macro to avoid - compiler-warnings. - -2002-10-10 Mark D. Baushke - - * Makefile (EMACS_OPTIONS): New macro for command-line compile - options. - (EMACS): Allow the user to specify which emacs command to use for - the compile. - (COMPILE_COMMAND): Combine the compile command with its options. - (.el.elc): Use the new $(COMPILE_COMMAND). - -2002-10-10 Mark D. Baushke - - * mh-speed.el (mh-speed-select-attached-frame): Define a new - compatibility macro for getting to the attached-frame. - (mh-speed-update-current-folder): Use it. - -2002-10-10 Mark D. Baushke - - * mh-speed.el (mh-speed-update-current-folder): Use - 'dframe-select-attached-frame if we are in a newer speedbar - version that no longer supports the 'speedbar-attached-frame - variable. - -2002-10-10 Steve Youngs - - * mh-speed.el (mh-speed-update-current-folder): Use - 'dframe-select-attached-frame' if we're in XEmacs. - - * mh-e.el (mh-folder-mode): Remove the horizontal scrollbar from - the MH-Folder buffer if we're in XEmacs. - -2002-10-09 Satyaki Das - - * mh-utils.el (mh-show-xface-function): New global that stores - what function needs to be called to display X-Face. - (mh-show-xface): Rewritten to avoid compiler warning. - -2002-10-09 Peter S Galbraith - - * mh-utils.el (mh-exchange-point-and-mark-preserving-active-mark): - Simplify code for all emacsen to avoid byte-compilation warnings. - -2002-10-09 Satyaki Das - - * mh-mime.el (mh-mm-display-part): If a sub-part of the current - part is an inline image then clicking the button keeps the image - around. The change fixes this bug. - -2002-10-09 Peter S Galbraith - - * mh-utils.el (mh-exec-cmd-output): Use new function - 'mh-exchange-point-and-mark-preserving-active-mark instead of - 'exchange-point-and-mark. Fixes a bug in emacs20 and XEmacs21. - (mh-exchange-point-and-mark-preserving-active-mark): New function. - Does like 'exchange-point-and-mark but doesn't activate the mark. - - * mh-comp.el (mh-letter-menu): Allow access to "Pull in All - Compositions" menu entries when edits have really occurred. - Works with "forw: -mime" mh_profile entry, so this fixes a bug. - - * mh-mime.el (mh-mime-inline-part, mh-mm-display-part): Use - line-beginning-position and line-end-position instead of - point-at-bol and point-at-eol XEmacs functions. - * mh-xemacs-compat.el: Added line-end-position and - line-beginning-position compatibility aliases. - -2002-10-08 Mark D. Baushke - - * mh-utils.el (mh-scan-msg-format-regexp): The regexp to find - %number(msg). - (mh-scan-msg-format-string): Format to be used with the current - maximum width of message number for the folder in the - `mh-update-scan-format' function. - (mh-update-scan-format): Use `mh-scan-msg-format-regexp' for greater - flexibility. The message number is no longer anchored to the - beginning of the `mh-scan-format-nmh' or `mh-scan-format-mh' format - strings. The `mh-update-scan-format' allows for using zero-filled - message numbers. - -2002-10-08 Peter S Galbraith - - * mh-e.el (mh-folder-folder-menu): Add entry for "Thread Folder". - -2002-10-07 Satyaki Das - - * mh-seq.el (mh-thread-generate): Use mh-progs to get path to mh - executables. - - * mh-speed.el (mh-speed-flists): Use mh-progs to get path to mh - executables right. - (mh-speed-folders-actual): Same as above. - -2002-10-05 Steve Youngs - - * mh-comp.el (mh-yank-from-start-of-msg): Make default setting 't' - a const. - - * mh-xemacs-compat.el (match-string-no-properties): Rewrite as a - defsubst using 'buffer-substring-no-properties' so we don't grab - any extents. - (rfc822-goto-eoh): Removed. This exists in the XEmacs mail-lib - package. - (mail-header-end): Ditto. - (mail-mode-fill-paragraph): Ditto. - -2002-10-05 Satyaki Das - - * mh-speed.el (mh-speed-invalidate-map): When called interactively - the function will clear mh-speed-folders-cache. - -2002-10-02 Satyaki Das - - * mh-mime.el (mh-insert-mime-button): Rewrite without using - replace-match. - -2002-10-01 Satyaki Das - - * mh-mime.el (mh-file-mime-type-substitutions): Reorder code to - avoid compiler warning. - -2002-10-01 Bill Wohler - - * Makefile (MH-E-ETC): Moved ChangeLog into MH-E-ETC-ETC since it - shouldn't get installed in Emacs. - (install-emacs): Install MH-E-IMG into Emacs' lisp/toolbar and - MH-E-IMG2 into Emacs' lisp/mail. - -2002-10-01 Peter S Galbraith - - * mh-e.el (mh-tool-bar-reply-3-buttons): New customization. - 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. - (mh-folder-tool-bar-map): Use mh-tool-bar-reply-3-buttons to - decide how many buttons to use for replying. - - * mh-mime.el (mh-file-mime-type-substitutions) - (mh-file-mime-type-substitute): Fix typos and doc strings. - -2002-09-30 Peter S Galbraith - - * mh-mime.el (mh-file-mime-type): Run Content-Type string returned - by file command through mh-file-mime-type-substitute (see below). - (mh-file-mime-type-substitute): Possibly change Content-Type - string using mh-file-mime-type-substitutions variable. This is - mostly because all MS-Office file are seen as application/msword - by the file command. - (mh-file-mime-type-substitutions): New variable. Defines - substitutions to make for Content-Type returned from file command. - -2002-09-27 Bill Wohler - - * README: Moved Id to end of file since it broke outline mode at - the beginning. - - * import-emacs (release): Renamed "mainline" tag to - "emacs-mainline" to correspond with existing CVS tag. - (EMACS_HOME): Fixed typo in docstring. - - * mh-utils.el (mh-folder-name-p, mh-defun-show-buffer): Lowercase - NIL and T in docstring. - (mh-update-scan-format): Fixed typo. - - * mh-comp.el, mh-e.el, mh-pick.el, mh-utils.el: Updated from CVS - Emacs. The only new thing appears to be to downcase NIL and T in - the documentation. - -2002-09-26 Satyaki Das - - * mh-seq.el (mh-thread-generate): The threading code will now be - more resistant to corruption of messages. Before the change any - corruption of message x would cause all messages with indices - higher than x to be neglected when threading! - -2002-09-23 Peter S Galbraith - - * mh-mime.el (mh-store-mime-parts): Don't store value into - user-customizable variable mh-store-mime-parts-default-directory - and use mh-store-mime-parts-directory instead. - -2002-09-20 Satyaki Das - - * mh-seq.el (mh-thread-prune-subject): Use regular expressions to - make the subject pruning behave the way it is specified in the - imap-thread RFC. - - * mh-speed.el (mh-speed-folders-actual): Don't use pop when we - are not going to use the first element. This avoids a compilation - warning with cvs emacs. - -2002-09-19 Satyaki Das - - * mh-utils.el (mh-display-msg): Put the call to - set-buffer-modified after mh-show-mode. This is needed for CVS - emacs since calling mh-show-mode marks the buffer as modified if - font-lock is on. - -2002-09-17 Peter S Galbraith - - * mh-mime.el (mh-store-mime-parts-default-directory): Renamed from - mh-store-mime-parts-directory. - (mh-store-mime-parts-directory): Renamed from - mh-store-mime-parts-directory-default. - -2002-09-16 Peter S Galbraith - - * mh-comp.el (mail-citation-hook): Doc tweaks suggested by Bill. - -2002-09-08 Satyaki Das - - * mh-e.el (autoloads): Reorder autoload of mh-reply to avoid - compiler warning. - -2002-09-03 Peter S Galbraith - - * mh-mime.el (mh-store-mime-parts-directory): New defcustom. - Default directory to use for mh-store-mime-parts. - (mh-store-mime-parts): New Command. Store the MIME parts of the - current message. - (mh-store-mime-parts-directory-default): New internal working - variable. Default to use for mh-store-mime-parts-directory, set - from last use. - - * mh-e.el (mh-folder-seq-tool-bar-map): Add mh-store-mime-parts to - toolbar. - -2002-08-22 Satyaki Das - - * mh-seq.el (mh-thread-generate-scan-lines): In threaded view, - complete scan lines are printed for all messages (not just the - ones at the top of a thread). - - * mh-index.el (mh-index-insert-scan): Replace use of kill-line - since that pollutes the kill-ring. - - * mh-comp.el (autoloads): Add autoloads for search and subseq to - get rid of compiler warnings. - -2002-08-19 Peter S Galbraith - - * reply-to.xpm, reply-to.pbm, reply-from.xpm, reply-from.pbm, - * reply-all.xpm, reply-all.pbm: New icons for various reply methods. - * mh-e.el (mh-folder-tool-bar-map): Split reply button into three - that won't prompt for "from", "to" and "all". - * mh-comp.el (mh-reply): Put variable reply-to in the interactive - list since it's specified on the command line for the new toolbar. - - * mh-comp.el (mail-citation-hook): Tweak docs concerning - historical usage for supercite. - (mh-yank-from-start-of-msg): Add settings 'supercite and - 'autosupercite. Rename 'automatic to 'autoattrib. - (mh-insert-prefix-string): Invoke sc-cite-original if - mh-yank-from-start-of-msg is et to 'supercite or 'autosupercite. - -2002-08-17 Satyaki Das - - * mh-comp.el (compilation-fix): Reorder defvars to avoid warnings - during compilation. - -2002-08-17 Peter S Galbraith - - * mh-comp.el (mh-yank-from-start-of-msg): Add 'automatic choice. - Do as for `attribution' automatically when show buffer matches the - message being replied-to. - (mh-reply): Call 'mh-yank-cur-msg when mh-yank-from-start-of-msg - is set to 'automatic and show buffer matches message number being - replied-to. - (mh-show-buffer-message-number): New helper function to get the - message number of the current show-buffer. - (mh-yank-cur-msg): Handle 'automatic choice the same as 'attribution. - (mh-yank-cur-msg): Bug fix. It would bail on error if - mh-show-buffer didn't exists. - -2002-08-16 Peter S Galbraith - - * mh-comp.el (mh-insert-x-mailer): It wrongly assumed that Emacs - was used even when XEmacs was used. Fixed so X-Mailer header is - more exact about what we are using. - -2002-08-15 Peter S Galbraith - - * mh-e.el (mh-version): Change CVS version number to 6.1+cvs just - so X-Mailer header is more exact about what we are using. - - * mh-mime.el (mh-mhn-compose-insertion, mh-mhn-compose-anon-ftp, - mh-mml-attach-file): - "Jeffrey P. Morgenthaler" reported - that "require" in emacs 20.3 doesn't handle 3 arguments. We - use "load" at the top of file elsewhere anyway to handle such a - case of non-essential loading, so switch to that here. - -2002-08-06 Satyaki Das - - * mh-funcs.el (autoload): Add autoload for mh-speed-invalidate-map. - - * mh-speed.el (mh-speed-add-folder): New function to make the - speedbar aware of new folders when they are created by mh-e. - - * mh-utils.el (mh-prompt-for-folder): Use mh-speed-add-folder to - tell speedbar that new folder is being created. Also use folder - instead of mkdir to create new folders. - -2002-08-01 Peter S Galbraith - - * mh-utils.el (mh-decode-quoted-printable): Conditionalize the - limit of search for quoted-printable. If we're using mm-decode - for MIME decoding, it's possible that `mimedecode' could mess our - message, so we only run a full search for quoted-printable parts - when not using gnus' mm-decode. When using mm-decode, mimedecode - can still help by handling the case of the whole message being - quoted-printable as opposed to only a part. - -2002-07-31 Peter S Galbraith - - * mh-comp.el (mh-compose-insertion): Moved from mh-mime.el because - the pulldown menu were broken in XEmacs21 from this variable being - undefined. - -2002-07-28 Mark D. Baushke - - * mh-utils.el (mh-show-mode): Use the default paragraph-start - rather than the inherited text-mode value. - -2002-07-28 Satyaki Das - - * mh-seq.el (mh-thread-duplicates): New hash table to track - duplicate messages. - (mh-thread-get-message): Remove debug code. - (mh-thread-canonicalize-id): Modified to handle messages without - message-id header. Such messages are given distinct copies of the - empty string as message-id. - (mh-thread-generate): The function was inadvertently rebuilding - the thread tree when message refiles and message deletes are - processed. The change here fixes that. Also code has been added to - keep track of duplicate message-id's. - (mh-thread-generate-scan-lines): Modified to print scan lines for - duplicate messages (that is messages with the same message-id). - (mh-thread-forget-message): Modified to maintain - mh-thread-duplicates. - -2002-07-22 Satyaki Das - - * mh-speed.el (mh-speed-parse-flists-output): Use delete-region - instead of kill-region. Otherwise the kill ring gets polluted. - -2002-07-16 Satyaki Das - - * mh-seq.el (mh-thread-update-scan-line-map): New function to - refresh the stale scan lines. - (mh-thread-inc): Update old scan lines when mh-thread-inc is - called. Otherwise notations for deleted and refiled messages get - lost and the folder display gets out of sync with real mh-e state. - - * mh-mime.el (mh-mm-display-part): Call Gnus citation highlight - code when text part is displayed. Otherwise buttonized text parts - aren't correctly fontified when they are displayed. - -2002-07-15 Mark D. Baushke - - * mh-utils.el (mm-decode): Use load for the Non-fatal dependency - on the mm-decode library. - * mh-mime.el (mm-decode, mm-uu, mm-view): Use load for the - Non-fatal dependencies on the mm-decode, mm-uu and mm-view - libraries. - -2002-07-15 Satyaki Das - - * mh-utils.el (mh-require, mh-autoload): Remove these macros. - (mh-decode-mime): Initialized to t iff the mm-decode library is - present in the load-path. - * mh-mime.el (mh-require): Don't use it anymore. - -2002-07-15 Mark D. Baushke - - * mh-utils.el (mh-update-scan-format): Rewrite for compatibility - with XEmacs as replace-match appears not to have identical - functionality with GNU Emacs. - (mh-scan-msg-format-regexp): Deleted. This regexp is now hardcoded - into the mh-update-scan-format function. - -2002-07-12 Satyaki Das - - * mh-seq.el: Add message threading code. - - * mh-utils.el (mh-letter-thread-folder): New interactive function - that allows switching to threaded view from show buffer. - (mh-show-folder-map): Bound "F t" to call mh-letter-thread-folder. - (mh-goto-msg): Replace the function to not assume that messages - are sorted in the folder buffer. - - * mh-e.el (mh-folder-threaded-view-p): New buffer local variable - in the folder buffer that records whether threaded view is being - used currently. - (mh-scan-subject-regexp, mh-scan-format-regexp): Get font lock - working for threaded view as well. - (mh-regenerate-headers): Reset mh-folder-threaded-view-p to nil. - (mh-get-new-mail, mh-process-commands): Do incremental threading - if folder is in threaded view. - (mh-delete-scan-msgs): Update thread tables if folder is in - threaded view. - (mh-folder-map): Add "F t" as key binding for mh-thread-folder - - * mh-comp.el (mh-yank-cur-msg): Bug fix. mh-show-buffer is only - has a meaningful value in the folder buffer. - -2002-07-11 Peter S Galbraith - - * mh-comp.el (mh-yank-cur-msg): Run only if mh-show-buffer - actually exists (otherwise a back-traceable error occurred). - - * mh-utils.el (mh-find-progs): Run PATH search only when mh-progs, - mh-lib and mh-lib-progs are not all already set. This allows the - user to set them using a simple setq prior to loading mh-e. This - is useful for implementation of mh-e on w32. Note that many - commands still call mh-find-path which also parses the mh_profile - file (that may still fail on w32), so this is still done often. - But it lets us change the mh_profile file and have mh-e see the - changed file without exiting emacs and starting over so I left - that in. - -2002-07-04 Satyaki Das - - * mh-index.el (mh-index-show): Fixed a bug in mh-index-show which - caused it to lose track of point when called from show buffer. - -2002-07-04 Mark D. Baushke - - * Makefile: Add more information and common methods to allow both - GNU make and Berkeley make to properly build everything. - -2002-07-04 Satyaki Das - - * mh-mime.el (mh-push-button): Bug fix for mime display with - mouse. Select show window before executing the mime display - functions. - -2002-07-01 Mark D. Baushke - - * Makefile: Use a conditional variable assignment operator rather - than ifndef to let Makefile be used by both GNU make and Berkeley - make (or similar versions of make). This does not help Solaris - /usr/ccs/bin/make, but Solaris make has problems with the ifndef - syntax too. - -2002-07-01 Satyaki Das - - * mh-index.el (mh-index-search): Check for mh-decode-mime before - adding mh-mime-cleanup to kill-buffer-hook. - - * mh-mime.el (mm-destroy-parts): Add definition for old emacs. - -2002-06-30 Mark D. Baushke - - * mh-utils.el (mh-update-scan-format): Add documentation string. - (mh-scan-msg-format-regexp): Update the regexp to find %(msg). - (mh-set-cmd-note): When mh-scan-format-file is not t, dynamic - update of mh-cmd-note is wrong. Do not assume that - mh-scan-format-nmh and mh-scan-format-mh can be kept in lock-step - with mh-cmd-note via mh-set-cmd-note. The mh-scan-format function - is now where the updated mh-cmd-note value is put into the scan - format. - - * mh-e.el (mh-generate-new-cmd-note): Add documentation string. - (mh-scan-format): Use mh-update-scan-format to get updated copies - of mh-scan-format-nmh and mh-scan-format-mh to avoid format skew. - (mh-get-new-mail): Do not try to adapt mh-cmd-note unless - mh-scan-format-file is equal to t. - (mh-scan-format-nmh): No longer buffer local. - (mh-scan-format-mh): No longer buffer local. - -2002-06-30 Satyaki Das - - * mh-index.el (mh-index-max-msg-index): New variable to keep track - of max message index among search results. If mh-adaptive-cmd-note - is non-nil this is used to compute the width of the index field. - (mh-index-search): Keep track of max index seen while parsing the - search results and set it if mh-adaptive-cmd-note is non-nil. - (mh-index-find-max-width): New function to find the required width - of the message index field. - (mh-defun-index): Binding buffer local variables is bad, so don't - do that. - (mh-index-show): New argument display-headers-p decides whether - the message is displayed in raw form or not. - (mh-index-header-display): New interactive function bound to "," - which shows the message in raw form. - (mh-index-keymap): Add appropriate bindings for backtab and ",". - (read-from-string): Add ignore-errors around it so that the code - doesn't die when it gets unexpected input. - -2002-06-29 Satyaki Das - - * mh-index.el (mh-count-windows): This function works around the - lack of the window-list builtin function in emacs20. - -2002-06-29 Mark D. Baushke - - * mh-utils.el (mh-message-number-width): New function to scan - the last message of a folder and return its width. - (mh-adaptive-cmd-note): New variable, if Non-nil indicates that - mh-set-cmd-note should be called with the message width for the - folder. - (mh-cmd-note): Update documentation. - (mh-update-scan-format): Helper function for updating the - mh-scan-format-nmh and mh-scan-format-mh variables. - (mh-scan-msg-overflow-regexp): New variable to help find problem - messages after an inc. - (mh-scan-msg-format-regexp): New variable to find the old message - width in one of the mh-scan-format-nmh or mh-scan-format-mh - variables. - (mh-set-default-cmd-note): Replaced by mh-set-cmd-note. - (mh-set-cmd-note): New function to replace update mh-cmd-note - value. - - * mh-e.el (mh-regenerate-headers): If mh-adaptive-cmd-note is - non-nil, use mh-set-cmd-note on empty folder buffers. - (mh-make-folder): Ditto. - (mh-generate-new-cmd-note): New function to adapt the mh-cmd-note - to fit when mh-get-new-mail gets message number truncation. - (mh-get-new-mail): Maybe use mh-generate-new-cmd-note if - mh-adaptive-cmd-note is Non-nil. - -2002-06-29 Satyaki Das - - * mh-speed.el (mh-speed-view): The display gets confused if the - cursor is in the show buffer when mh-speed-view is called. This is - a fix for that. - -2002-06-27 Satyaki Das - - * mh-e.el (mh-next-undeleted-msg): Get rid of optional arg - reverse-p. If there are no more undeleted messages the point - remains at its original position and a message is produced (closes - SF #494304). - (mh-previous-undeleted-msg): Change similar to - mh-next-undeleted-msg. - (mh-next-msg, mh-refile-msg, mh-delete-msg): Backout previous - change. - (mh-folder-map): Bind "S-tab" and "K S-tab" to mh-prev-button. - - * mh-utils.el (mh-show-mode-map): Bind "S-tab" and "K S-tab" to - mh-letter-prev-button. - - * mh-mime.el (gnus-newsgroup-name): Initialize it to nil, so that - mm-uu-dissect doesn't cause error. - -2002-06-27 Mark D. Baushke - - * mh-utils.el (mh-cmd-note): Make buffer-local. Changes to this - variable should be made via the new mh-set-default-cmd-note - function. - (mh-set-default-cmd-note): New function to setq-default the - mh-cmd-note, mh-scan-format-mh and mh-scan-format-nmh values to - related values. - - * mh-e.el (mh-scan-format-mh): Make buffer-local. - (mh-scan-format-nmh): Ditto. - (mh-scan-good-msg-regexp): Use a more general regular expression - so that the width of message numbers, mh-cmd-note, may vary. - (mh-scan-deleted-msg-regexp): Ditto. - (mh-scan-refiled-msg-regexp): Ditto. - (mh-scan-cur-msg-number-regexp): Ditto. - (mh-scan-cur-msg-regexp): Ditto. - (mh-scan-subject-regexp): Ditto. - -2002-06-26 Satyaki Das - - * mh-speed.el: Speedbar support code. - - * Makefile: Add mh-speed.el to MH-E-SRC. - - * mh-utils.el (mh-prompt-for-folder): Add speedbar hook if - speedbar is being used. - - * mh-funcs.el (mh-kill-folder): Add speedbar hook if speedbar is - being used. - - * mh-e.el (speedbar-autoloads): Autoload speedbar initialization - functions so that speedbar can find them. - -2002-06-25 Satyaki Das - - * mh-index.el (mh-grep-execute-search, mh-grep-next-result): Allow - grep to be used to search mail. - (mh-index-font-lock-keywords): Modified to avoid bug when using - lazy font-lock. - - * mh-e.el (mh-delete-msg, mh-refile-msg): Modify so that if no - undeleted (or unrefiled) message exists in the current movement - direction then try to find an undeleted (or unrefiled) message in - the opposite direction instead. - (mh-next-undeleted-msg): Added a new optional argument. If non-nil - search for undeleted message backwards if none exists in the - forward direction. - (mh-previous-undeleted-msg): Added an optional argument. If - non-nil search for undeleted message in the forward direction if - none exists in the backward direction. - (mh-next-msg): Optional argument to change direction if undeleted - messages are not found in the current direction. - - * mh-index.el (mh-cmd-note): Use mh-cmd-note instead of hardcoding - the index field size to 4. - - * mh-utils.el (mh-show-addr, mh-show-xface): New functions added - to do xface display and goto-addr interface to allow reuse by the - mime display code. - (mh-show-mode): Use mh-show-addr and mh-show-xface. Only add - mh-mime-cleanup to kill-buffer-hook if mime decoding is enabled. - (mh-modify): Use mh-letter-mode instead of mh-show-mode when - editing messages. - - * mh-mime.el (mh-mm-inline-message): Arrange for xface and - highlighting to work in forwarded messages. - -2002-06-23 Peter S Galbraith - - * mh-comp.el (mh-yank-from-start-of-msg): Add 'attribution' option - to add an attribution line in mh-yank-cur-msg. - (mh-extract-from-attribution-verb): Verb to use for attribution - when a message is yanked by mh-yank-cur-msg. Provides a method - for setting a different language. - (mh-yank-cur-msg): Add support for 'attribution' option. - (mh-extract-from-attribution): Function to get the attribution - line, or the sender from the From: line in the current show buffer. - -2002-06-20 Satyaki Das - - * mh-index.el (mh-index-show): mh-display-msg was not being called - in the show buffer. This causes weird results on some mime messages. - - * mh-mime.el (gnus-newsgroup-charset): Defvar to avoid error in - pgp messages if gnus hasn't been used yet. - - * mh-comp.el (mh-letter-mode-map): Typo fix. - -2002-06-19 Satyaki Das - - * mh-mime.el (mh-mml-secure-message-encrypt-pgpmime): Typo fix. - (compiler-warnings): Add autoloads to remove compiler warnings. - - * mh-index.el (autoload-fixes): Fix autoload forms. - -2002-06-18 Satyaki Das - - * mh-comp.el (mh-letter-mode-map): Change binding of "\C-c\C-ma" - to mh-compose-insertion. Remove duplicate binding for "C-c\C-mf". - (compiler-warnings): Add defvar to remove compiler-warning. - -2002-06-18 Peter S Galbraith - - * mh-comp.el (mh-letter-menu): Conditionalize GPG function on - mh-gnus-pgp-support-p. - - * mh-mime.el (mh-mml-forward-message): s/subseq/substring/. - (mh-compose-forward): cut&paste typo: s/messages/message/. - (mml-minibuffer-read-file): autoload added. - (mml-minibuffer-read-description): autoload added. - (mml-insert-empty-tag): autoload added. - (mh-mml-secure-message-sign-pgpmime): Check mh-gnus-pgp-support-p. - (mh-mml-secure-message-encrypt-pgpmime): Check mh-gnus-pgp-support-p. - -2002-06-17 Peter S Galbraith - - * mh-utils.el (mh-show-use-xface): Check for availability of - `uncompface' executable on system. - - * mh-mime.el (mh-compose-forward): New front end for both - mh-mml-forward-message and mh-mhn-compose-forw. - (mh-compose-insertion): New front end for both mh-mml-attach-file - and mh-mhn-compose-insertion. - (mh-mml-to-mime): New function. Compose mime message from mml - directives. - (mh-mml-forward-message): New function. Forward a message as - attachment. - (mh-mml-attach-file): New function. Attach a file to the outgoing - MIME message. - (mh-mml-compose-insert-p): New variable. Buffer-local variable to - know whether MIME insertion was done. Triggers an automatic call - to `mh-mml-to-mime' in `mh-send-letter'. - (mh-mml-secure-message-sign-pgpmime): New function. - Front end to mml-secure-message-sign-pgpmime. - (mh-mml-secure-message-encrypt-pgpmime): New function. - Front end to mml-secure-message-encrypt-pgpmime. - - * mh-comp.el (mh-send-letter): automatic call to `mh-mml-to-mime' - if mh-mml-compose-insert-p is set. - (mh-letter-mode-map): Add keys for new mh-mime functions above. - * mh-comp.el: Added autoloads for new mh-mime functions above. - -2002-06-17 Peter S Galbraith - - * mh-utils.el (mh-show-use-xface): new defcustom to determine - whether to call external package x-face to display the x-face. - (mh-invisible-headers-show-xface): variable now defaults to value - of mh-show-use-xface. - (mh-show-mode): When mh-show-use-xface is t, invoke - external package x-face to display the x-face. - -2002-06-15 Satyaki Das - - * mh-e.el (mh-prev-button): New interactive function which moves - point to the previous mime button in the show buffer. - (mh-folder-mode-map): Bind M-TAB and K M-TAB to mh-prev-button. - - * mh-utils.el (mh-show-mode-map): Bind M-TAB and K M-TAB to call - mh-letter-prev-button (which is analogous to mh-prev-button). - (mh-gnus-pgp-support-p): New global variable to replace the - variable mh-recent-gnus-p. The name better describes what it is - used for. - - * mh-mime.el (mh-mime-display-part, mh-mime-display-single): Use - mh-gnus-pgp-support-p instead of mh-recent-gnus-p. - -2002-06-12 Satyaki Das - - * mh-mime.el (mh-display-buttons-for-inline-parts): New - customizable variable. When non-nil inline parts have are - displayed with a button (that is initially expanded). - (mh-maybe-insert-newline): The function has been removed. - (mh-mime-display-single): Add code to display buttons for inline - parts. Reduce the insertion of extra newlines between inline parts - and also for pgp signature parts. - (mh-mm-display-part): The function has been rewritten and cleaned - up. There was a bug which could change the show buffer if the user - pressed C-g while a mime part was being displayed has been fixed. - (mh-press-button, mh-push-button): Use unwind-protect to make sure - that set-buffer-modified-p is always called after mime display. - (mh-mime-inline-part): The behavior of the function has been - changed so that it toggles the display of the raw bytes. - (mh-mime-display-security): Remove the display of too many - newlines. - (documentation): Remove most check-doc warnings. - - * mh-comp.el (mh-filter-out-non-text): Updated since whitespace - added around mime buttons have changed. - -2002-06-10 Satyaki Das - - * mh-index.el (mh-index-last-search, mh-index-search): The default - prompt in mh-index-search has been removed since currently there - is no good way of reading "+" with mh-prompt-for-folder. - (mh-index-folder-mode, mh-index-show-mode): New major modes - derived from mh-folder-mode and mh-show-mode respectively. They - use a restricted keymap compared to the parent modes. - (mh-index-folder-face): New customizable face to display folder - names in the index buffer. - (documentation): Change two spaces after period back to one. - -2002-06-08 Satyaki Das - - * mh-e.el (mh-folder-toggle-mime-part): New interactive function - to control mime display from folder buffer. - (mh-folder-inline-mime-part): New interactive function to inline - raw mime part from folder buffer. - (mh-folder-save-mime-part): New interactive function to save mime - part from folder buffer. - (mh-folder-mode-map): Add keybindings for "K v", "K o", "K i" and - "K \t" to mh-folder-mode-map. - (mh-goto-next-button): Modified to allow searching for next button - that satisfies some condition. - (mh-folder-mime-action): Support function for - mh-folder-save-mime-part, mh-folder-inline-mime-part and - mh-folder-toggle-mime-part. - - * mh-utils.el (mh-show-mode-map): Modify keymap to add appropriate - bindings for "K v", "K o", "K i" and "K \t". - - * mh-index.el (documentation): Fix docs according to checkdoc - format. - -2002-06-07 Satyaki Das - - * mh-seq.el, mh-funcs.el (Compiler): Remove (require 'view) and - instead add defvar for view-exit-action. - -2002-06-06 Satyaki Das - - * mh-comp.el (mh-insert-x-face): If transient-mark-mode is enabled - the call to mark returns error. So avoid using mark. - - * mh-index.el: Support for new interactive function - mh-index-search. - - * mh-e.el (mh-next-button, mh-goto-next-button): Refactor - mh-next-button so that the code may be reused by mh-index.el. - (mh-folder-map): Add key "F i" to call mh-index-search. - - * mh-utils.el (mh-recent-gnus-p): Fix documentation. - (mh-msg-folder, mh-display-msg): The new function mh-msg-folder - maps a MH folder name to the buffer displaying it. In normal - operation the two names are identical but they are different in a - folder buffer generated by index search. Minor modification to - mh-display-msg to use mh-msg-folder to enable mh-index-search to - reuse code. - (mh-show-mode-map): Add key "F i" to call mh-index-search. - - * Makefile: Add mh-index.el - -2002-06-05 Peter S Galbraith - - * mh-e.el (mh-folder-message-menu): Add an entry for mh-modify. - -2002-05-31 Satyaki Das - - * mh-utils.el (mh-decode-quoted-printable): Only decode if the - whole message is encoded. So restrict the search for the - content-transfer-encoding header to the headers of the message - itself. - - * mh-mime.el (mh-mime-display-alternative): Make sure that point - is moved after mm-display-part is called. - -2002-05-29 Satyaki Das - - * mh-mime.el (mh-mime-display-single): Fix the logic that - determines when an attachment is buttonized. For inline parts that - can't be displayed a button is now created. - -2002-05-29 Satyaki Das - - * mh-e.el (mh-regenerate-headers): Fix an error in which the - mh-mode-line-annotation was not being set properly. - - * mh-mime.el, mh-utils.el (compilation): Macros mh-require and - mh-autoload are used to make sure that emacs20 doesn't croak when - it tries to load non-existent mm-* files. - (mh-decode-mime): Make it default to nil for Emacs major version - below 21. - -2002-05-28 Satyaki Das - - * mh-e.el (mh-regenerate-headers): Generalize the function to - handle multiple ranges. - -2002-05-25 Satyaki Das - - * Makefile, mh-comp.el, mh-e.el, mh-funcs.el, mh-seq.el, mh-utils.el: - Reduce use of eval-when-compile so that load-path is - not changed if lisp files are loaded without compilation. - - * mh-e.el (mh-next-button, mh-folder-mode-map): New interactive - function to advance point to next MIME button. It is bound to TAB. - - * mh-utils.el (mh-letter-next-button, mh-show-mode-map): New - interactive function mh-letter-next-button has been added to - advance point to the next MIME button. It is bound to TAB. - - * mh-mime.el (comments): Added some comments. - -2002-05-24 Satyaki Das - - * mh-mime.el (compilation): Replace (eval-when-compile ...) by - (eval-when (compile) ...) to remove a bug when mh-e is loaded - without compilation. - -2002-05-23 Satyaki Das - - * mh-comp.el (compilation): Some code was rearranged to avoid - compiler warnings. - - * mh-e.el (compilation): Code rearrangement and extra autoloads to - remove compiler warnings. - (mh-quit): Add call to mh-destroy-postponed-handles to remove - handles that are associated with external viewers. Also fixed a - bug that I accidentally introduced by adding an extra line when - cut and pasting my changes. - - * mh-funcs.el (compilation): Code rearrangement to remove compiler - warnings. - - * mh-mime.el (compilation): Code rearrangement to remove compiler - warnings. - (mh-defun-compat): New macro to define to useful functions that - aren't present in old Gnus. - (mh-destroy-postponed-handles): New function to cleanup handles - that are associated with external viewers. - (mh-handle-set-external-undisplayer): New function to replace - mm-handle-set-external-undisplayer. It associates handles for - external viewers with the folder buffer. These are released when - the user quits the folder. - (mh-mime-display, mh-press-button, mh-push-button): Hook in - mh-handle-set-external-undisplayer. - (mh-maybe-insert-newline): New function to avoid inserting too - many newlines between mime parts. - (mh-mm-display-part): Workaround for Gnus bug which causes new - lines to be inserted when images are shown inline. - (mh-mime-display-security): Cut down on newlines inserted. - - * mh-pick.el (compilation): Code rearrangement to remove compiler - warnings. - - * mh-seq.el (compilation): Code rearrangement to remove compiler - warnings. - (comments): Remove @SD from comments. - - * mh-utils.el (compilation): Slight code rearrangement. - (mh-defun-show-buffer): Fix documentation so that the first line - is not too long as was the case earlier. Use - mh-previous-window-config to remember where the cursor should - return functions like mh-reply. - (mh-display-msg): Initialize handles data-structure for the folder - buffer so that postponed handles can be added to it. - (mh-add-msgs-to-seq): Always keep messages in the sequences - sorted. This removes some unexpected behavior when working with - sequences that go out of sync with the corresponding MH sequences. - (mh-canonicalize-sequence): New function to sort and remove - duplicates from mh-e sequence. - -2002-05-21 Satyaki Das - - * mh-utils.el (require): Load mm-decode.el here so that - mm-inline-media-tests is properly initialized. - - * mh-comp.el (mh-yank-cur-msg): Don't try to remove the displayed - mime parts when yanking the message. This also fixes the problem - of regions not being respected during the yank. - -2002-05-20 Satyaki Das - - * mh-utils.el (compiler-warnings): Some code was rearranged to - remove all compiler warnings. - (mh-decode-mime): New defcustom to control whether - mime attachments are shown using Gnus. - (mh-globals-hash): New global variable which maps a given buffer - to the corresponding mime data structures. - (mh-recent-gnus-p): New global variable which checks if Gnus is - recent enough so that PGP/GPG encrypted messages can be handled. - (mh-mm-inline-media-tests): Tests to determine whether a mime part - can be shown inline. - (mh-gnus-article-highlight-citation): Shadow the Gnus function, - gnus-article-add-button before gnus-article-highlight-citation is - called. This prevents the insertion of useless buttons in the - message. - (mh-show-mode): Don't set font-lock-support-mode to nil. Modify - kill-buffer-hook to call mh-mime-cleanup. - (mh-modify): Only the edit buffer is shown. - (mh-display-msg): Add call to mh-mime-display, mh-display-smileys, - mh-display-emphasis when mh-decode-mime is non-nil. - - * mh-mime.el (mh-buffer-data): New structure to keep track of - per-buffer mime information. - (compiler-warnings): Some code was rearranged to get rid of all - compiler warnings. - (mh-graphical-smileys-p): New defcustom which controls whether - graphical smileys are shown. - (mh-graphical-emphasis-p): New defcustom for graphical emphasis. - (mh-max-inline-image-width, mh-max-inline-image-height): New - defcustoms for inlining image. - (gnus-local-map-property, mm-merge-handles): Copy utility - functions for use with version of Gnus that ships with Emacs21.1. - (mh-mime-cleanup): New function to free mime data-structures. - (mh-add-missing-mime-version-header): New function to add missing - Mime-Version header if a Content-Type header exists. - (mh-display-smileys): New function to show graphical smileys. - (mh-display-emphasis): New function to show graphical emphasis. - (new-globals): New variables mh-mime-button-* and - mh-mime-security-* were added to control mime buttons. - (mh-mime-display): New function to display mime messages. The - functions mh-mime-display-part, mh-mime-display-alternative, - mh-mime-display-mixed, mh-mime-part-index, mh-small-image-p, - mh-mime-display-single, mh-insert-mime-button, mh-mm-display-part, - mh-press-button, mh-push-button, mh-mime-save-part, - mh-mime-inline-part, mh-widget-press-button, mh-mm-inline-message, - mh-mime-display-security, mh-mime-security-show-details, - mh-mime-security-press-button and mh-insert-mime-security-button - were added to support mh-mime-display. - - * mh-e.el (mh-header-display): Bind mh-decode-mime to nil when - mh-show-msg is called, so that mime isn't decoded when headers are - displayed. - (mh-quit): The show buffer is killed instead of invalidating and - burying it. - - * mh-comp.el (mh-yank-cur-msg): Filter out the mime buttons from - the yanked message. - (mh-filter-out-non-text): New function to filter out attachments - from message being yanked. - -2002-05-20 Bill Wohler - - * mh-utils.el (mh-invisible-headers-show-xface): First sentence of - docstring was not entirely on first line so was truncated in - customize and help buffers. Reworded so first sentence could fit - within 80 columns per checkdoc recommendation. - (mh-defun-show-buffer): Reworded per checkdoc recommendations. - Removed @SD while I was in there. - -2002-05-18 Satyaki Das - - * mh-seq.el (mh-narrow-to-seq): This function now removes the - current message notation in the folder. Otherwise, two current - message notations may be present after mh-widen is called. Also - mh-copy-seq-to-eob is called instead of mh-copy-seq-to-point since - the latter has a bug. - (mh-copy-seq-to-point): This function has a tricky problem. It - calls mh-map-to-seq-msgs which uses mh-goto-msg. mh-goto-msg - assumes that the folder is sorted (since it uses binary - search). The assumption isn't true, so it may not copy all the - messages. Since this function is not used any more it has been - removed. - (mh-copy-seq-to-eob): This function is a specialized (and - hopefully correct) replacement for mh-copy-seq-to-point. - -2002-05-17 Satyaki Das - - * mh-utils.el (mh-gnus-article-highlight-citation): Workaround for - problem caused by low value of recursive-load-depth-limit in - Emacs21.1 and CVS version of Gnus. - (mh-show-mode-map): New keymap variable to facilitate use of - summary commands from the show buffer. - (mh-show-folder-buffer): New local variable which keeps track of - the folder-buffer corresponding to the message being shown. - (mh-defun-show-buffer): New macro to convert interactive functions - callable in the summary buffer to interactive functions callable - in the show buffer. - (mh-show-mode): Make buffer read-only and use mh-show-mode-map as - keymap (closes SF #527946). - (mh-modify): New interactive function to edit a message in-place. - - * mh-e.el (mh-goto-cur-msg): Add an optional argument, - minimal-changes-p. If non-nil, the function will just change - the point to current message and do not change folder display. - (mh-folder-mode-map): Make "M" call mh-modify. - -2002-05-07 Peter S Galbraith - - * mh-utils.el (mh-invisible-headers-show-xface): New defcustom - variable. If non-nil, the X-Face header line will be excluded from - the variable `mh-invisible-headers'. Set this when using a - package such as x-face-el to display X-Face icons in mh-show-mode. - This variable's setting will eventually be set automatically when - mh-e does its own X-Face decoding (or this variable will be replaced - by one telling mh-e to decode the X-Face). We may not ship the - next release with this variable. - -2002-05-07 Peter S Galbraith - - * mh-comp.el (mh-x-face-file): New defcustom variable. File name - containing the encoded X-Face string to insert in outgoing mail. - (mh-insert-x-face): New function. Appends an X-Face field to the - header, but only if it doesn't already exist and if 'mh-x-face-file' - is non-nil and points to an existing file. - (mh-send-letter): Invoke mh-insert-x-face. - -2002-04-29 Mike Kupfer - - * mh-e.el (mh-delete-msg, mh-refile-msg, mh-undo): Check - whether XEmacs region is actually active (needed at least for 21.1). - [Patch committed by psg] - -2002-04-29 Mike Kupfer - - * mh-utils.el (mh-prompt-for-folder): Remove "default" argument - from completing-read as XEmacs-21.1 doesn't have it (21.4 does - however) and using the argument adds no functionality. - [Patch committed by psg] - -2002-04-11 Peter S Galbraith - - * mh-e.el (mh-delete-msg, mh-refile-msg, mh-undo): Add support for - XEmacs to act on selected region when active. - -2002-04-10 Peter S Galbraith - - * mh-e.el (mh-delete-msg, mh-refile-msg, mh-undo): XEmacs fix; Add - check to see if mark-active is bound, because Mandrake Linux include - XEmacs initialization code that binds transient-mark-mode. This - fix gets around a problem in Mandrake only. It wasn't a problem - on XEmacs generally. Fixes SF #541915. - -2002-04-08 Bill Wohler - - Released mh-e version 6.1. - - * mh-e.el (mh-folder-unseen-seq-name): Use "mhparam -component - Unseen-Sequence" command and "Unseen-Sequence: \\(.*\\)$" regexp - to increase robustness. - (mh-folder-unseen-seq-list): Use `expand-file-name' as - `mh-expand-file-name' isn't needed and the former saves function - call. - (Version, mh-version): Updated for release 6.1. - -2002-04-08 Peter S Galbraith - - * mh-e.el (mh-folder-unseen-seq-list): Specify mh-progs path in - call to mark command. Fixes a bug in which unseen messages - weren't highlighted if "mark" wasn't in the path. - -2002-04-07 Bill Wohler - - * MH-E-NEWS: Updated for release 6.1. - - * README: Updated for release 6.1. Updated verbiage about reading - MH-E-NEWS. - - * mh-comp.el, mh-e.el, mh-funcs.el, mh-mime.el, mh-seq.el, - mh-utils.el, mh-xemacs-compat.el: Updated copyright in files - modified this year. - - * mh-xemacs-compat.el: Put Author field back in, but set to FSF. - - * mh-comp.el, mh-funcs.el, mh-mime.el, mh-seq.el, - mh-utils.el: Fixed all checkdoc errors, except for no - documentation, and documentation in comments. Also removed the- - prefix from certain local variables. - - * mh-e.el: Fixed all checkdoc errors, except for no documentation, - and documentation in comments. Also removed the- prefix from - certain local variables. - (mh-folder-unseen-seq-name): Refactored to make default sequence - name more explicit and to handle undefined Unseen-Sequence MH - profile entry better. - -2002-04-02 Peter S Galbraith - - * mh-e.el: 'defvar mh-folder-unseen-seq-name' called a function to - set its value, and this happens also on byte-compilation (where - it can fail if the user's MH environment is not setup correctly). - I now set the value of mh-folder-unseen-seq-name at runtime when I - first need it. This should fix Debian bugs - https://bugs.debian.org/140232 and https://bugs.debian.org/140817 - -2002-03-25 Peter S Galbraith - - * mh-utils.el: remove "(require 'mh-e)" since mh-utils.el should - be at the bottom of the dependency tree. - * mh-e.el (mh-folder-unseen-seq-name): Make sure mh-progs is set - and use it as path to mhparam command in call-process. - -2002-01-23 Peter S Galbraith - - * mh-e.el (mh-folder-font-lock-keywords): Add call to - mh-folder-font-lock-unseen to fontify unseen messages in bold. - (mh-folder-unseen-seq-name): Provide name of unseen sequence from - mhparam. Used as default for variable of same name. - (mh-folder-unseen-seq-list): Returns a list of unseen messages - numbers for current folder. - (mh-folder-unseen-seq-cache): Cache variable to hold list of - unseen message numbers while font-lock iterates. This variable is - buffer-local. - (mh-folder-font-lock-unseen): Returns unseen message lines to - font-lock one by one. - -2002-01-15 Peter S Galbraith - - * mh-comp.el (mh-insert-prefix-string): Wrap a - "(let ((zmacs-regions nil))" around (mark) so it works in XEmacs. - Bug reported and fix suggested by Will Partain - Indeed, this is how it appears in XEmacs-21's mh-comp.el. - -2001-12-16 Jeffrey C Honig - - * mh-comp.el (mh-forward): Move the assignment to `fwd-msg-file' - to before the assignment to `draft' as the later changes buffers - and invalidates `mh-seq-list' (which is used in a function called - by (mh-seq-to-msgs)). Resolves SF #489448. - - * mh-utils.el: Add defcustoms for `mh-temp-folders-buffer' and - `mh-temp-sequences-buffer'. - - * mh-e.el (mh-quit): If they exist, kill 'mh-temp-buffer, - 'mh-temp-folders-buffer and 'mh-temp-sequences-buffer when - quitting. - - * mh-funcs.el (mh-list-folders): Use `mh-temp-folders-buffer' - (a defcustom initialized to "*Folders*") for folder listing. Put - into view mode and set it up to kill the buffer when exiting view - mode. - - * mh-seq.el (mh-list-sequences): Use `mh-temp-sequences-buffer' - (a defcustom initialized to "*Sequences") for sequences listing. - Put into view mode and set it up to kill the buffer when exiting - view mode. - -2001-12-16 Bill Wohler - - Released mh-e version 6.0. - - * MH-E-NEWS: Be a little more specific about incompatible changes. - Added info about outdated manual. - Removed variables in mh-scan regexp table that did not exist in - 5.0.2. - Added helpful documentation about finding relevant variables - containing regexps to mh-scan-format-file's description. - - * mh-e.el (mh-scan-format-file): Added information about getting a - list of regexp variables that you'll need to change if you - customize your scan's output. - (mh-folder-mode): Added documentation about `mh-scan-format-file' - for those users who modify their scan formats. - - * README: New file. Describes packages and provides simple - installation instructions. - - * Makefile (clean, dist, install-emacs): Replaced $(RM) with rm - -rf (closes SF #488661). - -2001-12-14 Bill Wohler - - Released mh-e version 5.0.93. - - * Makefile (MH-E-SRC): Added mh-xemacs-compat.el. - (MH-E-IMG): Added .pbm images for all. Removed mail_ prefix from - all. - (MH-E-IMG2): New variable to hold images in mail sub-directory. - (dist): Updated target to make mail sub-directory and copy - MH-E-IMG2 images there. - - * mh-xemacs-compat.el: Modified docs per GNU coding conventions. - - * mh-e.el: Reorganized variables having to do with the scan line. - Moved some random variables that were interspersed out of the - middle. Moved `mh-scan-format-file' first and let the variables - flow from there. - - As the number of variables increases, it is becoming important to - organize the mh-e namespace. Several variables having to do with - the format of scan lines were renamed, as follows: - (mh-good-msg-regexp): Renamed to mh-scan-good-msg-regexp. - (mh-deleted-msg-regexp): Renamed to mh-scan-deleted-msg-regexp. - (mh-refiled-msg-regexp): Renamed to mh-scan-refiled-msg-regexp. - (mh-valid-scan-line): Renamed to mh-scan-valid-regexp. - (mh-cur-msg-number-regexp): Renamed to mh-scan-cur-msg-number-regexp. - (mh-cur-msg-line-regexp): Renamed to mh-scan-cur-msg-regexp. - (mh-scan-rcpt-addr-regexp): Renamed to mh-scan-rcpt-regexp. - (mh-scan.font-lock-regexp): Renamed to mh-scan-format-regexp. - (mh-folder-scan-font-lock-face): Renamed to - mh-folder-scan-format-face. - (mh-folder-cur-msg-line-face): Renamed to mh-folder-cur-msg-face). - -2001-12-13 Bill Wohler - - * mh-utils.el (mh-msg-number-regexp): Renamed to - mh-scan-msg-number-regexp. - (mh-msg-search-regexp): Renamed to mh-scan-msg-search-regexp. - - * Corrected typos, quoted variables in doc strings, and made minor - wording changes in docs. - -2001-12-13 Peter S Galbraith - - * mh-xemacs-compat.el: defalias 'match-string-no-properties to - 'match-string for XEmacs. I've seen a better function for this - that actually removes text properties, but this will do for now. - - * mh-utils.el (mh-decode-quoted-printable): deactivate-mark not - bound in XEmacs. - - * mh-xemacs-compat.el: GNU Emacs Functions needed by XEmacs. - New file. - * mh-e.el: (require 'mh-xemacs-compat) when running XEmacs. - -2001-12-12 Peter S Galbraith - - * mh-comp.el (mh-send-letter): function local-variable-p needs two - arguments in XEmacs. - (mh-send-letter): sendmail-coding-system not bound in XEmacs. - (mh-send-letter): default-buffer-file-coding-system not bound in - XEmacs. - - * mh-e.el (mh-delete-msg, mh-refile-msg, mh-undo): - transient-mark-mode not bound in XEmacs. The feature of - operations made on all messages in the selected range when - transient-mark-mode is on doesn't work in XEmacs. - - * mh-e.el, mh-utils.el: Conditionalize calls to - 'add-to-list 'facemenu-unlisted-faces for XEmacs. - -2001-12-11 Jeffrey C Honig - - * mh-e.el (mh-scan-format): Add `mh-scan-format-file' variable to - specify the scan format string or file to use. Define formats for - MH and nmh that are compatible with the standard format, but - provide hints for font-lock. Define (mh-scan-format) for use by - (mh-regenerate-headers) and (mh-get-new-mail) to specify the args - necessary to inform the scan program which scan format string or - file to use. - -2001-12-07 Peter S Galbraith - - * mh-e.el (scan.font-lock): New format file documented in comments. - (mh-scan.font-lock-regexp): Adapted to new format. - (mh-folder-font-lock-keywords): Use new format. - - * mh-e.el (page-down.xpm): Icon renamed from nextpage. - - * mh-utils.el (mh-decode-quoted-printable): Bug fix. Better check - on what actually is a quoted-printable attachment. - -2001-12-06 Eric Ding - - * mh-mime.el (mh-mhn-compose-insertion, mh-mhn-compose-anon-ftp): - require mailcap.el here rather than using autoload at top of - mh-mime. - (mh-file-mime-type): get rid of unused variables (why were they - there to begin with?) - -2001-12-06 Peter S Galbraith - - * mh-e.el (mh-cur-msg-number-regexp, mh-cur-msg-line-regexp): - mh-cur-scan-msg-regexp splits into these two variables. - The whole-line fontification is disabled, but easily restored by a - user (although it could be a defcustom with choices DISABLED or - the correct regexp?) - (mh-folder-cur-msg-line-face): mh-folder-current-msg-face renamed - to this. - (mh-folder-cur-msg-number-face): mh-folder-current-face renamed to - this. - - * cabinet.xpm: Revert to rescan icon name. - * mh-e.el (mh-folder-tool-bar-map): s/cabinet/rescan/ - - * mh-e.el (mh-folder-font-lock-keywords): Reorder and tweak such - that current message line highlight doesn't mess up other highlights. - -2001-12-05 Eric Ding - - * mh-utils.el (mh-show-from-face): Change mh-show-from-face to - cyan on dark backgrounds; through a series of changes, it had - become the same color as mh-show-subject-face! - -2001-12-05 Bill Wohler - - * mh-e.el, mh-utils.el: Fixed typos in face definitions, and made - a couple of small doc string tweaks while I was in there. Peter, - if you don't agree, let me know and I'll back them out. I thought - the "mh-e" in the text was redundant since the variables start - with "mh"; I was also thinking ahead to how the documentation may - read. - -2001-12-05 Peter S Galbraith - - * mh-e.el (mh-cur-scan-msg-regexp): Match 0 is the whole line. - (mh-folder-current-msg-face): New face with only a background - settings, used in font-lock for the current message. - (mh-folder-font-lock-keywords): Use mh-folder-current-msg-face for - mh-cur-scan-msg-regexp. - - * mh-utils.el (mh-show-from-face): Use red3 instead of red for - light backgrounds. It's not as bright on the eyes. - (mh-show-subject-face): copy from mh-folder-subject-face instead. - Makes the look consistent with folder-mode. - - * mh-e.el (mh-folder-subject-face): Moved to mh-utils since we - need it to copy to mh-show-subject-face. - -2001-12-05 Bill Wohler - - * mh-e.el (mh-folder-mode-map): Moved `mh-extract-rejected-mail' - from "a" to "E". Better mnemonic, nicer to folks used to using a - for `mh-reply'. - -2001-12-04 Bill Wohler - - * mh-e.el (mh-folder-map): Added "S" for `mh-sort-folder'. - -2001-12-04 Peter S Galbraith - - * mh-e.el (mh-folder-subject-face et al.): Yet another attempt at - colors for folder-mode. Still themed, but fewer and darker - colors (Blame Eric this time!). I'll get to underlining tomorrow - night. - - * mh-e.el (mh-folder-tool-bar-map): Renamed all icons so they - don't have the word mail in them. Also generated a pbm format of - each icon for users without XPM support conpiled into Emacs. - -2001-12-04 Eric Ding - - * mh-utils.el (mh-show-font-lock-keywords): Use - mh-header-subject-font-lock instead of regexp for subject headers, - which may go multiple lines. - (mh-header-subject-font-lock): New function. - Fix typos ("highlight"). - -2001-12-04 Eric Ding - - * mh-e.el: changes to face colors on dark backgrounds. - (mh-folder-followup-face): change to LightGoldenRod. - (mh-folder-date-face): change to snow3. - (mh-folder-msg-number-face): change to snow4. - -2001-12-04 Bill Wohler - - Released mh-e version 5.0.92. - - * mh-utils.el (gnus-cite-face-list) - (mh-gnus-article-highlight-citation): Don't autoload. Revert to - requiring in `mh-gnus-article-highlight-citation' as before. With - the autoloads, if you ran mh-e before gnus, you'd get an undefined - gnus variable when viewing an article in gnus. Go figure. - -2001-12-03 Bill Wohler - - Released mh-e version 5.0.91. - - * MH-E-NEWS: Removed info about bumping up `max-specpdl-size' now - that workaround has been implemented. - - * Makefile (MH-E-OBJ): New variable to hold .elc files. - (all): Just compile. - (clean): New target that blows away MH-E-OBJ. - (dist): Added $(MH-E-OBJ) to tarball. - - Attempt to quiet compilation errors to a dull roar. - - * mh-e.el: Require easymenu, added autoload of info. - (mh-smail, mh-smail-other-window): Comment says these were needed - by Emacs 18. Out! - - * mh-utils.el: Don't require sendmail, but require mh-e. - Moved autoloads to top of file, and autoload gnus-cite and - sendmail too. - - * mh-pick.el: Require easymenu. Remove cond on - `easy-menu-define'--it exists. - - * mh-mime.el: Autoload mailcap. - - * mh-comp.el: Require mh-e and easymenu, moved autoloads to top of - file. - - * Makefile (EMACS): New constant to hold emacs calling sequence. - (install): Renamed to install-emacs. - (compile): New target to compile all files. - (dist): Make dependent on compile. - (import): Renamed to import-emacs. - (%.elc): New implicit rule to compile elisp files. - - * mh-e.el (mh-thread-map): Added "Td" for - mh-delete-subject-thread. - -2001-12-03 Peter S Galbraith - - * mh-e.el (mh-folder-tool-bar-map): Change tooltip for exec icon. - - * mh-e.el (mh-folder-subject-face): Change to IndianRed1. - (mh-folder-followup-face): Change to IndianRed. - (mh-folder-deleted-face): Use sedate face instead of bright one. - -2001-12-03 Bill Wohler - - * mh-utils.el (mh-invisible-headers): Increase size of - `max-specpdl-size' locally to work around insufficient default. - (mh-invisible-headers): Added X-Info and X-VSMLoop (NTMail). - -2001-12-03 Jeffrey C Honig - - * mh-utils.el (mh-find-progs): Searches should not stop if the - strings are not found, there is error detection at the end of the - routine (closes SF #488231). - -2001-12-02 Bill Wohler - - * MH-E-NEWS: Added info about bumping up `max-specpdl-size'. - - * Makefile (MH-E-IMG): New variable that contains images used by - mh-e. Add these files to release. - - * MH-E-NEWS: Second draft of mh-e 6.0 (was 5.1) release notes. - - * mh-e.el (mh-folder-updated-hook): Reworded to avoid ambiguity. - Is the hook called when you type `d' or when you type `x'? - (mh-unseen-updated-hook): Reworded to be consistent with - `mh-folder-updated-hook.' - - * mh-utils.el (mh-recenter): Accepted Gerd's change which is - evaluated at compile time. - -2001-12-02 Bill Wohler - - * mh-e.el Major, major keymap changes. The specific changes are - listed below, but view the sources, or use "C-h m" in MH Folder - mode for the complete list. - - Use of sub-keymaps inspired by gnus. The changes tripped me up at - first too, but after about 5 minutes of shock (which is to be - expected, I've been using the old keybindings for 16 years), I - honestly found the new bindings to be nice indeed. It will also - provide flexibility to allow for future functionality. I hate to - do this on the eve of the beta release, but you asked for it! It's - likely I'll have to pull an Eric and back this change out, but if - we can live with pink subjects, this can't be so bad ;-). - Question: will the users revolt? If they do, I suppose we can - release 6.0.1 the next day ;-). - (mh-folder-map, mh-sequence-map, mh-extract-map, mh-digest-map): - New keymaps which start with F, S, X, and D, respectively. The - mhstore commands can go in the mh-extract-map eventually. - (mh-thread-map): Renamed from mh-folder-thread-map. - - Keymap changes and rationale. The sub-keymaps allowed some - consistency (e.g., esp. with l(ist) and k(ill). - - e Deleted. Already have x. Now used by mh-edit-again. - a Deleted. Already have r. Now used by mh-extract-rej.. - j Deleted. Already have g. - - M-a -> e Better mnemonic. Matches rmail. Frees movement cmd. - M-e -> a Try `a'gain! - - M-f -> Fv Frees movement command - M-f -> Ff Alias (keep?) - M-f -> Fo Alias (keep?) - M-k -> Fk No reason but to keep with folder commands - M-l -> Fl No reason but to keep with folder commands - M-p -> Fp No reason but to keep with folder commands - M-r -> Fr Frees movement command - M-s -> Fs No reason but to keep with folder commands - M-u -> Fu No reason but to keep with folder commands - - M-% -> Sd Better mnemonic - M-# -> Sk Better mnemonic - M-q -> Sl Better mnemonic - C-xn -> Sn Frees up standard key binding - % -> Sp Better mnemonic for putting a message in a sequence - ? -> Ss Shows sequences that message is in - C-xw -> Sw Frees up standard key binding - - M-n -> Xs Better mnemonic (shar) - M-n -> Xu Better mnemonic (uuencode) - - M-SPC -> DSPC Frees mark command - M-\177 -> D\177 No reason but to keep with digest commands - M-b -> Db Frees movement command - -2001-12-01 Bill Wohler - - * mh-e.el: Use gnus style of keymaps. Now requires gnus-util. - (mh-folder-thread-map): New map, created by gnus-define-keys. - Reached when typing T in mh-folder-mode-map. Moved threading - functions to this new keymap so we can use dired again. - (mh-folder-mode-map): Defined by gnus-define-keys. Otherwise than - the new threading functions, no changes to the UI were made at - this point--saving that for the next check-in. - - * mh-pick.el (mh-pick-mode-map): Use gnus-define-keys. Now - requires gnus-util. - - * mh-comp.el (mh-letter-mode-map): Use gnus-define-keys. Now - requires gnus-util. - -2001-12-01 Jeffrey C Honig - - * mh-e.el: Update the documentation for the regexps used by - `mh-folder-font-lock-keywords' to specify how many parenthesized - expressions they are expected to have and what those expressions - are expected to match. - -2001-12-01 Bill Wohler - - * mh-e.el (mh-folder-mode): Removed iteration of key bindings, - \\{mh-folder-mode-map} suffices. Removed variable documentation - also as this is already out of date and a maintenance hassle. - Reference new mh customization group instead. - - * mh-comp.el (mh-letter-mode): Ditto. Also added new information - about MIME directives getting processed automatically if inserted - via mh-e commands. - - * mh-pick.el (mh-pick-mode): Edited documentation so it reads like - the other modes. - - * mh-e.el (mh-compat-quit): Deleted obsolete and unused function. - Comment in this function said that `b' shouldn't be used for - burst-digest, as it is used for `back' in info, less, and rn. But - what does `back' mean in MH Folder? I suppose if you visit a - folder, you would go `back' to the original folder. Hmmm, I guess - we'll leave the `b' binding alone for now. - - * mh-utils.el: Moved some of the variable comments to the first - column so they wouldn't wrap in such an ugly fashion. - (mh-showing-mode): Renamed variable and function from mh-showing - to conform with minor mode conventions. Added optional arg to - function so it would behave like a normal minor mode: no or nil - arg toggles mode, 0 arg turns off, non-nil turns on. It also turns - out that desktop-create-buffer would barf when recreating mh-e - buffers because it was calling mh-show with an arg. - (mh-show-mode): Use define-derived-mode to simplify definition a - *lot*. - (mh-set-mode-name): Deprecated by use of define-derived-mode. - Removed. - - * mh-pick.el (mh-pick-mode): Use define-derived-mode to simplify - definition a *lot*. - - * mh-e.el (mh-scan-prog): Removed message about "Buffer local" as - this message will appear in a future version of Emacs. - (mh-inc-folder): mh-showing renamed to mh-show-mode and made a - real minor mode. - (mh-folder-mode): Use define-derived-mode to simplify definition a - *lot*. - - * import-emacs (release): Change `(none)' to `mainline' so import - doesn't choke after running `cvs up -A' on Emacs. - (COPYING): Moved from $EMACS_HOME/etc to $EMACS_HOME. - (cvs update): Whoops! Forgot the second join (-jemacs). - make import works fine again. - -2001-11-30 Peter S Galbraith - - * mh-e.el (mh-folder-font-lock-keywords): Change order of - font-lock patterns such that subject body text doesn't get date - fontification. - - * mh-e.el (mh-scan-subject-regexp): Bug fix. Remove a dot. - scan.font-lock users have to setq it separately. - -2001-11-30 Eric Ding - - * mh-utils.el (mh-clean-msg-header): Go back to using - mh-delete-line. Using invisible text property is nicer in some - ways, but winds up with somewhat mysterious behavior should user - kill/yank stuff from the header (i.e., text gets yanked invisibly - and won't be seen by user until file is reloaded). - -2001-11-29 Bill Wohler - - * mh-e.el (mh-page-msg): Use mh-next-direction to page in the - right direction. - -2001-11-29 Jeffrey C Honig - - * mh-e.el (mh-scan-folder): Fix logic to not attempt to go to - the current message if there are no messages in the folder. - -2001-11-29 Peter S Galbraith - - * mh-e.el (mh-folder-font-lock-subject): New fontifier function - for subject lines in folder-mode. - (mh-scan-followup-regexp): Deleted obsolete regexp. Use - mh-scan-subject-regexp instead. - (mh-folder-font-lock-keywords): Use mh-folder-font-lock-subject - instead of obsolete mh-scan-followup-regexp variable. - (mh-folder-date-face, mh-folder-msg-number-face): - (mh-folder-subject-face, mh-folder-followup-face): - Now defined as proper faces instead of copied from font-lock - faces. - - * mh-mime.el (mh-media-type-regexp): New variable. Regexp matching - valid media types used in MIME attachment compositions. - (mh-file-mime-type): Use mh-media-type-regexp instead of - hard-wiring its value. - - * mh-utils.el (mh-show-unquote-From): New function to unquote - "^>From" in mh-show-mode (not saved to disk). - (mh-show-mode): Call mh-show-unquote-From. - -2001-11-29 Eric Ding - - * mh-utils.el (mh-clean-msg-header): Use mh-make-line-invisible - rather than mh-delete-line. - (mh-make-line-invisible): New function to make line(s) invisible - rather than deleting line(s). Optional argument specifies number - of lines to delete. - (mh-show-msg): screen-height has been deprecated; use no more. - (mh-notate): screen-width has been deprecated; use no more. - -2001-11-29 Jeffrey C Honig - - * mh-utils.el (mh-find-progs): Change mh-find-progs to rely on - the existence of mhparam. The location of mhparam is used to find - `mh-progs'. It uses the libdir and etcdir to find the - `mh-lib-progs' and `mh-lib' directories. If etcdir doesn't return - anything we assume `mh-lib-progs' is the same as `mh-lib' and that - we are using MH instead of nmh. - -2001-11-29 Peter S Galbraith - - * mh-e.el (mh-scan.font-lock-regexp): Change docs to reflect that - second paren expression is the user match. - (mh-folder-font-lock-keywords): Change from 1st to 2nd parenthesized - expression to match user name, after Jeffrey's change to the regexps. - -2001-11-29 Bill Wohler - - * mh-utils.el (mh-clean-message-header): Default is now t. - (mh-invisible-headers): Padded out to contain all the headers that - the mh-e developers don't like to see (closes SF #415759). - -2001-11-28 Bill Wohler - - * mh-comp.el (mh-rejected-letter-start): Added MIME MDN. While - this allows mh-extract-rejected-mail to strip the start of the - MDN, there is still a closing MIME marker at the end. This should - be cleaned up eventually. - -2001-11-28 Peter S Galbraith - - * mh-e.el (mh-folder-seq-tool-bar-map): New tool-bar used for - folder-mode when narrowed to sequence. - * mh-seq.el (mh-narrow-to-seq): Set tool-bar to - mh-folder-seq-tool-bar-map. - (mh-widen): Set tool-bar to mh-folder-tool-bar-map. - * widen.xpm: New icon used in mh-folder-seq-tool-bar-map. - - * mh-mime.el (mh-file-mime-type): Much better check on validity of - 'file' output. - - * mh-e.el (mh-scan-subject-regexp): New regexp variable for - subject string in folder mode. Used to extract subject sequence, - and will be used for font-lock soon. - * mh-seq.el (mh-subject-thread-to-sequence): More robust code by - using mh-scan-subject-regexp, allows users with non-standard - scan format to use subject sequences. - - * mh-comp.el (mh-letter-fill-column): Fill column to use in - mh-letter-mode. (Yes, I'm doing this in spite of what Bill said; - Someone can always undo it later) - (mh-letter-mode): setq fill-column to mh-letter-fill-column. - -2001-11-28 Bill Wohler - - * mh-e.el (mh-page-msg): The first time the end of page is hit, - set mh-page-to-next-msg-p to t. The second time the end of page is - hit, go to the next message. - - * mh-utils.el (mh-show-msg): Initialize mh-page-to-next-msg-p to - nil. - -2001-11-27 Bill Wohler - - * mh-mime.el (mh-mime-content-types): Updated list of types to - contain types used by mh-e developers, but not including types not - listed in - http://www.isi.edu/in-notes/iana/assignments/media-types/media-types. - -2001-11-27 Peter S Galbraith - - * mh-seq.el (mh-subject-thread-to-sequence) New function placing - all messages with similar subject line into a sequence named - 'subject. - (mh-narrow-to-subject-thread): New command to narrow to all - messages with similar subject line into a sequence named 'subject. - (mh-toggle-subject-thread): New command to toggle between a new - 'subject sequence or the wide view of a folder. - (mh-delete-subject-thread): New command to delete all following - messages with similar subject lines (leaving preceding ones - untouched). - (mh-next-unseen-subject-thread): New command to create and move to - a new subject thread created from the next unseen message as a - starting point. - * mh-e.el (mh-folder-message-menu): New menu entries for subject - threads. - (mh-folder-mode-map): New keybindings for subject threads. - (mh-lessp): New function to sort messages. - - * mh-utils.el (mh-show-font-lock-keywords): and various - faces... scoped within eval-after-load "font-lock" to avoid - requiring font-lock to use its faces. - * mh-e.el (mh-folder-font-lock-keywords): Same. - -2001-11-27 Jeffrey C Honig - - * mh-mime.el (mh-file-mime-type): Use mh-temp-buffer instead of - " *mh-temp". - - * mh-comp.el (mh-insert-x-mailer): Kill mh-temp-buffer after use. - -2001-11-26 Eric Ding - - * mh-utils.el: revert to using external mimedecode to decode - MIME quoted-printable parts - -2001-11-26 Jeffrey C Honig - - * mh-e.el (mh-process-commands): Added mh-folder-updated-hook. - * mh-e.el (mh-update-unseen): Added mh-unseen-updated-hook. - -2001-11-26 Peter S Galbraith - - * mh-mime.el (mh-file-mime-type): Make sure output from file - command is known to mailcap file, otherwise prompt the user. - (mh-mime-content-types): Add "image/png" type. - - * mh-e.el (mh-folder-font-lock-keywords): Use a bunch of new - mh-folder-*-face faces. - * mh-utils.el (mh-show-font-lock-keywords): Use a bunch of new - mh-show-*-face faces. - - * mh-utils.el (mh-letter-header-font-lock): Bug fix. Fix infinite - loop in emacs20 font-locking. - (mh-header-field-font-lock): Preventive fix with similar change. - - * mh-comp.el (mh-reply-show-message-p): Fix typo for "displayed". - * MH-E-NEWS: Same. - - * mh-e.el (mh-folder-tool-bar-map): Bug fix. I had - mh-repack-folder instead of mh-pack-folder. - -2001-11-26 Bill Wohler - - * mh-e.el: - Updated header for consistency and to conform with (elisp)Library - Headers. - (mh-do-not-confirm): Updated documentation string to reflect - reality (e.g., is no longer used by mh-kill-folder and is used by - more functions than just mh-undo-folder). - (mh-page-msg): Now shows the next undeleted message if looking at the - bottom of the current message. - (mh-process-or-undo-commands): Fixed indentation. - - * mh-mime.el: - (mh-mhn-compose-insertion, mh-mhn-compose-anon-ftp): If MIME type - cannot be determined with file command, use mailcap-mime-types (if - available) to provide list for completing read. - - * MH-E-NEWS: First draft of mh-e 5.1 release notes. - -2001-11-26 Eric Ding - - * mh-utils.el (mh-decode-quoted-printable): Implement - quoted-printable decoding in elisp (starting with code copied - from FLIM). - (mh-decode-quoted-printable-region): Move (require 'hexl) outside - while loop. - (mh-decode-quoted-printable): give user a choice between using - internal code or external program to decode quoted-printable - content. Resurrect code that calls external mimedecode program. - -2001-11-25 Peter S Galbraith - - * mh-utils.el (mh-highlight-citation-p): New variable to determine - whether to highlight citations in message body with gnus, - font-lock or not at all. - (mh-show-font-lock-keywords): removed citations from keywords. - (mh-show-font-lock-keywords-with-cite): New variable, equivalent - to prior mh-show-font-lock-keywords. - (mh-gnus-article-highlight-citation): hook into gnus for - multi-level citation highlighting. - (mh-show-mode): Use either mh-show-font-lock-keywords or - mh-show-font-lock-keywords-with-cite, depending on value of - mh-highlight-citation-p, and possibly call - mh-gnus-article-highlight-citation. - * mh-comp.el (mh-letter-mode): Same as for mh-show-mode above. - -2001-11-25 Jeffrey C Honig - - * mh-comp.el (mh-redistribute): Added mh-redist-background - variable to cause mh-redistribute to run the redist command in the - background. This causes the transaction log to be visible, like - with send. - -2001-11-25 Peter S Galbraith - - * mh-e.el (mh-inc-folder): 'inc' finishes by displaying the first - new message if already showing messages. - -2001-11-22 Peter S Galbraith - - * mh-utils.el (mh-prompt-for-folder): Exit with error if no folder - specified, otherwise mh-refile-msg may try to create a folder with - empty name, and this creates problems; even mh-undo can't handle - it (Closes SF #476824). - - * mh-comp.el (mh-letter-tool-bar-map): Info button needed to - require 'info. Also tweaked help texts. - (mh-letter-menu): Use headline capitalization (Closes SF #483203). - * mh-e.el (mh-folder-tool-bar-map): Same as above. - (mh-folder-folder-menu, mh-folder-message-menu): - (mh-folder-sequence-menu): Same as above. - * mh-pick.el (mh-pick-menu): Same as above. - -2001-11-21 Peter S Galbraith - - * mh-comp.el (mh-reply-show-message-p): The setting of this - variable determines whether the MH show-buffer is displayed with - the current message when using mh-reply without a prefix argument. - Set it to nil if you already include the message automatically in - your draft using "repl: -filter repl.filter" in your ~/.mh_profile - file. - (mh-reply): Don't show message in other window if - mh-reply-show-message-p is nil. - - * mh-e.el (mh-folder-tool-bar-map): Add mail_exec.xpm icon for - mh-execute-commands. - - * mh-utils.el (mh-show-mouse): New function to click on a message - in folder-mode and show that message. - * mh-e.el (mh-folder-mode-map): Bind mh-show-mouse to mouse-2. - - * mh-e.el (mh-page-msg): Show buffer first if not displayed, - instead of simply complaining there's no other window. - - * mh-e.el (mh-folder-tool-bar-map): New tool-bar for folder mode! - (mh-folder-mode): Setup tool-bar. - - * mh-mime.el (mh-have-file-command): try to non-fatally load - executable.el because emacs20 doesn't autoload it. - * mh-utils.el (load "executable" t t): Idem. - - * mh-utils.el (mh-clean-msg-header): Bug fix. locally bind - after-change-functions to nil, working around a strange font-lock - bug in emacs20 when (add-hook 'mh-show-mode-hook 'turn-on-font-lock) - was used. - - * mh-comp.el (require 'sendmail): Moved from mh-comp.el to - mh-utils.el because it is needed in reading mail too. - (mh-header-field-end, mh-in-header-p): Moved to mh-utils.el - because they are needed by mh-show-mode's font-lock code. - Unfortunately, this splits the field related code into two files. - Perhaps it should all go into mh-utils? - -2001-11-20 Eric Ding - - * mh-utils.el (mh-show-from-face): Fix typo in defface - -2001-11-20 Bill Wohler - - * mh-utils.el (mh-mail-header-separator): Set to -------- as - defined by MH (components, and replcomps files). This variable - cannot be a regexp since it is used as an argument to insert and - is passed through regexp-quote before being used. The previous - value broke a lot of code, including mailcrypt. - - * mh-comp.el (mh-letter-mode, mh-send-letter): Insert X-Mailer - header field from mh-send-letter. - (mh-edit-again, mh-extract-rejected-mail): Call - mh-insert-header-separator to ensure that there is a separator. - Packages such as mailcrypt depend on it. - (mh-insert-header-separator): New function to insert - mh-mail-header-separator if it doesn't exist. - -2001-11-20 Peter S Galbraith - - * mh-comp.el (mh-letter-mode): Make font-lock-defaults a local variable - * mh-e.el (mh-folder-mode): Same. - * mh-utils.el (mh-show-mode): Same. - - * mh-e.el (mh-scan-msg-num-regexp): Delete variable and replace - with mh-good-msg-regexp. - - * mh-utils.el (mh-mail-header-separator): Bug fix. Moved from - mh-comp.el to mh-utils.el (which mh-comp.el loads). - - * mh-comp.el (mh-in-header-p): Recycle sendmail.el code (as - suggested by Bill). - * mh-utils.el (mh-letter-header-font-lock): Use mh-in-header-p. - - * mh-comp.el (mh-letter-tool-bar-map): tool-bar customize button goes - to customizing mh-compose group. - - * mh-utils.el (mh-show-mode): font-lock bug fix. Locally set - font-lock-support-mode to nil. - (mh-letter-header-font-lock, mh-header-field-font-lock): font-lock - bug fix. Don't return match beyond font-lock search limit. - - * mh-comp.el (mh-letter-mode): Emacs20 bug fix. tool-bar-mode is - not a bound variable. - -2001-11-19 Peter S Galbraith - - * mh-comp.el (mh-letter-tool-bar-map): tool-bar help button goes - to 'Draft Editing' info node. - - * mh-utils.el (mh-show-from-face, mh-show-to-face): New faces used - for font-lock. - (mh-header-to-font-lock, mh-header-cc-font-lock) - (mh-header-field-font-lock): New helper function returning whole - header field arguments to font-lock. - (mh-show-font-lock-keywords): Heavily modified using the above. - - * mh-e.el (mh-scan-msg-num-regexp): Regexp matching the message - number in scan lines. - (mh-scan-date-regexp): Regexp matching a valid date in scan lines. - (mh-scan-rcpt-addr-regexp): Regexp specifying the recipient in - scan lines for messages we sent. - (mh-scan-followup-regexp): Regexp matching a followup subject - line, starting with Re: - (mh-scan-body-regexp): - Regexp matching the message body beginning displayed in scan lines. - (mh-scan.font-lock-regexp): Regexp matching output of the - optional scan.font-lock format file. - (mh-folder-font-lock-keywords): New font-lock for folder-mode that - uses the above regexps. - -2001-11-19 chad brown - - * mh-comp.el (mh-letter-tool-bar-map): made both references to - mh-letter-tool-bar-map conditional on tool-bar-mode, instead of - just one. - -2001-11-19 Bill Wohler - - * mh-comp.el (mh-position-on-field): Move to the end of the header - if the field is not present. This function was documented to do - this, but wasn't doing so. - (mh-insert-x-mailer): Simplified by using existing - mh-goto-header-field and mh-insert-fields functions. Now that - mh-insert-fields is used to insert X-Mailer header field, no - longer need to include X-Mailer in mh-x-mailer-string. - -2001-11-18 Peter S Galbraith - - * mh-comp.el (mh-letter-tool-bar-map): New version of - mh-letter-mode tool-bar. Changed order of buttons; made customize - and info buttons specific to mh-e. - - * mh-e.el (mh-folder-font-lock-keywords): New font-lock regexp - uses variables mh-deleted-msg-regexp, mh-refiled-msg-regexp and - mh-cur-scan-msg-regexp, so will better adapt to non-default scan - formats. Also, lines marked for refiling are now fontified. - -2001-11-18 Bill Wohler - - * mh-utils.el (mh-show-mode): Added local variable - mail-header-separator which is initialized to - mh-mail-header-separator. - - * mh-comp.el (mh-mail-header-separator): Updated to include ^$. - Needed when running mh-edit-again, since by then the separator is - gone. Added documentation saying one should use - mail-header-separator and initialize it from - mh-mail-header-separator. - (mh-forward): Initialize mail-header-separator since - mh-letter-mode hasn't kicked in yet (which does initialize - mail-header-separator). - (mh-letter-mode): Initialize mail-header-separator from - mh-mail-header-separator, not hard-coded string. - - * mh-comp.el (mh-insert-x-mailer-p): New variable to control - whether X-Mailer string is inserted. Default: t. - (mh-x-mailer-string): New variable that caches actual X-Mailer - string. - (mh-letter-mode): Call mh-insert-x-mailer if mh-insert-x-mailer-p - is t. - (mh-insert-x-mailer): New function that inserts X-Mailer header - field. - -2001-11-17 Peter S Galbraith - - * mh-utils.el (mh-letter-header-font-lock): New function to return - the entire mail header to font-lock for sedate font-locking. - (mh-show-font-lock-keywords): Modified to fontify whole lines and use - mh-letter-header-font-lock above to fontify whole header. - -2001-11-17 Bill Wohler - - * mh-comp.el (mail-header-separator): Added ^ and $ to make more - specific. - (mh-forward, mh-letter-mode): Replaced hard-coded string with - mail-header-separator. - -2001-11-16 Bill Wohler - - * mh-e.el (mh-e-RCS-id): Renamed to mh-version. - (mh-version): The variable: Set to a number instead of Id since - the Id didn't have the mh-e version number, and both Emacs and - gnus do it this way too. - (mh-version): The function: Fixed for nmh. Now displays mh-e - version correctly. Cleaned up output and display mh-progs, etc. - (Closes SF #405620.) - -2001-11-15 Peter S Galbraith - - * mh-comp.el (mh-letter-tool-bar-map): New tool-bar support for - mh-letter-mode in emacs21. Uses icons from gnus/message.el. - * mh-comp.el (mh-letter-mode): Add buffer-local binding of - tool-bar-map to mh-letter-tool-bar-map. - -2001-11-15 Peter S Galbraith - - * mh-mime.el (mh-have-file-command): Add check for existence of - executable-find command, which Jeffrey didn't exist in emacs-20.4. - * mh-utils.el (mh-decode-quoted-printable-have-mimedecode): same - as above. - * mh-mime.el (mh-file-mime-type): Bug Fix. Some versions of - 'file' output a string like "file: Using regular magic file..." - to stderr, so discard stderr when using call-process with 'file'. - -2001-11-14 Peter S Galbraith - - * mh-mime.el (mh-have-file-command): Check if 'file' command on - system accepts arguments -i -b before accepting it for our use. - -2001-11-14 Peter S Galbraith - - * mh-utils.el (mh-find-progs): Use expand-file-name instead of - concatenating together strings into a path. - -2001-11-14 Peter S Galbraith - - * mh-e.el (mh-folder-sequence-menu): Enable mh-widen in sequence - menu only when mh-narrowed-to-seq is t. - -2001-11-14 Peter S Galbraith - - * mh-mime.el (mh-have-file-command): Use 'executable-find' instead - of more complicated and error-prone call-process to which command. - * mh-utils.el (mh-decode-quoted-printable-have-mimedecode): Same - change as above. - -2001-11-14 Jeffrey C Honig - - * mh-e.el (mh-make-folder-mode-line): Bug fix. Properly deal with - folders that do not have any lines in them. Print "no msgs" - instead of "0 msgs". Do not try to print a range when there are - no messages. - * mh-e.el (mh-regenerate-headers): Bug fix. Catch and remove the - "scan: bad message list" message. - -2001-11-13 Jeffrey C Honig - - * mh-utils.el (mh-find-progs): Bug fix. Add "mh/etc" to the - subdirectories to search for "components". On BSD/OS, nmh is in - "/usr/contrib/mh/*". - -2001-11-13 Peter S Galbraith - - * mh-comp.el (mh-letter-mode): Bug fix. Load mh-mime before - setting mh-mhn-compose-insert-p (when looking at a "forw: -mime" - message containing a MIME composition) such that the variable is - properly declared as buffer-local. - -2001-11-12 Bill Wohler - - * mh-funcs.el (mh-print-msg): mhl is in the mh-lib-progs - directory, not mh-lib (closes SF #481128). - -2001-11-12 Peter S Galbraith - - * mh-seq.el (mh-widen): Bug fix (closes SF #481036). - In a sequence with pending deletes and refiles, running mh-widen - would wipe out their notations, even though the sequences are still - defined. Fixed by calling a new function, - mh-notate-deleted-and-refiled. Also changed the coping of - mh-goto-msg-num since it didn't work consistently. - * mh-seq.el (mh-notate-deleted-and-refiled): New functions written - to fix above mh-widen bug. It's a first cut, we may want to clear - all notations first, and notate the current-message sequence and - user sequences. Time will tell. - -2001-11-12 Peter S Galbraith - - * mh-seq.el (mh-widen): Make it attempt to stay on the same - message number (closes SF bug #480922). - -2001-11-11 Bill Wohler - - * import-emacs: New shell script to import Emacs changes to mh-e. - - * Makefile (import): New target to import Emacs changes. - -2001-11-09 Peter S Galbraith - - * mh-mime.el (mh-file-mime-type): Bug fix. Change regexp to - extract mime type from 'file -i' command output. - -2001-11-08 Peter S Galbraith - - * mh-utils.el (mh-update-sequences-after-mh-show): - New customizable variable telling whether to run - mh-update-sequences in mh-show-mode. Default is t. - * mh-utils.el (mh-show-msg): Run mh-update-sequences when - mh-update-sequences-after-mh-show is set. - -2001-11-08 Peter S Galbraith - - * mh-utils.el (mh-decode-quoted-printable-have-mimedecode): - New variable telling whether command 'mimedecode' is on system. - (http://www.freesoft.org/CIE/FAQ/mimedeco.c) - * mh-utils.el (mh-decode-quoted-printable): - New customizable variable telling whether to run mimedecode on - MIME message containing quoted-printable parts. mimedecode will - only alter quoted-printable parts, leaving others intact, and the - resulting message is still fully MIME. - * mh-utils.el (mh-decode-quoted-printable): New function to run - mimedecode on the current buffer. - * mh-utils.el (mh-display-msg): Conditionally call - mh-decode-quoted-printable function if mh-decode-quoted-printable - variable is set, to view messages containing quoted-printable - characters into 8-bit. - -2001-11-08 Peter S Galbraith - - * mh-comp.el (mh-letter-mode): Set mh-mhn-compose-insert-p if - looking at a "forw: -mime" message containing a MIME composition. - * mh-mime.el (mh-file-mime-type): Bug fix. Failed on files like - "~/.mh_profile" because of shell construct. Wrapped filename with - expand-file-name. - * mh-comp.el (mh-letter-mode-map): C-cC-o keybinding in - mh-letter-mode-map for mh-open-line. - -2001-11-07 Peter S Galbraith - - * mh-comp.el (mh-open-line): New user function to split open a line - when editing a reply with included text. - * mh-comp.el (mh-current-fill-prefix): New function used by - mh-open-line to get the fill-prefix on the current line. - * mh-comp.el: Add mh-open-line to mh-letter-mode menubar. - -2001-11-06 Peter S Galbraith - - * mh-seq.el (mh-region-to-sequence): New function, creating a - sequence named 'region containing the message list in the selected - region. - * mh-e.el (mh-delete-msg): Mark messages in region for deletion if - mark is active and in transient-mark-mode. - * mh-e.el (mh-refile-msg): Mark messages in region for refiling if - mark is active and in transient-mark-mode. - * mh-e.el (mh-undo): Undo message marks for refile or deletion if - region if mark is active and in transient-mark-mode. - -2001-11-06 Peter S Galbraith - - * mh-comp.el (mh-letter-mode): Use sendmail.el's fill-paragraph. - Copy its settings for paragraph-start, paragraph-separate, - fill-paragraph-function, adaptive-fill-regexp and - adaptive-fill-first-line-regexp. This make M-q (fill-paragraph) - work correctly! - -2001-11-05 Peter S Galbraith - - * mh-funcs.el (mh-kill-folder): Remove mh-do-not-confirm condition - and always prompt the user for such a drastic step. Also change - the prompt a bit to clarify it. - -2001-11-04 Peter S Galbraith - - * mh-mime.el (mh-mhn-compose-insert-p): New buffer-local variable - to tell when a MIME insertion was done in a letter. - * mh-mime.el (mh-mhn-compose-type): Set mh-mhn-compose-insert-p. - * mh-mime.el (mh-mhn-compose-external-type): - Set mh-mhn-compose-insert-p. - * mh-mime.el (mh-mhn-compose-forw): Set mh-mhn-compose-insert-p. - * mh-mime.el (mh-edit-mhn): Clear mh-mhn-compose-insert-p. - * mh-comp.el (mh-send-letter): Run mh-edit-mhn when - mh-mhn-compose-insert-p is set. - -2001-11-03 Peter S Galbraith - - * mh-mime.el (mh-have-file-command): new function testing whether - file command is on the system. - * mh-mime.el (mh-file-mime-type): new function returning MIME type - from file command. - * mh-mime.el (mh-mhn-compose-insertion): Make use of - mh-file-mime-type function instead of prompting. - -2001-10-30 Peter S Galbraith - - * mh-utils.el (mh-show-use-goto-addr): defcustom this new - variable, determining whether to call goto-addr in mh-show-mode. - * mh-utils.el (mh-show-mode): Call goto-address when - mh-show-use-goto-addr is t. - -2001-10-25 Peter S Galbraith - - * mh-utils.el (mh-recenter): Clarify docs and change '(t) to - (list 4) to match elisp doc on what C-u prefix argument actually is. - -2001-10-23 Peter S Galbraith - - * mh-utils.el (mh-summary-height): In my quest to make mh-e more - useful out-of-the-box for new users, set mh-summary-height to a - minimum of 4 and a maximum of 10 depending on frame height. I - typically have 70 lines in my Emacs frame, so having a default of - 4 was silly for my case. - * mh-e.el (mh-update-sequences): Check for nil value of - mh-current-folder, which happens if mh-summary-height < 4 - although I haven't tracked down why that happens. - -2001-10-22 Peter S Galbraith - - * mh-comp.el (mh-insert-fields): Test for nil value when inserting - field. - -2001-10-20 Peter S Galbraith - - * mh-comp.el (mh-user-agent-compose): Merged-in from XEmacs-21.4 source - * mh-comp.el (mh-letter-mode): Add easy-menu-add statement for XEmacs21 - * mh-pick.el (mh-pick-mode): Add easy-menu-add statement for XEmacs21. - * mh-e.el (mh-folder-mode): Add easy-menu-add statements for XEmacs21. - * mh-utils.el: defalias 'screen-height to 'frame-height for XEmacs21. - -2001-10-19 Peter S Galbraith - - * mh-mime.el (mh-edit-mhn): Use mhbuild in nmh context. - * mh-utils.el (mh-find-progs): The variable mh-nmh-p (t when nmh - is in use rather than MH) was set assuming that the string "nmh" - will be in mh-lib-progs or mh-lib. This failed on Debian systems. - Better to check for the existence of mhbuild in directory mh-progs. - (closes SF bug #441776) - -2001-10-18 Peter S Galbraith - - * mh-e.el: Add menubar entry from contrib/mh-menubar.el - * mh-comp.el: Add menubar entry from contrib/mh-menubar.el - * mh-pick.el: Add menubar entry from contrib/mh-menubar.el - -2001-07-30 Peter S Galbraith - - * mh-e.el: Change font-lock patterns for folders. - Fontify scan.font-lock patterns (which will be documented) - and fontify subject lines prefixed with "Re:" differently. - * mh-comp.el (mh-letter-mode): Add font-lock support as in - mh-show-mode. - -2001-04-14 chad brown - - Rearrange the font-lock keywords a bit. - -2001-04-12 chad brown - - Preliminary (somewhat boring) font-lock support for mh-e. More - interesting font-lock support probably wants to have better - support for multiple format files - -2001-02-24 chad brown - - Add default nmh paths to mh-find-prog in mh-utils.el. - change to mh-kill-folder in mh-funcs.el to make it more general. - -2001-02-19 Bill Wohler - - * Makefile (EMACS): Renamed to EMACS_HOME. Also, don't define if - EMACS_HOME already exists to give developer a chance to set - environment variable. - (install): $MH-E-SRC is copied to $(EMACS_HOME)/lisp/mail, not - $(EMACS_HOME)/src. - (dist): Leave release in current directory. - - - Copyright (C) 2003-2024 Free Software Foundation, Inc. - - This file is part of GNU Emacs. - - GNU Emacs is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - GNU Emacs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNU Emacs. If not, see . - -;; Local Variables: -;; coding: utf-8 -;; End: diff --git a/lisp/mh-e/ChangeLog.2 b/lisp/mh-e/ChangeLog.2 deleted file mode 100644 index e632bcf1858..00000000000 --- a/lisp/mh-e/ChangeLog.2 +++ /dev/null @@ -1,3697 +0,0 @@ -2014-10-20 Glenn Morris - - * Merge in all changes up to 24.4 release. - -2014-09-30 Bill Wohler - - Release MH-E version 8.6. - - * mh-e.el (Version, mh-version): Update for release 8.6. - -2014-09-30 Mike Kupfer - - * mh-comp.el (mh-insert-x-face): Ensure that mh-x-face-file is a - string before trying to use it (closes SF #474). - (mh-bare-components): New function to create a temporary initial - components file; replaces mh-find-components. Improve the temp - folder and file names as per a suggestion from Bill Wohler. - Also address XEmacs compatibility issues: use mm-make-temp-file instead - of make-temp-file, and only pass one argument to delete-directory. - (mh-edit-again, mh-send-sub): Use mh-bare-components instead of - mh-find-components (partially closes SF #468). - -2014-05-09 Glenn Morris - - * mh-e.el (mh-variants): Use file-accessible-directory-p. - -2014-03-16 Bill Wohler - - * mh-folder.el (mh-regenerate-headers): Fix scan: bad message list - `unseen' error (closes SF #471). - * mh-e.el (mh-version): Add +bzr to version. - -2014-03-06 Glenn Morris - - * mh-compat.el (mh-display-completion-list): - Replace use of obsolete argument of display-completion-list. - -2013-11-05 Stefan Monnier - - * mh-print.el (mh-ps-print-preprint): Don't use dynamic-var - `prefix-arg' as function argument. - -2013-06-18 Juri Linkov - - * mh-alias.el (mh-alias-local-users): Add non-nil arg REPLACE to - the call of `shell-command-on-region'. (Bug#14637) - -2013-05-22 Glenn Morris - - * mh-speed.el (mh-speed-view): - Use dframe-with-attached-buffer rather than speedbar- alias. - -2013-05-21 Glenn Morris - - * mh-comp.el (mh-regexp-in-field-p): Fix previous change. - -2013-05-09 Glenn Morris - - * mh-e.el (mh-sortm-args, mh-default-folder-for-message-function): - Fix custom types. - -2013-05-08 Stefan Monnier - - * mh-comp.el (mh-regexp-in-field-p): Minor simplification. - -2013-03-02 Bill Wohler - - Release MH-E version 8.5. - - * mh-e.el (Version, mh-version): Update for release 8.5. - -2013-03-02 Jeffrey C Honig - - * mh-folder.el (mh-inc-folder): Revert SF #2321115, SF #250 - which processed pending deletes and refiles. Call to - mh-process-or-undo-commands to ensure that pending changes are - properly tagged after including new mail (closes SF #271). - - * mh-comp.el: Ensure that mail-header-separator is set before - invoking any mml functions (closes SF #270). - -2013-01-23 Dmitry Antipov - - * mh-acros.el (mh-do-at-event-location): Use point-marker. - * mh-search.el (mh-index-create-imenu-index): Likewise. - * mh-xface.el (mh-x-image-url-display): Likewise. - -2012-11-25 Bill Wohler - - Release MH-E version 8.4. - - * mh-e.el (Version, mh-version): Update for release 8.4. - - * mh-comp.el (mh-regexp-in-field-syntax-table): Fix docstring. - (mh-edit-again): Format. - (mh-components-to-list): Fix docstring. - (mh-regexp-in-field-p): Remove unused variable `field'. - - * mh-compat.el (mh-define-obsolete-variable-alias) - (mh-make-obsolete-variable): New macros to fix XEmacs compiler - warnings. - - * mh-letter.el (mh-yank-hooks): Use new mh-make-obsolete-variable - macro. - - * mh-e.el (mh-kill-folder-suppress-prompt-hooks): - Use new mh-define-obsolete-variable-alias macro. - - * mh-compat.el (mh-cl-flet): New alias for cl-flet on Emacs 24 and - flet elsewhere. - - * mh-thread.el (mh-thread-set-tables): Replace flet with new alias - mh-cl-flet. - - * mh-show.el (mh-gnus-article-highlight-citation): - Replace flet with new alias mh-cl-flet. - - * mh-mime.el (mh-display-with-external-viewer, mh-mime-display) - (mh-press-button, mh-push-button, mh-display-emphasis): - Replace flet with new alias mh-cl-flet. - - * mh-e.el (mh-invisible-header-fields-internal): - Remove trailing whitespace. - -2012-11-25 Jeffrey C Honig - - * mh-comp.el: (mh-edit-again): Use the components file to specify - default values for missing headers in the draft. - (mh-regexp-in-field-syntax-table, mh-fcc-syntax-table) - (mh-addr-syntax-table, mh-regexp-in-field-p): Use a syntax table - so we'll properly parse non-address fields. - (mh-components-to-list, mh-extract-header-field): New functions to - read components file. - (mh-find-components, mh-send-sub): Move code to locate components - file into a new function. - (mh-insert-auto-fields, mh-modify-header-field): New syntax for - calling mh-regexp-in-field-p (closes SF #1708292). - - * mh-e.el (mh-invisible-header-fields-internal): Added: X-xsi. - (addresses SF #1916032). - - * mh-folder.el (mh-inc-folder): Call mh-process-or-undo-commands - before running to ensure we do not lose any pending changes. - (closes SF #2321115). - -2012-11-25 Ted Phelps - - Postpone junk processing (closes SF #2945712). Patch submitted by - Ted Phelps and refined by Bill Wohler. - - * mh-e.el (mh-blacklist, mh-whitelist): New variables. - (mh-whitelist-preserves-sequences-flag): New option. - (mh-before-commands-processed-hook): Update documentation. - (mh-blacklist-msg-hook, mh-whitelist-msg-hook): New hooks. - (mh-folder-blacklisted, mh-folder-whitelisted): New faces. - * mh-folder.el (mh-folder-message-menu): Add "Junk" to "Undo." - (mh-folder-font-lock-keywords): Add regexps for blacklisted and - whitelisted messages. - (mh-folder-mode): Add mh-blacklist and mh-whitelist variables. - (mh-execute-commands): Update documentation. - (mh-undo, mh-outstanding-commands-p, mh-process-commands) - (mh-delete-a-msg, mh-refile-a-msg, mh-undo-msg): - Handle blacklisted and whitelisted messages. - * mh-junk.el (mh-junk-blacklist, mh-junk-whitelist): Update to put - messages in blacklist and whitelist respectively for latter - processing. - (mh-blacklist-a-msg, mh-junk-whitelist-a-msg): New function to - support previous functions. - (mh-junk-blacklist-disposition): New function. - (mh-junk-process-blacklist, mh-junk-process-whitelist): - New functions that perform the blacklisting and whitelisting - respectively that used to be performed by mh-junk-blacklist and - mh-junk-whitelist. - * mh-scan.el (mh-scan-blacklisted-msg-regexp) - (mh-scan-whitelisted-msg-regexp): New scan line regexps. - (mh-scan-good-msg-regexp): Add B and W characters to regexp. - (mh-scan-cmd-note-width): Update documentation. - (mh-note-blacklisted, mh-note-whitelisted): New scan line - characters. - * mh-search.el (mh-index-execute-commands): Handle blacklisted and - whitelisted messages. - -2012-11-25 Jeffrey C Honig - - * mh-e.el (mh-invisible-header-fields-internal): Added: - Bounces-To:, Bounces_to:, X-ACL-Warn:, X-BFI:, X-BPS1:, X-BPS2:, - X-Campaign-Id:, X-Campaign:, X-Cloudmark-SP-, X-Destination-ID:, - X-detected-operating-system:, X-DocGen-Version:, X-EM-, - X-Email-Type-Id:, X-FB-SS:, X-FuHaFi:, X-MailFlowPolicy:, - X-mail_abuse-inquires, X-MailingID:, X-Match:, - X-MaxCode-Template:, X-ME-Bayesian:, X-Sendergroup:, X-SFDC-, - X-SMFBL:, X-SMHeaderMap:, X-VGI-OESCD:, X-VirtualServer:, - X-VirtualServerGroup:, X-XPT-XSL-Name:, X-Y-GMX-Trusted:, - X-XWALL-, X-ZixNet:. Changed X-Habeas-SWE- to X-Habeas-. - Updated the comment. (addresses SF #1916032). - -2012-11-25 Bill Wohler - - * mh-e.el (mh-invisible-header-fields-internal): - Add X-AnalysisOut, X-Authentication-Info, X-Auto-Response-Suppress, - X-Bayes-Prob, X-Cam-, X-CanIt-Geo, X-Completed, X-Facebook, - X-Forwarded-, X-Generated-By, X-Headers-End, X-IEEE-UCE, - X-Jira-Fingerprint, X-Junkmail-, X-Launchpad-, X-MXL-Hash, - X-Notification-, X-Notifications, X-Oracle-Calendar. - Replace X-DCC-Usenix-Metrics with X-DCC- (addresses SF #1916032). - -2012-11-25 Jeffrey C Honig - - * mh-letter.el (mh-yank-cur-msg): Replace usage of set-buffer with - with-current-buffer in mh-yang-cur-msg, semantics changed in emacs - 23 and we do not want to use set-buffer unless we actually want to - change the buffer the user is looking at (closes SF #2830504). - - * mh-show.el (mh-show-folder-map): Add missing key binding for - mh-show-pack-folder (closes SF #3466086). - -2012-11-25 Bill Wohler - - * mh-e.el (Version, mh-version): Add +bzr to version. - -2012-10-23 Stefan Monnier - - * mh-letter.el (mh-yank-hooks): Use make-obsolete-variable. - -2012-04-25 Stefan Monnier - - * mh-utils.el (minibuffer-completing-file-name): Don't declare, unused. - -2012-04-21 Juanma Barranquero - - * mh-folder.el (top): Check whether which-func-modes is t before - adding mh-folder-mode. - -2011-11-20 Bill Wohler - - * Release MH-E version 8.3.1. - - * mh-e.el (Version, mh-version): Update for release 8.3.1. - -2011-11-20 Juanma Barranquero - - * mh-utils.el (mh-folder-list): Fix typo. - (mh-children-p): Move part of the docstring to a comment. - -2011-11-16 Juanma Barranquero - - * mh-search.el (mh-pick-parse-search-buffer): Fix typo. - -2011-09-20 Bill Wohler - - Release MH-E version 8.3. - - * mh-e.el (Version, mh-version): Update for release 8.3. - -2011-07-30 Bill Wohler - - * mh-show.el (mh-unvisit-file): Clarify language in yes-or-no-p - and error messages. - -2011-07-17 Bill Wohler - - Release MH-E version 8.2.93. - - * mh-e.el (Version, mh-version): Update for release 8.2.93. - - * mh-compat.el (mh-pop-to-buffer-same-window): Delete. - * mh-folder.el (mh-inc-folder, mh-modify, mh-scan-folder) - (mh-make-folder): Revert to switch-to-buffer, as the Emacs folks - decided that it was fine to use it in programs. - -2011-07-16 Bill Wohler - - Release MH-E version 8.2.92. - - * mh-e.el (Version, mh-version): Update for release 8.2.92. - -2011-07-12 Bill Wohler - - Release MH-E version 8.2.91. - - * mh-e.el (Version, mh-version): Update for release 8.2.91. - - * mh-compat.el (mh-pop-to-buffer-same-window): Add compatibility - function to call switch-to-buffer on systems that lack - pop-to-buffer-same-window. - * mh-folder.el (mh-inc-folder, mh-modify, mh-scan-folder) - (mh-make-folder): Call mh-pop-to-buffer-same-window instead of - switch-to-buffer. The previous change which used pop-to-buffer - produced the wrong behavior. - -2011-07-12 Henrique Martins (tiny change) - - * mh-xface.el (mh-picon-get-image): Remove quote from block - argument. - * mh-mime.el (mh-mh-directive-present-p): Ditto. - -2011-07-10 Bill Wohler - - Release MH-E version 8.2.90. - - * mh-e.el (Version, mh-version): Update for release 8.2.90. - - * mh-utils.el (mh-sub-folders-actual): Remove FIXME question. - - * mh-mime.el (mh-decode-message-subject): Fix case of Subject. - - * mh-folder.el (mh-inc-folder, mh-modify, mh-scan-folder) - (mh-make-folder): Replace calls to switch-to-buffer with of - pop-to-buffer. The former is intended for interactive use only - and generates warnings in Emacs 24. - -2011-07-09 Bill Wohler - - * mh-speed.el (mh-speed-toggle, mh-speed-view): Document "ignored" - arguments to keep checkdoc happy. - - * mh-search.el (mh-flists-execute): Ditto. - - * mh-funcs.el (mh-undo-folder): Ditto. - - * mh-comp.el (mh-user-agent-compose): Ditto. - - * mh-xface.el (mh-face-to-png, mh-uncompface) - (mh-picon-file-contents): Only call set-buffer-multibyte if it - exists, which it doesn't in XEmacs. - -2011-07-04 Bill Wohler - - * mh-e.el: Just require mh-loaddefs since loading it in an - eval-and-compile block causes compilation errors in XEmacs. - - * mh-acros.el, mh-comp.el, mh-e.el, mh-folder.el, mh-letter.el: - * mh-mime.el, mh-search.el, mh-seq.el: Shush XEmacs compiler in - mh-do-in-xemacs block. - - * mh-compat.el (mh-window-full-height-p): Add compatibility - function for XEmacs. - * mh-show.el (mh-show-msg): Use it, and avoid compiler warning on - XEmacs. - - * mh-letter.el (mh-letter-mode-map, mh-letter-complete) - (mh-complete-word): Remove FIXME comments since these functions - are still needed in other Emacsen. However, they can probably - stand to be generalized like completion-at-point. - (mh-letter-complete-or-space): Remove unused variable. - -2011-07-03 Bill Wohler - - * mh-compat.el (mh-test-completion): Add compatibility function - for XEmacs. - * mh-alias.el (mh-alias-letter-expand-alias): Use it, and avoid - compiler warning on XEmacs. - - * mh-utils.el: - * mh-mime.el: Shush XEmacs compiler in mh-do-in-xemacs block. - - * mh-folder.el: Use boundp instead of fboundp when testing - existence of desktop-buffer-mode-handlers (closes SF #1510145). - -2011-05-10 Jim Meyering - - Fix doubled-word typos. - * mh-alias.el (mh-alias-minibuffer-confirm-address): - * mh-scan.el (mh-scan-destination-width): Fix typos. - -2011-04-28 Stefan Monnier - - * mh-utils.el (mh-folder-completion-function): Make it work like - file-name completion, so partial-completion can do its job. - - * mh-letter.el (mh-letter-completion-at-point): New function, extracted - from mh-letter-complete - (mh-letter-mode, mh-letter-complete, mh-letter-complete-or-space): - Use it. - (mh-complete-word): Only use the common-substring arg when it works. - (mh-folder-expand-at-point): - * mh-alias.el (mh-alias-letter-expand-alias): Return data suitable for - completion-at-point-functions. - -2011-04-06 Juanma Barranquero - - * mh-funcs.el (mh-undo-folder): Accept and ignore arguments, - for compatibility with `revert-buffer'. Doc fix. (Bug#8431) - -2011-03-07 Chong Yidong - - * Version 23.3 released. - -2011-03-05 Antoine Levitt - - * mh-funcs.el (mh-store-msg, mh-store-buffer): - * mh-mime.el (mh-mime-save-parts): Use read-directory-name. - -2011-01-13 Chong Yidong - - * mh-comp.el (mh-user-agent-compose): New arg RETURN-ACTION. - -2010-11-07 Glenn Morris - - * mh-seq.el (mh-read-msg-list): Use point-at-eol. - -2010-11-03 Glenn Morris - - * mh-mime.el (dots, type, ov): Avoid unnecessary declaration. - -2010-05-14 Peter S Galbraith - - * mh-mime.el (mh-decode-message-subject): New function to decode - RFC2047 encoded Subject lines. Used for reply drafts. - * mh-comp.el (mh-compose-and-send-mail): - Call `mh-decode-message-subject' on (reply or forward) message drafts. - -2010-05-07 Chong Yidong - - * Version 23.2 released. - -2010-05-03 Stefan Monnier - - * mh-show.el (mh-showing-mode): Move function to mh-e.el. - * mh-e.el (mh-showing-mode): Use define-minor-mode. - -2010-03-24 Juanma Barranquero - - * mh-scan.el (mh-scan-cmd-note-width): Doc fix. - (mh-scan-format-mh, mh-scan-body-regexp, mh-scan-cur-msg-number-regexp) - (mh-scan-cur-msg-number-regexp, mh-scan-date-regexp) - (mh-scan-deleted-msg-regexp, mh-scan-good-msg-regexp) - (mh-scan-msg-format-regexp, mh-scan-msg-format-string) - (mh-scan-msg-number-regexp, mh-scan-rcpt-regexp) - (mh-scan-refiled-msg-regexp, mh-scan-sent-to-me-sender-regexp) - (mh-scan-subject-regexp, mh-update-scan-format) - (mh-msg-num-width-to-column): Fix typos in docstrings. - -2010-03-10 Chong Yidong - - * Branch for 23.2. - -2009-12-01 Bill Wohler - - * mh-search.el (mh-mairix-execute-search): Use mh vfolder_format. - Fix typo in database path. - (mh-namazu-execute-search): Specify -q in example since namazu is - excessively garrulous. - -2009-11-05 Stefan Monnier - - * mh-thread.el (mh-thread-set-tables): - * mh-speed.el (mh-folder-speedbar-menu-items, mh-speed-stealth-update) - (mh-speed-extract-folder-name, mh-speed-parse-flists-output) - (mh-speed-invalidate-map, mh-speed-add-folder): - * mh-show.el (mh-invalidate-show-buffer, mh-show-sequence-menu): - * mh-seq.el (mh-list-sequences): - * mh-search.el (mh-index-execute-commands, mh-index-add-to-sequence) - (mh-index-delete-from-sequence, mh-index-update-maps): - * mh-scan.el (mh-msg-num-width): - * mh-print.el (mh-ps-spool-buffer): - * mh-mime.el (mh-mime-save-parts, mh-handle-set-external-undisplayer) - (mh-file-mime-type): - * mh-letter.el (mh-yank-cur-msg): - * mh-funcs.el (mh-list-folders, mh-pipe-msg, mh-store-msg) - (mh-store-buffer): - * mh-folder.el (mh-modify, mh-visit-folder, mh-write-msg-to-file) - (mh-prompt-for-refile-folder): - * mh-e.el (mh-exec-cmd, mh-exec-cmd-error, mh-exec-cmd-daemon) - (mh-handle-process-error, mh-variant-info): - * mh-comp.el (mh-forward): - * mh-alias.el (mh-alias-local-users, mh-alias-which-file-has-alias) - (mh-alias-add-alias-to-file): Use with-current-buffer (closes SF - #1903293). - -2009-11-04 Stefan Monnier - - * mh-e.el: Load mh-loaddefs during compilation as well. - -2009-11-04 Juanma Barranquero - - * mh-e.el (mh-loaddefs): Load rather than require. - -2009-10-06 Glenn Morris - - * mh-show.el (mh-show-msg): Use window-full-height-p. - -2009-08-28 Stefan Monnier - - * mh-comp.el (mh-send-letter): default-buffer-file-coding-system - => (default-value 'buffer-file-coding-system). - -2009-08-10 Bill Wohler - - * mh-junk.el (mh-spamassassin-blacklist, mh-bogofilter-blacklist) - (mh-spamprobe-blacklist): Sync docstring with manual. - -2009-07-22 Kevin Ryde - - * mh-junk.el (mh-spamassassin-blacklist, mh-bogofilter-blacklist) - (mh-spamprobe-blacklist): Hyperlink URLs in docstrings with URL `...'. - -2009-06-13 Bill Wohler - - Release MH-E version 8.2. - - * mh-e.el (Version, mh-version): Update for release 8.2. - - * mh-seq.el (mh-folder-size-flist) - * mh-speed.el (mh-speed-parse-flists-output) - * mh-xface.el (mh-face-display-function): Remove trailing space. - -2009-03-13 D. Goel - - * mh-seq.el (mh-folder-size-flist): Use (values-list) in m-v call - to list. - - * mh-speed.el (mh-speed-parse-flists-output): Ditto. - * mh-xface.el (mh-face-display-function): Ditto. - * mh-search.el (mh-index-parse-search-regexp): Ditto. - - * mh-thread.el (mh-thread-generate): Ditto. - - * mh-seq.el (mh-parse-flist-output-line): Return list rather than values. - We want to avoid emacs using m-v facilities. - (mh-folder-size-folder): Ditto. - (mh-parse-flist-output-line): Ditto. - * mh-thread.el (mh-thread-prune-subject): Ditto. - * mh-xface.el (mh-picon-get-image): Ditto. - (mh-picon-file-contents): Ditto. - * mh-search.el (mh-index-evaluate): Ditto. - -2009-01-27 Bill Wohler - - * mh-funcs.el (mh-pack-folder): Fix docstring. - - * mh-e.el (mh-pack-folder-hook): Bump package-version to 8.2. - - * mh-gnus.el (mh-mm-merge-handles) - (mh-mm-set-handle-multipart-parameter, mh-mm-inline-text-vcard) - (mh-mml-minibuffer-read-disposition, mh-mm-save-part): Update with - code from Gnus 5.11 (closes SF #2235022). - -2009-01-26 Stephen Gildea - - * mh-e.el (mh-pack-folder-hook): New variable. - * mh-funcs.el (mh-pack-folder): Call new mh-pack-folder-hook. - -2009-01-26 Bill Wohler - - * mh-utils.el (mh-goto-header-end): Use mh-mail-header-separator - instead of -* in regexp. - - * mh-folder.el (mh-folder-mode-help-messages): Add e and t to K's - help. - -2009-01-09 Glenn Morris - - * mh-letter.el: Replace last-input-char with last-input-event. - -2008-08-18 Bill Wohler - - Release MH-E version 8.1. - - * mh-e.el (Version, mh-version): Update for release 8.1. - -2008-08-11 Bill Wohler - - * mh-e.el (mh-variant-mh-info, mh-variant-nmh-info) - (mh-variant-set-variant, mh-variant-p, mh-profile-component) - (mh-variant-set, mh-variant, mh-scan-format-file): Fix typo in - docstring. - - * mh-comp.el (mh-reply) - * mh-e.el (mh-sys-path, mh-variant-info, mh-variant-mu-mh-info) - (mh-variant-p, mh-profile-component, mh-variant-set, mh-variant) - (mh-scan-format-file) - * mh-folder.el (mh-regenerate-headers) - * mh-scan.el (mh-scan-format) - * mh-search.el (mh-pick-regexp-builder): Rename variant mu-mh to - gnu-mh and be explicit about GNU mailutils MH in docstrings (with - thanks to Darel Henman) (closes SF #1768928). - -2008-08-01 Bill Wohler - - * mh-show.el (mh-show-preferred-alternative) - * mh-e.el (mh-annotate-msg-hook): Sync docstring with manual. - - * mh-comp.el (mh-send-letter, mh-redistribute): - Mention mh-annotate-msg-hook in docstring. - -2008-06-29 Jeffrey C Honig - - * mh-e.el (mh-invisible-header-fields-internal): Add invisible - header fields for X-Hz (mail from Hertz), X-Proofpoint (Proofpoint - antivirus/anti-spam) and X-RIM (Research In Motion). - -2008-06-20 Stephen Eglen - - * mh-show.el (mh-defun-show-buffer): Use `...' rather than - "..." in generated docstrings. - -2008-06-12 Glenn Morris - - * mh-seq.el (tool-bar-map): Define for compiler. - - * mh-folder.el (mh-folder-mode): - * mh-letter.el (mh-letter-mode): - * mh-show.el (mh-show-mode): Check tool-bar-map is bound. - -2008-06-08 John Paul Wallington - - * mh-acros.el (toplevel): Put `doc-string-elt' properties on - `defun-mh' and `defmacro-mh'. - - * mh-alias.el (mh-alias-read-address-map): Define within defvar. - - * mh-comp.el (mh-letter-mode-syntax-table): Define within defvar. - - * mh-letter.el (mh-complete-word): Doc fix. - -2008-06-02 John Paul Wallington - - * mh-e.el (mh-exec-cmd-env-daemon): Doc fix. - -2008-06-01 John Paul Wallington - - * mh-e.el (mh-path, mh-variant): Use dotted syntax for - `package-version' info. - -2008-05-26 Jeffrey C Honig - - * mh-e.el (mh-invisible-header-fields-internal): Remove Newsgroups - from the list. Add Bytes, X-Campaignid, X-Country-Chain, - X-Declude-, X-fmx-, X-Identity, X-Mailer_, X-pair-, X-SPF-, - X-Usenet-Provider. - -2008-05-23 Bill Wohler - - * mh-e.el (mh-invisible-header-fields-internal): - Remove DKIM-Signature as it is covered by DKIM-. Fully qualify X-EID. - -2008-05-19 Sergey Poznyakoff - - * mh-mime.el (mh-mh-to-mime, mh-mh-to-mime-undo): Preserve modes - when converting to or from MIME (closes SF #1966722). - -2008-05-19 Bill Wohler - - * mh-e.el (mh-invisible-header-fields-internal): Sort list in a - case-insensitive way and add comment about it. Add many header - fields (closes SF #1916032). - -2008-05-19 Xavier Maillard (tiny change) - - * mh-utils.el (mh-find-path): Don't throw error if MH environment - variable is being used (closes SF #1946861). - -2008-05-19 Nick Dokos (tiny change) - - * mh-search.el (mh-mairix-regexp-builder): Add additional items to - search string to support org-mode (closes SF #1965704). - -2008-03-18 Bill Wohler - - * mh-e.el (mh-invisible-header-fields-internal): Add Accreditor, - Seal-Send-Time. - (mh-invisible-header-fields, mh-invisible-header-fields-default): - Update URL to bug report for users to report ignored fields. - -2008-03-12 Stefan Monnier - - * mh-xface.el (mh-uncompface, mh-picon-file-contents): - Use set-buffer-multibyte... - (mh-face-display-function, mh-x-image-display): ...rather than bind - default-enable-multibyte-characters. - -2008-02-24 Bill Wohler - - * mh-comp.el (mh-send-letter): Call split-string on mh-send-args - when sending synchronously too. - -2008-02-19 Bill Wohler - - * mh-comp.el (mh-annotate-msg): - * mh-e.el (mh-invisible-header-fields-internal): Remove trailing - whitespace. - -2008-01-30 Bill Wohler - - * mh-mime.el (mh-mml-to-mime): Don't look up sender if From - absent. Fixes "Wrong type argument: stringp, nil" error. - -2007-12-02 Glenn Morris - - * mh-mime.el (mail-strip-quoted-names): Autoload it. - -2007-11-17 Dan Nicolaescu - - * mh-e.el (mh-xemacs-flag): Remove. - (mh-min-colors-defined-flag): - * mh-xface.el (mh-show-xface-function): - * mh-utils.el (mh-colors-available-p): - * mh-show.el (mh-show-mode): - * mh-gnus.el (mh-gnus-local-map-property): - * mh-folder.el (mh-folder-mode-map) - (mh-remove-xemacs-horizontal-scrollbar, mh-folder-mode): - * mh-comp.el (mh-insert-x-mailer): Replace uses of mh-xemacs-flag - with (featurep 'xemacs). - -2007-09-11 Bill Wohler - - * mh-e.el (Version, mh-version): Add +cvs to version. - -2007-08-25 Stephen Gildea - - * mh-e.el (mh-annotate-msg-hook): New variable. - - * mh-comp.el (mh-annotate-msg): Call new mh-annotate-msg-hook. - (mh-annotate-list): New variable, for mh-annotate-msg-hook. - -2007-08-21 Jeffrey C Honig - - * mh-folder.el (mh-folder-message-menu, mh-folder-mode-map): - Add folder mode support for mh-show-preferred-alternative (closes SF - #1777321). - - * mh-show.el (mh-show-preferred-alternative) - (mh-show-write-message-to-file, mh-show-message-menu) - (mh-show-mode-map): Add mh-show-preferred-alternative (bound to - ":") which will show the message's preferred alternative - overriding the users configured preference. Useful for showing - HTML when text content is lacking (closes SF #1777321). - - * mh-e.el: - (mh-invisible-header-fields-internal): Exclude Fax and Phone. - Put known exclusions as comments before the list and move parens to - separate lines to aid in sorting (closes SF #1701231). - - * mh-mime.el (mm-decode-body): Remove explicit autoload of - mh-alias-expand. - - * mh-alias.el (mh-alias-expand): Set up automatic autoload of - mh-alias-expand. - -2007-08-20 Jeffrey C Honig - - * mh-mime.el (message-options-set): Add missing autoloads from my - last change. - - * mh-comp.el (mh-forward): When forwarding with mml, messages are - no longer included in reverse order (closes SF #1730393). - - * mh-mime.el (mh-mml-forward-message): Forward messages as inline - attachments (closes SF #1378993). - -2008-02-06 Richard Stallman - - * mh-seq.el (mh-make-seq, mh-seq-name): Use defsubst. - - * mh-acros.el (mh-do-in-gnu-emacs, mh-do-in-xemacs) - (with-mh-folder-updating, mh-in-show-buffer) - (mh-iterate-on-messages-in-region, mh-iterate-on-range) - (mh-do-at-event-location): Add debug decls. - (mh-seq-msgs): Use defsubst. - -2008-02-05 Juanma Barranquero - - * mh-e.el (mh-scan-format-file-check, mh-adaptive-cmd-note-flag-check): - * mh-xface.el (mh-x-image-url-cache-canonicalize): - Replace `legal' with `valid'. - -2007-08-19 Jeffrey C Honig - - * mh-e.el (mh-invisible-header-fields-internal): We want to show - Comments: and hide Comment:, not the other way around. - - * mh-mime.el (mh-mml-to-mime): GPG requires e-mail addresses, not - aliases. So resolve aliases before passing addresses to GPG/PGP - (closes SF #649226). - - * mh-e.el (mh-invisible-header-fields-internal): Update with all - the entries from - http://people.dsv.su.se/~jpalme/ietf/mail-headers, plus some of my - own. I added attributions to entries we already had that did not - list an RFC. - -2007-08-08 Glenn Morris - - * mh-folder.el, mh-letter.el, mh-show.el: Replace `iff' in - doc-strings and comments. - -2007-07-25 Glenn Morris - - * Relicense all FSF files to GPLv3 or later. - -2007-07-11 Bill Wohler - - * mh-compat.el (mh-display-color-cells): Fix on XEmacs 21.5b28. - Thanks to Henrique Martins for the help (closes SF #1749774). - -2007-06-06 Juanma Barranquero - - * mh-mime.el (mh-mh-directive-present-p): - * mh-search.el (mh-index-group-by-folder): Fix typos in docstrings. - -2006-11-14 Bill Wohler - - * mh-xface.el (mh-x-image-url-cache-canonicalize): Add `*' to - reserved Windows filename characters (closes SF #1396499). - -2006-11-13 Bill Wohler - - Release MH-E version 8.0.3. - - * mh-e.el (Version, mh-version): Update for release 8.0.3. - - * mh-e.el (mh-alias-local-users): Boolean docstrings should start - with "Non-nil means". Perhaps this option should have a -flag - appended. - (mh-junk-background): Sync docstring with manual. - - * mh-junk.el (mh-spamassassin-blacklist, mh-bogofilter-blacklist) - (mh-spamprobe-blacklist): Sync docstring with manual. - -2006-11-11 Stephen Gildea - - * mh-junk.el (mh-spamassassin-blacklist, mh-spamassassin-whitelist): - Use mh-junk-background consistently in call-process calls. - (mh-bogofilter-blacklist, mh-bogofilter-whitelist) - (mh-spamprobe-blacklist, mh-spamprobe-whitelist): - Use with-current-buffer so the right thing happens if - mh-junk-background is t (closes SF #1594802). - - * mh-e.el (mh-junk-background): Document that On value is 0; - t may be used for debugging. - -2006-11-10 Andreas Schwab - - * mh-e.el (mh-draft-folder): Avoid starting sentence with "nil". - -2006-11-10 Glenn Morris - - * mh-e.el (mh-draft-folder): Doc fix (Nil -> nil). - -2006-09-25 Stephen Gildea - - * mh-junk.el (mh-spamassassin-whitelist): Add two missing - quotation marks, so that the last two arguments of sa-learn - are separated properly (closes SF #1565460). - (mh-spamassassin-blacklist): In example .procmailrc, add - PATH element to find mhparam on Debian. - -2006-09-24 Stephen Gildea - - * mh-comp.el (mh-send-args): Initialize to "" instead of nil - so that we always have a valid string for split-string even if - nothing is added in mh-send-letter (closes SF #1564742). - -2006-07-03 Bill Wohler - - Release MH-E version 8.0.2. - - * mh-e.el (Version, mh-version): Update for release 8.0.2. - -2006-07-03 Ted Phelps (tiny change) - - * mh-tool-bar.el (mh-tool-bar-define): Fix XEmacs' vector-list so - it refers to the icons in mh-xemacs-icon-map instead of trying to - declare the icons in situ. This allows mh-tool-bar.el to be - compiled under XEmacs. Remove initial value for - mh-tool-bar-folder-buttons, mh-tool-bar-show-buttons, - mh-tool-bar-letter-buttons. The MH-E icons now appear in XEmacs. - In mh-tool-bar-init, check for mh-xemacs-use-tool-bar-flag sooner. - This allows MH-E to be used in XEmacs in a tty (closes SF #1506846). - -2006-07-03 Bill Wohler - - * mh-e.el: Require mh-buffers and mh-compat before mh-xemacs now - that mh-xemacs needs functions in mh-compat. - -2006-06-29 Bill Wohler - - * mh-search.el (mh-search, mh-index-group-by-folder): Add "the" in - loop construct to be consistent with other loops, and because - edebug doesn't work without it. - -2006-06-29 Ted Phelps (tiny change) - - * mh-search.el (mh-folder-exists-p): Strip + from folder to avoid - redundant +s in regexp (closes SF #1514424). - -2006-06-29 Sergey Poznyakoff (tiny change) - - * mh-mime.el (mh-mime-save-parts): Add -store option to - mhn (closes SF #1513140). - -2006-06-20 Bill Wohler - - Release MH-E version 8.0.1. - - * mh-e.el (Version, mh-version): Update for release 8.0.1. - -2006-06-15 Bill Wohler - - * mh-search.el (mh-index-new-folder): Use -2 suffix instead of <2> - suffix for folder names, as <> are illegal filename characters on - Windows (closes SF #1507002). - -2006-06-05 Jacob Morzinski (tiny change) - - * mh-comp.el (mh-send-uses-spost): New variable. - (mh-send-letter): Do not use -msgid and -mime if - mh-send-uses-spost is t (closes SF #1486726). - -2006-06-02 Bill Wohler - - * mh-search.el (mh-folder-exists-p): Change test from an empty buffer, - to one that contains the actual folder, since GNU mailutils' folder - command displays output if the folder doesn't exist (closes SF - #1499712). - -2006-05-06 Bill Wohler - - Release MH-E version 8.0. - - * mh-e.el (Version, mh-version): Update for release 8.0. - -2006-05-05 Bill Wohler - - * mh-e.el: Update commentary. - -2006-04-28 Bill Wohler - - Release MH-E version 7.95. - - * mh-e.el (Version, mh-version): Update for release 7.95. - -2006-04-26 Eric Ding - - * mh-e.el (mh-invisible-header-fields-internal): Add entry - "X-Provags-ID:". - -2006-04-25 Bill Wohler - - * mh-letter.el (mh-folder-expand-at-point): Fix folder completion. - Folders returned by mh-folder-completion-function no longer need - adornment (closes SF #1476270). - -2006-04-21 Bill Wohler - - * mh-e.el (Version, mh-version): Add +cvs to version. - -2006-04-21 Bill Wohler - - Release MH-E version 7.94. - - * mh-e.el (Version, mh-version): Update for release 7.94. - -2006-04-21 Bill Wohler - - * mh-letter.el (mh-insert-letter): If a message number isn't - given, throw an error rather than using a potentially incorrect - message number (closes SF #1473729). In addition, use the cur - message if mh-sent-from-msg is nil (when sending a message, in - contrast to replying). Move conversion of int to string into - interactive stanza so body can assume variables are of proper - type. - -2006-04-20 Bill Wohler - - * mh-tool-bar.el (image-load-path): Define to shush compiler. - (mh-buffer-exists-p): Move inside mh-do-in-gnu-emacs since it - isn't used outside of it. - (mh-tool-bar-folder-buttons-init, mh-tool-bar-letter-buttons-init): - Update load-path/image-load-path before setting buttons. - This code used to be in mh-folder-mode/mh-letter-mode but this was - the wrong place since mh-tool-bar-*-buttons-init can also be called - when customizing the buttons. - (mh-tool-bar-update): New function which updates tool-bar-map in - all of the MH-E buffers after customizing the buttons (closes SF - #1452718). - (mh-tool-bar-folder-buttons-set, mh-tool-bar-letter-buttons-set): - Call it (closes SF #1452718). - - * mh-folder.el (mh-folder-buttons-init-flag): Delete. - Use mh-folder-tool-bar-map instead. - (image-load-path): Delete. No longer used. - (mh-folder-mode): Move setting of image-load-path into - mh-tool-bar-folder-buttons-init. - - * mh-letter.el (mh-letter-buttons-init-flag): Delete. - Use mh-letter-tool-bar-map instead. - (image-load-path): Delete. No longer used. - (mh-letter-mode): Move setting of image-load-path into - mh-tool-bar-letter-buttons-init. - - * mh-seq.el (mh-narrow-to-seq, mh-widen): Use with-current-buffer - instead of set-buffer. - -2006-04-19 Bill Wohler - - * mh-tool-bar.el (mh-tool-bar-define): Fix enable-expr so that one - can permanently disable a button (such as a separator) with nil. - -2006-04-18 Bill Wohler - - * mh-e.el (defcustom-mh, defface-mh, defgroup-mh, mh-face-data) - (mh-strip-package-version, mh-face-data, mh-inherit-face-flag) - (mh-min-colors-defined-flag): Do not unbind these macros and - variables. Nice idea, but too many nasty side-effects. These - macros are needed by [Cc]ustom-make-dependencies when creating the - MH-E customization groups in mh-cus-load.el. These disappeared - when the macros above were introduced. Besides, if a developer - were to try to show the help for a macro or variable they were - looking at and got [No match] when they did so, that would be bad. - -2006-04-17 Bill Wohler - - * mh-comp.el (mh-insert-x-mailer): Strip build number from - version in X-Mailer field (closes SF #1466481). - - * mh-acros.el (mh-defun-compat): Rename to defun-mh in order that - variables and functions with the same name are found correctly by - find-func (invoked by clicking on the filename link in the *Help* - buffer). - (mh-defmacro-compat): Rename to defmacro-mh. Ditto. - - * mh-e.el (mh-defgroup): Rename to defgroup-mh. Ditto. - (mh-defcustom): Rename to defcustom-mh. Ditto. - (mh-defface): Rename to defface-mh. Ditto. - (mh-font-lock-add-keywords): Make changes according to these - renamings. - - * mh-e.el, mh-compat.el, mh-gnus.el: Use the new names (closes SF - #1472029). - - * mh-utils.el (mh-sub-folders-actual): Mention that folder must - have been processed by mh-normalize-folder-name. - (mh-folder-completion-function): Handle completion of folders with - absolute names. Also, when flag is t, display complete folder name - to provide proper highlighting in Emacs 22 now that - minibuffer-completing-file-name is nil (closes SF #1470518). - (mh-folder-completing-read): No longer set - minibuffer-completing-file-name to t. This was causing "Can't set - current directory errors" when browsing absolute file names. - Another benefit of this change is that SPC can be used for - completion again (closes SF #1470518). - -2006-04-15 Bill Wohler - - * mh-compat.el (mh-font-lock-add-keywords): Fix typo in docstring. - -2006-04-14 Bill Wohler - - * mh-funcs.el (view-exit-action): No need to wrap defvar with - eval-when-compile when shushing compiler. - - * mh-mime.el (mh-identity-pgg-default-user-id): Ditto. - - * mh-seq.el (view-exit-action): Ditto. - - * mh-show.el (font-lock-auto-fontify): Ditto. - - * mh-utils.el (mh-speed-flists-cache): Ditto. - - * mh-acros.el (struct, x, y): No need to wrap defvar with - eval-when-compile when shushing compiler, even when - mh-do-in-xemacs or another construct is used. - - * mh-comp.el (sendmail-coding-system): Ditto. - - * mh-e.el (mark-active): Ditto. - - * mh-folder.el (desktop-save-buffer, font-lock-auto-fontify) - (image-load-path, font-lock-defaults): Ditto. - - * mh-letter.el (image-load-path, font-lock-defaults): Ditto. - - * mh-mime.el (dots, type, ov) - (mm-verify-function-alist, mm-decrypt-function-alist) - (pressed-details): Ditto. - - * mh-search.el (pick-folder, mh-do-in-xemacs) - (mh-mairix-folder, mh-flists-search-folders) - (which-func-mode, mh-speed-flists-inhibit-flag): Ditto. - - * mh-seq.el (tool-bar-mode): Ditto. - - * mh-utils.el (completion-root-regexp) - (minibuffer-completing-file-name): Ditto. - - * mh-xface.el (default-enable-multibyte-characters): Ditto. - - * mh-compat.el (mh-font-lock-add-keywords): New alias for - font-lock-add-keywords. Returns nil on XEmacs. - - * mh-e.el: Add MH-E function and variable keywords such as - mh-defun-compat and mh-defcustom to font-lock-keywords. - -2006-04-13 Bill Wohler - - * mh-e.el (customize-package-emacs-version-alist) - (mh-e, mh-alias, mh-folder, mh-folder-selection) - (mh-identity, mh-inc, mh-junk, mh-letter, mh-ranges) - (mh-scan-line-formats, mh-search, mh-sending-mail) - (mh-sequences, mh-show, mh-speedbar, mh-thread, mh-tool-bar) - (mh-hooks, mh-faces, mh-alias-completion-ignore-case-flag) - (mh-alias-expand-aliases-flag, mh-alias-flash-on-comma) - (mh-alias-insert-file, mh-alias-insertion-location) - (mh-alias-local-users, mh-alias-local-users-prefix) - (mh-alias-passwd-gecos-comma-separator-flag) - (mh-new-messages-folders, mh-ticked-messages-folders) - (mh-large-folder, mh-recenter-summary-flag) - (mh-recursive-folders-flag, mh-sortm-args) - (mh-default-folder-for-message-function) - (mh-default-folder-list, mh-default-folder-must-exist-flag) - (mh-default-folder-prefix, mh-identity-list) - (mh-auto-fields-list, mh-auto-fields-prompt-flag) - (mh-identity-default, mh-identity-handlers, mh-inc-prog) - (mh-inc-spool-list, mh-junk-background, mh-junk-disposition) - (mh-junk-program, mh-compose-insertion) - (mh-compose-skipped-header-fields) - (mh-compose-space-does-completion-flag) - (mh-delete-yanked-msg-window-flag) - (mh-extract-from-attribution-verb, mh-ins-buf-prefix) - (mh-letter-complete-function, mh-letter-fill-column) - (mh-mml-method-default, mh-signature-file-name) - (mh-signature-separator-flag, mh-x-face-file) - (mh-yank-behavior, mh-interpret-number-as-range-flag) - (mh-adaptive-cmd-note-flag, mh-scan-format-file, mh-scan-prog) - (mh-search-program, mh-compose-forward-as-mime-flag) - (mh-compose-letter-function, mh-compose-prompt-flag) - (mh-forward-subject-format, mh-insert-x-mailer-flag) - (mh-redist-full-contents-flag, mh-reply-default-reply-to) - (mh-reply-show-message-flag) - (mh-refile-preserves-sequences-flag, mh-tick-seq) - (mh-update-sequences-after-mh-show-flag) - (mh-bury-show-buffer-flag, mh-clean-message-header-flag) - (mh-decode-mime-flag) - (mh-display-buttons-for-alternatives-flag) - (mh-display-buttons-for-inline-parts-flag) - (mh-do-not-confirm-flag, mh-fetch-x-image-url) - (mh-graphical-smileys-flag, mh-graphical-emphasis-flag) - (mh-highlight-citation-style, mh-invisible-header-fields) - (mh-invisible-header-fields-default, mh-lpr-command-format) - (mh-max-inline-image-height, mh-max-inline-image-width) - (mh-mhl-format-file, mh-mime-save-parts-default-directory) - (mh-print-background-flag, mh-show-maximum-size) - (mh-show-use-xface-flag, mh-store-default-directory) - (mh-summary-height, mh-speed-update-interval) - (mh-show-threads-flag, mh-tool-bar-search-function) - (mh-defcustom, mh-after-commands-processed-hook) - (mh-alias-reloaded-hook, mh-before-commands-processed-hook) - (mh-before-quit-hook, mh-before-send-letter-hook) - (mh-delete-msg-hook, mh-find-path-hook, mh-folder-mode-hook) - (mh-forward-hook, mh-inc-folder-hook, mh-insert-signature-hook) - (mh-kill-folder-suppress-prompt-hooks, mh-letter-mode-hook) - (mh-mh-to-mime-hook, mh-search-mode-hook, mh-quit-hook) - (mh-refile-msg-hook, mh-show-hook, mh-show-mode-hook) - (mh-unseen-updated-hook, mh-folder-address, mh-folder-body) - (mh-folder-cur-msg-number, mh-folder-date, mh-folder-deleted) - (mh-folder-followup, mh-folder-msg-number, mh-folder-refiled) - (mh-folder-sent-to-me-hint, mh-folder-sent-to-me-sender) - (mh-folder-subject, mh-folder-tick, mh-folder-to) - (mh-letter-header-field, mh-search-folder, mh-show-cc) - (mh-show-date, mh-show-from, mh-show-header, mh-show-pgg-bad) - (mh-show-pgg-good, mh-show-pgg-unknown, mh-show-signature) - (mh-show-subject, mh-show-to, mh-show-xface) - (mh-speedbar-folder, mh-speedbar-folder-with-unseen-messages) - (mh-speedbar-selected-folder) - (mh-speedbar-selected-folder-with-unseen-messages): Use dotted - notation in :package-version keyword. - -2006-04-07 Bill Wohler - - * mh-e.el (mh-path, mh-variant): Define with mh-defcustom and add - :package-version keyword. - -2006-03-31 Bill Wohler - - * mh-e.el (mh-strip-package-version): Move before use to avoid - compiler error. Make macro, also to avoid compiler error. - (mh-defface-compat): Incorporate body into mh-face-data and - delete. - -2006-03-30 Bill Wohler - - * mh-e.el (mh-defcustom, mh-defface, mh-defgroup): Macros to - remove new :package-version keyword in older settings. - (customize-package-emacs-version-alist): Add MH-E version to Emacs - version mappings. - (mh-e, mh-alias, mh-folder, mh-folder-selection) - (mh-identity, mh-inc, mh-junk, mh-letter, mh-ranges) - (mh-scan-line-formats, mh-search, mh-sending-mail) - (mh-sequences, mh-show, mh-speedbar, mh-thread, mh-tool-bar) - (mh-hooks, mh-faces): Add :package-version keyword to these - groups (closes SF #1452724). - (mh-alias-completion-ignore-case-flag) - (mh-alias-expand-aliases-flag, mh-alias-flash-on-comma) - (mh-alias-insert-file, mh-alias-insertion-location) - (mh-alias-local-users, mh-alias-local-users-prefix) - (mh-alias-passwd-gecos-comma-separator-flag) - (mh-new-messages-folders, mh-ticked-messages-folders) - (mh-large-folder, mh-recenter-summary-flag) - (mh-recursive-folders-flag, mh-sortm-args) - (mh-default-folder-for-message-function) - (mh-default-folder-list, mh-default-folder-must-exist-flag) - (mh-default-folder-prefix, mh-identity-list) - (mh-auto-fields-list, mh-auto-fields-prompt-flag) - (mh-identity-default, mh-identity-handlers, mh-inc-prog) - (mh-inc-spool-list, mh-junk-background, mh-junk-disposition) - (mh-junk-program, mh-compose-insertion) - (mh-compose-skipped-header-fields) - (mh-compose-space-does-completion-flag) - (mh-delete-yanked-msg-window-flag) - (mh-extract-from-attribution-verb, mh-ins-buf-prefix) - (mh-letter-complete-function, mh-letter-fill-column) - (mh-mml-method-default, mh-signature-file-name) - (mh-signature-separator-flag, mh-x-face-file) - (mh-yank-behavior, mh-interpret-number-as-range-flag) - (mh-adaptive-cmd-note-flag, mh-scan-format-file, mh-scan-prog) - (mh-search-program, mh-compose-forward-as-mime-flag) - (mh-compose-letter-function, mh-compose-prompt-flag) - (mh-forward-subject-format, mh-insert-x-mailer-flag) - (mh-redist-full-contents-flag, mh-reply-default-reply-to) - (mh-reply-show-message-flag) - (mh-refile-preserves-sequences-flag, mh-tick-seq) - (mh-update-sequences-after-mh-show-flag) - (mh-bury-show-buffer-flag, mh-clean-message-header-flag) - (mh-decode-mime-flag) - (mh-display-buttons-for-alternatives-flag) - (mh-display-buttons-for-inline-parts-flag) - (mh-do-not-confirm-flag, mh-fetch-x-image-url) - (mh-graphical-smileys-flag, mh-graphical-emphasis-flag) - (mh-highlight-citation-style, mh-invisible-header-fields) - (mh-invisible-header-fields-default, mh-lpr-command-format) - (mh-max-inline-image-height, mh-max-inline-image-width) - (mh-mhl-format-file, mh-mime-save-parts-default-directory) - (mh-print-background-flag, mh-show-maximum-size) - (mh-show-use-xface-flag, mh-store-default-directory) - (mh-summary-height, mh-speed-update-interval) - (mh-show-threads-flag, mh-tool-bar-search-function): - Add :package-version keyword to these options (closes SF #1452724). - (mh-after-commands-processed-hook) - (mh-alias-reloaded-hook, mh-before-commands-processed-hook) - (mh-before-quit-hook, mh-before-send-letter-hook) - (mh-delete-msg-hook, mh-find-path-hook, mh-folder-mode-hook) - (mh-forward-hook, mh-inc-folder-hook) - (mh-insert-signature-hook) - (mh-kill-folder-suppress-prompt-hooks, mh-letter-mode-hook) - (mh-mh-to-mime-hook, mh-search-mode-hook, mh-quit-hook) - (mh-refile-msg-hook, mh-show-hook, mh-show-mode-hook) - (mh-unseen-updated-hook): Add :package-version keyword to these - hooks (closes SF #1452724). - (mh-min-colors-defined-flag) - (mh-folder-address, mh-folder-body, mh-folder-cur-msg-number) - (mh-folder-date, mh-folder-deleted, mh-folder-followup) - (mh-folder-msg-number, mh-folder-refiled) - (mh-folder-sent-to-me-hint, mh-folder-sent-to-me-sender) - (mh-folder-subject, mh-folder-tick, mh-folder-to) - (mh-letter-header-field, mh-search-folder, mh-show-cc) - (mh-show-date, mh-show-from, mh-show-header, mh-show-pgg-bad) - (mh-show-pgg-good, mh-show-pgg-unknown, mh-show-signature) - (mh-show-subject, mh-show-to, mh-show-xface) - (mh-speedbar-folder, mh-speedbar-folder-with-unseen-messages) - (mh-speedbar-selected-folder) - (mh-speedbar-selected-folder-with-unseen-messages): - Add :package-version keyword to these faces (closes SF #1452724). - - * mh-tool-bar.el (mh-tool-bar-define): Add commented-out - :package-version keywords (closes SF #1452724). - -2006-03-28 Bill Wohler - - * mh-tool-bar.el: Use clipboard-kill-region, - clipboard-kill-ring-save, and clipboard-yank instead of undo, - kill-region, and menu-bar-kill-ring-save respectively. - In MH-Letter mode, move save-buffer and mh-fully-kill-draft icons in - front of mh-compose-insertion to be consistent with other mailers, - such as Evolution. In MH-Folder mode, move vanilla reply icon to - the left of the other reply icons. Use mail/inbox icon instead of - mail, next-page instead of page-down, delete instead of close, - mail/move instead of mail/refile, data-save instead of execute, - mail/flag-for-followup instead of highlight, contact instead of - mail/alias, open instead of fld-open, zoom-out instead of widen. - - * mh-folder.el (mh-execute-commands, mh-rescan-folder): - * mh-funcs.el (mh-pack-folder): Sync docstrings with manual. - -2006-03-27 Eric Ding - - * mh-e.el (mh-invisible-header-fields-internal): Add entries - "X-AOL-IP:" and "X-MB-Message-" (AOL WebMail). - -2006-03-19 Bill Wohler - - * mh-comp.el (mh-reply): Sync docstring with manual. - - * mh-compat.el (mh-image-load-path-for-library): Shorten first line in - docstring. - -2006-03-17 Bill Wohler - - * mh-compat.el (mh-image-load-path-for-library): Minor docstring fix. - -2006-03-16 Bill Wohler - - * mh-comp.el (mh-send-letter): Use split-string to break up - mh-send-args (closes SF #1448604). - (mh-compose-and-send-mail): Use run-hook-with-args for - mh-compose-letter-function. - - * mh-e.el (mh-list-to-string-1): Use dolist. - - * mh-compat.el (mh-image-load-path-for-library): Prefer user's images. - -2006-03-15 Bill Wohler - - * mh-compat.el (mh-image-load-path-for-library): Fix example by - not recommending that one binds image-load-path. Just defvar it to - placate compiler and only use it if previously defined. - - * mh-e.el (image-load-path): Don't bind! - - * mh-folder.el (mh-folder-mode): Only use image-load-path if - previously defined. - - * mh-letter.el (mh-letter-mode): Ditto. - - * mh-utils.el (mh-logo-display): Ditto. - -2006-03-14 Bill Wohler - - * mh-compat.el (mh-image-load-path-for-library): - Incorporate changes from image-load-path-for-library, which are: - (image-load-path-for-library): Pass value of path rather than - symbol. Always return list of directories. Guarantee that image - directory comes first. - - * mh-e.el (image-load-path): Define on those Emacsen that lack it - to avoid compile and run-time errors. - - * mh-folder.el (mh-folder-mode): Use new idiom for setting - image-load-path. - - * mh-letter.el (mh-letter-mode): Ditto. - - * mh-utils.el (mh-logo-display): Ditto. - -2006-03-12 Bill Wohler - - * mh-utils.el (mh-folder-list): Fix docstring (closes SF - #1448498). - -2006-03-10 Bill Wohler - - * mh-compat.el (mh-replace-regexp-in-string): Pass the literal - flag to replace-in-string. This was badly needed by - mh-quote-pick-expr in order to properly quote subjects when using - / s on XEmacs (closes SF #1447598). - (mh-image-load-path-for-library): Merged changes from Reiner. - Add no-error argument. If path t, just return directory. - - * mh-e.el (mh-profile-component): Drop `s' from mhparam - -components for Mailutils compatibility (closes SF #1446985). - -2006-03-06 Bill Wohler - - * mh-e.el (Version, mh-version): Add +cvs to version. - -2006-03-05 Satyaki Das - - * mh-search.el (mh-index-update-single-msg): Fix a bug in the - handling of duplicate messages. The test in cond was too strong - and wasn't catching the case where origin-map was nil. - -2006-03-05 Bill Wohler - - Release MH-E version 7.93. - - * mh-e.el (Version, mh-version): Update for release 7.93. - -2006-03-05 Bill Wohler - - * mh-folder.el (mh-folder-mode): Drop 'load-path argument when - calling mh-image-load-path-for-library since this is the default. - - * mh-letter.el (mh-letter-mode): Ditto. - - * mh-utils.el (mh-logo-display): Ditto. - -2006-03-04 Bill Wohler - - * mh-compat.el (mh-image-load-path-for-library): Move here from - mh-utils.el and wrap with mh-defun-compat since this function will - be soon added to image.el. - - * mh-utils.el (mh-image-load-path-for-library): Move to mh-compat.el. - (mh-normalize-folder-name): Add return-nil-if-folder-empty - argument which is useful when calling mh-normalize-folder-name to - process the folder argument for the folders command. - (mh-sub-folders): Use new flag to mh-normalize-folder-name to make - this function more robust. It could too easily list the folders in /. - (mh-folder-list): Fix a couple of problems pointed out by Thomas - Baumann. Set folder to nil if empty. Don't append "/" if folder nil. - -2006-03-03 Bill Wohler - - * mh-folder.el (mh-folder-mode): Rename mh-image-load-path to - mh-image-load-path-for-library. - - * mh-letter.el (mh-letter-mode): Rename mh-image-load-path to - mh-image-load-path-for-library. - - * mh-utils.el (mh-image-load-path): Rename to - mh-image-load-path-for-library. Add example to docstring. Rename - local variable mh-image-directory to image-directory. Move error - checks to default case in cond and simplify. - - * mh-comp.el (mh-send-letter, mh-insert-auto-fields): - Sync docstrings with manual. - -2006-03-02 Bill Wohler - - * mh-folder.el (mh-tool-bar-init): Autoload. - (mh-folder-mode): Call mh-tool-bar-init conditionally in XEmacs. - Set scoped variables image-load-path and load-path with updated - mh-image-load-path before calling mh-tool-bar-folder-buttons-init. - - * mh-letter.el (mh-tool-bar-init): Autoload. - (mh-letter-mode): Call mh-tool-bar-init conditionally in XEmacs. - Set scoped variables image-load-path and load-path with updated - mh-image-load-path before calling mh-tool-bar-letter-buttons-init. - - * mh-show.el (mh-tool-bar-init): Autoload. - (mh-show-mode): Perform tool bar stuff conditionally in XEmacs and - GNU Emacs. - - * mh-tool-bar.el (mh-tool-bar-define): Don't quote stuff in error - messages per conventions. - (mh-tool-bar-folder-buttons-init) - (mh-tool-bar-letter-buttons-init): Don't call mh-image-load-path. - (mh-tool-bar-define call): Format. - - * mh-utils.el (mh-image-directory) - (mh-image-load-path-called-flag): Delete. - (mh-image-load-path): Incorporate changes from Gnus team. - Biggest changes are that it no longer uses/sets mh-image-directory or - mh-image-load-path-called-flag, and returns the updated path - rather than change it. - (mh-logo-display): Change usage of mh-image-load-path. - -2006-02-28 Bill Wohler - - * mh-limit.el (mh-narrow-to-cc, mh-narrow-to-from) - (mh-narrow-to-subject, mh-narrow-to-to): Fix inability to narrow - to subjects with special characters by quoting regular expression - characters in pick expression derived from existing subjects and - other fields (closes SF #1432548). - (mh-narrow-to-subject): Remove Re: string from subject so that - pick can find originating message (closes SF #1438369). - - * mh-utils.el (mh-image-load-path): Rename variable to - mh-image-directory. - (mh-image-load-path): Access mh-image-directory instead of - mh-image-load-path. - (mh-folder-list): Fix problem with passing in a folder and getting - nothing back. Fix problem with passing in empty string and getting - the entire filesystem (or infinite loop). Don't append slash to - folder. These fixes fix problems observed with the pick search. - Thanks to Thomas Baumann for the help (closes SF #1435381). - (mh-pick-regexp-chars, mh-quote-pick-expr): New variable and - function for quoting pick regular expression characters (closes SF - #1432548). - -2006-02-27 Bill Wohler - - * mh-e.el (mh-default-folder-for-message-function): Sync docstring - with manual. - - * mh-mime.el (mh-minibuffer-read-type): Delete comment in - docstring about obsolete variable mh-mime-content-types. - - * mh-e.el (mh-variant): Sync docstring with manual. - (cus-face): Require as it is needed by mh-inherit-face-flag. - - * mh-compat.el (mh-display-color-cells): Return 2 if - device-color-cells returns nil (closes SF #1436924). - - * mh-e.el (mh-compiling-flag): Delete. No longer needed by - mh-display-color-cells. - -2006-02-21 Eric Ding - - * mh-e.el (mh-invisible-header-fields-internal): Add entry - "X-Sasl-enc:". - -2006-02-20 Eric Ding - - * mh-e.el (mh-invisible-header-fields-internal): Add entries - "X-Authenticated-Sender:", "X-Barracuda-", "X-EFL-Spamscore", - "X-IronPort-AV:", "X-Mail-from:", "X-Mailman-Approved-At:", - "X-Resolved-to:", and "X-SA-Exim". Fixed "X-Bugzilla-" and - "X-Roving-" by removing unnecessary "*" at end. - -2006-02-19 Bill Wohler - - * mh-alias.el (mh-address-mail-regexp) - (mh-goto-address-find-address-at-point): Delete copies from - goto-addr.el. - (mh-alias-suggest-alias): Use goto-address-mail-regexp instead of - mh-address-mail-regexp. - (mh-alias-add-address-under-point): - Use goto-address-find-address-at-point instead of - mh-goto-address-find-address-at-point. - - * mh-e.el (mh-show-use-goto-addr-flag): Delete. - - * mh-show.el (mh-show-mode): Mention goto-address-highlight-p in - docstring. - (mh-show-addr): Call goto-address unconditionally. User should use - goto-address-highlight-p instead of mh-show-use-goto-addr-flag. - -2006-02-18 Bill Wohler - - * mh-e.el (Version, mh-version): Add +cvs to version. - -2006-02-18 Bill Wohler - - Release MH-E version 7.92. - - * mh-e.el (Version, mh-version): Update for release 7.92. - -2006-02-17 Bill Wohler - - * mh-e.el (mh-folder-msg-number): Use purple on low-color, light - backgrounds per Mark's suggestion. - - * mh-utils.el (mh-image-load-path): Fix problem that images on - load-path or image-load-path would win over relative paths (newer - MH-E or Emacs distribution). - -2006-02-16 Bill Wohler - - * mh-e.el (mh-inherit-face-flag): New variable. Non-nil means that - the defface :inherit keyword is available. - (mh-face-data): New variable (contains all face specs) and - function (accessor). - (mh-folder-address, mh-folder-body, mh-folder-cur-msg-number) - (mh-folder-date, mh-folder-deleted, mh-folder-followup) - (mh-folder-msg-number, mh-folder-refiled) - (mh-folder-sent-to-me-hint, mh-folder-sent-to-me-sender) - (mh-folder-subject, mh-folder-tick, mh-folder-to) - (mh-search-folder, mh-letter-header-field, mh-show-cc) - (mh-show-date, mh-show-from) - (mh-show-header, mh-show-pgg-bad, mh-show-pgg-good) - (mh-show-pgg-unknown, mh-show-signature, mh-show-subject) - (mh-show-to, mh-show-xface, mh-speedbar-folder) - (mh-speedbar-folder-with-unseen-messages) - (mh-speedbar-selected-folder) - (mh-speedbar-selected-folder-with-unseen-messages): - Use mh-face-data. - - * mh-utils.el (mh-image-load-path): The variables image-load-path - or load-path would not get updated if user set mh-image-load-path. - Moved tests and add-to-list calls outside of cond so they are - applied consistently, even if they are redundant in some - circumstances. Efficiency isn't a concern here. Made error - messages more user-friendly. - -2006-02-15 Peter S Galbraith - - * mh-compat.el (mh-image-search-load-path): Compatibility code. - Emacs 21 and XEmacs don't have `image-search-load-path'. - - * mh-utils.el (mh-image-load-path): Don't bail out on error if the - images are already found. - -2006-02-10 Bill Wohler - - * mh-search.el (mh-search): Wrap code in (block mh-search ...) - rather than use defun*. XEmacs cannot create a proper autoload for - a defun*. - -2006-02-09 Bill Wohler - - * mh-utils.el (mh-folder-list): Don't replace "/*$" with "/" since - that causes an infinite loop on XEmacs. - - * mh-compat.el(mh-replace-regexp-in-string): Add missing regexp - argument. - -2006-02-08 Peter S Galbraith - - * mh-e.el (mh-invisible-header-fields-internal): Add entries - "X-BrightmailFiltered:", "X-Brightmail-Tracker:" and "X-Hashcash". - -2006-02-04 Bill Wohler - - * mh-e.el (mh-inc-spool-list): Update example for Emacs 22 which - has an emacsclient command that supports --eval. I had read that - gnudoit was deprecated in favor of gnuclient anyway. - -2006-02-04 Eric Ding - - * mh-mime.el (mh-file-mime-type-substitutions): Add entries to - handle OpenOffice documents. - -2006-02-03 Bill Wohler - - * mh-e.el (Version, mh-version): Add +cvs to version. - -2006-02-03 Bill Wohler - - Release MH-E version 7.91. - - * mh-e.el (Version, mh-version): Update for release 7.91. - -2006-02-03 Bill Wohler - - * mh-utils.el (mh-image-load-path, mh-image-load-path-called-flag) - (mh-image-load-path): Checkdoc fix. Docstring edits. Reduce scope - of local variable mh-library-name. - - * mh-e.el (mh-folder-msg-number, mh-folder-refiled, mh-folder-to) - (mh-show-cc, mh-show-date, mh-show-header): Replace (min-colors - 88) with (min-colors 64) in face specifications so that MH-E still - looks good on systems with fewer colors (such as Eric Ding's). - -2006-02-03 Peter S Galbraith - - * mh-utils.el (mh-image-load-path): New variable to optionally - hold the directory where MH-E images are stored. If nil, then - the function `mh-image-load-path' will find it. This variable - will be used for Debian packaging. - (mh-image-load-path function): Use variable `mh-image-load-path' - if non-nil and exists. - -2006-02-03 Mark D. Baushke - - * mh-tool-bar.el: Add conditional require of 'tool-bar or 'toolbar - for GNU Emacs or XEmacs to avoid void-variable tool-bar-map lisp - errors if describe-bindings is called before tool-bar-mode is used. - -2006-02-03 Peter S Galbraith - - * mh-compat.el (mh-url-unreserved-chars): Fix typo from - `mh-url-unresrved-chars'. - -2006-02-02 Bill Wohler - - * mh-e.el (Version, mh-version): Add +cvs to version. - -2006-02-02 Bill Wohler - - Release MH-E version 7.90. - - * mh-e.el (Version, mh-version): Update for release 7.90. - -2006-02-01 Bill Wohler - - * mh-search.el (which-func-mode): Shush compiler on Emacs 21 too. - - * mh-alias.el (mh-alias-gecos-name): - Use mh-replace-regexp-in-string instead of replace-regexp-in-string. - (crm, multi-prompt): Use mh-require instead of require. - (mh-goto-address-find-address-at-point): - Use mh-line-beginning-position and mh-line-end-position instead of - line-beginning-position and line-end-position. - Use mh-match-string-no-properties instead of - match-string-no-properties. - - * mh-comp.el (mh-modify-header-field): - Use mh-line-beginning-position and mh-line-end-position instead of - line-beginning-position and line-end-position. - - * mh-compat.el (mailabbrev): Use mh-require instead of require. - (mh-assoc-string, mh-display-completion-list, mh-face-foreground) - (mh-face-background): Make docstring consistent. - (mh-require, mh-cancel-timer, mh-display-color-cells) - (mh-line-beginning-position, mh-line-end-position) - (mh-match-string-no-properties, mh-replace-regexp-in-string) - (mh-view-mode-enter): Move definition here from mh-xemacs.el and - add mh- prefix since compatibility functions should have our - package prefix (mh-) by Emacs convention and to avoid messing up - checks for the same functions in other packages. - - * mh-e.el (mh-compiling-flag): Move mh-xemacs-compiling-flag here - from mh-xemacs.el and rename. - (mh-xargs): Use mh-line-beginning-position and - mh-line-end-position instead of line-beginning-position and - line-end-position. - (mh-defface-compat): Use mh-display-color-cells instead of - display-color-cells. - - * mh-folder.el (which-func): Use mh-require instead of require. - - * mh-funcs.el (mh-list-folders): Use mh-view-mode-enter instead of - view-mode-enter. - - * mh-gnus.el (gnus-util, mm-bodies, mm-decode, mm-view, mml): - Use mh-require instead of require. - - * mh-letter.el (mh-letter-header-end, mh-letter-mode) - (mh-letter-next-header-field): Use mh-line-beginning-position and - mh-line-end-position instead of line-beginning-position and - line-end-position. - - * mh-limit.el (mh-subject-to-sequence-unthreaded): - Use mh-match-string-no-properties instead of - match-string-no-properties. - (mh-narrow-to-header-field): Use mh-line-beginning-position and - mh-line-end-position instead of line-beginning-position and - line-end-position. - - * mh-mime.el (mh-mime-inline-part, mh-mm-display-part) - (mh-mh-quote-unescaped-sharp, mh-mh-directive-present-p): - Use mh-line-beginning-position and mh-line-end-position instead of - line-beginning-position and line-end-position. - - * mh-search.el (which-func): Use mh-require instead of require. - (mh-make-pick-template, mh-index-visit-folder) - (mh-pick-parse-search-buffer, mh-swish-next-result) - (mh-mairix-next-result, mh-namazu-next-result) - (mh-pick-next-result, mh-grep-next-result) - (mh-index-create-imenu-index, mh-index-match-checksum) - (mh-md5sum-parser, mh-openssl-parser, mh-index-update-maps): - Use mh-line-beginning-position and mh-line-end-position instead of - line-beginning-position and line-end-position. - - * mh-seq.el (mh-list-sequences): Use mh-view-mode-enter instead of - view-mode-enter. - (mh-folder-size-flist, mh-parse-flist-output-line) - (mh-add-sequence-notation): Use mh-line-beginning-position and - mh-line-end-position instead of line-beginning-position and - line-end-position. - - * mh-show.el (mh-show-addr): Use mh-require instead of require. - - * mh-speed.el (mh-folder-speedbar-menu-items, mh-speed-toggle) - (mh-speed-view, mh-folder-speedbar-buttons) - (mh-speed-highlight, mh-speed-goto-folder) - (mh-speed-add-buttons, mh-speed-parse-flists-output) - (mh-speed-invalidate-map, mh-speedbar-change-expand-button-char) - (mh-speed-add-folder): Use mh-line-beginning-position and - mh-line-end-position instead of line-beginning-position and - line-end-position. - (mh-speed-flists): Use mh-cancel-timer instead of cancel-timer. - - * mh-thread.el (mh-thread-find-children) - (mh-thread-parse-scan-line, mh-thread-generate): - Use mh-line-beginning-position and mh-line-end-position instead of - line-beginning-position and line-end-position. - - * mh-utils.el (mh-colors-available-p): Use mh-display-color-cells - instead of display-color-cells. - (mh-folder-list): Use mh-replace-regexp-in-string instead of - replace-regexp-in-string. - (mh-sub-folders-actual, mh-letter-toggle-header-field-display): - Use mh-line-beginning-position and mh-line-end-position instead of - line-beginning-position and line-end-position. - - * mh-comp.el (mh-send-sub): Don't find components file in current - directory--this seems to have been a side-effect of commenting out - the use of an old mh-etc variable. Improve error message. - -2006-01-31 Bill Wohler - - * mh-acros.el (mh-defun-compat, mh-defmacro-compat): Add name - argument since compatibility functions should have our package - prefix (mh-) by Emacs convention and to avoid messing up checks - for the same functions in other packages. Use explicit argument - instead of forming name by adding mh- prefix so that one can grep - and find the definition. - - * mh-alias.el (mh-alias-local-users, mh-alias-reload) - (mh-alias-expand, mh-alias-minibuffer-confirm-address): - Use mh-assoc-string instead of assoc-string. - - * mh-compat.el (assoc-string): Rename to mh-assoc-string. - (mh-mail-abbrev-make-syntax-table, mh-url-hexify-string): - Move here from mh-utils.el. - (mh-display-completion-list): Move here from mh-comp.el. - (mh-face-foreground, mh-face-background): Move here from - mh-xface.el. - (mh-write-file-functions): Move here from mh-folder.el. - - * mh-folder.el (mh-write-file-functions-compat): Move to - mh-compat.el and rename to mh-write-file-functions. - (mh-folder-mode): Use the new name. - - * mh-gnus.el (gnus-local-map-property): Rename to - mh-gnus-local-map-property. - (mm-merge-handles): Rename to mh-mm-merge-handles. - (mm-set-handle-multipart-parameter): Rename to - mh-mm-set-handle-multipart-parameter. - (mm-inline-text-vcard): Rename to mh-mm-inline-text-vcard. - (mm-possibly-verify-or-decrypt): Rename to - mh-mm-possibly-verify-or-decrypt. - (mm-handle-multipart-ctl-parameter): Rename to - mh-mm-handle-multipart-ctl-parameter. - (mm-readable-p): Rename to mh-mm-readable-p. - (mm-long-lines-p): Rename to mh-mm-long-lines-p. - (mm-keep-viewer-alive-p): Rename to mh-mm-keep-viewer-alive-p. - (mm-destroy-parts): Rename to mh-mm-destroy-parts. - (mm-uu-dissect-text-parts): Rename to mh-mm-uu-dissect-text-parts. - (mml-minibuffer-read-disposition): Rename to - mh-mml-minibuffer-read-disposition. - - * mh-identity.el (mh-identity-field-handler): Use mh-assoc-string - instead of assoc-string. - - * mh-mime.el (mh-mm-inline-media-tests, mh-mm-inline-message) - (mh-mime-display, mh-mime-display-security) - (mh-insert-mime-button, mh-insert-mime-security-button) - (mh-handle-set-external-undisplayer) - (mh-mime-security-press-button, mh-mime-security-show-details) - (mh-mml-attach-file, mh-mime-cleanup) - (mh-destroy-postponed-handles): Use new mh-* names for - compatibility functions. - - * mh-utils.el (mail-abbrev-make-syntax-table): Move to - mh-compat.el and rename to mh-mail-abbrev-make-syntax-table. - (mh-beginning-of-word): Use the new name. - (mh-get-field): Delete ancient alias. - - * mh-xface.el (mh-face-foreground-compat): Move to mh-compat.el - and rename to mh-face-foreground. - (mh-face-background-compat): Move to mh-compat.el - and rename to mh-face-background. - (mh-face-display-function): Use the new names. - (mh-x-image-url-cache-canonicalize): Use mh-url-hexify-string - instead of url-hexify-string. - (url-unreserved-chars): Move to mh-compat.el and rename to - mh-url-unreserved-chars. - (url-hexify-string): Move to mh-compat.el and rename to - mh-url-hexify-string. - - * mh-letter.el (mh-complete-word): Fix bug in call to - mh-display-completion-list. Wrong argument was passed, so - completions wouldn't show highlighted prefix. - -2006-01-29 Bill Wohler - - * mh-e.el (mh-scan-format-file-check): Allow any non-nil for - mh-adaptive-cmd-note-flag. - - * mh-comp.el (sc-cite-original): Remove autoload of "sc" with old - docstring. sc-cite-original is autoloaded via loaddefs.el for all - supported versions. In addition, the package name "sc" has been - made obsolete by "supercite since at least Emacs 21. - - * mh-scan.el (mh-note-copied, mh-note-printed): Reorganization - revealed character constants that were still strings (closes SF - #770772). - - * mh-comp.el (mh-letter-hide-all-skipped-fields) - (mh-get-header-field): Move to mh-utils.el so that you can read - messages without having to load mh-comp.el and mh-letter.el. - - * mh-letter.el (mh-hidden-header-keymap) - (mh-letter-toggle-header-field-display) - (mh-letter-skipped-header-field-p) - (mh-letter-skip-leading-whitespace-in-header-field) - (mh-letter-truncate-header-field): Move to mh-utils.el so that you - can read messages without having to load mh-comp.el and - mh-letter.el. - - * mh-utils.el (mh-get-header-field) - (mh-letter-hide-all-skipped-fields) - (mh-letter-skipped-header-field-p, mh-hidden-header-keymap) - (mh-letter-toggle-header-field-display) - (mh-letter-skip-leading-whitespace-in-header-field) - (mh-letter-truncate-header-field): Move here from mh-comp.el and - mh-letter.el so that you can read messages without having to load - mh-comp.el and mh-letter.el. - - * mh-comp.el (mh-insert-fields): Handle nil values. Rmail, at - least, will deliver them to us. - - * mh-e.el (mh-after-commands-processed-hook) - (mh-before-commands-processed-hook): Specify what sort of requests - in docstring. - - * mh-folder.el (mh-folder-mode): Use add-to-list to modify - minor-mode-alias. - - * mh-letter.el (mh-letter-menu): Remove. Defvar no longer needed - to shush compiler. - (mh-letter-mode): Remove Mail menu. - -2006-01-29 Bill Wohler - - The Great Cleanup - Remove circular dependencies. mh-e.el now includes few require - statements and stands alone. Other files should need to require - mh-e.el, which requires mh-loaddefs.el, plus variable-only files - such as mh-scan.el. - Remove unneeded require statements. - Remove unneeded load statements, or replace them with non-fatal - require statements. - Break out components into their own files that were often spread - between many files. - As a result, many functions that are now only used within a single - file no longer need to be autoloaded. - Rearrange and provide consistent headings. - Untabify. - - * mh-acros.el: Update commentary to reflect current usage. - Add autoload cookies to all macros. - (mh-require-cl): Merge docstring and comment. - (mh-do-in-xemacs): Fix typo in docstring. - (assoc-string): Move to new file mh-compat.el. - (with-mh-folder-updating, mh-in-show-buffer) - (mh-do-at-event-location, mh-seq-msgs): Move here from mh-utils.el. - (mh-iterate-on-messages-in-region, mh-iterate-on-range): Move here - from mh-seq.el. - - * mh-alias.el (mh-address-mail-regexp) - (mh-goto-address-find-address-at-point): Move here from mh-utils.el. - (mh-folder-line-matches-show-buffer-p): Move here from mh-e.el. - - * mh-buffers.el: Update descriptive text. - - * mh-comp.el (mh-note-repl, mh-note-forw, mh-note-dist): Move to - new file mh-scan.el. - (mh-yank-hooks, mh-to-field-choices, mh-position-on-field) - (mh-letter-menu, mh-letter-mode-help-messages) - (mh-letter-buttons-init-flag, mh-letter-mode) - (mh-font-lock-field-data, mh-letter-header-end) - (mh-auto-fill-for-letter, mh-to-field, mh-to-fcc) - (mh-file-is-vcard-p, mh-insert-signature, mh-check-whom) - (mh-insert-letter, mh-extract-from-attribution, mh-yank-cur-msg) - (mh-filter-out-non-text, mh-insert-prefix-string) - (mh-current-fill-prefix, mh-open-line, mh-complete-word) - (mh-folder-expand-at-point, mh-letter-complete-function-alist) - (mh-letter-complete, mh-letter-complete-or-space) - (mh-letter-confirm-address, mh-letter-header-field-at-point) - (mh-letter-next-header-field-or-indent) - (mh-letter-next-header-field, mh-letter-previous-header-field) - (mh-letter-skipped-header-field-p) - (mh-letter-skip-leading-whitespace-in-header-field) - (mh-hidden-header-keymap) - (mh-letter-toggle-header-field-display-button) - (mh-letter-toggle-header-field-display) - (mh-letter-truncate-header-field, mh-letter-mode-map): Move to new - file mh-letter.el. - (mh-letter-mode-map, mh-sent-from-folder, mh-send-args) - (mh-pgp-support-flag, mh-x-mailer-string) - (mh-letter-header-field-regexp): Move to mh-e.el. - (mh-goto-header-field, mh-goto-header-end) - (mh-extract-from-header-value, mh-beginning-of-word): Move to - mh-utils.el. - (mh-insert-header-separator): Move to mh-comp.el. - (mh-display-completion-list-compat): Move to new file - mh-compat.el. - - * mh-compat.el: New file. - (assoc-string): Move here from mh-acros.el. - (mh-display-completion-list): Move here from mh-comp.el. - - * mh-customize.el: Move content into mh-e.el and remove. - - * mh-e.el (mh-folder-mode-map, mh-folder-seq-tool-bar-map) - (mh-folder-tool-bar-map, mh-inc-spool-map, mh-letter-mode-map) - (mh-letter-tool-bar-map, mh-search-mode-map, mh-show-mode-map) - (mh-show-seq-tool-bar-map, mh-show-tool-bar-map): All maps now - declared here so that they can be used in docstrings. - (mh-sent-from-folder, mh-sent-from-msg) - (mh-letter-header-field-regexp, mh-pgp-support-flag) - (mh-x-mailer-string): Move here from mh-comp.el. - (mh-folder-line-matches-show-buffer-p): Move to mh-alias.el. - (mh-thread-scan-line-map, mh-thread-scan-line-map-stack): - Move here from mh-seq.el. - (mh-draft-folder, mh-inbox, mh-user-path, mh-current-folder) - (mh-previous-window-config, mh-seen-list, mh-seq-list) - (mh-show-buffer, mh-showing-mode, mh-globals-hash) - (mh-show-folder-buffer, mh-mail-header-separator) - (mh-unseen-seq, mh-previous-seq, mh-page-to-next-msg-flag) - (mh-signature-separator, mh-signature-separator-regexp) - (mh-list-to-string, mh-list-to-string-1): Move here from - mh-utils.el. - (mh-index-max-cmdline-args, mh-xargs, mh-quote-for-shell) - (mh-exec-cmd, mh-exec-cmd-error, mh-exec-cmd-daemon) - (mh-exec-cmd-env-daemon, mh-process-daemon, mh-exec-cmd-quiet) - (mh-exec-cmd-output) - (mh-exchange-point-and-mark-preserving-active-mark) - (mh-exec-lib-cmd-output, mh-handle-process-error): Move here from - deprecated file mh-exec.el. - (mh-path): Move here from deprecated file mh-customize.el. - (mh-sys-path, mh-variants, mh-variant-in-use, mh-progs, mh-lib) - (mh-flists-present-flag, mh-variants, mh-variant-mh-info) - (mh-variant-mu-mh-info, mh-variant-nmh-info, mh-file-command-p) - (mh-variant-set-variant, mh-variant-p, mh-profile-component) - (mh-profile-component-value, mh-defface-compat): Move here from - deprecated file mh-init.el. - (mh-goto-next-button, mh-folder-mime-action) - (mh-folder-toggle-mime-part, mh-folder-inline-mime-part) - (mh-folder-save-mime-part, mh-toggle-mime-buttons): Move to to - mh-mime.el. - (mh-scan-format-mh, mh-scan-format-nmh, mh-note-deleted) - (mh-note-refiled, mh-note-cur, mh-scan-good-msg-regexp) - (mh-scan-deleted-msg-regexp, mh-scan-refiled-msg-regexp) - (mh-scan-valid-regexp, mh-scan-cur-msg-number-regexp) - (mh-scan-date-regexp, mh-scan-rcpt-regexp, mh-scan-body-regexp) - (mh-scan-subject-regexp, mh-scan-sent-to-me-sender-regexp) - (mh-scan-cmd-note-width, mh-scan-destination-width) - (mh-scan-date-width, mh-scan-date-flag-width) - (mh-scan-from-mbox-width, mh-scan-from-mbox-sep-width) - (mh-scan-field-destination-offset) - (mh-scan-field-from-start-offset, mh-scan-field-from-end-offset) - (mh-scan-field-subject-start-offset, mh-scan-format) - (mh-msg-num-width-to-column, mh-set-cmd-note): Move to new file - mh-scan.el. - (mh-partial-folder-mode-line-annotation) - (mh-folder-font-lock-keywords, mh-folder-font-lock-subject) - (mh-generate-sequence-font-lock, mh-last-destination) - (mh-last-destination-write, mh-first-msg-num, mh-last-msg-num) - (mh-rmail, mh-nmail, mh-delete-msg, mh-delete-msg-no-motion) - (mh-execute-commands, mh-first-msg, mh-header-display) - (mh-inc-folder, mh-last-msg, mh-next-undeleted-msg) - (mh-folder-from-address, mh-prompt-for-refile-folder) - (mh-refile-msg, mh-refile-or-write-again, mh-quit, mh-page-msg) - (mh-previous-page, mh-previous-undeleted-msg) - (mh-previous-unread-msg, mh-next-button, mh-prev-button) - (mh-reset-threads-and-narrowing, mh-rescan-folder) - (mh-write-msg-to-file, mh-toggle-showing, mh-undo) - (mh-visit-folder, mh-update-sequences, mh-delete-a-msg) - (mh-refile-a-msg, mh-next-msg, mh-next-unread-msg) - (mh-set-scan-mode, mh-undo-msg, mh-make-folder) - (mh-folder-sequence-menu, mh-folder-message-menu) - (mh-folder-folder-menu, mh-remove-xemacs-horizontal-scrollbar) - (mh-write-file-functions-compat, mh-folder-mode) - (mh-restore-desktop-buffer, mh-scan-folder) - (mh-regenerate-headers, mh-generate-new-cmd-note) - (mh-get-new-mail, mh-make-folder-mode-line, mh-goto-cur-msg) - (mh-process-or-undo-commands, mh-process-commands) - (mh-update-unseen, mh-delete-scan-msgs) - (mh-outstanding-commands-p): Move to new file mh-folder.el. - (mh-mapc, mh-colors-available-p, mh-colors-in-use-p) - (mh-make-local-vars, mh-coalesce-msg-list, mh-greaterp) - (mh-lessp): Move to mh-utils.el. - (mh-parse-flist-output-line, mh-folder-size-folder) - (mh-folder-size-flist, mh-folder-size, mh-add-sequence-notation) - (mh-remove-sequence-notation, mh-remove-cur-notation) - (mh-remove-all-notation, mh-delete-seq-locally) - (mh-read-folder-sequences, mh-read-msg-list) - (mh-notate-user-sequences, mh-internal-seqs, mh-internal-seq) - (mh-valid-seq-p, mh-delete-msg-from-seq, mh-catchup) - (mh-delete-a-msg-from-seq, mh-undefine-sequence) - (mh-define-sequence, mh-seq-containing-msg): Move to mh-seq.el. - (mh-xemacs-flag) - (mh-customize, mh-e, mh-alias, mh-folder, mh-folder-selection) - (mh-identity, mh-inc, mh-junk, mh-letter, mh-ranges) - (mh-scan-line-formats, mh-search, mh-sending-mail, mh-sequences) - (mh-show, mh-speedbar, mh-thread, mh-tool-bar, mh-hooks) - (mh-faces, mh-alias-completion-ignore-case-flag) - (mh-alias-expand-aliases-flag, mh-alias-flash-on-comma) - (mh-alias-insert-file, mh-alias-insertion-location) - (mh-alias-local-users, mh-alias-local-users-prefix) - (mh-alias-passwd-gecos-comma-separator-flag) - (mh-new-messages-folders, mh-ticked-messages-folders) - (mh-large-folder, mh-recenter-summary-flag) - (mh-recursive-folders-flag, mh-sortm-args) - (mh-default-folder-for-message-function, mh-default-folder-list) - (mh-default-folder-must-exist-flag, mh-default-folder-prefix) - (mh-identity-list, mh-auto-fields-list) - (mh-auto-fields-prompt-flag, mh-identity-default) - (mh-identity-handlers, mh-inc-prog, mh-inc-spool-list) - (mh-junk-choice, mh-junk-function-alist, mh-junk-choose) - (mh-junk-background, mh-junk-disposition, mh-junk-program) - (mh-compose-insertion, mh-compose-skipped-header-fields) - (mh-compose-space-does-completion-flag) - (mh-delete-yanked-msg-window-flag) - (mh-extract-from-attribution-verb, mh-ins-buf-prefix) - (mh-letter-complete-function, mh-letter-fill-column) - (mh-mml-method-default, mh-signature-file-name) - (mh-signature-separator-flag, mh-x-face-file, mh-yank-behavior) - (mh-interpret-number-as-range-flag, mh-adaptive-cmd-note-flag) - (mh-scan-format-file-check, mh-scan-format-file) - (mh-adaptive-cmd-note-flag-check, mh-scan-prog) - (mh-search-program, mh-compose-forward-as-mime-flag) - (mh-compose-letter-function, mh-compose-prompt-flag) - (mh-forward-subject-format, mh-insert-x-mailer-flag) - (mh-redist-full-contents-flag, mh-reply-default-reply-to) - (mh-reply-show-message-flag, mh-refile-preserves-sequences-flag) - (mh-tick-seq, mh-update-sequences-after-mh-show-flag) - (mh-bury-show-buffer-flag, mh-clean-message-header-flag) - (mh-decode-mime-flag, mh-display-buttons-for-alternatives-flag) - (mh-display-buttons-for-inline-parts-flag) - (mh-do-not-confirm-flag, mh-fetch-x-image-url) - (mh-graphical-smileys-flag, mh-graphical-emphasis-flag) - (mh-highlight-citation-style) - (mh-invisible-header-fields-internal) - (mh-delay-invisible-header-generation-flag) - (mh-invisible-header-fields, mh-invisible-header-fields-default) - (mh-invisible-header-fields-compiled, mh-invisible-headers) - (mh-lpr-command-format, mh-max-inline-image-height) - (mh-max-inline-image-width, mh-mhl-format-file) - (mh-mime-save-parts-default-directory, mh-print-background-flag) - (mh-show-maximum-size, mh-show-use-goto-addr-flag) - (mh-show-use-xface-flag, mh-store-default-directory) - (mh-summary-height, mh-speed-update-interval) - (mh-show-threads-flag, mh-tool-bar-search-function) - (mh-after-commands-processed-hook, mh-alias-reloaded-hook) - (mh-before-commands-processed-hook, mh-before-quit-hook) - (mh-before-send-letter-hook, mh-delete-msg-hook) - (mh-find-path-hook, mh-folder-mode-hook, mh-forward-hook) - (mh-inc-folder-hook, mh-insert-signature-hook) - (mh-kill-folder-suppress-prompt-hooks, mh-letter-mode-hook) - (mh-mh-to-mime-hook, mh-search-mode-hook, mh-quit-hook) - (mh-refile-msg-hook, mh-show-hook, mh-show-mode-hook) - (mh-unseen-updated-hook, mh-min-colors-defined-flag) - (mh-folder-address, mh-folder-body) - (mh-folder-cur-msg-number, mh-folder-date, mh-folder-deleted) - (mh-folder-followup, mh-folder-msg-number, mh-folder-refiled) - (mh-folder-sent-to-me-hint, mh-folder-sent-to-me-sender) - (mh-folder-subject, mh-folder-tick, mh-folder-to) - (mh-search-folder, mh-letter-header-field, mh-show-cc) - (mh-show-date, mh-show-from, mh-show-header, mh-show-pgg-bad) - (mh-show-pgg-good, mh-show-pgg-unknown, mh-show-signature) - (mh-show-subject, mh-show-to, mh-show-xface, mh-speedbar-folder) - (mh-speedbar-folder-with-unseen-messages) - (mh-speedbar-selected-folder) - (mh-speedbar-selected-folder-with-unseen-messages): Move here from - deprecated file mh-customize.el. - - * mh-exec.el: Move content into mh-e.el and remove. - - * mh-folder.el: New file. Contains mh-folder-mode from mh-e.el. - - * mh-funcs.el (mh-note-copied, mh-note-printed): Move to new file - mh-scan.el. - (mh-ephem-message, mh-help, mh-prefix-help): Move to mh-utils.el. - - * mh-gnus.el (mm-uu-dissect-text-parts): Add. - (mh-mail-abbrev-make-syntax-table): Move to mh-utils.el and rename - to mail-abbrev-make-syntax-table. - - * mh-identity.el (mh-identity-menu): New variable for existing - menu. - (mh-identity-make-menu-no-autoload): New alias for - mh-identity-make-menu which can be called from mh-e.el. - (mh-identity-list-set): Move to mh-e.el. - (mh-identity-add-menu): New function. - (mh-insert-identity): Add optional argument maybe-insert so that - local variable mh-identity-local does not have to be visible. - - * mh-inc.el (mh-inc-spool-map): Move declaration to mh-e.el (with - rest of keymaps). Update key binding for ? to call mh-help with - help messages in new argument. - (mh-inc-spool-make-no-autoload): New alias for mh-inc-spool-make - which can be called from mh-e.el. - (mh-inc-spool-list-set): Simplify update of mh-inc-spool-map-help. - - * mh-init.el: Move content into mh-e.el and remove. - - * mh-junk.el: Update requires, untabify, and add mh-autoload - cookies. - - * mh-letter.el: New file. Contains mh-letter-mode from mh-comp.el. - - * mh-limit.el: New file. Contains display limit commands from - mh-mime.el. - - * mh-mime.el: Rearrange for consistency with other files. - (mh-buffer-data, mh-mm-inline-media-tests): Move here from - mh-utils.el. - (mh-folder-inline-mime-part, mh-folder-save-mime-part) - (mh-folder-toggle-mime-part, mh-toggle-mime-buttons) - (mh-goto-next-button): Move here from mh-e.el. - - * mh-print.el: Rearrange for consistency with other files. - - * mh-scan.el: New file. Contains scan line constants and utilities - from XXX, mh-funcs, mh-utils.el. - - * mh-search.el: Rearrange for consistency with other files. - (mh-search-mode-map): Drop C-c C-f {dr} bindings since these - fields which don't exist in the saved header. Replace C-c C-f f - with C-c C-f m per mail-mode consistency. - (mh-search-mode): Use mh-set-help instead of setting - mh-help-messages. - - * mh-seq.el (mh-thread-message, mh-thread-container) - (mh-thread-id-hash, mh-thread-subject-hash, mh-thread-id-table) - (mh-thread-id-index-map, mh-thread-index-id-map) - (mh-thread-scan-line-map, mh-thread-scan-line-map-stack) - (mh-thread-subject-container-hash, mh-thread-duplicates) - (mh-thread-history, mh-thread-body-width) - (mh-thread-find-msg-subject mh-thread-initialize-hash) - (mh-thread-initialize, mh-thread-id-container) - (mh-thread-remove-parent-link, mh-thread-add-link) - (mh-thread-ancestor-p, mh-thread-get-message-container) - (mh-thread-get-message, mh-thread-canonicalize-id) - (mh-thread-prune-subject, mh-thread-container-subject) - (mh-thread-rewind-pruning, mh-thread-prune-containers) - (mh-thread-sort-containers, mh-thread-group-by-subject) - (mh-thread-process-in-reply-to, mh-thread-set-tables) - (mh-thread-update-id-index-maps, mh-thread-generate) - (mh-thread-inc, mh-thread-generate-scan-lines) - (mh-thread-parse-scan-line, mh-thread-update-scan-line-map) - (mh-thread-add-spaces, mh-thread-print-scan-lines) - (mh-thread-folder, mh-toggle-threads, mh-thread-forget-message) - (mh-thread-current-indentation-level, mh-thread-next-sibling) - (mh-thread-previous-sibling, mh-thread-immediate-ancestor) - (mh-thread-ancestor, mh-thread-find-children) - (mh-message-id-regexp, mh-thread-delete, mh-thread-refile): - Move to new file mh-thread.el. - (mh-subject-to-sequence, mh-subject-to-sequence-unthreaded) - (mh-subject-to-sequence-threaded, mh-edit-pick-expr) - (mh-pick-args-list, mh-narrow-to-subject, mh-narrow-to-from) - (mh-narrow-to-cc, mh-narrow-to-to, mh-narrow-to-header-field) - (mh-current-message-header-field, mh-narrow-to-range) - (mh-delete-subject, mh-delete-subject-or-thread): Move to new file - mh-limit.el. - (mh-iterate-on-messages-in-region, mh-iterate-on-range): Move to - mh-acros.el. - (mh-internal-seqs, mh-catchup, mh-delete-msg-from-seq) - (mh-internal-seq, mh-valid-seq-p, mh-seq-containing-msg) - (mh-define-sequence, mh-undefine-sequence) - (mh-delete-a-msg-from-seq, mh-delete-seq-locally) - (mh-folder-size, mh-folder-size-flist, mh-folder-size-folder) - (mh-parse-flist-output-line, mh-read-folder-sequences) - (mh-read-msg-list, mh-notate-user-sequences) - (mh-remove-cur-notation, mh-add-sequence-notation) - (mh-remove-sequence-notation, mh-remove-all-notation): Move here - from mh-e.el. - (mh-make-seq, mh-seq-name, mh-find-seq, mh-seq-to-msgs) - (mh-add-msgs-to-seq, mh-notate): Move here from mh-utils.el. - - * mh-show.el: New file. Contains mh-show-mode from mh-utils.el. - - * mh-speed.el: Rearrange for consistency with other files. - - * mh-thread.el: New file. Contains threading code from mh-seq.el. - - * mh-tool-bar.el: New file. Contains tool bar creation code from - deprecated file mh-customize.el. - - * mh-utils.el (recursive-load-depth-limit): Remove setting. - No longer needed. - (mh-scan-msg-number-regexp, mh-scan-msg-overflow-regexp) - (mh-scan-msg-format-regexp, mh-scan-msg-format-string) - (mh-scan-msg-search-regexp, mh-cmd-note, mh-note-seq) - (mh-update-scan-format, mh-msg-num-width): Move to new file - mh-scan.el. - (mh-show-buffer-mode-line-buffer-id, mh-letter-header-font-lock) - (mh-header-field-font-lock, mh-header-to-font-lock) - (mh-header-cc-font-lock, mh-header-subject-font-lock) - (mh-show-font-lock-keywords) - (mh-show-font-lock-keywords-with-cite) - (mh-show-font-lock-fontify-region) - (mh-gnus-article-highlight-citation, mh-showing-with-headers) - (mh-start-of-uncleaned-message, mh-invalidate-show-buffer) - (mh-unvisit-file, mh-defun-show-buffer, mh-show-mode-map) - (mh-show-sequence-menu, mh-show-message-menu) - (mh-show-folder-menu, mh-show-mode, mh-show-addr) - (mh-maybe-show, mh-show, mh-show-msg, mh-show-unquote-From) - (mh-msg-folder, mh-display-msg, mh-clean-msg-header): Move to new - file mh-show.el. - (mh-mail-header-separator, mh-signature-separator-regexp) - (mh-signature-separator, mh-globals-hash, mh-user-path) - (mh-draft-folder, mh-unseen-seq, mh-previous-seq, mh-inbox) - (mh-previous-window-config, mh-current-folder mh-show-buffer) - (mh-showing-mode, mh-show-mode-map, mh-show-folder-buffer) - (mh-showing-mode, mh-seq-list, mh-seen-list, mh-summary-height) - (mh-list-to-string, mh-list-to-string-1): Move to mh-e.el. - (mh-buffer-data, mh-mm-inline-media-tests): Move to mh-mime.el. - (mh-address-mail-regexp, mh-goto-address-find-address-at-point): - Move to mh-alias.el. - (mh-letter-font-lock-keywords): Move to new file mh-letter.el. - (mh-folder-filename, mh-msg-count, mh-recenter, mh-msg-filename) - (mh-show-mouse, mh-modify, mh-goto-msg, mh-set-folder-modified-p): - Move to new file mh-folder.el. - (with-mh-folder-updating, mh-in-show-buffer) - (mh-do-at-event-location, mh-seq-msgs): Move to mh-acros.el. - (mh-make-seq, mh-seq-name, mh-notate, mh-find-seq) - (mh-seq-to-msgs, mh-add-msgs-to-seq, mh-canonicalize-sequence): - Move to mh-seq.el. - (mh-show-xface-function, mh-uncompface-executable, mh-face-to-png) - (mh-uncompface, mh-icontopbm, mh-face-foreground-compat) - (mh-face-background-compat, mh-face-display-function) - (mh-show-xface, mh-picon-directory-list) - (mh-picon-existing-directory-list) - (mh-picon-cache, mh-picon-image-types) - (mh-picon-set-directory-list, mh-picon-get-image) - (mh-picon-file-contents, mh-picon-generate-path) - (mh-x-image-cache-directory, mh-x-image-scaling-function) - (mh-wget-executable, mh-wget-choice, mh-wget-option) - (mh-x-image-temp-file, mh-x-image-url, mh-x-image-marker) - (mh-x-image-url-cache-file, mh-x-image-scale-with-pnm) - (mh-x-image-scale-with-convert) - (url-unreserved-chars, url-hexify-string) - (mh-x-image-url-cache-canonicalize) - (mh-x-image-set-download-state, mh-x-image-get-download-state) - (mh-x-image-url-fetch-image, mh-x-image-display) - (mh-x-image-scale-and-display, mh-x-image-url-sane-p) - (mh-x-image-url-display): Move to new file mh-xface.el. - (mh-logo-display): Call mh-image-load-path. - (mh-find-path-run, mh-find-path): Move here from deprecated file - mh-init.el. - (mh-help-messages): Now an alist of modes to an alist of messages. - (mh-set-help): New function used to set mh-help-messages. - (mh-help): Adjust for new format of mh-help-messages. - Add help-messages argument. - (mh-prefix-help): Refactor to use mh-help. - (mh-coalesce-msg-list, mh-greaterp, mh-lessp): Move here from - mh-e.el. - (mh-clear-sub-folders-cache): New function added to avoid exposing - mh-sub-folders-cache variable. - - * mh-xface.el: New file. Contains X-Face and Face header field - display routines from mh-utils.el. - -2006-01-17 Bill Wohler - - * mh-acros.el (assoc-string): Fix typo in argument. - -2006-01-16 Bill Wohler - - * mh-acros.el (require): Remove defadvice of require as defadvice - is verboten within Emacs and our implementation was returning the - wrong value from require. Upcoming restructuring should make this - unnecessary. - (mh-assoc-ignore-case): Replace with defsubst assoc-string. - - * mh-alias.el (mh-alias-local-users, mh-alias-reload) - (mh-alias-expand, mh-alias-minibuffer-confirm-address): Use it. - - * mh-identity.el (mh-identity-field-handler): Use it. - - * mh-comp.el (mh-show-buffer-message-number): Replace (car - (read-from-string string) with (string-to-number string). - - * mh-e.el (mh-parse-flist-output-line, mh-folder-size-folder): - Ditto. - - * mh-mime.el (mh-mml-forward-message): Ditto. - - * mh-search.el (mh-swish-next-result, mh-mairix-next-result) - (mh-namazu-next-result, mh-grep-next-result, mh-md5sum-parser) - (mh-openssl-parser, mh-index-update-maps): Ditto. - - * mh-seq.el (mh-translate-range, mh-narrow-to-header-field) - (mh-thread-generate): Ditto. - -2006-01-16 Katsumi Yamaoka - - * mh-mime.el (mh-mime-display, mh-mm-inline-message): Fix use of - mm- functions for proper text=flowed handling (addresses SF - #1273521). - -2006-01-15 Bill Wohler - - * mh-e.el (mh-limit-map, mh-help-messages): Change keybinding of - mh-narrow-to-from from / f to / m; mh-narrow-to-range from / r to - / g. - - * mh-utils.el (mh-show-limit-map): Ditto. - - * mh-exec.el: Require mh-acros, mh-buffers, and mh-utils for - standalone compile. - (mh-progs, mh-lib, mh-lib-progs): Move here from mh-init.el. - - * mh-init.el (mh-progs, mh-lib, mh-lib-progs): Move to mh-exec.el, - where they are used. - - * mh-comp.el (mh-pgp-support-flag): Move here from mh-utils.el; - needed to help remove dependency on mh-utils. - - * mh-exec.el: New file. Move process support routines here from - mh-utils.el. - - * mh-init.el (mh-utils): Remove require. - (mh-exec): Add require. - (mh-profile-component, mh-profile-component-value): Move here from - mh-utils.el. - - * mh-utils.el (mh-pgp-support-flag): Move to mh-comp.el to reduce - dependencies on mh-utils.el. - (mh-profile-component, mh-profile-component-value): Move to - mh-init.el since that's the only place that uses them. (Other than - mh-alias.el; I'm thinking that mh-find-path can set variable from - the Aliasfile component like it does the other components). - (mh-index-max-cmdline-args, mh-xargs, mh-quote-for-shell) - (mh-exec-cmd, mh-exec-cmd-error, mh-exec-cmd-daemon) - (mh-exec-cmd-env-daemon, mh-process-daemon, mh-exec-cmd-quiet) - (defvar, mh-exec-cmd-output) - (mh-exchange-point-and-mark-preserving-active-mark) - (mh-exec-lib-cmd-output, mh-handle-process-error): Move to new - file mh-exec.el so that mh-init.el doesn't have to depend on - mh-utils.el, breaking circular dependency. - - * mh-alias.el: - * mh-customize.el: - * mh-e.el: - * mh-funcs.el: - * mh-gnus.el: - * mh-identity.el: - * mh-inc.el: - * mh-junk.el: - * mh-mime.el: - * mh-print.el: - * mh-search.el: - * mh-seq.el: - * mh-speed.el: Added debugging statements (commented out) around - requires to help find dependency loops. Will remove them when - issues are resolved. - -2006-01-14 Bill Wohler - - * mh-customize.el (mh-index): Rename group to mh-search and sort - group definition and options accordingly. - (mh-index-program): Rename to mh-search-program. - (mh-kill-folder-suppress-prompt-hooks): Rename mh-index-p to - mh-search-p. - (mh-search-mode-hook): Change group from mh-index to mh-search. - (mh-index-folder): Rename to mh-search-folder. Change group from - mh-index to mh-search. - - * mh-e.el (mh-folder-font-lock-keywords): Rename mh-index-folder - to mh-search-folder. - - * mh-search.el (mh-indexer) Rename to mh-searcher. The commands - pick and grep are searchers too but aren't indexed. - (mh-index-execute-search-function): Rename to mh-search-function. - (mh-index-next-result-function): Rename to - mh-search-next-result-function. - (mh-index-regexp-builder): Rename to mh-search-regexp-builder. - (mh-search): Since redo-search-flag defaults to nil and is of - lesser importance, make it an optional argument and place it after - the folder and search-regexp arguments. Sync docstring with manual. - (mh-search-mode-map): Autoload so that keys are shown in help even - before mh-search is loaded. - (mh-search-mode): Sync docstring with manual. - (mh-index-do-search): Rename argument indexer to searcher. - Sync docstring with manual. - (mh-pick-do-search): Sync docstring with manual. - (mh-index-p): Rename to mh-search-p. - (mh-indexer-choices): Rename to mh-search-choices. - (mh-index-choose): Rename to mh-search-choose. Rename argument - indexer to searcher. - (mh-swish++-execute-search, mh-swish-execute-search) - (mh-mairix-execute-search, mh-namazu-execute-search): Drop "and - read the results" from docstring since these functions don't. - (mh-pick-execute-search, mh-grep-execute-search): Sync docstring - with manual. - (mh-index-generate-pretty-name): Prune -search from string so that - folder names for pick searches are the same as those of other - searches. - -2006-01-13 Bill Wohler - - * mh-acros.el (require): Add Satyaki's comment regarding what - needs to happen to remove this defadvice which caused a little - discussion on emacs-devel today (see Subject: mh-e/mh-acros.el - advices `require' incorrectly). - - * mh-search.el (mh-index-next-result-function): Add format to - docstring. - (mh-mairix-next-result): Use nil instead of () which doesn't stand - out as well. - (mh-pick-execute-search): Operate across all folders if no folder - given and recurse folder(s). - (mh-pick-next-result): Handle new output. - - * mh-utils.el (mh-collect-folder-names): Fix docstring. - (mh-children-p, mh-folder-list): New functions. - -2006-01-12 Bill Wohler - - * mh-search.el: New file containing contents of mh-index.el and - mh-pick.el. C-c C-c launches your mh-index-program; C-c C-p runs - pick. Pick no longer sets the "search" sequence. Instead, it - brings up a folder view that we're accustomed to. (Closes SF - #829207.) - (mh-index-search): Rename to mh-search. - (mh-pick-menu): Rename menu from Pick to Search. Rename Execute - the Search to Perform Search and call mh-do-search. Add Search - with Pick menu item. - (mh-do-search): Delete. - (mh-search-mode): Rename from mh-pick-mode. - (MH-Search): Rename mode from MH-Pick. - (mh-search-mode-map): Rename from mh-pick-mode-map. - (mh-search-mode-help-messages): Rename from - mh-pick-mode-help-messages. - (mh-index-choose): Don't reuse the last value of mh-indexer; when - mh-pick-do-search sets it to 'pick, we don't necessarily want to - stay with that choice! - - * mh-index.el: - * mh-pick.el: Merge into mh-search.el and delete. - - * mh-customize.el (mh-index-program): Change mh-index-search to - mh-search in docstring. - (mh-tool-bar-search-function): Change default from - mh-search-folder to mh-search. Remove mh-search-folder as choice - and rename mh-index-search choice to mh-search. Fix docstring. - (mh-pick-mode-hook): Rename to mh-search-mode-hook and change - mh-search-folder to mh-search in docstring. - - * mh-e.el (mh-folder-folder-menu): Delete Search a Folder. Change - Indexed Search to Search. Use mh-search instead of mh-index-search. - (mh-folder-map): Delete i (mh-index-search) keybinding. Change s - from mh-show-search-folder to mh-search. - - * mh-seq.el (mh-put-msg-in-seq): Fix docstring now that - mh-search-folder no longer creates the search sequence. - - * mh-utils.el (mh-show-search-folder): Delete. - (mh-show-folder-map): Delete i (mh-index-search) keybinding. - Change s from mh-show-search-folder to mh-search. - (mh-show-folder-menu): Delete Search a Folder. Change Indexed - Search to Search. Use mh-search instead of mh-index-search. - (mh-index-max-cmdline-args, mh-xargs, mh-quote-for-shell): - Move here from deleted mh-index.el. - -2006-01-11 Bill Wohler - - * mh-acros.el (mh-defun-compat, mh-defmacro-compat): Move here - from mh-gnus.el. - - * mh-gnus.el: Require mh-acros. - (mh-defmacro-compat, mh-defun-compat): Move to mh-acros.el. - - * mh-utils.el (mh-x-image-url-cache-canonicalize): - Use url-hexify-string to remove special characters from filenames - (closes SF #1396499). Note that this invalidates the existing - names in your cache so you might as well remove - ~/Mail/.mhe-x-image-cache/* now. - (url-unreserved-chars, url-hexify-string): Define if not defined. - Copied from url-util.el in Emacs22 for Emacs 21. - - * mh-buffers.el: New file. Contains constants and code from - mh-index.el and mh-utils.el. - - * mh-alias.el: - * mh-comp.el: - * mh-e.el: - * mh-funcs.el: - * mh-init.el: - * mh-junk.el: - * mh-mime.el: - * mh-print.el: - * mh-seq.el: Require new file mh-buffers.el. - - * mh-index.el: Require new file mh-buffers.el. - (mh-index-temp-buffer, mh-checksum-buffer): Move to new file - mh-buffers.el. - - * mh-utils.el: Require new file mh-buffers.el. - (mh-temp-buffer, mh-temp-fetch-buffer) - (mh-aliases-buffer, mh-folders-buffer, mh-help-buffer) - (mh-info-buffer, mh-log-buffer, mh-mail-delivery-buffer) - (mh-recipients-buffer, mh-sequences-buffer, mh-log-buffer-lines) - (mh-truncate-log-buffer): Move to new file mh-buffers.el. - - * mh-comp.el (mh-forward): Cosmetics on prompt when draft exists. - (mh-send-letter): Add -msgid to mh-send-args (closes SF #725425). - -2006-01-10 Bill Wohler - - * mh-comp.el (mh-insert-letter): If you choose a different folder, - the cur message is used. Sync docstring with manual (closes SF - #1205890). - - * mh-mime.el (mh-compose-forward): Use standard range argument - instead of messages. Use more powerful mh-read-range instead of - read-string. Sync docstring with manual (close SF #1205890). - - * mh-index.el (mh-index-search): Checking mh-find-path-run is - unnecessary. - (mh-index-next-folder): Don't back up a line when going backwards - since this skips the current folder heading if point is on the - first message after the folder heading (closes SF #1126188). - - * mh-init.el (mh-sys-path): Co-locate with mh-variants, which uses it. - (mh-variants): Note variable isn't meant to be accessed directly; - use function mh-variants instead. - (mh-variant-info, mh-variant-mh-info, mh-variant-mu-mh-info) - (mh-variant-nmh-info): Co-locate next to mh-variants, which uses - them. Updated to use mh-file-command-p which is more accurate - than file-executable-p which returns t for directories. - (mh-file-command-p): Move here from mh-utils, since - mh-variant-*-info are the only functions to use it. - (mh-variant-set, mh-variant-set-variant, mh-variant-p): - Use function mh-variants instead of variable. More robust. - (mh-find-path-run): Move here from mh-utils.el. Mention that - checking this variable is unnecessary. - (mh-find-path): Move here from mh-utils.el. With the advent of MH - variants and an mhparam command that doesn't work if there isn't - an MH profile, we can't get libdir for running install-mh. - So don't bother. If there's an issue with the environment, direct the - user to install MH and run install-mh (closes SF #835192). - Don't read ~/.mh_profile directly. Use mh-profile-component which uses - mhparam (closes SF #1016027). - - * mh-utils.el (mh-get-profile-field): Rename to - mh-profile-component-value. Add colon to search removing - unnecessary addition of colon to field in mh-profile-component. - (mh-profile-component): Modify call to mh-profile-component-value - accordingly. Move next to mh-profile-component-value. - (mh-find-path-run, mh-find-path, mh-file-command-p): Move to - mh-init.el. It makes sense that code that is only run once per - session (more or less) is in mh-init.el rather than cluttering - mh-utils.el. - (mh-no-install, mh-install): Delete. - - * mh-customize.el (mh-folder-msg-number): - * mh-mime.el (mh-file-mime-type): Remove trailing whitespace. - -2006-01-09 Bill Wohler - - * mh-init.el (mh-variant-mu-mh-info, mh-variant-nmh-info): - Applied patch from Satyaki from SF #1016027. - - * mh-e.el (mh-rescan-folder): Try to keep cursor at current - message, even if cur sequence is no longer present (closes SF - #1207247). - - * mh-comp.el: Use ";; Shush compiler." comment consistently per - Mark's suggestion. - (mh-letter-mode): Derive from mail-mode and delete code copied - from mail-mode (closes SF #1385571). Mention mail-mode-hook in - docstring. - (mh-fill-paragraph-function): Delete. Handled by mail-mode. - (mh-to-field-choices): For consistency with mail-mode, add "a" for - "Mail-Reply-To:", "l" for "Mail-Followup-To:", and "r" for - "Reply-To:". Change "r" to "m" for "From:" (closes SF #1400139). - (mh-to-fcc): Move setting of folder argument to interactive - argument as is the norm. - (mh-letter-complete-function-alist): Add mail-reply-to. - (mh-letter-mode-map): Add keys for mh-to-field (Mail-Reply-To, - Mail-Followup-To, Reply-To, From). - - * mh-customize.el: Use ";; Forward definition." consistently. - Comment declaration to remind programmer to update forward - definition if default changes. - - * mh-funcs.el: - * mh-inc.el: - * mh-init.el: - * mh-mime.el: - * mh-seq.el: - * mh-utils.el: Use ";; Shush compiler." comment consistently per - Mark's suggestion. - -2006-01-08 Bill Wohler - - Removed code that was marked as Emacs 20 compatible that was - easily found showing how important it is to document such - things (closes SF #1359240). Feel free to nuke any other Emacs 20 - peculiarities that you find. Wrapped code for shushing compiler - with (eval-when-compile), sometimes moving the defvars closer to - where they were used. - - * mh-alias.el (mh-alias-gecos-name): Use replace-regexp-in-string - instead of mh-replace-in-string as mh-replace-in-string was - replaced by a more appropriate defsubst in mh-xemacs.el. - - * mh-comp.el: Require cleanup, wrap compiler-shushing defvars with - eval-when-compile. - (mh-file-is-vcard-p): Remove redundant test. - - * mh-customize.el: Require cleanup, wrap compiler-shushing defvars - with eval-when-compile. - (mh-adaptive-cmd-note-flag, mh-invisible-header-fields) - (mh-invisible-header-fields-default): Add forward definitions. - (mh-invisible-header-fields-default): Alphabetize. - - * mh-e.el: Require cleanup, wrap compiler-shushing defvars with - eval-when-compile. - (mh-thread-scan-line-map-stack, tool-bar-mode): Delete unused - variables. - (mh-colors-available-p): Just call display-color-cells. It's on - all supported Emacsen (and defaliased on XEmacs). - - * mh-funcs.el: - * mh-inc.el: - * mh-init.el: Wrap compiler-shushing defvars with - eval-when-compile. - - * mh-identity.el: Don't need (mh-require-cl). - - * mh-index.el: Don't need to load executable any more. - - * mh-mime.el: Wrap compiler-shushing defvars with - eval-when-compile. - (mh-have-file-command): Initialize variable to 'undefined. - Add docstring. Update function of same name accordingly. Also don't - need to load executable any more. - (mh-mime-content-types): Delete. - (mh-minibuffer-read-type): Prompt user for type if - mh-file-mime-type returns application/octet-stream. Assume we have - mailcap-mime-types. - (mh-mime-display): Update error message. - - * mh-seq.el: Require cleanup, and wrap compiler-shushing defvars - with eval-when-compile. - - * mh-utils.el: Require cleanup, and wrap compiler-shushing defvars - with eval-when-compile. - (mh-clean-msg-header): Don't set after-change-functions to nil. - (mh-replace-in-string): Remove. Create defsubst in mh-xemacs.el - instead. - -2006-01-07 Bill Wohler - - * mh-customize.el: Updated Faces documentation in header. - (mh-invisible-header-fields-internal): Add X-Lumos-SenderID, - X-Return-Path-Hint, and X-Roving-* from Roving ConstantContact. - - * mh-mime.el (mh-mml-tag-present-p): Update regexp to handle - tags inserted by Gnus gnus-summary-mail-forward (closes SF - #1399307). - -2006-01-03 Mark D. Baushke - - * mh-e.el (mh-delete-a-msg): Fix whitespace nit. - * mh-index.el (mh-mairix-execute-search): Fix symbol quote. - -2006-01-03 Bill Wohler - - * mh-alias.el (mh-alias-add-alias): Grand message and error string - unification. Use single sentence if possible by using semicolon. - Don't end message with punctuation. Don't need format with - message. Quote messages as in docstrings: use `' around symbols, - \" for option choices. Don't use quotes around %s. - - * mh-comp.el (mh-complete-word): Ditto. - - * mh-customize.el (mh-adaptive-cmd-note-flag-check) - (mh-scan-format-file-check): Ditto. - - * mh-e.el (mh-refile-or-write-again, mh-previous-unread-msg) - (mh-delete-a-msg, mh-refile-a-msg, mh-next-unread-msg) - (mh-msg-num-width-to-column): Ditto. - - * mh-identity.el (mh-identity-field-handler): Ditto. - - * mh-index.el (mh-mairix-execute-search) - (mh-swish-execute-search, mh-swish++-execute-search) - (mh-namazu-execute-search): Ditto. - - * mh-init.el (mh-variant-set): Ditto. - - * mh-mime.el (mh-mh-to-mime-undo, mh-mml-forward-message) - (mh-secure-message, mh-mime-display): Ditto. - - * mh-pick.el (mh-search-folder, mh-pick-construct-regexp): Ditto. - - * mh-seq.el (mh-narrow-to-seq, mh-put-msg-in-seq, mh-read-seq) - (mh-read-range, mh-thread-container-subject): Ditto. - - * mh-utils.el (mh-x-image-scale-and-display) - (mh-prompt-for-folder, mh-handle-process-error) - (mh-list-to-string-1): Ditto. - - * mh-comp.el (mh-reply): Use standard default notation in - prompts (closes SF #1275933). - - * mh-mime.el (mh-mime-save-parts): Ditto. - - * mh-seq.el (mh-read-seq, mh-read-range): Ditto. - - * mh-customize.el (mh-folder-msg-number): Snow is actually - off-white on low color displays which turns to white when bold. - This is unreadable on white backgrounds. Use snow with min-colors - requirement. Use cyan on low-color displays. - - * mh-init.el (mh-defface-compat): On low-color displays, delete - the high-color display rather than simply strip the min-colors - requirement since the existing algorithm shadowed the desired - display on low-color displays. - - * mh-alias.el (mh-alias-add-alias): Remove leading * from - docstring. - -2006-01-02 Bill Wohler - - * mh-alias.el (mh-alias-grab-from-field): Remove leading * from - docstring. Does this mean something in a defun? - - * mh-customize.el (bw-new-face-to-old, bw-old-face-to-new): - Checkdoc fix. - - * mh-e.el (mh-inc-folder): Rename maildrop-name argument to file - so it reads better in docstring and manual. Sync docstring with - manual. - - * mh-init.el (mh-defface-compat): Remove trailing space (checkdoc). - - * mh-alias.el (mh-alias-apropos): Sync docstring with manual. - - * mh-comp.el (mh-redistribute, mh-to-field, mh-to-fcc) - (mh-insert-auto-fields, mh-send-letter, mh-yank-cur-msg) - (mh-fully-kill-draft, mh-open-line, mh-letter-complete) - (mh-letter-complete-or-space, mh-letter-confirm-address) - (mh-letter-next-header-field-or-indent) - (mh-letter-previous-header-field): Ditto. - - * mh-customize.el (mh-alias-completion-ignore-case-flag) - (mh-default-folder-for-message-function, mh-mml-method-default) - (mh-signature-file-name, mh-yank-behavior, mh-show-hook) - (mh-show-mode-hook) Ditto. - - * mh-e.el (mh-refile-or-write-again, mh-toggle-showing): Ditto. - - * mh-funcs.el (mh-pipe-msg, mh-sort-folder, mh-undo-folder) - (mh-store-msg, mh-store-buffer): Ditto. - - * mh-index.el (mh-index-search, mh-index-do-search) - (mh-index-next-folder, mh-index-sequenced-messages): Ditto. - - * mh-junk.el (mh-spamassassin-blacklist): Ditto. - - * mh-mime.el (mh-mh-compose-external-compressed-tar) - (mh-mh-compose-external-type, mh-mh-to-mime, mh-mh-to-mime-undo) - (mh-mml-secure-message-sign, mh-mml-secure-message-encrypt) - (mh-mml-secure-message-signencrypt): Ditto. - - * mh-pick.el (mh-search-folder): Ditto. - - * mh-seq.el (mh-widen): Ditto. - - * mh-utils.el (mh-show, mh-modify): Ditto. - -2006-01-02 Mark D. Baushke - - * mh-mime.el (mh-mml-unsecure-message): Remove unused argument. - -2006-01-01 Bill Wohler - - * mh-customize.el: Sync docstrings with manual for faces and sort - them alphabetically. - (mh-faces): Move below mh-hooks. - (mh-folder-faces, mh-index-faces, mh-letter-faces) - (mh-show-faces, mh-speed-faces): Delete. Organize faces like hooks. - (mh-speed-update-interval): Fix group (mh-speedbar, not mh-speed). - (facemenu-unlisted-faces): Might as well ignore all MH-E faces. - (mh-folder-body-face, mh-folder-cur-msg-face) - (mh-folder-cur-msg-number-face, mh-folder-date-face) - (mh-folder-followup-face, mh-folder-msg-number-face) - (mh-folder-deleted-face, mh-folder-refiled-face) - (mh-folder-subject-face, mh-folder-address-face) - (mh-folder-scan-format-face, mh-folder-to-face) - (mh-index-folder-face, mh-show-cc-face, mh-show-date-face) - (mh-show-header-face, mh-show-pgg-good-face) - (mh-show-pgg-unknown-face, mh-show-pgg-bad-face) - (mh-show-to-face, mh-show-from-face, mh-show-subject-face): - Delete. - (mh-folder-cur-msg): Unused. Delete. - (mh-folder-address): Use defface; inherit from mh-folder-subject. - (mh-folder-body, mh-folder-cur-msg-number, mh-folder-date): - Inherit from mh-folder-msg-number. - (mh-folder-deleted): Use defface. Inherit from - mh-folder-msg-number. - (mh-folder-sent-to-me-hint): New face. Inherit from - mh-folder-date. - (mh-folder-sent-to-me-sender): Rename from mh-folder-scan-format. - Use defface. Inherit from mh-folder-followup. - (mh-show-xface): Inherit from mh-show-from and highlight. - (bw-face-generation, bw-toggle-faces) - (bw-new-face-to-old, bw-old-face-to-new): New (tempoarary) - variables, functions for toggling between old and new faces. - - * mh-e.el (font-lock-auto-fontify, font-lock-defaults): Hide in - eval-when-compile. We should probably do this throughout. - (mh-scan-good-msg-regexp, mh-scan-deleted-msg-regexp) - (mh-scan-refiled-msg-regexp, mh-scan-cur-msg-number-regexp) - (mh-scan-date-regexp, mh-scan-rcpt-regexp, mh-scan-body-regexp) - (mh-scan-subject-regexp): Sync docstrings with manual. - (mh-scan-format-regexp): Rename to - mh-scan-sent-to-me-sender-regexp. Drop date parenthesized - expression. Make expression more like the others (anchored at the - beginning of line). Sync docstrings with manual. - (mh-folder-font-lock-keywords): Use faces directly rather than - -face variables. Use mh-scan-sent-to-me-sender-regexp instead of - mh-scan-format-regexp, and within that expression, use faces - mh-folder-sent-to-me-hint and mh-folder-sent-to-me-sender instead - of mh-folder-date-face and mh-folder-scan-format-face which were - misleading. - - * mh-mime.el (mh-mime-security-button-face): Use faces directly - rather than -face variables. - - * mh-utils.el (mh-show-font-lock-keywords): Use faces directly - rather than -face variables. - (mh-face-foreground-compat, mh-face-background-compat): New macros. - (mh-face-display-function): Use mh-face-foreground-compat and - mh-face-background-compat to use inherited attributes of - mh-show-xface on Emacs 22 while still working on Emacs 21. - -2005-12-28 Bill Wohler - - * mh-comp.el (mh-e-user-agent): Move here from simple.el. - Use mh-user-agent-compose instead of mh-smail-batch. - -2005-12-27 Bill Wohler - - * mh-utils.el (mh-prompt-for-folder): Use can-create argument to - suppress creation of folder if it doesn't exist. - -2005-12-27 Stefan Monnier - - * mh-utils.el (mh-process-daemon): Don't change buffer in proc-filter. - -2005-12-23 Bill Wohler - - * mh-e.el (mh-folders-changed): Fix typo in docstring. - - Follow MH-E Developers Guide conventions. Use `' quotes for Help - hyperlinks such as symbols, Info nodes, or URLs. Use \" quotes for - everything else. Otherwise, you can accidentally get links to - nonsense symbols. - -2005-12-22 Bill Wohler - - Follow Emacs coding conventions. Use default setting of - emacs-lisp-docstring-fill-column which is 65. - - * mh-alias.el (mh-alias-reload): Sync docstrings with manual. - - * mh-comp.el (mh-letter-mode): Use 60 column width. - (mh-forward, mh-insert-signature, mh-send-letter): Sync docstrings - with manual. - (mh-yank-cur-msg): Mention that mh-ins-buf-prefix isn't used if - you have added a mail-citation-hook and neither are used if you - use one of the supercite flavors of mh-yank-behavior. - Sync docstrings with manual. - - * mh-customize.el (mh-kill-folder-suppress-prompt-hooks): - Rename from mh-kill-folder-suppress-prompt-hook since it is an abnormal - hook. Use "Hook run by `function'..." instead of "Invoked...". - Sync docstrings with manual. - (mh-ins-buf-prefix, mh-yank-behavior): Mention that - mh-ins-buf-prefix isn't used if you have added a - mail-citation-hook and neither are used if you use one of the - supercite flavors of mh-yank-behavior. Sync docstrings with manual. - (mail-citation-hook): Delete. Use one in sendmail.el. - (mh-signature-file-name, mh-after-commands-processed-hook) - (mh-alias-reloaded-hook, mh-before-commands-processed-hook) - (mh-before-quit-hook, mh-before-send-letter-hook) - (mh-delete-msg-hook, mh-find-path-hook, mh-folder-mode-hook) - (mh-forward-hook, mh-inc-folder-hook, mh-insert-signature-hook) - (mh-letter-mode-hook) - (mh-mh-to-mime-hook, mh-pick-mode-hook, mh-quit-hook) - (mh-refile-msg-hook, mh-show-hook, mh-show-mode-hook) - (mh-unseen-updated-hook): Use "Hook run by `function'..." instead - of "Invoked...". Sync docstrings with manual. - - * mh-e.el (mh-last-destination, mh-last-destination-folder) - (mh-last-destination-write, mh-folder-mode-map, mh-arrow-marker) - (mh-delete-list, mh-refile-list, mh-folders-changed) - (mh-next-direction, mh-view-ops, mh-folder-view-stack) - (mh-index-data, mh-first-msg-num, mh-last-msg-num) - (mh-mode-line-annotation, mh-sequence-notation-history) - (mh-colors-available-flag): Move comment into docstring. - (mh-delete-msg, mh-execute-commands, mh-inc-folder, mh-quit) - (mh-process-commands): Sync docstrings with manual. - (mh-refile-msg): Small doc edit. - (mh-delete-a-msg, mh-refile-a-msg): Sync docstrings with manual. - Rename msg argument to message. - - * mh-funcs.el (mh-kill-folder): Sync docstrings with manual. - - * mh-e.el (mh-update-unseen): No longer say "The value of - `foo-hook' is a list of functions to be called, with no arguments, - ...," but rather just "The hook foo-hook is called...". - - * mh-mime.el (mh-mh-to-mime): Ditto. - - * mh-pick.el (mh-pick-mode): Ditto. - - * mh-utils.el (mh-showing-mode): Use uppercase for argument in - docstring. - (mh-seq-list, mh-seen-list, mh-showing-with-headers): Move comment - into docstring. - (mh-show-mode, mh-show-msg, mh-find-path): Sync docstrings with - manual. - -2005-12-19 Stephen Gildea - - * mh-customize.el (mh-after-commands-processed-hook): New variable. - (mh-before-commands-processed-hook): Rename mh-folder-updated-hook. - - * mh-e.el (mh-process-commands): Rename mh-folder-updated-hook to - mh-before-commands-processed-hook, call new - mh-after-commands-processed-hook. - (mh-folders-changed): New variable (for use in - mh-after-commands-processed-hook). - -2005-12-19 Bill Wohler - - * mh-acros.el: - * mh-alias.el: - * mh-comp.el: - * mh-customize.el: - * mh-e.el: - * mh-funcs.el: - * mh-gnus.el: - * mh-identity.el: - * mh-inc.el: - * mh-index.el: - * mh-init.el: - * mh-junk.el: - * mh-mime.el: - * mh-pick.el: - * mh-print.el: - * mh-seq.el: - * mh-speed.el: - * mh-utils.el: - Follow commenting conventions. Don't use ;;; form so much, except - for headings. Precede headings with page feed. This was mostly - already done, so I made it a convention. Did not update copyright - on a couple of files since this was an insignificant change. - -2005-12-18 Bill Wohler - - * mh-customize.el (mh-toolbar): Rename to mh-tool-bar. - (mh-tool-bar-search-function): Sync docstrings with manual. - (mh-tool-bar-customize): Replace toolbar with tool bar in docstring. - (mh-tool-bar-letter-help): Fix manual reference. - (mh-xemacs-use-toolbar-flag): Rename to - mh-xemacs-use-tool-bar-flag. Initialize to - mh-xemacs-has-tool-bar-flag. Sync docstrings with manual. - (mh-xemacs-toolbar-position): Rename to - mh-xemacs-tool-bar-position. Initialize to nil. Drop "no tool bar" - option (redundant) and change "Same As Default Tool Bar" setting - to nil. Sync docstrings with manual. - (mh-tool-bar-define): Replace toolbar with tool-bar or tool bar - depending on context. - (mh-toolbar-init): Rename to mh-tool-bar-init. Simplify condition - for calling set-specifier. Only look at the value of - mh-xemacs-use-tool-bar-flag. - (mh-tool-bar-folder-buttons, mh-tool-bar-letter-buttons): - Sync docstrings with manual. - - * mh-comp.el (mh-letter-mode): Use mh-tool-bar-init instead of - mh-toolbar-init. - - * mh-e.el (mh-folder-mode): Ditto. - - * mh-utils.el (mh-show-mode): Ditto. - -2005-12-15 Bill Wohler - - * mh-e.el (mh-delete-msg): Sync docstrings with manual. - - * mh-seq.el (mh-delete-subject, mh-thread-next-sibling) - (mh-thread-previous-sibling, mh-thread-ancestor) - (mh-thread-delete, mh-thread-refile): Ditto. - -2005-12-14 Bill Wohler - - * mh-customize.el (mh-speed-flists-interval): Rename to - mh-speed-update-interval. - (mh-speed-run-flists-flag): Delete. - Setting mh-speed-flists-interval to 0 accomplishes the same thing. - - * mh-speed.el (mh-folder-speedbar-buttons, mh-speed-flists): - Use mh-speed-update-interval instead of mh-speed-run-flists-flag. - (mh-speed-toggle, mh-speed-view, mh-speed-refresh): - Sync docstrings with manual. - -2005-12-09 Bill Wohler - - * mh-customize.el (mh-path): Move here from mh-init.el. - (mh-variant): Mention that mh-path can be customized. - (mh-invisible-header-fields-internal): Add X-ContentStamp, - X-MAIL-INFO, and X-UNTD- from NetZero. - - * mh-init.el (mh-path): Move defcustom to mh-customize.el. - -2005-12-04 Bill Wohler - - * mh-customize.el (mh-sortm-args): Sync docstrings with manual. - (mh-invisible-header-fields-internal): Add X-Bugzilla-* and - X-Virus-Scanned. - - * mh-customize.el (mh-insert-signature-hook): - Rename mh-letter-insert-signature-hook to mh-insert-signature-hook. - - * mh-comp.el (mh-insert-signature): Ditto. - - * mh-customize.el (mh-fetch-x-image-url): Change default from 'ask - to nil. Remove t option. Sync docstring with manual (closes SF - #831278). - (mh-invisible-header-fields-internal): Remove X-Image-URL so that - users can see it, look it up in the manual's index, and discover - mh-fetch-x-image-url (closes SF #831278). - - * mh-customize.el (mh-new-messages-folders): Rename from - mh-index-new-messages-folders. - (mh-ticked-messages-folders): Rename from - mh-index-ticked-messages-folders. - - * mh-index.el (mh-index-sequenced-messages) - (mh-index-new-messages): Ditto. - - * mh-comp.el (mh-forward): Went over all uses of the word "RANGE" - in the docstrings and made usage consistent. Generally speaking, - "messages in range" and "range of messages" is redundant and just - "range" can be used in most circumstances. Also ensured that - mh-interactive-range was mentioned in all interactive functions - that use a range which describes the range argument for both users - and programmers. - - * mh-e.el (mh-delete-msg-no-motion, mh-refile-msg) - (mh-refile-or-write-again, mh-rescan-folder, mh-undo) - (mh-visit-folder, mh-scan-folder, mh-regenerate-headers) - (mh-notate-user-sequences, mh-delete-msg-from-seq, mh-catchup): - Ditto. - - * mh-funcs.el (mh-copy-msg, mh-pack-folder, mh-pack-folder-1): - Ditto. - - * mh-junk.el (mh-junk-blacklist, mh-junk-whitelist): Ditto. - - * mh-print.el (mh-ps-print-range, mh-ps-print-msg) - (mh-ps-print-msg-file, mh-print-msg): Ditto. - - * mh-seq.el (mh-put-msg-in-seq, mh-range-to-msg-list) - (mh-narrow-to-range, mh-toggle-tick): Ditto. - -2005-12-01 Bill Wohler - - Rewrote Reading Mail chapter in manual which affected mh-show - customization group and related functions. - - * mh-comp.el (mh-letter-mode): Use mh-highlight-citation-style - instead of mh-highlight-citation-p. - (mh-letter-toggle-header-field-display): "Ellipsed" isn't a word, - I think, so use "truncated". - - * mh-customize.el (mh-folder, mh-folder-faces): Group's manual - section is Folders, not Organizing. Parent of mh-folder-faces is - mh-folder, not mh-show. - (mh-speed): Rename to mh-speedbar for consistency with mh-toolbar. - (mh-thread): New group that corresponds with manual's Threading chapter. - (mh-letter-faces): Group's manual section is Editing Drafts, not - Sending Mail. - (mh-sortm-args): New customization variable that used to be a defvar. - (mh-index-new-messages-folders, mh-index-ticked-messages-folders): - Move from mh-index group to mh-folders group. - (mh-alias-local-users-prefix, mh-large-folder) - (mh-recursive-folders-flag, mh-before-quit-hook) - (mh-folder-mode-hook, mh-kill-folder-suppress-prompt-hook) - (mh-quit-hook, mh-refile-msg-hook): Move from mh-show group to - mh-folder group. - (mh-highlight-citation-style): Rename from - mh-highlight-citation-p. Sync docstrings with manual. - (mh-mhl-format-file): Rename from mhl-formfile. Sync docstrings - with manual. - (mh-show-threads-flag): Move from mh-show group to mh-thread - group. - (mh-find-path-hook): Move from mh-show group to mh-e group. - (mh-folder-updated-hook): Add to mh-folder group. - (mh-forward-hook): Move from mh-folder to mh-sending-mail group. - (mh-unseen-updated-hook): Move from mh-show to mh-sequences group. - (mh-bury-show-buffer-flag, mh-clean-message-header-flag) - (mh-decode-mime-flag, mh-display-buttons-for-alternatives-flag) - (mh-display-buttons-for-inline-parts-flag) - (mh-do-not-confirm-flag, mh-fetch-x-image-url) - (mh-graphical-smileys-flag, mh-graphical-emphasis-flag) - (mh-invisible-header-fields-default, mh-invisible-header-fields) - (mh-lpr-command-format, mh-max-inline-image-height) - (mh-max-inline-image-width) - (mh-mime-save-parts-default-directory, mh-print-background-flag) - (mh-show-maximum-size, mh-show-use-goto-addr-flag) - (mh-show-use-xface-flag, mh-store-default-directory) - (mh-summary-height, mh-delete-msg-hook) - (mh-show-hook, mh-show-mode-hook): Sync docstrings with manual. - - * mh-e.el (mh-scan-format-mh, mh-scan-good-msg-regexp) - (mh-scan-deleted-msg-regexp, mh-scan-refiled-msg-regexp) - (mh-scan-cur-msg-number-regexp, mh-scan-subject-regexp): - Use non-fontification instead of non-fontifying. - (mh-header-display): Use mh-mhl-format-file instead of - mhl-formfile. Sync docstrings with manual. - (mh-next-undeleted-msg, mh-previous-undeleted-msg): Rename arg to - count. Sync docstrings with manual. - (mh-refile-or-write-again): Use output from mh-write-msg-to-file - so that message doesn't change when using this command. - Sync docstrings with manual. - (mh-page-msg, mh-previous-page): Rename arg to lines. - Sync docstrings with manual. - (mh-write-msg-to-file): Rename msg to message. Rename no-headers - to no-header. Sync docstrings with manual. - (mh-ps-print-map): Delete keybindings for deleted commands - mh-ps-print-toggle-mime and mh-ps-print-msg-show. - (mh-help-messages): Update printing help. - (mh-delete-msg, mh-delete-msg-no-motion, mh-first-msg) - (mh-last-msg, mh-previous-unread-msg, mh-next-button) - (mh-prev-button, mh-folder-toggle-mime-part) - (mh-folder-inline-mime-part, mh-folder-save-mime-part) - (mh-next-unread-msg, mh-toggle-mime-buttons): Sync docstrings with - manual. - - * mh-funcs.el (mh-sortm-args): Now a customization option and in - mh-customize.el. - (mh-pipe-msg): Rename include-headers to include-header. - Sync docstrings with manual. - (mh-burst-digest, mh-page-digest, mh-page-digest-backwards) - (mh-store-msg): Sync docstrings with manual. - - * mh-mime.el (mh-mime-save-parts): Rename arg to prompt. - Sync docstrings with manual. - (mh-toggle-mh-decode-mime-flag): Use English in message, not Lisp. - Sync docstrings with manual. - (mh-mm-display-part, mh-mm-inline-message): - Use mh-highlight-citation-style instead of mh-highlight-citation-p. - (mh-press-button): Sync docstrings with manual. - (mh-display-with-external-viewer): Fix default output in - minibuffer. Sync docstrings with manual. - - * mh-print.el (mh-ps-print-mime, mh-ps-print-toggle-mime): - Delete. - (mh-ps-print-color-option): Incorporate docstring from - ps-print-color-p. - (mh-ps-spool-buffer): Remove unused code. Fix indent. - Slimline docstring. - (mh-ps-spool-msg): Slimline docstring. Rename from - mh-ps-spool-a-msg. Rewrite to use existing show buffer when - available. - (mh-ps-print-range): Extract method from common code in - mh-ps-print-msg and mh-ps-print-msg-file. - (mh-ps-print-preprint): Clean docstring. Use filename "mh-%s". - (mh-ps-print-msg-show): Delete. Can use either - mh-ps-print-msg-show or mh-ps-print-msg-show to same effect with - new code in mh-ps-spool-msg. - (mh-print-msg): Use mh-mhl-format-file instead of mhl-formfile. - Sync docstrings with manual. - (mh-ps-print-msg, mh-ps-print-msg-file) - (mh-ps-print-toggle-faces, mh-ps-print-toggle-color): - Sync docstrings with manual. - - * mh-utils.el (mh-show-ps-print-msg-show) - (mh-show-ps-print-toggle-mime): Delete. - (mh-show-ps-print-map): Update accordingly. - (mh-show-mode): Use mh-highlight-citation-style instead of - mh-highlight-citation-p. - (mh-show-xface, mh-display-msg): Use mh-mhl-format-file instead of - mhl-formfile. - (mh-show): Use mh-mhl-format-file instead of mhl-formfile. - Sync docstrings with manual. - (mh-show-font-lock-fontify-region, mh-modify, mh-goto-msg): - Sync docstrings with manual. - -2005-12-01 Bill Wohler - - * mh-init.el (mh-defface-compat): Checkdoc fix. - - * mh-junk.el (mh-bogofilter-blacklist, mh-bogofilter-whitelist): - Bogofilter is lowercase except at beginning of sentence and in - titles. - -2005-11-04 Bill Wohler - - * mh-customize.el (mh-min-colors-defined-flag, mh-defface-compat): - Move to mh-init.el to minimize bulk of mh-customize.el. - - * mh-init.el: Modify commentary since file is used for load and - initialization as well as setting and getting the variant. - (mh-min-colors-defined-flag, mh-defface-compat): Move here from - mh-customize.el. - - * mh-customize.el: Refactor faces. Move grayscale requirements - last before t. Use uniform line breaks. - (mh-min-colors-defined-flag): New variable. - (mh-defface-compat): New function. Provides backward compatibility - for face specs. - (mh-show-header, mh-show-date, mh-show-cc, mh-folder-to) - (mh-folder-refiled, mh-folder-cur-msg-number, mh-folder-cur-msg) - (mh-folder-body): Use mh-defface-compat. - -2005-11-03 Dan Nicolaescu - - * mh-customize.el (mh-folder-body-face, mh-folder-cur-msg-face) - (mh-folder-cur-msg-number-face, mh-folder-refiled-face) - (mh-folder-to-face): Use the min-colors attribute instead of the - type attribute. - -2005-11-03 Bill Wohler - - * mh-customize.el (mh-refile-preserves-sequences-flag) - (mh-tick-seq, mh-update-sequences-after-mh-show-flag): - Sync docstrings with manual. - - * mh-e.el (mh-update-sequences): Sync docstrings with manual. - - * mh-seq.el (mh-delete-seq, mh-list-sequences, mh-narrow-to-seq) - (mh-widen, mh-toggle-tick, mh-narrow-to-tick): Sync docstrings - with manual. - -2005-11-01 Bill Wohler - - * mh-comp.el (mh-redist-full-contents) Convert defvar to - defcustom. - (mh-smail, mh-extract-rejected-mail, mh-forward, mh-redistribute) - (mh-reply, mh-send, mh-send-other-window) - (mh-fill-paragraph-function): Sync docstrings with manual. - (mh-edit-again, mh-extract-rejected-mail, mh-redistribute): - Rename msg argument to message (to make for a better docstring). - - * mh-customize.el (mh-redist-full-contents-flag): Convert defvar - to defcustom. Rename by adding -flag. - (mh-compose-forward-as-mime-flag) - (mh-compose-letter-function, mh-forward-subject-format) - (mh-insert-x-mailer-flag, mh-reply-default-reply-to) - (mh-reply-show-message-flag, mh-letter-mode-hook): Sync docstrings - with manual. - - * mh-print.el (mh-ps-spool-buffer, mh-ps-spool-a-msg) - (mh-ps-print-msg): Remove debugging messages. - (mh-ps-print-msg-show, mh-ps-print-msg-show) - (mh-ps-print-toggle-color, mh-ps-print-toggle-mime): Remove period - after message per conventions. - -2005-10-30 Bill Wohler - - * mh-e.el (mh-scan-good-msg-regexp, mh-scan-deleted-msg-regexp) - (mh-scan-refiled-msg-regexp, mh-scan-cur-msg-number-regexp): - Sync docstrings with manual. - - * mh-customize.el (mh-compose-space-does-completion-flag) - (mh-signature-separator-flag, mh-interpret-number-as-range-flag) - (mh-adaptive-cmd-note-flag): Use "Non-nil means" instead of "On - means" to remain checkdoc clean and consistent with Emacs. - I raised this issue with the Emacs developers and Stallman agrees - that "On means" should be allowed in custom docstrings but that - this change requires thought and should wait until after the Emacs - 22 release. - -2005-10-28 Bill Wohler - - * mh-comp.el (mh-annotate-msg): Use new variable - mh-scan-field-destination-offset rather than hard-coding 1. - - * mh-customize.el (mh-interpret-number-as-range-flag): Add * to - docstring. - (mh-adaptive-cmd-note-flag-check, mh-scan-format-file-check): - New functions to check input for mh-adaptive-cmd-note-flag and - mh-scan-format-file respectively. - (mh-adaptive-cmd-note-flag, mh-scan-format-file): Docstring fixes, - add :set. - - * mh-e.el (mh-scan-field-destination-offset): New variable. - The destination is the -, t, b, c, or n character for Replied, To, cc, - Bcc, or Newsgroups respectively. - (mh-make-folder, mh-regenerate-headers, mh-generate-new-cmd-note): - Call new function mh-msg-num-width-to-column to make leap between - width and column more explicit. - (mh-msg-num-width-to-column): New function that steals logic from - old mh-set-cmd-note. Also, throw error if mh-scan-format-file - isn't t since we can't adapt the scan lines in this case. - (mh-set-cmd-note): Now just simply sets mh-cmd-note which will - make the documentation more clear. - (mh-generate-new-cmd-note): Docstring fix--mh-cmd-note is a - column, not a width. - (mh-add-sequence-notation, mh-remove-sequence-notation): Use new - variable mh-scan-field-destination-offset rather than hard-coding 1. - - * mh-utils.el (mh-cmd-note) Synced docstring with manual. - (mh-notate): Use new variable mh-scan-field-destination-offset - rather than hard-coding 1. - (mh-message-number-width): Rename to mh-msg-num-width to be - consistent with mh-get-msg-num and mh-msg-num-width-to-column. - - * mh-customize.el (mh-x-face-file, mh-show-use-xface-flag) - (mail-citation-hook): Quote URLs in docstrings and precede with - `URL'. The former will suppress checkdoc warnings, the latter will - turn them into hyperlinks in Emacs 22 (I just added the code to do - that today). - (mh-scan-format-file): Checkdoc fix. - -2005-10-27 Bill Wohler - - * mh-customize.el (mh-adaptive-cmd-note-flag) - (mh-scan-format-file, mh-scan-prog): Sync docstrings with manual. - - * mh-e.el (mh-scan-format-mh, mh-note-deleted, mh-note-refiled) - (mh-note-cur, mh-scan-good-msg-regexp) - (mh-scan-deleted-msg-regexp, mh-scan-refiled-msg-regexp) - (mh-scan-valid-regexp, mh-scan-cur-msg-number-regexp) - (mh-scan-date-regexp, mh-scan-rcpt-regexp, mh-scan-body-regexp) - (mh-scan-subject-regexp, mh-scan-format-regexp) - (mh-folder-font-lock-keywords, mh-set-cmd-note): Sync docstrings - with manual. - - * mh-funcs.el (mh-note-copied): Sync docstrings with manual. - - * mh-utils.el (mh-goto-msg): Use mh-scan-msg-search-regexp instead - of hard-coded string. - (mh-mail-header-separator, mh-signature-separator-regexp): - Use "regular expression" in docstring instead of regexp. - (mh-scan-msg-number-regexp) - (mh-scan-msg-overflow-regexp, mh-scan-msg-format-regexp) - (mh-scan-msg-format-string, mh-scan-msg-search-regexp) - (mh-cmd-note): Sync docstrings with manual. - - * mh-comp.el (mh-insert-signature, mh-insert-auto-fields): - Checkdoc fixes. - - * mh-customize.el (mh-compose-insertion, mh-x-face-file): Ditto. - - * mh-mime.el (mh-mh-to-mime, mh-mml-attach-file) - (mh-mml-secure-message-sign, mh-mml-secure-message-encrypt) - (mh-mml-secure-message-signencrypt): Ditto. - -2005-10-24 Bill Wohler - - * mh-gnus.el: Load mml.el in order to see if - mml-minibuffer-read-disposition is defined or not. - - * mh-mime.el: Now that mh-gnus.el loads mml, we shouldn't need the - mml autoloads. - -2005-10-23 Miles Bader - - * .arch-inventory: New file. - -2005-10-23 Bill Wohler - - * mh-customize.el (mh-interpret-number-as-range-flag): - Sync docstring with manual. - - * mh-identity.el (mh-assoc-ignore-case): Merge with version in - mh-alias.el and move to mh-acros.el. - - * mh-alias.el (mh-assoc-ignore-case): Merge with version in - mh-identity.el and move to mh-acros.el. - - * mh-acros.el (mh-assoc-ignore-case): Merge of function from - mh-identity.el and mh-alias.el. - - * mh-mime.el: Autoload mm-uu for mm-uu-dissect to avoid compiler - warning in Emacs 22. - -2005-10-23 Satyaki Das - - * mh-identity.el (mh-assoc-ignore-case): New macro that uses - assoc-string (if the function is available) and falls back on - assoc-ignore-case if assoc-string is not found. - (mh-identity-field-handler): Use mh-assoc-ignore-case since - assoc-ignore-case is a obsolete function in Emacs 22. - - * mh-e.el (mh-folder-buttons-init-flag): New variable that keeps - track of whether the tool-bar in mh-folder-mode has been - initialized yet. - (mh-folder-mode): Initialize the tool-bar for folders the first - time we get into mh-letter-mode. - - * mh-customize.el (mh-buffer-exists-p): New function which tests - presence of buffers of a given mode. - (mh-tool-bar-define): New functions mh-tool-bar-folder-buttons-init and - mh-tool-bar-letter-buttons-init are defined. These functions are - used to create the tool-bar from the corresponding customizable - variables. - - * mh-comp.el (mh-letter-buttons-init-flag): New variable that - keeps track of whether the tool-bar in mh-letter-mode has been - initialized yet. - (mh-letter-mode): Initialize the tool-bar for drafts the first - time we get into mh-letter-mode. - -2005-10-23 Bill Wohler - - * mh-comp.el (mh-letter-menu): - Rename mh-mhn-compose-external-compressed-tar to - mh-mh-compose-external-compressed-tar. - Rename mh-mhn-compose-anon-ftp to mh-mh-compose-anon-ftp. Rename - mh-edit-mhn to mh-mh-to-mime. Rename mh-mhn-directive-present-p to - mh-mh-directive-present-p. Rename mh-revert-mhn-edit to - mh-mh-to-mime-undo. Rename mh-gnus-pgp-support-flag to - mh-pgp-support-flag. Rename mh-compose-insertion value from 'mhn - to 'mh. - (mh-insert-signature): Rename mh-mhn-directive-present-p to - mh-mh-directive-present-p. - (mh-send-letter): Rename mh-mhn-directive-present-p to - mh-mh-directive-present-p. Rename mh-edit-mhn to mh-mh-to-mime. - (mh-letter-mode-map): Rename mh-edit-mhn to mh-mh-to-mime. - Rename mh-mhn-compose-anon-ftp to mh-mh-compose-anon-ftp. - Rename mh-mhn-compose-external-compressed-tar to - mh-mh-compose-external-compressed-tar. Rename mh-revert-mhn-edit - to mh-mh-to-mime-undo. Rename mh-mhn-compose-external-type to - mh-mh-compose-external-type. Rename mh-mhn-compose-anon-ftp to - mh-mh-compose-anon-ftp. - Rename mh-mhn-compose-external-compressed-tar to - mh-mh-compose-external-compressed-tar. Rename mh-revert-mhn-edit - to mh-mh-to-mime-undo. Rename mh-mhn-compose-external-type to - mh-mh-compose-external-type. - (mh-send-letter, mh-letter-mode-map): Rename mh-edit-mhn to - mh-mh-to-mime, mh-revert-mhn-edit to mh-mh-to-mime-undo. - (mh-reply, mh-yank-cur-msg, mh-insert-prefix-string): - Rename mh-yank-from-start-of-msg to mh-yank-behavior. - (mh-letter-mode, mh-to-field, mh-to-fcc, mh-insert-signature) - (mh-check-whom, mh-insert-auto-fields, mh-send-letter) - (mh-insert-letter, mh-yank-cur-msg, mh-insert-prefix-string) - (mh-fully-kill-draft, mh-open-line, mh-letter-complete) - (mh-letter-complete-or-space, mh-letter-confirm-address) - (mh-letter-next-header-field-or-indent) - (mh-letter-previous-header-field) - (mh-letter-toggle-header-field-display): Sync docstrings with - manual. - - * mh-customize.el (mh-edit-mhn-hook): Rename to - mh-mh-to-mime-hook. - (mh-yank-from-start-of-msg): Rename to mh-yank-behavior. - (mh-compose-insertion): Rename values from 'gnus and 'mhn to 'mh - and user-visible values from mhn and Gnus to MH and MML. - (mh-before-send-letter-hook): Add 'ispell-message option. - (mh-mml-method-default): Rename mh-gnus-pgp-support-flag to - mh-pgp-support-flag. - (mh-compose-insertion, mh-compose-space-does-completion-flag) - (mh-delete-yanked-msg-window-flag) - (mh-extract-from-attribution-verb, mh-ins-buf-prefix) - (mh-letter-complete-function, mh-letter-fill-column) - (mh-mml-method-default, mh-signature-file-name) - (mh-signature-separator-flag, mh-x-face-file) - (mh-yank-behavior, mail-citation-hook) - (mh-before-send-letter-hook, mh-mh-to-mime-hook): Sync docstrings - with manual. - - * mh-gnus.el (mml-minibuffer-read-disposition): New function - provided for Emacs 21 environments that lack it. - - * mh-mime.el (mh-mml-query-cryptographic-method): Use default - prompt convention. - (mh-compose-forward): mh-mh-forward-message requires string arg. - (mh-minibuffer-read-type): New function. - (mh-mhn-args): Rename to mh-mh-to-mime-args. - (mh-mhn-compose-insertion): Rename to mh-mh-attach-file. - (mh-mhn-compose-forw): Rename to mh-mh-forward-message. - (mh-mhn-compose-type): Rename to mh-mh-compose-type. - (mh-mhn-compose-anon-ftp): Rename to mh-mh-compose-anon-ftp. - Rename mh-mhn-compose-external-type to mh-mh-compose-external-type. - (mh-mhn-compose-external-compressed-tar): Rename to - mh-mh-compose-external-compressed-tar. - Rename mh-mhn-compose-external-type to mh-mh-compose-external-type. - (mh-mhn-compose-external-type): Rename to mh-mh-compose-external-type. - (mh-edit-mhn): Rename to mh-mh-to-mime. Rename mh-mhn-args to - mh-mh-to-mime-args. Rename mh-edit-mhn-hook to mh-mh-to-mime-hook. - Use correct program in message. - (mh-mhn-directive-present-p): Rename to mh-mh-directive-present-p. - (mh-mml-directive-present-p): Rename to mh-mml-tag-present-p. - (mh-compose-forward, mh-mh-attach-file) - (mh-mh-compose-anon-ftp, mh-mh-compose-external-compressed-tar) - (mh-mh-compose-external-type, mh-mh-forward-message) - (mh-mml-attach-file): Use mml-minibuffer-read-description, - mh-minibuffer-read-type. - (mh-mime-content-types): Move comment about only being used in - Emacs 20 to docstring. - (mh-mh-compose-external-type): Rename extra-param argument to - parameters. - (mh-mml-to-mime, mh-secure-message, mh-mml-unsecure-message) - (mh-mime-display-part, mh-mime-display-single): - Rename mh-gnus-pgp-support-flag to mh-pgp-support-flag. - (mh-compose-insertion): Rename mh-mhn-compose-insertion to - mh-mh-attach-file. - (mh-compose-forward): Rename mh-mhn-compose-forw to - mh-mh-forward-message. - (mh-mhn-compose-insertion): Rename mh-mhn-compose-type to - mh-mh-compose-type. - (mh-compose-insertion, mh-compose-forward, mh-mh-to-mime-args) - (mh-mh-attach-file, mh-mh-compose-type) - (mh-mh-compose-anon-ftp, mh-mh-compose-external-compressed-tar) - (mh-mh-compose-external-compressed-tar) - (mh-mh-compose-external-type, mh-mh-forward-message) - (mh-mh-to-mime, mh-mh-quote-unescaped-sharp) - (mh-mh-to-mime-undo, mh-mh-directive-present-p, mh-mml-to-mime) - (mh-mml-attach-file, mh-secure-message, mh-mml-unsecure-message) - (mh-mml-secure-message-sign, mh-mml-secure-message-encrypt) - (mh-mml-directive-present-p, mh-destroy-postponed-handles) - (mh-display-smileys, mh-display-emphasis, mh-mime-save-parts): - Sync docstrings with manual. - - * mh-utils.el (mh-gnus-pgp-support-flag): Rename to - mh-pgp-support-flag. - -2005-10-17 Peter S Galbraith - - * mh-identity.el (mh-identity-field-handler): Use `assoc-ignore-case' - to compare against header field for mixed-case "From:". - -2005-10-17 Bill Wohler - - * mh-customize.el (mh-folder-tool-bar-map): Rename image file - left_arrow to left-arrow, right_arrow to right-arrow, mail_compose - to mail/compose, fld_open to fld-open. - (mh-letter-tool-bar-map): Rename image file mail_send to - mail/send. - -2005-10-16 Bill Wohler - - * mh-comp.el (mh-display-completion-list-compat): New macro which - calls `display-completion-list' correctly in older environments. - Versions of Emacs prior to version 22 lacked a COMMON-SUBSTRING - argument. - (mh-complete-word): Use it. - - * mh-init.el (mh-image-load-path): Use locate-library to find - MH-E. This simplified the code a lot. Flattened out nested - statements even more. - -2005-10-16 Satyaki Das - - * mh-init.el (mh-image-load-path): Remove use of pushnew since it - causes a compiler warning. - - * mh-utils.el (mh-display-msg): Do MIME cleanup before inserting - the message to be viewed (closes SF #1306141). - -2005-10-16 Masatake YAMATO - - * mh-comp.el (mh-complete-word): Pass the common prefix substring - of completion to `display-completion-list'. - -2005-10-15 Satyaki Das - - * mh-init.el (mh-image-load-path-called-flag): New variable which - is used by mh-image-load-path so that it runs only once. - (mh-image-load-path): Modify so that it gets run only once. - Also flatten out heavily nested if statements to make it clearer. - - * mh-e.el (mh-folder-mode): Call mh-image-load-path to allow Emacs - to find images used in the toolbar. - - * mh-customize.el (:folder): Remove call to mh-image-load-path. - -2005-10-14 Bill Wohler - - * mh-e.el (Version, mh-version): Add +cvs to version. - -2005-10-14 Bill Wohler - - Released MH-E version 7.85. - - * mh-e.el (Version, mh-version): Update for release 7.85. - -2005-10-14 Bill Wohler - - * mh-e.el, mh-funcs.el, mh-init.el, mh-mime.el, mh-pick.el: - * mh-seq.el, mh-utils.el: Ran mh-unit. Continued copyright lines - need to be indented. - - * mh-e.el: mh-folder-tick-face had been renamed to mh-folder-tick - but the code that invoked the face had not been updated. - Tick highlighting working again. - - * mh-seq.el (mh-non-seq-mode-line-annotation): - Move make-variable-buffer-local call to top level to avoid warnings in - CVS Emacs. - - * mh-comp.el (mh-insert-letter): Replace deprecated read-input - with read-string. - -2005-10-09 Bill Wohler - - * mh-init.el (mh-image-load-path): New function that adds the path - to the MH-E images to the image-load-path or load-path depending - on the version of Emacs. - - * mh-customize.el: Call mh-image-load-path just before - mh-tool-bar-define so that the toolbar images can be found. - -2005-10-06 Bill Wohler - - * mh-loaddefs.el: Remove. Now generated automatically. - -2005-10-04 Bill Wohler - - * ChangeLog: Move contents into ChangeLog.1 and trim. - - * ChangeLog.1: New file. Contains old ChangeLog. - -See ChangeLog.1 for earlier changes. - - Copyright (C) 2005-2024 Free Software Foundation, Inc. - - This file is part of GNU Emacs. - - GNU Emacs is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - GNU Emacs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNU Emacs. If not, see . - -;; Local Variables: -;; coding: utf-8 -;; sentence-end-double-space: nil -;; add-log-time-zone-rule: t -;; End: diff --git a/lisp/mh-e/mh-acros.el b/lisp/mh-e/mh-acros.el deleted file mode 100644 index 8f582df128d..00000000000 --- a/lisp/mh-e/mh-acros.el +++ /dev/null @@ -1,221 +0,0 @@ -;;; mh-acros.el --- macros used in MH-E -*- lexical-binding: t; -*- - -;; Copyright (C) 2004, 2006-2024 Free Software Foundation, Inc. - -;; Author: Satyaki Das -;; Maintainer: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; This file contains all macros that are used in more than one file. -;; If you run "make recompile" in Bazaar Emacs and see the message -;; "Source is newer than compiled," it is a sign that macro probably -;; needs to be moved here. - -;; Historically, it was so named with a silent "m" so that it would be -;; compiled first. Otherwise, "make recompile" in Bazaar Emacs would use -;; compiled files with stale macro definitions. Later, no-byte-compile -;; was added to the Local Variables section to avoid this problem and -;; because it's pointless to compile a file full of macros. But we -;; kept the name. - -;;; Code: - -(require 'cl-lib) - - - -;;; Miscellaneous - -;;;###mh-autoload -(defmacro with-mh-folder-updating (save-modification-flag &rest body) - "Format is (with-mh-folder-updating (SAVE-MODIFICATION-FLAG) &body BODY). -Execute BODY, which can modify the folder buffer without having to -worry about file locking or the read-only flag, and return its result. -If SAVE-MODIFICATION-FLAG is non-nil, the buffer's modification flag -is unchanged, otherwise it is cleared." - (declare (debug t) (indent defun)) - (setq save-modification-flag (car save-modification-flag)) ; CL style - `(prog1 - (let ((mh-folder-updating-mod-flag (buffer-modified-p)) - (buffer-read-only nil) - (buffer-file-name nil)) ;don't let the buffer get locked - (prog1 - (progn - ,@body) - (mh-set-folder-modified-p mh-folder-updating-mod-flag))) - ,@(if (not save-modification-flag) - '((mh-set-folder-modified-p nil))))) - -;;;###mh-autoload -(defmacro mh-in-show-buffer (show-buffer &rest body) - "Format is (mh-in-show-buffer (SHOW-BUFFER) &body BODY). -Display buffer SHOW-BUFFER in other window and execute BODY in it. -Stronger than `save-excursion', weaker than `save-window-excursion'." - (declare (debug t) (indent defun)) - (setq show-buffer (car show-buffer)) ; CL style - `(let ((mh-in-show-buffer-saved-window (selected-window))) - (switch-to-buffer-other-window ,show-buffer) - (if mh-bury-show-buffer-flag (bury-buffer (current-buffer))) - (unwind-protect - (progn - ,@body) - (select-window mh-in-show-buffer-saved-window)))) - -;;;###mh-autoload -(defmacro mh-do-at-event-location (event &rest body) - "Switch to the location of EVENT and execute BODY. -After BODY has been executed return to original window. -The modification flag of the buffer in the event window is -preserved." - (declare (debug t) (indent defun)) - (let ((event-window (make-symbol "event-window")) - (event-position (make-symbol "event-position")) - (original-window (make-symbol "original-window")) - (original-position (make-symbol "original-position")) - (modified-flag (make-symbol "modified-flag"))) - `(save-excursion - (let* ((,event-window (posn-window (event-start ,event))) - (,event-position (posn-point (event-start ,event))) - (,original-window (selected-window)) - (,original-position (progn - (set-buffer (window-buffer ,event-window)) - (point-marker))) - (,modified-flag (buffer-modified-p)) - (buffer-read-only nil)) - (unwind-protect (progn - (select-window ,event-window) - (goto-char ,event-position) - ,@body) - (set-buffer-modified-p ,modified-flag) - (goto-char ,original-position) - (set-marker ,original-position nil) - (select-window ,original-window)))))) - - - -;;; Sequences and Ranges - -;;;###mh-autoload -(defsubst mh-seq-msgs (sequence) - "Extract messages from the given SEQUENCE." - (cdr sequence)) - -;;;###mh-autoload -(defmacro mh-iterate-on-messages-in-region (var begin end &rest body) - "Iterate over region. - -VAR is bound to the message on the current line as we loop -starting from BEGIN till END. In each step BODY is executed. - -If VAR is nil then the loop is executed without any binding." - (declare (debug (symbolp body)) (indent defun)) - (unless (symbolp var) - (error "Can not bind the non-symbol %s" var)) - (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))))) - -;;;###mh-autoload -(defmacro mh-iterate-on-range (var range &rest body) - "Iterate an operation over a region or sequence. - -VAR is bound to each message in turn in a loop over RANGE, which -can be a message number, a list of message numbers, a sequence, a -region in a cons cell, or a MH range (something like last:20) in -a string. In each iteration, BODY is executed. - -The parameter RANGE is usually created with -`mh-interactive-range' in order to provide a uniform interface to -MH-E functions." - (declare (debug (symbolp body)) (indent defun)) - (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 ,range) - (when (mh-goto-msg ,range t t) - (let ,(if binding-needed-flag `((,var ,range)) ()) - ,@body))) - ((and (consp ,range) - (numberp (car ,range)) (numberp (cdr ,range))) - (mh-iterate-on-messages-in-region ,var - (car ,range) (cdr ,range) - ,@body)) - (t (let ((,msgs (cond ((and ,range (symbolp ,range)) - (mh-seq-to-msgs ,range)) - ((stringp ,range) - (mh-translate-range mh-current-folder - ,range)) - (t ,range))) - (,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)))))))) - -(defmacro mh-dlet* (binders &rest body) - "Like `let*' but always dynamically scoped." - (declare (debug let) (indent 1)) - ;; Works in both lexical and non-lexical mode. - `(progn - (with-suppressed-warnings ((lexical - ,@(mapcar (lambda (binder) - (if (consp binder) - (car binder) - binder)) - binders))) - ,@(mapcar (lambda (binder) - `(defvar ,(if (consp binder) (car binder) binder))) - binders) - (let* ,binders ,@body)))) - -;; Emacs 24 made flet obsolete and suggested either cl-flet or -;; cl-letf. This macro is based upon gmm-flet from Gnus. -(defmacro mh-flet (bindings &rest body) - "Make temporary overriding function definitions. -That is, temporarily rebind the functions listed in BINDINGS and then -execute BODY. BINDINGS is a list containing one or more lists of the -form (FUNCNAME ARGLIST BODY...), similar to defun." - (declare (indent 1) (debug ((&rest (sexp sexp &rest form)) &rest form))) - (if (fboundp 'cl-letf) - `(cl-letf ,(mapcar (lambda (binding) - `((symbol-function ',(car binding)) - (lambda ,@(cdr binding)))) - bindings) - ,@body) - `(flet ,bindings ,@body))) - -(provide 'mh-acros) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-acros.el ends here diff --git a/lisp/mh-e/mh-alias.el b/lisp/mh-e/mh-alias.el deleted file mode 100644 index 023bccad71a..00000000000 --- a/lisp/mh-e/mh-alias.el +++ /dev/null @@ -1,664 +0,0 @@ -;;; mh-alias.el --- MH-E mail alias completion and expansion -*- lexical-binding: t; -*- - -;; Copyright (C) 1994-1997, 2001-2024 Free Software Foundation, Inc. - -;; Author: Peter S. Galbraith -;; Maintainer: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;;; Code: - -(require 'mh-e) - -(require 'goto-addr) - -(defvar mh-alias-alist 'not-read - "Alist of MH aliases.") -(defvar mh-alias-blind-alist nil - "Alist of MH aliases that are blind lists.") -(defvar mh-alias-passwd-alist nil - "Alist of aliases extracted from passwd file and their expansions.") -(defvar mh-alias-tstamp nil - "Time aliases were last loaded.") -(defvar mh-alias-read-address-map - (let ((map (copy-keymap minibuffer-local-completion-map))) - (define-key map "," #'mh-alias-minibuffer-confirm-address) - (define-key map " " #'self-insert-command) - map)) - -(defcustom mh-alias-system-aliases - '("/etc/nmh/MailAliases" "/etc/mh/MailAliases" - "/usr/lib/mh/MailAliases" "/usr/share/mailutils/mh/MailAliases" - "/etc/passwd") - "A list of system files which are a source of aliases. -If these files are modified, they are automatically reread. This list -need include only system aliases and the passwd file, since personal -alias files listed in your \"Aliasfile:\" MH profile component are -automatically included. You can update the alias list manually using -\\[mh-alias-reload]." - :type '(repeat file) - :group 'mh-alias) - - - -;;; Alias Loading - -(defun mh-alias-tstamp (arg) - "Check whether alias files have been modified. -Return t if any file listed in the Aliasfile MH profile component has -been modified since the timestamp. -If ARG is non-nil, set timestamp with the current time." - (if arg - (setq mh-alias-tstamp (current-time)) - (let ((stamp)) - (car (memq t (mapcar - (lambda (file) - (when (and file (file-exists-p file)) - (setq stamp (file-attribute-modification-time - (file-attributes file))) - (time-less-p mh-alias-tstamp stamp))) - (mh-alias-filenames t))))))) - -(defun mh-alias-filenames (arg) - "Return list of filenames that contain aliases. -The filenames come from the Aliasfile profile component and are -expanded. -If ARG is non-nil, filenames listed in `mh-alias-system-aliases' are -appended." - (or mh-progs (mh-find-path)) - (save-excursion - (let* ((filename (mh-profile-component "Aliasfile")) - (filelist (and filename (split-string filename "[ \t]+"))) - (userlist - (mapcar - (lambda (file) - (if (and mh-user-path file - (file-exists-p (expand-file-name file mh-user-path))) - (expand-file-name file mh-user-path))) - filelist))) - (if arg - (if (stringp mh-alias-system-aliases) - (append userlist (list mh-alias-system-aliases)) - (append userlist mh-alias-system-aliases)) - userlist)))) - -(defun mh-alias-gecos-name (gecos-name username comma-separator) - "Return a usable address string from a GECOS-NAME and USERNAME. -Use only part of the GECOS-NAME up to the first comma if -COMMA-SEPARATOR is non-nil." - (let ((res gecos-name)) - ;; Keep only string until first comma if COMMA-SEPARATOR is t. - (if (and comma-separator - (string-match "^\\([^,]+\\)," res)) - (setq res (match-string 1 res))) - ;; Replace "&" with capitalized username - (if (string-search "&" res) - (setq res (replace-regexp-in-string "&" (capitalize username) res))) - ;; Remove " character - (if (string-search "\"" res) - (setq res (replace-regexp-in-string "\"" "" res))) - ;; If empty string, use username instead - (if (string-equal "" res) - (setq res username)) - ;; Surround by quotes if doesn't consist of simple characters - (if (not (string-match "^[ a-zA-Z0-9-]+$" res)) - (setq res (concat "\"" res "\""))) - res)) - -(defun mh-alias-local-users () - "Return an alist of local users from /etc/passwd. -Exclude all aliases already in `mh-alias-alist' from \"ali\"" - (let (passwd-alist) - (with-current-buffer (get-buffer-create mh-temp-buffer) - (erase-buffer) - (cond - ((eq mh-alias-local-users t) - (if (file-readable-p "/etc/passwd") - (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 t) - (goto-char (point-min)))) - (while (< (point) (point-max)) - (cond - ((looking-at "\\([^:]*\\):[^:]*:\\([^:]*\\):[^:]*:\\([^:]*\\):") - (when (> (string-to-number (match-string 2)) 200) - (let* ((username (match-string 1)) - (gecos-name (match-string 3)) - (realname (mh-alias-gecos-name - gecos-name username - mh-alias-passwd-gecos-comma-separator-flag)) - (alias-name (if mh-alias-local-users-prefix - (concat mh-alias-local-users-prefix - (mh-alias-suggest-alias realname t)) - username)) - (alias-translation - (if (string-equal username realname) - (concat "<" username ">") - (concat realname " <" username ">")))) - (when (not (assoc-string alias-name mh-alias-alist t)) - (setq passwd-alist (cons (list alias-name alias-translation) - passwd-alist))))))) - (forward-line 1))) - passwd-alist)) - -(defun mh-alias-reload () - "Reload MH aliases. - -Since aliases are updated frequently, MH-E reloads aliases -automatically whenever an alias lookup occurs if an alias source has -changed. Sources include files listed in your \"Aliasfile:\" profile -component and your password file if option `mh-alias-local-users' is -turned on. However, you can reload your aliases manually by calling -this command directly. - -This function runs `mh-alias-reloaded-hook' after the aliases have -been loaded." - (interactive) - (save-excursion - (message "Loading MH aliases...") - (mh-alias-tstamp t) - (mh-exec-cmd-quiet t "ali" "-nolist" "-nouser") - (setq mh-alias-alist nil) - (setq mh-alias-blind-alist nil) - (while (< (point) (point-max)) - (cond - ((looking-at "^[ \t]")) ;Continuation line - ((looking-at "\\(.+\\): .+: .*$") ; A new -blind- MH alias - (when (not (assoc-string (match-string 1) mh-alias-blind-alist t)) - (setq mh-alias-blind-alist - (cons (list (match-string 1)) mh-alias-blind-alist)) - (setq mh-alias-alist (cons (list (match-string 1)) mh-alias-alist)))) - ((looking-at "\\(.+\\): .*$") ; A new MH alias - (when (not (assoc-string (match-string 1) mh-alias-alist t)) - (setq mh-alias-alist - (cons (list (match-string 1)) mh-alias-alist))))) - (forward-line 1))) - (when mh-alias-local-users - (setq mh-alias-passwd-alist (mh-alias-local-users)) - ;; Update aliases with local users, but leave existing aliases alone. - (let ((local-users mh-alias-passwd-alist) - user) - (while local-users - (setq user (car local-users)) - (if (not (assoc-string (car user) mh-alias-alist t)) - (setq mh-alias-alist (append mh-alias-alist (list user)))) - (setq local-users (cdr local-users))))) - (run-hooks 'mh-alias-reloaded-hook) - (message "Loading MH aliases...done")) - -;;;###mh-autoload -(defun mh-alias-reload-maybe () - "Load new MH aliases." - (if (or (eq mh-alias-alist 'not-read) ; Doesn't exist? - (mh-alias-tstamp nil)) ; Out of date? - (mh-alias-reload))) - - - -;;; Alias Expansion - -(defun mh-alias-ali (alias &optional user) - "Return ali expansion for ALIAS. -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." - (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-char -1)) - (buffer-substring (point-min)(point-max))) - (error (progn - (message "%s" (error-message-string err)) - alias)))) - -;;;###mh-autoload -(defun mh-alias-expand (alias) - "Return expansion for ALIAS. -Blind aliases or users from /etc/passwd are not expanded." - (cond - ((assoc-string alias mh-alias-blind-alist t) - alias) ; Don't expand a blind alias - ((assoc-string alias mh-alias-passwd-alist t) - (cadr (assoc-string alias mh-alias-passwd-alist t))) - (t - (mh-alias-ali alias)))) - -;;;###mh-autoload -(defun mh-read-address (prompt) - "Read an address from the minibuffer with PROMPT." - (mh-alias-reload-maybe) - (if (not mh-alias-alist) ; If still no aliases, just prompt - (read-string prompt) - (let* ((minibuffer-local-completion-map mh-alias-read-address-map) - (completion-ignore-case mh-alias-completion-ignore-case-flag) - (the-answer (completing-read-multiple 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 alias or blind first - (mapconcat #'mh-alias-expand the-answer ",\n "))))) - -;;;###mh-autoload -(defun mh-alias-minibuffer-confirm-address () - "Display the alias expansion if `mh-alias-flash-on-comma' is non-nil." - (interactive) - (when mh-alias-flash-on-comma - (save-excursion - (let* ((case-fold-search t) - (beg (mh-beginning-of-word)) - (the-name (buffer-substring-no-properties beg (point)))) - (if (assoc-string the-name mh-alias-alist t) - (message "%s -> %s" the-name (mh-alias-expand the-name)) - ;; Check if it was a single word likely to be an alias - (if (and (equal mh-alias-flash-on-comma 1) - (not (string-search " " the-name))) - (message "No alias for %s" the-name)))))) - (self-insert-command 1)) - -;;;###mh-autoload -(defun mh-alias-letter-expand-alias () - "Expand mail alias before point." - (mh-alias-reload-maybe) - (let* ((begin (mh-beginning-of-word)) - (end (save-excursion - (goto-char begin) - (mh-beginning-of-word -1)))) - (when (>= end (point)) - (list - begin (if (fboundp 'completion-at-point) end (point)) - (if (not mh-alias-expand-aliases-flag) - mh-alias-alist - (lambda (string pred action) - (cl-case action - ((nil) - (let ((res (try-completion string mh-alias-alist pred))) - (if (or (eq res t) - (and (stringp res) - (eq t (try-completion res mh-alias-alist pred)))) - (or (mh-alias-expand (if (stringp res) res string)) - res) - res))) - ((t) (all-completions string mh-alias-alist pred)) - ((lambda) (test-completion string mh-alias-alist pred))))))))) - - -;;; Alias File Updating - -(defun mh-alias-suggest-alias (string &optional no-comma-swap) - "Suggest an alias for STRING. -Don't reverse the order of strings separated by a comma if -NO-COMMA-SWAP is non-nil." - (cond - ((string-match "^<\\(.*\\)>$" string) - ;; -> recurse, stripping brackets. - (mh-alias-suggest-alias (match-string 1 string) no-comma-swap)) - ((string-match "^\\sw+$" string) - ;; One word -> downcase it. - (downcase string)) - ((string-match "^\\(\\sw+\\)\\s-+\\(\\sw+\\)$" string) - ;; Two words -> first.last - (downcase - (format "%s.%s" (match-string 1 string) (match-string 2 string)))) - ((string-match "^\\([-a-zA-Z0-9._]+\\)@[-a-zA-Z0-9_]+\\.+[a-zA-Z0-9]+$" - string) - ;; email only -> downcase username - (downcase (match-string 1 string))) - ((string-match "^\"\\(.*\\)\".*" string) - ;; "Some name" -> recurse -> "Some name" - (mh-alias-suggest-alias (match-string 1 string) no-comma-swap)) - ((string-match "^\\(.*\\) +<.*>$" string) - ;; Some name -> recurse -> Some name - (mh-alias-suggest-alias (match-string 1 string) no-comma-swap)) - ((string-match (concat goto-address-mail-regexp " +(\\(.*\\))$") string) - ;; somename@foo.bar (Some name) -> recurse -> Some name - (mh-alias-suggest-alias (match-string 1 string) no-comma-swap)) - ((string-match "^\\(Dr\\|Prof\\)\\.? +\\(.*\\)" string) - ;; Strip out title - (mh-alias-suggest-alias (match-string 2 string) no-comma-swap)) - ((string-match "^\\(.*\\), +\\(Jr\\.?\\|II+\\)$" string) - ;; Strip out tails with comma - (mh-alias-suggest-alias (match-string 1 string) no-comma-swap)) - ((string-match "^\\(.*\\) +\\(Jr\\.?\\|II+\\)$" string) - ;; Strip out tails - (mh-alias-suggest-alias (match-string 1 string) no-comma-swap)) - ((string-match "^\\(\\sw+\\) +[A-Z]\\.? +\\(.*\\)$" string) - ;; Strip out initials - (mh-alias-suggest-alias - (format "%s %s" (match-string 1 string) (match-string 2 string)) - no-comma-swap)) - ((and (not no-comma-swap) - (string-match "^\\([^,]+\\), +\\(.*\\)$" string)) - ;; Reverse order of comma-separated fields to handle: - ;; From: "Galbraith, Peter" - ;; but don't this for a name string extracted from the passwd file - ;; with mh-alias-passwd-gecos-comma-separator-flag set to nil. - (mh-alias-suggest-alias - (format "%s %s" (match-string 2 string) (match-string 1 string)) - no-comma-swap)) - (t - ;; Output string, with spaces replaced by dots. - (mh-alias-canonicalize-suggestion string)))) - -(defun mh-alias-canonicalize-suggestion (string) - "Process STRING to replace spaces by periods. -First all spaces and commas 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)) - (while (re-search-forward " +" nil t) - (replace-match "." nil nil)) - ;; Replace commas with periods - (goto-char (point-min)) - (while (re-search-forward ",+" nil t) - (replace-match "." nil nil)) - ;; Replace consecutive periods with a single period - (goto-char (point-min)) - (while (re-search-forward "\\.\\.+" nil t) - (replace-match "." nil nil)) - ;; 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." - (with-current-buffer (get-buffer-create mh-temp-buffer) - (let ((the-list file-list) - (found)) - (while the-list - (erase-buffer) - (when (file-writable-p (car file-list)) - (insert-file-contents (car file-list)) - (if (re-search-forward (concat "^" (regexp-quote alias) ":") nil t) - (setq found (car file-list) - the-list nil) - (setq the-list (cdr the-list))))) - found))) - -(defun mh-alias-insert-file (&optional alias) - "Return filename which should be used to add ALIAS. -The value of the option `mh-alias-insert-file' is used if non-nil; -otherwise the value of the \"Aliasfile:\" profile component is used. -If the alias already exists, try to return the name of the file that -contains it." - (cond - ((and mh-alias-insert-file (listp mh-alias-insert-file)) - (if (not (elt mh-alias-insert-file 1)) ; Only one entry, use it - (car mh-alias-insert-file) - (if (or (not alias) - (string-equal alias (mh-alias-ali alias))) ;alias doesn't exist - (completing-read "Alias file: " - (mapcar #'list mh-alias-insert-file) nil t) - (or (mh-alias-which-file-has-alias alias mh-alias-insert-file) - (completing-read "Alias file: " - (mapcar #'list mh-alias-insert-file) nil t))))) - ((and mh-alias-insert-file (stringp mh-alias-insert-file)) - mh-alias-insert-file) - (t - ;; writable ones returned from (mh-alias-filenames): - (let ((autolist (delq nil (mapcar (lambda (file) - (if (and (file-writable-p file) - (not (string-equal - file "/etc/passwd"))) - file)) - (mh-alias-filenames t))))) - (cond - ((not autolist) - (error "No writable alias file; -set `mh-alias-insert-file' or the \"Aliasfile:\" profile component")) - ((not (elt autolist 1)) ; Only one entry, use it - (car autolist)) - ((or (not alias) - (string-equal alias (mh-alias-ali alias))) ;alias doesn't exist - (completing-read "Alias file: " autolist nil t)) - (t - (or (mh-alias-which-file-has-alias alias autolist) - (completing-read "Alias file: " autolist nil t)))))))) - -;;;###mh-autoload -(defun mh-alias-address-to-alias (address) - "Return the ADDRESS alias if defined, or nil." - (let* ((aliases (mh-alias-ali address t))) - (if (string-equal aliases address) - nil ; ali returned same string -> no. - ;; Double-check that we have an individual alias. This means that the - ;; alias doesn't expand into a list (of which this address is part). - (car (delq nil (mapcar - (lambda (alias) - (let ((recurse (mh-alias-ali alias nil))) - (if (string-match ".*,.*" recurse) - nil - alias))) - (split-string aliases ", +"))))))) - -;;;###mh-autoload -(defun mh-alias-for-from-p () - "Return t if sender's address has a corresponding alias." - (mh-alias-reload-maybe) - (save-excursion - (if (not (mh-folder-line-matches-show-buffer-p)) - nil ;No corresponding show buffer - (if (eq major-mode 'mh-folder-mode) - (set-buffer mh-show-buffer)) - (let ((from-header (mh-extract-from-header-value))) - (and from-header - (mh-alias-address-to-alias from-header) - t))))) - -(defun mh-alias-add-alias-to-file (alias address &optional file) - "Add ALIAS for ADDRESS in alias FILE without alias check or prompts. -Prompt for alias file if not provided and there is more than one -candidate. - -If the alias exists already, you will have the choice of -inserting the new alias before or after the old alias. In the -former case, this alias will be used when sending mail to this -alias. In the latter case, the alias serves as an additional -folder name hint when filing messages." - (if (not file) - (setq file (mh-alias-insert-file alias))) - (with-current-buffer (find-file-noselect file) - (goto-char (point-min)) - (let ((alias-search (concat alias ":")) - (letter) - (case-fold-search t)) - (cond - ;; Search for exact match (if we had the same alias before) - ((re-search-forward - (concat "^" (regexp-quote alias-search) " *\\(.*\\)") nil t) - (let ((answer (read-string - (format (concat "Alias %s exists; insert new address " - "[b]efore or [a]fter: ") - (match-string 1)))) - (case-fold-search t)) - (cond ((string-match "^b" answer)) - ((string-match "^a" answer) - (forward-line 1)) - (t - (error "Unrecognized response"))))) - ;; No, so sort-in at the right place - ;; search for "^alias", then "^alia", etc. - ((eq mh-alias-insertion-location 'sorted) - (setq letter (substring alias-search -1) - alias-search (substring alias-search 0 -1)) - (while (and (not (equal alias-search "")) - (not (re-search-forward - (concat "^" (regexp-quote alias-search)) nil t))) - (setq letter (substring alias-search -1) - alias-search (substring alias-search 0 -1))) - ;; Next, move forward to sort alphabetically for following letters - (beginning-of-line) - (while (re-search-forward - (concat "^" (regexp-quote alias-search) "[a-" letter "]") - nil t) - (forward-line 1))) - ((eq mh-alias-insertion-location 'bottom) - (goto-char (point-max))) - ((eq mh-alias-insertion-location 'top) - (goto-char (point-min))))) - (beginning-of-line) - (insert (format "%s: %s\n" alias address)) - (save-buffer))) - -(defun mh-alias-add-alias (alias address) - "Add ALIAS for ADDRESS in personal alias file. - -This function prompts you for an alias and address. If the alias -exists already, you will have the choice of inserting the new -alias before or after the old alias. In the former case, this -alias will be used when sending mail to this alias. In the latter -case, the alias serves as an additional folder name hint when -filing messages." - (interactive "P\nP") - (mh-alias-reload-maybe) - (setq alias (completing-read "Alias: " mh-alias-alist nil nil alias)) - (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) - (setq alias-address nil)) - (cond - ((and (equal alias address-alias) - (equal address alias-address)) - (message "Already defined as %s" alias-address)) - (address-alias - (if (y-or-n-p (format "Address has alias %s; set new one? " - address-alias)) - (mh-alias-add-alias-to-file alias address))) - (t - (mh-alias-add-alias-to-file alias address))))) - -;;;###mh-autoload -(defun mh-alias-grab-from-field () - "Add alias for the sender of the current message." - (interactive) - (mh-alias-reload-maybe) - (save-excursion - (cond - ((mh-folder-line-matches-show-buffer-p) - (set-buffer mh-show-buffer)) - ((and (eq major-mode 'mh-folder-mode) - (mh-get-msg-num nil)) - (set-buffer (get-buffer-create mh-temp-buffer)) - (insert-file-contents (mh-msg-filename (mh-get-msg-num t)))) - ((eq major-mode 'mh-folder-mode) - (user-error "Cursor not pointing to a message"))) - (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)))) - -(defun mh-alias-add-address-under-point () - "Insert an alias for address under point." - (interactive) - (let ((address (goto-address-find-address-at-point))) - (if address - (mh-alias-add-alias nil address) - (message "No email address found under point")))) - -(defun mh-alias-apropos (regexp) - "Show all aliases or addresses that match a regular expression REGEXP." - (interactive "sAlias regexp: ") - (if mh-alias-local-users - (mh-alias-reload-maybe)) - (let ((matches "") - (group-matches "") - (passwd-matches)) - (save-excursion - (message "Reading MH aliases...") - (mh-exec-cmd-quiet t "ali" "-nolist" "-nouser") - (message "Parsing MH aliases...") - (while (re-search-forward regexp nil t) - (beginning-of-line) - (cond - ((looking-at "^[ \t]") ;Continuation line - (setq group-matches - (concat group-matches - (buffer-substring - (save-excursion - (or (re-search-backward "^[^ \t]" nil t) - (point))) - (progn - (if (re-search-forward "^[^ \t]" nil t) - (forward-char -1)) - (point)))))) - (t - (setq matches - (concat matches - (buffer-substring (point)(progn (end-of-line)(point))) - "\n"))))) - (message "Parsing MH aliases...done") - (when mh-alias-local-users - (message "Making passwd aliases...") - (setq passwd-matches - (mapconcat - (lambda (elem) - (if (or (string-match regexp (car elem)) - (string-match regexp (cadr elem))) - (format "%s: %s\n" (car elem) (cadr elem)))) - mh-alias-passwd-alist "")) - (message "Making passwd aliases...done"))) - (if (and (string-equal "" matches) - (string-equal "" group-matches) - (string-equal "" passwd-matches)) - (message "No matches") - (with-output-to-temp-buffer mh-aliases-buffer - (if (not (string-equal "" matches)) - (princ matches)) - (when (not (string-equal group-matches "")) - (princ "\nGroup Aliases:\n\n") - (princ group-matches)) - (when (not (string-equal passwd-matches "")) - (princ "\nLocal User Aliases:\n\n") - (princ passwd-matches)))))) - -(defun mh-folder-line-matches-show-buffer-p () - "Return t if the message under point in folder-mode is in the show buffer. -Return nil in any other circumstance (no message under point, no -show buffer, the message in the show buffer doesn't match." - (and (eq major-mode 'mh-folder-mode) - (mh-get-msg-num nil) - mh-show-buffer - (get-buffer mh-show-buffer) - (buffer-file-name (get-buffer mh-show-buffer)) - (string-match ".*/\\([0-9]+\\)$" - (buffer-file-name (get-buffer mh-show-buffer))) - (string-equal - (match-string 1 (buffer-file-name (get-buffer mh-show-buffer))) - (int-to-string (mh-get-msg-num nil))))) - -(provide 'mh-alias) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-alias.el ends here diff --git a/lisp/mh-e/mh-buffers.el b/lisp/mh-e/mh-buffers.el deleted file mode 100644 index e757f330675..00000000000 --- a/lisp/mh-e/mh-buffers.el +++ /dev/null @@ -1,81 +0,0 @@ -;;; mh-buffers.el --- MH-E buffer constants and utilities -*- lexical-binding: t; -*- - -;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation, -;; Inc. - -;; Author: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;;; Code: - -;; The names of ephemeral buffers have a " *mh-" prefix (so that they -;; are hidden and can be programmatically removed in mh-quit), and the -;; variable names have the form mh-temp-.*-buffer. -(defconst mh-temp-buffer " *mh-temp*") ;scratch -(defconst mh-temp-checksum-buffer " *mh-checksum*") -(defconst mh-temp-fetch-buffer " *mh-fetch*") ;wget/curl/fetch output -(defconst mh-temp-index-buffer " *mh-index*") - -;; The names of MH-E buffers that are not ephemeral and can be used by -;; the user (and deleted by the user when no longer needed) have a -;; "*MH-E " prefix (so they can be programmatically removed in -;; mh-quit), and the variable names have the form mh-.*-buffer. -;; Temporary buffers for search results -(defconst mh-aliases-buffer "*MH-E Aliases*") ;alias lookups -(defconst mh-folders-buffer "*MH-E Folders*") ;folder list -(defconst mh-help-buffer "*MH-E Help*") ;quick help -(defconst mh-info-buffer "*MH-E Info*") ;version information buffer -(defconst mh-log-buffer "*MH-E Log*") ;output of MH commands and so on -(defconst mh-mail-delivery-buffer "*MH-E Mail Delivery*") ;mail delivery log -(defconst mh-recipients-buffer "*MH-E Recipients*") ;killed when draft sent -(defconst mh-sequences-buffer "*MH-E Sequences*") ;sequences list - -(defvar mh-log-buffer-lines 100 - "Number of lines to keep in `mh-log-buffer'.") - - - -(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))) - -(provide 'mh-buffers) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-buffers.el ends here diff --git a/lisp/mh-e/mh-comp.el b/lisp/mh-e/mh-comp.el deleted file mode 100644 index f85151840b8..00000000000 --- a/lisp/mh-e/mh-comp.el +++ /dev/null @@ -1,1276 +0,0 @@ -;;; mh-comp.el --- MH-E functions for composing and sending messages -*- lexical-binding: t; -*- - -;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation, -;; Inc. - -;; Author: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; This file includes the functions in the MH-Folder maps that get us -;; into MH-Letter mode, as well the functions in the MH-Letter mode -;; that are used to send the mail. Other that those, functions that -;; are needed in mh-letter.el should be found there. - -;;; Code: - -(require 'mh-e) -(require 'mh-gnus) ;needed because mh-gnus.el not compiled -(require 'mh-scan) - -(require 'sendmail) - -(autoload 'easy-menu-add "easymenu") -(autoload 'mail-header-parse-address "mail-parse") -(autoload 'mml-insert-tag "mml") - - - -;;; Site Customization - -(defvar mh-send-prog "send" - "Name of the MH send program. -Some sites need to change this because of a name conflict.") - -(defvar mh-send-uses-spost-flag nil - "Non-nil means \"send\" uses \"spost\" to submit messages. - -If the value of \"postproc:\" is \"spost\", you may need to set -this variable to t to tell MH-E to avoid using features of -\"post\" that are not supported by \"spost\". You'll know that -you'll need to do this if sending mail fails with an error of -\"spost: -msgid unknown\".") - -(defvar mh-redist-background nil - "If non-nil redist will be done in background like send. -This allows transaction log to be visible if -watch, -verbose or --snoop are used.") - - - -;;; Variables - -(defvar mh-comp-formfile "components" - "Name of file to be used as a skeleton for composing messages. - -Default is \"components\". - -If not an absolute file name, the file is searched for first in the -user's MH directory, then in the system MH lib directory.") - -(defvar mh-dist-formfile "distcomps" - "Name of file to be used as a skeleton for redistributing messages. - -Default is \"distcomps\". - -If not an absolute file name, the file is searched for first in the -user's MH directory, then in the system MH lib directory.") - -(defvar mh-repl-formfile "replcomps" - "Name of file to be used as a skeleton for replying to messages. - -Default is \"replcomps\". - -If not an absolute file name, the file is searched for first in the -user's MH directory, then in the system MH lib directory.") - -(defvar mh-repl-group-formfile "replgroupcomps" - "Name of file to be used as a skeleton for replying to messages. - -Default is \"replgroupcomps\". - -This file is used to form replies to the sender and all recipients of -a message. Only used if (mh-variant-p \\='nmh) is non-nil. -If not an absolute file name, the file is searched for first in the -user's MH directory, then in the system MH lib directory.") - -(defvar mh-rejected-letter-start - (format "^%s$" - (regexp-opt - '("Content-Type: message/rfc822" ;MIME MDN - "------ This is a copy of the message, including all the headers. ------";from exim - "--- Below this line is a copy of the message."; from qmail - " ----- Unsent message follows -----" ;from sendmail V5 - " --------Unsent Message below:" ; from sendmail at BU - " ----- Original message follows -----" ;from sendmail V8 - "------- Unsent Draft" ;from MH itself - "---------- Original Message ----------" ;from zmailer - " --- The unsent message follows ---" ;from AIX mail system - " Your message follows:" ;from MMDF-II - "Content-Description: Returned Content" ;1993 KJ sendmail - )))) - -(defvar mh-new-draft-cleaned-headers - "^Date:\\|^Received:\\|^Message-Id:\\|^From:\\|^Sender:\\|^Errors-To:\\|^Delivery-Date:\\|^Return-Path:" - "Regexp of header lines to remove before offering a message as a new draft\\. -Used by the \\[mh-edit-again] and \\[mh-extract-rejected-mail] commands.") - -(defvar mh-letter-mode-syntax-table - (let ((syntax-table (make-syntax-table text-mode-syntax-table))) - (modify-syntax-entry ?% "." syntax-table) - syntax-table) - "Syntax table used by MH-E while in MH-Letter mode.") - -(defvar mh-regexp-in-field-syntax-table nil - "Specify a syntax table for `mh-regexp-in-field-p' to use.") - -(defvar mh-fcc-syntax-table - (let ((syntax-table (make-syntax-table text-mode-syntax-table))) - (modify-syntax-entry ?+ "w" syntax-table) - (modify-syntax-entry ?/ "w" syntax-table) - syntax-table) - "Syntax table used by MH-E while searching an Fcc field.") - -(defvar mh-addr-syntax-table - (let ((syntax-table (make-syntax-table text-mode-syntax-table))) - (modify-syntax-entry ?! "w" syntax-table) - (modify-syntax-entry ?# "w" syntax-table) - (modify-syntax-entry ?$ "w" syntax-table) - (modify-syntax-entry ?% "w" syntax-table) - (modify-syntax-entry ?& "w" syntax-table) - (modify-syntax-entry ?' "w" syntax-table) - (modify-syntax-entry ?* "w" syntax-table) - (modify-syntax-entry ?+ "w" syntax-table) - (modify-syntax-entry ?- "w" syntax-table) - (modify-syntax-entry ?/ "w" syntax-table) - (modify-syntax-entry ?= "w" syntax-table) - (modify-syntax-entry ?? "w" syntax-table) - (modify-syntax-entry ?^ "w" syntax-table) - (modify-syntax-entry ?_ "w" syntax-table) - (modify-syntax-entry ?` "w" syntax-table) - (modify-syntax-entry ?{ "w" syntax-table) - (modify-syntax-entry ?| "w" syntax-table) - (modify-syntax-entry ?} "w" syntax-table) - (modify-syntax-entry ?~ "w" syntax-table) - (modify-syntax-entry ?. "w" syntax-table) - (modify-syntax-entry ?@ "w" syntax-table) - syntax-table) - "Syntax table used by MH-E while searching an address field.") - -(defvar mh-send-args "" - "Extra args to pass to \"send\" command.") - -(defvar mh-annotate-char nil - "Character to use to annotate `mh-sent-from-msg'.") - -(defvar mh-annotate-field nil - "Field name for message annotation.") - -(defvar mh-annotate-list nil - "Messages annotated, either a sequence name or a list of message numbers. -This variable can be used by `mh-annotate-msg-hook'.") - -(defvar-local mh-insert-auto-fields-done-local nil - "Buffer-local variable set when `mh-insert-auto-fields' called successfully.") - - - -;;; MH-E Entry Points - -;;;###autoload -(defun mh-smail () - "Compose a message with the MH mail system. -See `mh-send' for more details on composing mail." - (interactive) - (mh-find-path) - (call-interactively 'mh-send)) - -;;;###autoload -(defun mh-smail-other-window () - "Compose a message with the MH mail system in other window. -See `mh-send' for more details on composing mail." - (interactive) - (mh-find-path) - (call-interactively 'mh-send-other-window)) - -(defun mh-send-other-window (to cc subject) - "Compose a message in another window. - -See `mh-send' for more information and a description of how the -TO, CC, and SUBJECT arguments are used." - (interactive (list - (mh-interactive-read-address "To: ") - (mh-interactive-read-address "Cc: ") - (mh-interactive-read-string "Subject: "))) - (let ((pop-up-windows t)) - (mh-send-sub to cc subject (current-window-configuration)))) - -(defvar mh-error-if-no-draft nil) ;raise error over using old draft - -;;;###autoload -(defun mh-smail-batch (&optional to subject _other-headers &rest _ignored) - "Compose a message with the MH mail system. - -This function does not prompt the user for any header fields, and -thus is suitable for use by programs that want to create a mail -buffer. Users should use \\[mh-smail] to compose mail. - -Optional arguments for setting certain fields include TO, -SUBJECT, and OTHER-HEADERS. Additional arguments are IGNORED. - -This function remains for Emacs 21 compatibility. New -applications should use `mh-user-agent-compose'." - (mh-find-path) - (let ((mh-error-if-no-draft t)) - (mh-send (or to "") "" (or subject "")))) - -;;;###autoload -(define-mail-user-agent 'mh-e-user-agent - 'mh-user-agent-compose 'mh-send-letter 'mh-fully-kill-draft - 'mh-before-send-letter-hook) - -;;;###autoload -(defun mh-user-agent-compose (&optional to subject other-headers &rest _ignored) - "Set up mail composition draft with the MH mail system. -This is the `mail-user-agent' entry point to MH-E. This function -conforms to the contract specified by `define-mail-user-agent' -which means that this function should accept the same arguments -as `compose-mail'. - -The optional arguments TO and SUBJECT specify recipients and the -initial Subject field, respectively. - -OTHER-HEADERS is an alist specifying additional header fields. -Elements look like (HEADER . VALUE) where both HEADER and VALUE -are strings. - -Any additional arguments are IGNORED." - (mh-find-path) - (let ((mh-error-if-no-draft t)) - (mh-send to "" subject) - (while other-headers - (mh-insert-fields (concat (car (car other-headers)) ":") - (cdr (car other-headers))) - (setq other-headers (cdr other-headers))))) - -(defvar sendmail-coding-system) - -;;;###autoload -(defun mh-send-letter (&optional arg) - "Save draft and send message. - -When you are all through editing a message, you send it with this -command. You can give a prefix argument ARG to monitor the first stage -of the delivery; this output can be found in a buffer called \"*MH-E -Mail Delivery*\". - -The hook `mh-before-send-letter-hook' is run at the beginning of -this command. For example, if you want to check your spelling in -your message before sending, add the function `ispell-message'. - -Unless `mh-insert-auto-fields' had previously been called -manually, the function `mh-insert-auto-fields' is called to -insert fields based upon the recipients. If fields are added, you -are given a chance to see and to confirm these fields before the -message is actually sent. You can do away with this confirmation -by turning off the option `mh-auto-fields-prompt-flag'. - -In case the MH \"send\" program is installed under a different name, -use `mh-send-prog' to tell MH-E the name. - -The hook `mh-annotate-msg-hook' is run after annotating the -message and scan line." - (interactive "P") - (run-hooks 'mh-before-send-letter-hook) - (if (and (mh-insert-auto-fields t) - mh-auto-fields-prompt-flag - (goto-char (point-min))) - (if (not (y-or-n-p "Auto fields inserted, send? ")) - (error "Send aborted"))) - (cond ((mh-mh-directive-present-p) - (mh-mh-to-mime)) - ((or (mh-mml-tag-present-p) (not (mh-ascii-buffer-p))) - (mh-mml-to-mime))) - (save-buffer) - (message "Sending...") - (let ((draft-buffer (current-buffer)) - (file-name buffer-file-name) - (config mh-previous-window-config) - (coding-system-for-write (select-message-coding-system))) - ;; Older versions of spost do not support -msgid and -mime. - (unless mh-send-uses-spost-flag - ;; Adding a Message-ID field looks good, makes it easier to search for - ;; message in your +outbox, and best of all doesn't break threading for - ;; the recipient if you reply to a message in your +outbox. - (setq mh-send-args (concat "-msgid " mh-send-args)) - ;; The default Bcc encapsulation will make a MIME message unreadable. - ;; With nmh use the -mime arg to prevent this. - (if (and (mh-variant-p 'nmh) - (mh-goto-header-field "Bcc:") - (mh-goto-header-field "Content-Type:")) - (setq mh-send-args (concat "-mime " mh-send-args)))) - (cond (arg - (pop-to-buffer mh-mail-delivery-buffer) - (erase-buffer) - (mh-exec-cmd-output mh-send-prog t - "-nodraftfolder" "-watch" "-nopush" - (split-string mh-send-args) file-name) - (goto-char (point-max)) ; show the interesting part - (recenter -1) - (set-buffer draft-buffer)) ; for annotation below - (t - (mh-exec-cmd-daemon mh-send-prog nil - "-nodraftfolder" "-noverbose" - (split-string mh-send-args) file-name))) - (if mh-annotate-char - (mh-annotate-msg mh-sent-from-msg - mh-sent-from-folder - mh-annotate-char - "-component" mh-annotate-field - "-text" (format "\"%s %s\"" - (mh-get-header-field "To:") - (mh-get-header-field "Cc:")))) - - (cond ((or (not arg) - (y-or-n-p "Kill draft buffer? ")) - (kill-buffer draft-buffer) - (if config - (set-window-configuration config)))) - (if arg - (message "Sending...done") - (message "Sending...backgrounded")))) - -;;;###autoload -(defun mh-fully-kill-draft () - "Quit editing and delete draft message. - -If for some reason you are not happy with the draft, you can use -this command to kill the draft buffer and delete the draft -message. Use the command \\[kill-buffer] if you don't want to -delete the draft message." - (interactive) - (if (y-or-n-p "Kill draft message? ") - (let ((config mh-previous-window-config)) - (if (file-exists-p buffer-file-name) - (delete-file buffer-file-name)) - (set-buffer-modified-p nil) - (kill-buffer (buffer-name)) - (message "") - (if config - (set-window-configuration config))) - (error "Message not killed"))) - - - -;;; MH-Folder Commands - -;; Alphabetical. - -;;;###mh-autoload -(defun mh-edit-again (message) - "Edit a MESSAGE to send it again. - -If you don't complete a draft for one reason or another, and if -the draft buffer is no longer available, you can pick your draft -up again with this command. If you don't use a draft folder, your -last \"draft\" file will be used. If you use draft folders, -you'll need to visit the draft folder with \"\\[mh-visit-folder] -drafts \", use \\[mh-next-undeleted-msg] to move to the -appropriate message, and then use \\[mh-edit-again] to prepare -the message for editing. - -This command can also be used to take messages that were sent to -you and to send them to more people. - -Don't use this command to re-edit a message from a Mailer-Daemon -who complained that your mail wasn't posted for some reason or -another (see `mh-extract-rejected-mail'). - -The default message is the current message. - -See also `mh-send'." - (interactive (list (mh-get-msg-num t))) - (let* ((from-folder mh-current-folder) - (config (current-window-configuration)) - (components-file (mh-bare-components mh-comp-formfile)) - (draft - (cond ((and mh-draft-folder (equal from-folder mh-draft-folder)) - (pop-to-buffer (find-file-noselect (mh-msg-filename message)) - t) - (rename-buffer (format "draft-%d" message)) - ;; Make buffer writable... - (setq buffer-read-only nil) - ;; If buffer was being used to display the message reinsert - ;; from file... - (when (eq major-mode 'mh-show-mode) - (erase-buffer) - (insert-file-contents buffer-file-name)) - (buffer-name)) - (t - (mh-read-draft "clean-up" (mh-msg-filename message) nil))))) - (mh-clean-msg-header (point-min) mh-new-draft-cleaned-headers nil) - (mh-insert-header-separator) - ;; Merge in components - (mapc - (lambda (header-field) - (let ((field (car header-field)) - (value (cdr header-field)) - (case-fold-search t)) - (cond - ;; Address field - ((string-match field "^To$\\|^Cc$\\|^From$") - (cond - ((not (mh-goto-header-field (concat field ":"))) - ;; Header field does not exist, add it - (mh-goto-header-end 0) - (insert field ": " value "\n")) - ((string-equal value "") - ;; Header field already exists and no value - ) - (t - ;; Header field exists and we have a value - (let (address mailbox (alias (mh-alias-expand value))) - (and alias - (setq address (mail-header-parse-address alias)) - (setq mailbox (car address))) - ;; XXX - Need to parse all addresses out of field - (if (and - (not (mh-regexp-in-field-p - (concat "\\b" (regexp-quote value) "\\b") field)) - mailbox - (not (mh-regexp-in-field-p - (concat "\\b" (regexp-quote mailbox) "\\b") field))) - (insert " " value ",")) - )))) - ((string-match field "^Fcc$") - ;; Folder reference - (mh-modify-header-field field value)) - ;; Text field, that's an easy case - (t - (mh-modify-header-field field value))))) - (mh-components-to-list components-file)) - (delete-file components-file) - (goto-char (point-min)) - (save-buffer) - (mh-compose-and-send-mail - draft "" from-folder nil nil nil nil nil nil config) - (mh-letter-mode-message) - (mh-letter-adjust-point))) - -(defun mh-extract-header-field () - "Extract field name and field value from the field at point. -Returns a list of field name and value (which may be null)." - (let ((end (save-excursion (mh-header-field-end) - (point)))) - (if (looking-at mh-letter-header-field-regexp) - (save-excursion - (goto-char (match-end 1)) - (forward-char 1) - (skip-chars-forward " \t") - (cons (match-string-no-properties 1) (buffer-substring-no-properties (point) end)))))) - - -(defun mh-components-to-list (components) - "Convert the COMPONENTS file to a list of field names and values." - (with-current-buffer (get-buffer-create mh-temp-buffer) - (erase-buffer) - (insert-file-contents components) - (goto-char (point-min)) - (let - ((header-fields nil)) - (while (mh-in-header-p) - (setq header-fields (append header-fields (list (mh-extract-header-field)))) - (mh-header-field-end) - (forward-char 1) - ) - header-fields))) - -;;;###mh-autoload -(defun mh-extract-rejected-mail (message) - "Edit a MESSAGE that was returned by the mail system. - -This command prepares the message for editing by removing the -Mailer-Daemon envelope and unneeded header fields. Fix whatever -addressing problem you had, and send the message again with -\\[mh-send-letter]. - -The default message is the current message. - -See also `mh-send'." - (interactive (list (mh-get-msg-num t))) - (let ((from-folder mh-current-folder) - (config (current-window-configuration)) - (draft (mh-read-draft "extraction" (mh-msg-filename message) nil))) - (goto-char (point-min)) - (cond ((re-search-forward mh-rejected-letter-start nil t) - (skip-chars-forward " \t\n") - (delete-region (point-min) (point)) - (mh-clean-msg-header (point-min) mh-new-draft-cleaned-headers nil)) - (t - (message "Does not appear to be a rejected letter"))) - (mh-insert-header-separator) - (goto-char (point-min)) - (save-buffer) - (mh-compose-and-send-mail draft "" from-folder message - (mh-get-header-field "To:") - (mh-get-header-field "From:") - (mh-get-header-field "Cc:") - nil nil config) - (mh-letter-mode-message))) - -;;;###mh-autoload -(defun mh-forward (to cc &optional range) - "Forward message. - -You are prompted for the TO and CC recipients. You are given a -draft to edit that looks like it would if you had run the MH -command \"forw\". You can then add some text. - -You can forward several messages by using a RANGE. All of the -messages in the range are inserted into your draft. Check the -documentation of `mh-interactive-range' to see how RANGE is read -in interactive use. - -The hook `mh-forward-hook' is called on the draft. - -See also `mh-compose-forward-as-mime-flag', -`mh-forward-subject-format', and `mh-send'." - (interactive (list (mh-interactive-read-address "To: ") - (mh-interactive-read-address "Cc: ") - (mh-interactive-range "Forward"))) - (let* ((folder mh-current-folder) - (msgs (mh-range-to-msg-list range)) - (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 - (draft-name (expand-file-name "draft" mh-user-path)) - (draft (cond ((or (not (file-exists-p draft-name)) - (y-or-n-p "The file draft exists; discard it? ")) - (mh-exec-cmd "forw" "-build" - (if (and (mh-variant-p 'nmh) - mh-compose-forward-as-mime-flag) - "-mime") - mh-current-folder - (mh-coalesce-msg-list msgs)) - (prog1 - (mh-read-draft "" draft-name t) - (mh-insert-fields "To:" to "Cc:" cc) - (save-buffer))) - (t - (mh-read-draft "" draft-name nil))))) - (let (orig-from - orig-subject) - (with-current-buffer (get-buffer-create mh-temp-buffer) - (erase-buffer) - (insert-file-contents fwd-msg-file) - (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))) - (mh-modify-header-field "Subject" forw-subject t) - (goto-char (point-min)) - ;; Set the local value of mh-mail-header-separator according to what is - ;; present in the buffer... - (setq-local mh-mail-header-separator - (save-excursion - (goto-char (mh-mail-header-end)) - (buffer-substring-no-properties (point) - (line-end-position)))) - (setq-local mail-header-separator mh-mail-header-separator) ;override sendmail.el - ;; If using MML, translate MH-style directive - (if (equal mh-compose-insertion 'mml) - (save-excursion - (goto-char (mh-mail-header-end)) - (while - (re-search-forward - "^#forw \\[\\([^]]+\\)\\] \\(\\+\\S-+\\) \\(.*\\)$" - (point-max) t) - (let ((description (if (equal (match-string 1) - "forwarded messages") - "forwarded message %d" - (match-string 1))) - (msgs (split-string (match-string 3))) - (i 0)) - (beginning-of-line) - (delete-region (point) (progn (forward-line 1) (point))) - (dolist (msg msgs) - (setq i (1+ i)) - (mh-mml-forward-message (format description i) - folder msg) - ;; Was inserted before us, move to end of file to preserve order - (goto-char (point-max))))))) - ;; Position just before forwarded message. - (if (re-search-forward "^------- Forwarded Message" nil t) - (forward-line -1) - (goto-char (mh-mail-header-end)) - (forward-line 1)) - (delete-other-windows) - (mh-add-msgs-to-seq msgs 'forwarded t) - (mh-compose-and-send-mail draft "" folder msgs - to forw-subject cc - mh-note-forw "Forwarded:" - config) - (mh-letter-mode-message) - (mh-letter-adjust-point) - (run-hooks 'mh-forward-hook))))) - -(defun mh-forwarded-letter-subject (from subject) - "Return a Subject suitable for a forwarded message. -Original message has headers FROM and SUBJECT." - ;; Join continued lines. - (setq from (replace-regexp-in-string "\\s *\n\\s +" " " from)) - (let ((addr-start (string-search "<" from)) - (comment (string-search "(" from))) - (cond ((and addr-start (> addr-start 0)) - ;; Full Name - (setq from (substring from 0 (1- addr-start)))) - (comment - ;; luser@host (Full Name) - (setq from (substring from (1+ comment) (1- (length from))))))) - (format mh-forward-subject-format from subject)) - -;;;###mh-autoload -(defun mh-redistribute (to cc identity &optional message) - "Redistribute a message. - -This command is similar in function to forwarding mail, but it -does not allow you to edit the message, nor does it add your name -to the \"From\" header field. It appears to the recipient as if -the message had come from the original sender. When you run this -command, you are prompted for the TO and CC recipients. You are -also prompted for the sending IDENTITY to use. The default -MESSAGE is the current message. - -Also investigate the command \\[mh-edit-again] for another way to -redistribute messages. - -See also `mh-redist-full-contents-flag'. - -The hook `mh-annotate-msg-hook' is run after annotating the -message and scan line." - (interactive (list (mh-read-address "Redist-To: ") - (mh-read-address "Redist-Cc: ") - (if mh-identity-list - (mh-select-identity mh-identity-default) - nil) - (mh-get-msg-num t))) - (or message - (setq message (mh-get-msg-num t))) - (save-window-excursion - (let ((folder mh-current-folder) - (draft (mh-read-draft "redistribution" - (if mh-redist-full-contents-flag - (mh-msg-filename message) - nil) - nil)) - (from (mh-identity-field identity "From")) - (fcc (mh-identity-field identity "Fcc")) - (bcc (mh-identity-field identity "Bcc")) - comp-fcc comp-to comp-cc comp-bcc) - (if mh-redist-full-contents-flag - (mh-clean-msg-header - (point-min) - "^Message-Id:\\|^Received:\\|^Return-Path:\\|^Date:\\|^Resent-.*:" - nil)) - ;; Read fields from the distcomps file and put them in our - ;; draft. For "To", "Cc", "Bcc", and "Fcc", multiple headers are - ;; combined into a single header with comma-separated entries. - ;; For "From", the first value wins, with the identity's "From" - ;; trumping anything in the distcomps file. - (let ((components-file (mh-bare-components mh-dist-formfile))) - (mapc - (lambda (header-field) - (let ((field (car header-field)) - (value (cdr header-field)) - (case-fold-search t)) - (cond - ((string-match field "^Resent-Fcc$") - (setq comp-fcc value)) - ((string-match field "^Resent-From$") - (or from - (setq from value))) - ((string-match field "^Resent-To$") - (setq comp-to value)) - ((string-match field "^Resent-Cc$") - (setq comp-cc value)) - ((string-match field "^Resent-Bcc$") - (setq comp-bcc value)) - ((string-match field "^Resent-.*$") - (mh-insert-fields field value))))) - (mh-components-to-list components-file)) - (delete-file components-file)) - (mh-insert-fields "Resent-To:" (mapconcat #'identity (list to comp-to) - ", ") - "Resent-Cc:" (mapconcat #'identity (list cc comp-cc) - ", ") - "Resent-Fcc:" (mapconcat #'identity (list fcc comp-fcc) - ", ") - "Resent-Bcc:" (mapconcat #'identity (list bcc comp-bcc) - ", ") - "Resent-From:" from) - (save-buffer) - (message "Redistributing...") - (let ((env "mhdist=1")) - ;; Setup environment... - (setq env (concat env " mhaltmsg=" - (if mh-redist-full-contents-flag - buffer-file-name - (mh-msg-filename message folder)))) - (unless mh-redist-full-contents-flag - (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 message folder mh-note-dist - "-component" "Resent:" - "-text" (format "\"To: %s Cc: %s From: %s\"" - to cc from))) - (kill-buffer draft) - (message "Redistributing...done")))) - -;;;###mh-autoload -(defun mh-reply (message &optional reply-to includep) - "Reply to a MESSAGE. - -When you reply to a message, you are first prompted with \"Reply -to whom?\" (unless the optional argument REPLY-TO is provided). -You have several choices here. - - Response Reply Goes To - - from The person who sent the message. This is the - default, so is sufficient. - - to Replies to the sender, plus all recipients in the - \"To:\" header field. - - all cc Forms a reply to the addresses in the - \"Mail-Followup-To:\" header field if one - exists; otherwise forms a reply to the sender, - plus all recipients. - -Depending on your answer, \"repl\" is given a different argument -to form your reply. Specifically, a choice of \"from\" or none at -all runs \"repl -nocc all\", and a choice of \"to\" runs \"repl --cc to\". Finally, either \"cc\" or \"all\" runs \"repl -cc all --nocc me\". - -Two windows are then created. One window contains the message to -which you are replying in an MH-Show buffer. Your draft, in -MH-Letter mode (*note `mh-letter-mode'), is in the other window. -If the reply draft was not one that you expected, check the -things that affect the behavior of \"repl\" which include the -\"repl:\" profile component and the \"replcomps\" and -\"replgroupcomps\" files. - -If you supply a prefix argument INCLUDEP, the message you are -replying to is inserted in your reply after having first been run -through \"mhl\" with the format file \"mhl.reply\". - -Alternatively, you can customize the option `mh-yank-behavior' -and choose one of its \"Automatically\" variants to do the same -thing. If you do so, the prefix argument has no effect. - -Another way to include the message automatically in your draft is -to use \"repl: -filter repl.filter\" in your MH profile. - -If you wish to customize the header or other parts of the reply -draft, please see \"repl\" and \"mh-format\". - -See also `mh-reply-show-message-flag', -`mh-reply-default-reply-to', and `mh-send'." - (interactive (list - (mh-get-msg-num t) - (or mh-reply-default-reply-to - (completing-read "Reply to whom (default from): " - '(("from") ("to") ("cc") ("all")) - nil - t)) - current-prefix-arg)) - (let* ((folder mh-current-folder) - (show-buffer mh-show-buffer) - (config (current-window-configuration)) - (group-reply (or (equal reply-to "cc") (equal reply-to "all"))) - (form-file (cond ((and (mh-variant-p 'nmh 'gnu-mh) group-reply - (stringp mh-repl-group-formfile)) - mh-repl-group-formfile) - ((stringp mh-repl-formfile) mh-repl-formfile) - (t nil)))) - (message "Composing a reply...") - (mh-exec-cmd "repl" "-build" "-noquery" "-nodraftfolder" - (if form-file - (list "-form" form-file)) - mh-current-folder message - (cond ((or (equal reply-to "from") (equal reply-to "")) - '("-nocc" "all")) - ((equal reply-to "to") - '("-cc" "to")) - (group-reply (if (mh-variant-p 'nmh 'gnu-mh) - '("-group" "-nocc" "me") - '("-cc" "all" "-nocc" "me")))) - (cond ((or (eq mh-yank-behavior 'autosupercite) - (eq mh-yank-behavior 'autoattrib)) - '("-noformat")) - (includep '("-filter" "mhl.reply")) - (t '()))) - (let ((draft (mh-read-draft "reply" - (expand-file-name "reply" mh-user-path) - t))) - (delete-other-windows) - (save-buffer) - - (let ((to (mh-get-header-field "To:")) - (subject (mh-get-header-field "Subject:")) - (cc (mh-get-header-field "Cc:"))) - (goto-char (point-min)) - (mh-goto-header-end 1) - (or includep - (not mh-reply-show-message-flag) - (mh-in-show-buffer (show-buffer) - (mh-display-msg message folder))) - (mh-add-msgs-to-seq message 'answered t) - (message "Composing a reply...done") - (mh-compose-and-send-mail draft "" folder message to subject cc - mh-note-repl "Replied:" config)) - (when (and (or (eq 'autosupercite mh-yank-behavior) - (eq 'autoattrib mh-yank-behavior)) - (eq (mh-show-buffer-message-number) mh-sent-from-msg)) - (undo-boundary) - (mh-yank-cur-msg)) - (mh-letter-mode-message)))) - -;;;###mh-autoload -(defun mh-send (to cc subject) - "Compose a message. - -Your letter appears in an Emacs buffer whose mode is -MH-Letter (see `mh-letter-mode'). - -The arguments TO, CC, and SUBJECT can be used to prefill the -draft fields or suppress the prompts if `mh-compose-prompt-flag' -is on. They are also passed to the function set in the option -`mh-compose-letter-function'. - -See also `mh-insert-x-mailer-flag' and `mh-letter-mode-hook'. - -Outside of an MH-Folder buffer (`mh-folder-mode'), you must call -either \\[mh-smail] or \\[mh-smail-other-window] to compose a new -message." - (interactive (list - (mh-interactive-read-address "To: ") - (mh-interactive-read-address "Cc: ") - (mh-interactive-read-string "Subject: "))) - (let ((config (current-window-configuration))) - (delete-other-windows) - (mh-send-sub to cc subject config))) - - - -;;; Support Routines - -(defun mh-interactive-read-address (prompt) - "Read an address. -If `mh-compose-prompt-flag' is non-nil, then read an address with -PROMPT. -Otherwise return the empty string." - (if mh-compose-prompt-flag (mh-read-address prompt) "")) - -(defun mh-interactive-read-string (prompt) - "Read a string. -If `mh-compose-prompt-flag' is non-nil, then read a string with -PROMPT. -Otherwise return the empty string." - (if mh-compose-prompt-flag (read-string prompt) "")) - -;;;###mh-autoload -(defun mh-show-buffer-message-number (&optional buffer) - "Message number of displayed message in corresponding show buffer. - -Return nil if show buffer not displayed. -If in `mh-letter-mode', don't display the message number being replied -to, but rather the message number of the show buffer associated with -our originating folder buffer. -Optional argument BUFFER can be used to specify the buffer." - (save-excursion - (if buffer - (set-buffer buffer)) - (cond ((eq major-mode 'mh-show-mode) - (let ((number-start (mh-search-from-end ?/ buffer-file-name))) - (string-to-number (substring buffer-file-name - (1+ number-start))))) - ((and (eq major-mode 'mh-folder-mode) - mh-show-buffer - (get-buffer mh-show-buffer)) - (mh-show-buffer-message-number mh-show-buffer)) - ((and (eq major-mode 'mh-letter-mode) - mh-sent-from-folder - (get-buffer mh-sent-from-folder)) - (mh-show-buffer-message-number mh-sent-from-folder)) - (t - nil)))) - -(defun mh-send-sub (to cc subject config) - "Do the real work of composing and sending a letter. -Expects the TO, CC, and SUBJECT fields as arguments. -CONFIG is the window configuration before sending mail." - (let ((folder mh-current-folder) - (msg-num (mh-get-msg-num nil))) - (message "Composing a message...") - (let ((draft (mh-read-draft - "message" - (mh-bare-components mh-comp-formfile) - t))) - (mh-insert-fields "To:" to "Subject:" subject "Cc:" cc) - (goto-char (point-max)) - (mh-compose-and-send-mail draft "" folder msg-num - to subject cc - nil nil config) - (mh-letter-mode-message) - (mh-letter-adjust-point)))) - -(defun mh-bare-components (formfile) - "Generate a temporary, clean components file from FORMFILE. -Return the path to the temporary file." - ;; Let comp(1) create the skeleton for us. This is particularly - ;; important with nmh-1.5, because its default "components" needs - ;; some processing before it can be used. Unfortunately, comp(1) - ;; didn't have a -build option until later versions of nmh. So, to - ;; avoid the possibility of clobbering an existing draft, create - ;; a temporary directory and use it as the drafts folder. Then - ;; copy the skeleton to a regular temp file, and return the - ;; regular temp file. - (let (new - (temp-folder (make-temp-file - (concat mh-user-path "draftfolder.") t))) - (mh-exec-cmd "comp" "-nowhatnowproc" - "-draftfolder" (format "+%s" - (file-name-nondirectory temp-folder)) - (if (stringp formfile) - (list "-form" formfile))) - (setq new (make-temp-file "comp.")) - (rename-file (concat temp-folder "/" "1") new t) - ;; The temp folder could contain various metadata files. Rather - ;; than trying to enumerate all the known files, just do a - ;; recursive delete on the directory. - (delete-directory temp-folder t) - new)) - -(defun mh-read-draft (use initial-contents delete-contents-file) - "Read draft file into a draft buffer and make that buffer the current one. - -USE is a message used for prompting about the intended use of the -message. -INITIAL-CONTENTS is filename that is read into an empty buffer, or nil -if buffer should not be modified. Delete the initial-contents file if -DELETE-CONTENTS-FILE flag is set. -Returns the draft folder's name. -If the draft folder facility is enabled in ~/.mh_profile, a new buffer -is used each time and saved in the draft folder. The draft file can -then be reused." - (cond (mh-draft-folder - (let ((orig-default-dir default-directory) - (draft-file-name (mh-new-draft-name))) - (pop-to-buffer (generate-new-buffer - (format "draft-%s" - (file-name-nondirectory draft-file-name)))) - (condition-case () - (insert-file-contents draft-file-name t) - (file-error)) - (setq default-directory orig-default-dir))) - (t - (let ((draft-name (expand-file-name "draft" mh-user-path))) - (pop-to-buffer "draft") ; Create if necessary - (if (buffer-modified-p) - (if (y-or-n-p "Draft has been modified; kill anyway? ") - (set-buffer-modified-p nil) - (error "Draft preserved"))) - (setq buffer-file-name draft-name) - (clear-visited-file-modtime) - (unlock-buffer) - (cond ((and (file-exists-p draft-name) - (not (equal draft-name initial-contents))) - (insert-file-contents draft-name) - (delete-file draft-name)))))) - (cond ((and initial-contents - (or (zerop (buffer-size)) - (if (y-or-n-p - (format "A draft exists. Use for %s? " use)) - (if mh-error-if-no-draft - (error "A prior draft exists")) - t))) - (erase-buffer) - (insert-file-contents initial-contents) - (if delete-contents-file (delete-file initial-contents)))) - (auto-save-mode 1) - (if mh-draft-folder - (save-buffer)) ; Do not reuse draft name - (buffer-name)) - -(defun mh-new-draft-name () - "Return the pathname of folder for draft messages." - (save-excursion - (mh-exec-cmd-quiet t "mhpath" mh-draft-folder "new") - (buffer-substring (point-min) (1- (point-max))))) - -(defun mh-insert-fields (&rest name-values) - "Insert the NAME-VALUES pairs in the current buffer. -If the field exists, append the value to it. -Do not insert any pairs whose value is the empty string." - (let ((case-fold-search t)) - (while name-values - (let ((field-name (car name-values)) - (value (car (cdr name-values)))) - (if (not (string-match "^.*:$" field-name)) - (setq field-name (concat field-name ":"))) - (cond ((or (null value) - (equal value "")) - nil) - ((mh-position-on-field field-name) - (insert " " (or value ""))) - (t - (insert field-name " " value "\n"))) - (setq name-values (cdr (cdr name-values))))))) - -(defun mh-compose-and-send-mail (draft send-args - sent-from-folder sent-from-msg - to subject cc - annotate-char annotate-field - config) - "Edit and compose a draft message in buffer DRAFT and send or save it. -SEND-ARGS is the argument passed to the send command. -SENT-FROM-FOLDER is buffer containing scan listing of current folder, -or nil if none exists. -SENT-FROM-MSG is the message number or sequence name or nil. -The TO, SUBJECT, and CC fields are passed to the -`mh-compose-letter-function'. -If ANNOTATE-CHAR is non-null, it is used to notate the scan listing of -the message. In that case, the ANNOTATE-FIELD is used to build a -string for `mh-annotate-msg'. -CONFIG is the window configuration to restore after sending the -letter." - (pop-to-buffer draft) - (mh-letter-mode) - - ;; Insert identity. - (mh-insert-identity mh-identity-default t) - (mh-identity-make-menu) - - ;; Cleanup possibly RFC2047 encoded subject header - (mh-decode-message-subject) - - ;; Insert extra fields. - (mh-insert-x-mailer) - (mh-insert-x-face) - - (mh-letter-hide-all-skipped-fields) - - (setq mh-sent-from-folder sent-from-folder) - (setq mh-sent-from-msg sent-from-msg) - (setq mh-send-args send-args) - (setq mh-annotate-char annotate-char) - (setq mh-annotate-field annotate-field) - (setq mh-previous-window-config config) - (setq mode-line-buffer-identification (list " {%b}")) - (mh-logo-display) - (add-hook 'kill-buffer-hook #'mh-tidy-draft-buffer nil t) - (run-hook-with-args 'mh-compose-letter-function to subject cc)) - -(defun mh-insert-x-mailer () - "Append an X-Mailer field to the header. -The versions of MH-E, Emacs, and MH are shown." - (or mh-variant-in-use (mh-variant-set mh-variant)) - ;; Lazily initialize mh-x-mailer-string. - (when (and mh-insert-x-mailer-flag (null mh-x-mailer-string)) - (setq mh-x-mailer-string - (format "MH-E %s; %s; Emacs %s" - mh-version mh-variant-in-use emacs-version))) - ;; Insert X-Mailer, but only if it doesn't already exist. - (save-excursion - (when (and mh-insert-x-mailer-flag - (null (mh-goto-header-field "X-Mailer"))) - (mh-insert-fields "X-Mailer:" mh-x-mailer-string)))) - -(defun mh-insert-x-face () - "Append X-Face, Face or X-Image-URL field to header. -If the field already exists, this function does nothing." - (when (and (stringp mh-x-face-file) - (file-exists-p mh-x-face-file) - (file-readable-p mh-x-face-file)) - (save-excursion - (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: ")))))) - -(defun mh-tidy-draft-buffer () - "Run when a draft buffer is destroyed." - (let ((buffer (get-buffer mh-recipients-buffer))) - (if buffer - (kill-buffer buffer)))) - -(defun mh-letter-mode-message () - "Display a help message for users of `mh-letter-mode'. -This should be the last function called when composing the draft." - (message "%s" (substitute-command-keys - (concat "Type \\[mh-send-letter] to send message, " - "\\[mh-help] for help")))) - -(defun mh-letter-adjust-point () - "Move cursor to first header field if are using the no prompt mode." - (unless mh-compose-prompt-flag - (goto-char (point-max)) - (mh-letter-next-header-field))) - -(defun mh-annotate-msg (msg folder note &rest args) - "Mark MSG in FOLDER with character NOTE and annotate message with ARGS. -MSG can be a message number, a list of message numbers, or a sequence. -The hook `mh-annotate-msg-hook' is run after annotating; see its -documentation for variables it can use." - (apply #'mh-exec-cmd "anno" folder - (if (listp msg) (append msg args) (cons msg args))) - (save-excursion - (cond ((get-buffer folder) ; Buffer may be deleted - (set-buffer folder) - (mh-iterate-on-range nil msg - (mh-notate nil note - (+ mh-cmd-note mh-scan-field-destination-offset)))))) - (let ((mh-current-folder folder) - ;; mh-annotate-list is a sequence name or a list of message numbers - (mh-annotate-list (if (numberp msg) (list msg) msg))) - (run-hooks 'mh-annotate-msg-hook))) - -(defun mh-insert-header-separator () - "Insert `mh-mail-header-separator', if absent." - (save-excursion - (goto-char (point-min)) - (rfc822-goto-eoh) - (if (looking-at "$") - (insert mh-mail-header-separator)))) - -;;;###mh-autoload -(defun mh-insert-auto-fields (&optional non-interactive) - "Insert custom fields if recipient is found in `mh-auto-fields-list'. - -Once the header contains one or more recipients, you may run this -command to insert these fields manually. However, if you use this -command, the automatic insertion when the message is sent is -disabled. - -In a program, set buffer-local `mh-insert-auto-fields-done-local' -if header fields were added. If NON-INTERACTIVE is non-nil, -perform actions quietly and only if -`mh-insert-auto-fields-done-local' is nil. Return t if fields -added; otherwise return nil." - (interactive) - (when (or (not non-interactive) - (not mh-insert-auto-fields-done-local)) - (save-excursion - (when (and (or (mh-goto-header-field "To:") - (mh-goto-header-field "cc:"))) - (let ((list mh-auto-fields-list) - (fields-inserted nil)) - (while list - (let ((regexp (nth 0 (car list))) - (entries (nth 1 (car list)))) - (when (mh-regexp-in-field-p regexp "To:" "cc:") - (setq mh-insert-auto-fields-done-local t) - (setq fields-inserted t) - (if (not non-interactive) - (message "Fields for %s added" regexp)) - (let ((entry-list entries)) - (while entry-list - (let ((field (caar entry-list)) - (value (cdar entry-list))) - (cond - ((equal ":identity" field) - (when - ;;(and (not mh-identity-local) - ;; Bug 1204506. But do we need to be able - ;; to set an identity manually that won't be - ;; overridden by mh-insert-auto-fields? - (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))) - fields-inserted))))) - -(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 ((and overwrite-flag - (mh-goto-header-field (concat field ":"))) - (insert " " value) - (delete-region (point) (line-end-position))) - ((and (not overwrite-flag) - (mh-regexp-in-field-p (concat "\\b" (regexp-quote value) "\\b") field)) - ;; Already there, do nothing. - ) - ((and (not overwrite-flag) - (mh-goto-header-field (concat field ":"))) - (insert " " value ",")) - (t - (mh-goto-header-end 0) - (insert field ": " value "\n")))) - -(defun mh-regexp-in-field-p (regexp &rest fields) - "Non-nil means REGEXP was found in FIELDS." - (let ((old-syntax-table (syntax-table))) - (unwind-protect - (save-excursion - (let ((search-result nil)) - (while fields - (let* ((field (car fields)) - (syntax-table - (or mh-regexp-in-field-syntax-table - (let ((case-fold-search t)) - (cond - ((string-match field "^To$\\|^[BD]?cc$\\|^From$") - mh-addr-syntax-table) - ((string-match field "^Fcc$") - mh-fcc-syntax-table) - (t - (syntax-table))) - )))) - (if (and (mh-goto-header-field field) - (set-syntax-table syntax-table) - (re-search-forward - regexp (save-excursion (mh-header-field-end)(point)) t)) - (setq fields nil - search-result t) - (setq fields (cdr fields))) - (set-syntax-table old-syntax-table))) - search-result)) - (set-syntax-table old-syntax-table)))) - -(defun mh-ascii-buffer-p () - "Check if current buffer is entirely composed of ASCII." - (cl-loop for charset in (find-charset-region (point-min) (point-max)) - unless (eq charset 'ascii) return nil - finally return t)) - -(provide 'mh-comp) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-comp.el ends here diff --git a/lisp/mh-e/mh-e.el b/lisp/mh-e/mh-e.el deleted file mode 100644 index 3d686b4a777..00000000000 --- a/lisp/mh-e/mh-e.el +++ /dev/null @@ -1,3711 +0,0 @@ -;;; mh-e.el --- GNU Emacs interface to the MH mail system -*- lexical-binding: t; -*- - -;; Copyright (C) 1985-1988, 1990, 1992-1995, 1997, 1999-2024 Free -;; Software Foundation, Inc. - -;; Author: Bill Wohler -;; Version: 8.6+git -;; Keywords: mail - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; MH-E is an Emacs interface to the MH mail system. - -;; MH-E is compatible with MH versions 6.8.4 and higher, all versions -;; of nmh, and GNU mailutils 1.0 and higher. - -;; MH (Message Handler) is a powerful mail reader. See -;; https://rand-mh.sourceforge.io/. - -;; N.B. MH must have been compiled with the MHE compiler flag or several -;; features necessary for MH-E will be missing from MH commands, specifically -;; the -build switch to repl and forw. - -;; How to use: -;; M-x mh-rmail to read mail. Type C-h m there for a list of commands. -;; C-u M-x mh-rmail to visit any folder. -;; M-x mh-smail to send mail. From within the mail reader, "s" works, too. - -;; Your .emacs might benefit from these bindings: -;; (global-set-key "\C-cr" 'mh-rmail) -;; (global-set-key "\C-xm" 'mh-smail) -;; (global-set-key "\C-x4m" 'mh-smail-other-window) - -;; Mailing Lists: -;; mh-e-users@lists.sourceforge.net -;; mh-e-announce@lists.sourceforge.net -;; mh-e-devel@lists.sourceforge.net - -;; Subscribe by sending a "subscribe" message to -;; -request@lists.sourceforge.net, or by using the web interface at -;; https://sourceforge.net/mail/?group_id=13357 - -;; Bug Reports: -;; https://sourceforge.net/tracker/?group_id=13357&atid=113357 -;; Include the output of M-x mh-version in the bug report unless -;; you're 110% sure we won't ask for it. - -;; Feature Requests: -;; https://sourceforge.net/tracker/?group_id=13357&atid=363357 - -;; Support: -;; https://sourceforge.net/tracker/?group_id=13357&atid=213357 - -;;; Change Log: - -;; Original version for Gosling emacs by Brian Reid, Stanford, 1982. -;; Modified by James Larus, BBN, July 1984 and UCB, 1984 & 1985. -;; Rewritten for GNU Emacs, James Larus, 1985. -;; Modified by Stephen Gildea, 1988. -;; Maintenance picked up by Bill Wohler and the -;; SourceForge Crew , 2001. -;; Since 2016, MH-E development occurs within the Emacs repository. - -;;; Code: - -;; Provide functions to the rest of MH-E. However, mh-e.el must not -;; use any definitions in files that require mh-e from mh-loaddefs, -;; for if it does it will introduce a require loop. -(require 'mh-loaddefs) - -(require 'cl-lib) - -(require 'mh-buffers) - - - -;;; Global Variables - -;; Try to keep variables local to a single file. Provide accessors if -;; variables are shared. Use this section as a last resort. - -(defconst mh-version "8.6+git" "Version number of MH-E.") - -;; Variants - -(defvar mh-sys-path - '("/usr/local/nmh/bin" ; nmh default - "/usr/local/bin/mh/" - "/usr/local/mh/" - "/usr/bin/mh/" ; Ultrix 4.2, Linux - "/usr/new/mh/" ; Ultrix < 4.2 - "/usr/contrib/mh/bin/" ; BSDI - "/usr/pkg/bin/" ; NetBSD - "/usr/local/bin/" - "/usr/local/bin/mu-mh/" ; GNU mailutils MH - default - "/usr/bin/mu-mh/") ; GNU mailutils MH - packaged - "List of directories to search for variants of the MH variant. -The list `exec-path' is searched in addition to this list. -There's no need for users to modify this list. Instead add extra -directories to the customizable variable `mh-path'.") - -(defvar mh-variants nil - "List describing known MH variants. -Do not access this variable directly as it may not have yet been initialized. -Use the function `mh-variants' instead.") - -(defvar mh-variant-in-use nil - "The MH variant currently in use; a string with variant and version number. -This differs from `mh-variant' when the latter is set to -\"autodetect\".") - -(defvar mh-progs nil - "Directory containing MH commands, such as inc, repl, and rmm.") - -;;;###autoload -(put 'mh-progs 'risky-local-variable t) - -(defvar mh-lib nil - "Directory containing the MH library. -This directory contains, among other things, the components file.") - -;;;###autoload -(put 'mh-lib 'risky-local-variable t) - -(defvar mh-lib-progs nil - "Directory containing MH helper programs. -This directory contains, among other things, the mhl program.") - -;;;###autoload -(put 'mh-lib-progs 'risky-local-variable t) - -;; Profile Components - -(defvar mh-draft-folder nil - "Cached value of the \"Draft-Folder:\" MH profile component. -Name of folder containing draft messages. -Do not use a draft folder if nil.") - -(defvar mh-inbox nil - "Cached value of the \"Inbox:\" MH profile component. -Set to \"+inbox\" if no such component. -Name of the Inbox folder.") - -(defvar mh-user-path nil - "Cached value of the \"Path:\" MH profile component. -User's mail folder directory.") - -;; Maps declared here so that they can be used in docstrings. - -(defvar-keymap mh-folder-mode-map - :doc "Keymap for MH-Folder mode." - :full t) - -(defvar mh-folder-seq-tool-bar-map nil - "Keymap for MH-Folder tool bar.") - -(defvar mh-folder-tool-bar-map nil - "Keymap for MH-Folder tool bar.") - -(defvar-keymap mh-inc-spool-map - :doc "Keymap for MH-E's mh-inc-spool commands.") - -(defvar mh-letter-mode-map (copy-keymap text-mode-map) - "Keymap for MH-Letter mode.") - -(defvar mh-letter-tool-bar-map nil - "Keymap for MH-Letter tool bar.") - -(defvar-keymap mh-search-mode-map - :doc "Keymap for MH-Search mode.") - -(defvar-keymap mh-show-mode-map - :doc "Keymap for MH-Show mode.") - -(defvar mh-show-seq-tool-bar-map nil - "Keymap for MH-Show tool bar.") - -(defvar mh-show-tool-bar-map nil - "Keymap for MH-Show tool bar.") - -;; MH-Folder Locals (alphabetical) - -(defvar mh-arrow-marker nil - "Marker for arrow display in fringe.") - -(defvar mh-blocklist nil - "List of messages to use to train the junk filter. -This variable can be used by -`mh-before-commands-processed-hook'.") - -(defvar mh-colors-available-flag nil - "Non-nil means colors are available.") - -(defvar mh-current-folder nil - "Name of current folder, a string.") - -(defvar mh-delete-list nil - "List of message numbers to delete. -This variable can be used by -`mh-before-commands-processed-hook'.") - -(defvar mh-folder-view-stack nil - "Stack of previous folder views.") - -(defvar mh-index-data nil - "Info about index search results.") - -(defvar mh-index-previous-search nil) - -(defvar mh-index-msg-checksum-map nil) - -(defvar mh-index-checksum-origin-map nil) - -(defvar mh-index-sequence-search-flag nil) - -(defvar mh-mode-line-annotation nil - "Message range displayed in buffer.") - -(defvar mh-next-direction 'forward - "Direction to move to next message.") - -(defvar mh-previous-window-config nil - "Window configuration before MH-E command.") - -(defvar mh-refile-list nil - "List of folder names in `mh-seq-list'. -This variable can be used by -`mh-before-commands-processed-hook'.") - -(defvar mh-seen-list nil - "List of displayed messages to be removed from the \"Unseen\" sequence.") - -(defvar mh-seq-list nil - "Alist of this folder's sequences. -Elements have the form (SEQUENCE . MESSAGES).") - -(defvar mh-sequence-notation-history nil - "Remember original notation that is overwritten by `mh-note-seq'.") - -(defvar mh-show-buffer nil - "Buffer that displays message for this folder.") - -(define-minor-mode mh-showing-mode - "Minor mode to show the message in a separate window." - ;; FIXME: maybe this should be moved to mh-show.el. - :lighter " Show") - -(defvar mh-view-ops nil - "Stack of operations that change the folder view. -These operations include narrowing or threading.") - -(defvar mh-allowlist nil - "List of messages to use to train the junk filter. -This variable can be used by -`mh-before-commands-processed-hook'.") - -;; MH-Show Locals (alphabetical) - -(defvar mh-globals-hash (make-hash-table) - "Keeps track of MIME data on a per buffer basis.") - -(defvar mh-show-folder-buffer nil - "Keeps track of folder whose message is being displayed.") - -;; MH-Letter Locals - -(defvar mh-folders-changed nil - "Lists which folders were affected by deletes and refiles. -This list will always include the current folder -`mh-current-folder'. This variable can be used by -`mh-after-commands-processed-hook'.") - -(defcustom mh-mail-header-separator "--------" - "Line used by MH to separate headers from text in messages being composed. - -This variable should not be used directly in programs. Programs -should use `mail-header-separator' instead. -`mail-header-separator' is initialized to -`mh-mail-header-separator' in `mh-letter-mode'; in other -contexts, you may have to perform this initialization yourself. - -Do not make this a regular expression as it may be the argument -to `insert' and it is passed through `regexp-quote' before being -used by functions like `re-search-forward'." - :group 'mh-e ; FIXME? - :type 'string) - -(defvar mh-sent-from-folder nil - "Folder of msg assoc with this letter.") - -(defvar mh-sent-from-msg nil - "Number of msg assoc with this letter.") - -;; Sequences - -(defvar mh-unseen-seq nil - "Cached value of the \"Unseen-Sequence:\" MH profile component. -Name of the Unseen sequence.") - -(defvar mh-previous-seq nil - "Cached value of the \"Previous-Sequence:\" MH profile component. -Name of the Previous sequence.") - -;; Etc. (alphabetical) - -(defvar mh-flists-present-flag nil - "Non-nil means that we have \"flists\".") - -(defvar mh-index-data-file ".mhe_index" - "MH-E specific file where index search info is stored.") - -(defvar mh-letter-header-field-regexp "^\\([A-Za-z][A-Za-z0-9-]*\\):") - -(defvar mh-page-to-next-msg-flag nil - "Non-nil means next SPC or whatever goes to next undeleted message.") - -(defvar mh-pgp-support-flag (not (not (locate-library "mml2015"))) - "Non-nil means PGP support is available.") - -(defvar mh-signature-separator "-- \n" - "Text of a signature separator. - -A signature separator is used to separate the body of a message -from the signature. This can be used by user agents such as MH-E -to render the signature differently or to suppress the inclusion -of the signature in a reply. Use `mh-signature-separator-regexp' -when searching for a separator.") - -(defvar mh-signature-separator-regexp "^-- $" - "This regular expression matches the signature separator. -See `mh-signature-separator'.") - -(defvar-local mh-thread-scan-line-map nil - "Map of message index to various parts of the scan line.") - -(defvar-local mh-thread-scan-line-map-stack nil - "Old map of message index to various parts of the scan line. -This is the original map that is stored when the folder is -narrowed.") - -(defcustom 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." - :group 'mh-e ; FIXME? - :type '(choice (const :tag "Default" nil) string)) - - -;;; MH-E Entry Points - -(eval-when-compile (require 'gnus)) - -(defmacro mh-macro-expansion-time-gnus-version () - "Return Gnus version available at macro expansion time. -The macro evaluates the Gnus version at macro expansion time. If -MH-E was compiled then macro expansion happens at compile time." -gnus-version) - -(defun mh-run-time-gnus-version () - "Return Gnus version available at run time." - (require 'gnus) - gnus-version) - -(defvar mh-variant) - -;;;###autoload -(defun mh-version () - "Display version information about MH-E and the MH mail handling system." - (interactive) - (set-buffer (get-buffer-create mh-info-buffer)) - (erase-buffer) - ;; MH-E version. - (insert "MH-E " mh-version "\n\n") - ;; MH-E compilation details. - (insert "MH-E compilation details:\n") - (let* ((compiled-mhe (compiled-function-p (symbol-function 'mh-version))) - (gnus-compiled-version (if compiled-mhe - (mh-macro-expansion-time-gnus-version) - "N/A"))) - (insert " Compiled:\t\t" (if compiled-mhe "yes" "no") "\n" - " Gnus (compile-time):\t" gnus-compiled-version "\n" - " Gnus (run-time):\t" (mh-run-time-gnus-version) "\n\n")) - ;; Emacs version. - (insert (emacs-version) "\n\n") - ;; MH version. - (or mh-variant-in-use (mh-variant-set mh-variant)) - (if mh-variant-in-use - (insert mh-variant-in-use "\n" - " mh-progs:\t" mh-progs "\n" - " mh-lib:\t" mh-lib "\n" - " mh-lib-progs:\t" mh-lib-progs "\n\n") - (insert "No MH variant detected\n")) - ;; Linux version. - (condition-case () - (call-process "uname" nil t nil "-a") - (file-error)) - (goto-char (point-min)) - (display-buffer mh-info-buffer)) - - - -;;; Support Routines - -(defun mh-list-to-string (l) - "Flatten the list L and make every element of the new list into a string." - (nreverse (mh-list-to-string-1 l))) - -(defun mh-list-to-string-1 (l) - "Flatten the list L and make every element of the new list into a string." - (let (new-list) - (dolist (element l) - (cond ((null element)) - ((symbolp element) - (push (symbol-name element) new-list)) - ((numberp element) - (push (int-to-string element) new-list)) - ((equal element "")) - ((stringp element) - (push element new-list)) - ((listp element) - (setq new-list (nconc (mh-list-to-string-1 element) new-list))) - (t - (error "Bad element: %s" element)))) - new-list)) - - - -;;; MH-E Process Support - -(defvar mh-index-max-cmdline-args 500 - "Maximum number of command line args.") - -(defun mh-xargs (cmd &rest args) - "Partial imitation of xargs. -The current buffer contains a list of strings, one on each line. -The function 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 ((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) - (cl-incf count) - (forward-line)) - (apply #'call-process cmd nil (list out nil) nil - (nreverse arg-list)))) - (erase-buffer) - (insert-buffer-substring out))))) - -;; XXX This should be applied anywhere MH-E calls out to /bin/sh. -(defun mh-quote-for-shell (string) - "Quote STRING for /bin/sh. -Adds double-quotes around entire string and quotes the characters -\\, `, and $ with a backslash." - (concat "\"" - (cl-loop for x across string - concat (format (if (memq x '(?\\ ?` ?$)) "\\%c" "%c") x)) - "\"")) - -(defun mh-exec-cmd (command &rest args) - "Execute mh-command COMMAND with ARGS. -The side effects are what is desired. Any output is assumed to be -an error and is shown to the user. The output is not read or -parsed by MH-E." - (with-current-buffer (get-buffer-create mh-log-buffer) - (let* ((initial-size (mh-truncate-log-buffer)) - (start (point)) - (args (mh-list-to-string args))) - (apply #'call-process (expand-file-name command mh-progs) nil t nil args) - (when (> (buffer-size) initial-size) - (save-excursion - (goto-char start) - (insert "Errors when executing: " command) - (cl-loop for arg in args do (insert " " arg)) - (insert "\n")) - (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. -ENV is nil or a string of space-separated \"var=value\" elements. -Signals an error if process does not complete successfully." - (with-current-buffer (get-buffer-create mh-temp-buffer) - (erase-buffer) - (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. - -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." - (with-current-buffer (get-buffer-create mh-log-buffer) - (mh-truncate-log-buffer)) - (let* ((process-connection-type nil) - (process (apply #'start-process - command nil - (expand-file-name command mh-progs) - (mh-list-to-string args)))) - (set-process-filter process (or filter 'mh-process-daemon)) - process)) - -(defun mh-exec-cmd-env-daemon (env command filter &rest args) - "In environment 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." - (with-current-buffer (get-buffer-create mh-log-buffer) - (insert-before-markers output) - (display-buffer mh-log-buffer))) - -(defun mh-exec-cmd-quiet (raise-error command &rest args) - "Signal RAISE-ERROR if COMMAND with ARGS fails. -Execute MH command COMMAND with ARGS. ARGS is a list of strings. -Return at start of mh-temp buffer, where output can be parsed and -used. -Returns value of `call-process', which is 0 for success, unless -RAISE-ERROR is non-nil, in which case an error is signaled if -`call-process' returns non-0." - (set-buffer (get-buffer-create mh-temp-buffer)) - (erase-buffer) - (let ((value - (apply #'call-process - (expand-file-name command mh-progs) nil t nil - args))) - (goto-char (point-min)) - (if raise-error - (mh-handle-process-error command value) - value))) - -(defun mh-exec-cmd-output (command display &rest args) - "Execute MH command COMMAND with DISPLAY flag and ARGS. -Put the output into buffer after point. -Set mark after inserted text. -Output is expected to be shown to user, not parsed by MH-E." - (push-mark (point) t) - (apply #'call-process - (expand-file-name command mh-progs) nil t display - (mh-list-to-string args)) - - ;; The following is used instead of 'exchange-point-and-mark because the - ;; latter activates the current region (between point and mark), which - ;; turns on highlighting. So prior to this bug fix, doing "inc" would - ;; highlight a region containing the new messages, which is undesirable. - ;; The bug wasn't seen in emacs21 but still occurred in XEmacs21.4. - (mh-exchange-point-and-mark-preserving-active-mark)) - -(defun mh-exchange-point-and-mark-preserving-active-mark () - "Put the mark where point is now, and point where the mark is now. -This command works even when the mark is not active, and -preserves whether the mark is active or not." - (interactive nil) - (let ((is-active mark-active)) - (let ((omark (mark t))) - (if (null omark) - (error "No mark set in this buffer")) - (set-mark (point)) - (goto-char omark) - (setq mark-active is-active) - nil))) - -(defun mh-exec-lib-cmd-output (command &rest args) - "Execute MH library command COMMAND with ARGS. -Put the output into buffer after point. -Set mark after inserted text." - (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." - (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))) - (let ((error-message (buffer-substring (point-min) (point-max)))) - (with-current-buffer (get-buffer-create mh-log-buffer) - (mh-truncate-log-buffer) - (insert error-message))) - (error "%s failed, check buffer %s for error message" - command mh-log-buffer))) - - - -;;; MH-E Customization Support Routines - -;; Temporary function and data structure used customization. -;; These will be unbound after the options are defined. -(defmacro mh-strip-package-version (args) - "ARGS is returned unchanged." - (declare (obsolete identity "29.1")) - args) - -(defmacro defgroup-mh (symbol members doc &rest args) - "Declare SYMBOL as a customization group containing MEMBERS. -See documentation for `defgroup' for a description of the arguments -SYMBOL, MEMBERS, DOC and ARGS." - (declare (obsolete defgroup "29.1") (doc-string 3) (indent defun)) - `(defgroup ,symbol ,members ,doc ,args)) - -(defmacro defcustom-mh (symbol value doc &rest args) - "Declare SYMBOL as a customizable variable that defaults to VALUE. -See documentation for `defcustom' for a description of the arguments -SYMBOL, VALUE, DOC and ARGS." - (declare (obsolete defcustom "29.1") (doc-string 3) (indent defun)) - `(defcustom ,symbol ,value ,doc ,args)) - -(defmacro defface-mh (face spec doc &rest args) - "Declare FACE as a customizable face that defaults to SPEC. -See documentation for `defface' for a description of the arguments -FACE, SPEC, DOC and ARGS." - (declare (obsolete defface "29.1") (doc-string 3) (indent defun)) - `(defface ,face ,spec ,doc ,args)) - - - -;;; Variant Support - -(defcustom mh-path nil - "Additional list of directories to search for MH. -See `mh-variant'." - :group 'mh-e - :type '(repeat (directory)) - :package-version '(MH-E . "8.0")) - -(defun mh-variants () - "Return a list of installed variants of MH on the system. -This function looks for MH in `mh-sys-path', `mh-path' and -`exec-path'. The format of the list of variants that is returned -is described by the variable `mh-variants'." - (if mh-variants - mh-variants - (let ((list-unique)) - ;; Make a unique list of directories, keeping the given order. - ;; We don't want the same MH variant to be listed multiple times. - (cl-loop for dir in (append mh-path mh-sys-path exec-path) do - ;; skip relative dirs, typically "." - (if (file-name-absolute-p dir) - (progn - (setq dir (file-chase-links (directory-file-name dir))) - (cl-pushnew dir list-unique :test #'equal)))) - (cl-loop for dir in (nreverse list-unique) do - (when (and dir (file-accessible-directory-p dir)) - (let ((variant (mh-variant-info dir))) - (if variant - (add-to-list 'mh-variants variant))))) - mh-variants))) - -(defun mh-variant-info (dir) - "Return MH variant found in DIR, or nil if none present." - (let ((tmp-buffer (get-buffer-create mh-temp-buffer))) - (with-current-buffer tmp-buffer - (cond - ((mh-variant-mh-info dir)) - ((mh-variant-nmh-info dir)) - ((mh-variant-gnu-mh-info dir)))))) - -(defun mh-variant-mh-info (dir) - "Return info for MH variant in DIR assuming a temporary buffer is set up." - ;; MH does not have the -version option. - ;; Its version number is included in the output of "-help" as: - ;; - ;; version: MH 6.8.4 #2[UCI] (burrito) of Fri Jan 15 20:01:39 EST 1999 - ;; options: [ATHENA] [BIND] [DUMB] [LIBLOCKFILE] [LOCALE] [MAILGROUP] [MHE] - ;; [MHRC] [MIME] [MORE='"/usr/bin/sensible-pager"'] [NLINK_HACK] - ;; [NORUSERPASS] [OVERHEAD] [POP] [POPSERVICE='"pop-3"'] [RENAME] - ;; [RFC1342] [RPATHS] [RPOP] [SENDMTS] [SMTP] [SOCKETS] - ;; [SPRINTFTYPE=int] [SVR4] [SYS5] [SYS5DIR] [TERMINFO] - ;; [TYPESIG=void] [UNISTD] [UTK] [VSPRINTF] - (let ((mhparam (expand-file-name "mhparam" dir))) - (when (mh-file-command-p mhparam) - (erase-buffer) - (call-process mhparam nil '(t nil) nil "-help") - (goto-char (point-min)) - (when (search-forward-regexp "version: MH \\(\\S +\\)" nil t) - (let ((version (format "MH %s" (match-string 1)))) - (erase-buffer) - (call-process mhparam nil '(t nil) nil "libdir") - (goto-char (point-min)) - (when (search-forward-regexp "^.*$" nil t) - (let ((libdir (match-string 0))) - `(,version - (variant mh) - (mh-lib-progs ,libdir) - (mh-lib ,libdir) - (mh-progs ,dir) - (flists nil))))))))) - -(defun mh-variant-gnu-mh-info (dir) - "Return info for GNU mailutils MH variant in DIR. -This assumes that a temporary buffer is set up." - ;; Sample '-version' outputs: - ;; mhparam (GNU mailutils 0.3.2) - ;; install-mh (GNU Mailutils 2.2) - ;; install-mh (GNU Mailutils 3.7) - (let ((install-mh (expand-file-name "install-mh" dir))) - (when (mh-file-command-p install-mh) - (erase-buffer) - (call-process install-mh nil '(t nil) nil "-version") - (goto-char (point-min)) - (when (search-forward-regexp "install-mh (\\(GNU [Mm]ailutils \\S +\\))" - nil t) - (let ((version (match-string 1)) - (mh-progs dir)) - `(,version - (variant gnu-mh) - (mh-lib-progs ,(mh-profile-component "libdir")) - (mh-lib ,(mh-profile-component "etcdir")) - (mh-progs ,dir) - (flists ,(file-exists-p - (expand-file-name "flists" dir))))))))) - -(defun mh-variant-nmh-info (dir) - "Return info for nmh variant in DIR assuming a temporary buffer is set up." - ;; Sample '-version' outputs: - ;; mhparam -- nmh-1.1-RC1 [compiled on chaak at Fri Jun 20 11:03:28 PDT 2003] - ;; install-mh -- nmh-1.7.1 built October 26, 2019 on build-server-000 - ;; "libdir" was deprecated in nmh-1.7 in favor of "libexecdir", and - ;; removed completely in nmh-1.8. - (let ((install-mh (expand-file-name "install-mh" dir))) - (when (mh-file-command-p install-mh) - (erase-buffer) - (call-process install-mh nil '(t nil) nil "-version") - (goto-char (point-min)) - (when (search-forward-regexp "install-mh -- nmh-\\(\\S +\\)" nil t) - (let ((version (format "nmh %s" (match-string 1))) - (mh-progs dir)) - `(,version - (variant nmh) - (mh-lib-progs ,(or (mh-profile-component "libdir") - (mh-profile-component "libexecdir"))) - (mh-lib ,(mh-profile-component "etcdir")) - (mh-progs ,dir) - (flists ,(file-exists-p - (expand-file-name "flists" dir))))))))) - -(defun mh-file-command-p (file) - "Return t if file FILE is the name of an executable regular file." - (and (file-regular-p file) (file-executable-p file))) - -(defun mh-variant-set-variant (variant) - "Set up the system variables for the MH variant named VARIANT. -If VARIANT is a string, use that key in the alist returned by the -function `mh-variants'. -If VARIANT is a symbol, select the first entry that matches that -variant." - (cond - ((stringp variant) ;e.g. "nmh 1.1-RC1" - (when (assoc variant (mh-variants)) - (let* ((alist (cdr (assoc variant (mh-variants)))) - (lib-progs (cadr (assoc 'mh-lib-progs alist))) - (lib (cadr (assoc 'mh-lib alist))) - (progs (cadr (assoc 'mh-progs alist))) - (flists (cadr (assoc 'flists alist)))) - ;;(set-default mh-variant variant) - (setq mh-x-mailer-string nil - mh-flists-present-flag flists - mh-lib-progs lib-progs - mh-lib lib - mh-progs progs - mh-variant-in-use variant)))) - ((symbolp variant) ;e.g. 'nmh (pick the first match) - (cl-loop for variant-list in (mh-variants) - when (eq variant (cadr (assoc 'variant (cdr variant-list)))) - return (let* ((version (car variant-list)) - (alist (cdr variant-list)) - (lib-progs (cadr (assoc 'mh-lib-progs alist))) - (lib (cadr (assoc 'mh-lib alist))) - (progs (cadr (assoc 'mh-progs alist))) - (flists (cadr (assoc 'flists alist)))) - ;;(set-default mh-variant flavor) - (setq mh-x-mailer-string nil - mh-flists-present-flag flists - mh-lib-progs lib-progs - mh-lib lib - mh-progs progs - mh-variant-in-use version) - t))))) - -(defun mh-variant-p (&rest variants) - "Return t if variant is any of VARIANTS. -Currently known variants are `MH', `nmh', and `gnu-mh'." - (or mh-variant-in-use (mh-variant-set mh-variant)) - (let ((variant-in-use - (cadr (assoc 'variant (assoc mh-variant-in-use (mh-variants)))))) - (not (null (member variant-in-use variants))))) - -(defun mh-profile-component (component) - "Return COMPONENT value from mhparam, or nil if unset." - (save-excursion - ;; MH and nmh use -components, GNU mailutils MH uses -component. - ;; Since MH and nmh work with an unambiguous prefix, the `s' is - ;; dropped here. - (mh-exec-cmd-quiet nil "mhparam" "-component" component) - (mh-profile-component-value component))) - -(defun mh-profile-component-value (component) - "Find and return the value of COMPONENT in the current buffer. -Returns nil if the component is not in the buffer." - (let ((case-fold-search t)) - (goto-char (point-min)) - (cond ((not (re-search-forward (format "^%s:" component) nil t)) nil) - ((looking-at "[\t ]*$") nil) - (t - (re-search-forward "[\t ]*\\([^\t \n].*\\)$" nil t) - (let ((start (match-beginning 1))) - (end-of-line) - (buffer-substring start (point))))))) - -(defun mh-variant-set (variant) - "Set the MH variant to VARIANT. -Sets `mh-progs', `mh-lib', `mh-lib-progs' and -`mh-flists-present-flag'. -If the VARIANT is \"autodetect\", then first try nmh, then MH and -finally GNU mailutils MH." - (interactive - (list (completing-read - "MH variant: " - (mapcar (lambda (x) (list (car x))) (mh-variants)) - nil t))) - - ;; TODO Remove mu-mh backwards compatibility in 9.0. - (when (and (stringp variant) - (string-match "^mu-mh" variant)) - (message - (format "%s\n%s; %s" "The variant name mu-mh has been renamed to gnu-mh" - "and will be removed in MH-E 9.0" - "try M-x customize-option mh-variant")) - (sit-for 5) - (setq variant (concat "gnu-mh" (substring variant (match-end 0))))) - - (let ((valid-list (mapcar (lambda (x) (car x)) (mh-variants)))) - (cond - ((eq variant 'none)) - ((eq variant 'autodetect) - (cond - ((mh-variant-set-variant 'nmh) - (message "%s installed as MH variant" mh-variant-in-use)) - ((mh-variant-set-variant 'mh) - (message "%s installed as MH variant" mh-variant-in-use)) - ((mh-variant-set-variant 'gnu-mh) - (message "%s installed as MH variant" mh-variant-in-use)) - (t - (message "No MH variant found on the system")))) - ((member variant valid-list) - (when (not (mh-variant-set-variant variant)) - (message "Warning: %s variant not found. Autodetecting..." variant) - (mh-variant-set 'autodetect))) - ((null valid-list) - (message "Unknown variant %s; can't find MH anywhere" variant)) - (t - (message "Unknown variant %s; use %s" - variant - (mapconcat (lambda (x) (format "%s" (car x))) - (mh-variants) " or ")))))) - -(defcustom mh-variant 'autodetect - "Specifies the variant used by MH-E. - -The default setting of this option is \"Auto-detect\" which means -that MH-E will automatically choose the first of nmh, MH, or GNU -mailutils MH that it finds in the directories listed in -`mh-path' (which you can customize), `mh-sys-path', and -`exec-path'. If MH-E can't find MH at all, you may have to -customize `mh-path' and add the directory in which the command -\"mhparam\" is located. If, on the other hand, you have both nmh -and GNU mailutils MH installed (for example) and -`mh-variant-in-use' was initialized to nmh but you want to use -GNU mailutils MH, then you can set this option to \"gnu-mh\". - -When this variable is changed, MH-E resets `mh-progs', `mh-lib', -`mh-lib-progs', `mh-flists-present-flag', and `mh-variant-in-use' -accordingly. Prior to version 8, it was often necessary to set -some of these variables in \"~/.emacs\"; now it is no longer -necessary and can actually cause problems." - :type `(radio - (const :tag "Auto-detect" autodetect) - ,@(mapcar (lambda (x) `(const ,(car x))) (mh-variants))) - :set (lambda (symbol value) - (set-default symbol value) ;Done in mh-variant-set-variant! - (mh-variant-set value)) - :initialize #'custom-initialize-default - :group 'mh-e - :package-version '(MH-E . "8.0")) - - - -;;; MH-E Customization - -;; 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 section contains the following sub-sections: - -;; 1. MH-E Customization Groups - -;; These are the customization group definitions. Every group has a -;; associated manual node. The ordering is alphabetical, except for -;; the groups mh-faces and mh-hooks which are last . - -;; 2. MH-E Customization - -;; These are the actual customization variables. There is a -;; sub-section for each group in the MH-E Customization Groups -;; section, in the same order, separated by page breaks. Within -;; each section, variables are sorted alphabetically. - -;; 3. Hooks - -;; All hooks must be placed in the mh-hook group; in addition, add -;; the group associated with the manual node in which the hook is -;; described. Since the mh-hook group appears near the end of this -;; section, the hooks will appear at the end of these other groups. - -;; 4. Faces - -;; All faces must be placed in the mh-faces group; in addition, add -;; the group associated with the manual node in which the face is -;; described. Since the mh-faces group appears near the end of this -;; section, the faces will appear at the end of these other groups. - -(defun mh-customize (&optional delete-other-windows-flag) - "Customize MH-E variables. -If optional argument DELETE-OTHER-WINDOWS-FLAG is non-nil, other -windows in the frame are removed." - (interactive "P") - (customize-group 'mh-e) - (when delete-other-windows-flag - (delete-other-windows))) - -(add-to-list 'customize-package-emacs-version-alist - '(MH-E ("6.0" . "22.1") ("6.1" . "22.1") ("7.0" . "22.1") - ("7.1" . "22.1") ("7.2" . "22.1") ("7.3" . "22.1") - ("7.4" . "22.1") ("8.0" . "22.1") ("8.1" . "23.1") - ("8.2" . "23.1") ("8.3" . "24.1") ("8.4" . "24.4") - ("8.5" . "24.4") ("8.6" . "24.4"))) - - - -;;; MH-E Customization Groups - -(defgroup mh-e nil - "Emacs interface to the MH mail system. -MH is the Rand Mail Handler. Other implementations include nmh -and GNU mailutils." - :link '(custom-manual "(mh-e)Top") - :group 'mail - :package-version '(MH-E . "8.0")) - -(defgroup mh-alias nil - "Aliases." - :link '(custom-manual "(mh-e)Aliases") - :prefix "mh-alias-" - :group 'mh-e - :package-version '(MH-E . "7.1")) - -(defgroup mh-folder nil - "Organizing your mail with folders." - :prefix "mh-" - :link '(custom-manual "(mh-e)Folders") - :group 'mh-e - :package-version '(MH-E . "7.1")) - -(defgroup mh-folder-selection nil - "Folder selection." - :prefix "mh-" - :link '(custom-manual "(mh-e)Folder Selection") - :group 'mh-e - :package-version '(MH-E . "8.0")) - -(defgroup mh-identity nil - "Identities." - :link '(custom-manual "(mh-e)Identities") - :prefix "mh-identity-" - :group 'mh-e - :package-version '(MH-E . "7.1")) - -(defgroup mh-inc nil - "Incorporating your mail." - :prefix "mh-inc-" - :link '(custom-manual "(mh-e)Incorporating Mail") - :group 'mh-e - :package-version '(MH-E . "8.0")) - -(defgroup mh-junk nil - "Dealing with junk mail." - :link '(custom-manual "(mh-e)Junk") - :prefix "mh-junk-" - :group 'mh-e - :package-version '(MH-E . "7.3")) - -(defgroup mh-letter nil - "Editing a draft." - :prefix "mh-" - :link '(custom-manual "(mh-e)Editing Drafts") - :group 'mh-e - :package-version '(MH-E . "7.1")) - -(defgroup mh-ranges nil - "Ranges." - :prefix "mh-" - :link '(custom-manual "(mh-e)Ranges") - :group 'mh-e - :package-version '(MH-E . "8.0")) - -(defgroup mh-scan-line-formats nil - "Scan line formats." - :link '(custom-manual "(mh-e)Scan Line Formats") - :prefix "mh-" - :group 'mh-e - :package-version '(MH-E . "8.0")) - -(defgroup mh-search nil - "Searching." - :link '(custom-manual "(mh-e)Searching") - :prefix "mh-search-" - :group 'mh-e - :package-version '(MH-E . "8.0")) - -(defgroup mh-sending-mail nil - "Sending mail." - :prefix "mh-" - :link '(custom-manual "(mh-e)Sending Mail") - :group 'mh-e - :package-version '(MH-E . "8.0")) - -(defgroup mh-sequences nil - "Sequences." - :prefix "mh-" - :link '(custom-manual "(mh-e)Sequences") - :group 'mh-e - :package-version '(MH-E . "8.0")) - -(defgroup mh-show nil - "Reading your mail." - :prefix "mh-" - :link '(custom-manual "(mh-e)Reading Mail") - :group 'mh-e - :package-version '(MH-E . "7.1")) - -(defgroup mh-speedbar nil - "The speedbar." - :prefix "mh-speed-" - :link '(custom-manual "(mh-e)Speedbar") - :group 'mh-e - :package-version '(MH-E . "8.0")) - -(defgroup mh-thread nil - "Threading." - :prefix "mh-thread-" - :link '(custom-manual "(mh-e)Threading") - :group 'mh-e - :package-version '(MH-E . "8.0")) - -(defgroup mh-tool-bar nil - "The tool bar." - :link '(custom-manual "(mh-e)Tool Bar") - :prefix "mh-" - :group 'mh-e - :package-version '(MH-E . "8.0")) - -(defgroup mh-hooks nil - "MH-E hooks." - :link '(custom-manual "(mh-e)Top") - :prefix "mh-" - :group 'mh-e - :package-version '(MH-E . "7.1")) - -(defgroup mh-faces nil - "Faces used in MH-E." - :link '(custom-manual "(mh-e)Top") - :prefix "mh-" - :group 'faces - :group 'mh-e - :package-version '(MH-E . "7.1")) - - - -;;; MH-E Customization - -;; See Variant Support, above, for mh-e group. - -;;; Aliases (:group 'mh-alias) - -(defcustom mh-alias-completion-ignore-case-flag t - "Non-nil means don't consider case significant in MH alias completion. - -As MH ignores case in the aliases, so too does MH-E. However, you -may turn off this option to make case significant which can be -used to segregate completion of your aliases. You might use -lowercase for mailing lists and uppercase for people." - :type 'boolean - :group 'mh-alias - :package-version '(MH-E . "7.1")) - -(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 - :package-version '(MH-E . "7.1")) - -(defcustom mh-alias-flash-on-comma t - "Specify whether to flash address or warn on translation. - -This option controls the behavior when a [comma] is pressed while -entering aliases or addresses. The default setting flashes the -address associated with an address in the minibuffer briefly, but -does not display a warning if the alias is not found." - :type '(choice (const :tag "Flash but Don't Warn If No Alias" t) - (const :tag "Flash and Warn If No Alias" 1) - (const :tag "Don't Flash Nor Warn If No Alias" nil)) - :group 'mh-alias - :package-version '(MH-E . "7.1")) - -(defcustom mh-alias-insert-file nil - "Filename used to store a new MH-E alias. - -The default setting of this option is \"Use Aliasfile Profile -Component\". This option can also hold the name of a file or a -list a file names. If this option is set to a list of file names, -or the \"Aliasfile:\" profile component contains more than one file -name, MH-E will prompt for one of them when MH-E adds an alias." - :type '(choice (const :tag "Use Aliasfile Profile Component" nil) - (file :tag "Alias File") - (repeat :tag "List of Alias Files" file)) - :group 'mh-alias - :package-version '(MH-E . "7.1")) - -(defcustom mh-alias-insertion-location 'sorted - "Specifies where new aliases are entered in alias files. - -This option is set to \"Alphabetical\" by default. If you organize -your alias file in other ways, then adding aliases to the \"Top\" -or \"Bottom\" of your alias file might be more appropriate." - :type '(choice (const :tag "Alphabetical" sorted) - (const :tag "Top" top) - (const :tag "Bottom" bottom)) - :group 'mh-alias - :package-version '(MH-E . "7.1")) - -(defcustom mh-alias-local-users t - "Non-nil means local users are added to alias completion. - -Aliases are created from \"/etc/passwd\" entries with a user ID -larger than a magical number, typically 200. This can be a handy -tool on a machine where you and co-workers exchange messages. -These aliases have the form \"local.first.last\" if a real name is -present in the password file. Otherwise, the alias will have the -form \"local.login\". - -If you're on a system with thousands of users you don't know, and -the loading of local aliases slows MH-E down noticeably, then -turn this option off. - -This option also takes a string which is executed to generate the -password file. For example, use \"ypcat passwd\" to obtain the -NIS password file." - :type '(choice (boolean) (string)) - :group 'mh-alias - :package-version '(MH-E . "7.1")) - -(defcustom mh-alias-local-users-prefix "local." - "String prefixed to the real names of users from the password file. -This option can also be set to \"Use Login\". - -For example, consider the following password file entry: - - psg:x:1000:1000:Peter S Galbraith,,,:/home/psg:/bin/tcsh - -The following settings of this option will produce the associated -aliases: - - \"local.\" local.peter.galbraith - \"\" peter.galbraith - Use Login psg - -This option has no effect if variable `mh-alias-local-users' is -turned off." - :type '(choice (const :tag "Use Login" nil) - (string)) - :group 'mh-alias - :package-version '(MH-E . "7.4")) - -(defcustom mh-alias-passwd-gecos-comma-separator-flag t - "Non-nil means the gecos field in the password file uses a comma separator. - -In the example in `mh-alias-local-users-prefix', commas are used -to separate different values within the so-called gecos field. -This is a fairly common usage. However, in the rare case that the -gecos field in your password file is not separated by commas and -whose contents may contain commas, you can turn this option off." - :type 'boolean - :group 'mh-alias - :package-version '(MH-E . "7.4")) - -;;; Organizing Your Mail with Folders (:group 'mh-folder) - -(defcustom mh-new-messages-folders t - "Folders searched for the \"unseen\" sequence. - -Set this option to \"Inbox\" to search the \"+inbox\" folder or -\"All\" to search all of the top level folders. Otherwise, list -the folders that should be searched with the \"Choose Folders\" -menu item. - -See also `mh-recursive-folders-flag'." - :type '(choice (const :tag "Inbox" t) - (const :tag "All" nil) - (repeat :tag "Choose Folders" (string :tag "Folder"))) - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defcustom mh-ticked-messages-folders t - "Folders searched for `mh-tick-seq'. - -Set this option to \"Inbox\" to search the \"+inbox\" folder or -\"All\" to search all of the top level folders. Otherwise, list -the folders that should be searched with the \"Choose Folders\" -menu item. - -See also `mh-recursive-folders-flag'." - :type '(choice (const :tag "Inbox" t) - (const :tag "All" nil) - (repeat :tag "Choose Folders" (string :tag "Folder"))) - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defcustom mh-large-folder 200 - "The number of messages that indicates a large folder. - -If a folder is deemed to be large, that is the number of messages -in it exceed this value, then confirmation is needed when it is -visited. Even when `mh-show-threads-flag' is non-nil, the folder -is not automatically threaded, if it is large. If set to nil all -folders are treated as if they are small." - :type '(choice (const :tag "No Limit") integer) - :group 'mh-folder - :package-version '(MH-E . "7.0")) - -(defcustom mh-recenter-summary-flag nil - "Non-nil means to recenter the summary window. - -If this option is turned on, recenter the summary window when the -show window is toggled off." - :type 'boolean - :group 'mh-folder - :package-version '(MH-E . "7.0")) - -(defcustom mh-recursive-folders-flag nil - "Non-nil means that commands which operate on folders do so recursively." - :type 'boolean - :group 'mh-folder - :package-version '(MH-E . "7.0")) - -(defcustom mh-sortm-args nil - "Additional arguments for \"sortm\"\\. - -This option is consulted when a prefix argument is used with -\\[mh-sort-folder]. Normally default arguments to \"sortm\" are -specified in the MH profile. This option may be used to provide -an alternate view. For example, (\"-nolimit\" \"-textfield\" -\"subject\") is a useful setting." - :type '(repeat string) - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -;;; Folder Selection (:group 'mh-folder-selection) - -(defcustom mh-default-folder-for-message-function nil - "Function to select a default folder for refiling or \"Fcc:\". - -When this function is called, the current buffer contains the message -being refiled and point is at the start of the message. This function -should return the default folder as a string with a leading \"+\" -sign. It can also return nil so that the last folder name is used as -the default, or an empty string to suppress the default entirely." - :type '(choice (const nil) function) - :group 'mh-folder-selection - :package-version '(MH-E . "8.0")) - -(defcustom mh-default-folder-list nil - "List of addresses and folders. - -The folder name associated with the first address found in this -list is used as the default for `mh-refile-msg' and similar -functions. Each element in this list contains a \"Check Recipient\" -item. If this item is turned on, then the address is checked -against the recipient instead of the sender. This is useful for -mailing lists. - -See `mh-prompt-for-refile-folder' and `mh-folder-from-address' -for more information." - :type '(repeat (list (regexp :tag "Address") - (string :tag "Folder") - (boolean :tag "Check Recipient"))) - :group 'mh-folder-selection - :package-version '(MH-E . "7.2")) - -(defcustom mh-default-folder-must-exist-flag t - "Non-nil means guessed folder name must exist to be used. - -If the derived folder does not exist, and this option is on, then -the last folder name used is suggested. This is useful if you get -mail from various people for whom you have an alias, but file -them all in the same project folder. - -See `mh-prompt-for-refile-folder' and `mh-folder-from-address' -for more information." - :type 'boolean - :group 'mh-folder-selection - :package-version '(MH-E . "7.2")) - -(defcustom mh-default-folder-prefix "" - "Prefix used for folder names generated from aliases. -The prefix is used to prevent clutter in your mail directory. - -See `mh-prompt-for-refile-folder' and `mh-folder-from-address' -for more information." - :type 'string - :group 'mh-folder-selection - :package-version '(MH-E . "7.2")) - -;;; Identities (:group 'mh-identity) - -(eval-and-compile - (unless (fboundp 'mh-identity-make-menu-no-autoload) - (defun mh-identity-make-menu-no-autoload () - "Temporary definition. -Real definition will take effect when mh-identity is loaded." - nil))) - -(defcustom mh-identity-list nil - "List of identities. - -To customize this option, click on the \"INS\" button and enter a label -such as \"Home\" or \"Work\". Then click on the \"INS\" button with the -label \"Add at least one item below\". Then choose one of the items in -the \"Value Menu\". - -You can specify an alternate \"From:\" header field using the \"From -Field\" menu item. You must include a valid email address. A standard -format is \"First Last \". If you use an initial -with a period, then you must quote your name as in `\"First I. Last\" -'. People usually list the name of the company -where they work using the \"Organization Field\" menu item. Set any -arbitrary header field and value in the \"Other Field\" menu item. -Unless the header field is a standard one, precede the name of your -field's label with \"X-\", as in \"X-Fruit-of-the-Day:\". The value of -\"Attribution Verb\" overrides the setting of -`mh-extract-from-attribution-verb'. Set your signature with the -\"Signature\" menu item. You can specify the contents of -`mh-signature-file-name', a file, or a function. Specify a different -key to sign or encrypt messages with the \"GPG Key ID\" menu item. - -You can select the identities you have added via the menu called -\"Identity\" in the MH-Letter buffer. You can also use -\\[mh-insert-identity]. To clear the fields and signature added by the -identity, select the \"None\" identity. - -The \"Identity\" menu contains two other items to save you from having -to set the identity on every message. The menu item \"Set Default for -Session\" can be used to set the default identity to the current -identity until you exit Emacs. The menu item \"Save as Default\" sets -the option `mh-identity-default' to the current identity setting. You -can also customize the `mh-identity-default' option in the usual -fashion." - :type '(repeat (list :tag "" - (string :tag "Label") - (repeat :tag "Add at least one item below" - (choice - (cons :tag "From Field" - (const "From") - (string :tag "Value")) - (cons :tag "Organization Field" - (const "Organization") - (string :tag "Value")) - (cons :tag "Other Field" - (string :tag "Field") - (string :tag "Value")) - (cons :tag "Attribution Verb" - (const ":attribution-verb") - (string :tag "Value")) - (cons :tag "Signature" - (const :tag "Signature" - ":signature") - (choice - (const :tag "mh-signature-file-name" - nil) - (file) - (function))) - (cons :tag "GPG Key ID" - (const :tag "GPG Key ID" - ":pgg-default-user-id") - (string :tag "Value")))))) - :set (lambda (symbol value) - (set-default symbol value) - (mh-identity-make-menu-no-autoload)) - :group 'mh-identity - :package-version '(MH-E . "7.1")) - -(defcustom mh-auto-fields-list nil - "List of recipients for which header lines are automatically inserted. - -This option can be used to set the identity depending on the -recipient. To customize this option, click on the \"INS\" button and -enter a regular expression for the recipient's address. Click on the -\"INS\" button with the \"Add at least one item below\" label. Then choose -one of the items in the \"Value Menu\". - -The \"Identity\" menu item is used to select an identity from those -configured in `mh-identity-list'. All of the information for that -identity will be added if the recipient matches. The \"Fcc Field\" menu -item is used to select a folder that is used in the \"Fcc:\" header. -When you send the message, MH will put a copy of your message in this -folder. The \"Mail-Followup-To Field\" menu item is used to insert an -\"Mail-Followup-To:\" header field with the recipients you provide. If -the recipient's mail user agent supports this header field (as nmh -does), then their replies will go to the addresses listed. This is -useful if their replies go both to the list and to you and you don't -have a mechanism to suppress duplicates. If you reply to someone not -on the list, you must either remove the \"Mail-Followup-To:\" field, or -ensure the recipient is also listed there so that he receives replies -to your reply. Other header fields may be added using the \"Other -Field\" menu item. - -These fields can only be added after the recipient is known. Once the -header contains one or more recipients, run the -\\[mh-insert-auto-fields] command or choose the \"Identity -> Insert -Auto Fields\" menu item to insert these fields manually. However, you -can just send the message and the fields will be added automatically. -You are given a chance to see these fields and to confirm them before -the message is actually sent. You can do away with this confirmation -by turning off the option `mh-auto-fields-prompt-flag'. - -You should avoid using the same header field in `mh-auto-fields-list' -and `mh-identity-list' definitions that may apply to the same message -as the result is undefined." - :type `(repeat - (list :tag "" - (string :tag "Recipient") - (repeat :tag "Add at least one item below" - (choice - (cons :tag "Identity" - (const ":identity") - ,(append - '(radio) - (mapcar - (lambda (arg) `(const ,arg)) - (mapcar #'car mh-identity-list)))) - (cons :tag "Fcc Field" - (const "fcc") - (string :tag "Value")) - (cons :tag "Mail-Followup-To Field" - (const "Mail-Followup-To") - (string :tag "Value")) - (cons :tag "Other Field" - (string :tag "Field") - (string :tag "Value")))))) - :group 'mh-identity - :package-version '(MH-E . "7.3")) - -(defcustom mh-auto-fields-prompt-flag t - "Non-nil means to prompt before sending if fields inserted. -See `mh-auto-fields-list'." - :type 'boolean - :group 'mh-identity - :package-version '(MH-E . "8.0")) - -(defcustom mh-identity-default nil - "Default identity to use when `mh-letter-mode' is called. -See `mh-identity-list'." - :type (append - '(radio) - (cons '(const :tag "None" nil) - (mapcar (lambda (arg) `(const ,arg)) - (mapcar #'car mh-identity-list)))) - :group 'mh-identity - :package-version '(MH-E . "7.1")) - -(defcustom mh-identity-handlers - '(("From" . mh-identity-handler-top) - (":default" . mh-identity-handler-bottom) - (":attribution-verb" . mh-identity-handler-attribution-verb) - (":signature" . mh-identity-handler-signature) - (":pgg-default-user-id" . mh-identity-handler-gpg-identity)) - "Handler functions for fields in `mh-identity-list'. - -This option is used to change the way that fields, signatures, -and attributions in `mh-identity-list' are added. To customize -`mh-identity-handlers', replace the name of an existing handler -function associated with the field you want to change with the -name of a function you have written. You can also click on an -\"INS\" button and insert a field of your choice and the name of -the function you have written to handle it. - -The \"Field\" field can be any field that you've used in your -`mh-identity-list'. The special fields \":attribution-verb\", -\":signature\", or \":pgg-default-user-id\" are used for the -`mh-identity-list' choices \"Attribution Verb\", \"Signature\", and -\"GPG Key ID\" respectively. - -The handler associated with the \":default\" field is used when no -other field matches. - -The handler functions are passed two or three arguments: the -FIELD itself (for example, \"From\"), or one of the special -fields (for example, \":signature\"), and the ACTION `remove' or -`add'. If the action is `add', an additional argument -containing the VALUE for the field is given." - :type '(repeat (cons (string :tag "Field") function)) - :group 'mh-identity - :package-version '(MH-E . "8.0")) - -;;; Incorporating Your Mail (:group 'mh-inc) - -(defcustom mh-inc-prog "inc" - "Program to incorporate new mail into a folder. - -This program generates a one-line summary for each of the new -messages. Unless it is an absolute pathname, the file is assumed -to be in the `mh-progs' directory. You may also link a file to -\"inc\" that uses a different format. You'll then need to modify -several scan line format variables appropriately." - :type 'string - :group 'mh-inc - :package-version '(MH-E . "6.0")) - -(eval-and-compile - (unless (fboundp 'mh-inc-spool-make-no-autoload) - (defun mh-inc-spool-make-no-autoload () - "Temporary definition. -Real definition will take effect when mh-inc is loaded." - nil))) - -(defcustom mh-inc-spool-list nil - "Alternate spool files. - -You can use the `mh-inc-spool-list' variable to direct MH-E to -retrieve mail from arbitrary spool files other than your system -mailbox, file it in folders other than your \"+inbox\", and assign -key bindings to incorporate this mail. - -Suppose you are subscribed to the \"mh-e-devel\" mailing list and -you use \"procmail\" to filter this mail into \"~/mail/mh-e\" with -the following recipe in \".procmailrc\": - - MAILDIR=$HOME/mail - :0: - * ^From mh-e-devel-admin@stop.mail-abuse.org - mh-e - -In order to incorporate \"~/mail/mh-e\" into \"+mh-e\" with an -\"I m\" (mh-inc-spool-mh-e) command, customize this option, and click -on the \"INS\" button. Enter a \"Spool File\" of \"~/mail/mh-e\", a -\"Folder\" of \"mh-e\", and a \"Key Binding\" of \"m\". - -You can use \"xbuffy\" to automate the incorporation of this mail -using \"emacsclient\" as follows: - - box ~/mail/mh-e - title mh-e - origMode - polltime 10 - headertime 0 - command emacsclient --eval \\='(mh-inc-spool-mh-e)\\='" - :type '(repeat (list (file :tag "Spool File") - (string :tag "Folder") - (character :tag "Key Binding"))) - :set (lambda (symbol value) - (set-default symbol value) - (mh-inc-spool-make-no-autoload)) - :group 'mh-inc - :package-version '(MH-E . "7.3")) - -;;; Dealing with Junk Mail (:group 'mh-junk) - -(defvar mh-junk-choice nil - "Chosen spam fighting program.") - -;; Available spam filter interfaces -(defvar mh-junk-function-alist - '((spamassassin mh-spamassassin-blocklist mh-spamassassin-allowlist) - (bogofilter mh-bogofilter-blocklist mh-bogofilter-allowlist) - (spamprobe mh-spamprobe-blocklist mh-spamprobe-allowlist)) - "Available choices of spam programs to use. - -This is an alist. For each element there are functions that -blocklist a message as spam and allowlist 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) ;XXX shouldn't this be set-default? - (setq mh-junk-choice - (or value - (cl-loop for element in mh-junk-function-alist - until (executable-find (symbol-name (car element))) - finally return (car element))))) - -(defcustom mh-junk-background nil - "If on, spam programs are run in background. - -By default, the programs are run in the foreground, but this can -be slow when junking large numbers of messages. If you have -enough memory or don't junk that many messages at the same time, -you might try turning on this option. - -Note that this option is used as the \"destination\" argument in -the call to `call-process'. Therefore, turning on this option means -setting its value to \"0\". You can also set its value to t to -direct the programs' output to the \"*MH-E Log*\" buffer; this -may be useful for debugging." - :type '(choice (const :tag "Off" nil) - (const :tag "On" 0)) - :group 'mh-junk - :package-version '(MH-E . "8.0")) - -(defcustom mh-junk-disposition nil - "Disposition of junk mail." - :type '(choice (const :tag "Delete Spam" nil) - (string :tag "Spam Folder")) - :group 'mh-junk - :package-version '(MH-E . "8.0")) - -(defcustom mh-junk-program nil - "Spam program that MH-E should use. - -The default setting of this option is \"Auto-detect\" which means -that MH-E will automatically choose one of SpamAssassin, -bogofilter, or SpamProbe in that order. If, for example, you have -both SpamAssassin and bogofilter installed and you want to use -bogofilter, then you can set this option to \"Bogofilter\"." - :type '(choice (const :tag "Auto-detect" nil) - (const :tag "SpamAssassin" spamassassin) - (const :tag "Bogofilter" bogofilter) - (const :tag "SpamProbe" spamprobe)) - :set #'mh-junk-choose - :group 'mh-junk - :package-version '(MH-E . "7.3")) - -;;; Editing a Draft (:group 'mh-letter) - -(defcustom mh-compose-insertion (if (locate-library "mml") 'mml 'mh) - "Type of tags used when composing MIME messages. - -In addition to MH-style directives, MH-E also supports MML (MIME -Meta Language) tags. (see Info node `(emacs-mime)Composing'). -This option can be used to choose between them. By default, this -option is set to \"MML\" if it is supported since it provides a -lot more functionality. This option can also be set to \"MH\" if -MH-style directives are preferred." - :type '(choice (const :tag "MML" mml) - (const :tag "MH" mh)) - :group 'mh-letter - :package-version '(MH-E . "7.0")) - -(defcustom mh-compose-skipped-header-fields - '("From" "Organization" "References" "In-Reply-To" - "X-Face" "Face" "X-Image-URL" "X-Mailer") - "List of header fields to skip over when navigating in draft." - :type '(repeat (string :tag "Field")) - :group 'mh-letter - :package-version '(MH-E . "7.4")) - -(defcustom mh-compose-space-does-completion-flag nil - "Non-nil means \\\\[mh-letter-complete-or-space] does completion in message header." - :type 'boolean - :group 'mh-letter - :package-version '(MH-E . "7.4")) - -(defcustom mh-delete-yanked-msg-window-flag nil - "Non-nil means delete any window displaying the message. - -This deletes the window containing the original message after -yanking it with \\\\[mh-yank-cur-msg] to make -more room on your screen for your reply." - :type 'boolean - :group 'mh-letter - :package-version '(MH-E . "7.0")) - -(defcustom mh-extract-from-attribution-verb "wrote:" - "Verb to use for attribution when a message is yanked by \\\\[mh-yank-cur-msg]. - -The attribution consists of the sender's name and email address -followed by the content of this option. This option can be set to -\"wrote:\", \"a écrit:\", and \"schrieb:\". You can also use the -\"Custom String\" menu item to enter your own verb." - :type '(choice (const "wrote:") - (const "a écrit:") - (const "schrieb:") - (string :tag "Custom String")) - :group 'mh-letter - :package-version '(MH-E . "7.0")) - -(defcustom mh-ins-buf-prefix "> " - "String to put before each line of a yanked or inserted message. - -The prefix \"> \" is the default setting of this option. I -suggest that you not modify this option since it is used by many -mailers and news readers: messages are far easier to read if -several included messages have all been indented by the same -string. - -This prefix is not inserted if you use one of the supercite -flavors of `mh-yank-behavior' or you have added a -`mail-citation-hook'." - :type 'string - :group 'mh-letter - :package-version '(MH-E . "6.0")) - -(defcustom mh-letter-complete-function 'ispell-complete-word - "Function to call when completing outside of address or folder fields. - -In the body of the message, -\\\\[completion-at-point] runs this function, -which is set to \"ispell-complete-word\" by default." - :type '(choice function (const nil)) - :group 'mh-letter - :package-version '(MH-E . "7.1")) - -(defcustom mh-letter-fill-column 72 - "Fill column to use in MH Letter mode. - -By default, this option is 72 to allow others to quote your -message without line wrapping." - :type 'integer - :group 'mh-letter - :package-version '(MH-E . "6.0")) - -(defcustom mh-mml-method-default (if mh-pgp-support-flag "pgpmime" "none") - "Default method to use in security tags. - -This option is used to select between a variety of mail security -mechanisms. The default is \"PGP (MIME)\" if it is supported; -otherwise, the default is \"None\". Other mechanisms include -vanilla \"PGP\" and \"S/MIME\"." - :type '(choice (const :tag "PGP (MIME)" "pgpmime") - (const :tag "PGP" "pgp") - (const :tag "S/MIME" "smime") - (const :tag "None" "none")) - :group 'mh-letter - :package-version '(MH-E . "8.0")) - -(defcustom mh-signature-file-name "~/.signature" - "Source of user's signature. - -By default, the text of your signature is taken from the file -\"~/.signature\". You can read from other sources by changing this -option. This file may contain a vCard in which case an attachment is -added with the vCard. - -This option may also be a symbol, in which case that function is -called. You may not want a signature separator to be added for you; -instead you may want to insert one yourself. Options that you may find -useful to do this include `mh-signature-separator' (when inserting a -signature separator) and `mh-signature-separator-regexp' (for finding -said separator). The function `mh-signature-separator-p', which -reports t if the buffer contains a separator, may be useful as well. - -The signature is inserted into your message with the command -\\\\[mh-insert-signature] or with the option -`mh-identity-list'." - :type 'file - :group 'mh-letter - :package-version '(MH-E . "6.0")) - -(defcustom mh-signature-separator-flag t - "Non-nil means a signature separator should be inserted. - -It is not recommended that you change this option since various -mail user agents, including MH-E, use the separator to present -the signature differently, and to suppress the signature when -replying or yanking a letter into a draft." - :type 'boolean - :group 'mh-letter - :package-version '(MH-E . "8.0")) - -(defcustom mh-x-face-file "~/.face" - "File containing face header field to insert in outgoing mail. - -If the file starts with either of the strings \"X-Face:\", \"Face:\" -or \"X-Image-URL:\" then the contents are added to the message header -verbatim. Otherwise it is assumed that the file contains the value of -the \"X-Face:\" header field. - -The \"X-Face:\" header field, which is a low-resolution, black and -white image, can be generated using the \"compface\" command (see URL -`ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.Z'). The -\"Online X-Face Converter\" is a useful resource for quick conversion -of images into \"X-Face:\" header fields (see URL -`https://www.dairiki.org/xface/'). - -Use the \"make-face\" script to convert a JPEG image to the higher -resolution, color, \"Face:\" header field (see URL -`https://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. - -To prevent the setting of any of these header fields, either set -`mh-x-face-file' to nil, or simply ensure that the file defined by -this option doesn't exist." - :type 'file - :group 'mh-letter - :package-version '(MH-E . "7.0")) - -(defcustom mh-yank-behavior 'attribution - "Controls which part of a message is yanked by \\\\[mh-yank-cur-msg]. - -To include the entire message, including the entire header, use -\"Body and Header\". Use \"Body\" to yank just the body without -the header. To yank only the portion of the message following the -point, set this option to \"Below Point\". - -Choose \"Invoke supercite\" to pass the entire message and header -through supercite. - -If the \"Body With Attribution\" setting is used, then the -message minus the header is yanked and a simple attribution line -is added at the top using the value of the option -`mh-extract-from-attribution-verb'. This is the default. - -If the \"Invoke supercite\" or \"Body With Attribution\" settings -are used, the \"-noformat\" argument is passed to the \"repl\" -program to override a \"-filter\" or \"-format\" argument. These -settings also have \"Automatically\" variants that perform the -action automatically when you reply so that you don't need to use -\\[mh-yank-cur-msg] at all. Note that this automatic action is -only performed if the show buffer matches the message being -replied to. People who use the automatic variants tend to turn on -the option `mh-delete-yanked-msg-window-flag' as well so that the -show window is never displayed. - -If the show buffer has a region, the option `mh-yank-behavior' is -ignored unless its value is one of Attribution variants in which -case the attribution is added to the yanked region. - -If this option is set to one of the supercite flavors, the hook -`mail-citation-hook' is ignored and `mh-ins-buf-prefix' is not -inserted." - :type '(choice (const :tag "Body and Header" t) - (const :tag "Body" body) - (const :tag "Below Point" nil) - (const :tag "Invoke supercite" supercite) - (const :tag "Invoke supercite, Automatically" autosupercite) - (const :tag "Body With Attribution" attribution) - (const :tag "Body With Attribution, Automatically" - autoattrib)) - :group 'mh-letter - :package-version '(MH-E . "8.0")) - -;;; Ranges (:group 'mh-ranges) - -(defcustom mh-interpret-number-as-range-flag t - "Non-nil means interpret a number as a range. - -Since one of the most frequent ranges used is \"last:N\", MH-E -will interpret input such as \"200\" as \"last:200\" if this -option is on (which is the default). If you need to scan just the -message 200, then use the range \"200:200\"." - :type 'boolean - :group 'mh-ranges - :package-version '(MH-E . "7.4")) - -;;; Scan Line Formats (:group 'mh-scan-line-formats) - -(eval-and-compile - (unless (fboundp 'mh-adaptive-cmd-note-flag-check) - (defun mh-adaptive-cmd-note-flag-check (symbol value) - "Temporary definition. -Real definition, below, uses variables that aren't defined yet." - (set-default symbol value)))) - -(defcustom mh-adaptive-cmd-note-flag t - "Non-nil means that the message number width is determined dynamically. - -If you've created your own format to handle long message numbers, -you'll be pleased to know you no longer need it since MH-E adapts its -internal format based upon the largest message number if this option -is on (the default). This option may only be turned on when -`mh-scan-format-file' is set to \"Use MH-E scan Format\". - -If you prefer fixed-width message numbers, turn off this option and -call `mh-set-cmd-note' with the width specified by your format file -\(see `mh-scan-format-file'). For example, the default width is 4, so -you would use \"(mh-set-cmd-note 4)\"." - :type 'boolean - :group 'mh-scan-line-formats - :set #'mh-adaptive-cmd-note-flag-check - :package-version '(MH-E . "7.0")) - -(defun mh-scan-format-file-check (symbol value) - "Check if desired setting is valid. -Throw an error if user tries to set `mh-scan-format-file' to -anything but t when `mh-adaptive-cmd-note-flag' is on. Otherwise, -set SYMBOL to VALUE." - (if (and (not (eq value t)) - mh-adaptive-cmd-note-flag) - (error "%s %s" "You must turn off `mh-adaptive-cmd-note-flag'" - "unless you use \"Use MH-E scan Format\"") - (set-default symbol value))) - -(defcustom mh-scan-format-file t - "Specifies the format file to pass to the scan program. - -The default setting for this option is \"Use MH-E scan Format\". This -means that the format string will be taken from the either -`mh-scan-format-mh' or `mh-scan-format-nmh' depending on whether MH or -nmh (or GNU mailutils MH) is in use. This setting also enables you to -turn on the `mh-adaptive-cmd-note-flag' option. - -You can also set this option to \"Use Default scan Format\" to get the -same output as you would get if you ran \"scan\" from the shell. If -you have a format file that you want MH-E to use but not MH, you can -set this option to \"Specify a scan Format File\" and enter the name -of your format file. - -If you change the format of the scan lines you'll need to tell MH-E -how to parse the new format. As you will see, quite a lot of variables -are involved to do that. Use \"\\[apropos] RET mh-scan.*regexp\" to -obtain a list of these variables. You will also have to call -`mh-set-cmd-note' if your notations are not in column 4 (columns in -Emacs start with 0)." - :type '(choice (const :tag "Use MH-E scan Format" t) - (const :tag "Use Default scan Format" nil) - (file :tag "Specify a scan Format File")) - :group 'mh-scan-line-formats - :set #'mh-scan-format-file-check - :package-version '(MH-E . "6.0")) - -(defun mh-adaptive-cmd-note-flag-check (symbol value) - "Check if desired setting is valid. -Throw an error if user tries to turn on -`mh-adaptive-cmd-note-flag' when `mh-scan-format-file' isn't t. -Otherwise, set SYMBOL to VALUE." - (if (and value - (not (eq mh-scan-format-file t))) - (error "%s %s" "Can't turn on unless `mh-scan-format-file'" - "is set to \"Use MH-E scan Format\"") - (set-default symbol value))) - -(defcustom mh-scan-prog "scan" - "Program used to scan messages. - -The name of the program that generates a listing of one line per -message is held in this option. Unless this variable contains an -absolute pathname, it is assumed to be in the `mh-progs' -directory. You may link another program to `scan' (see -\"mh-profile(5)\") to produce a different type of listing." - :type 'string - :group 'mh-scan-line-formats - :package-version '(MH-E . "6.0")) -(make-variable-buffer-local 'mh-scan-prog) - -;;; Searching (:group 'mh-search) - -(defcustom mh-search-program nil - "Search program that MH-E shall use. - -The default setting of this option is \"Auto-detect\" which means -that MH-E will automatically choose one of swish++, swish-e, -mairix, namazu, pick and grep in that order. If, for example, you -have both swish++ and mairix installed and you want to use -mairix, then you can set this option to \"mairix\". - -More information about setting up an indexing program to use with -MH-E can be found in the documentation of `mh-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 "pick" pick) - (const :tag "grep" grep)) - :group 'mh-search - :package-version '(MH-E . "8.0")) - -;;; Sending Mail (:group 'mh-sending-mail) - -(defcustom mh-compose-forward-as-mime-flag t - "Non-nil means that messages are forwarded as attachments. - -By default, this option is on which means that the forwarded -messages are included as attachments. If you would prefer to -forward your messages verbatim (as text, inline), then turn off -this option. Forwarding messages verbatim works well for short, -textual messages, but your recipient won't be able to view any -non-textual attachments that were in the forwarded message. Be -aware that if you have \"forw: -mime\" in your MH profile, then -forwarded messages will always be included as attachments -regardless of the settings of this option." - :type 'boolean - :group 'mh-sending-mail - :package-version '(MH-E . "8.0")) - -(defcustom mh-compose-letter-function nil - "Invoked when starting a new draft. - -However, it is the last function called before you edit your -message. The consequence of this is that you can write a function -to write and send the message for you. This function is passed -three arguments: the contents of the TO, SUBJECT, and CC header -fields." - :type '(choice (const nil) function) - :group 'mh-sending-mail - :package-version '(MH-E . "6.0")) - -(defcustom mh-compose-prompt-flag nil - "Non-nil means prompt for header fields when composing a new draft." - :type 'boolean - :group 'mh-sending-mail - :package-version '(MH-E . "7.4")) - -(defcustom mh-forward-subject-format "%s: %s" - "Format string for forwarded message subject. - -This option is a string which includes two escapes (\"%s\"). The -first \"%s\" is replaced with the sender of the original message, -and the second one is replaced with the original \"Subject:\"." - :type 'string - :group 'mh-sending-mail - :package-version '(MH-E . "6.0")) - -(defcustom mh-insert-x-mailer-flag t - "Non-nil means append an \"X-Mailer:\" header field to the header. - -This header field includes the version of MH-E and Emacs that you -are using. If you don't want to participate in our marketing, you -can turn this option off." - :type 'boolean - :group 'mh-sending-mail - :package-version '(MH-E . "7.0")) - -(defcustom mh-redist-full-contents-flag nil - "Non-nil means the \"dist\" command needs entire letter for redistribution. - -This option must be turned on if \"dist\" requires the whole -letter for redistribution, which is the case if \"send\" is -compiled with the BERK option (which many people abhor). If you -find that MH will not allow you to redistribute a message that -has been redistributed before, turn off this option." - :type 'boolean - :group 'mh-sending-mail - :package-version '(MH-E . "8.0")) - -(defcustom mh-reply-default-reply-to nil - "Sets the person or persons to whom a reply will be sent. - -This option is set to \"Prompt\" by default so that you are -prompted for the recipient of a reply. If you find that most of -the time that you specify \"cc\" when you reply to a message, set -this option to \"cc\". Other choices include \"from\", \"to\", or -\"all\". You can always edit the recipients in the draft." - :type '(choice (const :tag "Prompt" nil) - (const "from") - (const "to") - (const "cc") - (const "all")) - :group 'mh-sending-mail - :package-version '(MH-E . "6.0")) - -(defcustom mh-reply-show-message-flag t - "Non-nil means the MH-Show buffer is displayed when replying. - -If you include the message automatically, you can hide the -MH-Show buffer by turning off this option. - -See also `mh-reply'." - :type 'boolean - :group 'mh-sending-mail - :package-version '(MH-E . "7.0")) - -;;; Sequences (:group 'mh-sequences) - -;; If `mh-unpropagated-sequences' becomes a defcustom, add the following to -;; the docstring: "Additional sequences that should not to be preserved can be -;; specified by setting `mh-unpropagated-sequences' appropriately." XXX - -(defcustom mh-refile-preserves-sequences-flag t - "Non-nil means that sequences are preserved when messages are refiled. - -If a message is in any sequence (except \"Previous-Sequence:\" -and \"cur\") when it is refiled, then it will still be in those -sequences in the destination folder. If this behavior is not -desired, then turn off this option." - :type 'boolean - :group 'mh-sequences - :package-version '(MH-E . "7.4")) - -(defcustom mh-tick-seq 'tick - "The name of the MH sequence for ticked messages. - -You can customize this option if you already use the \"tick\" -sequence for your own use. You can also disable all of the -ticking functions by choosing the \"Disable Ticking\" item but -there isn't much advantage to that." - :type '(choice (const :tag "Disable Ticking" nil) - symbol) - :group 'mh-sequences - :package-version '(MH-E . "7.3")) - -(defcustom mh-update-sequences-after-mh-show-flag t - "Non-nil means flush MH sequences to disk after message is shown\\. - -Three sequences are maintained internally by MH-E and pushed out -to MH when a message is shown. They include the sequence -specified by your \"Unseen-Sequence:\" profile entry, \"cur\", -and the sequence listed by the option `mh-tick-seq' which is -\"tick\" by default. If you do not like this behavior, turn off -this option. You can then update the state manually with the -\\[mh-execute-commands], \\[mh-quit], or \\[mh-update-sequences] -commands." - :type 'boolean - :group 'mh-sequences - :package-version '(MH-E . "7.0")) - -(defcustom mh-allowlist-preserves-sequences-flag t - "Non-nil means that sequences are preserved when messages are allowlisted. - -If a message is in any sequence (except \"Previous-Sequence:\" -and \"cur\") when it is allowlisted, then it will still be in -those sequences in the destination folder. If this behavior is -not desired, then turn off this option." - :type 'boolean - :group 'mh-sequences - :package-version '(MH-E . "8.4")) - -;;; Reading Your Mail (:group 'mh-show) - -(defcustom mh-bury-show-buffer-flag t - "Non-nil means show buffer is buried. - -One advantage of not burying the show buffer is that one can -delete the show buffer more easily in an electric buffer list -because of its proximity to its associated MH-Folder buffer. Try -running \\[electric-buffer-list] to see what I mean." - :type 'boolean - :group 'mh-show - :package-version '(MH-E . "7.0")) - -(defcustom mh-clean-message-header-flag t - "Non-nil means remove extraneous header fields. - -See also `mh-invisible-header-fields-default' and -`mh-invisible-header-fields'." - :type 'boolean - :group 'mh-show - :package-version '(MH-E . "7.0")) - -(defcustom mh-decode-mime-flag (not (not (locate-library "mm-decode"))) - "Non-nil means attachments are handled\\. - -MH-E can handle attachments as well if the Gnus `mm-decode' -library is present. If so, this option will be on. Otherwise, -you'll see the MIME body parts rather than text or attachments. -There isn't much point in turning off this option; however, you -can inspect it if it appears that the body parts are not being -interpreted correctly or toggle it with the command -\\[mh-toggle-mh-decode-mime-flag] to view the raw message. - -This option also controls the display of quoted-printable -messages and other graphical widgets. See the options -`mh-graphical-smileys-flag' and `mh-graphical-emphasis-flag'." - :type 'boolean - :group 'mh-show - :package-version '(MH-E . "7.0")) - -(defcustom mh-display-buttons-for-alternatives-flag nil - "Non-nil means display buttons for all alternative attachments. - -Sometimes, a mail program will produce multiple alternatives of -the attachment in increasing degree of faithfulness to the -original content. By default, only the preferred alternative is -displayed. If this option is on, then the preferred part is shown -inline and buttons are shown for each of the other alternatives." - :type 'boolean - :group 'mh-show - :package-version '(MH-E . "7.4")) - -(defcustom mh-display-buttons-for-inline-parts-flag nil - "Non-nil means display buttons for all inline attachments\\. - -The sender can request that attachments should be viewed inline so -that they do not really appear like an attachment at all to the -reader. Most of the time, this is desirable, so by default MH-E -suppresses the buttons for inline attachments. On the other hand, you -may receive code or HTML which the sender has added to his message as -inline attachments so that you can read them in MH-E. In this case, it -is useful to see the buttons so that you know you don't have to cut -and paste the code into a file; you can simply save the attachment. - -If you want to make the buttons visible for inline attachments, you -can use the command \\[mh-toggle-mime-buttons] to toggle the -visibility of these buttons. You can turn on these buttons permanently -by turning on this option. - -MH-E cannot display all attachments inline however. It can display -text (including HTML) and images." - :type 'boolean - :group 'mh-show - :package-version '(MH-E . "7.0")) - -(defcustom mh-do-not-confirm-flag nil - "Non-nil means non-reversible commands do not prompt for confirmation. - -Commands such as `mh-pack-folder' prompt to confirm whether to -process outstanding moves and deletes or not before continuing. -Turning on this option means that these actions will be -performed--which is usually desired but cannot be -retracted--without question." - :type 'boolean - :group 'mh-show - :package-version '(MH-E . "7.0")) - -(defcustom mh-fetch-x-image-url nil - "Control fetching of \"X-Image-URL:\" header field image. - -This option controls the fetching of the \"X-Image-URL:\" header -field image with the following values: - -Ask Before Fetching - You are prompted before the image is fetched. MH-E will - remember your reply and will either use the already fetched - image the next time the same URL is encountered or silently - skip it if you didn't fetch it the first time. This is a - good setting. - -Never Fetch - Images are never fetched and only displayed if they are - already present in the cache. This is the default. - -There isn't a value of \"Always Fetch\" for privacy and DOS (denial of -service) reasons. For example, fetching a URL can tip off a spammer -that you've read his email (which is why you shouldn't blindly answer -yes if you've set this option to \"Ask Before Fetching\"). Someone may -also flood your network and fill your disk drive by sending a torrent -of messages, each specifying a unique URL to a very large file. - -The cache of images is found in the directory \".mhe-x-image-cache\" -within your MH directory. You can add your own face to the \"From:\" -field too. See Info node `(mh-e)Picture'. - -This setting only has effect if the option `mh-show-use-xface-flag' is -turned on." - - :type '(choice (const :tag "Ask Before Fetching" ask) - (const :tag "Never Fetch" nil)) - :group 'mh-show - :package-version '(MH-E . "7.3")) - -(defcustom mh-graphical-smileys-flag t - "Non-nil means graphical smileys are displayed. - -It is a long standing custom to inject body language using a -cornucopia of punctuation, also known as the \"smileys\". MH-E -can render these as graphical widgets if this option is turned -on, which it is by default. Smileys include patterns such as :-) -and ;-). - -This option is disabled if the option `mh-decode-mime-flag' is -turned off." - :type 'boolean - :group 'mh-show - :package-version '(MH-E . "7.0")) - -(defcustom mh-graphical-emphasis-flag t - "Non-nil means graphical emphasis is displayed. - -A few typesetting features are indicated in ASCII text with -certain characters. If your terminal supports it, MH-E can render -these typesetting directives naturally if this option is turned -on, which it is by default. For example, _underline_ will be -underlined, *bold* will appear in bold, /italics/ will appear in -italics, and so on. See the option `gnus-emphasis-alist' for the -whole list. - -This option is disabled if the option `mh-decode-mime-flag' is -turned off." - :type 'boolean - :group 'mh-show - :package-version '(MH-E . "7.0")) - -(defcustom mh-highlight-citation-style 'gnus - "Style for highlighting citations. - -If the sender of the message has cited other messages in his -message, then MH-E will highlight these citations to emphasize -the sender's actual response. This option can be customized to -change the highlighting style. The \"Multicolor\" method uses a -different color for each indentation while the \"Monochrome\" -method highlights all citations in red. To disable highlighting -of citations entirely, choose \"None\"." - :type '(choice (const :tag "Multicolor" gnus) - (const :tag "Monochrome" font-lock) - (const :tag "None" nil)) - :group 'mh-show - :package-version '(MH-E . "8.0")) - -;; These entries have been intentionally excluded by the developers. -;; "Comments:" ; RFC 822 (or later) - show this one -;; "Fax:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ -;; "Mail-System-Version:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ -;; "Mailer:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ -;; "Organization:" ; -;; "Phone:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ -;; "Reply-By:" ; RFC 2156 -;; "Reply-To:" ; RFC 822 (or later) -;; "Sender:" ; -;; "User-Agent:" ; Similar to X-Mailer, so display it. -;; "X-Mailer:" ; -;; "X-Operator:" ; Similar to X-Mailer, so display it - -;; Keep fields alphabetized with case folding. Use M-:(setq -;; sort-fold-case t) from the minibuffer to accomplish this. -;; Mention source, if known. -(defvar mh-invisible-header-fields-internal - '( - "Abuse-Reports-To:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Accept-Language:" - "AcceptLanguage:" - "Accreditor:" ; Habeas - "Also-Control:" ; H. Spencer: News Article Format and Transmission, June 1994 - "Alternate-recipient:" ; RFC 2156 - "Approved-By:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Approved:" ; RFC 1036 - "Article-Names:" ; H. Spencer: News Article Format and Transmission, June 1994 - "Article-Updates:" ; H. Spencer: News Article Format and Transmission, June 1994 - "Authentication-Results:" - "Auto-forwarded:" ; RFC 2156 - "Autoforwarded:" ; RFC 2156 - "Bestservhost:" - "Bounces-To:" - "Bounces_to:" - "Bytes:" - "Cancel-Key:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Cancel-Lock:" ; NNTP posts - "Comment:" ; Shows up with DomainKeys - "Content-" ; RFC 2045, 1123, 1766, 1864, 2045, 2110, 2156, 2183, 2912 - "Control:" ; RFC 1036 - "Conversion-With-Loss:" ; RFC 2156 - "Conversion:" ; RFC 2156 - "Delivered-To:" ; Egroups/yahoogroups mailing list manager - "Delivery-Date:" ; RFC 2156 - "Delivery:" - "Discarded-X400-" ; RFC 2156 - "Disclose-Recipients:" ; RFC 2156 - "Disposition-Notification-Options:" ; RFC 2298 - "Disposition-Notification-To:" ; RFC 2298 - "Distribution:" ; RFC 1036 - "DKIM-" ; https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail - "DL-Expansion-History:" ; RFC 2156 - "DomainKey-" ; https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail - "DomainKey-Signature:" - "Encoding:" ; RFC 1505 - "Envelope-to:" - "Errors-To:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Expires:" ; RFC 1036 - "Expiry-Date:" ; RFC 2156 - "Face:" ; Gnus Face header - "Followup-To:" ; RFC 1036 - "For-Approval:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "For-Comment:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "For-Handling:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Forwarded:" ; MH - "From " ; sendmail - "Generate-Delivery-Report:" ; RFC 2156 - "Importance:" ; RFC 2156, 2421 - "In-Reply-To:" ; RFC 822 (or later) - "Incomplete-Copy:" ; RFC 2156 - "Keywords:" ; RFC 822 (or later) - "Language:" ; RFC 2156 - "Lines:" ; RFC 1036 - "List-" ; RFC 2369, 2919 - "Mail-Copies-To:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Mail-Followup-To:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Mail-from:" ; MH - "Mail-Reply-To:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Mailing-List:" ; Egroups/yahoogroups mailing list manager - "Message-Content:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Message-ID:" ; RFC 822 (or later) - "Message-Type:" ; RFC 2156 - "Mime-Version" ; RFC 2045 - "Msgid:" - "NNTP-" ; News - "Obsoletes:" ; RFC 2156 - "Old-Return-Path:" - "OpenPGP:" - "Original-Encoded-Information-Types:" ; RFC 2156 - "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-Recipient:" ; RFC 2298 - "Original-To:" ; mail to news - "Original-X-" ; mail to news - "Origination-Client:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Originator:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "P1-Content-Type:" ; X400 - "P1-Message-Id:" ; X400 - "P1-Recipient:" ; X400 - "Path:" ; RFC 1036 - "Pics-Label:" ; W3C - "Posted-To:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Precedence:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Prev-Resent" ; MH - "Prevent-NonDelivery-Report:" ; RFC 2156 - "Priority:" ; RFC 2156 - "Read-Receipt-To:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Received-SPF:" ; Gmail - "Received:" ; RFC 822 (or later) - "References:" ; RFC 822 (or later) - "Registered-Mail-Reply-Requested-By:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Remailed-" ; MH - "Replaces:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Replied:" ; MH - "Resent-" ; RFC 822 (or later) - "Return-Path:" ; RFC 822 (or later) - "Return-Receipt-Requested:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Return-Receipt-To:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Seal-Send-Time:" - "See-Also:" ; H. Spencer: News Article Format and Transmission, June 1994 - "Sensitivity:" ; RFC 2156, 2421 - "Speech-Act:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Status:" ; sendmail - "Supersedes:" ; H. Spencer: News Article Format and Transmission, June 1994 - "Telefax:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Thread-" - "Thread-Index:" - "Thread-Topic:" - "Translated-By:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Translation-Of:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "Ua-Content-Id:" ; X400 - "Via:" ; MH - "X-Abuse-and-DMCA-" - "X-Abuse-Info:" - "X-Accept-Language:" ; Netscape/Mozilla - "X-Ack:" - "X-ACL-Warn:" ; https://www.exim.org - "X-Admin:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-Administrivia-To:" - "X-AMAZON" ; Amazon.com - "X-AnalysisOut:" ; Exchange - "X-AntiAbuse:" ; cPanel - "X-Antivirus-Scanner:" - "X-AOL-IP:" ; AOL WebMail - "X-Apparently-From:" ; MS Outlook - "X-Apparently-To:" ; Egroups/yahoogroups mailing list manager - "X-Attribution:" - "X-AuditID:" - "X-Authenticated-Info:" ; Verizon.net? - "X-Authenticated-Sender:" ; AT&T Message Center (webmail) - "X-Authentication-Info:" ; verizon.net? - "X-Authentication-Warning:" ; sendmail - "X-Authority-Analysis:" - "X-Auto-Response-Suppress:" ; Exchange - "X-Barracuda-" ; Barracuda spam scores - "X-Bayes-Prob:" ; IEEE spam filter - "X-Beenthere:" ; Mailman mailing list manager - "X-BFI:" - "X-Bigfish:" - "X-Bogosity:" ; bogofilter - "X-BPS1:" ; http://www.boggletools.com [dead link?] - "X-BPS2:" ; http://www.boggletools.com [dead link?] - "X-Brightmail-Tracker:" ; Brightmail - "X-BrightmailFiltered:" ; Brightmail - "X-Bugzilla-" ; Bugzilla - "X-Cam-" ; Cambridge scanners - "X-Campaign-Id:" - "X-Campaign:" - "X-Campaignid:" - "X-CanIt-Geo:" ; IEEE spam filter - "X-Cloudmark-SP-" ; Cloudmark (www.cloudmark.com) - "X-Comment:" ; AT&T Mailennium - "X-Complaints-To:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-Completed:" - "X-Confirm-Reading-To:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-Content-Filtered-By:" - "X-ContentStamp:" ; NetZero - "X-Country-Chain:" ; http://www.declude.com/x-note.htm [dead link?] - "X-Cr-Hashedpuzzle:" - "X-Cr-Puzzleid:" - "X-Cron-Env:" - "X-DCC-" ; SpamAssassin - "X-Declude-" ; http://www.declude.com/x-note.htm [dead link?] - "X-Dedicated:" - "X-Delivered" - "X-Destination-ID:" - "X-detected-operating-system:" ; GNU.ORG? - "X-DH-Virus-" - "X-DMCA" - "X-DocGen-Version:" ; DocGen - "X-Domain:" - "X-Echelon-Distraction" - "X-EFL-Spamscore:" ; MIT alumni spam filtering - "X-eGroups-" ; Egroups/yahoogroups mailing list manager - "X-EID:" - "X-ELNK-Trace:" ; Earthlink mailer - "X-EM-" ; Some ecommerce software - "X-Email-Type-Id:" ; Paypal https://www.paypal.com - "X-Enigmail-Version:" - "X-Envelope-Date:" ; GNU mailutils - "X-Envelope-From:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-Envelope-Sender:" - "X-Envelope-To:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-EviteMessageId:" ; evite.com - "X-Evolution:" ; Evolution mail client - "X-ExtLoop" - "X-Face:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-Facebook" ; Facebook - "X-FB-SS:" - "X-fmx-" - "X-Folder:" ; Spam - "X-Forwarded-" ; Google+ - "X-From-Line" - "X-FuHaFi:" ; https://www.gmx.net/ - "X-Generated-By:" ; launchpad.net - "X-Gmail-" ; Gmail - "X-Gnus-Mail-Source:" ; gnus - "X-Google-" ; Google mail - "X-Google-Sender-Auth:" - "X-Greylist:" ; milter-greylist-1.2.1 - "X-Habeas-" ; https://www.returnpath.net - "X-Hashcash:" ; hashcash - "X-Headers-End:" ; SpamCop - "X-HPL-" - "X-HR-" - "X-HTTP-UserAgent:" - "X-Hz" ; Hertz - "X-Identity:" ; http://www.declude.com/x-note.htm [dead link?] - "X-IEEE-UCE-" ; IEEE spam filter - "X-Image-URL:" - "X-IMAP:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-Info:" ; NTMail - "X-IronPort-" ; IronPort AV - "X-ISI-4-30-3-MailScanner:" - "X-J2-" - "X-Jira-Fingerprint:" ; JIRA - "X-Junkmail-" ; RCN? - "X-Juno-" ; Juno - "X-Key:" - "X-Launchpad-" ; plaunchpad.net - "X-List-Host:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-List-Subscribe:" ; Unknown mailing list managers - "X-List-Unsubscribe:" ; Unknown mailing list managers - "X-Listprocessor-" ; ListProc(tm) by CREN - "X-Listserver:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-Loop:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-Lrde-Mailscanner:" - "X-Lumos-SenderID:" ; Roving ConstantContact - "X-mail_abuse_inquiries:" ; https://www.salesforce.com - "X-Mail-from:" ; fastmail.fm - "X-MAIL-INFO:" ; NetZero - "X-Mailer_" - "X-MailFlowPolicy:" ; Cisco Email Security (formerly IronPort; http://www.ironport.com) - "X-Mailing-List:" ; Unknown mailing list managers - "X-MailingID:" - "X-Mailman-Approved-At:" ; Mailman mailing list manager - "X-Mailman-Version:" ; Mailman mailing list manager - "X-MailScanner" ; ListProc(tm) by CREN - "X-Mailutils-Message-Id" ; GNU Mailutils - "X-Majordomo:" ; Majordomo mailing list manager - "X-Match:" - "X-MaxCode-Template:" ; Paypal https://www.paypal.com - "X-MB-Message-" ; AOL WebMail - "X-MDaemon-Deliver-To:" - "X-MDRemoteIP:" - "X-ME-Bayesian:" ; https://www.newmediadevelopment.net/page.cfm/parent/Client-Area/content/Managing-spam/ - "X-Message-Id" - "X-Message-Type:" - "X-MessageWall-Score:" ; Unknown mailing list manager, AUC TeX - "X-MHE-Checksum:" ; Checksum added during index search - "X-MIME-Autoconverted:" ; sendmail - "X-MIMEOLE:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/sendmail - "X-MIMETrack:" - "X-Mms-" ; T-Mobile pictures - "X-Mozilla-Status:" ; Netscape/Mozilla - "X-MS-" ; MS Outlook - "X-Msmail-" ; MS Outlook - "X-MSMail-Priority" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-MXL-Hash:" - "X-NAI-Spam-" ; Network Associates Inc. SpamKiller - "X-News:" ; News - "X-Newsreader:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-No-Archive:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-Notes-Item:" ; Lotus Notes Domino structured header - "X-Notification-" ; Google+ - "X-Notifications:" ; Google+ - "X-OperatingSystem:" - "X-Oracle-Calendar:" ; Oracle calendar invitations - "X-ORBL:" - "X-Orcl-Content-Type:" - "X-Organization:" - "X-Original-Arrival-Type:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-Original-Complaints-To:" - "X-Original-Date:" ; SourceForge mailing list manager - "X-Original-To:" - "X-Original-Trace:" - "X-OriginalArrivalTime:" ; Hotmail - "X-Originating-Email:" ; Hotmail - "X-Originating-IP:" ; Hotmail - "X-pair-" - "X-PGP:" - "X-PID:" - "X-PMG-" - "X-PMX-Version:" - "X-Policyd-Weight:" ; policyd-weight (Postfix) - "X-Postfilter:" - "X-Priority:" ; MS Outlook - "X-Proofpoint-" ; Proofpoint mail filter - "X-Provags-ID:" - "X-PSTN-" - "X-Qotd-" ; User added - "X-RCPT-TO:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-Received-Date:" - "X-Received:" - "X-Report-Abuse-To:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-Request-" - "X-Resolved-to:" ; fastmail.fm - "X-Return-Path-Hint:" ; Roving ConstantContact - "X-RIM-" ; Research In Motion (i.e. BlackBerry) - "X-RM" - "X-RocketYMMF:" ; Yahoo - "X-Roving-" ; Roving ConstantContact - "X-SA-Exim-" ; Exim SpamAssassin - "X-Sasl-enc:" ; Apple Mail - "X-SBClass:" ; Spam - "X-SBNote:" ; Spam - "X-SBPass:" ; Spam - "X-SBRS:" - "X-SBRule:" ; Spam - "X-Scanned-By:" - "X-Sender-ID:" ; Google+ - "X-Sender:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-Sendergroup:" ; Cisco Email Security (formerly IronPort; http://www.ironport.com) - "X-Server-Date:" - "X-Server-Uuid:" - "X-Service-Code:" - "X-SFDC-" ; https://www.salesforce.com - "X-Sieve:" ; Sieve filtering - "X-SMFBL:" - "X-SMHeaderMap:" - "X-SMTP-" - "X-Source" - "X-Spam-" ; SpamAssassin - "X-Spam:" ; Exchange - "X-SpamBouncer:" ; Spam - "X-SPF-" - "X-Status" - "X-Submission-Address:" - "X-Submissions-To:" - "X-Sun-Charset:" - "X-Telecom-Digest" - "X-TM-IMSS-Message-ID:" ; https://www.trendmicro.com - "X-Trace:" - "X-UID" - "X-UIDL:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-Unity" - "X-UNTD-" ; NetZero - "X-URI:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-URL:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-USANET-" ; usa.net - "X-Usenet-Provider" - "X-UserInfo1:" - "X-VGI-OESCD:" - "X-VirtualServer:" - "X-VirtualServerGroup:" - "X-Virus-" ; - "X-Vms-To:" - "X-VSMLoop:" ; NTMail - "X-WebTV-Signature:" - "X-Wss-Id:" ; Worldtalk gateways - "X-X-Sender:" ; https://people.dsv.su.se/~jpalme/ietf/mail-headers/ - "X-XPT-XSL-Name:" ; Paypal https://www.paypal.com - "X-xsi-" - "X-XWALL-" ; https://www.dataenter.co.at/doc/xwall_undocumented_config.htm - "X-Y-GMX-Trusted:" ; https://www.gmx.net/ - "X-Yahoo" - "X-Yahoo-Newman-" - "X-YMail-" - "X-ZixNet:" - "X400-" ; X400 - "Xref:" ; RFC 1036 - ) - "List of default header fields that are not to be shown. - -Do not alter this variable directly. Instead, add entries from -here that you would like to be displayed in -`mh-invisible-header-fields-default' and add entries to hide in -`mh-invisible-header-fields'.") - -(eval-and-compile - (unless (fboundp 'mh-invisible-headers) - (defun mh-invisible-headers () - "Temporary definition. -Real definition, below, uses variables that aren't defined yet." - nil))) - -(defvar mh-delay-invisible-header-generation-flag t - "Non-nil means to delay the generation of invisible header fields. -Because the function `mh-invisible-headers' uses both -`mh-invisible-header-fields' and `mh-invisible-header-fields', it -cannot be run until both variables have been initialized.") - -(defcustom mh-invisible-header-fields nil - "Additional header fields to hide. - -Header fields that you would like to hide that aren't listed in -`mh-invisible-header-fields-default' can be added to this option -with a couple of caveats. Regular expressions are not allowed. -Unique fields should have a \":\" suffix; otherwise, the element -can be used to render invisible an entire class of fields that -start with the same prefix. - -If you think a header field should be generally ignored, please -update SF #1916032 (see URL -`https://sourceforge.net/tracker/index.php?func=detail&aid=1916032&group_id=13357&atid=113357'). - -See also `mh-clean-message-header-flag'." - - :type '(repeat (string :tag "Header field")) - :set (lambda (symbol value) - (set-default symbol value) - (mh-invisible-headers)) - :group 'mh-show - :package-version '(MH-E . "7.1")) - -(defcustom mh-invisible-header-fields-default nil - "List of hidden header fields. - -The header fields listed in this option are hidden, although you -can check off any field that you would like to see. - -Header fields that you would like to hide that aren't listed can -be added to the option `mh-invisible-header-fields'. - -See also `mh-clean-message-header-flag'. - -If you think a header field should be added to this list, please -update SF #1916032 (see URL -`https://sourceforge.net/tracker/index.php?func=detail&aid=1916032&group_id=13357&atid=113357')." - :type `(set ,@(mapcar (lambda (x) `(const ,x)) - mh-invisible-header-fields-internal)) - :set (lambda (symbol value) - (set-default symbol value) - (mh-invisible-headers)) - :group 'mh-show - :package-version '(MH-E . "8.0")) - -(defvar mh-invisible-header-fields-compiled nil - "Regexp matching lines in a message header that are not to be shown. -Do not alter this variable directly. Instead, customize -`mh-invisible-header-fields-default' checking for fields normally -hidden that you wish to display, and add extra entries to hide in -`mh-invisible-header-fields'.") - -(defun mh-invisible-headers () - "Make or remake the variable `mh-invisible-header-fields-compiled'. -Done using `mh-invisible-header-fields-internal' as input, from -which entries from `mh-invisible-header-fields-default' are -removed and entries from `mh-invisible-header-fields' are added." - (let ((fields mh-invisible-header-fields-internal)) - (when mh-invisible-header-fields-default - ;; Remove entries from `mh-invisible-header-fields-default' - (setq fields - (cl-loop for x in fields - unless (member x mh-invisible-header-fields-default) - collect x))) - (when (and (boundp 'mh-invisible-header-fields) - mh-invisible-header-fields) - (dolist (x mh-invisible-header-fields) - (unless (member x fields) (setq fields (cons x fields))))) - (if fields - (setq mh-invisible-header-fields-compiled - (concat - "^" - (regexp-opt fields t))) - (setq mh-invisible-header-fields-compiled nil)))) - -;; Compile invisible header fields. -(mh-invisible-headers) - -(defcustom mh-lpr-command-format "lpr -J '%s'" - "Command used to print\\. - -This option contains the Unix command line which performs the -actual printing for the \\[mh-print-msg] command. The string can -contain one escape, \"%s\", which is replaced by the name of the -folder and the message number and is useful for print job names. -I use \"mpage -h\\='%s\\=' -b Letter -H1of -mlrtb -P\" which produces a -nice header and adds a bit of margin so the text fits within my -printer's margins. - -This option is not used by the commands \\[mh-ps-print-msg] or -\\[mh-ps-print-msg-file]." - :type 'string - :group 'mh-show - :package-version '(MH-E . "6.0")) - -(defcustom mh-max-inline-image-height nil - "Maximum inline image height if \"Content-Disposition:\" is not present. - -Some older mail programs do not insert this needed plumbing to -tell MH-E whether to display the attachments inline or not. If -this is the case, MH-E will display these images inline if they -are smaller than the window. However, you might want to allow -larger images to be displayed inline. To do this, you can change -the options `mh-max-inline-image-width' and -`mh-max-inline-image-height' from their default value of zero to -a large number. The size of your screen is a good choice for -these numbers." - :type '(choice (const nil) integer) - :group 'mh-show - :package-version '(MH-E . "7.0")) - -(defcustom mh-max-inline-image-width nil - "Maximum inline image width if \"Content-Disposition:\" is not present. - -Some older mail programs do not insert this needed plumbing to -tell MH-E whether to display the attachments inline or not. If -this is the case, MH-E will display these images inline if they -are smaller than the window. However, you might want to allow -larger images to be displayed inline. To do this, you can change -the options `mh-max-inline-image-width' and -`mh-max-inline-image-height' from their default value of zero to -a large number. The size of your screen is a good choice for -these numbers." - :type '(choice (const nil) integer) - :group 'mh-show - :package-version '(MH-E . "7.0")) - -(defcustom mh-mhl-format-file nil - "Specifies the format file to pass to the \"mhl\" program. - -Normally MH-E takes care of displaying messages itself (rather than -calling an MH program to do the work). If you'd rather have \"mhl\" -display the message (within MH-E), change this option from its default -value of \"Use Default mhl Format (Printing Only)\". - -You can set this option to \"Use Default mhl Format\" to get the same -output as you would get if you ran \"mhl\" from the shell. - -If you have a format file that you want MH-E to use, you can set this -option to \"Specify an mhl Format File\" and enter the name of your -format file. Your format file should specify a non-zero value for -\"overflowoffset\" to allow MH-E to parse the header. Note that -\"mhl\" is always used for printing and forwarding; in this case, the -value of this option is consulted if you have specified a format -file." - :type '(choice (const :tag "Use Default mhl Format (Printing Only)" nil) - (const :tag "Use Default mhl Format" t) - (file :tag "Specify an mhl Format File")) - :group 'mh-show - :package-version '(MH-E . "8.0")) - -(defcustom mh-mime-save-parts-default-directory t - "Default directory to use for \\\\[mh-mime-save-parts]. - -The default value for this option is \"Prompt Always\" so that -you are always prompted for the directory in which to save the -attachments. However, if you usually use the same directory -within a session, then you can set this option to \"Prompt the -First Time\" to avoid the prompt each time. you can make this -directory permanent by choosing \"Directory\" and entering the -directory's name." - :type '(choice (const :tag "Prompt the First Time" nil) - (const :tag "Prompt Always" t) - directory) - :group 'mh-show - :package-version '(MH-E . "7.0")) - -(defcustom mh-print-background-flag nil - "Non-nil means messages should be printed in the background\\. - -Normally messages are printed in the foreground. If this is slow on -your system, you may elect to turn off this option to print in the -background. - -WARNING: If you do this, do not delete the message until it is printed -or else the output may be truncated. - -This option is not used by the commands \\[mh-ps-print-msg] or -\\[mh-ps-print-msg-file]." - :type 'boolean - :group 'mh-show - :package-version '(MH-E . "7.0")) - -(defcustom mh-show-maximum-size 0 - "Maximum size of message (in bytes) to display automatically. - -This option provides an opportunity to skip over large messages -which may be slow to load. The default value of 0 means that all -message are shown regardless of size." - :type 'integer - :group 'mh-show - :package-version '(MH-E . "8.0")) - -(defcustom mh-show-use-xface-flag (>= emacs-major-version 21) - "Non-nil means display face images in MH-show buffers. - -MH-E can display the content of \"Face:\", \"X-Face:\", and -\"X-Image-URL:\" header fields. If any of these fields occur in the -header of your message, the sender's face will appear in the \"From:\" -header field. If more than one of these fields appear, then the first -field found in the order \"Face:\", \"X-Face:\", and \"X-Image-URL:\" -will be used. - -The option `mh-show-use-xface-flag' is used to turn this feature on -and off. This feature will be turned on by default if your system -supports it. - -The first header field used, if present, is the Gnus-specific -\"Face:\" field. The \"Face:\" field appeared in Emacs 21. -For more information, see URL -`https://quimby.gnus.org/circus/face/'. Next is the traditional -\"X-Face:\" header field. The display of this field requires the -\"uncompface\" program (see URL -`ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.z'). - -Finally, MH-E will display images referenced by the \"X-Image-URL:\" -header field if neither the \"Face:\" nor the \"X-Face:\" fields are -present. The display of the images requires \"wget\" (see URL -`https://www.gnu.org/software/wget/wget.html'), \"fetch\", or \"curl\" -to fetch the image and the \"convert\" program from the ImageMagick -suite (see URL `https://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. - -The option `mh-fetch-x-image-url' controls the fetching of the -\"X-Image-URL:\" header field image." - :type 'boolean - :group 'mh-show - :package-version '(MH-E . "7.0")) - -(defcustom mh-store-default-directory nil - "Default directory for \\\\[mh-store-msg]. - -If you would like to change the initial default directory, -customize this option, change the value from \"Current\" to -\"Directory\", and then enter the name of the directory for storing -the content of these messages." - :type '(choice (const :tag "Current" nil) - directory) - :group 'mh-show - :package-version '(MH-E . "6.0")) - -(defcustom mh-summary-height nil - "Number of lines in MH-Folder buffer (including the mode line). - -The default value of this option is \"Automatic\" which means -that the MH-Folder buffer will maintain the same proportional -size if the frame is resized. If you'd prefer a fixed height, -then choose the \"Fixed Size\" option and enter the number of -lines you'd like to see." - :type '(choice (const :tag "Automatic" nil) - (integer :tag "Fixed Size")) - :group 'mh-show - :package-version '(MH-E . "7.4")) - -;;; The Speedbar (:group 'mh-speedbar) - -(defcustom mh-speed-update-interval 60 - "Time between speedbar updates in seconds. -Set to 0 to disable automatic update." - :type 'integer - :group 'mh-speedbar - :package-version '(MH-E . "8.0")) - -;;; Threading (:group 'mh-thread) - -(defcustom mh-show-threads-flag nil - "Non-nil means new folders start in threaded mode. - -Threading large number of messages can be time consuming so this -option is turned off by default. If you turn this option on, then -threading will be done only if the number of messages being -threaded is less than `mh-large-folder'." - :type 'boolean - :group 'mh-thread - :package-version '(MH-E . "7.1")) - -;;; The Tool Bar (:group 'mh-tool-bar) - -;; mh-tool-bar-folder-buttons and mh-tool-bar-letter-buttons defined -;; dynamically in mh-tool-bar.el. - -(defcustom mh-tool-bar-search-function 'mh-search - "Function called by the tool bar search button. - -By default, this is set to `mh-search'. You can also choose -\"Other Function\" from the \"Value Menu\" and enter a function -of your own choosing." - :type '(choice (const mh-search) - (function :tag "Other Function")) - :group 'mh-tool-bar - :package-version '(MH-E . "7.0")) - - - -;;; Hooks (:group 'mh-hooks + group where hook described) - -(defcustom mh-after-commands-processed-hook nil - "Hook run by \\\\[mh-execute-commands] after performing outstanding refile and delete requests. - -Variables that are useful in this hook include -`mh-folders-changed', which lists which folders were affected by -deletes and refiles. This list will always include the current -folder, which is also available in `mh-current-folder'." - :type 'hook - :group 'mh-hooks - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defcustom mh-alias-reloaded-hook nil - "Hook run by `mh-alias-reload' after loading aliases." - :type 'hook - :group 'mh-hooks - :group 'mh-alias - :package-version '(MH-E . "8.0")) - -(defcustom mh-annotate-msg-hook nil - "Hook run when a message is sent and after annotating the scan lines and message. -Hook functions can access the current folder name with -`mh-current-folder' and obtain the message numbers of the -annotated messages with `mh-annotate-list'." - :type 'hook - :group 'mh-hooks - :group 'mh-sending-mail - :package-version '(MH-E . "8.1")) - -(defcustom mh-before-commands-processed-hook nil - "Hook run by \\\\[mh-execute-commands] before performing outstanding refile and delete requests. - -Variables that are useful in this hook include `mh-delete-list', -`mh-refile-list', `mh-blocklist', and `mh-allowlist' which can be -used to see which changes will be made to the current folder, -`mh-current-folder'." - :type 'hook - :group 'mh-hooks - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defcustom mh-before-quit-hook nil - "Hook run by \\\\[mh-quit] before quitting MH-E. - -This hook is called before the quit occurs, so you might use it -to perform any MH-E operations; you could perform some query and -abort the quit or call `mh-execute-commands', for example. - -See also `mh-quit-hook'." - :type 'hook - :group 'mh-hooks - :group 'mh-folder - :package-version '(MH-E . "6.0")) - -(defcustom mh-before-send-letter-hook nil - "Hook run at the beginning of the \\\\[mh-send-letter] command. - -For example, if you want to check your spelling in your message -before sending, add the `ispell-message' function." - :type 'hook - :options '(ispell-message) - :group 'mh-hooks - :group 'mh-letter - :package-version '(MH-E . "6.0")) - -(defcustom mh-blocklist-msg-hook nil - "Hook run by \\\\[mh-junk-blocklist] after marking each message for blocklisting." - :type 'hook - :group 'mh-hooks - :group 'mh-show - :package-version '(MH-E . "8.4")) - -(defcustom mh-delete-msg-hook nil - "Hook run by \\\\[mh-delete-msg] after marking each message for deletion. - -For example, a past maintainer of MH-E used this once when he -kept statistics on his mail usage." - :type 'hook - :group 'mh-hooks - :group 'mh-show - :package-version '(MH-E . "6.0")) - -(defcustom mh-find-path-hook nil - "Hook run by `mh-find-path' after reading the user's MH profile. - -This hook can be used the change the value of the variables that -`mh-find-path' sets if you need to run with different values -between MH and MH-E." - :type 'hook - :group 'mh-hooks - :group 'mh-e - :package-version '(MH-E . "7.0")) - -(defcustom mh-folder-mode-hook nil - "Hook run by `mh-folder-mode' when visiting a new folder." - :type 'hook - :group 'mh-hooks - :group 'mh-folder - :package-version '(MH-E . "6.0")) - -(defcustom mh-forward-hook nil - "Hook run by `mh-forward' on a forwarded letter." - :type 'hook - :group 'mh-hooks - :group 'mh-sending-mail - :package-version '(MH-E . "8.0")) - -(defcustom mh-inc-folder-hook nil - "Hook run by \\\\[mh-inc-folder] after incorporating mail into a folder." - :type 'hook - :group 'mh-hooks - :group 'mh-inc - :package-version '(MH-E . "6.0")) - -(defcustom mh-insert-signature-hook nil - "Hook run by \\\\[mh-insert-signature] after signature has been inserted. - -Hook functions may access the actual name of the file or the -function used to insert the signature with -`mh-signature-file-name'." - :type 'hook - :group 'mh-hooks - :group 'mh-letter - :package-version '(MH-E . "8.0")) - -(defcustom mh-kill-folder-suppress-prompt-functions '(mh-search-p) - "Abnormal hook run at the beginning of \\\\[mh-kill-folder]. - -The hook functions are called with no arguments and should return -a non-nil value to suppress the normal prompt when you remove a -folder. This is useful for folders that are easily regenerated. - -The default value of `mh-search-p' suppresses the prompt on -folders generated by searching. - -WARNING: Use this hook with care. If there is a bug in your hook -which returns t on \"+inbox\" and you hit \\[mh-kill-folder] by -accident in the \"+inbox\" folder, you will not be happy." - :type 'hook - :group 'mh-hooks - :group 'mh-folder - :package-version '(MH-E . "7.4")) - -(defcustom mh-letter-mode-hook nil - "Hook run by `mh-letter-mode' on a new letter. - -This hook allows you to do some processing before editing a -letter. For example, you may wish to modify the header after -\"repl\" has done its work, or you may have a complicated -\"components\" file and need to tell MH-E where the cursor should -go." - :type 'hook - :group 'mh-hooks - :group 'mh-sending-mail - :package-version '(MH-E . "6.0")) - -(defcustom mh-mh-to-mime-hook nil - "Hook run on the formatted letter by \\\\[mh-mh-to-mime]." - :type 'hook - :group 'mh-hooks - :group 'mh-letter - :package-version '(MH-E . "8.0")) - -(defcustom mh-search-mode-hook nil - "Hook run upon entry to `mh-search-mode'\\. - -If you find that you do the same thing over and over when editing -the search template, you may wish to bind some shortcuts to keys. -This can be done with this hook which is called when -\\[mh-search] is run on a new pattern." - :type 'hook - :group 'mh-hooks - :group 'mh-search - :package-version '(MH-E . "8.0")) - -(defcustom mh-pack-folder-hook nil - "Hook run by \\\\[mh-pack-folder] after renumbering the messages. -Hook functions can access the current folder name with `mh-current-folder'." - :type 'hook - :group 'mh-hooks - :group 'mh-folder - :package-version '(MH-E . "8.2")) - -(defcustom mh-quit-hook nil - "Hook run by \\\\[mh-quit] after quitting MH-E. - -This hook is not run in an MH-E context, so you might use it to -modify the window setup. - -See also `mh-before-quit-hook'." - :type 'hook - :group 'mh-hooks - :group 'mh-folder - :package-version '(MH-E . "6.0")) - -(defcustom mh-refile-msg-hook nil - "Hook run by \\\\[mh-refile-msg] after marking each message for refiling." - :type 'hook - :group 'mh-hooks - :group 'mh-folder - :package-version '(MH-E . "6.0")) - -(defcustom mh-show-hook nil - "Hook run after \\\\[mh-show] shows a message. - -It is the last thing called after messages are displayed. It's -used to affect the behavior of MH-E in general or when -`mh-show-mode-hook' is too early. See `mh-show-mode-hook'." - :type 'hook - :group 'mh-hooks - :group 'mh-show - :package-version '(MH-E . "6.0")) - -(defcustom mh-show-mode-hook nil - "Hook run upon entry to `mh-show-mode'. - -This hook is called early on in the process of the message display, -before the message contents have been inserted into the buffer. -It is usually used to perform some action on the -buffer itself. See also `mh-show-hook'." - :type 'hook - :group 'mh-hooks - :group 'mh-show - :package-version '(MH-E . "8.7")) - -(defcustom mh-unseen-updated-hook nil - "Hook run after the unseen sequence has been updated. - -The variable `mh-seen-list' can be used by this hook to obtain -the list of messages which were removed from the unseen -sequence." - :type 'hook - :group 'mh-hooks - :group 'mh-sequences - :package-version '(MH-E . "6.0")) - -(defcustom mh-allowlist-msg-hook nil - "Hook run by \\\\[mh-junk-allowlist] after marking each message for allowlisting." - :type 'hook - :group 'mh-hooks - :group 'mh-show - :package-version '(MH-E . "8.4")) - - - -;;; Faces (:group 'mh-faces + group where faces described) - -;; To add a new face: -;; 1. Add entry to variable mh-face-data. -;; 2. Create face using defface, accessing face data with function -;; mh-face-data. -;; 3. Add inherit argument to function mh-face-data if applicable. -(defvar mh-face-data - '((mh-folder-followup - ((((class color) (background light)) - (:foreground "blue3")) - (((class color) (background dark)) - (:foreground "LightGoldenRod")) - (t - (:bold t)))) - (mh-folder-msg-number - ((((class color) (min-colors 64) (background light)) - (:foreground "snow4")) - (((class color) (min-colors 64) (background dark)) - (:foreground "snow3")) - (((class color) (background light)) - (:foreground "purple")) - (((class color) (background dark)) - (:foreground "cyan")))) - (mh-folder-refiled - ((((class color) (min-colors 64) (background light)) - (:foreground "DarkGoldenrod")) - (((class color) (min-colors 64) (background dark)) - (:foreground "LightGoldenrod")) - (((class color)) - (:foreground "yellow" :weight light)) - (((class grayscale) (background light)) - (:foreground "Gray90" :bold t :italic t)) - (((class grayscale) (background dark)) - (:foreground "DimGray" :bold t :italic t)) - (t - (:bold t :italic t)))) - (mh-folder-subject - ((((class color) (background light)) - (:foreground "blue4")) - (((class color) (background dark)) - (:foreground "yellow")) - (t - (:bold t)))) - (mh-folder-tick - ((((class color) (background light)) - (:background "#dddf7e")) - (((class color) (background dark)) - (:background "#dddf7e")) - (t - (:underline t)))) - (mh-folder-to - ((((class color) (min-colors 64) (background light)) - (:foreground "RosyBrown")) - (((class color) (min-colors 64) (background dark)) - (:foreground "LightSalmon")) - (((class color)) - (:foreground "green")) - (((class grayscale) (background light)) - (:foreground "DimGray" :italic t)) - (((class grayscale) (background dark)) - (:foreground "LightGray" :italic t)) - (t - (:italic t)))) - (mh-letter-header-field - ((((class color) (background light)) - (:background "gray90")) - (((class color) (background dark)) - (:background "gray10")) - (t - (:bold t)))) - (mh-search-folder - ((((class color) (background light)) - (:foreground "dark green" :bold t)) - (((class color) (background dark)) - (:foreground "indian red" :bold t)) - (t - (:bold t)))) - (mh-show-cc - ((((class color) (min-colors 64) (background light)) - (:foreground "DarkGoldenrod")) - (((class color) (min-colors 64) (background dark)) - (:foreground "LightGoldenrod")) - (((class color)) - (:foreground "yellow" :weight light)) - (((class grayscale) (background light)) - (:foreground "Gray90" :bold t :italic t)) - (((class grayscale) (background dark)) - (:foreground "DimGray" :bold t :italic t)) - (t - (:bold t :italic t)))) - (mh-show-date - ((((class color) (min-colors 64) (background light)) - (:foreground "ForestGreen")) - (((class color) (min-colors 64) (background dark)) - (:foreground "PaleGreen")) - (((class color)) - (:foreground "green")) - (((class grayscale) (background light)) - (:foreground "Gray90" :bold t)) - (((class grayscale) (background dark)) - (:foreground "DimGray" :bold t)) - (t - (:bold t :underline t)))) - (mh-show-from - ((((class color) (background light)) - (:foreground "red3")) - (((class color) (background dark)) - (:foreground "cyan")) - (t - (:bold t)))) - (mh-show-header - ((((class color) (min-colors 64) (background light)) - (:foreground "RosyBrown")) - (((class color) (min-colors 64) (background dark)) - (:foreground "LightSalmon")) - (((class color)) - (:foreground "green")) - (((class grayscale) (background light)) - (:foreground "DimGray" :italic t)) - (((class grayscale) (background dark)) - (:foreground "LightGray" :italic t)) - (t - (:italic t)))) - (mh-show-pgg-bad ((t (:bold t :foreground "DeepPink1")))) - (mh-show-pgg-good ((t (:bold t :foreground "LimeGreen")))) - (mh-show-pgg-unknown ((t (:bold t :foreground "DarkGoldenrod2")))) - (mh-show-signature ((t (:italic t)))) - (mh-show-to - ((((class color) (background light)) - (:foreground "SaddleBrown")) - (((class color) (background dark)) - (:foreground "burlywood")) - (((class grayscale) (background light)) - (:foreground "DimGray" :underline t)) - (((class grayscale) (background dark)) - (:foreground "LightGray" :underline t)) - (t (:underline t)))) - (mh-speedbar-folder - ((((class color) (background light)) - (:foreground "blue4")) - (((class color) (background dark)) - (:foreground "light blue")))) - (mh-speedbar-selected-folder - ((((class color) (background light)) - (:foreground "red1" :underline t)) - (((class color) (background dark)) - (:foreground "red1" :underline t)) - (t - (:underline t))))) - "MH-E face data. -Used by function `mh-face-data' which returns spec that is -consumed by `defface'.") - -(require 'cus-face) - -(defvar mh-inherit-face-flag t - "Non-nil means that the `defface' :inherit keyword is available.") -(make-obsolete-variable 'mh-inherit-face-flag nil "29.1") - -(defvar mh-min-colors-defined-flag t - "Non-nil means `defface' supports min-colors display requirement.") -(make-obsolete-variable 'mh-min-colors-defined-flag nil "29.1") - -(defun mh-face-data (face &optional inherit) - "Return spec for FACE. -See `defface' for the spec definition. - -If INHERIT is non-nil and `defface' supports the :inherit -keyword, return INHERIT literally; otherwise, return spec for -FACE from the variable `mh-face-data'. This isn't a perfect -implementation. In the case that the :inherit keyword is not -supported, any additional attributes in the inherit parameter are -not added to the returned spec." - (or inherit - (cadr (assq face mh-face-data)) - (error "Could not find %s in mh-face-data" face))) - -(defface mh-folder-address - (mh-face-data 'mh-folder-subject '((t (:inherit mh-folder-subject)))) - "Recipient face." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defface mh-folder-blocklisted - (mh-face-data 'mh-folder-msg-number '((t (:inherit mh-folder-msg-number)))) - "Blocklisted message face." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.4")) - -(defface mh-folder-body - (mh-face-data 'mh-folder-msg-number - '((((class color)) - (:inherit mh-folder-msg-number)) - (t - (:inherit mh-folder-msg-number :italic t)))) - "Body text face." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defface mh-folder-cur-msg-number - (mh-face-data 'mh-folder-msg-number - '((t (:inherit mh-folder-msg-number :bold t)))) - "Current message number face." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defface mh-folder-date - (mh-face-data 'mh-folder-msg-number '((t (:inherit mh-folder-msg-number)))) - "Date face." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defface mh-folder-deleted - (mh-face-data 'mh-folder-msg-number '((t (:inherit mh-folder-msg-number)))) - "Deleted message face." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defface mh-folder-followup (mh-face-data 'mh-folder-followup) - "\"Re:\" face." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defface mh-folder-msg-number (mh-face-data 'mh-folder-msg-number) - "Message number face." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defface mh-folder-refiled (mh-face-data 'mh-folder-refiled) - "Refiled message face." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defface mh-folder-sent-to-me-hint - (mh-face-data 'mh-folder-msg-number '((t (:inherit mh-folder-date)))) - "Fontification hint face in messages sent directly to us. -The detection of messages sent to us is governed by the scan -format `mh-scan-format-nmh' and the regular expression -`mh-scan-sent-to-me-sender-regexp'." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defface mh-folder-sent-to-me-sender - (mh-face-data 'mh-folder-followup '((t (:inherit mh-folder-followup)))) - "Sender face in messages sent directly to us. -The detection of messages sent to us is governed by the scan -format `mh-scan-format-nmh' and the regular expression -`mh-scan-sent-to-me-sender-regexp'." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defface mh-folder-subject (mh-face-data 'mh-folder-subject) - "Subject face." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defface mh-folder-tick (mh-face-data 'mh-folder-tick) - "Ticked message face." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defface mh-folder-to (mh-face-data 'mh-folder-to) - "\"To:\" face." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.0")) - -(defface mh-folder-allowlisted - (mh-face-data 'mh-folder-refiled '((t (:inherit mh-folder-refiled)))) - "Allowlisted message face." - :group 'mh-faces - :group 'mh-folder - :package-version '(MH-E . "8.4")) - -(defface mh-letter-header-field (mh-face-data 'mh-letter-header-field) - "Editable header field value face in draft buffers." - :group 'mh-faces - :group 'mh-letter - :package-version '(MH-E . "8.0")) - -(defface mh-search-folder (mh-face-data 'mh-search-folder) - "Folder heading face in MH-Folder buffers created by searches." - :group 'mh-faces - :group 'mh-search - :package-version '(MH-E . "8.0")) - -(defface mh-show-cc (mh-face-data 'mh-show-cc) - "Face used to highlight \"cc:\" header fields." - :group 'mh-faces - :group 'mh-show - :package-version '(MH-E . "8.0")) - -(defface mh-show-date (mh-face-data 'mh-show-date) - "Face used to highlight \"Date:\" header fields." - :group 'mh-faces - :group 'mh-show - :package-version '(MH-E . "8.0")) - -(defface mh-show-from (mh-face-data 'mh-show-from) - "Face used to highlight \"From:\" header fields." - :group 'mh-faces - :group 'mh-show - :package-version '(MH-E . "8.0")) - -(defface mh-show-header (mh-face-data 'mh-show-header) - "Face used to deemphasize less interesting header fields." - :group 'mh-faces - :group 'mh-show - :package-version '(MH-E . "8.0")) - -(defface mh-show-pgg-bad (mh-face-data 'mh-show-pgg-bad) - "Bad PGG signature face." - :group 'mh-faces - :group 'mh-show - :package-version '(MH-E . "8.0")) - -(defface mh-show-pgg-good (mh-face-data 'mh-show-pgg-good) - "Good PGG signature face." - :group 'mh-faces - :group 'mh-show - :package-version '(MH-E . "8.0")) - -(defface mh-show-pgg-unknown (mh-face-data 'mh-show-pgg-unknown) - "Unknown or untrusted PGG signature face." - :group 'mh-faces - :group 'mh-show - :package-version '(MH-E . "8.0")) - -(defface mh-show-signature (mh-face-data 'mh-show-signature) - "Signature face." - :group 'mh-faces - :group 'mh-show - :package-version '(MH-E . "8.0")) - -(defface mh-show-subject - (mh-face-data 'mh-folder-subject '((t (:inherit mh-folder-subject)))) - "Face used to highlight \"Subject:\" header fields." - :group 'mh-faces - :group 'mh-show - :package-version '(MH-E . "8.0")) - -(defface mh-show-to (mh-face-data 'mh-show-to) - "Face used to highlight \"To:\" header fields." - :group 'mh-faces - :group 'mh-show - :package-version '(MH-E . "8.0")) - -(defface mh-show-xface - (mh-face-data 'mh-show-from '((t (:inherit (mh-show-from highlight))))) -"X-Face image face. -The background and foreground are used in the image." - :group 'mh-faces - :group 'mh-show - :package-version '(MH-E . "8.0")) - -(defface mh-speedbar-folder (mh-face-data 'mh-speedbar-folder) - "Basic folder face." - :group 'mh-faces - :group 'mh-speedbar - :package-version '(MH-E . "8.0")) - -(defface mh-speedbar-folder-with-unseen-messages - (mh-face-data 'mh-speedbar-folder - '((t (:inherit mh-speedbar-folder :bold t)))) - "Folder face when folder contains unread messages." - :group 'mh-faces - :group 'mh-speedbar - :package-version '(MH-E . "8.0")) - -(defface mh-speedbar-selected-folder - (mh-face-data 'mh-speedbar-selected-folder) - "Selected folder face." - :group 'mh-faces - :group 'mh-speedbar - :package-version '(MH-E . "8.0")) - -(defface mh-speedbar-selected-folder-with-unseen-messages - (mh-face-data 'mh-speedbar-selected-folder - '((t (:inherit mh-speedbar-selected-folder :bold t)))) - "Selected folder face when folder contains unread messages." - :group 'mh-faces - :group 'mh-speedbar - :package-version '(MH-E . "8.0")) - -(provide 'mh-e) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-e.el ends here diff --git a/lisp/mh-e/mh-folder.el b/lisp/mh-e/mh-folder.el deleted file mode 100644 index c90537f1502..00000000000 --- a/lisp/mh-e/mh-folder.el +++ /dev/null @@ -1,2019 +0,0 @@ -;;; mh-folder.el --- MH-Folder mode -*- lexical-binding: t; -*- - -;; Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc. - -;; Author: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Mode for browsing folders - -;;; Code: - -(require 'mh-e) -(require 'mh-scan) - -;; Dynamically-created functions not found in mh-loaddefs.el. -(autoload 'mh-tool-bar-folder-buttons-init "mh-tool-bar") -(autoload 'mh-tool-bar-init "mh-tool-bar") - -(require 'gnus-util) -(autoload 'message-fetch-field "message") - - - -;;; MH-E Entry Points - -;;;###autoload -(defun mh-rmail (&optional arg) - "Incorporate new mail with MH. -Scan an MH folder if ARG is non-nil. - -This function is an entry point to MH-E, the Emacs interface to -the MH mail system." - (interactive "P") - (mh-find-path) - (if arg - (call-interactively 'mh-visit-folder) - (unless (get-buffer mh-inbox) - (mh-visit-folder mh-inbox (symbol-name mh-unseen-seq))) - (mh-inc-folder))) - -;;;###autoload -(defun mh-nmail (&optional arg) - "Check for new mail in inbox folder. -Scan an MH folder if ARG is non-nil. - -This function is an entry point to MH-E, the Emacs interface to -the MH mail system." - (interactive "P") - (mh-find-path) ; init mh-inbox - (if arg - (call-interactively 'mh-visit-folder) - (mh-visit-folder mh-inbox))) - - -;;; Desktop Integration - -(add-to-list 'desktop-buffer-mode-handlers - '(mh-folder-mode . mh-restore-desktop-buffer)) - -(defun mh-restore-desktop-buffer (_file-name name _misc) - "Restore an MH folder buffer specified in a desktop file. -When desktop creates a buffer, FILE-NAME holds the -file name to visit, NAME holds the desired buffer -name, and MISC holds a list of miscellaneous info -used by the `desktop-buffer-mode-handlers' functions." - (mh-find-path) - (mh-visit-folder name) - (current-buffer)) - - - -;;; Variables - -(defvar mh-folder-filename nil - "Full path of directory for this folder.") - -(defvar mh-partial-folder-mode-line-annotation "select" - "Annotation when displaying part of a folder. -The string is displayed after the folder's name. nil for no -annotation.") - -(defvar mh-last-destination nil - "Destination of last refile or write command.") - -(defvar mh-last-destination-folder nil - "Destination of last refile command.") - -(defvar mh-last-destination-write nil - "Destination of last write command.") - -(defvar mh-first-msg-num nil - "Number of first message in buffer.") - -(defvar mh-last-msg-num nil - "Number of last msg in buffer.") - -(defvar mh-msg-count nil - "Number of msgs in buffer.") - - - -;;; Sequence Menu - -(easy-menu-define - mh-folder-sequence-menu mh-folder-mode-map "Menu for MH-E folder-sequence." - '("Sequence" - ["Add Message to Sequence..." mh-put-msg-in-seq (mh-get-msg-num nil)] - ["List Sequences for Message" mh-msg-is-in-seq (mh-get-msg-num nil)] - ["Delete Message from Sequence..." mh-delete-msg-from-seq - (mh-get-msg-num nil)] - ["List Sequences in Folder..." mh-list-sequences t] - ["Delete Sequence..." mh-delete-seq t] - ["Narrow to Sequence..." mh-narrow-to-seq t] - ["Widen from Sequence" mh-widen mh-folder-view-stack] - "--" - ["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])) - -;;; Message Menu - -(easy-menu-define - mh-folder-message-menu mh-folder-mode-map "Menu for MH-E folder-message." - '("Message" - ["Show Message" mh-show (mh-get-msg-num nil)] - ["Show Message with Header" mh-header-display (mh-get-msg-num nil)] - ["Show Message with Preferred Alternative" - mh-show-preferred-alternative (mh-get-msg-num nil)] - ["Next Message" mh-next-undeleted-msg t] - ["Previous Message" mh-previous-undeleted-msg t] - ["Go to First Message" mh-first-msg t] - ["Go to Last Message" mh-last-msg t] - ["Go to Message by Number..." mh-goto-msg t] - ["Modify Message" mh-modify t] - ["Refile Message" mh-refile-msg (mh-get-msg-num nil)] - ["Delete Message" mh-delete-msg (mh-get-msg-num nil)] - ["Undo Delete/Refile/Junk" mh-undo (mh-outstanding-commands-p)] - ["Execute Delete/Refile" mh-execute-commands - (mh-outstanding-commands-p)] - "--" - ["Compose a New Message" mh-send t] - ["Reply to Message..." mh-reply (mh-get-msg-num nil)] - ["Forward Message..." mh-forward (mh-get-msg-num nil)] - ["Redistribute Message..." mh-redistribute (mh-get-msg-num nil)] - ["Edit Message Again" mh-edit-again (mh-get-msg-num nil)] - ["Re-edit a Bounced Message" mh-extract-rejected-mail t] - "--" - ["Copy Message to Folder..." mh-copy-msg (mh-get-msg-num nil)] - ["Print Message" mh-print-msg (mh-get-msg-num nil)] - ["Write Message to File..." mh-write-msg-to-file - (mh-get-msg-num nil)] - ["Pipe Message to Command..." mh-pipe-msg (mh-get-msg-num nil)] - ["Unpack Uuencoded Message..." mh-store-msg (mh-get-msg-num nil)] - ["Burst Digest Message" mh-burst-digest (mh-get-msg-num nil)])) - -;;; Folder Menu - -(easy-menu-define - mh-folder-folder-menu mh-folder-mode-map "Menu for MH-E folder." - '("Folder" - ["Incorporate New Mail" mh-inc-folder t] - ["Toggle Show/Folder" mh-toggle-showing t] - ["Execute Delete/Refile" mh-execute-commands - (mh-outstanding-commands-p)] - ["Rescan Folder" mh-rescan-folder t] - ["Thread Folder" mh-toggle-threads - (not (memq 'unthread mh-view-ops))] - ["Pack Folder" mh-pack-folder t] - ["Sort Folder" mh-sort-folder t] - "--" - ["List Folders" mh-list-folders t] - ["Visit a Folder..." mh-visit-folder t] - ["View New Messages" mh-index-new-messages t] - ["Search..." mh-search t] - "--" - ["Quit MH-E" mh-quit t])) - - - -;;; MH-Folder Keys - -(suppress-keymap mh-folder-mode-map) - -;; Use defalias to make sure the documented primary key bindings -;; appear in menu lists. -(defalias 'mh-alt-show #'mh-show) -(defalias 'mh-alt-refile-msg #'mh-refile-msg) -(defalias 'mh-alt-send #'mh-send) -(defalias 'mh-alt-visit-folder #'mh-visit-folder) - -;; Save the "b" binding for a future `back'. Maybe? -(define-keymap :keymap mh-folder-mode-map - "SPC" #'mh-page-msg - "!" #'mh-refile-or-write-again - "'" #'mh-toggle-tick - "," #'mh-header-display - "." #'mh-alt-show - ":" #'mh-show-preferred-alternative - ";" #'mh-toggle-mh-decode-mime-flag - ">" #'mh-write-msg-to-file - "?" #'mh-help - "E" #'mh-extract-rejected-mail - "M" #'mh-modify - "DEL" #'mh-previous-page - "C-d" #'mh-delete-msg-no-motion - "TAB" #'mh-index-next-folder - "" #'mh-index-previous-folder - "C-M-i" #'mh-index-previous-folder - "ESC <" #'mh-first-msg - "ESC >" #'mh-last-msg - "ESC d" #'mh-redistribute - "RET" #'mh-show - "^" #'mh-alt-refile-msg - "c" #'mh-copy-msg - "d" #'mh-delete-msg - "e" #'mh-edit-again - "f" #'mh-forward - "g" #'mh-goto-msg - "i" #'mh-inc-folder - "k" #'mh-delete-subject-or-thread - "m" #'mh-alt-send - "n" #'mh-next-undeleted-msg - "M-n" #'mh-next-unread-msg - "o" #'mh-refile-msg - "p" #'mh-previous-undeleted-msg - "M-p" #'mh-previous-unread-msg - "q" #'mh-quit - "r" #'mh-reply - "s" #'mh-send - "t" #'mh-toggle-showing - "u" #'mh-undo - "v" #'mh-index-visit-folder - "x" #'mh-execute-commands - "|" #'mh-pipe-msg - - "F" (define-keymap :prefix 'mh-folder-map - "?" #'mh-prefix-help - "'" #'mh-index-ticked-messages - "S" #'mh-sort-folder - "c" #'mh-catchup - "f" #'mh-alt-visit-folder - "k" #'mh-kill-folder - "l" #'mh-list-folders - "n" #'mh-index-new-messages - "o" #'mh-alt-visit-folder - "p" #'mh-pack-folder - "q" #'mh-index-sequenced-messages - "r" #'mh-rescan-folder - "s" #'mh-search - "u" #'mh-undo-folder - "v" #'mh-visit-folder) - - "I" mh-inc-spool-map - - "J" (define-keymap :prefix 'mh-junk-map - "?" #'mh-prefix-help - "a" #'mh-junk-allowlist - "b" #'mh-junk-blocklist - "w" #'mh-junk-whitelist) - - "P" (define-keymap :prefix 'mh-ps-print-map - "?" #'mh-prefix-help - "C" #'mh-ps-print-toggle-color - "F" #'mh-ps-print-toggle-faces - "f" #'mh-ps-print-msg-file - "l" #'mh-print-msg - "p" #'mh-ps-print-msg) - - "S" (define-keymap :prefix 'mh-sequence-map - "'" #'mh-narrow-to-tick - "?" #'mh-prefix-help - "d" #'mh-delete-msg-from-seq - "k" #'mh-delete-seq - "l" #'mh-list-sequences - "n" #'mh-narrow-to-seq - "p" #'mh-put-msg-in-seq - "s" #'mh-msg-is-in-seq - "w" #'mh-widen) - - "T" (define-keymap :prefix 'mh-thread-map - "?" #'mh-prefix-help - "u" #'mh-thread-ancestor - "p" #'mh-thread-previous-sibling - "n" #'mh-thread-next-sibling - "t" #'mh-toggle-threads - "d" #'mh-thread-delete - "o" #'mh-thread-refile) - - "/" (define-keymap :prefix 'mh-limit-map - "'" #'mh-narrow-to-tick - "?" #'mh-prefix-help - "c" #'mh-narrow-to-cc - "g" #'mh-narrow-to-range - "m" #'mh-narrow-to-from - "s" #'mh-narrow-to-subject - "t" #'mh-narrow-to-to - "w" #'mh-widen) - - "X" (define-keymap :prefix 'mh-extract-map - "?" #'mh-prefix-help - "s" #'mh-store-msg ;shar - "u" #'mh-store-msg) ;uuencode - - "D" (define-keymap :prefix 'mh-digest-map - "SPC" #'mh-page-digest - "?" #'mh-prefix-help - "DEL" #'mh-page-digest-backwards - "b" #'mh-burst-digest) - - "K" (define-keymap :prefix 'mh-mime-map - "?" #'mh-prefix-help - "a" #'mh-mime-save-parts - "e" #'mh-display-with-external-viewer - "i" #'mh-folder-inline-mime-part - "o" #'mh-folder-save-mime-part - "t" #'mh-toggle-mime-buttons - "v" #'mh-folder-toggle-mime-part - "TAB" #'mh-next-button - "" #'mh-prev-button - "C-M-i" #'mh-prev-button) - - "" #'mh-show-mouse) - -;; "C-c /" prefix is used in mh-folder-mode by pgp.el and mailcrypt - - - -;;; MH-Folder Help Messages - -;; If you add a new prefix, add appropriate text to the nil key. - -;; In general, messages are grouped logically. Taking the main commands for -;; example, the first line is "ways to view messages," the second line is -;; "things you can do with messages", and the third is "composing" messages. - -;; When adding a new prefix, ensure that the help message contains "what" the -;; prefix is for. For example, if the word "folder" were not present in the -;; "F" entry, it would not be clear what these commands operated upon. -(defvar mh-folder-mode-help-messages - '((nil "[i]nc, [.]show, [,]show all, [n]ext, [p]revious,\n" - "[d]elete, [o]refile, e[x]ecute,\n" - "[s]end, [r]eply,\n" - "[;]toggle MIME decoding.\n" - "Prefix characters:\n [F]older, [S]equence, [J]unk, MIME [K]eys," - "\n [T]hread, [/]limit, e[X]tract, [D]igest, [I]nc spools.") - - (?F "[l]ist; [v]isit folder;\n" - "[n]ew messages; [']ticked messages; [s]earch;\n" - "[p]ack; [S]ort; [r]escan; [k]ill") - (?P "[p]rint message to [f]ile; old-style [l]pr printing;\n" - "Toggle printing of [C]olors, [F]aces") - (?S "[p]ut message in sequence, [n]arrow, [']narrow to ticked, [w]iden,\n" - "[s]equences, [l]ist,\n" - "[d]elete message from sequence, [k]ill sequence") - (?T "[t]oggle, [d]elete, [o]refile thread") - (?/ "Limit to [c]c, ran[g]e, fro[m], [s]ubject, [t]o; [w]iden") - (?X "un[s]har, [u]udecode message") - (?D "[b]urst digest") - (?K "[v]iew, [i]nline, with [e]xternal viewer; \n" - "[o]utput/save MIME part; save [a]ll parts; \n" - "[t]oggle buttons; [TAB] next; [SHIFT-TAB] previous") - (?J "[b]locklist, [a]llowlist message")) - "Key binding cheat sheet. -See `mh-set-help'.") - - - -;;; MH-Folder Font Lock - -(defvar mh-folder-font-lock-keywords - (list - ;; Folders when displaying index buffer - (list "^\\+.*" - '(0 'mh-search-folder)) - ;; Marked for refile - (list (concat mh-scan-refiled-msg-regexp ".*") - '(0 'mh-folder-refiled)) - ;; Marked for deletion - (list (concat mh-scan-deleted-msg-regexp ".*") - '(0 'mh-folder-deleted)) - ;; Marked for blocklisting - (list (concat mh-scan-blocklisted-msg-regexp ".*") - '(0 'mh-folder-blocklisted)) - ;; Marked for allowlisting - (list (concat mh-scan-allowlisted-msg-regexp ".*") - '(0 'mh-folder-allowlisted)) - ;; After subject - (list mh-scan-body-regexp - '(1 'mh-folder-body nil t)) - ;; Subject - '(mh-folder-font-lock-subject - (1 'mh-folder-followup append t) - (2 'mh-folder-subject append t)) - ;; Current message number - (list mh-scan-cur-msg-number-regexp - '(1 'mh-folder-cur-msg-number)) - ;; Message number - (list mh-scan-good-msg-regexp - '(1 'mh-folder-msg-number)) - ;; Date - (list mh-scan-date-regexp - '(1 'mh-folder-date)) - ;; Messages from me (To:) - (list mh-scan-rcpt-regexp - '(1 'mh-folder-to) - '(2 'mh-folder-address)) - ;; Messages to me - (list mh-scan-sent-to-me-sender-regexp - '(1 'mh-folder-sent-to-me-hint) - '(2 'mh-folder-sent-to-me-sender))) - "Keywords (regular expressions) used to fontify the MH-Folder buffer.") - -(defun mh-folder-font-lock-subject (limit) - "Return MH-E scan subject strings to font-lock between point and LIMIT." - (if (not (re-search-forward mh-scan-subject-regexp limit t)) - nil - (if (match-beginning 1) - (set-match-data (list (match-beginning 1) (match-end 3) - (match-beginning 1) (match-end 3) nil nil)) - (set-match-data (list (match-beginning 3) (match-end 3) - nil nil (match-beginning 3) (match-end 3)))) - t)) - -;; Fontify unseen messages in bold. - -(defmacro mh-generate-sequence-font-lock (seq prefix face) - "Generate the appropriate code to fontify messages in SEQ. -PREFIX is used to generate unique names for the variables and -functions defined by the macro. So a different prefix should be -provided for every invocation. -FACE is the font-lock face used to display the matching scan lines." - (let ((cache (intern (format "mh-folder-%s-seq-cache" prefix))) - (func (intern (format "mh-folder-font-lock-%s" prefix)))) - `(progn - (defvar ,cache nil - "Internal cache variable used for font-lock in MH-E. -Should only be non-nil through font-lock stepping, and nil once -font-lock is done highlighting.") - (make-variable-buffer-local ',cache) - - (defun ,func (limit) - "Return unseen message lines to font-lock between point and LIMIT." - (if (not ,cache) (setq ,cache (mh-seq-msgs (mh-find-seq ,seq)))) - (let ((cur-msg (mh-get-msg-num nil))) - (cond ((not ,cache) - nil) - ((>= (point) limit) ;Presumably at end of buffer - (setq ,cache nil) - nil) - ((member cur-msg ,cache) - (let ((bpoint (progn (beginning-of-line)(point))) - (epoint (progn (forward-line 1)(point)))) - (if (<= limit (point)) (setq ,cache nil)) - (set-match-data (list bpoint epoint bpoint epoint)) - t)) - (t - ;; move forward one line at a time, checking each message - (while (and (= 0 (forward-line 1)) - (> limit (point)) - (not (member (mh-get-msg-num nil) ,cache)))) - ;; Examine how we must have exited the loop... - (let ((cur-msg (mh-get-msg-num nil))) - (cond ((or (<= limit (point)) - (not (member cur-msg ,cache))) - (setq ,cache nil) - nil) - ((member cur-msg ,cache) - (let ((bpoint (progn (beginning-of-line) (point))) - (epoint (progn (forward-line 1) (point)))) - (if (<= limit (point)) (setq ,cache nil)) - (set-match-data - (list bpoint epoint bpoint epoint)) - t)))))))) - - (setq mh-folder-font-lock-keywords - (append mh-folder-font-lock-keywords - (list (list ',func (list 1 '',face 'prepend t)))))))) - -(mh-generate-sequence-font-lock mh-unseen-seq unseen bold) -(mh-generate-sequence-font-lock mh-tick-seq tick mh-folder-tick) - - - -;;; MH-Folder Mode - -(defmacro mh-remove-xemacs-horizontal-scrollbar () - (declare (obsolete nil "29.1")) - nil) - -;; Register mh-folder-mode as supporting which-function-mode... -(require 'which-func) -(when (and (boundp 'which-func-modes) (listp which-func-modes)) - (add-to-list 'which-func-modes 'mh-folder-mode)) - -;; Ensure new buffers won't get this mode if default major-mode is nil. -(put 'mh-folder-mode 'mode-class 'special) - -;; Autoload cookie needed by desktop.el -;;;###autoload -(define-derived-mode mh-folder-mode fundamental-mode "MH-Folder" - "Major MH-E mode for \"editing\" an MH folder scan listing. -\\ -You can show the message the cursor is pointing to, and step through -the messages. Messages can be marked for deletion or refiling into -another folder; these commands are executed all at once with a -separate command. - -Options that control this mode can be changed with -\\[customize-group]; specify the \"mh\" group. In particular, please -see the `mh-scan-format-file' option if you wish to modify scan's -format. - -When a folder is visited, the hook `mh-folder-mode-hook' is run. - -Ranges -====== -Many commands that operate on individual messages, such as -`mh-forward' or `mh-refile-msg' take a RANGE argument. This argument -can be used in several ways. - -If you provide the prefix argument (\\[universal-argument]) to -these commands, then you will be prompted for the message range. -This can be any valid MH range which can include messages, -sequences, and the abbreviations (described in the mh(1) man -page): - -- - Indicates all messages in the range to , inclusive. - The range must be nonempty. - -:N -:+N -:-N - Up to N messages beginning with (or ending with) message num. Num - may be any of the predefined symbols: first, prev, cur, next or - last. - -first:N -prev:N -next:N -last:N - The first, previous, next or last messages, if they exist. - -all - All of the messages. - -For example, a range that shows all of these things is `1 2 3 -5-10 last:5 unseen'. - -If the option `transient-mark-mode' is set to t and you set a -region in the MH-Folder buffer, then the MH-E command will -perform the operation on all messages in that region. - -\\{mh-folder-mode-map}" - (unless mh-folder-tool-bar-map - (mh-tool-bar-folder-buttons-init)) - (if (boundp 'tool-bar-map) - (setq-local tool-bar-map mh-folder-tool-bar-map)) - (make-local-variable 'font-lock-defaults) - (setq font-lock-defaults '(mh-folder-font-lock-keywords t)) - (make-local-variable 'desktop-save-buffer) - (setq desktop-save-buffer t) - (setq-local - mh-colors-available-flag (display-color-p) - ; Do we have colors available - mh-current-folder (buffer-name) ; Name of folder, a string - mh-show-buffer (format "show-%s" (buffer-name)) ; Buffer that displays msgs - mh-folder-filename ; e.g. "/usr/foobar/Mail/inbox/" - (file-name-as-directory (mh-expand-file-name (buffer-name))) - mh-display-buttons-for-inline-parts-flag - mh-display-buttons-for-inline-parts-flag ; Allow for display of buttons to - ; be toggled. - mh-arrow-marker (make-marker) ; Marker where arrow is displayed - overlay-arrow-position nil ; Allow for simultaneous display in - overlay-arrow-string ">" ; different MH-E buffers. - mh-showing-mode nil ; Show message also? - mh-refile-list nil ; List of folder names in mh-seq-list - mh-delete-list nil ; List of msgs nums to delete - mh-blocklist nil ; List of messages to process as spam - mh-allowlist nil ; List of messages to process as ham - mh-seq-list nil ; Alist of (seq . msgs) nums - mh-seen-list nil ; List of displayed messages - mh-next-direction 'forward ; Direction to move to next message - mh-view-ops () ; Stack that keeps track of the order - ; in which narrowing/threading has been - ; carried out. - mh-folder-view-stack () ; Stack of previous views of the - ; folder. - mh-index-data nil ; If the folder was created by a call - ; to mh-search, this contains info - ; about the search results. - mh-index-previous-search nil ; folder, indexer, search-regexp - mh-index-msg-checksum-map nil ; msg -> checksum map - mh-index-checksum-origin-map nil ; checksum -> ( orig-folder, orig-msg ) - mh-index-sequence-search-flag nil ; folder resulted from sequence search - mh-first-msg-num nil ; Number of first msg in buffer - mh-last-msg-num nil ; Number of last msg in buffer - mh-msg-count nil ; Number of msgs in buffer - mh-mode-line-annotation nil ; Indicates message range - mh-sequence-notation-history (make-hash-table) - ; Remember what is overwritten by - ; mh-note-seq. - imenu-create-index-function 'mh-index-create-imenu-index - ; Setup imenu support - mh-previous-window-config nil) ; Previous window configuration - (setq truncate-lines t) - (auto-save-mode -1) - (setq buffer-offer-save t) - (add-hook 'write-file-functions #'mh-execute-commands nil t) - (make-local-variable 'revert-buffer-function) - (make-local-variable 'hl-line-mode) ; avoid pollution - (hl-line-mode 1) - (setq revert-buffer-function #'mh-undo-folder) - (add-to-list 'minor-mode-alist '(mh-showing-mode " Show")) - (mh-inc-spool-make) - (mh-set-help mh-folder-mode-help-messages)) - - - -;;; MH-Folder Commands - -;; Alphabetical. -;; See also mh-comp.el, mh-junk.el, mh-mime.el, mh-print.el, -;; mh-search.el, and mh-seq.el. - -;;;###mh-autoload -(defun mh-delete-msg (range) - "Delete RANGE\\. - -To mark a message for deletion, use this command. A \"D\" is -placed by the message in the scan window, and the next undeleted -message is displayed. If the previous command had been -\\[mh-previous-undeleted-msg], then the next message displayed is -the first undeleted message previous to the message just deleted. -Use \\[mh-next-undeleted-msg] to force subsequent -\\[mh-delete-msg] commands to move forward to the next undeleted -message after deleting the message under the cursor. - -The hook `mh-delete-msg-hook' is called after you mark a message -for deletion. For example, a past maintainer of MH-E used this -once when he kept statistics on his mail usage. - -Check the documentation of `mh-interactive-range' to see how -RANGE is read in interactive use." - (interactive (list (mh-interactive-range "Delete"))) - (mh-delete-msg-no-motion range) - (if (looking-at mh-scan-deleted-msg-regexp) - (mh-next-msg))) - -;;;###mh-autoload -(defun mh-delete-msg-no-motion (range) - "Delete RANGE, don't move to next message. - -This command marks the RANGE for deletion but leaves the cursor -at the current message in case you wish to perform other -operations on the message. - -Check the documentation of `mh-interactive-range' to see how -RANGE is read in interactive use." - (interactive (list (mh-interactive-range "Delete"))) - (mh-iterate-on-range () range - (mh-delete-a-msg nil))) - -;;;###mh-autoload -(defun mh-execute-commands () - "Perform outstanding operations\\. - -If you've marked messages to be refiled, deleted, blocklisted, or -allowlisted and you want to go ahead and perform these operations -on these messages, use this command. Many MH-E commands that may -affect the numbering of the messages (such as -\\[mh-rescan-folder] or \\[mh-pack-folder]) will ask if you want -to perform these operations first and then either run this -command for you or undo the pending operations. - -This function runs `mh-before-commands-processed-hook' before the -commands are processed and `mh-after-commands-processed-hook' -after the commands are processed." - (interactive) - (if mh-folder-view-stack (mh-widen t)) - (mh-process-commands mh-current-folder) - (mh-set-scan-mode) - (mh-goto-cur-msg) ; after mh-set-scan-mode for efficiency - (mh-make-folder-mode-line) - t) ; return t for write-file-functions - -;;;###mh-autoload -(defun mh-first-msg () - "Display first message." - (interactive) - (goto-char (point-min)) - (while (and (not (eobp)) (not (looking-at mh-scan-valid-regexp))) - (forward-line 1))) - -;;;###mh-autoload -(defun mh-goto-msg (number &optional no-error-if-no-message dont-show) - "Go to a message\\. - -You can enter the message NUMBER either before or after typing -\\[mh-goto-msg]. In the latter case, Emacs prompts you. - -In a program, optional non-nil second argument NO-ERROR-IF-NO-MESSAGE -means return nil instead of signaling an error if message does not -exist; in this case, the cursor is positioned near where the message -would have been. Non-nil third argument DONT-SHOW means not to show -the message." - (interactive "NGo to message: ") - (setq number (prefix-numeric-value number)) - (let ((point (point)) - (return-value t)) - (goto-char (point-min)) - (unless (re-search-forward (format (mh-scan-msg-search-regexp) number) - nil t) - (goto-char point) - (unless no-error-if-no-message - (error "No message %d" number)) - (setq return-value nil)) - (beginning-of-line) - (or dont-show (not return-value) (mh-maybe-show number)) - return-value)) - -;;;###mh-autoload -(defun mh-inc-folder (&optional file folder) - "Incorporate new mail into a folder. - -You can incorporate mail from any file into the current folder by -specifying a prefix argument; you'll be prompted for the name of -the FILE to use as well as the destination FOLDER - -The hook `mh-inc-folder-hook' is run 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))) - (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))) - (when (and mh-show-buffer (get-buffer mh-show-buffer)) - (delete-windows-on mh-show-buffer)) - (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 file) - (when (and threading-needed-flag - (save-excursion - (goto-char (point-min)) - (or (null mh-large-folder) - (not (equal (forward-line (1+ mh-large-folder)) 0)) - (and (message "Not threading since the number of messages exceeds `mh-large-folder'") - nil)))) - (mh-toggle-threads)) - (beginning-of-line) - (when (mh-outstanding-commands-p) - (mh-notate-deleted-and-refiled)) - (if (and mh-showing-mode (looking-at mh-scan-valid-regexp)) (mh-show)) - (run-hooks 'mh-inc-folder-hook))) - -;;;###mh-autoload -(defun mh-last-msg () - "Display last message." - (interactive) - (goto-char (point-max)) - (while (and (not (bobp)) (not (looking-at mh-scan-valid-regexp))) - (forward-line -1)) - (mh-recenter nil)) - -;;;###mh-autoload -(defun mh-modify (&optional message) - "Edit message. - -There are times when you need to edit a message. For example, you -may need to fix a broken Content-Type header field. You can do -this with this command. It displays the raw message in an -editable buffer. When you are done editing, save and kill the -buffer as you would any other. - -From a program, edit MESSAGE; nil means edit current message." - (interactive) - (let* ((message (or message (mh-get-msg-num t))) - (msg-filename (mh-msg-filename message)) - edit-buffer) - (when (not (file-exists-p msg-filename)) - (error "Message %d does not exist" message)) - - ;; Invalidate the show buffer if it is showing the same message that is - ;; to be edited. - (when (and (buffer-live-p (get-buffer mh-show-buffer)) - (equal (with-current-buffer mh-show-buffer - buffer-file-name) - msg-filename)) - (mh-invalidate-show-buffer)) - - ;; Edit message - (find-file msg-filename) - (setq edit-buffer (current-buffer)) - - ;; Set buffer properties - (mh-letter-mode) - (use-local-map text-mode-map) - - ;; Just show the edit buffer... - (delete-other-windows) - (switch-to-buffer edit-buffer))) - -;;;###mh-autoload -(defun mh-next-button (&optional backward-flag) - "Go to the next button. - -If the end of the buffer is reached then the search wraps over to -the start of the buffer. - -If an optional prefix argument BACKWARD-FLAG is given, the cursor -will move to the previous button." - (interactive (list current-prefix-arg)) - (unless mh-showing-mode - (mh-show)) - (mh-in-show-buffer (mh-show-buffer) - (mh-goto-next-button backward-flag))) - -;;;###mh-autoload -(defun mh-next-undeleted-msg (&optional count wait-after-complaining-flag) - "Display next message. - -This command can be given a prefix argument COUNT to specify how -many unread messages to skip. - -In a program, pause for a second after printing message if we are -at the last undeleted message and optional argument -WAIT-AFTER-COMPLAINING-FLAG is non-nil." - (interactive "p") - (setq mh-next-direction 'forward) - (forward-line 1) - (cond ((re-search-forward mh-scan-good-msg-regexp nil t count) - (beginning-of-line) - (mh-maybe-show)) - (t (forward-line -1) - (message "No more undeleted messages") - (if wait-after-complaining-flag (sit-for 1))))) - -;;;###mh-autoload -(defun mh-next-unread-msg (&optional count) - "Display next unread message. - -This command can be given a prefix argument COUNT to specify how -many unread messages to skip." - (interactive "p") - (unless (> count 0) - (error "The function `mh-next-unread-msg' expects positive argument")) - (setq count (1- count)) - (let ((unread-sequence (reverse (cdr (assoc mh-unseen-seq mh-seq-list)))) - (cur-msg (mh-get-msg-num nil))) - (cond ((and (not cur-msg) (not (bobp)) - ;; If we are at the end of the buffer back up one line and go - ;; to unread message after that. - (progn - (forward-line -1) - (setq cur-msg (mh-get-msg-num nil))) - nil)) - ((or (null unread-sequence) (not cur-msg)) - ;; No unread message or there aren't any messages in buffer... - (message "No more unread messages")) - ((progn - ;; Skip messages - (while (and unread-sequence (>= cur-msg (car unread-sequence))) - (setq unread-sequence (cdr unread-sequence))) - (while (> count 0) - (setq unread-sequence (cdr unread-sequence)) - (setq count (1- count))) - (not (car unread-sequence))) - (message "No more unread messages")) - (t (cl-loop for msg in unread-sequence - when (mh-goto-msg msg t) return nil - finally (message "No more unread messages")))))) - -;;;###mh-autoload -(defun mh-page-msg (&optional lines) - "Display next page in message. - -You can give this command a prefix argument that specifies the -number of LINES to scroll. This command will also show the next -undeleted message if it is used at the bottom of a message." - (interactive "P") - (if mh-showing-mode - (if mh-page-to-next-msg-flag - (if (equal mh-next-direction 'backward) - (mh-previous-undeleted-msg) - (mh-next-undeleted-msg)) - (if (mh-in-show-buffer (mh-show-buffer) - (pos-visible-in-window-p (point-max))) - (progn - (message - "End of message (Type %s to read %s undeleted message)" - (single-key-description last-input-event) - (if (equal mh-next-direction 'backward) - "previous" - "next")) - (setq mh-page-to-next-msg-flag t)) - (scroll-other-window lines))) - (mh-show))) - -;;;###mh-autoload -(defun mh-prev-button () - "Go to the previous button. - -If the beginning of the buffer is reached then the search wraps -over to the end of the buffer." - (interactive) - (mh-next-button t)) - -;;;###mh-autoload -(defun mh-previous-page (&optional lines) - "Display next page in message. - -You can give this command a prefix argument that specifies the -number of LINES to scroll." - (interactive "P") - (mh-in-show-buffer (mh-show-buffer) - (scroll-down lines))) - -;;;###mh-autoload -(defun mh-previous-undeleted-msg (&optional count wait-after-complaining-flag) - "Display previous message. - -This command can be given a prefix argument COUNT to specify how -many unread messages to skip. - -In a program, pause for a second after printing message if we are -at the last undeleted message and optional argument -WAIT-AFTER-COMPLAINING-FLAG is non-nil." - (interactive "p") - (setq mh-next-direction 'backward) - (beginning-of-line) - (cond ((re-search-backward mh-scan-good-msg-regexp nil t count) - (mh-maybe-show)) - (t (message "No previous undeleted message") - (if wait-after-complaining-flag (sit-for 1))))) - -;;;###mh-autoload -(defun mh-previous-unread-msg (&optional count) - "Display previous unread message. - -This command can be given a prefix argument COUNT to specify how -many unread messages to skip." - (interactive "p") - (unless (> count 0) - (error "The function `mh-previous-unread-msg' expects positive argument")) - (setq count (1- count)) - (let ((unread-sequence (cdr (assoc mh-unseen-seq mh-seq-list))) - (cur-msg (mh-get-msg-num nil))) - (cond ((and (not cur-msg) (not (bobp)) - ;; If we are at the end of the buffer back up one line and go - ;; to unread message after that. - (progn - (forward-line -1) - (setq cur-msg (mh-get-msg-num nil))) - nil)) - ((or (null unread-sequence) (not cur-msg)) - ;; No unread message or there aren't any messages in buffer... - (message "No more unread messages")) - ((progn - ;; Skip count messages... - (while (and unread-sequence (>= (car unread-sequence) cur-msg)) - (setq unread-sequence (cdr unread-sequence))) - (while (> count 0) - (setq unread-sequence (cdr unread-sequence)) - (setq count (1- count))) - (not (car unread-sequence))) - (message "No more unread messages")) - (t (cl-loop for msg in unread-sequence - when (mh-goto-msg msg t) return nil - finally (message "No more unread messages")))))) - -;;;###mh-autoload -(defun mh-quit () - "Quit the current MH-E folder. - -When you want to quit using MH-E and go back to editing, you can use -this command. This buries the buffers of the current MH-E folder and -restores the buffers that were present when you first ran -\\[mh-rmail]. It also removes any MH-E working buffers whose name -begins with \" *mh-\" or \"*MH-E \". You can later restore your MH-E -session by selecting the \"+inbox\" buffer or by running \\[mh-rmail] -again. - -The two hooks `mh-before-quit-hook' and `mh-quit-hook' are called by -this function. The former one is called before the quit occurs, so you -might use it to perform any MH-E operations; you could perform some -query and abort the quit or call `mh-execute-commands', for example. -The latter is not run in an MH-E context, so you might use it to -modify the window setup." - (interactive) - (run-hooks 'mh-before-quit-hook) - (let ((show-buffer (get-buffer mh-show-buffer))) - (when show-buffer - (kill-buffer show-buffer))) - (mh-update-sequences) - (mh-destroy-postponed-handles) - (bury-buffer (current-buffer)) - - ;; Delete all MH-E temporary and working buffers. - (dolist (buffer (buffer-list)) - (when (or (string-match "^ \\*mh-" (buffer-name buffer)) - (string-match "^\\*MH-E " (buffer-name buffer))) - (kill-buffer buffer))) - - (if mh-previous-window-config - (set-window-configuration mh-previous-window-config)) - (run-hooks 'mh-quit-hook)) - -;;;###mh-autoload -(defun mh-refile-msg (range folder &optional dont-update-last-destination-flag) - "Refile (output) RANGE into FOLDER. - -You are prompted for the folder name. Note that this command can also -be used to create folders. If you specify a folder that does not -exist, you will be prompted to create it. - -The hook `mh-refile-msg-hook' is called after a message is marked to -be refiled. - -Check the documentation of `mh-interactive-range' to see how RANGE is -read in interactive use. - -In a program, the variables `mh-last-destination' and -`mh-last-destination-folder' are not updated if -DONT-UPDATE-LAST-DESTINATION-FLAG is non-nil." - (interactive (list (mh-interactive-range "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-range () range - (mh-refile-a-msg nil folder)) - (when (looking-at mh-scan-refiled-msg-regexp) (mh-next-msg))) - -;;;###mh-autoload -(defun mh-refile-or-write-again (range &optional interactive-flag) - "Repeat last output command. - -If you are refiling several messages into the same folder, you -can use this command to repeat the last -refile (\\[mh-refile-msg]) or write (\\[mh-write-msg-to-file]). -You can use a range. - -Check the documentation of `mh-interactive-range' to see how RANGE is -read in interactive use. - -In a program, a non-nil INTERACTIVE-FLAG means that the function was -called interactively." - (interactive (list (mh-interactive-range "Redo") t)) - (if (null mh-last-destination) - (error "No previous refile or write")) - (cond ((eq (car mh-last-destination) 'refile) - (mh-refile-msg range (cdr mh-last-destination)) - (message "Destination folder: %s" (cdr mh-last-destination))) - (t - (mh-iterate-on-range msg range - (apply #'mh-write-msg-to-file msg (cdr mh-last-destination))) - (mh-next-msg interactive-flag)))) - -;;;###mh-autoload -(defun mh-rescan-folder (&optional range dont-exec-pending) - "Rescan folder\\. - -This command is useful to grab all messages in your \"+inbox\" after -processing your new mail for the first time. If you don't want to -rescan the entire folder, this command will accept a RANGE. Check the -documentation of `mh-interactive-range' to see how RANGE is read in -interactive use. - -This command will ask if you want to process refiles or deletes first -and then either run \\[mh-execute-commands] for you or undo the -pending refiles and deletes. - -In a program, the processing of outstanding commands is not performed -if DONT-EXEC-PENDING is non-nil." - (interactive (list (if current-prefix-arg - (mh-read-range "Rescan" mh-current-folder t nil t - mh-interpret-number-as-range-flag) - nil))) - (setq mh-next-direction 'forward) - (let ((threaded-flag (memq 'unthread mh-view-ops)) - (msg-num (mh-get-msg-num nil))) - (mh-scan-folder mh-current-folder (or range "all") dont-exec-pending) - ;; If there isn't a cur sequence, mh-scan-folder goes to the first message. - ;; Try to stay where we were. - (if (null (car (mh-seq-to-msgs 'cur))) - (mh-goto-msg msg-num t t)) - (cond (threaded-flag (mh-toggle-threads)) - (mh-index-data (mh-index-insert-folder-headers))))) - -(defun mh-show-mouse (event) - "Move point to mouse EVENT and show message." - (interactive "e") - (mouse-set-point event) - (mh-show)) - -;;;###mh-autoload -(defun mh-toggle-showing () - "Toggle between MH-Folder and MH-Folder Show modes. - -This command switches between MH-Folder mode and MH-Folder Show -mode. MH-Folder mode turns off the associated show buffer so that -you can perform operations on the messages quickly without -reading them. This is an excellent way to prune out your junk -mail or to refile a group of messages to another folder for later -examination." - (interactive) - (if mh-showing-mode - (mh-set-scan-mode) - (mh-show))) - -;;;###mh-autoload -(defun mh-undo (range) - "Undo pending deletes or refiles in RANGE. - -If you've deleted a message or refiled it, but changed your mind, -you can cancel the action before you've executed it. Use this -command to undo a refile on or deletion of a single message. You -can also undo refiles and deletes for messages that are found in -a given RANGE. - -Check the documentation of `mh-interactive-range' to see how -RANGE is read in interactive use." - (interactive (list (mh-interactive-range "Undo"))) - (cond ((numberp range) - (let ((original-position (point))) - (beginning-of-line) - (while (not (or (looking-at mh-scan-refiled-msg-regexp) - (looking-at mh-scan-deleted-msg-regexp) - (looking-at mh-scan-blocklisted-msg-regexp) - (looking-at mh-scan-allowlisted-msg-regexp) - (and (eq mh-next-direction 'forward) (bobp)) - (and (eq mh-next-direction 'backward) - (save-excursion (forward-line) (eobp))))) - (forward-line (if (eq mh-next-direction 'forward) -1 1))) - (if (or (looking-at mh-scan-refiled-msg-regexp) - (looking-at mh-scan-deleted-msg-regexp) - (looking-at mh-scan-blocklisted-msg-regexp) - (looking-at mh-scan-allowlisted-msg-regexp)) - (progn - (mh-undo-msg (mh-get-msg-num t)) - (mh-maybe-show)) - (goto-char original-position) - (error "Nothing to undo")))) - (t (mh-iterate-on-range () range - (mh-undo-msg nil)))) - (if (not (mh-outstanding-commands-p)) - (mh-set-folder-modified-p nil))) - -;;;###mh-autoload -(defun mh-visit-folder (folder &optional range index-data) - "Visit FOLDER. - -When you want to read the messages that you have refiled into folders, -use this command to visit the folder. You are prompted for the folder -name. - -The folder buffer will show just unseen messages if there are any; -otherwise, it will show all the messages in the buffer as long there -are fewer than `mh-large-folder' messages. If there are more, then you -are prompted for a range of messages to scan. - -You can provide a prefix argument in order to specify a RANGE of -messages to show when you visit the folder. In this case, regions are -not used to specify the range and `mh-large-folder' is ignored. Check -the documentation of `mh-interactive-range' to see how RANGE is read -in interactive use. - -Note that this command can also be used to create folders. If you -specify a folder that does not exist, you will be prompted to create -it. - -Do not call this function from outside MH-E; use \\[mh-rmail] instead. - -If, in a program, RANGE is nil (the default), then all messages in -FOLDER are displayed. If an index buffer is being created then -INDEX-DATA is used to initialize the index buffer specific data -structures." - (interactive (let ((folder-name (mh-prompt-for-folder "Visit" mh-inbox t))) - (list folder-name - (mh-read-range "Scan" folder-name t nil - current-prefix-arg - mh-interpret-number-as-range-flag)))) - (let ((config (current-window-configuration)) - (current-buffer (current-buffer)) - (threaded-view-flag mh-show-threads-flag)) - (delete-other-windows) - (when (get-buffer folder) - (with-current-buffer folder - (setq threaded-view-flag (memq 'unthread mh-view-ops)))) - (when index-data - (mh-make-folder folder) - (setq mh-index-data (car index-data) - mh-index-msg-checksum-map (make-hash-table :test #'equal) - mh-index-checksum-origin-map (make-hash-table :test #'equal)) - (mh-index-update-maps folder (cadr index-data)) - (mh-index-create-sequences)) - (mh-scan-folder folder (or range "all")) - (cond ((and threaded-view-flag - (save-excursion - (goto-char (point-min)) - (or (null mh-large-folder) - (not (equal (forward-line (1+ mh-large-folder)) 0)) - (and (message "Not threading since the number of messages exceeds `mh-large-folder'") - nil)))) - (mh-toggle-threads)) - (mh-index-data - (mh-index-insert-folder-headers))) - (unless (eq current-buffer (current-buffer)) - (setq mh-previous-window-config config))) - nil) - -;;;###mh-autoload -(defun mh-write-msg-to-file (message file no-header) - "Append MESSAGE to end of FILE\\. - -You are prompted for the filename. If the file already exists, -the message is appended to it. You can also write the message to -the file without the header by specifying a prefix argument -NO-HEADER. Subsequent writes to the same file can be made with -the command \\[mh-refile-or-write-again]." - (interactive - (list (mh-get-msg-num t) - (let ((default-dir (if (eq 'write (car mh-last-destination-write)) - (file-name-directory - (car (cdr mh-last-destination-write))) - default-directory))) - (read-file-name (format "Save message%s in file: " - (if current-prefix-arg " body" "")) - default-dir - (if (eq 'write (car mh-last-destination-write)) - (car (cdr mh-last-destination-write)) - (expand-file-name "mail.out" default-dir)))) - current-prefix-arg)) - (let ((msg-file-to-output (mh-msg-filename message)) - (output-file (mh-expand-file-name file))) - (setq mh-last-destination (list 'write file (if no-header 'no-header)) - mh-last-destination-write mh-last-destination) - (with-current-buffer (get-buffer-create mh-temp-buffer) - (erase-buffer) - (insert-file-contents msg-file-to-output) - (goto-char (point-min)) - (if no-header (search-forward "\n\n")) - (append-to-file (point) (point-max) output-file)))) - -;;;###mh-autoload -(defun mh-update-sequences () - "Flush MH-E's state out to MH. - -This function updates the sequence specified by your -\"Unseen-Sequence:\" profile component, \"cur\", and the sequence -listed by the `mh-tick-seq' option which is \"tick\" by default. -The message at the cursor is used for \"cur\"." - (interactive) - ;; mh-update-sequences is the opposite of mh-read-folder-sequences, - ;; which updates MH-E's state from MH. - (let ((folder-set (mh-update-unseen)) - (new-cur (mh-get-msg-num nil))) - (if new-cur - (let ((seq-entry (mh-find-seq 'cur))) - (mh-remove-cur-notation) - (if seq-entry - (setcdr seq-entry (list new-cur)) - (mh-add-msgs-to-seq (list new-cur) 'cur)) - (mh-define-sequence 'cur (list new-cur)) - (beginning-of-line) - (if (looking-at mh-scan-good-msg-regexp) - (mh-notate-cur))) - (or folder-set - (save-excursion - ;; psg - mh-current-folder is nil if mh-summary-height < 4 ! - ;; So I added this sanity check. - (if (stringp mh-current-folder) - (mh-exec-cmd-quiet t "folder" mh-current-folder "-fast") - (mh-exec-cmd-quiet t "folder" "-fast"))))))) - - - -;;; Support Routines - -(defun mh-get-new-mail (maildrop-name) - "Read new mail from MAILDROP-NAME into the current buffer. -Return in the current buffer." - (let ((point-before-inc (point)) - (folder mh-current-folder) - (new-mail-flag nil)) - (with-mh-folder-updating (t) - (if maildrop-name - (message "inc %s -file %s..." folder maildrop-name) - (message "inc %s..." folder)) - (setq mh-next-direction 'forward) - (goto-char (point-max)) - (mh-remove-cur-notation) - (let ((start-of-inc (point))) - (if maildrop-name - ;; I think MH 5 used "-ms-file" instead of "-file", - ;; which would make inc'ing from maildrops fail. - (mh-exec-cmd-output mh-inc-prog nil folder - (mh-scan-format) - "-file" (expand-file-name maildrop-name) - "-width" (window-width) - "-truncate") - (mh-exec-cmd-output mh-inc-prog nil - (mh-scan-format) - "-width" (window-width))) - (if maildrop-name - (message "inc %s -file %s...done" folder maildrop-name) - (message "inc %s...done" folder)) - (goto-char start-of-inc) - (cond ((save-excursion - (re-search-forward "^inc: no mail" nil t)) - (message "No new mail%s%s" (if maildrop-name " in " "") - (if maildrop-name maildrop-name ""))) - ((and (when mh-folder-view-stack - (let ((saved-text (buffer-substring-no-properties - start-of-inc (point-max)))) - (delete-region start-of-inc (point-max)) - (unwind-protect (mh-widen t) - (mh-remove-cur-notation) - (goto-char (point-max)) - (setq start-of-inc (point)) - (insert saved-text) - (goto-char start-of-inc)))) - nil)) - ((re-search-forward "^inc:" nil t) ; Error messages - (error "Error incorporating mail")) - ((and - (equal mh-scan-format-file t) - mh-adaptive-cmd-note-flag - ;; Have we reached an edge condition? - (save-excursion - (re-search-forward mh-scan-msg-overflow-regexp nil 0 1)) - (setq start-of-inc (mh-generate-new-cmd-note folder)) - nil)) - (t - (setq new-mail-flag t))) - (keep-lines mh-scan-valid-regexp) ; Flush random scan lines - (let* ((sequences (mh-read-folder-sequences folder t)) - (new-cur (assoc 'cur sequences)) - (new-unseen (assoc mh-unseen-seq sequences))) - (unless (assoc 'cur mh-seq-list) - (push (list 'cur) mh-seq-list)) - (unless (assoc mh-unseen-seq mh-seq-list) - (push (list mh-unseen-seq) mh-seq-list)) - (setcdr (assoc 'cur mh-seq-list) (cdr new-cur)) - (setcdr (assoc mh-unseen-seq mh-seq-list) (cdr new-unseen))) - (when (equal (point-max) start-of-inc) - (mh-notate-cur)) - (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)) - (goto-char point-before-inc)) - (mh-notate-user-sequences (cons start-of-inc (point-max))))))) - -(defun mh-generate-new-cmd-note (folder) - "Fix the `mh-cmd-note' value for this FOLDER. - -After doing an `mh-get-new-mail' operation in this FOLDER, at least -one line that looks like a truncated message number was found. - -Remove the text added by the last `mh-inc' command. It should be the -messages cur-last. Call `mh-set-cmd-note', adjusting the notation -column with the width of the largest message number in FOLDER. - -Reformat the message number width on each line in the buffer and trim -the line length to fit in the window. - -Rescan the FOLDER in the range cur-last in order to display the -messages that were removed earlier. They should all fit in the scan -line now with no message truncation." - (save-excursion - (let ((maxcol (1- (window-width))) - (old-cmd-note mh-cmd-note) - mh-cmd-note-fmt - msgnum) - ;; Nuke all of the lines just added by the last inc - (delete-char (- (point-max) (point))) - ;; Update the current buffer to reflect the new mh-cmd-note - ;; value needed to display messages. - (mh-set-cmd-note (mh-msg-num-width-to-column (mh-msg-num-width folder))) - (setq mh-cmd-note-fmt (concat "%" (format "%d" mh-cmd-note) "d")) - ;; Cleanup the messages that are in the buffer right now - (goto-char (point-min)) - (cond ((memq 'unthread mh-view-ops) - (mh-thread-add-spaces (- mh-cmd-note old-cmd-note))) - (t (while (re-search-forward (mh-scan-msg-number-regexp) nil 0 1) - ;; reformat the number to fix in mh-cmd-note columns - (setq msgnum (string-to-number - (buffer-substring - (match-beginning 1) (match-end 1)))) - (replace-match (format mh-cmd-note-fmt msgnum)) - ;; trim the line to fix in the window - (end-of-line) - (let ((eol (point))) - (move-to-column maxcol) - (if (<= (point) eol) - (delete-char (- eol (point)))))))) - ;; now re-read the lost messages - (goto-char (point-max)) - (prog1 (point) - (mh-regenerate-headers "cur-last" t))))) - -;;;###mh-autoload -(defun mh-goto-cur-msg (&optional minimal-changes-flag) - "Position the cursor at the current message. -When optional argument MINIMAL-CHANGES-FLAG is non-nil, the -function doesn't recenter the folder buffer." - (let ((cur-msg (car (mh-seq-to-msgs 'cur)))) - (cond ((and cur-msg - (mh-goto-msg cur-msg t t)) - (unless minimal-changes-flag - (mh-notate-cur) - (mh-recenter 0) - (mh-maybe-show cur-msg))) - (t - (setq overlay-arrow-position nil) - (message "No current message"))))) - -;;;###mh-autoload -(defun mh-recenter (arg) - "Like recenter but with three improvements: - -- At the end of the buffer it tries to show fewer empty lines. - -- operates only if the current buffer is in the selected window. - (Commands like `save-some-buffers' can make this false.) - -- nil ARG means recenter as if prefix argument had been given." - (cond ((not (eq (get-buffer-window (current-buffer)) (selected-window))) - nil) - ((= (point-max) (save-excursion - (forward-line (- (/ (window-height) 2) 2)) - (point))) - (let ((lines-from-end 2)) - (save-excursion - (while (> (point-max) (progn (forward-line) (point))) - (cl-incf lines-from-end))) - (recenter (- lines-from-end)))) - ;; '(4) is the same as C-u prefix argument. - (t (recenter (or arg '(4)))))) - -(defun mh-update-unseen () - "Synchronize the unseen sequence with MH. -Return non-nil if the MH folder was set. -The hook `mh-unseen-updated-hook' is called after the unseen sequence -is updated." - (if mh-seen-list - (let* ((unseen-seq (mh-find-seq mh-unseen-seq)) - (unseen-msgs (mh-seq-msgs unseen-seq))) - (if unseen-msgs - (progn - (mh-undefine-sequence mh-unseen-seq mh-seen-list) - (run-hooks 'mh-unseen-updated-hook) - (while mh-seen-list - (setq unseen-msgs (delq (car mh-seen-list) unseen-msgs)) - (setq mh-seen-list (cdr mh-seen-list))) - (setcdr unseen-seq unseen-msgs) - t) ;since we set the folder - (setq mh-seen-list nil))))) - -;;;###mh-autoload -(defun mh-outstanding-commands-p () - "Return non-nil if there are outstanding deletes or refiles." - (save-excursion - (when (eq major-mode 'mh-show-mode) - (set-buffer mh-show-folder-buffer)) - (or mh-delete-list mh-refile-list mh-blocklist mh-allowlist))) - -;;;###mh-autoload -(defun mh-set-folder-modified-p (flag) - "Mark current folder as modified or unmodified according to FLAG." - (set-buffer-modified-p flag)) - -(defun mh-process-commands (folder) - "Process outstanding commands for FOLDER. - -This function runs `mh-before-commands-processed-hook' before the -commands are processed and `mh-after-commands-processed-hook' -after the commands are processed." - (message "Processing deletes and refiles for %s..." folder) - (set-buffer folder) - (with-mh-folder-updating (nil) - ;; Run the before hook -- the refile and delete lists are still valid - (run-hooks 'mh-before-commands-processed-hook) - - ;; Update the unseen sequence if it exists - (mh-update-unseen) - - (let ((redraw-needed-flag mh-index-data) - (folders-changed (list mh-current-folder)) - (seq-map (and - (or (and mh-refile-list mh-refile-preserves-sequences-flag) - (and mh-allowlist - mh-allowlist-preserves-sequences-flag)) - (mh-create-sequence-map mh-seq-list))) - (dest-map (and mh-refile-list mh-refile-preserves-sequences-flag - (make-hash-table))) - (allow-map (and mh-allowlist mh-allowlist-preserves-sequences-flag - (make-hash-table)))) - ;; Remove invalid scan lines if we are in an index folder and then remove - ;; the real messages - (when mh-index-data - (mh-index-delete-folder-headers) - (setq folders-changed - (append folders-changed (mh-index-execute-commands)))) - - ;; Then refile messages - (mapc (lambda (folder-msg-list) - (let* ((dest-folder (symbol-name (car folder-msg-list))) - (last (car (mh-translate-range dest-folder "last"))) - (msgs (cdr folder-msg-list))) - (push dest-folder folders-changed) - (setq redraw-needed-flag t) - (apply #'mh-exec-cmd - "refile" "-src" folder dest-folder - (mh-coalesce-msg-list msgs)) - (mh-delete-scan-msgs msgs) - ;; Preserve sequences in destination folder... - (when mh-refile-preserves-sequences-flag - (clrhash dest-map) - (cl-loop - for i from (1+ (or last 0)) - for msg in (sort (copy-sequence msgs) #'<) - do (cl-loop for seq-name in (gethash msg seq-map) - do (push i (gethash seq-name dest-map)))) - (maphash - #'(lambda (seq msgs) - ;; Can't be run in the background, since the - ;; current folder is changed by mark this could - ;; lead to a race condition with the next refile. - (apply #'mh-exec-cmd "mark" - "-sequence" (symbol-name seq) dest-folder - "-add" (mapcar #'(lambda (x) (format "%s" x)) - (mh-coalesce-msg-list msgs)))) - dest-map)))) - mh-refile-list) - (setq mh-refile-list ()) - - ;; Now delete messages - (cond (mh-delete-list - (setq redraw-needed-flag t) - (apply #'mh-exec-cmd "rmm" folder - (mh-coalesce-msg-list mh-delete-list)) - (mh-delete-scan-msgs mh-delete-list) - (setq mh-delete-list nil))) - - ;; Blocklist messages. - (when mh-blocklist - (let ((msg-list (mh-coalesce-msg-list mh-blocklist)) - (dest (mh-junk-blocklist-disposition))) - (mh-junk-process-blocklist mh-blocklist) - ;; TODO I wonder why mh-exec-cmd is used instead of the following: - ;; (mh-refile-a-msg nil (intern dest)) - ;; (mh-delete-a-msg nil))) - (if (null dest) - (apply #'mh-exec-cmd "rmm" folder msg-list) - (apply #'mh-exec-cmd "refile" "-src" folder dest msg-list) - (push dest folders-changed)) - (setq redraw-needed-flag t) - (mh-delete-scan-msgs mh-blocklist) - (setq mh-blocklist nil))) - - ;; Allowlist messages. - (when mh-allowlist - (let ((msg-list (mh-coalesce-msg-list mh-allowlist)) - (last (car (mh-translate-range mh-inbox "last")))) - (mh-junk-process-allowlist mh-allowlist) - (apply #'mh-exec-cmd "refile" "-src" folder mh-inbox msg-list) - (push mh-inbox folders-changed) - (setq redraw-needed-flag t) - (mh-delete-scan-msgs mh-allowlist) - (when mh-allowlist-preserves-sequences-flag - (clrhash allow-map) - (cl-loop for i from (1+ (or last 0)) - for msg in (sort (copy-sequence mh-allowlist) #'<) - do (cl-loop for seq-name in (gethash msg seq-map) - do (push i (gethash seq-name allow-map)))) - (maphash - (lambda (seq msgs) - ;; Can't be run in background, since the current - ;; folder is changed by mark this could lead to a - ;; race condition with the next refile/allowlist. - (apply #'mh-exec-cmd "mark" - "-sequence" (symbol-name seq) mh-inbox - "-add" (mapcar #'(lambda(x) (format "%s" x)) - (mh-coalesce-msg-list msgs)))) - allow-map)) - (setq mh-allowlist nil))) - - ;; Don't need to remove sequences since delete and refile do so. - ;; Mark cur message - (if (> (buffer-size) 0) - (mh-define-sequence 'cur (list (or (mh-get-msg-num nil) "last")))) - - ;; Redraw folder buffer if needed - (when (and redraw-needed-flag) - (when (mh-speed-flists-active-p) - (apply #'mh-speed-flists t folders-changed)) - (cond ((memq 'unthread mh-view-ops) (mh-thread-inc folder (point-max))) - (mh-index-data (mh-index-insert-folder-headers)))) - - (and (buffer-file-name (get-buffer mh-show-buffer)) - (not (file-exists-p (buffer-file-name (get-buffer mh-show-buffer)))) - ;; If "inc" were to put a new msg in this file, - ;; we would not notice, so mark it invalid now. - (mh-invalidate-show-buffer)) - - (setq mh-seq-list (mh-read-folder-sequences mh-current-folder nil)) - (mh-remove-all-notation) - (mh-notate-user-sequences) - - ;; Run the after hook -- now folders-changed is valid, - ;; but not the lists of specific messages. - (let ((mh-folders-changed folders-changed)) - (run-hooks 'mh-after-commands-processed-hook))) - - (message "Processing deletes and refiles for %s...done" folder))) - -(defun mh-delete-scan-msgs (msgs) - "Delete the scan listing lines for MSGS." - (save-excursion - (while msgs - (when (mh-goto-msg (car msgs) t t) - (when (memq 'unthread mh-view-ops) - (mh-thread-forget-message (car msgs))) - (mh-delete-line 1)) - (setq msgs (cdr msgs))))) - -(defun mh-set-scan-mode () - "Display the scan listing buffer, but do not show a message." - (if (get-buffer mh-show-buffer) - (delete-windows-on mh-show-buffer)) - (mh-showing-mode 0) - (force-mode-line-update) - (if mh-recenter-summary-flag - (mh-recenter nil))) - -;;;###mh-autoload -(defun mh-make-folder-mode-line (&optional _ignored) - "Set the fields of the mode line for a folder buffer. -The optional argument is now obsolete and IGNORED. It used to be -used to pass in what is now stored in the buffer-local variable -`mh-mode-line-annotation'." - (save-excursion - (save-window-excursion - (mh-first-msg) - (let ((new-first-msg-num (mh-get-msg-num nil))) - (when (or (not (memq 'unthread mh-view-ops)) - (null mh-first-msg-num) - (null new-first-msg-num) - (< new-first-msg-num mh-first-msg-num)) - (setq mh-first-msg-num new-first-msg-num))) - (mh-last-msg) - (let ((new-last-msg-num (mh-get-msg-num nil))) - (when (or (not (memq 'unthread mh-view-ops)) - (null mh-last-msg-num) - (null new-last-msg-num) - (> new-last-msg-num mh-last-msg-num)) - (setq mh-last-msg-num new-last-msg-num))) - (setq mh-msg-count (if mh-first-msg-num - (count-lines (point-min) (point-max)) - 0)) - (setq mode-line-buffer-identification - (list (format " {%%b%s} %s msg%s" - (if mh-mode-line-annotation - (format "/%s" mh-mode-line-annotation) - "") - (if (zerop mh-msg-count) - "no" - (format "%d" mh-msg-count)) - (if (zerop mh-msg-count) - "s" - (cond ((> mh-msg-count 1) - (format "s (%d-%d)" mh-first-msg-num - mh-last-msg-num)) - (mh-first-msg-num - (format " (%d)" mh-first-msg-num)) - ("")))))) - (mh-logo-display)))) - -;;;###mh-autoload -(defun mh-scan-folder (folder range &optional dont-exec-pending) - "Scan FOLDER over RANGE. - -After the scan is performed, switch to the buffer associated with -FOLDER. - -Check the documentation of `mh-interactive-range' to see how RANGE is -read in interactive use. - -The processing of outstanding commands is not performed if -DONT-EXEC-PENDING is non-nil." - (when (stringp range) - (setq range (delete "" (split-string range "[ \t\n]")))) - (cond ((null (get-buffer folder)) - (mh-make-folder folder)) - (t - (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)) - (if (equal range "all") - (message "Folder %s is empty" folder) - (message "No messages in %s, range %s" folder range)) - (mh-goto-cur-msg)) - (when (mh-outstanding-commands-p) - (mh-notate-deleted-and-refiled))) - -;;;###mh-autoload -(defun mh-process-or-undo-commands (folder) - "If FOLDER has outstanding commands, then either process or discard them. -Called by functions like `mh-sort-folder', so also invalidate -show buffer." - (set-buffer folder) - (if (mh-outstanding-commands-p) - (if (or mh-do-not-confirm-flag - (y-or-n-p - "Process outstanding deletes and refiles? ")) - (mh-process-commands folder) - (set-buffer folder) - (mh-undo-folder))) - (mh-update-unseen) - (mh-invalidate-show-buffer)) - -;;;###mh-autoload -(defun mh-regenerate-headers (range &optional update) - "Scan folder over RANGE. -If UPDATE, append the scan lines, otherwise replace." - (let ((folder mh-current-folder) - (range (if (and range (atom range)) (list range) range)) - scan-start) - (message "Scanning %s..." folder) - (mh-remove-all-notation) - (with-mh-folder-updating (nil) - (if update - (goto-char (point-max)) - (delete-region (point-min) (point-max)) - (if mh-adaptive-cmd-note-flag - (mh-set-cmd-note (mh-msg-num-width-to-column (mh-msg-num-width - folder))))) - (setq scan-start (point)) - (apply #'mh-exec-cmd-output - mh-scan-prog nil - (mh-scan-format) - "-noclear" "-noheader" - "-width" (window-width) - folder range) - (goto-char scan-start) - (cond ((or (looking-at "scan: no messages in") - (looking-at "scan: message set .* does not exist") - (looking-at "scan: bad message list ")) - (keep-lines mh-scan-valid-regexp)) ; flush common scan output - ((looking-at "scan: ")) ; keep unexpected error messages - (t - (keep-lines mh-scan-valid-regexp))) ; flush random scan output - (setq mh-seq-list (mh-read-folder-sequences folder nil)) - (mh-notate-user-sequences) - (or update - (setq mh-mode-line-annotation - (if (equal range '("all")) - nil - mh-partial-folder-mode-line-annotation))) - (mh-make-folder-mode-line)) - (message "Scanning %s...done" folder))) - -;;;###mh-autoload -(defun mh-reset-threads-and-narrowing () - "Reset all variables pertaining to threads and narrowing. -Also removes all content from the folder buffer." - (setq mh-view-ops ()) - (setq mh-folder-view-stack ()) - (setq mh-thread-scan-line-map-stack ()) - (let ((buffer-read-only nil)) (erase-buffer))) - -(defun mh-make-folder (name) - "Create a new mail folder called NAME. -Make it the current folder." - (switch-to-buffer name) - (setq buffer-read-only nil) - (erase-buffer) - (if mh-adaptive-cmd-note-flag - (mh-set-cmd-note (mh-msg-num-width-to-column (mh-msg-num-width name)))) - (setq buffer-read-only t) - (mh-folder-mode) - (mh-set-folder-modified-p nil) - (setq buffer-file-name mh-folder-filename) - (when (and (not mh-index-data) - (file-exists-p (concat buffer-file-name mh-index-data-file))) - (mh-index-read-data)) - (mh-make-folder-mode-line)) - -;;;###mh-autoload -(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 wait-after-complaining-flag) - (mh-previous-undeleted-msg 1 wait-after-complaining-flag))) - -;;;###mh-autoload -(defun mh-prompt-for-refile-folder () - "Prompt the user for a folder in which the message should be filed. -The folder is returned as a string. - -The default folder name is generated by the option -`mh-default-folder-for-message-function' if it is non-nil or -`mh-folder-from-address'." - (mh-prompt-for-folder - "Destination" - (let ((refile-file (ignore-errors (mh-msg-filename (mh-get-msg-num t))))) - (if (null refile-file) "" - (with-current-buffer (get-buffer-create mh-temp-buffer) - (erase-buffer) - (insert-file-contents refile-file) - (or (and mh-default-folder-for-message-function - (let ((buffer-file-name refile-file)) - (funcall mh-default-folder-for-message-function))) - (mh-folder-from-address) - (and (eq 'refile (car mh-last-destination-folder)) - (symbol-name (cdr mh-last-destination-folder))) - "")))) - t)) - -;;;###mh-autoload -(defun mh-folder-from-address () - "Derive folder name from sender. - -The name of the folder is derived as follows: - - a) The folder name associated with the first address found in - the list `mh-default-folder-list' is used. Each element in - this list contains a \"Check Recipient\" item. If this item is - turned on, then the address is checked against the recipient - instead of the sender. This is useful for mailing lists. - - b) An alias prefixed by `mh-default-folder-prefix' - corresponding to the address is used. The prefix is used to - prevent clutter in your mail directory. - -Return nil if a folder name was not derived, or if the variable -`mh-default-folder-must-exist-flag' is t and the folder does not -exist." - ;; Loop for all entries in mh-default-folder-list - (save-restriction - (goto-char (point-min)) - (re-search-forward "\n\n" nil 'limit) - (narrow-to-region (point-min) (point)) - (let ((to/cc (concat (or (message-fetch-field "to") "") ", " - (or (message-fetch-field "cc") ""))) - (from (or (message-fetch-field "from") "")) - folder-name) - (setq folder-name - (cl-loop for list in mh-default-folder-list - when (string-match (nth 0 list) - (if (nth 2 list) to/cc from)) - return (nth 1 list) - finally return nil)) - - ;; 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 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)))) - -;;;###mh-autoload -(defun mh-delete-a-msg (message) - "Delete MESSAGE. -If MESSAGE is nil then the message at point is deleted. -The hook `mh-delete-msg-hook' is called after you mark a message -for deletion. For example, a past maintainer of MH-E used this -once when he kept statistics on his mail usage." - (save-excursion - (if (numberp message) - (mh-goto-msg message nil t) - (beginning-of-line) - (setq message (mh-get-msg-num t))) - (if (looking-at mh-scan-refiled-msg-regexp) - (error "Message %d is refiled; undo refile before deleting" message)) - (if (looking-at mh-scan-blocklisted-msg-regexp) - (error "Message %d is blocklisted; undo before deleting" message)) - (if (looking-at mh-scan-allowlisted-msg-regexp) - (error "Message %d is allowlisted; undo before deleting" message)) - (if (looking-at mh-scan-deleted-msg-regexp) - nil - (mh-set-folder-modified-p t) - (setq mh-delete-list (cons message mh-delete-list)) - (mh-notate nil mh-note-deleted mh-cmd-note) - (run-hooks 'mh-delete-msg-hook)))) - -;;;###mh-autoload -(defun mh-refile-a-msg (message folder) - "Refile MESSAGE in FOLDER. -If MESSAGE is nil then the message at point is refiled. -Folder is a symbol, not a string. -The hook `mh-refile-msg-hook' is called after a message is marked to -be refiled." - (save-excursion - (if (numberp message) - (mh-goto-msg message nil t) - (beginning-of-line) - (setq message (mh-get-msg-num t))) - (cond ((looking-at mh-scan-deleted-msg-regexp) - (error "Message %d is deleted; undo delete before moving" message)) - ((looking-at mh-scan-blocklisted-msg-regexp) - (error "Message %d is blocklisted; undo before moving" message)) - ((looking-at mh-scan-allowlisted-msg-regexp) - (error "Message %d is allowlisted; undo before moving" message)) - ((looking-at mh-scan-refiled-msg-regexp) - (if (y-or-n-p - (format "Message %d already refiled; copy to %s as well? " - message folder)) - (mh-exec-cmd "refile" (mh-get-msg-num t) "-link" - "-src" mh-current-folder - (symbol-name folder)) - (message "Message not copied"))) - (t - (mh-set-folder-modified-p t) - (cond ((null (assoc folder mh-refile-list)) - (push (list folder message) mh-refile-list)) - ((not (member message (cdr (assoc folder mh-refile-list)))) - (push message (cdr (assoc folder mh-refile-list))))) - (mh-notate nil mh-note-refiled mh-cmd-note) - (run-hooks 'mh-refile-msg-hook))))) - -(defun mh-undo-msg (msg) - "Undo the deletion, refile, block- or allowlisting of one MSG. -If MSG is nil then act on the message at point" - (save-excursion - (if (numberp msg) - (mh-goto-msg msg t t) - (beginning-of-line) - (setq msg (mh-get-msg-num t))) - (cond ((memq msg mh-delete-list) - (setq mh-delete-list (delq msg mh-delete-list))) - ((memq msg mh-blocklist) - (setq mh-blocklist (delq msg mh-blocklist))) - ((memq msg mh-allowlist) - (setq mh-allowlist (delq msg mh-allowlist))) - (t - (dolist (folder-msg-list mh-refile-list) - (setf (cdr folder-msg-list) (remove msg (cdr folder-msg-list)))) - (setq mh-refile-list (cl-loop for x in mh-refile-list - unless (null (cdr x)) collect x)))) - (mh-notate nil ? mh-cmd-note))) - -;;;###mh-autoload -(defun mh-msg-filename (msg &optional folder) - "Return the file name of MSG in FOLDER (default current folder)." - (expand-file-name (int-to-string msg) - (if folder - (mh-expand-file-name folder) - mh-folder-filename))) - -(provide 'mh-folder) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-folder.el ends here diff --git a/lisp/mh-e/mh-funcs.el b/lisp/mh-e/mh-funcs.el deleted file mode 100644 index bb3e67467d5..00000000000 --- a/lisp/mh-e/mh-funcs.el +++ /dev/null @@ -1,372 +0,0 @@ -;;; mh-funcs.el --- MH-E functions not everyone will use right away -*- lexical-binding: t; -*- - -;; Copyright (C) 1993, 1995, 2001-2024 Free Software Foundation, Inc. - -;; Author: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Putting these functions in a separate file lets MH-E start up faster, -;; since less Lisp code needs to be loaded all at once. - -;; Please add the functions in alphabetical order. If only one or two -;; small support routines are needed, place them with the function; -;; otherwise, create a separate section for them. - -;;; Code: - -(require 'mh-e) -(require 'mh-scan) - -;;;###mh-autoload -(defun mh-burst-digest () - "Break up digest into separate messages\\. - -This command uses the MH command \"burst\" to break out each -message in the digest into its own message. Using this command, -you can quickly delete unwanted messages, like this: Once the -digest is split up, toggle out of MH-Folder Show mode with -\\[mh-toggle-showing] so that the scan lines fill the screen and -messages aren't displayed. Then use \\[mh-delete-msg] to quickly -delete messages that you don't want to read (based on the -\"Subject:\" header field). You can also burst the digest to -reply directly to the people who posted the messages in the -digest. One problem you may encounter is that the \"From:\" -header fields are preceded with a \">\" so that your reply can't -create the \"To:\" field correctly. In this case, you must -correct the \"To:\" field yourself." - (interactive) - (let ((digest (mh-get-msg-num t))) - (mh-process-or-undo-commands mh-current-folder) - (mh-set-folder-modified-p t) ; lock folder while bursting - (message "Bursting digest...") - (mh-exec-cmd "burst" mh-current-folder digest "-inplace") - (with-mh-folder-updating (t) - (beginning-of-line) - (delete-region (point) (point-max))) - (mh-regenerate-headers (format "%d-last" digest) t) - (mh-goto-cur-msg) - (message "Bursting digest...done"))) - -;;;###mh-autoload -(defun mh-copy-msg (range folder) - "Copy RANGE to FOLDER\\. - -If you wish to copy a message to another folder, you can use this -command (see the \"-link\" argument to \"refile\"). Like the -command \\[mh-refile-msg], this command prompts you for the name -of the target folder and you can specify a range. Note that -unlike the command \\[mh-refile-msg], the copy takes place -immediately. The original copy remains in the current folder. - -Check the documentation of `mh-interactive-range' to see how -RANGE is read in interactive use." - (interactive (list (mh-interactive-range "Copy") - (mh-prompt-for-folder "Copy to" "" t))) - (let ((msg-list (let ((result ())) - (mh-iterate-on-range msg range - (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))) - -;;;###mh-autoload -(defun mh-kill-folder () - "Remove folder. - -Remove all of the messages (files) within the current folder, and -then remove the folder (directory) itself. - -Run the abnormal hook `mh-kill-folder-suppress-prompt-functions'. -The hook functions are called with no arguments and should return -a non-nil value to suppress the normal prompt when you remove a -folder. This is useful for folders that are easily regenerated." - (interactive) - (if (or (run-hook-with-args-until-success - 'mh-kill-folder-suppress-prompt-functions) - (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)) - (mh-set-folder-modified-p t) ; lock folder to kill it - (mh-exec-cmd-daemon "rmf" 'mh-rmf-daemon folder) - (when (and (boundp 'speedbar-buffer) speedbar-buffer) - (mh-speed-invalidate-map folder)) - (mh-remove-from-sub-folders-cache folder) - (mh-set-folder-modified-p nil) ; so kill-buffer doesn't complain - (if (and mh-show-buffer (get-buffer mh-show-buffer)) - (kill-buffer mh-show-buffer)) - (if (get-buffer folder) - (kill-buffer folder)) - (when window-config - (set-window-configuration window-config)) - (message "Folder %s removed" folder)) - (message "Folder not removed"))) - -(defun mh-rmf-daemon (_process output) - "The rmf PROCESS puts OUTPUT in temporary buffer. -Display the results only if something went wrong." - (set-buffer (get-buffer-create mh-temp-buffer)) - (insert-before-markers output) - (when (save-excursion - (goto-char (point-min)) - (re-search-forward "^rmf: " (point-max) t)) - (display-buffer mh-temp-buffer))) - -;; Shush compiler. -(defvar view-exit-action) - -;;;###mh-autoload -(defun mh-list-folders () - "List mail folders." - (interactive) - (let ((temp-buffer mh-folders-buffer)) - (with-output-to-temp-buffer temp-buffer - (with-current-buffer temp-buffer - (erase-buffer) - (message "Listing folders...") - (mh-exec-cmd-output "folders" t (if mh-recursive-folders-flag - "-recurse" - "-norecurse")) - (goto-char (point-min)) - (view-mode-enter) - (setq view-exit-action 'kill-buffer) - (message "Listing folders...done"))))) - -;;;###mh-autoload -(defun mh-pack-folder (range) - "Pack folder\\. - -This command packs the folder, removing gaps from the numbering -sequence. If you don't want to rescan the entire folder -afterward, this command will accept a RANGE. Check the -documentation of `mh-interactive-range' to see how RANGE is read -in interactive use. - -This command will ask if you want to process refiles or deletes -first and then either run \\[mh-execute-commands] for you or undo -the pending refiles and deletes. - -The hook `mh-pack-folder-hook' is run after the folder is packed; -see its documentation for variables it can use." - (interactive (list (if current-prefix-arg - (mh-read-range "Scan" mh-current-folder t nil t - mh-interpret-number-as-range-flag) - '("all")))) - (let ((threaded-flag (memq 'unthread mh-view-ops))) - (mh-pack-folder-1 range) - (mh-goto-cur-msg) - (when mh-index-data - (mh-index-update-maps mh-current-folder)) - (cond (threaded-flag (mh-toggle-threads)) - (mh-index-data (mh-index-insert-folder-headers)))) - (run-hooks 'mh-pack-folder-hook) - (message "Packing folder...done")) - -(defun mh-pack-folder-1 (range) - "Close and pack the current folder. - -Display RANGE after packing, or the entire folder if RANGE is nil." - (mh-process-or-undo-commands mh-current-folder) - (message "Packing folder...") - (mh-set-folder-modified-p t) ; lock folder while packing - (save-excursion - (mh-exec-cmd-quiet t "folder" mh-current-folder "-pack" - "-norecurse" "-fast")) - (mh-reset-threads-and-narrowing) - (mh-regenerate-headers range)) - -;;;###mh-autoload -(defun mh-page-digest () - "Display next message in digest." - (interactive) - (mh-in-show-buffer (mh-show-buffer) - ;; Go to top of screen (in case user moved point). - (move-to-window-line 0) - (let ((case-fold-search nil)) - ;; Search for blank line and then for From: - (or (and (search-forward "\n\n" nil t) - (re-search-forward "^From:" nil t)) - (error "No more messages in digest"))) - ;; Go back to previous blank line, then forward to the first non-blank. - (search-backward "\n\n" nil t) - (forward-line 2) - (mh-recenter 0))) - -;;;###mh-autoload -(defun mh-page-digest-backwards () - "Display previous message in digest." - (interactive) - (mh-in-show-buffer (mh-show-buffer) - ;; Go to top of screen (in case user moved point). - (move-to-window-line 0) - (let ((case-fold-search nil)) - (beginning-of-line) - (or (and (search-backward "\n\n" nil t) - (re-search-backward "^From:" nil t)) - (error "No previous message in digest"))) - ;; Go back to previous blank line, then forward to the first non-blank. - (if (search-backward "\n\n" nil t) - (forward-line 2)) - (mh-recenter 0))) - -;;;###mh-autoload -(defun mh-pipe-msg (command include-header) - "Pipe message through shell command COMMAND. - -You are prompted for the Unix command through which you wish to -run your message. If you give a prefix argument INCLUDE-HEADER to -this command, the message header is included in the text passed -to the command." - (interactive - (list (read-string "Shell command on message: ") current-prefix-arg)) - (let ((msg-file-to-pipe (mh-msg-filename (mh-get-msg-num t))) - (message-directory default-directory)) - (with-current-buffer (get-buffer-create mh-temp-buffer) - (erase-buffer) - (insert-file-contents msg-file-to-pipe) - (goto-char (point-min)) - (if (not include-header) (search-forward "\n\n")) - (let ((default-directory message-directory)) - (shell-command-on-region (point) (point-max) command nil))))) - -;;;###mh-autoload -(defun mh-sort-folder (&optional extra-args) - "Sort folder. - -By default, messages are sorted by date. The option -`mh-sortm-args' holds extra arguments to pass on to the command -\"sortm\" when a prefix argument EXTRA-ARGS is used." - (interactive "P") - (mh-process-or-undo-commands mh-current-folder) - (setq mh-next-direction 'forward) - (mh-set-folder-modified-p t) ; lock folder while sorting - (message "Sorting folder...") - (let ((threaded-flag (memq 'unthread mh-view-ops))) - (mh-exec-cmd "sortm" mh-current-folder (if extra-args mh-sortm-args)) - (when mh-index-data - (mh-index-update-maps mh-current-folder)) - (message "Sorting folder...done") - (mh-scan-folder mh-current-folder "all") - (cond (threaded-flag (mh-toggle-threads)) - (mh-index-data (mh-index-insert-folder-headers))))) - -;;;###mh-autoload -(defun mh-store-msg (directory) - "Unpack message created with \"uudecode\" or \"shar\". - -The default DIRECTORY for extraction is the current directory; -however, you have a chance to specify a different extraction -directory. The next time you use this command, the default -directory is the last directory you used. If you would like to -change the initial default directory, customize the option -`mh-store-default-directory', change the value from \"Current\" -to \"Directory\", and then enter the name of the directory for -storing the content of these messages." - (interactive (list (let ((udir (or mh-store-default-directory - default-directory))) - (read-directory-name "Store message in directory: " - udir udir nil)))) - (let ((msg-file-to-store (mh-msg-filename (mh-get-msg-num t)))) - (with-current-buffer (get-buffer-create mh-temp-buffer) - (erase-buffer) - (insert-file-contents msg-file-to-store) - (mh-store-buffer directory)))) - -(defun mh-store-buffer (directory) - "Unpack buffer created with \"uudecode\" or \"shar\". - -See `mh-store-msg' for a description of DIRECTORY." - (interactive (list (let ((udir (or mh-store-default-directory - default-directory))) - (read-directory-name "Store buffer in directory: " - udir udir nil)))) - (let ((store-directory (expand-file-name directory)) - (sh-start (save-excursion - (goto-char (point-min)) - (if (re-search-forward - "^#![ \t]*/bin/sh\\|^#\\|^: " nil t) - (progn - ;; The "cut here" pattern was removed from above - ;; because it seemed to hurt more than help. - ;; But keep this to make it easier to put it back. - (if (looking-at "^[^a-z0-9\"]*cut here\\b") - (forward-line 1)) - (beginning-of-line) - (if (looking-at "^[#:]....+\n\\( ?\n\\)?end$") - nil ;most likely end of a uuencode - (point)))))) - (command "sh") - (uudecode-filename "(unknown filename)") - log-begin) - (if (not sh-start) - (save-excursion - (goto-char (point-min)) - (if (re-search-forward "^begin [0-7]+ " nil t) - (setq uudecode-filename - (buffer-substring (point) - (progn (end-of-line) (point))))))) - (with-current-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 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 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) - (with-current-buffer mh-log-buffer - (insert "\n(mh-store finished)\n")) - (error "Error occurred during execution of %s" command))))) - -;;;###mh-autoload -(defun mh-undo-folder (&rest _ignored) - "Undo all refiles and deletes in the current folder. -Arguments are IGNORED (for `revert-buffer')." - (interactive) - (cond ((or mh-do-not-confirm-flag - (yes-or-no-p "Undo all commands in folder? ")) - (setq mh-delete-list nil - mh-refile-list nil - mh-blocklist nil - mh-allowlist nil - mh-seq-list nil - mh-next-direction 'forward) - (with-mh-folder-updating (nil) - (mh-remove-all-notation))) - (t - (message "Commands not undone")))) - -(provide 'mh-funcs) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-funcs.el ends here diff --git a/lisp/mh-e/mh-gnus.el b/lisp/mh-e/mh-gnus.el deleted file mode 100644 index 2053dcc708a..00000000000 --- a/lisp/mh-e/mh-gnus.el +++ /dev/null @@ -1,114 +0,0 @@ -;;; mh-gnus.el --- make MH-E compatible with various versions of Gnus -*- lexical-binding: t; -*- - -;; Copyright (C) 2003-2004, 2006-2024 Free Software Foundation, Inc. - -;; Author: Satyaki Das -;; Maintainer: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;;; Code: - -(require 'mh-e) - -(require 'gnus-util) -(require 'mm-bodies) -(require 'mm-decode) -(require 'mm-view) -(require 'mml) - -(defun mh-gnus-local-map-property (map) - "Return a list suitable for a text property list specifying keymap MAP." - (declare (obsolete nil "29.1")) - (list 'keymap map)) - -(define-obsolete-function-alias 'mh-mm-merge-handles - #'mm-merge-handles "29.1") - -(define-obsolete-function-alias 'mh-mm-set-handle-multipart-parameter - #'mm-set-handle-multipart-parameter "29.1") - -(define-obsolete-function-alias 'mh-mm-inline-text-vcard - #'mm-inline-text-vcard "29.1") - -(define-obsolete-function-alias 'mh-mm-possibly-verify-or-decrypt - #'mm-possibly-verify-or-decrypt "29.1") - -(define-obsolete-function-alias 'mh-mm-handle-multipart-ctl-parameter - #'mm-handle-multipart-ctl-parameter "29.1") - -(define-obsolete-function-alias 'mh-mm-readable-p - #'mm-readable-p "29.1") - -(define-obsolete-function-alias 'mh-mm-long-lines-p - #'mm-long-lines-p "29.1") - -(define-obsolete-function-alias 'mh-mm-keep-viewer-alive-p - #'mm-keep-viewer-alive-p "29.1") - -(define-obsolete-function-alias 'mh-mm-destroy-parts - #'mm-destroy-parts "29.1") - -(define-obsolete-function-alias 'mh-mm-uu-dissect-text-parts - #'mm-uu-dissect-text-parts "29.1") - -(define-obsolete-function-alias 'mh-mml-minibuffer-read-disposition - #'mml-minibuffer-read-disposition "29.1") - -;; This is mm-save-part from Gnus 5.11 since that function in Emacs -;; 21.2 is buggy (the args to read-file-name are incorrect) and the -;; version in Emacs 22 is not consistent with C-x C-w in that you -;; can't just specify a directory and have the right thing happen. -(defun mh-mm-save-part (handle &optional prompt) - "Write HANDLE to a file. -PROMPT overrides the default one used to ask user for a file name." - (let ((filename (or (mail-content-type-get - (mm-handle-disposition handle) 'filename) - (mail-content-type-get - (mm-handle-type handle) 'name))) - file) - (when filename - (setq filename (gnus-map-function mm-file-name-rewrite-functions - (file-name-nondirectory filename)))) - (setq file - (read-file-name (or prompt "Save MIME part to: ") - (or mm-default-directory default-directory) - nil nil (or filename ""))) - (setq mm-default-directory (file-name-directory file)) - (and (or (not (file-exists-p file)) - (yes-or-no-p (format "File %s already exists; overwrite? " - file))) - (progn - (mm-save-part-to-file handle file) - file)))) - -(defun mh-mm-text-html-renderer () - "Find the renderer Gnus is using to display text/html MIME parts." - (declare (obsolete mm-text-html-renderer "29.1")) - mm-text-html-renderer) - -(provide 'mh-gnus) - -;; Local Variables: -;; no-update-autoloads: t -;; sentence-end-double-space: nil -;; End: - -;;; mh-gnus.el ends here diff --git a/lisp/mh-e/mh-identity.el b/lisp/mh-e/mh-identity.el deleted file mode 100644 index bfd0a1c0277..00000000000 --- a/lisp/mh-e/mh-identity.el +++ /dev/null @@ -1,324 +0,0 @@ -;;; mh-identity.el --- multiple identify support for MH-E -*- lexical-binding: t; -*- - -;; Copyright (C) 2002-2024 Free Software Foundation, Inc. - -;; Author: Peter S. Galbraith -;; Maintainer: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Multiple identity support for MH-E. - -;; Used to easily set different fields such as From and Organization, -;; as well as different signature files. - -;; Customize the variable `mh-identity-list' and see the Identity menu -;; in MH-Letter mode. The command `mh-insert-identity' can be used -;; to manually insert an identity. - -;;; Code: - -(require 'mh-e) - -(autoload 'mml-insert-tag "mml") - -(define-obsolete-variable-alias 'mh-identity-pgg-default-user-id - 'mh-identity-gpg-default-user-id "29.1") -(defvar-local mh-identity-gpg-default-user-id nil - "Holds the GPG key ID. -This is normally set as part of an Identity in -`mh-identity-list'.") - -(defvar mh-identity-menu nil - "The Identity menu.") - -(defalias 'mh-identity-make-menu-no-autoload #'mh-identity-make-menu) - -;;;###mh-autoload -(defun mh-identity-make-menu () - "Build the Identity menu. -This should be called any time `mh-identity-list' or -`mh-auto-fields-list' change." - (easy-menu-define mh-identity-menu mh-letter-mode-map - "MH-E identity menu" - (append - '("Identity") - ;; Dynamically render :type corresponding to `mh-identity-list' - ;; e.g.: - ;; ["Home" (mh-insert-identity "Home") - ;; :style radio :active (not (equal mh-identity-local "Home")) - ;; :selected (equal mh-identity-local "Home")] - '(["Insert Auto Fields" - (mh-insert-auto-fields) mh-auto-fields-list] - "--") - - (mapcar (lambda (arg) - `[,arg (mh-insert-identity ,arg) :style radio - :selected (equal mh-identity-local ,arg)]) - (mapcar #'car mh-identity-list)) - '(["None" - (mh-insert-identity "None") :style radio - :selected (not mh-identity-local)] - "--" - ["Set Default for Session" - (setq mh-identity-default mh-identity-local) t] - ["Save as Default" - (customize-save-variable 'mh-identity-default mh-identity-local) t] - ["Customize Identities" (customize-variable 'mh-identity-list) t] - )))) - -;;;###mh-autoload -(defun mh-identity-add-menu () - "Add the current Identity menu. -See `mh-identity-make-menu'." - (declare (obsolete nil "29.1")) - nil) - -(defvar-local mh-identity-local nil - "Buffer-local variable that holds the identity currently in use.") - -(defun mh-header-field-delete (field value-only) - "Delete header FIELD, or only its value if VALUE-ONLY is t. -Return t if anything is deleted." - (let ((field-colon (if (string-match "^.*:$" field) - field - (concat field ":")))) - (when (mh-goto-header-field field-colon) - (if (not value-only) - (beginning-of-line) - (forward-char)) - (delete-region (point) - (progn (mh-header-field-end) - (if (not value-only) (forward-char 1)) - (point))) - t))) - -(defvar mh-identity-signature-start nil - "Marker for the beginning of a signature inserted by `mh-insert-identity'.") -(defvar mh-identity-signature-end nil - "Marker for the end of a signature inserted by `mh-insert-identity'.") - -(defun mh-identity-field-handler (field) - "Return the handler for header FIELD or nil if none set. -The field name is downcased. If the FIELD begins with the -character \":\", then it must have a special handler defined in -`mh-identity-handlers', else return an error since it is not a -valid header field." - (or (cdr (assoc-string field mh-identity-handlers t)) - (and (eq (aref field 0) ?:) - (error "Field %s not found in `mh-identity-handlers'" field)) - (cdr (assoc ":default" mh-identity-handlers)) - 'mh-identity-handler-default)) - -;;;###mh-autoload -(defun mh-select-identity (default) - "Prompt for and return an identity. -If DEFAULT is non-nil, it will be used if the user doesn't enter a -different identity. - -See `mh-identity-list'." - (let (identity) - (setq identity - (completing-read - "Identity: " - (cons '("None") - (mapcar #'list (mapcar #'car mh-identity-list))) - nil t default nil default)) - (if (equal identity "None") - nil - identity))) - -;;;###mh-autoload -(defun mh-identity-field (identity field) - "Return the specified FIELD of the given IDENTITY. - -See `mh-identity-list'." - (let* ((pers-list (cadr (assoc identity mh-identity-list))) - (value (cdr (assoc field pers-list)))) - value)) - -;;;###mh-autoload -(defun mh-insert-identity (identity &optional maybe-insert) - "Insert fields specified by given IDENTITY. - -In a program, do not insert fields if MAYBE-INSERT is non-nil, -`mh-identity-default' is non-nil, and fields have already been -inserted. - -See `mh-identity-list'." - (interactive - (list (completing-read - "Identity: " - (if mh-identity-local - (cons '("None") - (mapcar #'list (mapcar #'car mh-identity-list))) - (mapcar #'list (mapcar #'car mh-identity-list))) - nil t) - nil)) - - (when (or (not maybe-insert) - (and (boundp 'mh-identity-default) - mh-identity-default - (not mh-identity-local))) - (save-excursion - ;;First remove old settings, if any. - (when mh-identity-local - (let ((pers-list (cadr (assoc mh-identity-local mh-identity-list)))) - (while pers-list - (let* ((field (caar pers-list)) - (handler (mh-identity-field-handler field))) - (funcall handler field 'remove)) - (setq pers-list (cdr pers-list))))) - ;; Then insert the replacement - (when (not (equal "None" identity)) - (let ((pers-list (cadr (assoc identity mh-identity-list)))) - (while pers-list - (let* ((field (caar pers-list)) - (value (cdar pers-list)) - (handler (mh-identity-field-handler field))) - (funcall handler field 'add value)) - (setq pers-list (cdr pers-list)))))) - ;; Remember what is in use in this buffer - (if (equal "None" identity) - (setq mh-identity-local nil) - (setq mh-identity-local identity)))) - -;;;###mh-autoload -(defun mh-identity-handler-gpg-identity (_field action &optional value) - "Process header FIELD \":pgg-default-user-id\". -The ACTION is one of `remove' or `add'. If `add', the VALUE is added. -The buffer-local variable `mh-identity-gpg-default-user-id' is set to -VALUE when action `add' is selected." - (cond - ((or (equal action 'remove) - (not value) - (string= value "")) - (setq mh-identity-gpg-default-user-id nil)) - ((equal action 'add) - (setq mh-identity-gpg-default-user-id value)))) - -;;;###mh-autoload -(defun mh-identity-handler-signature (_field action &optional value) - "Process header FIELD \":signature\". -The ACTION is one of `remove' or `add'. If `add', the VALUE is -added." - (cond - ((equal action 'remove) - (when (and (markerp mh-identity-signature-start) - (markerp mh-identity-signature-end)) - (delete-region mh-identity-signature-start - mh-identity-signature-end))) - (t - ;; Insert "signature". Nil value means to use `mh-signature-file-name'. - (when (not (mh-signature-separator-p)) ;...unless already present - (goto-char (point-max)) - (save-restriction - (narrow-to-region (point) (point)) - (if (null value) - (mh-insert-signature) - (mh-insert-signature value)) - (setq-local mh-identity-signature-start (point-min-marker)) - (set-marker-insertion-type mh-identity-signature-start t) - (setq-local mh-identity-signature-end (point-max-marker))))))) - -(defvar mh-identity-attribution-verb-start nil - "Marker for the beginning of the attribution verb.") -(defvar mh-identity-attribution-verb-end nil - "Marker for the end of the attribution verb.") - -;;;###mh-autoload -(defun mh-identity-handler-attribution-verb (_field action &optional value) - "Process header FIELD \":attribution-verb\". -The ACTION is one of `remove' or `add'. If `add', the VALUE is -added." - (when (and (markerp mh-identity-attribution-verb-start) - (markerp mh-identity-attribution-verb-end)) - (delete-region mh-identity-attribution-verb-start - mh-identity-attribution-verb-end) - (goto-char mh-identity-attribution-verb-start) - (cond - ((equal action 'remove) ; Replace with default - (mh-identity-insert-attribution-verb nil)) - (t ; Insert attribution verb. - (mh-identity-insert-attribution-verb value))))) - -;;;###mh-autoload -(defun mh-identity-insert-attribution-verb (value) - "Insert VALUE as attribution verb, setting up delimiting markers. -If VALUE is nil, use `mh-extract-from-attribution-verb'." - (save-restriction - (narrow-to-region (point) (point)) - (if (null value) - (insert mh-extract-from-attribution-verb) - (insert value)) - (setq-local mh-identity-attribution-verb-start (point-min-marker)) - (set-marker-insertion-type mh-identity-attribution-verb-start t) - (setq-local mh-identity-attribution-verb-end (point-max-marker)))) - -(defun mh-identity-handler-default (field action top &optional value) - "Process header FIELD. -The ACTION is one of `remove' or `add'. If TOP is non-nil, add the -field and its VALUE at the top of the header, else add it at the -bottom of the header. If action is `add', the VALUE is added." - (let ((field-colon (if (string-match "^.*:$" field) - field - (concat field ":")))) - (cond - ((equal action 'remove) - (mh-header-field-delete field-colon nil)) - (t - (cond - ;; No value, remove field - ((or (not value) - (string= value "")) - (mh-header-field-delete field-colon nil)) - ;; Existing field, replace - ((mh-header-field-delete field-colon t) - (insert value)) - ;; Other field, add at end or top - (t - (goto-char (point-min)) - (if (not top) - (mh-goto-header-end 0)) - (insert field-colon " " value "\n"))))))) - -;;;###mh-autoload -(defun mh-identity-handler-top (field action &optional value) - "Process header FIELD. -The ACTION is one of `remove' or `add'. If `add', the VALUE is -added. If the field wasn't present, it is added to the top of the -header." - (mh-identity-handler-default field action t value)) - -;;;###mh-autoload -(defun mh-identity-handler-bottom (field action &optional value) - "Process header FIELD. -The ACTION is one of `remove' or `add'. If `add', the VALUE is -added. If the field wasn't present, it is added to the bottom of -the header." - (mh-identity-handler-default field action nil value)) - -(provide 'mh-identity) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-identity.el ends here diff --git a/lisp/mh-e/mh-inc.el b/lisp/mh-e/mh-inc.el deleted file mode 100644 index acb0474a8f9..00000000000 --- a/lisp/mh-e/mh-inc.el +++ /dev/null @@ -1,84 +0,0 @@ -;;; mh-inc.el --- MH-E "inc" and separate mail spool handling -*- lexical-binding: t; -*- - -;; Copyright (C) 2003-2004, 2006-2024 Free Software Foundation, Inc. - -;; Author: Peter S. Galbraith -;; Maintainer: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; 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". - -;;; Code: - -(require 'mh-e) - -(defvar mh-inc-spool-map-help nil - "Help text for `mh-inc-spool-map'.") - -(define-key mh-inc-spool-map "?" - (lambda () - (interactive) - (if mh-inc-spool-map-help - (mh-help mh-inc-spool-map-help) - (mh-ephem-message - "There are no keys defined yet; customize `mh-inc-spool-list'")))) - -;;;###mh-autoload -(defun mh-inc-spool-make () - "Make all commands and defines keys for contents of `mh-inc-spool-list'." - (setq mh-inc-spool-map-help nil) - (when mh-inc-spool-list - (cl-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)))))) - -(defalias 'mh-inc-spool-make-no-autoload #'mh-inc-spool-make) - -(defun mh-inc-spool-generator (folder spool) - "Create a command to inc into FOLDER from SPOOL file." - (defalias (symbol-function (intern (concat "mh-inc-spool-" folder))) - (lambda () - (:documentation (format "Inc spool file %s into folder %s." spool folder)) - (interactive) - (mh-inc-folder spool (concat "+" folder))))) - -(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))) - (add-to-list 'mh-inc-spool-map-help - (concat "[" (char-to-string key) "] inc " folder " folder\n") - t))) - -(provide 'mh-inc) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-inc.el ends here diff --git a/lisp/mh-e/mh-junk.el b/lisp/mh-e/mh-junk.el deleted file mode 100644 index 9eb4f8d500c..00000000000 --- a/lisp/mh-e/mh-junk.el +++ /dev/null @@ -1,546 +0,0 @@ -;;; mh-junk.el --- MH-E interface to anti-spam measures -*- lexical-binding: t; -*- - -;; Copyright (C) 2003-2024 Free Software Foundation, Inc. - -;; Author: Satyaki Das , -;; Bill Wohler -;; Maintainer: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Spam handling in MH-E. - -;;; Code: - -(require 'mh-e) -(require 'mh-scan) - -(autoload 'mail-header-parse-address "mail-parse") - -;;;###mh-autoload -(defun mh-junk-blocklist (range) - "Blocklist RANGE as spam. - -This command trains the spam program in use (see the option -`mh-junk-program') with the content of RANGE and then handles the -message(s) as specified by the option `mh-junk-disposition'. - -Check the documentation of `mh-interactive-range' to see how RANGE is -read in interactive use. - -For more information about using your particular spam fighting -program, see: - - - `mh-spamassassin-blocklist' - - `mh-bogofilter-blocklist' - - `mh-spamprobe-blocklist'" - (interactive (list (mh-interactive-range "Blocklist"))) - (mh-iterate-on-range () range (mh-junk-blocklist-a-msg nil)) - (if (looking-at mh-scan-blocklisted-msg-regexp) - (mh-next-msg))) - -(defun mh-junk-blocklist-a-msg (message) - "Blocklist MESSAGE. -If MESSAGE is nil then the message at point is blocklisted. -The hook `mh-blocklist-msg-hook' is called after you mark a message -for blocklisting." - (save-excursion - (if (numberp message) - (mh-goto-msg message nil t) - (beginning-of-line) - (setq message (mh-get-msg-num t))) - (cond ((looking-at mh-scan-refiled-msg-regexp) - (error "Message %d is refiled; undo refile before blocklisting" - message)) - ((looking-at mh-scan-deleted-msg-regexp) - (error "Message %d is deleted; undo delete before blocklisting" - message)) - ((looking-at mh-scan-allowlisted-msg-regexp) - (error "Message %d is allowlisted; undo before blocklisting" - message)) - ((looking-at mh-scan-blocklisted-msg-regexp) nil) - (t - (mh-set-folder-modified-p t) - (setq mh-blocklist (cons message mh-blocklist)) - (if (not (memq message mh-seen-list)) - (setq mh-seen-list (cons message mh-seen-list))) - (mh-notate nil mh-note-blocklisted mh-cmd-note) - (run-hooks 'mh-blocklist-msg-hook))))) - -;;;###mh-autoload -(defun mh-junk-blocklist-disposition () - "Determines the fate of the selected spam." - (cond ((null mh-junk-disposition) nil) - ((equal mh-junk-disposition "") "+") - ((eq (aref mh-junk-disposition 0) ?+) - mh-junk-disposition) - ((eq (aref mh-junk-disposition 0) ?@) - (concat mh-current-folder "/" - (substring mh-junk-disposition 1))) - (t (concat "+" mh-junk-disposition)))) - -;;;###mh-autoload -(defun mh-junk-process-blocklist (range) - "Blocklist RANGE as spam. -This command trains the spam program in use (see the option -`mh-junk-program') with the content of RANGE and then handles the -message(s) as specified by the option `mh-junk-disposition'." - (let ((blocklist-func (nth 1 (assoc mh-junk-choice mh-junk-function-alist)))) - (unless blocklist-func - (error "Customize `mh-junk-program' appropriately")) - (mh-iterate-on-range msg range - (funcall (symbol-function blocklist-func) msg)))) - -;;;###mh-autoload -(defun mh-junk-whitelist (range) - "Old name for `mh-junk-allowlist'; use \\[mh-junk-allowlist] instead." - (interactive (list (mh-interactive-range "Allowlist"))) - ;; We do our own message here instead of using "declare obsolete" - ;; in order to talk about keys instead of function names. Also, it - ;; lets us bind "J w" to this without the Emacs 29 compiler complaining. - (when (not (get 'mh-junk-whitelist 'command-execute-obsolete-warned)) - (message "%s is an obsolete key (as of 28.1); use %s instead" - (substitute-command-keys "\\[mh-junk-whitelist]") - (substitute-command-keys "\\[mh-junk-allowlist]")) - (put 'mh-junk-whitelist 'command-execute-obsolete-warned t)) - (mh-junk-allowlist range)) - -;;;###mh-autoload -(defun mh-junk-allowlist (range) - "Allowlist RANGE as ham. - -This command reclassifies the RANGE as ham if it has been incorrectly -classified as spam (see the option `mh-junk-program'). It then -refiles the message into the \"+inbox\" folder. - -Check the documentation of `mh-interactive-range' to see how -RANGE is read in interactive use." - (interactive (list (mh-interactive-range "Allowlist"))) - (mh-iterate-on-range () range (mh-junk-allowlist-a-msg nil)) - (if (looking-at mh-scan-allowlisted-msg-regexp) - (mh-next-msg))) - -(defun mh-junk-allowlist-a-msg (message) - "Allowlist MESSAGE. -If MESSAGE is nil then the message at point is allowlisted. The -hook `mh-allowlist-msg-hook' is called after you mark a message -for allowlisting." - (save-excursion - (if (numberp message) - (mh-goto-msg message nil t) - (beginning-of-line) - (setq message (mh-get-msg-num t))) - (cond ((looking-at mh-scan-refiled-msg-regexp) - (error "Message %d is refiled; undo refile before allowlisting" - message)) - ((looking-at mh-scan-deleted-msg-regexp) - (error "Message %d is deleted; undo delete before allowlisting" - message)) - ((looking-at mh-scan-blocklisted-msg-regexp) - (error "Message %d is blocklisted; undo before allowlisting" - message)) - ((looking-at mh-scan-allowlisted-msg-regexp) nil) - (t - (mh-set-folder-modified-p t) - (setq mh-allowlist (cons message mh-allowlist)) - (mh-notate nil mh-note-allowlisted mh-cmd-note) - (run-hooks 'mh-allowlist-msg-hook))))) - -;;;###mh-autoload -(defun mh-junk-process-allowlist (range) - "Allowlist RANGE as ham. - -This command reclassifies the RANGE as ham if it were incorrectly -classified as spam (see the option `mh-junk-program')." - (let ((allowlist-func (nth 2 (assoc mh-junk-choice mh-junk-function-alist)))) - (unless allowlist-func - (error "Customize `mh-junk-program' appropriately")) - (mh-iterate-on-range msg range - (funcall (symbol-function allowlist-func) msg)))) - - - -;; SpamAssassin Interface - -(defvar mh-spamassassin-executable (executable-find "spamassassin")) -(defvar mh-sa-learn-executable (executable-find "sa-learn")) - -;;;###mh-autoload -(defun mh-spamassassin-blocklist (msg) - "Blocklist MSG with SpamAssassin. - -SpamAssassin is one of the more popular spam filtering programs. -Get it from your local distribution or from the SpamAssassin web -site at URL `https://spamassassin.apache.org/'. - -To use SpamAssassin, add the following recipes to -\".procmailrc\": - - PATH=$PATH:/usr/bin/mh - MAILDIR=$HOME/`mhparam Path` - - # Fight spam with SpamAssassin. - :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\". - -Note that one of the recipes above throws away messages with a -score greater than or equal to 10. Here's how you can determine a -value that works best for you. - -First, run \"spamassassin -t\" on every mail message in your -archive and use Gnumeric to verify that the average plus the -standard deviation of good mail is under 5, the SpamAssassin -default for \"spam\". - -Using Gnumeric, sort the messages by score and view the messages -with the highest score. Determine the score which encompasses all -of your interesting messages and add a couple of points to be -conservative. Add that many dots to the \"X-Spam-Level:\" header -field above to send messages with that score down the drain. - -In the example above, messages with a score of 5-9 are set aside -in the \"+spam\" folder for later review. The major weakness of -rules-based filters is a plethora of false positives so it is -worthwhile to check. - -If SpamAssassin classifies a message incorrectly, or is unsure, -you can use the MH-E commands \\[mh-junk-blocklist] and -\\[mh-junk-allowlist]. - -The command \\[mh-junk-blocklist] adds a \"blacklist_from\" entry -to \"~/spamassassin/user_prefs\", deletes the message, and sends -the message to the Razor, so that others might not see this spam. -If the \"sa-learn\" command is available, the message is also -recategorized as spam. - -The command \\[mh-junk-allowlist] adds a \"whitelist_from\" rule -to the \"~/.spamassassin/user_prefs\" file. If the \"sa-learn\" -command is available, the message is also recategorized as ham. - -Over time, you'll observe that the same host or domain occurs -repeatedly in the \"blacklist_from\" entries, so you might think -that you could avoid future spam by blocklisting all mail from a -particular domain. The utility function -`mh-spamassassin-identify-spammers' helps you do precisely that. -This function displays a frequency count of the hosts and domains -in the \"blacklist_from\" entries from the last blank line in -\"~/.spamassassin/user_prefs\" to the end of the file. This -information can be used so that you can replace multiple -\"blacklist_from\" entries with a single wildcard entry such as: - - blacklist_from *@*amazingoffersdirect2u.com" - (unless mh-spamassassin-executable - (error "Unable to find the spamassassin executable")) - (let ((current-folder mh-current-folder) - (msg-file (mh-msg-filename msg mh-current-folder)) - (sender)) - (message "Reporting message %d as spam with spamassassin..." msg) - (mh-truncate-log-buffer) - ;; Put call-process output in log buffer if we are saving it - ;; (this happens if mh-junk-background is t). - (with-current-buffer mh-log-buffer - (call-process mh-spamassassin-executable msg-file mh-junk-background nil - ;; -R removes from allowlist - "--report" "-R") - (when mh-sa-learn-executable - (message "Recategorizing message %d as spam with sa-learn..." msg) - (mh-truncate-log-buffer) - (call-process mh-sa-learn-executable msg-file mh-junk-background nil - "--spam" "--local" "--no-sync"))) - (message "Blocklisting sender of message %d..." msg) - (with-current-buffer (get-buffer-create mh-temp-buffer) - (erase-buffer) - (call-process (expand-file-name mh-scan-prog mh-progs) - nil t nil - (format "%d" 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 "Blocklisting sender of message %d...done" msg)) - (message "Blocklisting sender of message %d...not done (from my address)" msg))))) - -;;;###mh-autoload -(defun mh-spamassassin-allowlist (msg) - "Allowlist MSG with SpamAssassin. - -The \\[mh-junk-allowlist] command adds a \"whitelist_from\" rule to -the \"~/.spamassassin/user_prefs\" file. If the \"sa-learn\" command -is available, the message is also recategorized as ham. - -See `mh-spamassassin-blocklist' for more information." - (unless mh-spamassassin-executable - (error "Unable to find the spamassassin executable")) - (let ((msg-file (mh-msg-filename msg mh-current-folder)) - (show-buffer (get-buffer mh-show-buffer)) - from) - (with-current-buffer (get-buffer-create mh-temp-buffer) - (erase-buffer) - (message "Removing spamassassin markup from message %d..." msg) - (call-process mh-spamassassin-executable msg-file t nil - "--remove-markup") - (if show-buffer - (kill-buffer show-buffer)) - (write-file msg-file) - (when mh-sa-learn-executable - (message "Recategorizing message %d as ham with sa-learn..." msg) - (mh-truncate-log-buffer) - ;; Put call-process output in log buffer if we are saving it - ;; (this happens if mh-junk-background is t). - (with-current-buffer mh-log-buffer - (call-process mh-sa-learn-executable msg-file mh-junk-background nil - "--ham" "--local" "--no-sync"))) - (message "Allowlisting sender of message %d..." msg) - (setq from - (car (mail-header-parse-address (mh-get-header-field "From:")))) - (kill-buffer nil) - (if (or (null from) (equal from "")) - (message "Allowlisting sender of message %d...%s" - msg "not done (cannot identify sender)") - (mh-spamassassin-add-rule "whitelist_from" from) - (message "Allowlisting sender of message %d...done" msg))))) - -(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))))) - -;;;###mh-autoload -(defun mh-spamassassin-identify-spammers () - "Identify spammers who are repeat offenders. - -This function displays a frequency count of the hosts and domains -in the \"blacklist_from\" entries from the last blank line in -\"~/.spamassassin/user_prefs\" to the end of the file. This -information can be used so that you can replace multiple -\"blacklist_from\" entries with a single wildcard entry such as: - - blacklist_from *@*amazingoffersdirect2u.com" - (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)) - (setf (gethash (car host) domains) (1+ (if (not value) 0 value))) - (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)))) - - - -;; Bogofilter Interface - -(defvar mh-bogofilter-executable (executable-find "bogofilter")) - -;;;###mh-autoload -(defun mh-bogofilter-blocklist (msg) - "Blocklist MSG with bogofilter. - -Bogofilter is a Bayesian spam filtering program. Get it from your -local distribution or from the bogofilter web site at URL -`https://bogofilter.sourceforge.io/'. - -Bogofilter is taught by running: - - bogofilter -n < good-message - -on every good message, and - - bogofilter -s < spam-message - -on every spam message. This is called a full training; three other -training methods are described in the FAQ that is distributed with -bogofilter. Note that most Bayesian filters need 1000 to 5000 of each -type of message to start doing a good job. - -To use bogofilter, add the following recipes to \".procmailrc\": - - PATH=$PATH:/usr/bin/mh - MAILDIR=$HOME/`mhparam Path` - - # Fight spam with bogofilter. - :0fw - | bogofilter -3 -e -p - - :0: - * ^X-Bogosity: Yes, tests=bogofilter - spam/. - - :0: - * ^X-Bogosity: Unsure, tests=bogofilter - spam/unsure/. - -If bogofilter classifies a message incorrectly, or is unsure, you can -use the MH-E commands \\[mh-junk-blocklist] and \\[mh-junk-allowlist] -to update bogofilter's training. - -The \"Bogofilter FAQ\" suggests that you run the following -occasionally to shrink the database: - - bogoutil -d wordlist.db | bogoutil -l wordlist.db.new - mv wordlist.db wordlist.db.prv - mv wordlist.db.new wordlist.db - -The \"Bogofilter tuning HOWTO\" describes how you can fine-tune Bogofilter." - (unless mh-bogofilter-executable - (error "Unable to find the bogofilter executable")) - (message "Blocklisting message %d with bogofilter..." msg) - (let ((msg-file (mh-msg-filename msg mh-current-folder))) - (mh-truncate-log-buffer) - ;; Put call-process output in log buffer if we are saving it - ;; (this happens if mh-junk-background is t). - (with-current-buffer mh-log-buffer - (call-process mh-bogofilter-executable msg-file mh-junk-background - nil "-s") - (message "Blocklisting message %d with bogofilter...done" msg)))) - -;;;###mh-autoload -(defun mh-bogofilter-allowlist (msg) - "Allowlist MSG with bogofilter. - -See `mh-bogofilter-blocklist' for more information." - (unless mh-bogofilter-executable - (error "Unable to find the bogofilter executable")) - (message "Allowlisting message %d with bogofilter..." msg) - (let ((msg-file (mh-msg-filename msg mh-current-folder))) - (mh-truncate-log-buffer) - ;; Put call-process output in log buffer if we are saving it - ;; (this happens if mh-junk-background is t). - (with-current-buffer mh-log-buffer - (call-process mh-bogofilter-executable msg-file mh-junk-background - nil "-n") - (message "Allowlisting message %d with bogofilter...done" msg)))) - - - -;; Spamprobe Interface - -(defvar mh-spamprobe-executable (executable-find "spamprobe")) - -;;;###mh-autoload -(defun mh-spamprobe-blocklist (msg) - "Blocklist MSG with SpamProbe. - -SpamProbe is a Bayesian spam filtering program. Get it from your -local distribution or from the SpamProbe web site at URL -`https://spamprobe.sourceforge.net'. - -To use SpamProbe, add the following recipes to \".procmailrc\": - - PATH=$PATH:/usr/bin/mh - MAILDIR=$HOME/`mhparam Path` - - # Fight spam with SpamProbe. - :0 - SCORE=| spamprobe receive - - :0 wf - | formail -I \"X-SpamProbe: $SCORE\" - - :0: - *^X-SpamProbe: SPAM - spam/. - -If SpamProbe classifies a message incorrectly, you can use the -MH-E commands \\[mh-junk-blocklist] and \\[mh-junk-allowlist] to -update SpamProbe's training." - (unless mh-spamprobe-executable - (error "Unable to find the spamprobe executable")) - (message "Blocklisting message %d with spamprobe..." msg) - (let ((msg-file (mh-msg-filename msg mh-current-folder))) - (mh-truncate-log-buffer) - ;; Put call-process output in log buffer if we are saving it - ;; (this happens if mh-junk-background is t). - (with-current-buffer mh-log-buffer - (call-process mh-spamprobe-executable msg-file mh-junk-background - nil "spam") - (message "Blocklisting message %d with spamprobe...done" msg)))) - -;;;###mh-autoload -(defun mh-spamprobe-allowlist (msg) - "Allowlist MSG with SpamProbe. - -See `mh-spamprobe-blocklist' for more information." - (unless mh-spamprobe-executable - (error "Unable to find the spamprobe executable")) - (message "Allowlisting message %d with spamprobe..." msg) - (let ((msg-file (mh-msg-filename msg mh-current-folder))) - (mh-truncate-log-buffer) - ;; Put call-process output in log buffer if we are saving it - ;; (this happens if mh-junk-background is t). - (with-current-buffer mh-log-buffer - (call-process mh-spamprobe-executable msg-file mh-junk-background - nil "good") - (message "Allowlisting message %d with spamprobe...done" msg)))) - -(provide 'mh-junk) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-junk.el ends here diff --git a/lisp/mh-e/mh-letter.el b/lisp/mh-e/mh-letter.el deleted file mode 100644 index 8e0241f345e..00000000000 --- a/lisp/mh-e/mh-letter.el +++ /dev/null @@ -1,942 +0,0 @@ -;;; mh-letter.el --- MH-Letter mode -*- lexical-binding: t; -*- - -;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation, -;; Inc. - -;; Author: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Mode for composing and sending a draft message. - -;; Functions that would ordinarily be in here that are needed by -;; mh-show.el should be placed in the Message Utilities section in -;; mh-utils.el. That will help prevent the loading of this file until -;; a message is actually composed. - -;;; Code: - -(require 'mh-e) - -(require 'gnus-util) - -;; Dynamically-created functions not found in mh-loaddefs.el. -(autoload 'mh-tool-bar-letter-buttons-init "mh-tool-bar") -(autoload 'mh-tool-bar-init "mh-tool-bar") - -(autoload 'mml-insert-tag "mml") - -;;; Variables - -(defvar mh-letter-complete-function-alist - '((bcc . mh-alias-letter-expand-alias) - (cc . mh-alias-letter-expand-alias) - (dcc . mh-alias-letter-expand-alias) - (fcc . mh-folder-expand-at-point) - (from . mh-alias-letter-expand-alias) - (mail-followup-to . mh-alias-letter-expand-alias) - (mail-reply-to . mh-alias-letter-expand-alias) - (reply-to . mh-alias-letter-expand-alias) - (to . mh-alias-letter-expand-alias)) - "Alist of header fields and completion functions to use.") - - - -;;; Letter Menu - -(easy-menu-define - mh-letter-menu mh-letter-mode-map "Menu for MH-E letter mode." - '("Letter" - ["Send This Draft" mh-send-letter t] - ["Split Current Line" mh-open-line t] - ["Check Recipient" mh-check-whom t] - ["Yank Current Message" mh-yank-cur-msg t] - ["Insert a Message..." mh-insert-letter t] - ["Insert Signature" mh-insert-signature t] - ("Encrypt/Sign Message" - ["Sign Message" - mh-mml-secure-message-sign mh-pgp-support-flag] - ["Encrypt Message" - mh-mml-secure-message-encrypt mh-pgp-support-flag] - ["Sign+Encrypt Message" - mh-mml-secure-message-signencrypt mh-pgp-support-flag] - ["Disable Security" - mh-mml-unsecure-message mh-pgp-support-flag] - "--" - "Security Method" - ["PGP (MIME)" (setq mh-mml-method-default "pgpmime") - :style radio - :selected (equal mh-mml-method-default "pgpmime")] - ["PGP" (setq mh-mml-method-default "pgp") - :style radio - :selected (equal mh-mml-method-default "pgp")] - ["S/MIME" (setq mh-mml-method-default "smime") - :style radio - :selected (equal mh-mml-method-default "smime")] - "--" - ["Save Method as Default" - (customize-save-variable 'mh-mml-method-default mh-mml-method-default) t] - ) - ["Compose Insertion..." mh-compose-insertion t] - ["Compose Compressed tar (MH)..." - mh-mh-compose-external-compressed-tar t] - ["Compose Get File (MH)..." mh-mh-compose-anon-ftp t] - ["Compose Forward..." mh-compose-forward t] - ;; The next two will have to be merged. But I also need to make sure the - ;; user can't mix tags of both types. - ["Pull in All Compositions (MH)" - mh-mh-to-mime (mh-mh-directive-present-p)] - ["Pull in All Compositions (MML)" - mh-mml-to-mime (mh-mml-tag-present-p)] - ["Revert to Non-MIME Edit (MH)" - mh-mh-to-mime-undo (equal mh-compose-insertion 'mh)] - ["Kill This Draft" mh-fully-kill-draft t])) - - - -;;; MH-Letter Keys - -;; If this changes, modify mh-letter-mode-help-messages accordingly, above. -(define-keymap :keymap mh-letter-mode-map - "SPC" #'mh-letter-complete-or-space - "," #'mh-letter-confirm-address - "C-c ?" #'mh-help - "C-c C-\\" #'mh-fully-kill-draft ;if no C-q - "C-c C-^" #'mh-insert-signature ;if no C-s - "C-c C-c" #'mh-send-letter - "C-c C-d" #'mh-insert-identity - "C-c C-e" #'mh-mh-to-mime - "C-c C-f C-a" #'mh-to-field - "C-c C-f C-b" #'mh-to-field - "C-c C-f C-c" #'mh-to-field - "C-c C-f C-d" #'mh-to-field - "C-c C-f C-f" #'mh-to-fcc - "C-c C-f C-l" #'mh-to-field - "C-c C-f C-m" #'mh-to-field - "C-c C-f C-r" #'mh-to-field - "C-c C-f C-s" #'mh-to-field - "C-c C-f C-t" #'mh-to-field - "C-c C-f a" #'mh-to-field - "C-c C-f b" #'mh-to-field - "C-c C-f c" #'mh-to-field - "C-c C-f d" #'mh-to-field - "C-c C-f f" #'mh-to-fcc - "C-c C-f l" #'mh-to-field - "C-c C-f m" #'mh-to-field - "C-c C-f r" #'mh-to-field - "C-c C-f s" #'mh-to-field - "C-c C-f t" #'mh-to-field - "C-c C-i" #'mh-insert-letter - "C-c C-m C-e" #'mh-mml-secure-message-encrypt - "C-c C-m C-f" #'mh-compose-forward - "C-c C-m C-g" #'mh-mh-compose-anon-ftp - "C-c C-m TAB" #'mh-compose-insertion - "C-c C-m C-m" #'mh-mml-to-mime - "C-c C-m C-n" #'mh-mml-unsecure-message - "C-c C-m C-s" #'mh-mml-secure-message-sign - "C-c C-m C-t" #'mh-mh-compose-external-compressed-tar - "C-c C-m C-u" #'mh-mh-to-mime-undo - "C-c C-m C-x" #'mh-mh-compose-external-type - "C-c C-m e e" #'mh-mml-secure-message-encrypt - "C-c C-m e s" #'mh-mml-secure-message-signencrypt - "C-c C-m f" #'mh-compose-forward - "C-c C-m g" #'mh-mh-compose-anon-ftp - "C-c C-m i" #'mh-compose-insertion - "C-c C-m m" #'mh-mml-to-mime - "C-c C-m n" #'mh-mml-unsecure-message - "C-c C-m s e" #'mh-mml-secure-message-signencrypt - "C-c C-m s s" #'mh-mml-secure-message-sign - "C-c C-m t" #'mh-mh-compose-external-compressed-tar - "C-c C-m u" #'mh-mh-to-mime-undo - "C-c C-m x" #'mh-mh-compose-external-type - "C-c C-o" #'mh-open-line - "C-c C-q" #'mh-fully-kill-draft - "C-c C-s" #'mh-insert-signature - "C-c C-t" #'mh-letter-toggle-header-field-display - "C-c C-w" #'mh-check-whom - "C-c C-y" #'mh-yank-cur-msg - "C-c M-d" #'mh-insert-auto-fields - "C-M-i" #'completion-at-point - "TAB" #'mh-letter-next-header-field-or-indent - "" #'mh-letter-previous-header-field) - -;; "C-c /" prefix is used in mh-letter-mode by pgp.el and mailcrypt.el. - - - -;;; MH-Letter Help Messages - -;; Group messages logically, more or less. -(defvar mh-letter-mode-help-messages - '((nil - "Send letter: \\[mh-send-letter] " - "Open line: \\[mh-open-line]\n" - "Kill letter: \\[mh-fully-kill-draft] " - "Check recipients: \\[mh-check-whom]\n\n" - "Insert:\n" - " Current message: \\[mh-yank-cur-msg]\n" - " Attachment: \\[mh-compose-insertion]\n" - " Message to forward: \\[mh-compose-forward]\n" - " Signature: \\[mh-insert-signature]\n\n" - "Security:\n" - " Encrypt message: \\[mh-mml-secure-message-encrypt]\n" - " Sign message: \\[mh-mml-secure-message-sign]\n" - " Sign+Encrypt message: \\[mh-mml-secure-message-signencrypt]")) - "Key binding cheat sheet. - -This is an associative array which is used to show the most -common commands. The key is a prefix char. The value is one or -more strings which are concatenated together and displayed in the -minibuffer if ? is pressed after the prefix character. The -special key nil is used to display the non-prefixed commands. - -The substitutions described in `substitute-command-keys' are -performed as well.") - - - -;;; MH-Letter Font Lock - -(defvar mh-letter-font-lock-keywords - `(,@(mh-show-font-lock-keywords-with-cite) - (mh-font-lock-field-data - (1 'mh-letter-header-field prepend t))) - "Additional expressions to highlight in MH-Letter buffers.") - -(defun mh-font-lock-field-data (limit) - "Find header field region between point and LIMIT." - (and (< (point) (mh-letter-header-end)) - (< (point) limit) - (let ((end (min limit (mh-letter-header-end))) - (point (point)) - data-end data-begin field) - (end-of-line) - (setq data-end (if (re-search-forward "^[^ \t]" end t) - (match-beginning 0) - end)) - (goto-char (1- data-end)) - (if (not (re-search-backward "\\(^[^ \t][^:]*\\):[ \t]*" nil t)) - (setq data-begin (point-min)) - (setq data-begin (match-end 0)) - (setq field (match-string 1))) - (setq data-begin (max point data-begin)) - (goto-char (if (equal point data-end) (1+ data-end) data-end)) - (cond ((and field (mh-letter-skipped-header-field-p field)) - (set-match-data nil) - nil) - (t (set-match-data - (list data-begin data-end data-begin data-end)) - t))))) - -(defun mh-letter-header-end () - "Find the end of the message header. -This function is to be used only for font locking. It works by -searching for `mh-mail-header-separator' in the buffer." - (save-excursion - (goto-char (point-min)) - (cond ((equal mh-mail-header-separator "") (point-min)) - ((search-forward (format "\n%s\n" mh-mail-header-separator) nil t) - (line-beginning-position 0)) - (t (point-min))))) - - - -;;; MH-Letter Mode - -;; Ensure new buffers won't get this mode if default major-mode is nil. -(put 'mh-letter-mode 'mode-class 'special) - -;;;###mh-autoload -(define-derived-mode mh-letter-mode mail-mode "MH-Letter" - "Mode for composing letters in MH-E\\. - -When you have finished composing, type \\[mh-send-letter] to send -the message using the MH mail handling system. - -There are two types of tags used by MH-E when composing MIME -messages: MML and MH. The option `mh-compose-insertion' controls -what type of tags are inserted by MH-E commands. These tags can -be converted to MIME body parts by running \\[mh-mh-to-mime] for -MH-style directives or \\[mh-mml-to-mime] for MML tags. - -Options that control this mode can be changed with -\\[customize-group]; specify the \"mh-compose\" group. - -When a message is composed, the hooks `text-mode-hook', -`mail-mode-hook', and `mh-letter-mode-hook' are run (in that -order). - -\\{mh-letter-mode-map}" - (mh-find-path) - (make-local-variable 'mh-send-args) - (make-local-variable 'mh-annotate-char) - (make-local-variable 'mh-annotate-field) - (make-local-variable 'mh-previous-window-config) - (make-local-variable 'mh-sent-from-folder) - (make-local-variable 'mh-sent-from-msg) - (unless mh-letter-tool-bar-map - (mh-tool-bar-letter-buttons-init)) - (if (boundp 'tool-bar-map) - (setq-local tool-bar-map mh-letter-tool-bar-map)) - ;; Set the local value of mh-mail-header-separator according to what is - ;; present in the buffer... - (setq-local mh-mail-header-separator - (save-excursion - (goto-char (mh-mail-header-end)) - (buffer-substring-no-properties (point) (line-end-position)))) - (make-local-variable 'mail-header-separator) - (setq mail-header-separator mh-mail-header-separator) ;override sendmail.el - (mh-set-help mh-letter-mode-help-messages) - (setq buffer-invisibility-spec '((vanish . t) t)) - (setq-local line-move-ignore-invisible t) - - ;; Enable undo since a show-mode buffer might have been reused. - (buffer-enable-undo) - (make-local-variable 'font-lock-defaults) - (cond - ((or (equal mh-highlight-citation-style 'font-lock) - (equal mh-highlight-citation-style 'gnus)) - ;; Let's use font-lock even if gnus is used in show-mode. The reason - ;; is that gnus uses static text properties which are not appropriate - ;; for a buffer that will be edited. So the choice here is either fontify - ;; the citations and header... - (setq font-lock-defaults '(mh-letter-font-lock-keywords t))) - (t - ;; ...or the header only - (setq font-lock-defaults '((mh-show-font-lock-keywords) t)))) - ;; Maybe we want to use the existing Mail menu from mail-mode in - ;; 9.0; in the mean time, let's remove it since the redundancy will - ;; only produce confusion. - (define-key mh-letter-mode-map [menu-bar mail] #'undefined) - (setq fill-column mh-letter-fill-column) - (add-hook 'completion-at-point-functions - #'mh-letter-completion-at-point nil 'local) - ;; If text-mode-hook turned on auto-fill, tune it for messages - (when auto-fill-function - (make-local-variable 'auto-fill-function) - (setq auto-fill-function #'mh-auto-fill-for-letter))) - - - -;;; MH-Letter Commands - -;; Alphabetical. -;; See also mh-comp.el and mh-mime.el. - -(defun mh-check-whom () - "Verify recipients, showing expansion of any aliases. - -This command expands aliases so you can check the actual address(es) -in the alias. A new buffer named \"*MH-E Recipients*\" is created with -the output of \"whom\"." - (interactive) - (let ((file-name buffer-file-name)) - (save-buffer) - (message "Checking recipients...") - (mh-in-show-buffer (mh-recipients-buffer) - (bury-buffer (current-buffer)) - (erase-buffer) - (mh-exec-cmd-output "whom" t file-name)) - (message "Checking recipients...done"))) - -(defun mh-insert-letter (folder message verbatim) - "Insert a message. - -This command prompts you for the FOLDER and MESSAGE number, which -defaults to the current message in that folder. It then inserts -the message, indented by `mh-ins-buf-prefix' (\"> \") unless -`mh-yank-behavior' is set to one of the supercite flavors in -which case supercite is used to format the message. Certain -undesirable header fields (see -`mh-invisible-header-fields-compiled') are removed before -insertion. - -If given a prefix argument VERBATIM, the header is left intact, the -message is not indented, and \"> \" is not inserted before each line. -This command leaves the mark before the letter and point after it." - (interactive - (let* ((folder - (mh-prompt-for-folder "Message from" mh-sent-from-folder nil)) - (default - (if (equal folder mh-sent-from-folder) - (or mh-sent-from-msg (nth 0 (mh-translate-range folder "cur"))) - (nth 0 (mh-translate-range folder "cur")))) - (message - (read-string (format-prompt "Message number" default) - nil nil - (if (numberp default) - (int-to-string default) - default)))) - (list folder message current-prefix-arg))) - (if (equal message "") - (error "No message number given")) - (save-restriction - (narrow-to-region (point) (point)) - (let ((start (point-min))) - (insert-file-contents - (expand-file-name message (mh-expand-file-name folder))) - (when (not verbatim) - (mh-clean-msg-header start mh-invisible-header-fields-compiled nil) - (goto-char (point-max)) ;Needed for sc-cite-original - (push-mark) ;Needed for sc-cite-original - (goto-char (point-min)) ;Needed for sc-cite-original - (mh-insert-prefix-string mh-ins-buf-prefix))))) - -;;;###mh-autoload -(defun mh-insert-signature (&optional file) - "Insert signature in message. - -This command inserts your signature at the current cursor location. - -By default, the text of your signature is taken from the file -\"~/.signature\". You can read from other sources by changing the -option `mh-signature-file-name'. - -A signature separator (\"-- \") will be added if the signature block -does not contain one and `mh-signature-separator-flag' is on. - -The hook `mh-insert-signature-hook' is run after the signature is -inserted. Hook functions may access the actual name of the file or the -function used to insert the signature with `mh-signature-file-name'. - -The signature can also be inserted using Identities (see -`mh-identity-list'). - -In a program, you can pass in a signature FILE." - (interactive) - (save-excursion - (insert "\n") - (let ((mh-signature-file-name (or file mh-signature-file-name)) - (mh-mh-p (mh-mh-directive-present-p)) - (mh-mml-p (mh-mml-tag-present-p))) - (save-restriction - (narrow-to-region (point) (point)) - (cond - ((mh-file-is-vcard-p mh-signature-file-name) - (if (equal mh-compose-insertion 'mml) - (insert "<#part type=\"text/x-vcard\" filename=\"" - mh-signature-file-name - "\" disposition=inline description=VCard>\n<#/part>") - (insert "#text/x-vcard; name=\"" - (file-name-nondirectory mh-signature-file-name) - "\" [VCard] " (expand-file-name mh-signature-file-name)))) - (t - (cond - (mh-mh-p - (insert "#\n" "Content-Description: Signature\n")) - (mh-mml-p - (mml-insert-tag 'part 'type "text/plain" 'disposition "inline" - 'description "Signature"))) - (cond ((null mh-signature-file-name)) - ((and (stringp mh-signature-file-name) - (file-readable-p mh-signature-file-name)) - (insert-file-contents mh-signature-file-name)) - ((functionp mh-signature-file-name) - (funcall mh-signature-file-name))))) - (save-restriction - (widen) - (run-hooks 'mh-insert-signature-hook)) - (goto-char (point-min)) - (when (and (not (mh-file-is-vcard-p mh-signature-file-name)) - mh-signature-separator-flag - (> (point-max) (point-min)) - (not (mh-signature-separator-p))) - (cond (mh-mh-p - (forward-line 2)) - (mh-mml-p - (forward-line 1))) - (insert mh-signature-separator)) - (if (not (> (point-max) (point-min))) - (message "No signature found"))))) - (force-mode-line-update)) - -(defun mh-letter-completion-at-point () - "Return the completion data at point for MH letters. -This provides alias and folder completion in header fields according to -`mh-letter-complete-function-alist' and falls back on -`mh-letter-complete-function-alist' elsewhere." - (let ((func (and (mh-in-header-p) - (cdr (assoc (mh-letter-header-field-at-point) - mh-letter-complete-function-alist))))) - (if func - (or (funcall func) #'ignore) - mh-letter-complete-function))) - -(define-obsolete-function-alias 'mh-letter-complete - #'completion-at-point "29.1") - -(defun mh-letter-complete-or-space (arg) - "Perform completion or insert space. - -Turn on the option `mh-compose-space-does-completion-flag' to use -this command to perform completion in the header. Otherwise, a -space is inserted; use a prefix argument ARG to specify more than -one space." - (interactive "p") - (let ((end-of-prev (save-excursion - (goto-char (mh-beginning-of-word)) - (mh-beginning-of-word -1)))) - (cond ((not mh-compose-space-does-completion-flag) - (self-insert-command arg)) - ;; FIXME: This > test is redundant now that all the completion - ;; functions do it anyway. - ((> (point) end-of-prev) (self-insert-command arg)) - ((let ((mh-letter-complete-function nil)) - (mh-letter-completion-at-point)) - (completion-at-point)) - (t (self-insert-command arg))))) - -(defun mh-letter-confirm-address () - "Flash alias expansion. - -Addresses are separated by a comma; when you press the comma, -this command flashes the alias expansion in the minibuffer if -`mh-alias-flash-on-comma' is turned on." - (interactive) - (cond ((not (mh-in-header-p)) (self-insert-command 1)) - ((eq (cdr (assoc (mh-letter-header-field-at-point) - mh-letter-complete-function-alist)) - 'mh-alias-letter-expand-alias) - (mh-alias-reload-maybe) - (mh-alias-minibuffer-confirm-address)) - (t (self-insert-command 1)))) - -(defun mh-letter-next-header-field-or-indent (arg) - "Cycle to next field. - -Within the header of the message, this command moves between -fields that are highlighted with the face -`mh-letter-header-field', skipping those fields listed in -`mh-compose-skipped-header-fields'. After the last field, this -command then moves point to the message body before cycling back -to the first field. If point is already past the first line of -the message body, then this command indents by calling -`indent-relative' with the given prefix argument ARG." - (interactive "P") - (let ((header-end (save-excursion - (goto-char (mh-mail-header-end)) - (forward-line) - (point)))) - (if (> (point) header-end) - (indent-relative arg) - (mh-letter-next-header-field)))) - -(defun mh-letter-previous-header-field () - "Cycle to the previous header field. - -This command moves backwards between the fields and cycles to the -body of the message after the first field. Unlike the command -\\[mh-letter-next-header-field-or-indent], it will always take -point to the last field from anywhere in the body." - (interactive) - (let ((header-end (mh-mail-header-end))) - (if (>= (point) header-end) - (goto-char header-end) - (mh-header-field-beginning)) - (cond ((re-search-backward mh-letter-header-field-regexp nil t) - (if (mh-letter-skipped-header-field-p (match-string 1)) - (mh-letter-previous-header-field) - (goto-char (match-end 0)) - (mh-letter-skip-leading-whitespace-in-header-field))) - (t (goto-char header-end) - (forward-line))))) - -(defun mh-open-line () - "Insert a newline and leave point before it. - -This command is similar to the command \\[open-line] in that it -inserts a newline after point. It differs in that it also inserts -the right number of quoting characters and spaces so that the -next line begins in the same column as it was. This is useful -when breaking up paragraphs in replies." - (interactive) - (let ((column (current-column)) - (prefix (mh-current-fill-prefix))) - (if (> (length prefix) column) - (message "Sorry, point seems to be within the line prefix") - (newline 2) - (insert prefix) - (while (> column (current-column)) - (insert " ")) - (forward-line -1)))) - -(defun mh-to-fcc (&optional folder) - "Move to \"Fcc:\" header field. - -This command will prompt you for the FOLDER name in which to file -a copy of the draft." - (interactive (list (mh-prompt-for-folder - "Fcc" - (or (and mh-default-folder-for-message-function - (save-excursion - (goto-char (point-min)) - (funcall - mh-default-folder-for-message-function))) - "") - t))) - (let ((last-input-event ?\C-f)) - (expand-abbrev) - (save-excursion - (mh-to-field) - (insert (if (mh-folder-name-p folder) - (substring folder 1) - folder))))) - -(defvar mh-to-field-choices '(("a" . "Mail-Reply-To:") - ("b" . "Bcc:") - ("c" . "Cc:") - ("d" . "Dcc:") - ("f" . "Fcc:") - ("l" . "Mail-Followup-To:") - ("m" . "From:") - ("r" . "Reply-To:") - ("s" . "Subject:") - ("t" . "To:")) - "Alist of (final-character . field-name) choices for `mh-to-field'.") - -(defun mh-to-field () - "Move to specified header field. - -The field is indicated by the previous keystroke (the last -keystroke of the command) according to the list in the variable -`mh-to-field-choices'. -Create the field if it does not exist. -Set the mark to point before moving." - (interactive) - (expand-abbrev) - (let ((target (cdr (or (assoc (char-to-string (logior last-input-event ?`)) - mh-to-field-choices) - ;; also look for a char for version 4 compat - (assoc (logior last-input-event ?`) - mh-to-field-choices)))) - (case-fold-search t)) - (push-mark) - (cond ((mh-position-on-field target) - (let ((eol (point))) - (skip-chars-backward " \t") - (delete-region (point) eol)) - (if (and (not (eq (logior last-input-event ?`) ?s)) - (save-excursion - (backward-char 1) - (not (looking-at "[:,]")))) - (insert ", ") - (insert " "))) - (t - (if (mh-position-on-field "To:") - (forward-line 1)) - (insert (format "%s \n" target)) - (backward-char 1))))) - -;;;###mh-autoload -(defun mh-yank-cur-msg () - "Insert the current message into the draft buffer. - -It is often useful to insert a snippet of text from a letter that -someone mailed to provide some context for your reply. This -command does this by adding an attribution, yanking a portion of -text from the message to which you're replying, and inserting -`mh-ins-buf-prefix' (`> ') before each line. - -The attribution consists of the sender's name and email address -followed by the content of the option -`mh-extract-from-attribution-verb'. - -You can also turn on the option -`mh-delete-yanked-msg-window-flag' to delete the window -containing the original message after yanking it to make more -room on your screen for your reply. - -You can control how the message to which you are replying is -yanked into your reply using `mh-yank-behavior'. - -If this isn't enough, you can gain full control over the -appearance of the included text by setting `mail-citation-hook' -to a function that modifies it. For example, if you set this hook -to `trivial-cite' (which is NOT part of Emacs), set -`mh-yank-behavior' to \"Body and Header\" (see URL -`http://shasta.cs.uiuc.edu/~lrclause/tc.html'). - -Note that if `mail-citation-hook' is set, `mh-ins-buf-prefix' is -not inserted. If the option `mh-yank-behavior' is set to one of -the supercite flavors, the hook `mail-citation-hook' is ignored -and `mh-ins-buf-prefix' is not inserted." - (interactive) - (let ((show-buffer)) - (if (and mh-sent-from-folder - (with-current-buffer mh-sent-from-folder mh-show-buffer) - (setq show-buffer (with-current-buffer mh-sent-from-folder - (get-buffer mh-show-buffer))) - mh-sent-from-msg) - (let ((to-point (point)) - (to-buffer (current-buffer))) - (if mh-delete-yanked-msg-window-flag - (with-current-buffer mh-sent-from-folder - (delete-windows-on show-buffer))) - ;; Find displayed message - (with-current-buffer show-buffer - (let* ((from-attr (mh-extract-from-attribution)) - (yank-region mark-active) - (mh-ins-str - (cond ((and yank-region - (or (eq 'supercite mh-yank-behavior) - (eq 'autosupercite mh-yank-behavior) - (eq t mh-yank-behavior))) - ;; supercite needs the full header - (concat - (buffer-substring (point-min) (mh-mail-header-end)) - "\n" - (buffer-substring (region-beginning) (region-end)))) - (yank-region - (buffer-substring (region-beginning) (region-end))) - ((or (eq 'body mh-yank-behavior) - (eq 'attribution mh-yank-behavior) - (eq 'autoattrib mh-yank-behavior)) - (buffer-substring - (save-excursion - (goto-char (point-min)) - (mh-goto-header-end 1) - (point)) - (point-max))) - ((or (eq 'supercite mh-yank-behavior) - (eq 'autosupercite mh-yank-behavior) - (eq t mh-yank-behavior)) - (buffer-substring (point-min) (point-max))) - (t - (buffer-substring (point) (point-max)))))) - (with-current-buffer to-buffer - (save-restriction - (narrow-to-region to-point to-point) - (insert (mh-filter-out-non-text mh-ins-str)) - (goto-char (point-max)) ;Needed for sc-cite-original - (push-mark) ;Needed for sc-cite-original - (goto-char (point-min)) ;Needed for sc-cite-original - (mh-insert-prefix-string mh-ins-buf-prefix) - (when (or (eq 'attribution mh-yank-behavior) - (eq 'autoattrib mh-yank-behavior)) - (insert from-attr) - (mh-identity-insert-attribution-verb nil) - (insert "\n\n")) - ;; If the user has selected a region, he has already "edited" the - ;; text, so leave the cursor at the end of the yanked text. In - ;; either case, leave a mark at the opposite end of the included - ;; text to make it easy to jump or delete to the other end of the - ;; text. - (push-mark) - (goto-char (point-max)) - (if (null yank-region) - (mh-exchange-point-and-mark-preserving-active-mark))))))) - (error "There is no current message")))) - - - -;;; Support Routines - -(defun mh-auto-fill-for-letter () - "Perform auto-fill for message. -Header is treated specially by inserting a tab before continuation -lines." - (if (mh-in-header-p) - (let ((fill-prefix "\t")) - (do-auto-fill)) - (do-auto-fill))) - -(defun mh-filter-out-non-text (string) - "Return STRING but without adornments such as MIME buttons and smileys." - (with-temp-buffer - ;; Insert the string to filter - (insert string) - (goto-char (point-min)) - - ;; Remove the MIME buttons - (let ((can-move-forward t) - (in-button nil)) - (while can-move-forward - (cond ((and (not (get-text-property (point) 'mh-data)) - in-button) - (delete-region (1- (point)) (point)) - (setq in-button nil)) - ((get-text-property (point) 'mh-data) - (delete-region (point) - (save-excursion (forward-line) (point))) - (setq in-button t)) - (t (setq can-move-forward (= (forward-line) 0)))))) - - ;; Return the contents without properties... This gets rid of emphasis - ;; and smileys - (buffer-substring-no-properties (point-min) (point-max)))) - -(defun mh-current-fill-prefix () - "Return the `fill-prefix' on the current line as a string." - (save-excursion - (beginning-of-line) - ;; This assumes that the major-mode sets up adaptive-fill-regexp - ;; correctly such as mh-letter-mode or sendmail.el's mail-mode. But - ;; perhaps I should use the variable and simply inserts its value here, - ;; and set it locally in a let scope. --psg - (if (re-search-forward adaptive-fill-regexp nil t) - (match-string 0) - ""))) - -;;;###mh-autoload -(defun mh-letter-next-header-field () - "Cycle to the next header field. -If we are at the last header field go to the start of the message -body." - (let ((header-end (mh-mail-header-end))) - (cond ((>= (point) header-end) (goto-char (point-min))) - ((< (point) (progn - (beginning-of-line) - (re-search-forward mh-letter-header-field-regexp - (line-end-position) t) - (point))) - (beginning-of-line)) - (t (end-of-line))) - (cond ((re-search-forward mh-letter-header-field-regexp header-end t) - (if (mh-letter-skipped-header-field-p (match-string 1)) - (mh-letter-next-header-field) - (mh-letter-skip-leading-whitespace-in-header-field))) - (t (goto-char header-end) - (forward-line))))) - -;;;###mh-autoload -(defun mh-position-on-field (field &optional _ignored) - "Move to the end of the FIELD in the header. -Move to end of entire header if FIELD not found. -Returns non-nil if FIELD was found. -The optional second arg is for pre-version 4 compatibility and is -IGNORED." - (cond ((mh-goto-header-field field) - (mh-header-field-end) - t) - ((mh-goto-header-end 0) - nil))) - -(defun mh-letter-header-field-at-point () - "Return the header field name at point. -A symbol is returned whose name is the string obtained by -downcasing the field name." - (save-excursion - (end-of-line) - (and (re-search-backward mh-letter-header-field-regexp nil t) - (intern (downcase (match-string 1)))))) - -(defun mh-folder-expand-at-point () - "Do folder name completion in Fcc header field." - (let* ((beg (mh-beginning-of-word)) - (end (save-excursion - (goto-char beg) - (mh-beginning-of-word -1)))) - (when (>= end (point)) - (list beg (if (fboundp 'completion-at-point) end (point)) - #'mh-folder-completion-function)))) - -;;;###mh-autoload -(defun mh-complete-word (word choices begin end) - "Complete WORD from CHOICES. -Any match found replaces the text from BEGIN to END." - (let ((completion (try-completion word choices)) - (completions-buffer "*Completions*")) - (cond ((eq completion t) - (ignore-errors - (kill-buffer completions-buffer)) - (message "Completed: %s" word)) - ((null completion) - (ignore-errors - (kill-buffer completions-buffer)) - (message "No completion for %s" word)) - ((stringp completion) - (if (equal word completion) - (with-output-to-temp-buffer completions-buffer - (display-completion-list - (completion-hilit-commonality - (all-completions word choices) - ;; The `common-substring' arg only works if it's a prefix. - (unless (and (functionp choices) - (let ((bounds - (funcall choices - word nil '(boundaries . "")))) - (and (eq 'boundaries (car-safe bounds)) - (< 0 (cadr bounds))))) - word)))) - (ignore-errors - (kill-buffer completions-buffer)) - (delete-region begin end) - (insert completion)))))) - -(defun mh-file-is-vcard-p (file) - "Return t if FILE is a .vcf vcard." - (let ((case-fold-search t)) - (and (stringp file) - (file-exists-p file) - (or (and (not (mh-have-file-command)) - (not (null (string-match "\\.vcf$" file)))) - (string-equal "text/x-vcard" (mh-file-mime-type file)))))) - -;;;###mh-autoload -(defun mh-letter-toggle-header-field-display-button (event) - "Toggle header field display at location of EVENT. -This function does the same thing as -`mh-letter-toggle-header-field-display' except that it is -callable from a mouse button." - (interactive "e") - (mh-do-at-event-location event - (mh-letter-toggle-header-field-display nil))) - -(defun mh-extract-from-attribution () - "Extract phrase or comment from From header field." - (save-excursion - (if (not (mh-goto-header-field "From: ")) - nil - (skip-chars-forward " ") - (cond - ((looking-at "\"\\([^\"\n]+\\)\" \\(<.+>\\)") - (format "%s %s " (match-string 1)(match-string 2))) - ((looking-at "\\([^<\n]+<.+>\\)$") - (format "%s " (match-string 1))) - ((looking-at "\\([^ ]+@[^ ]+\\) +(\\(.+\\))$") - (format "%s <%s> " (match-string 2)(match-string 1))) - ((looking-at " *\\(.+\\)$") - (format "%s " (match-string 1))))))) - -(defun mh-insert-prefix-string (mh-ins-string) - "Insert prefix string before each line in buffer. -The inserted letter is cited using `sc-cite-original' if -`mh-yank-behavior' is one of `supercite' or `autosupercite'. -Otherwise, simply insert MH-INS-STRING before each line." - (goto-char (point-min)) - (cond ((or (eq mh-yank-behavior 'supercite) - (eq mh-yank-behavior 'autosupercite)) - (sc-cite-original)) - (mail-citation-hook - (run-hooks 'mail-citation-hook)) - (t - (or (bolp) (forward-line 1)) - (while (< (point) (point-max)) - (insert mh-ins-string) - (forward-line 1)) - (goto-char (point-min))))) ;leave point like sc-cite-original - -(provide 'mh-letter) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-letter.el ends here diff --git a/lisp/mh-e/mh-limit.el b/lisp/mh-e/mh-limit.el deleted file mode 100644 index 7af7f768b60..00000000000 --- a/lisp/mh-e/mh-limit.el +++ /dev/null @@ -1,331 +0,0 @@ -;;; mh-limit.el --- MH-E display limits -*- lexical-binding: t; -*- - -;; Copyright (C) 2001-2003, 2006-2024 Free Software Foundation, Inc. - -;; Author: Peter S. Galbraith -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; "Poor man's threading" by psg. - -;;; Code: - -(require 'mh-e) -(require 'mh-scan) - -(autoload 'message-fetch-field "message") - - - -;;; MH-Folder Commands - -;; Alphabetical. - -;;;###mh-autoload -(defun mh-delete-subject () - "Delete messages with same subject\\. - -To delete messages faster, you can use this command to delete all -the messages with the same subject as the current message. This -command puts these messages in a sequence named \"subject\". You -can undo this action by using \\[mh-undo] with a prefix argument -and then specifying the \"subject\" sequence." - (interactive) - (let ((count (mh-subject-to-sequence nil))) - (cond - ((not count) ; No subject line, delete msg anyway - (mh-delete-msg (mh-get-msg-num t))) - ((= 0 count) ; No other msgs, delete msg anyway. - (message "No other messages with same Subject following this one") - (mh-delete-msg (mh-get-msg-num t))) - (t ; We have a subject sequence. - (message "Marked %d messages for deletion" count) - (mh-delete-msg 'subject))))) - -;;;###mh-autoload -(defun mh-delete-subject-or-thread () - "Delete messages with same subject or thread\\. - -To delete messages faster, you can use this command to delete all -the messages with the same subject as the current message. This -command puts these messages in a sequence named \"subject\". You -can undo this action by using \\[mh-undo] with a prefix argument -and then specifying the \"subject\" sequence. - -However, if the buffer is displaying a threaded view of the -folder then this command behaves like \\[mh-thread-delete]." - (interactive) - (if (memq 'unthread mh-view-ops) - (mh-thread-delete) - (mh-delete-subject))) - -;;;###mh-autoload -(defun mh-narrow-to-cc (&optional pick-expr) - "Limit to messages with the same \"Cc:\" field. -With a prefix argument, edit PICK-EXPR. - -Use \\\\[mh-widen] to undo this command." - (interactive - (list (mh-edit-pick-expr - (mh-quote-pick-expr (mh-current-message-header-field 'cc))))) - (mh-narrow-to-header-field 'cc pick-expr)) - -;;;###mh-autoload -(defun mh-narrow-to-from (&optional pick-expr) - "Limit to messages with the same \"From:\" field. -With a prefix argument, edit PICK-EXPR. - -Use \\\\[mh-widen] to undo this command." - (interactive - (list (mh-edit-pick-expr - (mh-quote-pick-expr (mh-current-message-header-field 'from))))) - (mh-narrow-to-header-field 'from pick-expr)) - -;;;###mh-autoload -(defun mh-narrow-to-range (range) - "Limit to RANGE. - -Check the documentation of `mh-interactive-range' to see how -RANGE is read in interactive use. - -Use \\\\[mh-widen] to undo this command." - (interactive (list (mh-interactive-range "Narrow to"))) - (when (assoc 'range mh-seq-list) (mh-delete-seq 'range)) - (mh-add-msgs-to-seq (mh-range-to-msg-list range) 'range) - (mh-narrow-to-seq 'range)) - -;;;###mh-autoload -(defun mh-narrow-to-subject (&optional pick-expr) - "Limit to messages with same subject. -With a prefix argument, edit PICK-EXPR. -The string Re: is removed from the search. - -Use \\\\[mh-widen] to undo this command." - (interactive - (list (mh-edit-pick-expr - (mh-quote-pick-expr (mh-current-message-header-field 'subject))))) - (setq pick-expr - (let ((case-fold-search t)) - (cl-loop for s in pick-expr - collect (replace-regexp-in-string "re: *" "" s)))) - (mh-narrow-to-header-field 'subject pick-expr)) - -;;;###mh-autoload -(defun mh-narrow-to-to (&optional pick-expr) - "Limit to messages with the same \"To:\" field. -With a prefix argument, edit PICK-EXPR. - -Use \\\\[mh-widen] to undo this command." - (interactive - (list (mh-edit-pick-expr - (mh-quote-pick-expr (mh-current-message-header-field 'to))))) - (mh-narrow-to-header-field 'to pick-expr)) - - - -;;; Support Routines - -(defun mh-subject-to-sequence (all) - "Put all following messages with same subject in sequence `subject'. -If arg ALL is t, move to beginning of folder buffer to collect all -messages. -If arg ALL is nil, collect only messages from current one on forward. - -Return number of messages put in the sequence: - - nil -> there was no subject line. - - 0 -> there were no later messages with the same - subject (sequence not made) - - >1 -> the total number of messages including current one." - (if (memq 'unthread mh-view-ops) - (mh-subject-to-sequence-threaded all) - (mh-subject-to-sequence-unthreaded all))) - -(defun mh-subject-to-sequence-threaded (all) - "Put all messages with the same subject in the `subject' sequence. - -This function works when the folder is threaded. In this -situation the subject could get truncated and so the normal -matching doesn't work. - -The parameter ALL is non-nil then all the messages in the buffer -are considered, otherwise only the messages after the current one -are taken into account." - (let* ((cur (mh-get-msg-num nil)) - (subject (mh-thread-find-msg-subject cur)) - region msgs) - (if (null subject) - (and (message "No subject line") nil) - (setq region (cons (if all (point-min) (point)) (point-max))) - (mh-iterate-on-range msg region - (when (eq (mh-thread-find-msg-subject msg) subject) - (push msg msgs))) - (setq msgs (sort msgs #'mh-lessp)) - (if (null msgs) - 0 - (when (assoc 'subject mh-seq-list) - (mh-delete-seq 'subject)) - (mh-add-msgs-to-seq msgs 'subject) - (length msgs))))) - -(defvar mh-limit-max-subject-size 41 - "Maximum size of the subject part. -It would be desirable to avoid hard-coding this.") - -(defun mh-subject-to-sequence-unthreaded (all) - "Put all following messages with same subject in sequence `subject'. - -This function only works with an unthreaded folder. If arg ALL is -t, move to beginning of folder buffer to collect all messages. If -arg ALL is nil, collect only messages from current one on -forward. - -Return number of messages put in the sequence: - - nil -> there was no subject line. - 0 -> there were no later messages with the same - subject (sequence not made) - >1 -> the total number of messages including current one." - (if (not (eq major-mode 'mh-folder-mode)) - (error "Not in a folder buffer")) - (save-excursion - (beginning-of-line) - (if (or (not (looking-at mh-scan-subject-regexp)) - (not (match-string 3)) - (string-equal "" (match-string 3))) - (progn (message "No subject line") - nil) - (let ((subject (match-string-no-properties 3)) - (list)) - (if (> (length subject) mh-limit-max-subject-size) - (setq subject (substring subject 0 mh-limit-max-subject-size))) - (save-excursion - (if all - (goto-char (point-min))) - (while (re-search-forward mh-scan-subject-regexp nil t) - (let ((this-subject (match-string-no-properties 3))) - (if (> (length this-subject) mh-limit-max-subject-size) - (setq this-subject (substring this-subject - 0 mh-limit-max-subject-size))) - (if (string-equal this-subject subject) - (setq list (cons (mh-get-msg-num t) list)))))) - (cond - (list - ;; If we created a new sequence, add the initial message to it too. - (if (not (member (mh-get-msg-num t) list)) - (setq list (cons (mh-get-msg-num t) list))) - (if (assoc 'subject mh-seq-list) (mh-delete-seq 'subject)) - ;; sort the result into a sequence - (let ((sorted-list (sort (copy-sequence list) #'mh-lessp))) - (while sorted-list - (mh-add-msgs-to-seq (car sorted-list) 'subject nil) - (setq sorted-list (cdr sorted-list))) - (safe-length list))) - (t - 0)))))) - -(defun mh-edit-pick-expr (default) - "With prefix arg edit a pick expression. -If no prefix arg is given, then return DEFAULT." - (let ((default-string (cl-loop for x in default concat (format " %s" x)))) - (if (or current-prefix-arg (equal default-string "")) - (mh-pick-args-list (read-string "Pick expression: " - default-string)) - default))) - -(defun mh-pick-args-list (s) - "Form list by grouping elements in string S suitable for pick arguments. -For example, the string \"-subject a b c -from Joe User -\" is converted to (\"-subject\" \"a b c\" -\"-from\" \"Joe User \"" - (let ((full-list (split-string s)) - current-arg collection arg-list) - (while full-list - (setq current-arg (car full-list)) - (if (null (string-match "^-" current-arg)) - (setq collection - (if (null collection) - current-arg - (format "%s %s" collection current-arg))) - (when collection - (setq arg-list (append arg-list (list collection))) - (setq collection nil)) - (setq arg-list (append arg-list (list current-arg)))) - (setq full-list (cdr full-list))) - (when collection - (setq arg-list (append arg-list (list collection)))) - arg-list)) - -(defun mh-current-message-header-field (header-field) - "Return a pick regexp to match HEADER-FIELD of the message at point." - (let ((num (mh-get-msg-num nil))) - (when num - (let ((folder mh-current-folder)) - (with-temp-buffer - (insert-file-contents-literally (mh-msg-filename num folder)) - (goto-char (point-min)) - (when (search-forward "\n\n" nil t) - (narrow-to-region (point-min) (point))) - (let* ((field (or (message-fetch-field (format "%s" header-field)) - "")) - (field-option (format "-%s" header-field)) - (patterns (cl-loop for x in (split-string field "[ ]*,[ ]*") - unless (equal x "") - collect (if (string-match "<\\(.*@.*\\)>" x) - (match-string 1 x) - x)))) - (when patterns - (cl-loop with accum = `(,field-option ,(car patterns)) - for e in (cdr patterns) - do (setq accum `(,field-option ,e "-or" ,@accum)) - finally return accum)))))))) - -(defun mh-narrow-to-header-field (_header-field pick-expr) - "Limit to messages whose HEADER-FIELD match PICK-EXPR. -The MH command pick is used to do the match." - (let ((folder mh-current-folder) - (original (mh-coalesce-msg-list - (mh-range-to-msg-list (cons (point-min) (point-max))))) - (msg-list ())) - (with-temp-buffer - (apply #'mh-exec-cmd-output "pick" nil folder - (append original (list "-list") pick-expr)) - (goto-char (point-min)) - (while (not (eobp)) - (let ((num (ignore-errors - (string-to-number - (buffer-substring (point) (line-end-position)))))) - (when num (push num msg-list)) - (forward-line)))) - (if (null msg-list) - (message "No matches") - (when (assoc 'header mh-seq-list) (mh-delete-seq 'header)) - (mh-add-msgs-to-seq msg-list 'header) - (mh-narrow-to-seq 'header)))) - -(provide 'mh-limit) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-limit.el ends here diff --git a/lisp/mh-e/mh-mime.el b/lisp/mh-e/mh-mime.el deleted file mode 100644 index b0920d524a7..00000000000 --- a/lisp/mh-e/mh-mime.el +++ /dev/null @@ -1,1796 +0,0 @@ -;;; mh-mime.el --- MH-E MIME support -*- lexical-binding: t; -*- - -;; Copyright (C) 1993, 1995, 2001-2024 Free Software Foundation, Inc. - -;; Author: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Message composition of MIME message is done with either MH-style -;; directives for mhn or mhbuild (MH 6.8 or later) or MML (MIME Meta -;; Language) tags. - -;; TODO: -;; Paragraph code should not fill # lines if MIME enabled. -;; Implement mh-auto-mh-to-mime (if non-nil, \\[mh-send-letter] -;; invokes mh-mh-to-mime automatically before sending.) -;; Actually, instead of mh-auto-mh-to-mime, -;; should read automhnproc from profile. -;; MIME option to mh-forward command to move to content-description -;; insertion point. - -;;; Code: - -(require 'mh-e) -(require 'mh-acros) -(require 'mh-gnus) ;needed because mh-gnus.el not compiled - -(require 'font-lock) -(require 'gnus-util) -(require 'mailcap) -(require 'mm-decode) -(require 'mm-view) -(require 'mml) - -(autoload 'article-emphasize "gnus-art") -(autoload 'gnus-eval-format "gnus-spec") -(autoload 'mail-content-type-get "mail-parse") -(autoload 'mail-decode-encoded-word-region "mail-parse") -(autoload 'mail-decode-encoded-word-string "mail-parse") -(autoload 'mail-header-parse-content-type "mail-parse") -(autoload 'mail-header-strip-cte "mail-parse") -(autoload 'mail-strip-quoted-names "mail-utils") -(autoload 'message-options-get "message") -(autoload 'message-options-set "message") -(autoload 'message-options-set-recipient "message") -(autoload 'mm-decode-body "mm-bodies") -(autoload 'mm-uu-dissect "mm-uu") -(autoload 'mml-unsecure-message "mml-sec") -(autoload 'widget-convert-button "wid-edit") - - - -;;; Variables - -;; This has to be a macro, since we do: (setf (mh-buffer-data) ...) -;;;###mh-autoload -(defmacro mh-buffer-data () - "Convenience macro to get the MIME data structures of the current buffer." - '(gethash (current-buffer) mh-globals-hash)) - -;; Structure to keep track of MIME handles on a per buffer basis. -(cl-defstruct (mh-buffer-data (:conc-name mh-mime-) - (:constructor mh-make-buffer-data)) - (handles ()) ; List of MIME handles - (handles-cache (make-hash-table)) ; Cache to avoid multiple decodes of - ; nested messages - (parts-count 0) ; The button number is generated from - ; this number - (part-index-hash (make-hash-table))) ; Avoid incrementing the part number - ; for nested messages - -(defvar mh-mm-inline-media-tests - `(("image/jpeg" - mm-inline-image - (lambda (handle) - (mm-valid-and-fit-image-p 'jpeg handle))) - ("image/png" - mm-inline-image - (lambda (handle) - (mm-valid-and-fit-image-p 'png handle))) - ("image/gif" - mm-inline-image - (lambda (handle) - (mm-valid-and-fit-image-p 'gif handle))) - ("image/tiff" - mm-inline-image - (lambda (handle) - (mm-valid-and-fit-image-p 'tiff handle)) ) - ("image/xbm" - mm-inline-image - (lambda (handle) - (mm-valid-and-fit-image-p 'xbm handle))) - ("image/x-xbitmap" - mm-inline-image - (lambda (handle) - (mm-valid-and-fit-image-p 'xbm handle))) - ("image/xpm" - mm-inline-image - (lambda (handle) - (mm-valid-and-fit-image-p 'xpm handle))) - ("image/x-pixmap" - mm-inline-image - (lambda (handle) - (mm-valid-and-fit-image-p 'xpm handle))) - ("image/bmp" - mm-inline-image - (lambda (handle) - (mm-valid-and-fit-image-p 'bmp handle))) - ("image/x-portable-bitmap" - mm-inline-image - (lambda (handle) - (mm-valid-and-fit-image-p 'pbm handle))) - ("text/plain" mm-inline-text identity) - ("text/enriched" mm-inline-text identity) - ("text/richtext" mm-inline-text identity) - ("text/x-patch" mm-display-patch-inline - (lambda (handle) - (locate-library "diff-mode"))) - ("application/emacs-lisp" mm-display-elisp-inline identity) - ("application/x-emacs-lisp" mm-display-elisp-inline identity) - ("text/html" - mm-inline-text-html - (lambda (handle) - mm-text-html-renderer)) - ("text/x-vcard" - mm-inline-text-vcard - (lambda (handle) - (or (featurep 'vcard) - (locate-library "vcard")))) - ("message/delivery-status" mm-inline-text identity) - ("message/rfc822" mh-mm-inline-message identity) - ;;("message/partial" mm-inline-partial identity) - ;;("message/external-body" mm-inline-external-body identity) - ("text/.*" mm-inline-text identity) - ("audio/wav" mm-inline-audio - (lambda (handle) - (and (or (featurep 'nas-sound) (featurep 'native-sound)) - (device-sound-enabled-p)))) - ("audio/au" - mm-inline-audio - (lambda (handle) - (and (or (featurep 'nas-sound) (featurep 'native-sound)) - (device-sound-enabled-p)))) - ("application/pgp-signature" ignore identity) - ("application/x-pkcs7-signature" ignore identity) - ("application/pkcs7-signature" ignore identity) - ("application/x-pkcs7-mime" ignore identity) - ("application/pkcs7-mime" ignore identity) - ("multipart/alternative" ignore identity) - ("multipart/mixed" ignore identity) - ("multipart/related" ignore identity) - ;; Disable audio and image - ("audio/.*" ignore ignore) - ("image/.*" ignore ignore) - ;; Default to displaying as text - (".*" mm-inline-text mm-readable-p)) - "Alist of media types/tests saying whether types can be displayed inline.") - -(defvar mh-mime-save-parts-directory nil - "Default to use for `mh-mime-save-parts-default-directory'. -Set from last use.") - -;; Copied from gnus-art.el (should be checked for other cool things that can -;; be added to the buttons) -(defvar mh-mime-button-commands - '((mh-press-button "\r" "Toggle Display"))) -(defvar mh-mime-button-map - (let ((map (make-sparse-keymap))) - (define-key map [mouse-2] #'mh-push-button) - (dolist (c mh-mime-button-commands) - (define-key map (cadr c) (car c))) - map)) -(defvar mh-mime-button-line-format-alist - '((?T long-type ?s) - (?d description ?s) - (?p index ?s) - (?e dots ?s))) -(defvar mh-mime-button-line-format "%{%([%p. %d%T]%)%}%e\n") -(defvar mh-mime-security-button-pressed nil) -(defvar mh-mime-security-button-line-format "%{%([[%t:%i]%D]%)%}\n") -(defvar mh-mime-security-button-end-line-format "%{%([[End of %t]%D]%)%}\n") -(defvar mh-mime-security-button-line-format-alist - '((?t type ?s) - (?i info ?s) - (?d details ?s) - (?D pressed-details ?s))) -(defvar mh-mime-security-button-map - (let ((map (make-sparse-keymap))) - (define-key map "\r" #'mh-press-button) - (define-key map [mouse-2] #'mh-push-button) - map)) - - - -;;; MH-Folder Commands - -;; Alphabetical. - -;;;###mh-autoload -(defun mh-display-with-external-viewer (part-index) - "View attachment externally. - -If Emacs does not know how to view an attachment, you could save -it into a file and then run some program to open it. It is -easier, however, to launch the program directly from MH-E with -this command. While you'll most likely use this to view -spreadsheets and documents, it is also useful to use your browser -to view HTML attachments with higher fidelity than what Emacs can -provide. - -This command displays the attachment associated with the button -under the cursor. If the cursor is not located over a button, -then the cursor first moves to the next button, wrapping to the -beginning of the message if necessary. You can provide a numeric -prefix argument PART-INDEX to view the attachment labeled with -that number. - -This command tries to provide a reasonable default for the viewer -by calling the Emacs function `mailcap-mime-info'. This function -usually reads the file \"/etc/mailcap\"." - (interactive "P") - (when (consp part-index) (setq part-index (car part-index))) - (mh-folder-mime-action - part-index - (lambda () - (let* ((part (get-text-property (point) 'mh-data)) - (type (mm-handle-media-type part)) - (methods (mapcar (lambda (x) (list (cdr (assoc 'viewer x)))) - (mailcap-mime-info type 'all))) - (def (caar methods)) - (prompt (format-prompt "Viewer" def)) - (method (completing-read prompt methods nil nil nil nil def)) - (folder mh-show-folder-buffer) - (buffer-read-only nil)) - (when (string-match "^[^% \t]+$" method) - (setq method (concat method " %s"))) - (mh-flet - ((mm-handle-set-external-undisplayer - (handle function) - (mh-handle-set-external-undisplayer folder handle function))) - (unwind-protect (mm-display-external part method) - (set-buffer-modified-p nil))))) - nil)) - -;;;###mh-autoload -(defun mh-folder-inline-mime-part (part-index) - "Show attachment verbatim. - -You can view the raw contents of an attachment with this command. -This command displays (or hides) the contents of the attachment -associated with the button under the cursor verbatim. If the -cursor is not located over a button, then the cursor first moves -to the next button, wrapping to the beginning of the message if -necessary. - -You can also provide a numeric prefix argument PART-INDEX to view -the attachment labeled with that number." - (interactive "P") - (when (consp part-index) (setq part-index (car part-index))) - (mh-folder-mime-action part-index #'mh-mime-inline-part nil)) - -(defun mh-mime-inline-part () - "Toggle display of the raw MIME part." - (interactive) - (let* ((buffer-read-only nil) - (data (get-text-property (point) 'mh-data)) - (inserted-flag (get-text-property (point) 'mh-mime-inserted)) - (displayed-flag (mm-handle-displayed-p data)) - (point (point)) - start end) - (cond ((and data (not inserted-flag) (not displayed-flag)) - (let ((contents (mm-get-part data))) - (add-text-properties (line-beginning-position) - (line-end-position) '(mh-mime-inserted t)) - (setq start (point-marker)) - (forward-line 1) - (mm-insert-inline data contents) - (setq end (point-marker)) - (add-text-properties - start (progn (goto-char start) (line-end-position)) - `(mh-region (,start . ,end))))) - ((and data (or inserted-flag displayed-flag)) - (mh-press-button) - (message "MIME part already inserted"))) - (goto-char point) - (set-buffer-modified-p nil))) - -;;;###mh-autoload -(defun mh-folder-save-mime-part (part-index) - "Save (output) attachment. - -This command saves the attachment associated with the button under the -cursor. If the cursor is not located over a button, then the cursor -first moves to the next button, wrapping to the beginning of the -message if necessary. - -You can also provide a numeric prefix argument PART-INDEX to save the -attachment labeled with that number. - -This command prompts you for a filename and suggests a specific name -if it is available." - (interactive "P") - (when (consp part-index) (setq part-index (car part-index))) - (mh-folder-mime-action part-index #'mh-mime-save-part nil)) - -(defun mh-mime-save-part () - "Save MIME part at point." - (interactive) - (let ((data (get-text-property (point) 'mh-data))) - (when data - (let ((mm-default-directory - (file-name-as-directory (or mh-mime-save-parts-directory - default-directory)))) - (mh-mm-save-part data) - (setq mh-mime-save-parts-directory mm-default-directory))))) - -;;;###mh-autoload -(defun mh-folder-toggle-mime-part (part-index) - "View attachment. - -This command displays (or hides) the attachment associated with -the button under the cursor. If the cursor is not located over a -button, then the cursor first moves to the next button, wrapping -to the beginning of the message if necessary. This command has -the advantage over related commands of working from the MH-Folder -buffer. - -You can also provide a numeric prefix argument PART-INDEX to view -the attachment labeled with that number. If Emacs does not know -how to display the attachment, then Emacs offers to save the -attachment in a file." - (interactive "P") - (when (consp part-index) (setq part-index (car part-index))) - (mh-folder-mime-action part-index #'mh-press-button t)) - -;;;###mh-autoload -(defun mh-mime-save-parts (prompt) - "Save attachments. - -You can save all of the attachments at once with this command. -The attachments are saved in the directory specified by the -option `mh-mime-save-parts-default-directory' unless you use a -prefix argument PROMPT in which case you are prompted for the -directory. These directories may be superseded by MH profile -components, since this function calls on \"mhstore\" (\"mhn\") to -do the work." - (interactive "P") - (let ((msg (if (eq major-mode 'mh-show-mode) - (mh-show-buffer-message-number) - (mh-get-msg-num t))) - (folder (if (eq major-mode 'mh-show-mode) - mh-show-folder-buffer - mh-current-folder)) - (command (if (mh-variant-p 'nmh) "mhstore" "mhn")) - (directory - (cond - ((and (or prompt - (equal nil mh-mime-save-parts-default-directory) - (equal t mh-mime-save-parts-default-directory)) - (not mh-mime-save-parts-directory)) - (read-directory-name "Store in directory: " nil nil t)) - ((and (or prompt - (equal t mh-mime-save-parts-default-directory)) - mh-mime-save-parts-directory) - (read-directory-name "Store in directory: " - mh-mime-save-parts-directory nil t)) - ((stringp mh-mime-save-parts-default-directory) - mh-mime-save-parts-default-directory) - (t - mh-mime-save-parts-directory)))) - (if (and (equal directory "") mh-mime-save-parts-directory) - (setq directory mh-mime-save-parts-directory)) - (if (not (file-directory-p directory)) - (message "No directory specified") - (if (equal nil mh-mime-save-parts-default-directory) - (setq mh-mime-save-parts-directory directory)) - (with-current-buffer (get-buffer-create mh-log-buffer) - (let (default-directory) - (cd directory) - (setq mh-mime-save-parts-directory directory) - (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 (not (mh-variant-p 'nmh)) - "-store")))) - (if (> (buffer-size) initial-size) - (save-window-excursion - (switch-to-buffer-other-window mh-log-buffer) - (sit-for 3))))))))) - -;;;###mh-autoload -(defun mh-toggle-mh-decode-mime-flag () - "Toggle the value of `mh-decode-mime-flag'." - (interactive) - (setq mh-decode-mime-flag (not mh-decode-mime-flag)) - (mh-show nil t) - (message "%s" (if mh-decode-mime-flag - "Processing attachments normally" - "Displaying raw message"))) - -;;;###mh-autoload -(defun mh-toggle-mime-buttons () - "Toggle option `mh-display-buttons-for-inline-parts-flag'." - (interactive) - (setq mh-display-buttons-for-inline-parts-flag - (not mh-display-buttons-for-inline-parts-flag)) - (mh-show nil t)) - - - -;;; MIME Display Routines - -(defun mh-mm-inline-message (handle) - "Display message, HANDLE. -The function decodes the message and displays it. It avoids -decoding the same message multiple times." - (let ((b (point)) - (clean-message-header mh-clean-message-header-flag) - (invisible-headers mh-invisible-header-fields-compiled) - ) ;; (visible-headers nil) - (save-excursion - (save-restriction - (narrow-to-region b b) - (mm-insert-part handle) - (mh-mime-display - (or (gethash handle (mh-mime-handles-cache (mh-buffer-data))) - (setf (gethash handle (mh-mime-handles-cache (mh-buffer-data))) - (let ((handles (mm-dissect-buffer nil))) - (if handles - (mm-uu-dissect-text-parts handles) - (setq handles (mm-uu-dissect))) - (setf (mh-mime-handles (mh-buffer-data)) - (mm-merge-handles - handles (mh-mime-handles (mh-buffer-data)))) - handles)))) - - (goto-char (point-min)) - (mh-show-xface) - (cond (clean-message-header - (mh-clean-msg-header (point-min) - invisible-headers - nil) ;; visible-headers - (goto-char (point-min))) - (t - (mh-start-of-uncleaned-message))) - (mh-decode-message-header) - (mh-show-addr) - ;; The other highlighting types don't need anything special - (when (eq mh-highlight-citation-style 'gnus) - (mh-gnus-article-highlight-citation)) - (goto-char (point-min)) - (insert "\n------- Forwarded Message\n\n") - (mh-display-smileys) - (mh-display-emphasis) - (mm-handle-set-undisplayer - handle - (let ((beg (point-min-marker)) - (end (point-max-marker))) - (lambda () - (let ((inhibit-read-only t)) - (delete-region beg end))))))))) - -;;;###mh-autoload -(defun mh-decode-message-header () - "Decode RFC2047 encoded message header fields." - (when mh-decode-mime-flag - (let ((buffer-read-only nil)) - (mail-decode-encoded-word-region (point-min) (mh-mail-header-end))))) - -;;;###mh-autoload -(defun mh-decode-message-subject () - "Decode RFC2047 encoded message header fields." - (when mh-decode-mime-flag - (save-excursion - (let ((buffer-read-only nil)) - (mail-decode-encoded-word-region - (progn (mh-goto-header-field "Subject:") (point)) - (progn (mh-header-field-end) (point))))))) - -;;;###mh-autoload -(defun mh-mime-display (&optional pre-dissected-handles) - "Display (and possibly decode) MIME handles. -Optional argument, PRE-DISSECTED-HANDLES is a list of MIME -handles. If present they are displayed otherwise the buffer is -parsed and then displayed." - (let ((handles ()) - (folder mh-show-folder-buffer) - (raw-message-data (buffer-string))) - (mh-flet - ((mm-handle-set-external-undisplayer - (handle function) - (mh-handle-set-external-undisplayer folder handle function))) - (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) - (if (setq handles (mm-dissect-buffer nil)) - (mm-uu-dissect-text-parts handles) - (setq handles (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))) - - (cond ((and handles - (or (not (stringp (car handles))) - (cdr handles))) - ;; Go to 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)) - - ;; Display the MIME handles - (mh-mime-display-part handles)) - (t - (mh-signature-highlight)))) - (error - (message "Could not display body: %s" (error-message-string err)) - (delete-region (point-min) (point-max)) - (insert raw-message-data)))))) - -(defun mh-decode-message-body () - "Decode message based on charset. -If message has been encoded for transfer take that into account." - (let (ct charset cte) - (goto-char (point-min)) - (re-search-forward "\n\n" nil t) - (save-restriction - (narrow-to-region (point-min) (point)) - (setq 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 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 cte))) - (car ct)))))) - -(defun mh-mime-display-part (handle) - "Decides the viewer to call based on the type of HANDLE." - (cond ((null handle) - nil) - ((not (stringp (car handle))) - (mh-mime-display-single handle)) - ((equal (car handle) "multipart/alternative") - (mh-mime-display-alternative (cdr handle))) - ((and mh-pgp-support-flag - (or (equal (car handle) "multipart/signed") - (equal (car handle) "multipart/encrypted"))) - (mh-mime-display-security handle)) - (t - (mh-mime-display-mixed (cdr handle))))) - -(defun mh-mime-display-mixed (handles) - "Display the list of MIME parts, HANDLES recursively." - (mapcar #'mh-mime-display-part handles)) - -(defun mh-mime-display-alternative (handles) - "Choose among the alternatives, HANDLES the part that will be displayed. -If no part is preferred then all the parts are displayed." - (let* ((preferred (mm-preferred-alternative handles)) - (others (cl-loop for x in handles unless (eq x preferred) collect x))) - (cond ((and preferred - (stringp (car preferred))) - (mh-mime-display-part preferred) - (mh-mime-maybe-display-alternatives others)) - (preferred - (save-restriction - (narrow-to-region (point) (if (eobp) (point) (1+ (point)))) - (mh-mime-display-single preferred) - (mh-mime-maybe-display-alternatives others) - (goto-char (point-max)))) - (t - (mh-mime-display-mixed handles))))) - -(defun mh-mime-maybe-display-alternatives (alternatives) - "Show buttons for ALTERNATIVES. -If `mh-display-buttons-for-alternatives-flag' is non-nil then -display buttons for alternative parts that are usually -suppressed." - (when (and mh-display-buttons-for-alternatives-flag alternatives) - (insert "\n----------------------------------------------------\n") - (insert "Alternatives:\n") - (dolist (x alternatives) - (insert "\n") - (mh-insert-mime-button x (mh-mime-part-index x) nil)) - (insert "\n----------------------------------------------------\n"))) - -(defun mh-mime-display-security (handle) - "Display PGP encrypted/signed message, HANDLE." - (save-restriction - (narrow-to-region (point) (point)) - (insert "\n") - (mh-insert-mime-security-button handle) - (mh-mime-display-mixed (cdr handle)) - (insert "\n") - (let ((mh-mime-security-button-line-format - mh-mime-security-button-end-line-format)) - (mh-insert-mime-security-button handle)) - (mm-set-handle-multipart-parameter - handle 'mh-region (cons (point-min-marker) (point-max-marker))))) - -(defun mh-mime-display-single (handle) - "Display a leaf node, HANDLE in the MIME tree." - (let* ((type (mm-handle-media-type handle)) - (small-image-flag (mh-small-image-p handle)) - (attachmentp (equal (car (mm-handle-disposition handle)) - "attachment")) - (inlinep (and (equal (car (mm-handle-disposition handle)) "inline") - (mm-automatic-display-p handle) - (mm-inlinable-p handle) - (mm-inlined-p handle))) - (displayp (or inlinep ; show if inline OR - (mh-inline-vcard-p handle); inline vcard OR - (and (not attachmentp) ; if not an attachment - (or small-image-flag ; and small image - ; and user wants inline - (and (not (equal - (mm-handle-media-supertype handle) - "image")) - (mm-automatic-display-p handle) - (mm-inlinable-p handle) - (mm-inlined-p handle))))))) - (save-restriction - (narrow-to-region (point) (if (eobp) (point) (1+ (point)))) - (cond ((and mh-pgp-support-flag - (equal type "application/pgp-signature")) - nil) ; skip signatures as they are already handled... - ((not displayp) - (insert "\n") - (mh-insert-mime-button handle (mh-mime-part-index handle) nil)) - ((and displayp - (not mh-display-buttons-for-inline-parts-flag)) - (or (mm-display-part handle) - (mm-display-part handle)) - (mh-signature-highlight handle)) - ((and displayp - mh-display-buttons-for-inline-parts-flag) - (insert "\n") - (mh-insert-mime-button handle (mh-mime-part-index handle) nil) - (forward-line -1) - (mh-mm-display-part handle))) - (goto-char (point-max))))) - -;; There is a bug in Gnus inline image display due to which an extra line -;; gets inserted every time it is viewed. To work around that problem we are -;; using an extra property 'mh-region to remember the region that is added -;; when the button is clicked. The region is then deleted to make sure that -;; no extra lines get inserted. -(defun mh-mm-display-part (handle) - "Toggle display of button for MIME part, HANDLE." - (beginning-of-line) - (let ((id (get-text-property (point) 'mh-part)) - (point (point)) - (window (selected-window)) - (mail-parse-charset 'nil) - (mail-parse-ignored-charsets nil) - region buffer-read-only) - (save-excursion - (unwind-protect - (let ((win (get-buffer-window (current-buffer) t))) - (when win - (select-window win)) - (goto-char point) - - (if (mm-handle-displayed-p handle) - ;; This will remove the part. - (progn - ;; Delete the button and displayed part (if any) - (let ((region (get-text-property point 'mh-region))) - (when region - (remove-images (car region) (cdr region))) - (mm-display-part handle) - (when region - (delete-region (car region) (cdr region)))) - ;; Delete button (if it still remains). This happens for - ;; externally displayed parts where the previous step does - ;; nothing. - (unless (eolp) - (delete-region (point) (progn (forward-line) (point))))) - (save-restriction - (delete-region (point) (progn (forward-line 1) (point))) - (narrow-to-region (point) (point)) - ;; Maybe we need another unwind-protect here. - (when (equal (mm-handle-media-supertype handle) "image") - (insert "\n")) - (when (and (not (eq (ignore-errors (mm-display-part handle)) - 'inline)) - (equal (mm-handle-media-supertype handle) - "image")) - (goto-char (point-min)) - (delete-char 1)) - (when (equal (mm-handle-media-supertype handle) "text") - (when (eq mh-highlight-citation-style 'gnus) - (mh-gnus-article-highlight-citation)) - (mh-display-smileys) - (mh-display-emphasis) - (mh-signature-highlight handle)) - (setq region (cons (progn (goto-char (point-min)) - (point-marker)) - (progn (goto-char (point-max)) - (point-marker))))))) - (when (window-live-p window) - (select-window window)) - (goto-char point) - (beginning-of-line) - (mh-insert-mime-button handle id (mm-handle-displayed-p handle)) - (goto-char point) - (when region - (add-text-properties (line-beginning-position) - (line-end-position) - `(mh-region ,region))))))) - -(defun mh-mime-part-index (handle) - "Generate the button number for MIME part, HANDLE. -Notice that a hash table is used to display the same number when -buttons need to be displayed multiple times (for instance when -nested messages are opened)." - (or (gethash handle (mh-mime-part-index-hash (mh-buffer-data))) - (setf (gethash handle (mh-mime-part-index-hash (mh-buffer-data))) - (cl-incf (mh-mime-parts-count (mh-buffer-data)))))) - -(defun mh-small-image-p (handle) - "Decide whether HANDLE is a \"small\" image that can be displayed inline. -This is only useful if a Content-Disposition header is not present." - (let ((media-test (caddr (assoc (car (mm-handle-type handle)) - mh-mm-inline-media-tests))) - (mm-inline-large-images t)) - (and media-test - (equal (mm-handle-media-supertype handle) "image") - (funcall media-test handle) ; Since mm-inline-large-images is T, - ; this only tells us if the image is - ; something that emacs can display - (let ((image (mm-get-image handle))) - (let ((size (and (fboundp 'image-size) (image-size image)))) - (and size - (< (cdr size) (or mh-max-inline-image-height - (1- (window-height)))) - (< (car size) (or mh-max-inline-image-width - (window-width))))))))) - -(defun mh-inline-vcard-p (handle) - "Decide if HANDLE is a vcard that must be displayed inline." - (let ((type (mm-handle-type handle))) - (and (or (featurep 'vcard) (fboundp 'vcard-pretty-print)) - (consp type) - (equal (car type) "text/x-vcard") - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (not (mh-signature-separator-p))))))) - -(defun mh-signature-highlight (&optional handle) - "Highlight message signature in HANDLE. -The optional argument, HANDLE is a MIME handle if the function is -being used to highlight the signature in a MIME part." - (let ((regexp - (cond ((not handle) "^-- $") - ((not (and (equal (mm-handle-media-supertype handle) "text") - (equal (mm-handle-media-subtype handle) "html"))) - "^-- $") - ((eq mm-text-html-renderer 'lynx) "^ --$") - (t "^--$")))) - (save-excursion - (goto-char (point-max)) - (when (re-search-backward regexp nil t) - (let ((ov (make-overlay (point) (point-max)))) - (overlay-put ov 'face 'mh-show-signature) - (overlay-put ov 'evaporate t)))))) - - - -;;; Button Display - -(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 like \"K v\" which operate on individual MIME parts." - ;; The button could be displayed by a previous decode. In that case - ;; undisplay it if we need a hidden button. - (when (and (mm-handle-displayed-p handle) (not displayed)) - (mm-display-part handle)) - (let ((name (or (mail-content-type-get (mm-handle-type handle) 'name) - (mail-content-type-get (mm-handle-disposition handle) - 'filename) - (mail-content-type-get (mm-handle-type handle) 'url) - "")) - (type (mm-handle-media-type handle)) - begin end) - (if (string-match ".*/" name) (setq name (substring name (match-end 0)))) - ;; These vars are passed by dynamic-scoping to - ;; mh-mime-button-line-format-alist via gnus-eval-format. - (mh-dlet* ((index index) - (description (mail-decode-encoded-word-string - (or (mm-handle-description handle) ""))) - (dots (if (or displayed (mm-handle-displayed-p handle)) - " " "...")) - (long-type (concat type (and (not (equal name "")) - (concat "; " name))))) - (unless (equal description "") - (setq long-type (concat " --- " long-type))) - (unless (bolp) (insert "\n")) - (setq begin (point)) - (gnus-eval-format - mh-mime-button-line-format mh-mime-button-line-format-alist - `(keymap ,mh-mime-button-map - mh-callback mh-mm-display-part - mh-part ,index - mh-data ,handle))) - (setq end (point)) - (widget-convert-button - 'link begin end - :mime-handle handle - :action 'mh-widget-press-button - :button-keymap mh-mime-button-map - :help-echo - "Mouse-2 click or press RET (in show buffer) to toggle display") - (dolist (ov (overlays-in begin end)) - (overlay-put ov 'evaporate t)))) - -(defun mh-insert-mime-security-button (handle) - "Display buttons for PGP message, HANDLE." - (let* ((protocol (mm-handle-multipart-ctl-parameter handle 'protocol)) - (crypto-type (or (nth 2 (assoc protocol mm-verify-function-alist)) - (nth 2 (assoc protocol mm-decrypt-function-alist)) - "Unknown")) - begin end face) - ;; These vars are passed by dynamic-scoping to - ;; mh-mime-security-button-line-format-alist via gnus-eval-format. - (mh-dlet* ((type (concat crypto-type - (if (equal (car handle) "multipart/signed") - " Signed" " Encrypted") - " Part")) - (info (or (mm-handle-multipart-ctl-parameter - handle 'gnus-info) - "Undecided")) - (details (mm-handle-multipart-ctl-parameter - handle 'gnus-details)) - pressed-details) - (setq details (if details (concat "\n" details) "")) - (setq pressed-details (if mh-mime-security-button-pressed details "")) - (setq face (mh-mime-security-button-face info)) - (unless (bolp) (insert "\n")) - (setq begin (point)) - (gnus-eval-format - mh-mime-security-button-line-format - mh-mime-security-button-line-format-alist - `(keymap ,mh-mime-security-button-map - mh-button-pressed ,mh-mime-security-button-pressed - mh-callback mh-mime-security-press-button - mh-line-format ,mh-mime-security-button-line-format - mh-data ,handle)) - (setq end (point)) - (widget-convert-button 'link begin end - :mime-handle handle - :action 'mh-widget-press-button - :button-keymap mh-mime-security-button-map - :button-face face - :help-echo "Mouse-2 click or press RET (in show buffer) to see security details.") - (dolist (ov (overlays-in begin end)) - (overlay-put ov 'evaporate t)) - (when (equal info "Failed") - (let* ((type (if (equal (car handle) "multipart/signed") - "verification" "decryption")) - (warning (if (equal type "decryption") - "(passphrase may be incorrect)" ""))) - (message "%s %s failed %s" crypto-type type warning)))))) - -(defun mh-mime-security-button-face (info) - "Return the button face to use for encrypted/signed mail based on INFO." - (cond ((string-match "OK" info) ;Decrypted mail - 'mh-show-pgg-good) - ((string-match "Failed" info) ;Decryption failed or signature invalid - 'mh-show-pgg-bad) - ((string-match "Undecided" info);Unprocessed mail - 'mh-show-pgg-unknown) - ((string-match "Untrusted" info);Key not trusted - 'mh-show-pgg-unknown) - (t - 'mh-show-pgg-good))) - - - -;;; Button Handlers - -(defun mh-folder-mime-action (part-index action include-security-flag) - "Go to PART-INDEX and carry out ACTION. - -If PART-INDEX is nil then go to the next part in the buffer. The -search for the next buffer wraps around if end of buffer is reached. -If argument INCLUDE-SECURITY-FLAG is non-nil then include security -info buttons when searching for a suitable parts." - (unless mh-showing-mode - (mh-show)) - (mh-in-show-buffer (mh-show-buffer) - (let ((criterion - (cond (part-index - (lambda (p) - (let ((part (get-text-property p 'mh-part))) - (and (integerp part) (= part part-index))))) - (t (lambda (p) - (if include-security-flag - (get-text-property p 'mh-data) - (integerp (get-text-property p 'mh-part))))))) - (point (point))) - (cond ((and (get-text-property point 'mh-part) - (or (null part-index) - (= (get-text-property point 'mh-part) part-index))) - (funcall action)) - ((and (get-text-property point 'mh-data) - include-security-flag - (null part-index)) - (funcall action)) - (t - (mh-goto-next-button nil criterion) - (if (= (point) point) - (message "No matching MIME part found") - (funcall action))))))) - -;;;###mh-autoload -(defun mh-goto-next-button (backward-flag &optional criterion) - "Search for next button satisfying criterion. - -If BACKWARD-FLAG is non-nil search backward in the buffer for a mime -button. -If CRITERION is a function or a symbol which has a function binding -then that function must return non-nil at the button we stop." - (unless (or (and (symbolp criterion) (fboundp criterion)) - (functionp criterion)) - (setq criterion (lambda (_) t))) - ;; Move to the next button in the buffer satisfying criterion - (goto-char (or (save-excursion - (beginning-of-line) - ;; Find point before current button - (let ((point-before-current-button - (save-excursion - (while (get-text-property (point) 'mh-data) - (unless (= (forward-line - (if backward-flag 1 -1)) - 0) - (if backward-flag - (goto-char (point-min)) - (goto-char (point-max))))) - (point)))) - ;; Skip over current button - (while (and (get-text-property (point) 'mh-data) - (not (if backward-flag (bobp) (eobp)))) - (forward-line (if backward-flag -1 1))) - ;; Stop at next MIME button if any exists. - (cl-block loop - (while (/= (progn - (unless (= (forward-line - (if backward-flag -1 1)) - 0) - (if backward-flag - (goto-char (point-max)) - (goto-char (point-min))) - (beginning-of-line)) - (point)) - point-before-current-button) - (when (and (get-text-property (point) 'mh-data) - (funcall criterion (point))) - (cl-return-from loop (point)))) - nil))) - (point)))) - -(defun mh-widget-press-button (widget _el) - "Callback for widget, WIDGET. -Parameter EL is unused." - (goto-char (widget-get widget :from)) - (mh-press-button)) - -(defun mh-press-button () - "View contents of button. - -This command is a toggle so if you use it again on the same -attachment, the attachment is hidden." - (interactive) - (let ((mm-inline-media-tests mh-mm-inline-media-tests) - (data (get-text-property (point) 'mh-data)) - (function (get-text-property (point) 'mh-callback)) - (buffer-read-only nil) - (folder mh-show-folder-buffer)) - (mh-flet - ((mm-handle-set-external-undisplayer - (handle function) - (mh-handle-set-external-undisplayer folder handle function))) - (when (and function (eolp)) - (backward-char)) - (unwind-protect (and function (funcall function data)) - (set-buffer-modified-p nil))))) - -(defun mh-push-button (event) - "Click MIME button for EVENT. - -If the MIME part is visible then it is removed. Otherwise the -part is displayed. This function is called when the mouse is used -to click the MIME button." - (interactive "e") - (mh-do-at-event-location event - (let ((folder mh-show-folder-buffer) - (mm-inline-media-tests mh-mm-inline-media-tests) - (data (get-text-property (point) 'mh-data)) - (function (get-text-property (point) 'mh-callback))) - (mh-flet - ((mm-handle-set-external-undisplayer - (handle func) - (mh-handle-set-external-undisplayer folder handle func))) - (and function (funcall function data)))))) - -(defun mh-handle-set-external-undisplayer (folder handle function) - "Replacement for `mm-handle-set-external-undisplayer'. - -This is only called in recent versions of Gnus. The MIME handles -are stored in data structures corresponding to MH-E folder buffer -FOLDER instead of in Gnus (as in the original). The MIME part, -HANDLE is associated with the undisplayer FUNCTION." - (if (mm-keep-viewer-alive-p handle) - (let ((new-handle (copy-sequence handle))) - (mm-handle-set-undisplayer new-handle function) - (mm-handle-set-undisplayer handle nil) - (with-current-buffer folder - (push new-handle (mh-mime-handles (mh-buffer-data))))) - (mm-handle-set-undisplayer handle function))) - -(defun mh-mime-security-press-button (handle) - "Callback from security button for part HANDLE." - (if (mm-handle-multipart-ctl-parameter handle 'gnus-info) - (mh-mime-security-show-details handle) - (let ((region (mm-handle-multipart-ctl-parameter handle 'mh-region)) - point) - (setq point (point)) - (goto-char (car region)) - (delete-region (car region) (cdr region)) - (with-current-buffer (mm-handle-multipart-ctl-parameter handle 'buffer) - (let* ((mm-verify-option 'known) - (mm-decrypt-option 'known) - (new (mm-possibly-verify-or-decrypt (cdr handle) handle))) - (unless (eq new (cdr handle)) - (mm-destroy-parts (cdr handle)) - (setcdr handle new)))) - (mh-mime-display-security handle) - (goto-char point)))) - -;; I rewrote the security part because Gnus doesn't seem to ever minimize -;; the button. That is once the mime-security button is pressed there seems -;; to be no way of getting rid of the inserted text. -(defun mh-mime-security-show-details (handle) - "Toggle display of detailed security info for HANDLE." - (let ((details (mm-handle-multipart-ctl-parameter handle 'gnus-details))) - (when details - (let ((mh-mime-security-button-pressed - (not (get-text-property (point) 'mh-button-pressed))) - (mh-mime-security-button-line-format - (get-text-property (point) 'mh-line-format))) - (forward-char -1) - (while (eq (get-text-property (point) 'mh-line-format) - mh-mime-security-button-line-format) - (forward-char -1)) - (forward-char) - (save-restriction - (narrow-to-region (point) (point)) - (mh-insert-mime-security-button handle)) - (delete-region - (point) - (or (text-property-not-all - (point) (point-max) - 'mh-line-format mh-mime-security-button-line-format) - (point-max))) - (forward-line -1))))) - - - -;;; Miscellaneous Article Washing - -;;;###mh-autoload -(defun mh-add-missing-mime-version-header () - "Some mail programs don't put a MIME-Version header. -I have seen this only in spam, so maybe we shouldn't fix -this ;-)" - (save-excursion - (goto-char (point-min)) - (re-search-forward "\n\n" nil t) - (save-restriction - (narrow-to-region (point-min) (point)) - (when (and (message-fetch-field "content-type") - (not (message-fetch-field "mime-version"))) - (goto-char (point-min)) - (insert "MIME-Version: 1.0\n"))))) - -;;;###mh-autoload -(defun mh-display-smileys () - "Display smileys." - (when (and mh-graphical-smileys-flag (mh-small-show-buffer-p)) - (smiley-region (point-min) (point-max)))) - -;;;###mh-autoload -(defun mh-display-emphasis () - "Display graphical emphasis." - (when (and mh-graphical-emphasis-flag (mh-small-show-buffer-p)) - (mh-flet - ((article-goto-body ())) ; shadow this function to do nothing - (save-excursion - (goto-char (point-min)) - (article-emphasize))))) - -(defun mh-small-show-buffer-p () - "Check if show buffer is small. -This is used to decide if smileys and graphical emphasis should be -displayed." - (>= 64000 (buffer-size))) - - - -;;; MH-Letter Commands - -;; MH-E commands are alphabetical; specific support routines follow command. - -;;;###mh-autoload -(defun mh-compose-forward (&optional description folder range) - "Add tag to forward a message. - -You are prompted for a content DESCRIPTION, the name of the -FOLDER in which the messages to forward are located, and a RANGE -of messages, which defaults to the current message in that -folder. Check the documentation of `mh-interactive-range' to see -how RANGE is read in interactive use. - -The option `mh-compose-insertion' controls what type of tags are inserted." - (interactive - (let* ((description - (mml-minibuffer-read-description)) - (folder - (mh-prompt-for-folder "Message from" - mh-sent-from-folder nil)) - (default - (if (and (equal folder mh-sent-from-folder) - (numberp mh-sent-from-msg)) - mh-sent-from-msg - (nth 0 (mh-translate-range folder "cur")))) - (range - (mh-read-range "Forward" folder - (or (and default - (number-to-string default)) - t) - t t))) - (list description folder range))) - (let ((messages (mapconcat #'identity (mh-list-to-string range) " "))) - (dolist (message (mh-translate-range folder messages)) - (if (equal mh-compose-insertion 'mml) - (mh-mml-forward-message description folder (format "%s" message)) - (mh-mh-forward-message description folder (format "%s" message)))))) - -;;;###mh-autoload -(defun mh-mml-forward-message (description folder message) - "Forward a message as attachment. - -The function will prompt the user for a DESCRIPTION, a FOLDER and -MESSAGE number." - (let ((msg (if (and (equal message "") (numberp mh-sent-from-msg)) - mh-sent-from-msg - (string-to-number message)))) - (cond ((integerp msg) - (mml-attach-file (format "%s%s/%d" - mh-user-path (substring folder 1) msg) - "message/rfc822" - (if (string= "" description) nil description) - "inline")) - (t (error "The message number, %s, is not an integer" msg))))) - -(defun mh-mh-forward-message (&optional description folder messages) - "Add tag to forward a message. -You are prompted for a content DESCRIPTION, the name of the -FOLDER in which the messages to forward are located, and the -MESSAGES' numbers. - -See also \\[mh-mh-to-mime]." - (interactive (list - (mml-minibuffer-read-description) - (mh-prompt-for-folder "Message from" mh-sent-from-folder nil) - (read-string (format-prompt "Messages" mh-sent-from-msg)))) - (beginning-of-line) - (insert "#forw [") - (and description - (not (string= description "")) - (insert description)) - (insert "]") - (and folder - (not (string= folder "")) - (insert " " folder)) - (if (and messages - (not (string= messages ""))) - (let ((start (point))) - (insert " " messages) - (subst-char-in-region start (point) ?, ? )) - (if (numberp mh-sent-from-msg) - (insert " " (int-to-string mh-sent-from-msg)))) - (insert "\n")) - -;;;###mh-autoload -(defun mh-compose-insertion (&optional inline) - "Add tag to include a file such as an image or sound. - -You are prompted for the filename containing the object, the -media type if it cannot be determined automatically, and a -content description. If you're using MH-style directives, you -will also be prompted for additional attributes. - -The option `mh-compose-insertion' controls what type of tags are -inserted. Optional argument INLINE means make it an inline -attachment." - (interactive "P") - (if (equal mh-compose-insertion 'mml) - (if inline - (mh-mml-attach-file "inline") - (mh-mml-attach-file)) - (call-interactively 'mh-mh-attach-file))) - -(defun mh-mml-attach-file (&optional disposition) - "Add a tag to insert a MIME message part from a file. - -You are prompted for the filename containing the object, the -media type if it cannot be determined automatically, a content -description and the DISPOSITION of the attachment. - -This is basically `mml-attach-file' from Gnus, modified such that a prefix -argument yields an \"inline\" disposition and Content-Type is determined -automatically." - (let* ((file (mml-minibuffer-read-file "Attach file: ")) - (type (mh-minibuffer-read-type file)) - (description (mml-minibuffer-read-description)) - (dispos (or disposition - (mml-minibuffer-read-disposition type)))) - (mml-insert-empty-tag 'part 'type type 'filename file - 'disposition dispos 'description description))) - -(defun mh-mh-attach-file (filename type description attributes) - "Add a tag to insert a MIME message part from a file. -You are prompted for the FILENAME containing the object, the -media TYPE if it cannot be determined automatically, and a -content DESCRIPTION. In addition, you are also prompted for -additional ATTRIBUTES. - -See also \\[mh-mh-to-mime]." - (interactive (let ((filename (mml-minibuffer-read-file "Attach file: "))) - (list - filename - (mh-minibuffer-read-type filename) - (mml-minibuffer-read-description) - (read-string "Attributes: " - (concat "name=\"" - (file-name-nondirectory filename) - "\""))))) - (mh-mh-compose-type filename type description attributes)) - -(defun mh-mh-compose-type (filename type - &optional description attributes comment) - "Insert an MH-style directive to insert a file. -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." - (beginning-of-line) - (insert "#" type) - (and attributes - (insert "; " attributes)) - (and comment - (insert " (" comment ")")) - (insert " [") - (and description - (insert description)) - (insert "] " (expand-file-name filename)) - (insert "\n")) - -;;;###mh-autoload -(defun mh-mh-compose-anon-ftp (host filename type description) - "Add tag to include anonymous ftp reference to a file. - -You can have your message initiate an \"ftp\" transfer when the -recipient reads the message. You are prompted for the remote HOST -and FILENAME, the media TYPE, and the content DESCRIPTION. - -See also \\[mh-mh-to-mime]." - (interactive (list - (read-string "Remote host: ") - (read-string "Remote filename: ") - (mh-minibuffer-read-type "DUMMY-FILENAME") - (mml-minibuffer-read-description))) - (mh-mh-compose-external-type "anon-ftp" host filename - type description)) - -;;;###mh-autoload -(defun mh-mh-compose-external-compressed-tar (host filename description) - "Add tag to include anonymous ftp reference to a compressed tar file. - -In addition to retrieving the file via anonymous \"ftp\" as per -the command \\[mh-mh-compose-anon-ftp], the file will also be -uncompressed and untarred. You are prompted for the remote HOST -and FILENAME and the content DESCRIPTION. - -See also \\[mh-mh-to-mime]." - (interactive (list - (read-string "Remote host: ") - (read-string "Remote filename: ") - (mml-minibuffer-read-description))) - (mh-mh-compose-external-type "anon-ftp" host filename - "application/octet-stream" - description - "type=tar; conversions=x-compress" - "mode=image")) - -;; RFC 2045 - Multipurpose Internet Mail Extensions (MIME) Part One: -;; Format of Internet Message Bodies. -;; RFC 2046 - Multipurpose Internet Mail Extensions (MIME) Part Two: -;; Media Types. -;; RFC 2049 - Multipurpose Internet Mail Extensions (MIME) Part Five: -;; Conformance Criteria and Examples. -;; RFC 2017 - Definition of the URL MIME External-Body Access-Type -;; RFC 1738 - Uniform Resource Locators (URL) -(defvar mh-access-types - '(("anon-ftp") ; RFC2046 Anonymous File Transfer Protocol - ("file") ; RFC1738 Host-specific file names - ("ftp") ; RFC2046 File Transfer Protocol - ("gopher") ; RFC1738 The Gopher Protocol - ("http") ; RFC1738 Hypertext Transfer Protocol - ("https") ; RFC2818 HTTP Over TLS - ("local-file") ; RFC2046 Local file access - ("mail-server") ; RFC2046 mail-server Electronic mail address - ("mailto") ; RFC1738 Electronic mail address - ("news") ; RFC1738 Usenet news - ("nntp") ; RFC1738 Usenet news using NNTP access - ("prospero") ; RFC1738 Prospero Directory Service - ("telnet") ; RFC1738 Telnet - ("tftp") ; RFC2046 Trivial File Transfer Protocol - ("url") ; RFC2017 URL scheme MIME access-type Protocol - ("wais")) ; RFC1738 Wide Area Information Servers - "Valid MIME access-type values.") - -;;;###mh-autoload -(defun mh-mh-compose-external-type (access-type host filename type - &optional description - attributes parameters - comment) - "Add tag to refer to a remote file. - -This command is a general utility for referencing external files. -In fact, all of the other commands that insert directives to -access external files call this command. You are prompted for the -ACCESS-TYPE, remote HOST and FILENAME, and content TYPE. If you -provide a prefix argument, you are also prompted for a content -DESCRIPTION, ATTRIBUTES, PARAMETERS, and a COMMENT. - -See also \\[mh-mh-to-mime]." - (interactive (list - (completing-read "Access type: " mh-access-types) - (read-string "Remote host: ") - (read-string "Remote filename: ") - (mh-minibuffer-read-type "DUMMY-FILENAME") - (if current-prefix-arg (mml-minibuffer-read-description)) - (if current-prefix-arg (read-string "Attributes: ")) - (if current-prefix-arg (read-string "Parameters: ")) - (if current-prefix-arg (read-string "Comment: ")))) - (beginning-of-line) - (insert "#@" type) - (and attributes - (insert "; " attributes)) - (and comment - (insert " (" comment ") ")) - (insert " [") - (and description - (insert description)) - (insert "] ") - (insert "access-type=" access-type "; ") - (insert "site=" host) - (insert "; name=" (file-name-nondirectory filename)) - (let ((directory (file-name-directory filename))) - (and directory - (insert "; directory=\"" directory "\""))) - (and parameters - (insert "; " parameters)) - (insert "\n")) - -(defvar mh-mh-to-mime-args nil - "Extra arguments for \\[mh-mh-to-mime] to pass to the \"mhbuild\" command. -The arguments are passed to \"mhbuild\" if \\[mh-mh-to-mime] is -given a prefix argument. Normally default arguments to -\"mhbuild\" are specified in the MH profile.") - -;;;###mh-autoload -(defun mh-mh-to-mime (&optional extra-args) - "Compose MIME message from MH-style directives. - -Typically, you send a message with attachments just like any other -message. However, you may take a sneak preview of the MIME encoding if -you wish by running this command. - -If you wish to pass additional arguments to \"mhbuild\" (\"mhn\") -to affect how it builds your message, use the option -`mh-mh-to-mime-args'. For example, you can build a consistency -check into the message by setting `mh-mh-to-mime-args' to -\"-check\". The recipient of your message can then run \"mhbuild --check\" on the message--\"mhbuild\" (\"mhn\") will complain if -the message has been corrupted on the way. This command only -consults this option when given a prefix argument EXTRA-ARGS. - -The hook `mh-mh-to-mime-hook' is called after the message has been -formatted. - -The effects of this command can be undone by running -\\[mh-mh-to-mime-undo]." - (interactive "*P") - (mh-mh-quote-unescaped-sharp) - (save-buffer) - (message "Running %s..." (if (mh-variant-p 'nmh) "mhbuild" "mhn")) - (cond - ((mh-variant-p 'nmh) - (mh-exec-cmd-error nil - "mhbuild" - (if extra-args mh-mh-to-mime-args) - buffer-file-name)) - (t - (mh-exec-cmd-error (format "mhdraft=%s" buffer-file-name) - "mhn" - (if extra-args mh-mh-to-mime-args) - buffer-file-name))) - (revert-buffer t t t) - (message "Running %s...done" (if (mh-variant-p 'nmh) "mhbuild" "mhn")) - (run-hooks 'mh-mh-to-mime-hook)) - -(defun mh-mh-quote-unescaped-sharp () - "Quote \"#\" characters that haven't been quoted for \"mhbuild\". -If the \"#\" character is present in the first column, but it isn't -part of a MH-style directive then \"mhbuild\" gives an error. -This function will quote all such characters." - (save-excursion - (goto-char (point-min)) - (while (re-search-forward "^#" nil t) - (beginning-of-line) - (unless (mh-mh-directive-present-p (point) (line-end-position)) - (insert "#")) - (goto-char (line-end-position))))) - -;;;###mh-autoload -(defun mh-mh-to-mime-undo (noconfirm) - "Undo effects of \\[mh-mh-to-mime]. - -It does this by reverting to a backup file. You are prompted to -confirm this action, but you can avoid the confirmation by adding -a prefix argument NOCONFIRM." - (interactive "*P") - (if (null buffer-file-name) - (error "Buffer does not seem to be associated with any file")) - (let ((backup-strings '("," "#")) - backup-file) - (while (and backup-strings - (not (file-exists-p - (setq backup-file - (concat (file-name-directory buffer-file-name) - (car backup-strings) - (file-name-nondirectory buffer-file-name) - ".orig"))))) - (setq backup-strings (cdr backup-strings))) - (or backup-strings - (error "Backup file for %s no longer exists" buffer-file-name)) - (or noconfirm - (yes-or-no-p (format "Revert buffer from file %s? " - backup-file)) - (error "Revert not confirmed")) - (let ((buffer-read-only nil)) - (erase-buffer) - (insert-file-contents backup-file)) - (after-find-file nil nil nil nil t))) - -;; Shush compiler. -(defvar mh-identity-gpg-default-user-id) - -;;;###mh-autoload -(defun mh-mml-secure-message-encrypt (method) - "Add tag to encrypt the message. - -A proper multipart message is created for you when you send the -message. Use the command \\[mh-mml-unsecure-message] to remove -this tag. Use a prefix argument METHOD to be prompted for one of -the possible security methods (see `mh-mml-method-default')." - (interactive (list (mh-mml-query-cryptographic-method))) - (mh-secure-message method "encrypt" mh-identity-gpg-default-user-id)) - -;;;###mh-autoload -(defun mh-mml-secure-message-sign (method) - "Add tag to sign the message. - -A proper multipart message is created for you when you send the -message. Use the command \\[mh-mml-unsecure-message] to remove -this tag. Use a prefix argument METHOD to be prompted for one of -the possible security methods (see `mh-mml-method-default')." - (interactive (list (mh-mml-query-cryptographic-method))) - (mh-secure-message method "sign" mh-identity-gpg-default-user-id)) - -;;;###mh-autoload -(defun mh-mml-secure-message-signencrypt (method) - "Add tag to encrypt and sign the message. - -A proper multipart message is created for you when you send the -message. Use the command \\[mh-mml-unsecure-message] to remove -this tag. Use a prefix argument METHOD to be prompted for one of -the possible security methods (see `mh-mml-method-default')." - (interactive (list (mh-mml-query-cryptographic-method))) - (mh-secure-message method "signencrypt" mh-identity-gpg-default-user-id)) - -(defvar mh-mml-cryptographic-method-history ()) - -(defun mh-mml-query-cryptographic-method () - "Read the cryptographic method to use." - (if current-prefix-arg - (let ((def (or (car mh-mml-cryptographic-method-history) - mh-mml-method-default))) - (completing-read (format-prompt "Method" def) - '(("pgp") ("pgpmime") ("smime")) - nil t nil 'mh-mml-cryptographic-method-history def)) - mh-mml-method-default)) - -(defun mh-secure-message (method mode &optional _identity) - "Add tag to encrypt or sign message. - -METHOD should be one of: \"pgpmime\", \"pgp\", \"smime\". -MODE should be one of: \"sign\", \"encrypt\", \"signencrypt\", \"none\". -IDENTITY is optionally the default-user-id to use." - (if (not mh-pgp-support-flag) - (error "Your version of Gnus does not support PGP/GPG") - ;; Check the arguments - (let ((valid-methods (list "pgpmime" "pgp" "smime")) - (valid-modes (list "sign" "encrypt" "signencrypt" "none"))) - (if (not (member method valid-methods)) - (error "Method %s is invalid" method)) - (if (not (member mode valid-modes)) - (error "Mode %s is invalid" mode)) - (mml-unsecure-message) - (if (not (string= mode "none")) - (save-excursion - (goto-char (point-min)) - (mh-goto-header-end 1) - (if mh-identity-gpg-default-user-id - (mml-insert-tag 'secure 'method method 'mode mode - 'sender mh-identity-gpg-default-user-id) - (mml-insert-tag 'secure 'method method 'mode mode))))))) - -;;;###mh-autoload -(defun mh-mml-to-mime () - "Compose MIME message from MML tags. - -Typically, you send a message with attachments just like any -other message. However, you may take a sneak preview of the MIME -encoding if you wish by running this command. - -This action can be undone by running \\[undo]." - (interactive) - (require 'message) - (when mh-pgp-support-flag - ;; PGP requires actual e-mail addresses, not aliases. - ;; Parse the recipients and sender from the message. - (message-options-set-recipient) - ;; Do an alias lookup on sender (if From field is present). - (when (message-options-get 'message-sender) - (message-options-set 'message-sender - (mail-strip-quoted-names - (mh-alias-expand - (message-options-get 'message-sender))))) - ;; Do an alias lookup on recipients - (message-options-set 'message-recipients - (mapconcat - (lambda (ali) - (mail-strip-quoted-names (mh-alias-expand ali))) - (split-string (message-options-get 'message-recipients) "[, ]+") - ", "))) - (let ((saved-text (buffer-string)) - (buffer (current-buffer)) - (modified-flag (buffer-modified-p))) - (condition-case err (mml-to-mime) - (error - (with-current-buffer buffer - (delete-region (point-min) (point-max)) - (insert saved-text) - (set-buffer-modified-p modified-flag)) - (error (error-message-string err)))))) - -;;;###mh-autoload -(defun mh-mml-unsecure-message () - "Remove any secure message tags." - (interactive) - (if (not mh-pgp-support-flag) - (error "Your version of Gnus does not support PGP/GPG") - (mml-unsecure-message))) - - - -;;; Support Routines for MH-Letter Commands - -;;;###mh-autoload -(defun mh-mml-tag-present-p () - "Check if the current buffer has text which may be a MML tag." - (save-excursion - (goto-char (point-min)) - (re-search-forward - (concat - "\\(<#\\(mml\\|part\\)\\(.\\|\n\\)*>[ \n\t]*<#/\\(mml\\|part\\)>\\|" - "^<#secure.+>$\\)") - nil t))) - -(defvar mh-media-type-regexp - (concat (regexp-opt '("text" "image" "audio" "video" "application" - "multipart" "message") t) - "/[-.+a-zA-Z0-9]+") - "Regexp matching valid media types used in MIME attachment compositions.") - -;;;###mh-autoload -(defun mh-mh-directive-present-p (&optional begin end) - "Check if the text between BEGIN and END might be a MH-style directive. -The optional argument BEGIN defaults to the beginning of the -buffer, while END defaults to the end of the buffer." - (unless begin (setq begin (point-min))) - (unless end (setq end (point-max))) - (save-excursion - (cl-block search-for-mh-directive - (goto-char begin) - (while (re-search-forward "^#" end t) - (let ((s (buffer-substring-no-properties - (point) (line-end-position)))) - (cond ((equal s "")) - ((string-match "^forw[ \t\n]+" s) - (cl-return-from search-for-mh-directive t)) - (t (let ((first-token (car (split-string s "[ \t;@]")))) - (when (and first-token - (string-match mh-media-type-regexp - first-token)) - (cl-return-from search-for-mh-directive t))))))) - nil))) - -(defun mh-minibuffer-read-type (filename &optional default) - "Return the content type associated with the given FILENAME. -If the \"file\" command exists and recognizes the given file, -then its value is returned; otherwise, the user is prompted for -a type (see `mailcap-mime-types'). -Optional argument DEFAULT is returned if a type isn't entered." - (mailcap-parse-mimetypes) - (let* ((default (or default - (mm-default-file-type filename) - "application/octet-stream")) - (probed-type (mh-file-mime-type filename)) - (type (or (and (not (equal probed-type "application/octet-stream")) - probed-type) - (completing-read - (format-prompt "Content type" default) - (mapcar #'list (mailcap-mime-types)))))) - (if (not (equal type "")) - type - default))) - -;;;###mh-autoload -(defun mh-file-mime-type (filename) - "Return MIME type of FILENAME from file command. -Returns nil if file command not on system." - (cond - ((not (mh-have-file-command)) - nil) ;no file command, exit now - ((not (and (file-exists-p filename) - (file-readable-p filename))) - nil) ;no file or not readable, ditto - (t - (let ((tmp-buffer (get-buffer-create mh-temp-buffer))) - (with-current-buffer tmp-buffer - (unwind-protect - (progn - (call-process "file" nil '(t nil) nil "-b" "-i" - (expand-file-name filename)) - (goto-char (point-min)) - (if (not (re-search-forward mh-media-type-regexp nil t)) - nil - (mh-file-mime-type-substitute (match-string 0) filename))) - (kill-buffer tmp-buffer))))))) - -(defvar mh-file-mime-type-substitutions - '(("application/msword" "\\.xls" "application/ms-excel") - ("application/msword" "\\.ppt" "application/ms-powerpoint") - ("text/plain" "\\.vcf" "text/x-vcard") - ("text/rtf" "\\.rtf" "application/rtf") - ("application/x-zip" "\\.sxc" "application/vnd.sun.xml.calc") - ("application/x-zip" "\\.sxd" "application/vnd.sun.xml.draw") - ("application/x-zip" "\\.sxi" "application/vnd.sun.xml.impress") - ("application/x-zip" "\\.sxw" "application/vnd.sun.xml.writer") - ("application/x-zip" "\\.odg" "application/vnd.oasis.opendocument.graphics") - ("application/x-zip" "\\.odi" "application/vnd.oasis.opendocument.image") - ("application/x-zip" "\\.odp" - "application/vnd.oasis.opendocument.presentation") - ("application/x-zip" "\\.ods" - "application/vnd.oasis.opendocument.spreadsheet") - ("application/x-zip" "\\.odt" "application/vnd.oasis.opendocument.text")) - "Substitutions to make for Content-Type returned from file command. -The first element is the Content-Type returned by the file command. -The second element is a regexp matching the file name, usually the -extension. -The third element is the Content-Type to replace with.") - -(defun mh-file-mime-type-substitute (content-type filename) - "Return possibly changed CONTENT-TYPE on the FILENAME. -Substitutions are made from the `mh-file-mime-type-substitutions' -variable." - (let ((subst mh-file-mime-type-substitutions) - (type) (match) (answer content-type) - (case-fold-search t)) - (while subst - (setq type (car (car subst)) - match (elt (car subst) 1)) - (if (and (string-equal content-type type) - (string-match match filename)) - (setq answer (elt (car subst) 2) - subst nil) - (setq subst (cdr subst)))) - answer)) - -(defvar mh-have-file-command 'undefined - "Cached value of function `mh-have-file-command'. -Do not reference this variable directly as it might not have been -initialized. Always use the command `mh-have-file-command'.") - -;;;###mh-autoload -(defun mh-have-file-command () - "Return t if `file' command is on the system. -\"file -i\" is used to get MIME type of composition insertion." - (when (eq mh-have-file-command 'undefined) - (setq mh-have-file-command - (and (executable-find "file") ; file command exists - ; and accepts -i and -b args. - (zerop (call-process "file" nil nil nil "-i" "-b" - (expand-file-name "inc" mh-progs)))))) - mh-have-file-command) - - - -;;; MIME Cleanup - -;;;###mh-autoload -(defun mh-mime-cleanup () - "Free the decoded MIME parts." - (let ((mime-data (gethash (current-buffer) mh-globals-hash))) - (remove-images (point-min) (point-max)) - (when mime-data - (mm-destroy-parts (mh-mime-handles mime-data)) - (remhash (current-buffer) mh-globals-hash)))) - -;;;###mh-autoload -(defun mh-destroy-postponed-handles () - "Free MIME data for externally displayed MIME parts." - (let ((mime-data (mh-buffer-data))) - (when mime-data - (mm-destroy-parts (mh-mime-handles mime-data))) - (remhash (current-buffer) mh-globals-hash))) - -(provide 'mh-mime) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-mime.el ends here diff --git a/lisp/mh-e/mh-print.el b/lisp/mh-e/mh-print.el deleted file mode 100644 index b7c07d4239c..00000000000 --- a/lisp/mh-e/mh-print.el +++ /dev/null @@ -1,247 +0,0 @@ -;;; mh-print.el --- MH-E printing support -*- lexical-binding: t; -*- - -;; Copyright (C) 2003-2024 Free Software Foundation, Inc. - -;; Author: Jeffrey C Honig -;; Maintainer: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;;; Code: - -(require 'mh-e) -(require 'mh-scan) - -(require 'ps-print) - -(defvar mh-ps-print-color-option ps-print-color-p - "Specify how buffer's text color is printed. - -Valid values are: - - nil - Do not print colors. - t - Print colors. - black-white - Print colors on black/white printer. - See also `ps-black-white-faces'. - -Any other value is treated as t. This variable is initialized -from `ps-print-color-p'.") - -(defvar mh-ps-print-func 'ps-spool-buffer-with-faces - "Function to use to spool a buffer. - -Sensible choices are the functions `ps-spool-buffer' and -`ps-spool-buffer-with-faces'.") - -;;;###mh-autoload -(defun mh-ps-print-msg (range) - "Print RANGE\\. - -Check the documentation of `mh-interactive-range' to see how RANGE is -read in interactive use. - -This command will print inline text attachments but will not decrypt -messages. However, when a message is displayed in an MH-Show buffer, -then that buffer is used verbatim for printing with the caveat that -only text attachments, if opened inline, are printed. Therefore, -encrypted messages can be printed by showing and decrypting them -first. - -MH-E uses the \"ps-print\" package to do the printing, so you can -customize the printing further by going to the `ps-print' -customization group. This command does not use the options -`mh-lpr-command-format' or `mh-print-background-flag'. See also the -commands \\[mh-ps-print-toggle-color] and -\\[mh-ps-print-toggle-faces]." - (interactive (list (mh-interactive-range "Print"))) - (mh-ps-print-range range nil)) - -(defun mh-ps-print-range (range file) - "Print RANGE to FILE. - -This is the function that actually does the work. -If FILE is nil, then the messages are spooled to the printer." - (mh-iterate-on-range msg range - (mh-ps-spool-msg msg) - (mh-notate msg mh-note-printed mh-cmd-note)) - (ps-despool file)) - -(defun mh-ps-spool-msg (msg) - "Spool MSG." - (let* ((folder mh-current-folder) - (buffer (mh-in-show-buffer (mh-show-buffer) - (if (not (equal (mh-msg-filename msg folder) - buffer-file-name)) - (get-buffer-create mh-temp-buffer))))) - (unwind-protect - (save-excursion - (if buffer - (let ((mh-show-buffer buffer)) - (mh-display-msg msg folder))) - (mh-ps-spool-buffer (if buffer buffer mh-show-buffer))) - (if buffer - (kill-buffer buffer))))) - -(defun mh-ps-spool-buffer (buffer) - "Spool BUFFER." - (with-current-buffer buffer - (let ((ps-print-color-p mh-ps-print-color-option) - (ps-left-header - (list - (concat "(" (mh-get-header-field "Subject:") ")") - (concat "(" (mh-get-header-field "From:") ")"))) - (ps-right-header - (list - "/pagenumberstring load" - (concat "(" (mh-get-header-field "Date:") ")")))) - (funcall mh-ps-print-func)))) - -;;;###mh-autoload -(defun mh-ps-print-msg-file (range file) - "Print RANGE to FILE\\. - -Check the documentation of `mh-interactive-range' to see how RANGE is -read in interactive use. - -This command will print inline text attachments but will not decrypt -messages. However, when a message is displayed in an MH-Show buffer, -then that buffer is used verbatim for printing with the caveat that -only text attachments, if opened inline, are printed. Therefore, -encrypted messages can be printed by showing and decrypting them -first. - -MH-E uses the \"ps-print\" package to do the printing, so you can -customize the printing further by going to the `ps-print' -customization group. This command does not use the options -`mh-lpr-command-format' or `mh-print-background-flag'. See also the -commands \\[mh-ps-print-toggle-color] and -\\[mh-ps-print-toggle-faces]." - (interactive (list (mh-interactive-range "Print") (mh-ps-print-preprint 1))) - (mh-ps-print-range range file)) - -(defun mh-ps-print-preprint (arg) - "Provide a better default file name for `ps-print-preprint'. -Pass along the prefix ARG to it." - (let ((buffer-file-name (format "mh-%s" (substring (buffer-name) 1)))) - (ps-print-preprint arg))) - -;;;###mh-autoload -(defun mh-ps-print-toggle-faces () - "Toggle whether printing is done with faces or not. - -When faces are enabled, the printed message will look very -similar to the message in the MH-Show buffer." - (interactive) - (if (eq mh-ps-print-func 'ps-spool-buffer-with-faces) - (progn - (setq mh-ps-print-func 'ps-spool-buffer) - (message "Printing without faces")) - (setq mh-ps-print-func 'ps-spool-buffer-with-faces) - (message "Printing with faces"))) - -;;;###mh-autoload -(defun mh-ps-print-toggle-color () - "Toggle whether color is used in printing messages. - -Colors are emulated on black-and-white printers with shades of -gray. This might produce illegible output, even if your screen -colors only use shades of gray. If this is the case, try using -this command to toggle between color, no color, and a black and -white representation of the colors and see which works best. You -change this setting permanently by customizing the option -`ps-print-color-p'." - (interactive) - (if (eq mh-ps-print-color-option nil) - (progn - (setq mh-ps-print-color-option 'black-white) - (message "Colors will be printed as black & white")) - (if (eq mh-ps-print-color-option 'black-white) - (progn - (setq mh-ps-print-color-option t) - (message "Colors will be printed")) - (setq mh-ps-print-color-option nil) - (message "Colors will not be printed")))) - -;; Old non-PS based printing -;;;###mh-autoload -(defun mh-print-msg (range) - "Print RANGE the old fashioned way\\. - -The message is formatted with \"mhl\" (see option -`mh-mhl-format-file') and printed with the \"lpr\" command (see -option `mh-lpr-command-format'). - -Check the documentation of `mh-interactive-range' to see how -RANGE is read in interactive use. - -Consider using \\[mh-ps-print-msg] instead." - (interactive (list (mh-interactive-range "Print"))) - (message "Printing...") - (let (msgs) - ;; Gather message numbers and add them to "printed" sequence. - (mh-iterate-on-range msg range - (mh-add-msgs-to-seq msg 'printed t) - (mh-notate nil mh-note-printed mh-cmd-note) - (push msg msgs)) - (setq msgs (nreverse msgs)) - ;; Print scan listing if we have more than one message. - (if (> (length msgs) 1) - (let* ((msgs-string - (mapconcat #'identity (mh-list-to-string - (mh-coalesce-msg-list msgs)) - " ")) - (lpr-command - (format mh-lpr-command-format - (cond ((listp range) - (format "Folder: %s, Messages: %s" - mh-current-folder msgs-string)) - ((symbolp range) - (format "Folder: %s, Sequence: %s" - mh-current-folder range))))) - (scan-command - (format "scan %s | %s" msgs-string lpr-command))) - (if mh-print-background-flag - (mh-exec-cmd-daemon shell-file-name nil "-c" scan-command) - (call-process shell-file-name nil nil nil "-c" scan-command)))) - ;; Print the messages - (dolist (msg msgs) - (let* ((mhl-command (format "%s %s %s" - (expand-file-name "mhl" mh-lib-progs) - (if mh-mhl-format-file - (format " -form %s" mh-mhl-format-file) - "") - (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")) - -(provide 'mh-print) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-print.el ends here diff --git a/lisp/mh-e/mh-scan.el b/lisp/mh-e/mh-scan.el deleted file mode 100644 index b076ff5dbec..00000000000 --- a/lisp/mh-e/mh-scan.el +++ /dev/null @@ -1,532 +0,0 @@ -;;; mh-scan.el --- MH-E scan line constants and utilities -*- lexical-binding: t; -*- - -;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation, -;; Inc. - -;; Author: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; This file contains constants and a few functions for interpreting -;; scan lines. - -;;; Code: - -(require 'mh-e) - - - -;;; Scan Formats - -;; The following scan formats are passed to the scan program if the setting of -;; `mh-scan-format-file' is t. They are identical except the later one makes -;; use of the nmh `decode' function to decode RFC 2047 encodings. If you just -;; want to change the column of the notations, use the `mh-set-cmd-note' -;; function. - -(defcustom mh-scan-format-mh - (concat - "%4(msg)" - "%<(cur)+%| %>" - "%<{replied}-" - "%?(nonnull(comp{to}))%<(mymbox{to})t%>" - "%?(nonnull(comp{cc}))%<(mymbox{cc})c%>" - "%?(nonnull(comp{bcc}))%<(mymbox{bcc})b%>" - "%?(nonnull(comp{newsgroups}))n%>" - "%<(zero) %>" - "%02(mon{date})/%02(mday{date})%<{date} %|*%>" - "%<(mymbox{from})%<{to}To:%14(friendly{to})%>%>" - "%<(zero)%17(friendly{from})%> " - "%{subject}%<{body}<<%{body}%>") - "Scan format string for MH. -This string is passed to the scan program via the -format -argument. This format is identical to the default except that -additional hints for fontification have been added to the fifth -column (remember that in Emacs, the first column is 0). - -The values of the fifth column, in priority order, are: \"-\" if -the message has been replied to, t if an address on the To: line -matches one of the mailboxes of the current user, \"c\" if the Cc: -line matches, \"b\" if the Bcc: line matches, and \"n\" if a -non-empty Newsgroups: header is present." - :group 'mh-scan-line-formats - :type 'string) - -(defcustom mh-scan-format-nmh - (concat - "%4(msg)" - "%<(cur)+%| %>" - "%<{replied}-" - "%?(nonnull(comp{to}))%<(mymbox{to})t%>" - "%?(nonnull(comp{cc}))%<(mymbox{cc})c%>" - "%?(nonnull(comp{bcc}))%<(mymbox{bcc})b%>" - "%?(nonnull(comp{newsgroups}))n%>" - "%<(zero) %>" - "%02(mon{date})/%02(mday{date})%<{date} %|*%>" - "%<(mymbox{from})%<{to}To:%14(decode(friendly{to}))%>%>" - "%<(zero)%17(decode(friendly{from}))%> " - "%(decode{subject})%<{body}<<%{body}%>") - "Scan format string for nmh. -This string is passed to the scan program via the -format arg. -This format is identical to the default except that additional -hints for fontification have been added to the fifth -column (remember that in Emacs, the first column is 0). - -The values of the fifth column, in priority order, are: \"-\" if -the message has been replied to, t if an address on the To: field -matches one of the mailboxes of the current user, \"c\" if the Cc: -field matches, \"b\" if the Bcc: field matches, and \"n\" if a -non-empty Newsgroups: field is present." - :group 'mh-scan-line-formats - :type 'string) - - - -;;; Regular Expressions - -;; Alphabetical. - -(defvar mh-scan-allowlisted-msg-regexp "^\\( *[0-9]+\\)A" - "This regular expression matches allowlisted (non-spam) messages. - -It must match from the beginning of the line. Note that the -default setting of `mh-folder-font-lock-keywords' expects this -expression to contain at least one parenthesized expression which -matches the message number as in the default of - - \"^\\\\( *[0-9]+\\\\)A\". - -This expression includes the leading space within parenthesis -since it looks better to highlight it as well. The highlighting -is done with the face `mh-folder-allowlisted'. This regular -expression should be correct as it is needed by non-fontification -functions. See also `mh-note-allowlisted'.") - -(defvar mh-scan-blocklisted-msg-regexp "^\\( *[0-9]+\\)B" - "This regular expression matches blocklisted (spam) messages. - -It must match from the beginning of the line. Note that the -default setting of `mh-folder-font-lock-keywords' expects this -expression to contain at least one parenthesized expression which -matches the message number as in the default of - - \"^\\\\( *[0-9]+\\\\)B\". - -This expression includes the leading space within parenthesis -since it looks better to highlight it as well. The highlighting -is done with the face `mh-folder-blocklisted'. This regular -expression should be correct as it is needed by non-fontification -functions. See also `mh-note-blocklisted'.") - -(defvar mh-scan-body-regexp "\\(<<\\([^\n]+\\)?\\)" - "This regular expression matches the message body fragment. - -Note that the default setting of `mh-folder-font-lock-keywords' -expects this expression to contain at least one parenthesized -expression which matches the body text as in the default of -\"\\\\(<<\\\\([^\\n]+\\\\)?\\\\)\". If this regular expression is -not correct, the body fragment will not be highlighted with the -face `mh-folder-body'.") - -(defvar mh-scan-cur-msg-number-regexp "^\\( *[0-9]+\\+\\).*" - "This regular expression matches the current message. - -It must match from the beginning of the line. Note that the -default setting of `mh-folder-font-lock-keywords' expects this -expression to contain at least one parenthesized expression which -matches the message number as in the default of - - \"^\\\\( *[0-9]+\\\\+\\\\).*\". - -This expression includes the leading space and current message -marker \"+\" within the parenthesis since it looks better to -highlight these items as well. The highlighting is done with the -face `mh-folder-cur-msg-number'. This regular expression should -be correct as it is needed by non-fontification functions. See -also `mh-note-cur'.") - -(defvar mh-scan-date-regexp "\\([0-9][0-9]/[0-9][0-9]\\)" - "This regular expression matches a valid date. - -It must not be anchored to the beginning or the end of the line. -Note that the default setting of `mh-folder-font-lock-keywords' -expects this expression to contain only one parenthesized -expression which matches the date field as in the default of -\"\\\\([0-9][0-9]/[0-9][0-9]\\\\)\"}. If this regular expression -is not correct, the date will not be highlighted with the face -`mh-folder-date'.") - -(defvar mh-scan-deleted-msg-regexp "^\\( *[0-9]+\\)D" - "This regular expression matches deleted messages. - -It must match from the beginning of the line. Note that the -default setting of `mh-folder-font-lock-keywords' expects this -expression to contain at least one parenthesized expression which -matches the message number as in the default of - - \"^\\\\( *[0-9]+\\\\)D\". - -This expression includes the leading space within the parenthesis -since it looks better to highlight it as well. The highlighting -is done with the face `mh-folder-deleted'. This regular -expression should be correct as it is needed by non-fontification -functions. See also `mh-note-deleted'.") - -(defvar mh-scan-good-msg-regexp "^\\( *[0-9]+\\)[^^DBA0-9]" - "This regular expression matches \"good\" messages. - -It must match from the beginning of the line. Note that the -default setting of `mh-folder-font-lock-keywords' expects this -expression to contain at least one parenthesized expression which -matches the message number as in the default of - - \"^\\\\( *[0-9]+\\\\)[^^DBA0-9]\". - -This expression includes the leading space within the parenthesis -since it looks better to highlight it as well. The highlighting -is done with the face `mh-folder-msg-number'. This regular -expression should be correct as it is needed by non-fontification -functions.") - -(defvar mh-scan-msg-format-regexp "%\\([0-9]*\\)(msg)" - "This regular expression finds the message number width in a scan format. - -Note that the message number must be placed in a parenthesized -expression as in the default of \"%\\\\([0-9]*\\\\)(msg)\". This -variable is only consulted if `mh-scan-format-file' is set to -\"Use MH-E scan Format\".") - -(defvar mh-scan-msg-format-string "%d" - "This is a format string for width of the message number in a scan format. - -Use \"0%d\" for zero-filled message numbers. This variable is only -consulted if `mh-scan-format-file' is set to \"Use MH-E scan -Format\".") - -(defvar mh-scan-msg-number-regexp "^ *\\([0-9]+\\)" - "This regular expression extracts the message number. - -It must match from the beginning of the line. Note that the -message number must be placed in a parenthesized expression as in -the default of \"^ *\\\\([0-9]+\\\\)\".") - -(defvar mh-scan-msg-overflow-regexp "^[?0-9][0-9]" - "This regular expression matches overflowed message numbers.") - -(defvar mh-scan-msg-search-regexp "^[^0-9]*%d[^0-9]" - "This regular expression matches a particular message. - -It is a format string; use \"%d\" to represent the location of the -message number within the expression as in the default of -\"^[^0-9]*%d[^0-9]\".") - -(defvar mh-scan-rcpt-regexp "\\(To:\\)\\(..............\\)" - "This regular expression specifies the recipient in messages you sent. - -Note that the default setting of `mh-folder-font-lock-keywords' -expects this expression to contain two parenthesized expressions. -The first is expected to match the \"To:\" that the default scan -format file generates. The second is expected to match the -recipient's name as in the default of -\"\\\\(To:\\\\)\\\\(..............\\\\)\". If this regular -expression is not correct, the \"To:\" string will not be -highlighted with the face `mh-folder-to' and the recipient will -not be highlighted with the face `mh-folder-address'") - -(defvar mh-scan-refiled-msg-regexp "^\\( *[0-9]+\\)\\^" - "This regular expression matches refiled messages. - -It must match from the beginning of the line. Note that the -default setting of `mh-folder-font-lock-keywords' expects this -expression to contain at least one parenthesized expression which -matches the message number as in the default of - - \"^\\\\( *[0-9]+\\\\)\\\\^\". - -This expression includes the leading space within the parenthesis -since it looks better to highlight it as well. The highlighting -is done with the face `mh-folder-refiled'. This regular -expression should be correct as it is needed by non-fontification -functions. See also `mh-note-refiled'.") - -(defvar mh-scan-sent-to-me-sender-regexp - "^ *[0-9]+.\\([bct]\\).....[ ]*\\(..................\\)" - "This regular expression matches messages sent to us. - -Note that the default setting of `mh-folder-font-lock-keywords' -expects this expression to contain at least two parenthesized -expressions. The first should match the fontification hint (see -`mh-scan-format-nmh') and the second should match the user name -as in the default of - - ^ *[0-9]+.\\\\([bct]\\\\).....[ ]*\\\\(..................\\\\) - -If this regular expression is not correct, the notation hints -will not be highlighted with the face `mh-folder-sent-to-me-hint' -and the sender will not be highlighted with the face -`mh-folder-sent-to-me-sender'.") - -(defvar mh-scan-subject-regexp - "^ *[0-9]+........[ ]*...................\\([Rr][Ee]\\(\\[[0-9]+\\]\\)?:\\s-*\\)*\\([^<\n]*\\)" - "This regular expression matches the subject. - -It must match from the beginning of the line. Note that the -default setting of `mh-folder-font-lock-keywords' expects this -expression to contain at least three parenthesized expressions. -The first is expected to match the \"Re:\" string, if any, and is -highlighted with the face `mh-folder-followup'. The second -matches an optional bracketed number after \"Re:\", such as in -\"Re[2]:\" (and is thus a sub-expression of the first expression) -and the third is expected to match the subject line itself which -is highlighted with the face `mh-folder-subject'. For example, -the default (broken on multiple lines for readability) is - - ^ *[0-9]+........[ ]*................... - \\\\([Rr][Ee]\\\\(\\\\\\=[[0-9]+\\\\]\\\\)?:\\\\s-*\\\\)* - \\\\([^<\\n]*\\\\) - -This regular expression should be correct as it is needed by -non-fontification functions.") - -(defvar mh-scan-valid-regexp "^ *[0-9]" - "This regular expression describes a valid scan line. - -This is used to eliminate error messages that are occasionally -produced by \"inc\".") - - - -;;; Widths, Offsets and Columns - -(defvar-local mh-cmd-note 4 - "Column for notations. - -This variable should be set with the function `mh-set-cmd-note'. -This variable may be updated dynamically if -`mh-adaptive-cmd-note-flag' is on. - -Note that columns in Emacs start with 0.") - -(defvar mh-scan-cmd-note-width 1 - "Number of columns consumed by the cmd-note field in `mh-scan-format'. - -This column will have one of the values: - - \" \", \"^\", \"D\", \"B\", \"A\", \"+\" - -where - - \" \" is the default value, - \"^\" is the `mh-note-refiled' character, - \"D\" is the `mh-note-deleted' character, - \"B\" is the `mh-note-blocklisted' character, - \"A\" is the `mh-note-allowlisted' character, and - \"+\" is the `mh-note-cur' character.") - -(defvar mh-scan-destination-width 1 - "Number of columns consumed by the destination field in `mh-scan-format'. - -This column will have one of \" \", \"%\", \"-\", \"t\", \"c\", \"b\", or \"n\" -in it. - - \" \" blank space is the default character. - \"%\" indicates that the message in a named MH sequence. - \"-\" indicates that the message has been annotated with a replied field. - \"t\" indicates that the message contains mymbox in the To: field. - \"c\" indicates that the message contains mymbox in the Cc: field. - \"b\" indicates that the message contains mymbox in the Bcc: field. - \"n\" indicates that the message contains a Newsgroups: field.") - -(defvar mh-scan-date-width 5 - "Number of columns consumed by the date field in `mh-scan-format'. -This column will typically be of the form mm/dd.") - -(defvar mh-scan-date-flag-width 1 - "Number of columns consumed to flag (in)valid dates in `mh-scan-format'. -This column will have \" \" for valid and \"*\" for invalid or -missing dates.") - -(defvar mh-scan-from-mbox-width 17 - "Number of columns consumed with the \"From:\" line in `mh-scan-format'. -This column will have a friendly name or e-mail address of the -originator, or a \"To: address\" for outgoing e-mail messages.") - -(defvar mh-scan-from-mbox-sep-width 2 - "Number of columns consumed by whitespace after from-mbox in `mh-scan-format'. -This column will only ever have spaces in it.") - -(defvar mh-scan-field-destination-offset - (+ mh-scan-cmd-note-width) - "The offset from the `mh-cmd-note' for the destination column.") - -(defvar mh-scan-field-from-start-offset - (+ mh-scan-cmd-note-width - mh-scan-destination-width - mh-scan-date-width - mh-scan-date-flag-width) - "The offset from the `mh-cmd-note' to find the start of \"From:\" address.") - -(defvar mh-scan-field-from-end-offset - (+ mh-scan-field-from-start-offset mh-scan-from-mbox-width) - "The offset from the `mh-cmd-note' to find the end of \"From:\" address.") - -(defvar mh-scan-field-subject-start-offset - (+ mh-scan-cmd-note-width - mh-scan-destination-width - mh-scan-date-width - mh-scan-date-flag-width - mh-scan-from-mbox-width - mh-scan-from-mbox-sep-width) - "The offset from the `mh-cmd-note' to find the start of the subject.") - - - -;;; Notation - -;; Alphabetical. - -(defvar mh-note-allowlisted ?A - "Messages that have been allowlisted are marked by this character. -See also `mh-scan-allowlisted-msg-regexp'.") - -(defvar mh-note-blocklisted ?B - "Messages that have been blocklisted are marked by this character. -See also `mh-scan-blocklisted-msg-regexp'.") - -(defvar mh-note-copied ?C - "Messages that have been copied are marked by this character.") - -(defvar mh-note-cur ?+ - "The current message (in MH, not in MH-E) is marked by this character. -See also `mh-scan-cur-msg-number-regexp'.") - -(defvar mh-note-deleted ?D - "Messages that have been deleted are marked by this character. -See also `mh-scan-deleted-msg-regexp'.") - -(defvar mh-note-dist ?R - "Messages that have been redistributed are marked by this character.") - -(defvar mh-note-forw ?F - "Messages that have been forwarded are marked by this character.") - -(defvar mh-note-printed ?P - "Messages that have been printed are marked by this character.") - -(defvar mh-note-refiled ?^ - "Messages that have been refiled are marked by this character. -See also `mh-scan-refiled-msg-regexp'.") - -(defvar mh-note-repl ?- - "Messages that have been replied to are marked by this character.") - -(defvar mh-note-seq ?% - "Messages in a user-defined sequence are marked by this character. - -Messages in the \"search\" sequence are marked by this character as -well.") - - - -;;; Utilities - -;;;###mh-autoload -(defun mh-scan-msg-number-regexp () - "Return value of variable `mh-scan-msg-number-regexp'." - mh-scan-msg-number-regexp) - -;;;###mh-autoload -(defun mh-scan-msg-search-regexp () - "Return value of variable `mh-scan-msg-search-regexp'." - mh-scan-msg-search-regexp) - -;;;###mh-autoload -(defun mh-set-cmd-note (column) - "Set `mh-cmd-note' to COLUMN. -Note that columns in Emacs start with 0." - (setq mh-cmd-note column)) - -;;;###mh-autoload -(defun mh-scan-format () - "Return the output format argument for the scan program." - (if (equal mh-scan-format-file t) - (list "-format" (if (mh-variant-p 'nmh 'gnu-mh) - (list (mh-update-scan-format - mh-scan-format-nmh mh-cmd-note)) - (list (mh-update-scan-format - mh-scan-format-mh mh-cmd-note)))) - (if (not (equal mh-scan-format-file nil)) - (list "-form" mh-scan-format-file)))) - -(defun mh-update-scan-format (fmt width) - "Return a scan format with the (msg) width in the FMT replaced with WIDTH. - -The message number width portion of the format is discovered -using `mh-scan-msg-format-regexp'. Its replacement is controlled -with `mh-scan-msg-format-string'." - (or (and - (string-match mh-scan-msg-format-regexp fmt) - (let ((begin (match-beginning 1)) - (end (match-end 1))) - (concat (substring fmt 0 begin) - (format mh-scan-msg-format-string width) - (substring fmt end)))) - fmt)) - -;;;###mh-autoload -(defun mh-msg-num-width (folder) - "Return the width of the largest message number in this FOLDER." - (or mh-progs (mh-find-path)) - (let ((tmp-buffer (get-buffer-create mh-temp-buffer)) - (width 0)) - (with-current-buffer tmp-buffer - (erase-buffer) - (apply #'call-process - (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) - (setq width (length (buffer-substring - (match-beginning 1) (match-end 1)))))) - width)) - -;;;###mh-autoload -(defun mh-msg-num-width-to-column (width) - "Return the column for notations given message number WIDTH. -Note that columns in Emacs start with 0. - -If `mh-scan-format-file' is set to \"Use MH-E scan Format\" this -means that either `mh-scan-format-mh' or `mh-scan-format-nmh' is -in use. This function therefore assumes that the first column is -empty (to provide room for the cursor), the following WIDTH -columns contain the message number, and the column for notations -comes after that." - (if (eq mh-scan-format-file t) - (max (1+ width) 2) - (error "%s %s" "Can't call `mh-msg-num-width-to-column' when" - "`mh-scan-format-file' is not set to \"Use MH-E scan Format\""))) - -(provide 'mh-scan) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-scan.el ends here diff --git a/lisp/mh-e/mh-search.el b/lisp/mh-e/mh-search.el deleted file mode 100644 index 5ee70ae081d..00000000000 --- a/lisp/mh-e/mh-search.el +++ /dev/null @@ -1,1938 +0,0 @@ -;;; mh-search.el --- MH-Search mode -*- lexical-binding: t; -*- - -;; Copyright (C) 1993, 1995, 2001-2024 Free Software Foundation, Inc. - -;; Author: Indexed search by Satyaki Das -;; Maintainer: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Mode used to compose search criteria. - -;; (1) The following search engines are supported: -;; swish++ -;; swish-e -;; mairix -;; namazu -;; pick -;; grep - -;; (2) To use this package, you first have to build an index. Please -;; read the documentation for `mh-search' to get started. That -;; documentation will direct you to the specific instructions for -;; your particular searcher. - -;;; Code: - -(require 'mh-e) -(require 'mh-letter) - -(require 'gnus-util) -(require 'imenu) - -(defvar mh-searcher nil - "Cached value of chosen search program.") - -(defvar mh-search-function nil - "Function which executes the search program.") - -(defvar mh-search-next-result-function nil - "Function to parse the next line of output. -Expected to return a list of three strings: name of the folder, -message number, and optionally the match.") - -(defvar mh-search-regexp-builder nil - "Function used to construct search regexp.") - -(defvar mh-index-folder "+mhe-index" - "Folder that contains the folders resulting from the index searches.") - -(defvar mh-flists-results-folder "sequence" - "Subfolder for `mh-index-folder' where flists output is placed.") - -(defvar mh-flists-sequence) - -(defvar mh-flists-called-flag nil) - - - -;;; MH-Folder Commands - -;;;###mh-autoload -(defun mh-search (folder search-regexp - &optional redo-search-flag window-config) - "Search your MH mail. - -This command helps you find messages in your entire corpus of -mail. You can search for messages to or from a particular person -or about a particular subject. In fact, you can also search for -messages containing selected strings in any arbitrary header -field or any string found within the messages. - -Out of the box, MH-E uses \"pick\" to find messages. With a -little extra effort, you can set an indexing program which -rewards you with extremely quick results. The drawback is that -sometimes the index does not contain the words you're looking -for. You can still use \"pick\" in these situations. - -You are prompted for the FOLDER to search. This can be \"all\" to -search all folders. Note that the search works recursively on the -listed folder. - -Next, an MH-Search buffer appears where you can enter search -criteria SEARCH-REGEXP. - - From: - To: - Cc: - Date: - Subject: - -------- - -Edit this template by entering your search criteria in an -appropriate header field that is already there, or create a new -field yourself. If the string you're looking for could be -anywhere in a message, then place the string underneath the row -of dashes. - -As an example, let's say that we want to find messages from -Ginnean about horseback riding in the Kosciusko National -Park (Australia) during January, 1994. Normally we would start -with a broad search and narrow it down if necessary to produce a -manageable amount of data, but we'll cut to the chase and create -a fairly restrictive set of criteria as follows:\\ - - From: ginnean - To: - Cc: - Date: Jan 1994 - Subject: - -------- - horse - kosciusko - -As with MH-Letter mode, MH-Search provides commands like -\\[mh-to-field] to help you fill in the blanks.\\ - -If you find that you do the same thing over and over when editing -the search template, you may wish to bind some shortcuts to keys. -This can be done with the variable `mh-search-mode-hook', which is -called when \\[mh-search] is run on a new pattern.\\ - -To perform the search, type \\[mh-index-do-search]. - -Sometimes you're searching for text that is either not indexed, -or hasn't been indexed yet. In this case you can override the -default method with the pick method by running the command -\\[mh-pick-do-search]. - -The messages that are found are put in a temporary sub-folder of -\"+mhe-index\" and are displayed in an MH-Folder buffer. This -buffer is special because it displays messages from multiple -folders; each set of messages from a given folder has a heading -with the folder name.\\ - -The appearance of the heading can be modified by customizing the -face `mh-search-folder'. You can jump back and forth between the -headings using the commands \\[mh-index-next-folder] and -\\[mh-index-previous-folder]. - -In addition, the command \\[mh-index-visit-folder] can be used to -visit the folder of the message at point. Initially, only the -messages that matched the search criteria are displayed in the -folder. While the temporary buffer has its own set of message -numbers, the actual messages numbers are shown in the visited -folder. Thus, the command \\[mh-index-visit-folder] is useful to -find the actual message number of an interesting message, or to -view surrounding messages with the command \\[mh-rescan-folder]. - -Because this folder is temporary, you'll probably get in the -habit of killing it when you're done with \\[mh-kill-folder]. - -You can regenerate the results by running this command with a -prefix argument REDO-SEARCH-FLAG. - -Note: This command uses an \"X-MHE-Checksum:\" header field to -cache the MD5 checksum of a message. This means that if an -incoming message already contains an \"X-MHE-Checksum:\" field, -that message might not be found by this command. The following -\"procmail\" recipe avoids this problem by renaming the existing -header field: - - :0 wf - | formail -R \"X-MHE-Checksum\" \"X-Old-MHE-Checksum\" - -Configuring Indexed Searches - -The command \\[mh-search] runs the command defined by the option -`mh-search-program'. The default value is \"Auto-detect\" which -means that MH-E will automatically choose one of \"swish++\", -\"swish-e\", \"mairix\", \"namazu\", \"pick\" and \"grep\" in -that order. If, for example, you have both \"swish++\" and -\"mairix\" installed and you want to use \"mairix\", then you can -set this option to \"mairix\". - -The documentation for the following commands describe how to set -up the various indexing programs to use with MH-E. - - - `mh-swish++-execute-search' - - `mh-swish-execute-search' - - `mh-mairix-execute-search' - - `mh-namazu-execute-search' - - `mh-pick-execute-search' - - `mh-grep-execute-search' - -In a program, if FOLDER is \"+\" or nil, 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." - (interactive - (list (progn - (mh-find-path) - ;; Yes, we do want to call mh-search-choose every time in case the - ;; user has switched the searcher manually. - (unless (mh-search-choose (and current-prefix-arg - mh-index-previous-search - (cadr mh-index-previous-search))) - (error "No search program found")) - (or (and current-prefix-arg mh-index-sequence-search-flag) - (and current-prefix-arg (car mh-index-previous-search)) - (mh-prompt-for-folder "Search" "+" nil "all" t))) - (or (and current-prefix-arg (caddr mh-index-previous-search)) - mh-search-regexp-builder - (read-string (format "%s regexp: " - (upcase-initials (symbol-name mh-searcher))))) - current-prefix-arg - (if (and (not (and current-prefix-arg - (caddr mh-index-previous-search))) - mh-search-regexp-builder) - (current-window-configuration) - nil))) - (cl-block mh-search - ;; Redoing a sequence search? - (when (and redo-search-flag mh-index-data mh-index-sequence-search-flag - (not mh-flists-called-flag)) - (let ((mh-flists-called-flag t)) - (apply #'mh-index-sequenced-messages mh-index-previous-search)) - (cl-return-from mh-search)) - ;; We have fancy query parsing. - (when (symbolp search-regexp) - (mh-search-folder folder window-config) - (cl-return-from mh-search)) - ;; Begin search proper. - (mh-checksum-choose) - (let ((result-count 0) - (old-window-config (or window-config mh-previous-window-config)) - (previous-search mh-index-previous-search) - (index-folder (format "%s/%s" mh-index-folder - (mh-index-generate-pretty-name search-regexp)))) - ;; Create a new folder for the search results or recreate the old one... - (if (and redo-search-flag mh-index-previous-search) - (let ((buffer-name (buffer-name (current-buffer)))) - (mh-process-or-undo-commands buffer-name) - (save-excursion (mh-exec-cmd-quiet nil "rmf" buffer-name)) - (mh-exec-cmd-quiet nil "folder" "-create" "-fast" buffer-name) - (setq index-folder buffer-name)) - (setq index-folder (mh-index-new-folder index-folder search-regexp))) - - (let ((folder-path (format "%s%s" mh-user-path (substring folder 1))) - (folder-results-map (make-hash-table :test #'equal)) - (origin-map (make-hash-table :test #'equal))) - ;; Run search program... - (message "Executing %s... " mh-searcher) - (funcall mh-search-function folder-path search-regexp) - - ;; Parse searcher output. - (message "Processing %s output... " mh-searcher) - (goto-char (point-min)) - (cl-loop for next-result = (funcall mh-search-next-result-function) - 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) - (make-hash-table :test #'equal))) - (setf (gethash (cadr next-result) - (gethash (car next-result) folder-results-map)) - t))) - - ;; Copy the search results over. - (maphash (lambda (folder msgs) - (let ((cur (car (mh-translate-range folder "cur"))) - (msgs (sort (cl-loop - for msg being the hash-keys of msgs - collect msg) - #'<))) - (mh-exec-cmd "refile" msgs "-src" folder - "-link" index-folder) - ;; Restore cur to old value, that refile changed - (when cur - (mh-exec-cmd-quiet nil "mark" folder "-add" "-zero" - "-sequence" - "cur" (format "%s" cur))) - (cl-loop for msg in msgs - do (cl-incf result-count) - (setf (gethash result-count origin-map) - (cons folder msg))))) - folder-results-map) - - ;; Visit the results folder. - (mh-visit-folder index-folder () (list folder-results-map origin-map)) - - (goto-char (point-min)) - (forward-line) - (mh-update-sequences) - (mh-recenter nil) - - ;; Update the speedbar, if needed. - (when (mh-speed-flists-active-p) - (mh-speed-flists t mh-current-folder)) - - ;; Maintain history. - (when (or (and redo-search-flag previous-search) window-config) - (setq mh-previous-window-config old-window-config)) - (setq mh-index-previous-search (list folder mh-searcher search-regexp)) - - ;; Write out data to disk. - (unless mh-flists-called-flag (mh-index-write-data)) - - (message "%s found %s matches in %s folders" - (upcase-initials (symbol-name mh-searcher)) - (cl-loop for msg-hash being the hash-values of mh-index-data - sum (hash-table-count msg-hash)) - (cl-loop for msg-hash being the hash-values of mh-index-data - count (> (hash-table-count msg-hash) 0))))))) - -(defun mh-search-folder (folder window-config) - "Search FOLDER for messages matching a pattern. - -In a program, argument WINDOW-CONFIG is the current window -configuration and is used when the search folder is dismissed." - (interactive (list (mh-prompt-for-folder "Search" mh-current-folder nil nil t) - (current-window-configuration))) - ;; FIXME: `pick-folder' is unused! - (let () ;; (pick-folder (if (equal folder "+") mh-current-folder folder)) - (switch-to-buffer-other-window "search-pattern") - (if (or (zerop (buffer-size)) - (not (y-or-n-p "Reuse pattern? "))) - (mh-make-pick-template) - (message "")) - (setq-local mh-current-folder folder - mh-previous-window-config window-config) - (message "%s" (substitute-command-keys - (concat "Type \\[mh-index-do-search] to search messages, " - "\\[mh-pick-do-search] to use pick, " - "\\[mh-help] for help"))))) - -(defun mh-make-pick-template () - "Initialize the current buffer with a template for a pick pattern." - (let ((inhibit-read-only t)) (erase-buffer)) - (insert "From: \n" - "To: \n" - "Cc: \n" - "Date: \n" - "Subject: \n" - "---------\n") - (mh-search-mode) - (goto-char (point-min)) - (dotimes (_ 5) - (add-text-properties (point) (1+ (point)) '(front-sticky t)) - (add-text-properties (- (line-end-position) 2) - (1- (line-end-position)) - '(rear-nonsticky t)) - (add-text-properties (point) (1- (line-end-position)) '(read-only t)) - (forward-line)) - (add-text-properties (point) (1+ (point)) '(front-sticky t)) - (add-text-properties (point) (1- (line-end-position)) '(read-only t)) - (goto-char (point-max))) - -;; Sequence Searches - -;;;###mh-autoload -(defun mh-index-new-messages (folders) - "Display unseen messages. - -If you use a program such as \"procmail\" to use \"rcvstore\" to file -your incoming mail automatically, you can display new, unseen, -messages using this command. All messages in the \"unseen\" -sequence from the folders in `mh-new-messages-folders' are -listed. - -With a prefix argument, enter a space-separated list of FOLDERS, -or nothing to search all folders." - (interactive - (list (if current-prefix-arg - (split-string (read-string "Search folder(s) (default all): ")) - mh-new-messages-folders))) - (mh-index-sequenced-messages folders mh-unseen-seq)) - -;;;###mh-autoload -(defun mh-index-ticked-messages (folders) - "Display ticked messages. - -All messages in `mh-tick-seq' from the folders in -`mh-ticked-messages-folders' are listed. - -With a prefix argument, enter a space-separated list of FOLDERS, -or nothing to search all folders." - (interactive - (list (if current-prefix-arg - (split-string (read-string "Search folder(s) (default all): ")) - mh-ticked-messages-folders))) - (mh-index-sequenced-messages folders mh-tick-seq)) - -(defvar mh-mairix-folder) -(defvar mh-flists-search-folders) - -;;;###mh-autoload -(defun mh-index-sequenced-messages (folders sequence) - "Display messages in any sequence. - -All messages from the FOLDERS in `mh-new-messages-folders' in the -SEQUENCE you provide are listed. With a prefix argument, enter a -space-separated list of folders at the prompt, or nothing to -search all folders." - (interactive - (list (if current-prefix-arg - (split-string (read-string "Search folder(s) (default all): ")) - mh-new-messages-folders) - (mh-read-seq-default "Search" nil))) - (unless sequence (setq sequence mh-unseen-seq)) - (let* ((mh-flists-search-folders folders) - (mh-flists-sequence sequence) - (mh-flists-called-flag t) - (mh-searcher 'flists) - (mh-search-function 'mh-flists-execute) - (mh-search-next-result-function 'mh-mairix-next-result) - (mh-mairix-folder mh-user-path) - (mh-search-regexp-builder nil) - (new-folder (format "%s/%s/%s" mh-index-folder - mh-flists-results-folder sequence)) - (window-config (if (equal new-folder mh-current-folder) - mh-previous-window-config - (current-window-configuration))) - (redo-flag nil) - message) - (cond ((buffer-live-p (get-buffer new-folder)) - ;; The destination folder is being visited. Trick `mh-search' - ;; into thinking that the folder resulted from a previous search. - (set-buffer new-folder) - (setq mh-index-previous-search (list folders mh-searcher sequence)) - (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 an old flists search. Clear it out. - (mh-exec-cmd-quiet nil "rmf" new-folder))) - (setq message (mh-search "+" mh-flists-results-folder - redo-flag window-config) - mh-index-sequence-search-flag t - mh-index-previous-search (list folders mh-searcher sequence)) - (mh-index-write-data) - (when (stringp message) (message "%s" message)))) - -(defvar mh-flists-search-folders) - -(defun mh-flists-execute (&rest _ignored) - "Execute flists. -Search for messages belonging to `mh-flists-sequence' in the -folders specified by `mh-flists-search-folders'. If -`mh-recursive-folders-flag' is t, then the folders are searched -recursively. All arguments are IGNORED." - (set-buffer (get-buffer-create mh-temp-index-buffer)) - (erase-buffer) - (unless (executable-find "sh") - (error "Didn't find sh")) - (with-temp-buffer - (let ((seq (symbol-name mh-flists-sequence))) - (insert "for folder in `" (expand-file-name "flists" mh-progs) " " - (cond ((eq mh-flists-search-folders t) - (mh-quote-for-shell mh-inbox)) - ((eq mh-flists-search-folders nil) "") - ((listp mh-flists-search-folders) - (cl-loop for folder in mh-flists-search-folders - concat - (concat " " (mh-quote-for-shell folder))))) - (if mh-recursive-folders-flag " -recurse" "") - " -sequence " seq " -noshowzero -fast` ; do\n" - (expand-file-name "mhpath" mh-progs) " \"+$folder\" " seq "\n" - "done\n")) - (call-process-region - (point-min) (point-max) "sh" nil (get-buffer mh-temp-index-buffer)))) - -;; Navigation - -;;;###mh-autoload -(defun mh-index-next-folder (&optional backward-flag) - "Jump to the next folder marker. - -With non-nil optional argument BACKWARD-FLAG, jump to the previous -group of results." - (interactive "P") - (if (null mh-index-data) - (message "Only applicable in an MH-E index search buffer") - (let ((point (point))) - (forward-line (if backward-flag 0 1)) - (cond ((if backward-flag - (re-search-backward "^\\+" (point-min) t) - (re-search-forward "^\\+" (point-max) t)) - (beginning-of-line)) - ((and (if backward-flag - (goto-char (point-max)) - (goto-char (point-min))) - nil)) - ((if backward-flag - (re-search-backward "^\\+" (point-min) t) - (re-search-forward "^\\+" (point-max) t)) - (beginning-of-line)) - (t (goto-char point)))))) - -;;;###mh-autoload -(defun mh-index-previous-folder () - "Jump to the previous folder marker." - (interactive) - (mh-index-next-folder t)) - -;;;###mh-autoload -(defun mh-index-visit-folder () - "Visit original folder from where the message at point was found." - (interactive) - (unless mh-index-data - (error "Not in an index folder")) - (let (folder msg) - (save-excursion - (cond ((and (bolp) (eolp)) - (ignore-errors (forward-line -1)) - (setq msg (mh-get-msg-num t))) - ((equal (char-after (line-beginning-position)) ?+) - (setq folder (buffer-substring-no-properties - (line-beginning-position) - (line-end-position)))) - (t (setq msg (mh-get-msg-num t))))) - (when (not folder) - (setq folder (car (gethash (gethash msg mh-index-msg-checksum-map) - mh-index-checksum-origin-map)))) - (when (or (not (get-buffer folder)) - (y-or-n-p (format "Reuse buffer displaying %s? " folder))) - (mh-visit-folder - folder (cl-loop - for x being the hash-keys of (gethash folder mh-index-data) - when (mh-msg-exists-p x folder) collect x))))) - - - -;;; Search Menu - -(easy-menu-define - mh-pick-menu mh-search-mode-map "Menu for MH-E Search." - '("Search" - ["Perform Search" mh-index-do-search t] - ["Search with pick" mh-pick-do-search t])) - - - -;;; MH-Search Keys - -;; If this changes, modify mh-search-mode-help-messages accordingly, below. -(define-keymap :keymap mh-search-mode-map - "C-c ?" #'mh-help - "C-c C-c" #'mh-index-do-search - "C-c C-p" #'mh-pick-do-search - "C-c C-f C-b" #'mh-to-field - "C-c C-f C-c" #'mh-to-field - "C-c C-f C-m" #'mh-to-field - "C-c C-f C-s" #'mh-to-field - "C-c C-f C-t" #'mh-to-field - "C-c C-f b" #'mh-to-field - "C-c C-f c" #'mh-to-field - "C-c C-f m" #'mh-to-field - "C-c C-f s" #'mh-to-field - "C-c C-f t" #'mh-to-field) - - - -;;; MH-Search Help Messages - -;; Group messages logically, more or less. -(defvar mh-search-mode-help-messages - '((nil - "Perform search: \\[mh-index-do-search]\n" - "Search with pick: \\[mh-pick-do-search]\n\n" - "Move to a field by typing C-c C-f C-\n" - "where is the first letter of the desired field\n" - "(except for From: which uses \"m\").")) - "Key binding cheat sheet. - -This is an associative array which is used to show the most common -commands. The key is a prefix char. The value is one or more strings -which are concatenated together and displayed in the minibuffer if ? -is pressed after the prefix character. The special key nil is used to -display the non-prefixed commands. - -The substitutions described in `substitute-command-keys' are performed -as well.") - - - -;;; MH-Search Mode - -(put 'mh-search-mode 'mode-class 'special) - -(define-derived-mode mh-search-mode fundamental-mode "MH-Search" - "Mode for creating search templates in MH-E. -\\ -Edit this template by entering your search criteria in an -appropriate header field that is already there, or create a new -field yourself. If the string you're looking for could be -anywhere in a message, then place the string underneath the row -of dashes. - -To perform the search, type \\[mh-index-do-search]. - -Sometimes you're searching for text that is either not indexed, -or hasn't been indexed yet. In this case you can override the -default method with the pick method by running the command -\\[mh-pick-do-search]. - -The hook `mh-search-mode-hook' is called upon entry to this mode. - -\\{mh-search-mode-map}" - - (mh-set-help mh-search-mode-help-messages)) - - - -;;; MH-Search Commands - -(defun mh-index-do-search (&optional searcher) - "Find messages using `mh-search-program'. -If optional argument SEARCHER is present, use it instead of -`mh-search-program'." - (interactive) - (unless (mh-search-choose searcher) (error "No search program found")) - (let* ((regexp-list (mh-pick-parse-search-buffer)) - (pattern (funcall mh-search-regexp-builder regexp-list))) - (if pattern - (mh-search mh-current-folder pattern nil mh-previous-window-config) - (error "No search terms")))) - -(defun mh-pick-do-search () - "Find messages using \"pick\". - -Uses the pick method described in `mh-pick-execute-search'." - (interactive) - (mh-index-do-search 'pick)) - -(defun mh-pick-parse-search-buffer () - "Parse the search buffer contents. -The function returns an alist. The car of each element is either -the header name to search in or nil to search the whole message. -The cdr of the element is the pattern to search." - (save-excursion - (let ((pattern-list ()) - (in-body-flag nil) - start begin) - (goto-char (point-min)) - (while (not (eobp)) - (if (search-forward "--------" (line-end-position) t) - (setq in-body-flag t) - (beginning-of-line) - (setq begin (point)) - (setq start (if in-body-flag - (point) - (search-forward ":" (line-end-position) t) - (point))) - (push (cons (and (not in-body-flag) - (intern (downcase - (buffer-substring-no-properties - begin (1- start))))) - (mh-index-parse-search-regexp - (buffer-substring-no-properties - start (line-end-position)))) - pattern-list)) - (forward-line)) - pattern-list))) - -(defun mh-index-parse-search-regexp (input-string) - "Construct parse tree for INPUT-STRING. -All occurrences of &, |, ! and ~ in INPUT-STRING are replaced by -AND, OR and NOT as appropriate. Then the resulting string is -parsed." - (let (input) - (with-temp-buffer - (insert input-string) - ;; replace tabs - (mh-replace-string "\t" " ") - ;; synonyms of AND - (mh-replace-string " AND " " and ") - (mh-replace-string "&" " and ") - (mh-replace-string " -and " " and ") - ;; synonyms of OR - (mh-replace-string " OR " " or ") - (mh-replace-string "|" " or ") - (mh-replace-string " -or " " or ") - ;; synonyms of NOT - (mh-replace-string " NOT " " not ") - (mh-replace-string "!" " not ") - (mh-replace-string "~" " not ") - (mh-replace-string " -not " " not ") - ;; synonyms of left brace - (mh-replace-string "(" " ( ") - (mh-replace-string " -lbrace " " ( ") - ;; synonyms of right brace - (mh-replace-string ")" " ) ") - (mh-replace-string " -rbrace " " ) ") - ;; get the normalized input - (setq input (format "( %s )" (buffer-substring (point-min) (point-max))))) - - (let ((tokens (mh-index-add-implicit-ops (split-string input))) - (op-stack ()) - (operand-stack ()) - oper1) - (dolist (token tokens) - (cond ((equal token "(") (push 'paren op-stack)) - ((equal token "not") (push 'not op-stack)) - ((equal token "or") (push 'or op-stack)) - ((equal token "and") (push 'and op-stack)) - ((equal token ")") - (cl-multiple-value-setq (op-stack operand-stack) - (cl-values-list (mh-index-evaluate op-stack operand-stack))) - (when (eq (car op-stack) 'not) - (setq op-stack (cdr op-stack)) - (push `(not ,(pop operand-stack)) operand-stack)) - (when (eq (car op-stack) 'and) - (setq op-stack (cdr op-stack)) - (setq oper1 (pop operand-stack)) - (push `(and ,(pop operand-stack) ,oper1) operand-stack))) - ((eq (car op-stack) 'not) - (setq op-stack (cdr op-stack)) - (push `(not ,token) operand-stack) - (when (eq (car op-stack) 'and) - (setq op-stack (cdr op-stack)) - (setq oper1 (pop operand-stack)) - (push `(and ,(pop operand-stack) ,oper1) operand-stack))) - ((eq (car op-stack) 'and) - (setq op-stack (cdr op-stack)) - (push `(and ,(pop operand-stack) ,token) operand-stack)) - (t (push token operand-stack)))) - (prog1 (pop operand-stack) - (when (or op-stack operand-stack) - (error "Invalid regexp: %s" input)))))) - -(defun mh-index-add-implicit-ops (tokens) - "Add implicit operators in the list TOKENS." - (let ((result ()) - (literal-seen nil) - current) - (while tokens - (setq current (pop tokens)) - (cond ((or (equal current ")") (equal current "and") (equal current "or")) - (setq literal-seen nil) - (push current result)) - ((and literal-seen - (push "and" result) - (setq literal-seen nil) - nil)) - (t - (push current result) - (unless (or (equal current "(") (equal current "not")) - (setq literal-seen t))))) - (nreverse result))) - -(defun mh-index-evaluate (op-stack operand-stack) - "Read expression till starting paren based on OP-STACK and OPERAND-STACK." - (cl-block mh-index-evaluate - (let (op oper1) - (while op-stack - (setq op (pop op-stack)) - (cond ((eq op 'paren) - (cl-return-from mh-index-evaluate (list op-stack operand-stack))) - ((eq op 'not) - (push `(not ,(pop operand-stack)) operand-stack)) - ((or (eq op 'and) (eq op 'or)) - (setq oper1 (pop operand-stack)) - (push `(,op ,(pop operand-stack) ,oper1) operand-stack)))) - (error "Ran out of tokens")))) - - - -;;; Indexing Functions - -;; Support different search programs -(defvar mh-search-choices - '((swish++ - mh-swish++-binary mh-swish++-execute-search mh-swish++-next-result - mh-swish++-regexp-builder) - (swish - mh-swish-binary mh-swish-execute-search mh-swish-next-result nil) - (mairix - mh-mairix-binary mh-mairix-execute-search mh-mairix-next-result - mh-mairix-regexp-builder) - (namazu - mh-namazu-binary mh-namazu-execute-search mh-namazu-next-result nil) - (pick - mh-pick-binary mh-pick-execute-search mh-pick-next-result - mh-pick-regexp-builder) - (grep - mh-grep-binary mh-grep-execute-search mh-grep-next-result nil)) - "List of possible searcher choices.") - -(defun mh-search-choose (&optional searcher) - "Choose a searching function. -The side-effects of this function are that the variables -`mh-searcher', `mh-search-function', and -`mh-search-next-result-function' are set according to the first -searcher in `mh-search-choices' present on the system. If -optional argument SEARCHER is present, use it instead of -`mh-search-program'." - (cl-block nil - (let ((program-alist (cond (searcher - (list (assoc searcher mh-search-choices))) - (mh-search-program - (list - (assoc mh-search-program mh-search-choices))) - (t mh-search-choices)))) - (while program-alist - (let* ((current (pop program-alist)) - (executable (symbol-value (cadr current)))) - (when executable - (setq mh-searcher (car current)) - (setq mh-search-function (nth 2 current)) - (setq mh-search-next-result-function (nth 3 current)) - (setq mh-search-regexp-builder (nth 4 current)) - (cl-return mh-searcher)))) - nil))) - -;;; Swish++ - -(defvar mh-swish++-binary (or (executable-find "search++") - (executable-find "search"))) -(defvar mh-swish++-directory ".swish++") -(defvar mh-swish-folder nil) - -(defun mh-swish++-execute-search (folder-path search-regexp) - "Execute swish++. - -In the examples below, replace \"/home/user/Mail\" with the path to -your MH directory. - -First create the directory \"/home/user/Mail/.swish++\". Then create -the file \"/home/user/Mail/.swish++/swish++.conf\" with the following -contents: - - IncludeMeta Bcc Cc Comments Content-Description From Keywords - IncludeMeta Newsgroups Resent-To Subject To - IncludeMeta Message-Id References In-Reply-To - IncludeFile Mail * - IndexFile /home/user/Mail/.swish++/swish++.index - -Use the following command line to generate the swish index. Run -this daily from cron: - - find /home/user/Mail -path /home/user/Mail/mhe-index -prune \\ - -o -path /home/user/Mail/.swish++ -prune \\ - -o -name \"[0-9]*\" -print \\ - | index -c /home/user/Mail/.swish++/swish++.conf - - -This command does not index the folders that hold the results of your -searches in \"+mhe-index\" since they tend to be ephemeral and the -original messages are indexed anyway. - -On some systems (Debian GNU/Linux, for example), use \"index++\" -instead of \"index\". - -In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP is -used to search." - (set-buffer (get-buffer-create mh-temp-index-buffer)) - (erase-buffer) - (unless mh-swish++-binary - (error "Set `mh-swish++-binary' appropriately")) - (call-process mh-swish++-binary nil '(t nil) nil - "-m" "10000" - (format "-i%s%s/swish++.index" - mh-user-path mh-swish++-directory) - search-regexp) - (goto-char (point-min)) - (setq mh-swish-folder - (let ((last-char (substring folder-path (1- (length folder-path))))) - (if (equal last-char "/") - folder-path - (format "%s/" folder-path))))) - -(defalias 'mh-swish++-next-result #'mh-swish-next-result) - -(defun mh-swish++-regexp-builder (regexp-list) - "Generate query for swish++. -REGEXP-LIST is an alist of fields and values." - (let ((regexp "")) - (dolist (elem regexp-list) - (when (cdr elem) - (setq regexp (concat regexp " and " - (if (car elem) "(" "") - (if (car elem) (symbol-name (car elem)) "") - (if (car elem) " = " "") - (mh-swish++-print-regexp (cdr elem)) - (if (car elem) ")" ""))))) - (substring regexp 4))) - -(defun mh-swish++-print-regexp (expr) - "Return infix expression corresponding to EXPR." - (cond ((atom expr) (format "%s" expr)) - ((eq (car expr) 'not) - (format "(not %s)" (mh-swish++-print-regexp (cadr expr)))) - (t (format "(%s %s %s)" (mh-swish++-print-regexp (cadr expr)) - (symbol-name (car expr)) - (mh-swish++-print-regexp (caddr expr)))))) - -;;; Swish - -(defvar mh-swish-binary (executable-find "swish-e")) -(defvar mh-swish-directory ".swish") - -(defun mh-swish-execute-search (folder-path search-regexp) - "Execute swish-e. - -In the examples below, replace \"/home/user/Mail\" with the path -to your MH directory. - -First create the directory \"/home/user/Mail/.swish\". Then -create the file \"/home/user/Mail/.swish/config\" with the -following contents: - - DefaultContents TXT* - IndexDir /home/user/Mail - IndexFile /home/user/Mail/.swish/index - IndexName \"Mail Index\" - IndexDescription \"Mail Index\" - IndexPointer \"http://nowhere\" - IndexAdmin \"nobody\" - #MetaNames automatic - IndexReport 3 - FollowSymLinks no - UseStemming no - IgnoreTotalWordCountWhenRanking yes - WordCharacters abcdefghijklmnopqrstuvwxyz0123456789- - BeginCharacters abcdefghijklmnopqrstuvwxyz - EndCharacters abcdefghijklmnopqrstuvwxyz0123456789 - IgnoreLimit 50 1000 - IndexComments 0 - FileRules filename contains \\D - FileRules pathname contains /home/user/Mail/.swish - FileRules pathname contains /home/user/Mail/mhe-index - -This configuration does not index the folders that hold the -results of your searches in \"+mhe-index\" since they tend to be -ephemeral and the original messages are indexed anyway. - -If there are any directories you would like to ignore, append -lines like the following to \"config\": - - FileRules pathname contains /home/user/Mail/scripts - -Use the following command line to generate the swish index. Run -this daily from cron: - - swish-e -c /home/user/Mail/.swish/config - -In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP -is used to search." - (set-buffer (get-buffer-create mh-temp-index-buffer)) - (erase-buffer) - (unless mh-swish-binary - (error "Set `mh-swish-binary' appropriately")) - (call-process mh-swish-binary nil '(t nil) nil - "-w" search-regexp - "-f" (format "%s%s/index" mh-user-path mh-swish-directory)) - (goto-char (point-min)) - (setq mh-swish-folder - (let ((last-char (substring folder-path (1- (length folder-path))))) - (if (equal last-char "/") - folder-path - (format "%s/" folder-path))))) - -(defun mh-swish-next-result () - "Get the next result from swish output." - (prog1 - (cl-block nil - (when (or (eobp) (equal (char-after (point)) ?.)) - (cl-return nil)) - (when (equal (char-after (point)) ?#) - (cl-return 'error)) - (let* ((start (search-forward " " (line-end-position) t)) - (end (search-forward " " (line-end-position) t))) - (unless (and start end) - (cl-return 'error)) - (setq end (1- end)) - (unless (file-exists-p (buffer-substring-no-properties start end)) - (cl-return 'error)) - (unless (search-backward "/" start t) - (cl-return 'error)) - (list (let* ((s (buffer-substring-no-properties start (1+ (point))))) - (unless (string-match mh-swish-folder s) - (cl-return 'error)) - (if (and (string-match mh-user-path s) - (< (match-end 0) (1- (length s)))) - (format "+%s" - (substring s (match-end 0) (1- (length s)))) - (cl-return 'error))) - (let* ((s (buffer-substring-no-properties (1+ (point)) end)) - (n (ignore-errors (string-to-number s)))) - (or n (cl-return 'error))) - nil))) - (forward-line))) - -;;; Mairix - -(defvar mh-mairix-binary (executable-find "mairix")) -(defvar mh-mairix-directory ".mairix") -(defvar mh-mairix-folder nil) - -(defun mh-mairix-execute-search (folder-path search-regexp-list) - "Execute mairix. - -In the examples below, replace \"/home/user/Mail\" with the path -to your MH directory. - -First create the directory \"/home/user/Mail/.mairix\". Then -create the file \"/home/user/Mail/.mairix/config\" with the -following contents: - - base=/home/user/Mail - - # List of folders that should be indexed. 3 dots at the end means there - # are subfolders within the folder - mh=archive...:inbox:drafts:news:sent:trash - - vfolder_format=mh - database=/home/user/Mail/.mairix/database - -Use the following command line to generate the mairix index. Run -this daily from cron: - - mairix -f /home/user/Mail/.mairix/config - -In a program, FOLDER-PATH is the directory in which -SEARCH-REGEXP-LIST is used to search." - (set-buffer (get-buffer-create mh-temp-index-buffer)) - (erase-buffer) - (unless mh-mairix-binary - (error "Set `mh-mairix-binary' appropriately")) - (apply #'call-process mh-mairix-binary nil '(t nil) nil - "-r" "-f" (format "%s%s/config" mh-user-path mh-mairix-directory) - search-regexp-list) - (goto-char (point-min)) - (setq mh-mairix-folder - (let ((last-char (substring folder-path (1- (length folder-path))))) - (if (equal last-char "/") - folder-path - (format "%s/" folder-path))))) - -(defun mh-mairix-next-result () - "Return next result from mairix output." - (prog1 - (cl-block nil - (when (or (eobp) (and (bolp) (eolp))) - (cl-return nil)) - (unless (eq (char-after) ?/) - (cl-return 'error)) - (let ((start (point)) - end msg-start) - (setq end (line-end-position)) - (unless (search-forward mh-mairix-folder end t) - (cl-return 'error)) - (goto-char (match-beginning 0)) - (unless (equal (point) start) - (cl-return 'error)) - (goto-char end) - (unless (search-backward "/" start t) - (cl-return 'error)) - (setq msg-start (1+ (point))) - (goto-char start) - (unless (search-forward mh-user-path end t) - (cl-return 'error)) - (list (format "+%s" (buffer-substring-no-properties - (point) (1- msg-start))) - (string-to-number - (buffer-substring-no-properties msg-start end)) - nil))) - (forward-line))) - -(defun mh-mairix-regexp-builder (regexp-list) - "Generate query for mairix. -REGEXP-LIST is an alist of fields and values." - (let ((result ())) - (dolist (pair regexp-list) - (when (cdr pair) - (push - (concat - (cond ((eq (car pair) 'to) "t:") - ((eq (car pair) 'from) "f:") - ((eq (car pair) 'cc) "c:") - ((eq (car pair) 'to-or-cc) "tc:") - ((eq (car pair) 'address) "a:") - ((eq (car pair) 'subject) "s:") - ((eq (car pair) 'subject-or-body) "bs:") - ((eq (car pair) 'date) "d:") - ((eq (car pair) 'message-id) "m:") - ((eq (car pair) 'message-body) "b:") - ((eq (car pair) 'message-size) "z:") - ((eq (car pair) 'message-attachment-name) "n:") - ((eq (car pair) 'message-flags) "F:") - (t "")) - (let ((sop (cdr (mh-mairix-convert-to-sop* (cdr pair)))) - (final "")) - (dolist (conjunct sop) - (let ((expr-list (cdr conjunct)) - (expr-string "")) - (dolist (e expr-list) - (setq expr-string (concat expr-string "," - (if (atom e) "" "~") - (if (atom e) e (cadr e))))) - (setq final (concat final "/" (substring expr-string 1))))) - (substring final 1))) - result))) - result)) - -(defun mh-mairix-convert-to-sop* (expr) - "Convert EXPR to sum of product form." - (cond ((atom expr) `(or (and ,expr))) - ((eq (car expr) 'or) - (cons 'or - (cl-loop for e in (mapcar #'mh-mairix-convert-to-sop* (cdr expr)) - append (cdr e)))) - ((eq (car expr) 'and) - (let ((conjuncts (mapcar #'mh-mairix-convert-to-sop* (cdr expr))) - result next-factor) - (setq result (pop conjuncts)) - (while conjuncts - (setq next-factor (pop conjuncts)) - (setq result (let ((res ())) - (dolist (t1 (cdr result)) - (dolist (t2 (cdr next-factor)) - (push `(and ,@(cdr t1) ,@(cdr t2)) res))) - (cons 'or res)))) - result)) - ((atom (cadr expr)) `(or (and ,expr))) - ((eq (caadr expr) 'not) (mh-mairix-convert-to-sop* (cadadr expr))) - ((eq (caadr expr) 'and) (mh-mairix-convert-to-sop* - `(or ,@(mapcar (lambda (x) `(not ,x)) - (cdadr expr))))) - ((eq (caadr expr) 'or) (mh-mairix-convert-to-sop* - `(and ,@(mapcar (lambda (x) `(not ,x)) - (cdadr expr))))) - (t (error "Unreachable: %s" expr)))) - -;;; Namazu - -(defvar mh-namazu-binary (executable-find "namazu")) -(defvar mh-namazu-directory ".namazu") -(defvar mh-namazu-folder nil) - -(defun mh-namazu-execute-search (folder-path search-regexp) - "Execute namazu. - -In the examples below, replace \"/home/user/Mail\" with the path to -your MH directory. - -First create the directory \"/home/user/Mail/.namazu\". Then create -the file \"/home/user/Mail/.namazu/mknmzrc\" with the following -contents: - - package conf; # Don't remove this line! - $ADDRESS = \\='user@localhost\\='; - $ALLOW_FILE = \"[0-9]*\"; - $EXCLUDE_PATH = \"^/home/user/Mail/(mhe-index|spam)\"; - -This configuration does not index the folders that hold the results of -your searches in \"+mhe-index\" since they tend to be ephemeral and -the original messages are indexed anyway. - -Use the following command line to generate the namazu index. Run this -daily from cron: - - mknmz -f /home/user/Mail/.namazu/mknmzrc -O /home/user/Mail/.namazu \\ - -q /home/user/Mail - -In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP -is used to search." - (let ((namazu-index-directory - (format "%s%s" mh-user-path mh-namazu-directory))) - (unless (file-exists-p namazu-index-directory) - (error "Namazu directory %s not present" namazu-index-directory)) - (unless (executable-find mh-namazu-binary) - (error "Set `mh-namazu-binary' appropriately")) - (set-buffer (get-buffer-create mh-temp-index-buffer)) - (erase-buffer) - (call-process mh-namazu-binary nil '(t nil) nil - "-alR" search-regexp namazu-index-directory) - (goto-char (point-min)) - (setq mh-namazu-folder - (let ((last (substring folder-path (1- (length folder-path))))) - (if (equal last "/") - folder-path - (format "%s/" folder-path)))))) - -(defun mh-namazu-next-result () - "Get the next result from namazu output." - (prog1 - (cl-block nil - (when (eobp) (cl-return nil)) - (let ((file-name (buffer-substring-no-properties - (point) (line-end-position)))) - (unless (equal (string-match mh-namazu-folder file-name) 0) - (cl-return 'error)) - (unless (file-exists-p file-name) - (cl-return 'error)) - (string-match mh-user-path file-name) - (let* ((folder/msg (substring file-name (match-end 0))) - (mark (mh-search-from-end ?/ folder/msg))) - (unless mark (cl-return 'error)) - (list (format "+%s" (substring folder/msg 0 mark)) - (let ((n (ignore-errors (string-to-number - (substring folder/msg (1+ mark)))))) - (or n (cl-return 'error))) - nil)))) - (forward-line))) - -;;; Pick - -(defvar mh-index-pick-folder) -(defvar mh-pick-binary "pick") -(defconst mh-pick-single-dash '(cc date from subject to) - "Search components that are supported by single-dash option in pick.") - -(defun mh-pick-execute-search (folder-path search-regexp) - "Execute pick. - -Read \"pick(1)\" or the section Finding Messages with pick in the -MH book to find out more about how to enter the criteria (see URL -`http://www.ics.uci.edu/~mh/book/mh/finpic.htm'). - -In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP -is used to search." - (set-buffer (get-buffer-create mh-temp-index-buffer)) - (erase-buffer) - (let ((folders - (mh-folder-list (substring folder-path (length mh-user-path))))) - (cl-loop for folder in folders do - (setq folder (concat "+" folder)) - (insert folder "\n") - (apply #'call-process (expand-file-name "pick" mh-progs) - nil '(t nil) nil folder "-list" search-regexp))) - (goto-char (point-min))) - -(defun mh-pick-next-result () - "Return the next pick search result." - (prog1 - (cl-block nil - (when (eobp) (cl-return nil)) - (when (search-forward-regexp "^\\+" (line-end-position) t) - (setq mh-index-pick-folder - (buffer-substring-no-properties (line-beginning-position) - (line-end-position))) - (cl-return 'error)) - (unless (search-forward-regexp "^[1-9][0-9]*$" (line-end-position) t) - (cl-return 'error)) - (list mh-index-pick-folder - (string-to-number - (buffer-substring-no-properties (line-beginning-position) - (line-end-position))) - nil)) - (forward-line))) - -;; All implementations of pick have special options -cc, -date, -from and -;; -subject that allow searching for corresponding components. Any other -;; component is searched using option --COMPNAME, for example: `pick -;; --x-mailer mh-e'. Mailutils "pick" supports this option using a certain -;; kludge, but it prefers the following syntax for this purpose: -;; "--component=COMPNAME --pattern=PATTERN". -;; -- Sergey Poznyakoff, Aug 2003 -(defun mh-pick-regexp-builder (pattern-list) - "Generate pick search expression from PATTERN-LIST." - (let ((result ())) - (dolist (pattern pattern-list) - (when (cdr pattern) - (setq result `(,@result "-and" "-lbrace" - ,@(mh-pick-construct-regexp - (if (and (mh-variant-p 'gnu-mh) (car pattern)) - (format "--pattern=%s" (cdr pattern)) - (cdr pattern)) - (if (car pattern) - (cond - ((mh-variant-p 'gnu-mh) - (format "--component=%s" (car pattern))) - ((member (car pattern) mh-pick-single-dash) - (format "-%s" (car pattern))) - (t - (format "--%s" (car pattern)))) - "-search")) - "-rbrace")))) - (cdr result))) - -(defun mh-pick-construct-regexp (expr component) - "Construct pick compatible expression corresponding to EXPR. -COMPONENT is the component to search." - (cond ((atom expr) (list component expr)) - ((eq (car expr) 'and) - `("-lbrace" ,@(mh-pick-construct-regexp (cadr expr) component) "-and" - ,@(mh-pick-construct-regexp (caddr expr) component) "-rbrace")) - ((eq (car expr) 'or) - `("-lbrace" ,@(mh-pick-construct-regexp (cadr expr) component) "-or" - ,@(mh-pick-construct-regexp (caddr expr) component) "-rbrace")) - ((eq (car expr) 'not) - `("-lbrace" "-not" ,@(mh-pick-construct-regexp (cadr expr) component) - "-rbrace")) - (t (error "Unknown operator %s seen" (car expr))))) - -;;; Grep - -(defvar mh-grep-binary (executable-find "grep")) - -(defun mh-grep-execute-search (folder-path search-regexp) - "Execute grep. - -Unlike the other search methods, this method does not use the -MH-Search buffer. Instead, you simply enter a regular expression -in the minibuffer. For help in constructing regular expressions, -see your man page for \"grep\". - -In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP -is used to search." - (set-buffer (get-buffer-create mh-temp-index-buffer)) - (erase-buffer) - (call-process mh-grep-binary nil '(t nil) nil - "-i" "-r" search-regexp folder-path) - (goto-char (point-min))) - -(defun mh-grep-next-result () - "Read the next result. -Parse it and return the message folder, message index and the -match. If no other matches left then return nil. If the current -record is invalid return `error'." - (prog1 - (cl-block nil - (when (eobp) - (cl-return nil)) - (let ((eol-pos (line-end-position)) - (bol-pos (line-beginning-position)) - folder-start msg-end) - (goto-char bol-pos) - (unless (search-forward mh-user-path eol-pos t) - (cl-return 'error)) - (setq folder-start (point)) - (unless (search-forward ":" eol-pos t) - (cl-return 'error)) - (let ((match (buffer-substring-no-properties (point) eol-pos))) - (forward-char -1) - (setq msg-end (point)) - (unless (search-backward "/" folder-start t) - (cl-return 'error)) - (list (format "+%s" (buffer-substring-no-properties - folder-start (point))) - (let ((n (ignore-errors (string-to-number - (buffer-substring-no-properties - (1+ (point)) msg-end))))) - (or n (cl-return 'error))) - match)))) - (forward-line))) - - - -;;; Folder Utilities - -;;;###mh-autoload -(defun mh-index-group-by-folder () - "Partition the messages based on source folder. -Returns an alist with 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 :test #'equal))) - (cl-loop for msg being the 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))) - (cl-loop for x being the hash-keys of result-table - collect (cons x (nreverse (gethash x result-table))))))) - -;;;###mh-autoload -(defun mh-index-insert-folder-headers () - "Annotate the search results with original folder names." - (let ((cur-msg (mh-get-msg-num nil)) - (old-buffer-modified-flag (buffer-modified-p)) - (buffer-read-only nil) - current-folder last-folder) - (goto-char (point-min)) - (while (not (eobp)) - (setq current-folder (car (gethash (gethash (mh-get-msg-num nil) - mh-index-msg-checksum-map) - mh-index-checksum-origin-map))) - (when (and current-folder (not (equal current-folder last-folder))) - (insert (if last-folder "\n" "") current-folder "\n") - (setq last-folder current-folder)) - (forward-line)) - (when cur-msg - (mh-notate-cur) - (mh-goto-msg cur-msg t)) - (set-buffer-modified-p old-buffer-modified-flag)) - (mh-index-create-imenu-index)) - -;;;###mh-autoload -(defun mh-index-delete-folder-headers () - "Delete the folder headers." - (let ((cur-msg (mh-get-msg-num nil)) - (old-buffer-modified-flag (buffer-modified-p)) - (buffer-read-only nil)) - (while (and (not cur-msg) (not (eobp))) - (forward-line) - (setq cur-msg (mh-get-msg-num nil))) - (goto-char (point-min)) - (while (not (eobp)) - (if (or (char-equal (char-after) ?+) (char-equal (char-after) 10)) - (delete-region (point) (progn (forward-line) (point))) - (forward-line))) - (when cur-msg (mh-goto-msg cur-msg t t)) - (set-buffer-modified-p old-buffer-modified-flag))) - -(require 'which-func) - -;;;###mh-autoload -(defun mh-index-create-imenu-index () - "Create alist of folder names and positions in index folder buffers." - (save-excursion - (if (boundp 'which-func-mode) - (setq which-func-mode t)) - (let ((alist ())) - (goto-char (point-min)) - (while (re-search-forward "^\\+" nil t) - (save-excursion - (beginning-of-line) - (push (cons (buffer-substring-no-properties - (point) (line-end-position)) - (point-marker)) - alist))) - (setq imenu--index-alist (nreverse alist))))) - -;;;###mh-autoload -(defun mh-search-p () - "Non-nil means that this folder was generated by searching." - mh-index-data) - -(defvar mh-speed-flists-inhibit-flag) - -;;;###mh-autoload -(defun mh-index-execute-commands () - "Perform the outstanding operations on the actual messages. -The copies in the searched folder are then deleted, refiled, -blocklisted and allowlisted to get the desired result. Before -processing the messages we make sure that the message is -identical to the one that the user has marked in the index -buffer." - (save-excursion - (let ((folders ()) - (mh-speed-flists-inhibit-flag t)) - (maphash - (lambda (folder msgs) - (push folder folders) - (if (not (get-buffer folder)) - ;; If source folder not open, just delete the messages... - (apply #'mh-exec-cmd "rmm" folder (mh-coalesce-msg-list msgs)) - ;; Otherwise delete the messages in the source buffer... - (with-current-buffer folder - (let ((old-refile-list mh-refile-list) - (old-delete-list mh-delete-list) - (old-blocklist mh-blocklist) - (old-allowlist mh-allowlist)) - (setq mh-refile-list nil - mh-delete-list msgs - mh-blocklist nil - mh-allowlist nil) - (unwind-protect (mh-execute-commands) - (setq mh-refile-list - (mapcar (lambda (x) - (cons (car x) - (cl-loop for y in (cdr x) - unless (memq y msgs) - collect y))) - old-refile-list) - mh-delete-list - (cl-loop for x in old-delete-list - unless (memq x msgs) collect x) - mh-blocklist - (cl-loop for x in old-blocklist - unless (memq x msgs) collect x) - mh-allowlist - (cl-loop for x in old-allowlist - unless (memq x msgs) collect x)) - (mh-set-folder-modified-p (mh-outstanding-commands-p)) - (when (mh-outstanding-commands-p) - (mh-notate-deleted-and-refiled))))))) - (mh-index-matching-source-msgs (append (cl-loop for x in mh-refile-list - append (cdr x)) - mh-delete-list - mh-blocklist - mh-allowlist) - t)) - folders))) - -(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 replaced with underscores and all / are replaced -with $. If STRING is longer than 20 it is truncated too. STRING -could be a list of strings in which case they are concatenated to -construct the base name." - (with-temp-buffer - (if (stringp string) - (insert string) - (when (car string) (insert (car string))) - (dolist (s (cdr string)) - (insert "_" s))) - (setq string (mh-replace-string "-lbrace" " ")) - (setq string (mh-replace-string "-rbrace" " ")) - (setq string (mh-replace-string "-search" " ")) - (subst-char-in-region (point-min) (point-max) ?\( ? t) - (subst-char-in-region (point-min) (point-max) ?\) ? t) - (subst-char-in-region (point-min) (point-max) ?- ? t) - (goto-char (point-min)) - (while (and (not (eobp)) (memq (char-after) '(? ?\t ?\n ?\r ?_))) - (delete-char 1)) - (goto-char (point-max)) - (while (and (not (bobp)) (memq (char-before) '(? ?\t ?\n ?\r ?_))) - (delete-char -1)) - (subst-char-in-region (point-min) (point-max) ? ?_ t) - (subst-char-in-region (point-min) (point-max) ?\t ?_ t) - (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) - (let ((out (truncate-string-to-width (buffer-string) 20))) - (cond ((eq mh-searcher 'flists) - (format "%s/%s" mh-flists-results-folder mh-flists-sequence)) - ((equal out mh-flists-results-folder) (concat out "1")) - (t out))))) - -(defun mh-folder-exists-p (folder) - "Check if FOLDER exists." - (and (mh-folder-name-p folder) - (save-excursion - (with-temp-buffer - (mh-exec-cmd-output "folder" nil "-fast" "-nocreate" folder) - (goto-char (point-min)) - ;; Strip + from folder; use optional + in regexp. - (looking-at (format "+?%s" (substring folder 1))))))) - -(defun mh-msg-exists-p (msg folder) - "Check if MSG exists in FOLDER." - (file-exists-p (format "%s%s/%s" mh-user-path (substring folder 1) msg))) - -(defun mh-index-new-folder (name search-regexp) - "Return a folder name based on NAME for search results of SEARCH-REGEXP. - -If folder NAME already exists and was generated for the same -SEARCH-REGEXP then it is reused. - -Otherwise if the folder NAME was generated from a different -search then check if NAME-2 can be used. Otherwise try NAME-3. -This is repeated till we find a new folder name. - -If the folder returned doesn't exist then it is created." - (unless (mh-folder-name-p name) - (error "The argument should be a valid MH folder name")) - (let ((chosen-name - (cl-loop for i from 1 - for candidate = (if (equal i 1) name (format "%s-%s" name i)) - when (or (not (mh-folder-exists-p candidate)) - (equal (mh-index-folder-search-regexp candidate) - search-regexp)) - return candidate))) - ;; Do pending refiles/deletes... - (when (get-buffer chosen-name) - (mh-process-or-undo-commands chosen-name)) - ;; Recreate folder... - (save-excursion (mh-exec-cmd-quiet nil "rmf" chosen-name)) - (mh-exec-cmd-quiet nil "folder" "-create" "-fast" chosen-name) - (mh-remove-from-sub-folders-cache chosen-name) - (when (and (boundp 'speedbar-buffer) speedbar-buffer) - (mh-speed-add-folder chosen-name)) - chosen-name)) - -(defun mh-index-folder-search-regexp (folder) - "If FOLDER was created by an index search, return the search regexp. -Return nil if FOLDER doesn't exist or the .mhe_index file is -garbled." - (ignore-errors - (with-temp-buffer - (insert-file-contents - (format "%s%s/%s" mh-user-path (substring folder 1) mh-index-data-file)) - (goto-char (point-min)) - (forward-list 3) - (cadr (read (current-buffer)))))) - - - -;;; Sequence Support - -;;;###mh-autoload -(defun mh-index-create-sequences () - "Mirror sequences present in source folders in index folder." - (let ((seq-hash (make-hash-table :test #'equal)) - (seq-list ())) - (cl-loop for folder being the hash-keys of mh-index-data - do (setf (gethash folder seq-hash) - (mh-create-sequence-map - (mh-read-folder-sequences folder nil)))) - (dolist (msg (mh-translate-range mh-current-folder "all")) - (let* ((checksum (gethash msg mh-index-msg-checksum-map)) - (pair (gethash checksum mh-index-checksum-origin-map)) - (ofolder (car pair)) - (omsg (cdr pair))) - (cl-loop for seq in (ignore-errors - (gethash omsg (gethash ofolder seq-hash))) - do (if (assoc seq seq-list) - (push msg (cdr (assoc seq seq-list))) - (push (list seq msg) seq-list))))) - (cl-loop for seq in seq-list - do (apply #'mh-exec-cmd "mark" mh-current-folder - "-sequence" (symbol-name (car seq)) "-add" - (mapcar (lambda (x) (format "%s" x)) (cdr seq)))))) - -;;;###mh-autoload -(defun mh-create-sequence-map (seq-list) - "Return a map from msg number to list of sequences in which it is present. -SEQ-LIST is an assoc list whose keys are sequence names and whose -cdr is the list of messages in that sequence." - (cl-loop with map = (make-hash-table) - for seq in seq-list - when (and (not (memq (car seq) (mh-unpropagated-sequences))) - (mh-valid-seq-p (car seq))) - do (cl-loop for msg in (cdr seq) - do (push (car seq) (gethash msg map))) - finally return map)) - -;;;###mh-autoload -(defun mh-index-add-to-sequence (seq msgs) - "Add to SEQ the messages in the list MSGS. -This function updates the source folder sequences. Also makes an -attempt to update the source folder buffer if we have it open." - ;; Don't need to do anything for cur - (save-excursion - (when (and (not (memq seq (mh-unpropagated-sequences))) - (mh-valid-seq-p seq)) - (let ((folders ()) - (mh-speed-flists-inhibit-flag t)) - (maphash (lambda (folder msgs) - (push folder folders) - ;; Add messages to sequence in source folder... - (apply #'mh-exec-cmd-quiet nil "mark" folder - "-add" "-nozero" "-sequence" (symbol-name seq) - (mapcar (lambda (x) (format "%s" x)) - (mh-coalesce-msg-list msgs))) - ;; Update source folder buffer if we have it open... - (when (get-buffer folder) - (with-current-buffer folder - (mh-put-msg-in-seq msgs seq)))) - (mh-index-matching-source-msgs msgs)) - folders)))) - -;;;###mh-autoload -(defun mh-index-delete-from-sequence (seq msgs) - "Delete from SEQ the messages in MSGS. -This function updates the source folder sequences. Also makes an -attempt to update the source folder buffer if present." - (save-excursion - (when (and (not (memq seq (mh-unpropagated-sequences))) - (mh-valid-seq-p seq)) - (let ((folders ()) - (mh-speed-flists-inhibit-flag t)) - (maphash (lambda (folder msgs) - (push folder folders) - ;; Remove messages from sequence in source folder... - (apply #'mh-exec-cmd-quiet nil "mark" folder - "-del" "-nozero" "-sequence" (symbol-name seq) - (mapcar (lambda (x) (format "%s" x)) - (mh-coalesce-msg-list msgs))) - ;; Update source folder buffer if we have it open... - (when (get-buffer folder) - (with-current-buffer folder - (mh-delete-msg-from-seq msgs seq t)))) - (mh-index-matching-source-msgs msgs)) - folders)))) - -(defvar mh-unpropagated-sequences '(cur range subject search) - "List of sequences that aren't preserved.") - -(defun mh-unpropagated-sequences () - "Return a list of sequences that aren't propagated to the source folders. -It is just the sequences in the variable -`mh-unpropagated-sequences' in addition to the -Previous-Sequence (see mh-profile 5)." - (if mh-previous-seq - (cons mh-previous-seq mh-unpropagated-sequences) - mh-unpropagated-sequences)) - -(defun mh-index-matching-source-msgs (msgs &optional delete-from-index-data) - "Return a table of original messages and folders for messages in MSGS. -If optional argument DELETE-FROM-INDEX-DATA is non-nil, then each -of the messages, whose counter-part is found in some source -folder, is removed from `mh-index-data'." - (let ((table (make-hash-table :test #'equal))) - (dolist (msg msgs) - (let* ((checksum (gethash msg mh-index-msg-checksum-map)) - (pair (gethash checksum mh-index-checksum-origin-map))) - (when (and checksum (car pair) (cdr pair) - (mh-index-match-checksum (cdr pair) (car pair) checksum)) - (push (cdr pair) (gethash (car pair) table)) - (when delete-from-index-data - (remhash (cdr pair) (gethash (car pair) mh-index-data)))))) - table)) - -(defun mh-index-match-checksum (msg folder checksum) - "Check if MSG in FOLDER has X-MHE-Checksum header value of CHECKSUM." - (with-temp-buffer - (mh-exec-cmd-output mh-scan-prog nil "-width" "80" - "-format" "%{x-mhe-checksum}\n" folder msg) - (goto-char (point-min)) - (string-equal (buffer-substring-no-properties - (point) (line-end-position)) - checksum))) - - - -;;; Serialization of Index Data - -(defun mh-index-write-data () - "Write index data to file." - (ignore-errors - (unless (eq major-mode 'mh-folder-mode) - (error "Can't be called from folder in \"%s\"" major-mode)) - (let ((data mh-index-data) - (msg-checksum-map mh-index-msg-checksum-map) - (checksum-origin-map mh-index-checksum-origin-map) - (previous-search mh-index-previous-search) - (sequence-search-flag mh-index-sequence-search-flag) - (outfile (concat buffer-file-name mh-index-data-file)) - (print-length nil) - (print-level nil)) - (with-temp-file outfile - (mh-index-write-hashtable - data (lambda (x) (cl-loop for y being the hash-keys of x collect y))) - (mh-index-write-hashtable msg-checksum-map #'identity) - (mh-index-write-hashtable checksum-origin-map #'identity) - (pp previous-search (current-buffer)) (insert "\n") - (pp sequence-search-flag (current-buffer)) (insert "\n"))))) - -(defun mh-index-write-hashtable (table proc) - "Write TABLE to `current-buffer'. -PROC is used to serialize the values corresponding to the hash -table keys." - (pp (cl-loop for x being the hash-keys of table - collect (cons x (funcall proc (gethash x table)))) - (current-buffer)) - (insert "\n")) - -;;;###mh-autoload -(defun mh-index-read-data () - "Read index data from file." - (ignore-errors - (unless (eq major-mode 'mh-folder-mode) - (error "Can't be called from folder in \"%s\"" major-mode)) - (let ((infile (concat buffer-file-name mh-index-data-file)) - t1 t2 t3 t4 t5) - (with-temp-buffer - (insert-file-contents-literally infile) - (goto-char (point-min)) - (setq t1 (mh-index-read-hashtable - (lambda (data) - (cl-loop with table = (make-hash-table :test #'equal) - for x in data do (setf (gethash x table) t) - finally return table))) - t2 (mh-index-read-hashtable #'identity) - t3 (mh-index-read-hashtable #'identity) - t4 (read (current-buffer)) - t5 (read (current-buffer)))) - (setq mh-index-data t1 - mh-index-msg-checksum-map t2 - mh-index-checksum-origin-map t3 - mh-index-previous-search t4 - mh-index-sequence-search-flag t5)))) - -(defun mh-index-read-hashtable (proc) - "From BUFFER read a hash table serialized as a list. -PROC is used to convert the value to actual data." - (cl-loop with table = (make-hash-table :test #'equal) - for pair in (read (current-buffer)) - do (setf (gethash (car pair) table) (funcall proc (cdr pair))) - finally return table)) - - - -;;; Checksum Routines - -;; A few different checksum programs are supported. The supported -;; programs are: - -;; 1. md5sum -;; 2. md5 -;; 3. openssl - -;; To add support for your favorite checksum program add a clause to -;; the cond statement in mh-checksum-choose. This should set the -;; variable mh-checksum-cmd to the command line needed to run the -;; checksum program and should set mh-checksum-parser to a function -;; which returns a cons cell containing the message number and -;; checksum string. - -(defvar mh-checksum-cmd) -(defvar mh-checksum-parser) - -(defun mh-checksum-choose () - "Check if a program to create a checksum is present." - (unless (boundp 'mh-checksum-cmd) - (let ((exec-path (append '("/sbin" "/usr/sbin") exec-path))) - (cond ((executable-find "md5sum") - (setq mh-checksum-cmd (list (executable-find "md5sum"))) - (setq mh-checksum-parser #'mh-md5sum-parser)) - ((executable-find "openssl") - (setq mh-checksum-cmd (list (executable-find "openssl") "md5")) - (setq mh-checksum-parser #'mh-openssl-parser)) - ((executable-find "md5") - (setq mh-checksum-cmd (list (executable-find "md5"))) - (setq mh-checksum-parser #'mh-md5-parser)) - (t (error "No suitable checksum program")))))) - -(defun mh-md5sum-parser () - "Parse md5sum output." - (let ((begin (line-beginning-position)) - (end (line-end-position)) - first-space last-slash) - (setq first-space (search-forward " " end t)) - (goto-char end) - (setq last-slash (search-backward "/" begin t)) - (cond ((and first-space last-slash) - (cons (string-to-number (buffer-substring-no-properties - (1+ last-slash) end)) - (buffer-substring-no-properties begin (1- first-space)))) - (t (cons nil nil))))) - -(defun mh-openssl-parser () - "Parse openssl output." - (let ((begin (line-beginning-position)) - (end (line-end-position)) - last-space last-slash) - (goto-char end) - (setq last-space (search-backward " " begin t)) - (setq last-slash (search-backward "/" begin t)) - (cond ((and last-slash last-space) - (cons (string-to-number (buffer-substring-no-properties - (1+ last-slash) (1- last-space))) - (buffer-substring-no-properties (1+ last-space) end)))))) - -(defalias 'mh-md5-parser #'mh-openssl-parser) - -;;;###mh-autoload -(defun mh-index-update-maps (folder &optional origin-map) - "Annotate all as yet unannotated messages in FOLDER with their MD5 hash. -As a side effect msg -> checksum map is updated. Optional -argument ORIGIN-MAP is a hash table which maps each message in the -index folder to the original folder and message from whence it -was copied. If present the checksum -> (origin-folder, -origin-index) map is updated too." - (clrhash mh-index-msg-checksum-map) - ;; Clear temp buffer - (with-current-buffer (get-buffer-create mh-temp-checksum-buffer) - (erase-buffer) - ;; Run scan to check if any messages needs MD5 annotations at all - (with-temp-buffer - (mh-exec-cmd-output mh-scan-prog nil "-width" "80" - "-format" "%(msg)\n%{x-mhe-checksum}\n" - folder "all") - (goto-char (point-min)) - (let (msg checksum) - (while (not (eobp)) - (setq msg (buffer-substring-no-properties - (point) (line-end-position))) - (forward-line) - (save-excursion - (cond ((not (string-match "^[0-9]*$" msg))) - ((eolp) - ;; need to compute checksum - (set-buffer mh-temp-checksum-buffer) - (insert mh-user-path (substring folder 1) "/" msg "\n")) - (t - ;; update maps - (setq checksum (buffer-substring-no-properties - (point) (line-end-position))) - (let ((msg (string-to-number msg))) - (set-buffer folder) - (mh-index-update-single-msg msg checksum origin-map))))) - (forward-line)))) - ;; Run checksum program if needed - (unless (and (eobp) (bobp)) - (apply #'mh-xargs mh-checksum-cmd) - (goto-char (point-min)) - (while (not (eobp)) - (let* ((intermediate (funcall mh-checksum-parser)) - (msg (car intermediate)) - (checksum (cdr intermediate))) - (when msg - ;; annotate - (mh-exec-cmd "anno" folder msg "-component" "X-MHE-Checksum" - "-nodate" "-text" checksum "-inplace") - ;; update maps - (with-current-buffer folder - (mh-index-update-single-msg msg checksum origin-map))) - (forward-line))))) - (mh-index-write-data)) - -(defun mh-index-update-single-msg (msg checksum origin-map) - "Update various maps for one message. -MSG is an index folder message, CHECKSUM its MD5 hash and -ORIGIN-MAP, if non-nil, a hash table containing which maps each -message in the index folder to the folder and message that it was -copied from. The function updates the hash tables -`mh-index-msg-checksum-map' and `mh-index-checksum-origin-map'. - -This function should only be called in the appropriate index -folder buffer." - (cond ((gethash checksum mh-index-checksum-origin-map) - (when origin-map - (let* ((intermediate (gethash msg origin-map)) - (ofolder (car intermediate)) - (omsg (cdr intermediate))) - ;; This is most probably a duplicate. So eliminate it. - (call-process "rm" nil nil nil - (format "%s%s/%s" mh-user-path - (substring mh-current-folder 1) msg)) - (when (gethash ofolder mh-index-data) - (remhash omsg (gethash ofolder mh-index-data)))))) - (t - (setf (gethash msg mh-index-msg-checksum-map) checksum) - (when (and origin-map (gethash msg origin-map)) - (setf (gethash checksum mh-index-checksum-origin-map) - (gethash msg origin-map)))))) - - -(provide 'mh-search) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-search.el ends here diff --git a/lisp/mh-e/mh-seq.el b/lisp/mh-e/mh-seq.el deleted file mode 100644 index 0251d4875d4..00000000000 --- a/lisp/mh-e/mh-seq.el +++ /dev/null @@ -1,1002 +0,0 @@ -;;; mh-seq.el --- MH-E sequences support -*- lexical-binding: t; -*- - -;; Copyright (C) 1993, 1995, 2001-2024 Free Software Foundation, Inc. - -;; Author: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Sequences are stored in the alist `mh-seq-list' in the form: -;; ((seq-name msgs ...) (seq-name msgs ...) ...) - -;;; Code: - -(require 'mh-e) -(require 'mh-scan) - -(require 'font-lock) - -;;; Variables - -(defvar mh-last-seq-used nil - "Name of seq to which a msg was last added.") - -(defvar-local mh-non-seq-mode-line-annotation nil - "Saved value of `mh-mode-line-annotation' when narrowed to a seq.") - -(defvar mh-internal-seqs '(answered cur deleted forwarded printed)) - -;;; Macros - -(defsubst mh-make-seq (name msgs) - "Create sequence NAME with the given MSGS." - (cons name msgs)) - -(defsubst mh-seq-name (sequence) - "Extract sequence name from the given SEQUENCE." - (car sequence)) - - - -;;; MH-Folder Commands - -;; Alphabetical. - -;;;###mh-autoload -(defun mh-catchup (range) - "Delete RANGE from the \"unseen\" sequence. - -Check the documentation of `mh-interactive-range' to see how -RANGE is read in interactive use." - (interactive (list (mh-interactive-range "Catchup" - (cons (point-min) (point-max))))) - (mh-delete-msg-from-seq range mh-unseen-seq)) - -;;;###mh-autoload -(defun mh-delete-msg-from-seq (range sequence &optional internal-flag) - "Delete RANGE from SEQUENCE. - -Check the documentation of `mh-interactive-range' to see how -RANGE is read in interactive use. - -In a program, non-nil INTERNAL-FLAG means do not inform MH of the -change." - (interactive (list (mh-interactive-range "Delete") - (mh-read-seq-default "Delete from" t) - nil)) - (let ((entry (mh-find-seq sequence)) - (user-sequence-flag (not (mh-internal-seq sequence))) - (folders-changed (list mh-current-folder)) - (msg-list ())) - (when entry - (mh-iterate-on-range msg range - (push msg msg-list) - ;; Calling "mark" repeatedly takes too long. So we will pretend here - ;; that we are just modifying an internal sequence... - (when (memq msg (cdr entry)) - (mh-remove-sequence-notation msg (not user-sequence-flag))) - (mh-delete-a-msg-from-seq msg sequence t)) - ;; ... and here we will "mark" all the messages at one go. - (unless internal-flag (mh-undefine-sequence sequence msg-list)) - (when (and mh-index-data (not internal-flag)) - (setq folders-changed - (append folders-changed - (mh-index-delete-from-sequence sequence msg-list)))) - (when (and (eq sequence mh-unseen-seq) (mh-speed-flists-active-p)) - (apply #'mh-speed-flists t folders-changed))))) - -;;;###mh-autoload -(defun mh-delete-seq (sequence) - "Delete SEQUENCE. - -You are prompted for the sequence to delete. Note that this -deletes only the sequence, not the messages in the sequence. If -you want to delete the messages, use \"\\[universal-argument] -\\[mh-delete-msg]\"." - (interactive (list (mh-read-seq-default "Delete" t))) - (let ((msg-list (mh-seq-to-msgs sequence)) - (internal-flag (mh-internal-seq sequence)) - (folders-changed (list mh-current-folder))) - (mh-iterate-on-range msg sequence - (mh-remove-sequence-notation msg internal-flag)) - (mh-undefine-sequence sequence '("all")) - (mh-delete-seq-locally sequence) - (when mh-index-data - (setq folders-changed - (append folders-changed - (mh-index-delete-from-sequence sequence msg-list)))) - (when (and (eq sequence mh-unseen-seq) (mh-speed-flists-active-p)) - (apply #'mh-speed-flists t folders-changed)))) - -;; Shush compiler. -(defvar view-exit-action) - -;;;###mh-autoload -(defun mh-list-sequences () - "List all sequences in folder. - -The list appears in a buffer named \"*MH-E Sequences*\"." - (interactive) - (let ((folder mh-current-folder) - (temp-buffer mh-sequences-buffer) - (seq-list mh-seq-list) - (max-len 0)) - (with-output-to-temp-buffer temp-buffer - (with-current-buffer temp-buffer - (erase-buffer) - (message "Listing sequences ...") - (insert "Sequences in folder " folder ":\n") - (let ((seq-list seq-list)) - (while seq-list - (setq max-len - (max (length (symbol-name (mh-seq-name (pop seq-list)))) - max-len))) - (setq max-len (+ 2 max-len))) - (while seq-list - (let ((name (mh-seq-name (car seq-list))) - (sorted-seq-msgs - (mh-coalesce-msg-list - (sort (copy-sequence (mh-seq-msgs (car seq-list))) #'<))) - name-spec) - (insert (setq name-spec (format (format "%%%ss:" max-len) name))) - (while sorted-seq-msgs - (let ((next-element (format " %s" (pop sorted-seq-msgs)))) - (when (>= (+ (current-column) (length next-element)) - (window-width)) - (insert "\n") - (insert (format (format "%%%ss" (length name-spec)) ""))) - (insert next-element))) - (insert "\n")) - (setq seq-list (cdr seq-list))) - (goto-char (point-min)) - (view-mode-enter) - (setq view-exit-action 'kill-buffer) - (message "Listing sequences...done"))))) - -;;;###mh-autoload -(defun mh-msg-is-in-seq (message) - "Display the sequences in which the current message appears. - -Use a prefix argument to display the sequences in which another -MESSAGE appears." - (interactive "P") - (if (not message) - (setq message (mh-get-msg-num t))) - (let* ((dest-folder (cl-loop for seq in mh-refile-list - when (member message (cdr seq)) return (car seq) - finally return nil)) - (deleted-flag (unless dest-folder (member message mh-delete-list)))) - (message "Message %d%s is in sequences: %s" - message - (cond (dest-folder (format " (to be refiled to %s)" dest-folder)) - (deleted-flag " (to be deleted)") - (t "")) - (mapconcat #'concat - (mh-list-to-string (mh-seq-containing-msg message t)) - " ")))) - -;;;###mh-autoload -(defun mh-narrow-to-seq (sequence) - "Restrict display to messages in SEQUENCE. - -You are prompted for the name of the sequence. What this command -does is show only those messages that are in the selected -sequence in the MH-Folder buffer. In addition, it limits further -MH-E searches to just those messages. - -When you want to widen the view to all your messages again, use -\\[mh-widen]." - (interactive (list (mh-read-seq "Narrow to" t))) - (with-mh-folder-updating (t) - (cond ((mh-seq-to-msgs sequence) - (mh-remove-all-notation) - (let ((eob (point-max)) - (msg-at-cursor (mh-get-msg-num nil))) - (push mh-thread-scan-line-map mh-thread-scan-line-map-stack) - (setq mh-thread-scan-line-map (make-hash-table :test #'eql)) - (mh-copy-seq-to-eob sequence) - (push (buffer-substring-no-properties (point-min) eob) - mh-folder-view-stack) - (delete-region (point-min) eob) - (mh-notate-deleted-and-refiled) - (mh-notate-cur) - (when msg-at-cursor (mh-goto-msg msg-at-cursor t t)) - (setq mh-non-seq-mode-line-annotation mh-mode-line-annotation) - (setq mh-mode-line-annotation (symbol-name sequence)) - (mh-make-folder-mode-line) - (mh-recenter nil) - (when (and (boundp 'tool-bar-mode) tool-bar-mode) - (setq-local tool-bar-map - mh-folder-seq-tool-bar-map) - (when (buffer-live-p (get-buffer mh-show-buffer)) - (with-current-buffer mh-show-buffer - (setq-local 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-narrow-to-tick () - "Limit to ticked messages. - -What this command does is show only those messages that are in -the \"tick\" sequence (which you can customize via the -`mh-tick-seq' option) in the MH-Folder buffer. In addition, it -limits further MH-E searches to just those messages. When you -want to widen the view to all your messages again, use -\\[mh-widen]." - (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 %s sequence" mh-tick-seq)) - (t (mh-narrow-to-seq mh-tick-seq)))) - -;;;###mh-autoload -(defun mh-put-msg-in-seq (range sequence) - "Add RANGE to SEQUENCE\\. - -Give this command a RANGE and you can add all the messages in a -sequence to another sequence (for example, -\"\\[universal-argument] \\[mh-put-msg-in-seq] SourceSequence RET -DestSequence RET\"). Check the documentation of -`mh-interactive-range' to see how RANGE is read in interactive -use." - (interactive (list (mh-interactive-range "Add messages from") - (mh-read-seq-default "Add to" nil))) - (unless (mh-valid-seq-p sequence) - (error "Can't put message in invalid sequence %s" sequence)) - (let* ((internal-seq-flag (mh-internal-seq sequence)) - (original-msgs (mh-seq-msgs (mh-find-seq sequence))) - (folders (list mh-current-folder)) - (msg-list (mh-range-to-msg-list range))) - (mh-add-msgs-to-seq msg-list sequence nil t) - (mh-iterate-on-range m range - (unless (memq m original-msgs) - (mh-add-sequence-notation m internal-seq-flag))) - (if (not internal-seq-flag) - (setq mh-last-seq-used sequence)) - (when mh-index-data - (setq folders - (append folders (mh-index-add-to-sequence sequence msg-list)))) - (when (and (eq sequence mh-unseen-seq) (mh-speed-flists-active-p)) - (apply #'mh-speed-flists t folders)))) - -;;;###mh-autoload -(defun mh-toggle-tick (range) - "Toggle tick mark of RANGE. - -This command adds messages to the \"tick\" sequence (which you can customize -via the option `mh-tick-seq'). This sequence can be viewed later with the -\\[mh-index-ticked-messages] command. - -Check the documentation of `mh-interactive-range' to see how RANGE is read in -interactive use." - (interactive (list (mh-interactive-range "Tick"))) - (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)) - (ticked ()) - (unticked ())) - (mh-iterate-on-range msg range - (cond ((member msg tick-seq-msgs) - (push msg unticked) - (setcdr tick-seq (delq msg (cdr tick-seq))) - (when (null (cdr tick-seq)) (setq mh-last-seq-used nil)) - (mh-remove-sequence-notation msg (mh-colors-in-use-p))) - (t - (push msg ticked) - (setq mh-last-seq-used mh-tick-seq) - (let ((mh-seq-list (cons `(,mh-tick-seq ,msg) mh-seq-list))) - (mh-add-sequence-notation msg (mh-colors-in-use-p)))))) - (mh-add-msgs-to-seq ticked mh-tick-seq nil t) - (mh-undefine-sequence mh-tick-seq unticked) - (when mh-index-data - (mh-index-add-to-sequence mh-tick-seq ticked) - (mh-index-delete-from-sequence mh-tick-seq unticked)))) - -;;;###mh-autoload -(defun mh-widen (&optional all-flag) - "Remove last restriction. - -Each limit or sequence restriction can be undone in turn with -this command. Give this command a prefix argument ALL-FLAG to -remove all limits and sequence restrictions." - (interactive "P") - (let ((msg (mh-get-msg-num nil))) - (when mh-folder-view-stack - (cond (all-flag - (while (cdr mh-view-ops) - (setq mh-view-ops (cdr mh-view-ops))) - (when (eq (car mh-view-ops) 'widen) - (setq mh-view-ops (cdr mh-view-ops)))) - ((mh-valid-view-change-operation-p 'widen) nil) - ((memq 'widen mh-view-ops) - (while (not (eq (car mh-view-ops) 'widen)) - (setq mh-view-ops (cdr mh-view-ops))) - (setq mh-view-ops (cdr mh-view-ops))) - (t (error "Widening is not applicable"))) - ;; If ALL-FLAG is non-nil then rewind stacks - (when all-flag - (while (cdr mh-thread-scan-line-map-stack) - (setq mh-thread-scan-line-map-stack - (cdr mh-thread-scan-line-map-stack))) - (while (cdr mh-folder-view-stack) - (setq mh-folder-view-stack (cdr mh-folder-view-stack)))) - (setq mh-thread-scan-line-map (pop mh-thread-scan-line-map-stack)) - (with-mh-folder-updating (t) - (delete-region (point-min) (point-max)) - (insert (pop mh-folder-view-stack)) - (mh-remove-all-notation) - (setq mh-mode-line-annotation mh-non-seq-mode-line-annotation) - (mh-make-folder-mode-line)) - (if msg - (mh-goto-msg msg t t)) - (mh-notate-deleted-and-refiled) - (mh-notate-user-sequences) - (mh-notate-cur) - (mh-recenter nil))) - (when (and (null mh-folder-view-stack) (boundp 'tool-bar-mode) tool-bar-mode) - (setq-local tool-bar-map mh-folder-tool-bar-map) - (when (buffer-live-p (get-buffer mh-show-buffer)) - (with-current-buffer mh-show-buffer - (setq-local tool-bar-map mh-show-tool-bar-map))))) - - - -;;; Support Routines - -(defvar mh-sequence-history ()) - -;;;###mh-autoload -(defun mh-read-seq-default (prompt not-empty) - "Read and return sequence name with default narrowed or previous sequence. -PROMPT is the prompt to use when reading. If NOT-EMPTY is non-nil -then a non-empty sequence is read." - (mh-read-seq prompt not-empty - (or mh-last-seq-used - (car (mh-seq-containing-msg (mh-get-msg-num nil) nil))))) - -(defun mh-read-seq (prompt not-empty &optional default) - "Read and return a sequence name. -Prompt with PROMPT, raise an error if the sequence is empty and -the NOT-EMPTY flag is non-nil, and supply an optional DEFAULT -sequence. A reply of `%' defaults to the first sequence -containing the current message." - (let* ((input (completing-read (format-prompt "%s sequence" default prompt) - (mh-seq-names mh-seq-list) - nil nil nil 'mh-sequence-history)) - (seq (cond ((equal input "%") - (car (mh-seq-containing-msg (mh-get-msg-num t) nil))) - ((equal input "") default) - (t (intern input)))) - (msgs (mh-seq-to-msgs seq))) - (if (and (null msgs) not-empty) - (error "No messages in sequence %s" seq)) - seq)) - -(defun mh-internal-seq (name) - "Return non-nil if NAME is the name of an internal MH-E sequence." - (or (memq name mh-internal-seqs) - (eq name mh-unseen-seq) - (and (mh-colors-in-use-p) mh-tick-seq (eq name mh-tick-seq)) - (eq name mh-previous-seq) - (mh-folder-name-p name))) - -;;;###mh-autoload -(defun mh-valid-seq-p (name) - "Return non-nil if NAME is a valid MH sequence name." - (and (symbolp name) - (string-match "^[a-zA-Z][a-zA-Z0-9]*$" (symbol-name name)))) - -;;;###mh-autoload -(defun mh-find-seq (name) - "Return sequence NAME." - (assoc name mh-seq-list)) - -;;;###mh-autoload -(defun mh-seq-to-msgs (seq) - "Return a list of the messages in SEQ." - (mh-seq-msgs (mh-find-seq seq))) - -(defun mh-seq-containing-msg (msg &optional include-internal-flag) - "Return a list of the sequences containing MSG. -If INCLUDE-INTERNAL-FLAG non-nil, include MH-E internal sequences -in list." - (let ((l mh-seq-list) - (seqs ())) - (while l - (and (memq msg (mh-seq-msgs (car l))) - (or include-internal-flag - (not (mh-internal-seq (mh-seq-name (car l))))) - (setq seqs (cons (mh-seq-name (car l)) seqs))) - (setq l (cdr l))) - seqs)) - -;;;###mh-autoload -(defun mh-define-sequence (seq msgs) - "Define the SEQ to contain the list of MSGS. -Do not mark pseudo-sequences or empty sequences. -Signals an error if SEQ is an invalid name." - (if (and msgs - (mh-valid-seq-p seq) - (not (mh-folder-name-p seq))) - (save-excursion - (mh-exec-cmd-error nil "mark" mh-current-folder "-add" "-zero" - "-sequence" (symbol-name seq) - (mh-coalesce-msg-list msgs))))) - -;;;###mh-autoload -(defun mh-undefine-sequence (seq msgs) - "Remove from the SEQ the list of MSGS." - (when (and (mh-valid-seq-p seq) msgs) - (apply #'mh-exec-cmd "mark" mh-current-folder "-delete" - "-sequence" (symbol-name seq) (mh-coalesce-msg-list msgs)))) - -;;;###mh-autoload -(defun mh-add-msgs-to-seq (msgs seq &optional internal-flag dont-annotate-flag) - "Add MSGS to SEQ. - -Remove duplicates and keep sequence sorted. If optional -INTERNAL-FLAG is non-nil, do not mark the message in the scan -listing or inform MH of the addition. - -If DONT-ANNOTATE-FLAG is non-nil then the annotations in the -folder buffer are not updated." - (let ((entry (mh-find-seq seq)) - (internal-seq-flag (mh-internal-seq seq))) - (if (and msgs (atom msgs)) (setq msgs (list msgs))) - (if (null entry) - (setq mh-seq-list - (cons (mh-make-seq seq (mh-canonicalize-sequence msgs)) - mh-seq-list)) - (if msgs (setcdr entry (mh-canonicalize-sequence - (append msgs (mh-seq-msgs entry)))))) - (unless internal-flag - (mh-add-to-sequence seq msgs) - (when (not dont-annotate-flag) - (mh-iterate-on-range msg msgs - (unless (memq msg (cdr entry)) - (mh-add-sequence-notation msg internal-seq-flag))))))) - -(defun mh-add-to-sequence (seq msgs) - "The sequence SEQ is augmented with the messages in MSGS." - ;; Add to a SEQUENCE each message the list of MSGS. - (if (and (mh-valid-seq-p seq) (not (mh-folder-name-p seq))) - (if msgs - (apply #'mh-exec-cmd "mark" mh-current-folder "-add" - "-sequence" (symbol-name seq) - (mh-coalesce-msg-list msgs))))) - -(defun mh-canonicalize-sequence (msgs) - "Sort MSGS in decreasing order and remove duplicates." - (let* ((sorted-msgs (sort (copy-sequence msgs) #'>)) - (head sorted-msgs)) - (while (cdr head) - (if (= (car head) (cadr head)) - (setcdr head (cddr head)) - (setq head (cdr head)))) - sorted-msgs)) - -(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-delete-seq-locally (seq) - "Remove MH-E's record of SEQ." - (let ((entry (mh-find-seq seq))) - (setq mh-seq-list (delq entry mh-seq-list)))) - -(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 - ;; the buffer, so we will write something which works only at the end of - ;; the buffer. If we ever need to insert sequences in the middle of the - ;; buffer, this will need to be fixed. - (save-excursion - (let* ((msgs (mh-seq-to-msgs seq)) - (coalesced-msgs (mh-coalesce-msg-list msgs))) - (goto-char (point-max)) - (save-restriction - (narrow-to-region (point) (point)) - (mh-regenerate-headers coalesced-msgs t) - (cond ((memq 'unthread mh-view-ops) - ;; Populate restricted scan-line map - (mh-remove-all-notation) - (mh-iterate-on-range msg (cons (point-min) (point-max)) - (setf (gethash msg mh-thread-scan-line-map) - (mh-thread-parse-scan-line))) - ;; Remove scan lines and read results from pre-computed tree - (delete-region (point-min) (point-max)) - (mh-thread-print-scan-lines - (mh-thread-generate mh-current-folder ())) - (mh-notate-user-sequences)) - (mh-index-data - (mh-index-insert-folder-headers))))))) - -;;;###mh-autoload -(defun mh-valid-view-change-operation-p (op) - "Check if the view change operation can be performed. -OP is one of `widen' and `unthread'." - (cond ((eq (car mh-view-ops) op) - (pop mh-view-ops)) - (t nil))) - - - -;;; Ranges - -(defvar mh-range-seq-names) -(defvar mh-range-history ()) -(defvar mh-range-completion-map (copy-keymap minibuffer-local-completion-map)) -(define-key mh-range-completion-map " " #'self-insert-command) - -;;;###mh-autoload -(defun mh-interactive-range (range-prompt &optional default) - "Return interactive specification for message, sequence, range or region. -By convention, the name of this argument is RANGE. - -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 is provided, then prompt for message range -with RANGE-PROMPT. A list of messages in that range is returned. - -If a MH range is given, say something like last:20, then a list -containing the messages in that range is returned. - -If DEFAULT non-nil then it is returned. - -Otherwise, the message number at point is returned. - -This function is usually used with `mh-iterate-on-range' in order to -provide a uniform interface to MH-E functions." - (cond ((and transient-mark-mode mark-active) (cons (region-beginning) (region-end))) - (current-prefix-arg (mh-read-range range-prompt nil nil t t)) - (default default) - (t (mh-get-msg-num t)))) - -;;;###mh-autoload -(defun mh-read-range (prompt &optional folder default - expand-flag ask-flag number-as-range-flag) - "Read a message range with PROMPT. - -If FOLDER is non-nil then a range is read from that folder, otherwise -use `mh-current-folder'. - -If DEFAULT is a string then use that as default range to return. If -DEFAULT is nil then ask user with default answer a range based on the -sequences that seem relevant. Finally if DEFAULT is t, try to avoid -prompting the user. Unseen messages, if present, are returned. If the -folder has fewer than `mh-large-folder' messages then \"all\" messages -are returned. Finally as a last resort prompt the user. - -If EXPAND-FLAG is non-nil then a list of message numbers corresponding -to the input is returned. If this list is empty then an error is -raised. If EXPAND-FLAG is nil just return the input string. In this -case we don't check if the range is empty. - -If ASK-FLAG is non-nil, then the user is always queried for a range of -messages. If ASK-FLAG is nil, then the function checks if the unseen -sequence is non-empty. If that is the case, `mh-unseen-seq', or the -list of messages in it depending on the value of EXPAND, is returned. -Otherwise if the folder has fewer than `mh-large-folder' messages then -the list of messages corresponding to \"all\" is returned. If neither -of the above holds then as a last resort the user is queried for a -range of messages. - -If NUMBER-AS-RANGE-FLAG is non-nil, then if a number, N is read as -input, it is interpreted as the range \"last:N\". - -This function replaces the existing function `mh-read-msg-range'. -Calls to: - - (mh-read-msg-range folder flag) - -should be replaced with: - - (mh-read-range \"Suitable prompt\" folder t nil flag - mh-interpret-number-as-range-flag)" - (setq default (or default mh-last-seq-used - (car (mh-seq-containing-msg (mh-get-msg-num nil) t))) - prompt (format "%s range" prompt)) - (let* ((folder (or folder mh-current-folder)) - (guess (eq default t)) - (counts (and guess (mh-folder-size folder))) - (unseen (and counts (> (cadr counts) 0))) - (large (and counts mh-large-folder (> (car counts) mh-large-folder))) - (default (cond ((and guess large) (format "last:%s" mh-large-folder)) - ((and guess (not large)) "all") - ((stringp default) default) - ((symbolp default) (symbol-name default)))) - (prompt (cond ((and guess large default) - (format-prompt "%s (folder has %s messages)" - default prompt (car counts))) - (default - (format-prompt prompt default)))) - (minibuffer-local-completion-map mh-range-completion-map) - (seq-list (if (eq folder mh-current-folder) - mh-seq-list - (mh-read-folder-sequences folder nil))) - (mh-range-seq-names - (append '(("first") ("last") ("all") ("prev") ("next")) - (mh-seq-names seq-list))) - (input (cond ((and (not ask-flag) unseen) (symbol-name mh-unseen-seq)) - ((and (not ask-flag) (not large)) "all") - (t (completing-read prompt - 'mh-range-completion-function nil nil - nil 'mh-range-history default)))) - msg-list) - (when (and number-as-range-flag - (string-match "^[ \t]*\\([0-9]+\\)[ \t]*$" input)) - (setq input (concat "last:" (match-string 1 input)))) - (cond ((not expand-flag) input) - ((assoc (intern input) seq-list) - (cdr (assoc (intern input) seq-list))) - ((setq msg-list (mh-translate-range folder input)) msg-list) - (t (error "No messages in range %s" input))))) - -;;;###mh-autoload -(defun mh-range-to-msg-list (range) - "Return a list of messages for RANGE. - -Check the documentation of `mh-interactive-range' to see how -RANGE is read in interactive use." - (let (msg-list) - (mh-iterate-on-range msg range - (push msg msg-list)) - (nreverse msg-list))) - -;;;###mh-autoload -(defun mh-translate-range (folder expr) - "In FOLDER, translate the string EXPR to a list of messages numbers." - (save-excursion - (let ((strings (delete "" (split-string expr "[ \t\n]"))) - (result ())) - (ignore-errors - (apply #'mh-exec-cmd-quiet nil "mhpath" folder strings) - (set-buffer mh-temp-buffer) - (goto-char (point-min)) - (while (re-search-forward "/\\([0-9]*\\)$" nil t) - (push (string-to-number (match-string 1)) result)) - (nreverse result))))) - -(defun mh-range-completion-function (string predicate flag) - "Programmable completion of message ranges. -STRING is the user input that is to be completed. PREDICATE if non-nil is a -function used to filter the possible choices and FLAG determines whether the -completion is over." - (let* ((candidates mh-range-seq-names) - (last-char (and (not (equal string "")) - (aref string (1- (length string))))) - (last-word (cond ((null last-char) "") - ((memq last-char '(? ?- ?:)) "") - (t (car (last (split-string string "[ -:]+")))))) - (prefix (substring string 0 (- (length string) (length last-word))))) - (cond ((eq flag nil) - (let ((res (try-completion last-word candidates predicate))) - (cond ((null res) nil) - ((eq res t) t) - (t (concat prefix res))))) - ((eq flag t) - (all-completions last-word candidates predicate)) - ((eq flag 'lambda) - (cl-loop for x in candidates - when (equal x last-word) return t - finally return nil))))) - -(defun mh-seq-names (seq-list) - "Return an alist containing the names of the SEQ-LIST." - (mapcar (lambda (entry) (list (symbol-name (mh-seq-name entry)))) - seq-list)) - -(defun mh-folder-size (folder) - "Find size of FOLDER." - (if mh-flists-present-flag - (mh-folder-size-flist folder) - (mh-folder-size-folder folder))) - -(defun mh-folder-size-flist (folder) - "Find size of FOLDER using \"flist\"." - (with-temp-buffer - (call-process (expand-file-name "flist" mh-progs) nil t nil "-showzero" - "-norecurse" folder "-sequence" (symbol-name mh-unseen-seq)) - (goto-char (point-min)) - (cl-multiple-value-bind (folder unseen total) - (cl-values-list - (mh-parse-flist-output-line - (buffer-substring (point) (line-end-position)))) - (list total unseen folder)))) - -(defun mh-folder-size-folder (folder) - "Find size of FOLDER using \"folder\"." - (with-temp-buffer - (let ((u (length (cdr (assoc mh-unseen-seq - (mh-read-folder-sequences folder nil)))))) - (call-process (expand-file-name "folder" mh-progs) nil t nil - "-norecurse" folder) - (goto-char (point-min)) - (if (re-search-forward " has \\([0-9]+\\) " nil t) - (list (string-to-number (match-string 1)) u folder) - (list 0 u folder))))) - -;;;###mh-autoload -(defun mh-parse-flist-output-line (line &optional current-folder) - "Parse LINE to generate folder name, unseen messages and total messages. -If CURRENT-FOLDER is non-nil then it contains the current folder -name and it is used to avoid problems in corner cases involving -folders whose names end with a `+' character." - (with-temp-buffer - (insert line) - (goto-char (point-max)) - (let (folder unseen total p) - (when (search-backward " out of " (point-min) t) - (setq total (string-to-number - (buffer-substring-no-properties - (match-end 0) (line-end-position)))) - (when (search-backward " in sequence " (point-min) t) - (setq p (point)) - (when (search-backward " has " (point-min) t) - (setq unseen (string-to-number (buffer-substring-no-properties - (match-end 0) p))) - (while (eq (char-after) ? ) - (backward-char)) - (setq folder (buffer-substring-no-properties - (point-min) (1+ (point)))) - (when (and (equal (aref folder (1- (length folder))) ?+) - (equal current-folder folder)) - (setq folder (substring folder 0 (1- (length folder))))) - (list (format "+%s" folder) unseen total))))))) - -;;;###mh-autoload -(defun mh-read-folder-sequences (folder save-refiles) - "Read and return the predefined sequences for a FOLDER. -If SAVE-REFILES is non-nil, then keep the sequences -that note messages to be refiled." - (let ((seqs ())) - (cond (save-refiles - (mapc (lambda (seq) ; Save the refiling sequences - (if (mh-folder-name-p (mh-seq-name seq)) - (setq seqs (cons seq seqs)))) - mh-seq-list))) - (save-excursion - (if (eq 0 (mh-exec-cmd-quiet nil "mark" folder "-list")) - (progn - ;; look for name in line of form "cur: 4" or "myseq (private): 23" - (while (re-search-forward "^[^: ]+" nil t) - (setq seqs (cons (mh-make-seq (intern (buffer-substring - (match-beginning 0) - (match-end 0))) - (mh-read-msg-list)) - seqs))) - (delete-region (point-min) (point))))) ; avoid race with - ; mh-process-daemon - seqs)) - -(defun mh-read-msg-list () - "Return a list of message numbers from point to the end of the line. -Expands ranges into set of individual numbers." - (let ((msgs ()) - (end-of-line (line-end-position)) - num) - (while (re-search-forward "[0-9]+" end-of-line t) - (setq num (string-to-number (buffer-substring (match-beginning 0) - (match-end 0)))) - (cond ((looking-at "-") ; Message range - (forward-char 1) - (re-search-forward "[0-9]+" end-of-line t) - (let ((num2 (string-to-number - (buffer-substring (match-beginning 0) - (match-end 0))))) - (if (< num2 num) - (error "Bad message range: %d-%d" num num2)) - (while (<= num num2) - (setq msgs (cons num msgs)) - (setq num (1+ num))))) - ((not (zerop num)) ;"pick" outputs "0" to mean no match - (setq msgs (cons num msgs))))) - msgs)) - - - -;;; Notation - -;;;###mh-autoload -(defun mh-notate (msg notation offset) - "Mark MSG with the character NOTATION at position OFFSET. -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) - (let* ((change-stack-flag - (and (equal offset - (+ mh-cmd-note mh-scan-field-destination-offset)) - (not (eq notation mh-note-seq)))) - (msg (and change-stack-flag (or msg (mh-get-msg-num nil)))) - (stack (and msg (gethash msg mh-sequence-notation-history))) - (notation (or notation (char-after)))) - (if stack - ;; The presence of the stack tells us that we don't need to - ;; notate the message, since the notation would be replaced - ;; by a sequence notation. So we will just put the notation - ;; at the bottom of the stack. If the sequence is deleted, - ;; the correct notation will be shown. - (setf (gethash msg mh-sequence-notation-history) - (reverse (cons notation (cdr (reverse stack))))) - ;; Since we don't have any sequence notations in the way, just - ;; notate the scan line. - (delete-char 1) - (insert notation)) - (when change-stack-flag - (mh-thread-update-scan-line-map msg notation offset))))))) - -;;;###mh-autoload -(defun mh-notate-cur () - "Mark the MH sequence cur. -In addition to notating the current message with `mh-note-cur' -the function 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)) - (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)))) - -;;;###mh-autoload -(defun mh-remove-cur-notation () - "Remove old cur notation." - (let ((cur-msg (car (mh-seq-to-msgs 'cur)))) - (save-excursion - (when (and cur-msg - (mh-goto-msg cur-msg t t) - (looking-at mh-scan-cur-msg-number-regexp)) - (mh-notate nil ? mh-cmd-note) - (setq overlay-arrow-position nil))))) - -;; FIXME? We may want to clear all notations and add one for current-message -;; and process user sequences. -;;;###mh-autoload -(defun mh-notate-deleted-and-refiled () - "Notate messages marked for deletion or refiling. -Messages to be deleted are given by `mh-delete-list' while -messages to be refiled are present in `mh-refile-list'." - (let ((refiled-hash (make-hash-table)) - (deleted-hash (make-hash-table))) - (dolist (msg mh-delete-list) - (setf (gethash msg deleted-hash) t)) - (dolist (dest-msg-list mh-refile-list) - (dolist (msg (cdr dest-msg-list)) - (setf (gethash msg refiled-hash) t))) - (mh-iterate-on-messages-in-region msg (point-min) (point-max) - (cond ((gethash msg refiled-hash) - (mh-notate nil mh-note-refiled mh-cmd-note)) - ((gethash msg deleted-hash) - (mh-notate nil mh-note-deleted mh-cmd-note)))))) - -;;;###mh-autoload -(defun mh-notate-user-sequences (&optional range) - "Mark user-defined sequences in RANGE. - -Check the documentation of `mh-interactive-range' to see how -RANGE is read in interactive use; if nil all messages are -notated." - (unless range - (setq range (cons (point-min) (point-max)))) - (let ((seqs mh-seq-list) - (msg-hash (make-hash-table))) - (dolist (seq seqs) - (dolist (msg (mh-seq-msgs seq)) - (push (car seq) (gethash msg msg-hash)))) - (mh-iterate-on-range msg range - (cl-loop for seq in (gethash msg msg-hash) - do (mh-add-sequence-notation msg (mh-internal-seq seq)))))) - -(defun mh-add-sequence-notation (msg internal-seq-flag) - "Add sequence notation to the MSG on the current line. -If INTERNAL-SEQ-FLAG is non-nil, then refontify the scan line if -font-lock is turned on." - (with-mh-folder-updating (t) - (save-excursion - (beginning-of-line) - (if internal-seq-flag - (progn - ;; Change the buffer so that if transient-mark-mode is active - ;; and there is an active region it will get deactivated as in - ;; the case of user sequences. - (mh-notate nil nil mh-cmd-note) - (when font-lock-mode - (font-lock-fontify-region (point) (line-end-position)))) - (forward-char (+ mh-cmd-note mh-scan-field-destination-offset)) - (let ((stack (gethash msg mh-sequence-notation-history))) - (setf (gethash msg mh-sequence-notation-history) - (cons (char-after) stack))) - (mh-notate nil mh-note-seq - (+ mh-cmd-note mh-scan-field-destination-offset)))))) - -(defun mh-remove-sequence-notation (msg internal-seq-flag &optional all) - "Remove sequence notation from the MSG on the current line. -If INTERNAL-SEQ-FLAG is non-nil, then `font-lock' was used to -highlight the sequence. In that case, no notation needs to be removed. -Otherwise the effect of inserting `mh-note-seq' needs to be reversed. -If ALL is non-nil, then all sequence marks on the scan line are -removed." - (with-mh-folder-updating (t) - ;; This takes care of internal sequences... - (mh-notate nil nil mh-cmd-note) - (unless internal-seq-flag - ;; ... and this takes care of user sequences. - (let ((stack (gethash msg mh-sequence-notation-history))) - (while (and all (cdr stack)) - (setq stack (cdr stack))) - (when stack - (save-excursion - (beginning-of-line) - (forward-char (+ mh-cmd-note mh-scan-field-destination-offset)) - (delete-char 1) - (insert (car stack)))) - (setf (gethash msg mh-sequence-notation-history) (cdr stack)))))) - -;;;###mh-autoload -(defun mh-remove-all-notation () - "Remove all notations on all scan lines that MH-E introduces." - (save-excursion - (setq overlay-arrow-position nil) - (goto-char (point-min)) - (mh-iterate-on-range msg (cons (point-min) (point-max)) - (mh-notate nil ? mh-cmd-note) - (mh-remove-sequence-notation msg nil t)) - (clrhash mh-sequence-notation-history))) - - - -;; XXX Unused, delete, or create bind key? -(defun mh-rename-seq (sequence new-name) - "Rename SEQUENCE to have NEW-NAME." - (interactive (list (mh-read-seq "Old" t) - (intern (read-string "New sequence name: ")))) - (let ((old-seq (mh-find-seq sequence))) - (or old-seq - (error "Sequence %s does not exist" sequence)) - ;; Create new sequence first, since it might raise an error. - (mh-define-sequence new-name (mh-seq-msgs old-seq)) - (mh-undefine-sequence sequence (mh-seq-msgs old-seq)) - (rplaca old-seq new-name))) - -(provide 'mh-seq) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-seq.el ends here diff --git a/lisp/mh-e/mh-show.el b/lisp/mh-e/mh-show.el deleted file mode 100644 index 96b148ab49c..00000000000 --- a/lisp/mh-e/mh-show.el +++ /dev/null @@ -1,901 +0,0 @@ -;;; mh-show.el --- MH-Show mode -*- lexical-binding: t; -*- - -;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation, -;; Inc. - -;; Author: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Mode for showing messages. - -;;; Code: - -(require 'mh-e) -(require 'mh-mime) -(require 'mh-scan) - -;; Dynamically-created function not found in mh-loaddefs.el. -(autoload 'mh-tool-bar-init "mh-tool-bar") - -(require 'font-lock) -(require 'gnus-cite) -(require 'gnus-util) -(require 'goto-addr) - -(autoload 'mh-make-buffer-data "mh-mime") ;can't be automatically generated - - - -;;; MH-Folder Commands - -(defvar mh-showing-with-headers nil - "If non-nil, MH-Show buffer contains message with all header fields. -If nil, MH-Show buffer contains message processed normally.") - -;;;###mh-autoload -(defun mh-show (&optional message redisplay-flag) - "Display message\\. - -If the message under the cursor is already displayed, this command -scrolls to the beginning of the message. MH-E normally hides a lot of -the superfluous header fields that mailers add to a message, but if -you wish to see all of them, use the command \\[mh-header-display]. - -Two hooks can be used to control how messages are displayed. The -first hook, `mh-show-mode-hook', is called early on in the -process of the message display. It is usually used to perform -some action on the message's buffer. The second hook, -`mh-show-hook', is the last thing called after messages are -displayed. It's used to affect the behavior of MH-E in general or -when `mh-show-mode-hook' is too early. - -From a program, optional argument MESSAGE can be used to display an -alternative message. The optional argument REDISPLAY-FLAG forces the -redisplay of the message even if the show buffer was already -displaying the correct message. - -See the \"mh-show\" customization group for a litany of options that -control what displayed messages look like." - (interactive (list nil t)) - (when (or redisplay-flag - (and mh-showing-with-headers - (or mh-mhl-format-file mh-clean-message-header-flag))) - (mh-invalidate-show-buffer)) - (mh-show-msg message)) - -;;;###mh-autoload -(defun mh-header-display () - "Display message with all header fields\\. - -Use the command \\[mh-show] to show the message normally again." - (interactive) - (and (not mh-showing-with-headers) - (or mh-mhl-format-file mh-clean-message-header-flag) - (mh-invalidate-show-buffer)) - (let ((mh-decode-mime-flag nil) - (mh-mhl-format-file nil) - (mh-clean-message-header-flag nil)) - (mh-show-msg nil) - (mh-in-show-buffer (mh-show-buffer) - (goto-char (point-min)) - (mh-recenter 0)) - (setq mh-showing-with-headers t))) - -;;;###mh-autoload -(defun mh-show-preferred-alternative () - "Display message with the default preferred alternative. -This is as if `mm-discouraged-alternatives' is set to nil. - -Use the command \\[mh-show] to show the message normally again." - (interactive) - (let - ((mm-discouraged-alternatives)) - (mh-show nil t))) - - - -;;; Support Routines for MH-Folder Commands - -;;;###mh-autoload -(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." - (if mh-showing-mode (mh-show msg))) - -(defun mh-show-msg (msg) - "Show MSG. - -The hook `mh-show-hook' is called after the message has been -displayed." - (if (not msg) - (setq msg (mh-get-msg-num t))) - (mh-showing-mode t) - (setq mh-page-to-next-msg-flag nil) - (let ((folder mh-current-folder) - (folders (list mh-current-folder)) - (clean-message-header mh-clean-message-header-flag) - (show-window (get-buffer-window mh-show-buffer)) - (display-mime-buttons-flag mh-display-buttons-for-inline-parts-flag)) - (if (not (eq (next-window (minibuffer-window)) (selected-window))) - (delete-other-windows)) ; force ourselves to the top window - (mh-in-show-buffer (mh-show-buffer) - (setq mh-display-buttons-for-inline-parts-flag display-mime-buttons-flag) - (if (and show-window - (equal (mh-msg-filename msg folder) buffer-file-name)) - (progn ;just back up to start - (goto-char (point-min)) - (if (not clean-message-header) - (mh-start-of-uncleaned-message))) - (mh-display-msg msg folder))) - (unless (window-full-height-p) ; not vertically split - (shrink-window (- (window-height) (or mh-summary-height - (mh-summary-height))))) - (mh-recenter nil) - ;; The following line is a nop which forces update of the scan line so - ;; that font-lock will update it (if needed)... - (mh-notate nil nil mh-cmd-note) - (if (not (memq msg mh-seen-list)) - (setq mh-seen-list (cons msg mh-seen-list))) - (when mh-update-sequences-after-mh-show-flag - (mh-update-sequences) - (when mh-index-data - (setq folders - (append (mh-index-delete-from-sequence mh-unseen-seq (list msg)) - folders))) - (when (mh-speed-flists-active-p) - (apply #'mh-speed-flists t folders))) - (run-hooks 'mh-show-hook))) - -;;;###mh-autoload -(defun mh-start-of-uncleaned-message () - "Position uninteresting headers off the top of the window." - (let ((case-fold-search t)) - (re-search-forward - "^To:\\|^Cc:\\|^From:\\|^Subject:\\|^Date:" nil t) - (beginning-of-line) - (mh-recenter 0))) - -(defvar mh-show-buffer-mode-line-buffer-id " {show-%s} %d" - "Format string to produce `mode-line-buffer-identification' for show buffers. - -First argument is folder name. Second is message number.") - -;;;###mh-autoload -(defun mh-display-msg (msg-num folder-name) - "Display MSG-NUM of FOLDER-NAME. -Sets the current buffer to the show buffer." - (let ((folder (mh-msg-folder folder-name))) - (set-buffer folder) - ;; When Gnus uses external displayers it has to keep handles longer. So - ;; we will delete these handles when mh-quit is called on the folder. It - ;; would be nicer if there are weak pointers in Emacs Lisp, then we could - ;; get the garbage collector to do this for us. - (unless (mh-buffer-data) - (setf (mh-buffer-data) (mh-make-buffer-data))) - ;; Bind variables in folder buffer in case they are local - (let ((formfile mh-mhl-format-file) - (clean-message-header mh-clean-message-header-flag) - (invisible-headers mh-invisible-header-fields-compiled) - ;; (visible-headers nil) - (msg-filename (mh-msg-filename msg-num folder-name)) - (show-buffer mh-show-buffer) - (mm-inline-media-tests mh-mm-inline-media-tests)) - (if (not (file-exists-p msg-filename)) - (error "Message %d does not exist" msg-num)) - (if (and (> mh-show-maximum-size 0) - (> (elt (file-attributes msg-filename) 7) - mh-show-maximum-size) - (not (y-or-n-p - (format - "Message %d (%d bytes) exceeds %d bytes. Display it? " - msg-num (elt (file-attributes msg-filename) 7) - mh-show-maximum-size)))) - (error "Message %d not displayed" msg-num)) - (set-buffer show-buffer) - (cond ((not (equal msg-filename buffer-file-name)) - (mh-unvisit-file) - (setq buffer-read-only nil) - ;; Cleanup old mime handles - (mh-mime-cleanup) - (erase-buffer) - ;; Changing contents, so this hook needs to be reinitialized. - ;; pgp.el uses this. - (kill-local-variable 'write-contents-functions) - (font-lock-mode -1) - (mh-show-mode) - (if formfile - (mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear" - (if (stringp formfile) - (list "-form" formfile)) - msg-filename) - (insert-file-contents-literally msg-filename)) - ;; Use mm to display buffer - (when (and mh-decode-mime-flag (not formfile)) - (mh-add-missing-mime-version-header) - (setf (mh-buffer-data) (mh-make-buffer-data)) - (mh-mime-display)) - (mh-show-unquote-From) - (mh-show-xface) - (mh-show-addr) - ;; Header cleanup - (goto-char (point-min)) - (cond (clean-message-header - (mh-clean-msg-header (point-min) - invisible-headers - nil) ;; visible-headers - (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)) - (set-buffer-auto-saved) - ;; the parts of set-visited-file-name we want to do (no locking) - (setq buffer-file-name msg-filename) - (setq buffer-backed-up nil) - (auto-save-mode 1) - (set-mark nil) - (when (and mh-decode-mime-flag (not formfile)) - (mh-display-smileys) - (mh-display-emphasis)) - (set-buffer-modified-p nil) - (setq buffer-read-only t) - (setq mh-show-folder-buffer folder) - (setq mode-line-buffer-identification - (list (format mh-show-buffer-mode-line-buffer-id - folder-name msg-num))) - (mh-logo-display) - (set-buffer folder) - (setq mh-showing-with-headers nil)))))) - -(defun mh-msg-folder (folder-name) - "Return the name of the buffer for FOLDER-NAME." - folder-name) - -;;;###mh-autoload -(defun mh-clean-msg-header (start invisible-headers visible-headers) - "Flush extraneous lines in message header. - -Header is cleaned from START to the end of the message header. -INVISIBLE-HEADERS contains a regular expression specifying lines -to delete from the header. VISIBLE-HEADERS contains a regular -expression specifying the lines to display. INVISIBLE-HEADERS is -ignored if VISIBLE-HEADERS is non-nil." - ;; XXX Note that MH-E no longer supports the `mh-visible-headers' - ;; variable, so this function could be trimmed of this feature too." - (let ((case-fold-search t) - (buffer-read-only nil)) - (save-restriction - (goto-char start) - (if (search-forward "\n\n" nil 'move) - (backward-char 1)) - (narrow-to-region start (point)) - (goto-char (point-min)) - (if visible-headers - (while (< (point) (point-max)) - (cond ((looking-at visible-headers) - (forward-line 1) - (while (looking-at "[ \t]") (forward-line 1))) - (t - (mh-delete-line 1) - (while (looking-at "[ \t]") - (mh-delete-line 1))))) - (while (re-search-forward invisible-headers nil t) - (beginning-of-line) - (mh-delete-line 1) - (while (looking-at "[ \t]") - (mh-delete-line 1))))) - (let ((mh-compose-skipped-header-fields ())) - (mh-letter-hide-all-skipped-fields)) - (unlock-buffer))) - -;;;###mh-autoload -(defun mh-invalidate-show-buffer () - "Invalidate the show buffer so we must update it to use it." - (if (get-buffer mh-show-buffer) - (with-current-buffer mh-show-buffer - (mh-unvisit-file)))) - -(defun mh-unvisit-file () - "Separate current buffer from the message file it was visiting." - (or (not (buffer-modified-p)) - (null buffer-file-name) ;we've been here before - (yes-or-no-p (format "Message %s modified; discard changes? " - (file-name-nondirectory buffer-file-name))) - (error "Changes preserved")) - (clear-visited-file-modtime) - (unlock-buffer) - (setq buffer-file-name nil)) - -(defun mh-summary-height () - "Return ideal value for the variable `mh-summary-height'. -The current frame height is taken into consideration." - (or (and (> (frame-height) 24) - (min 10 (/ (frame-height) 6))) - 4)) - - - -;; Infrastructure to generate show-buffer functions from folder functions. -;; Should we be restoring the mark in the folder buffer after the -;; operation has been carried out? -(defmacro mh-defun-show-buffer (function original-function - &optional dont-return) - "Define FUNCTION to run ORIGINAL-FUNCTION in folder buffer. -If the buffer we start in is still visible and DONT-RETURN is nil -then switch to it after that." - `(defun ,function () - ,(format "Calls %s from the message's folder.\n%s\nSee `%s' for more info.\n" - original-function - (if dont-return "" - "When function completes, returns to the show buffer if it is -still visible.\n") - original-function) - (interactive) - (when (buffer-live-p (get-buffer mh-show-folder-buffer)) - (let ((config (current-window-configuration)) - (folder-buffer mh-show-folder-buffer) - (normal-exit nil) - ,@(if dont-return () '((cur-buffer-name (buffer-name))))) - (pop-to-buffer mh-show-folder-buffer nil) - (unless (equal (buffer-name - (window-buffer (frame-first-window (selected-frame)))) - folder-buffer) - (delete-other-windows)) - (mh-goto-cur-msg t) - (deactivate-mark) - (unwind-protect - (prog1 (call-interactively (function ,original-function)) - (setq normal-exit t)) - (deactivate-mark) - (when (eq major-mode 'mh-folder-mode) - (when (fboundp 'hl-line-highlight) - (hl-line-highlight))) - (cond ((not normal-exit) - (set-window-configuration config)) - ,(if dont-return - '(t (setq mh-previous-window-config config)) - '((and (get-buffer cur-buffer-name) - (window-live-p (get-buffer-window - (get-buffer cur-buffer-name)))) - (pop-to-buffer (get-buffer cur-buffer-name) nil))))))))) - -;; Generate interactive functions for the show buffer from the corresponding -;; folder functions. -(mh-defun-show-buffer mh-show-previous-undeleted-msg - mh-previous-undeleted-msg) -(mh-defun-show-buffer mh-show-next-undeleted-msg - mh-next-undeleted-msg) -(mh-defun-show-buffer mh-show-quit mh-quit) -(mh-defun-show-buffer mh-show-delete-msg mh-delete-msg) -(mh-defun-show-buffer mh-show-refile-msg mh-refile-msg) -(mh-defun-show-buffer mh-show-undo mh-undo) -(mh-defun-show-buffer mh-show-execute-commands mh-execute-commands) -(mh-defun-show-buffer mh-show-reply mh-reply t) -(mh-defun-show-buffer mh-show-redistribute mh-redistribute) -(mh-defun-show-buffer mh-show-forward mh-forward t) -(mh-defun-show-buffer mh-show-header-display mh-header-display) -(mh-defun-show-buffer mh-show-refile-or-write-again - mh-refile-or-write-again) -(mh-defun-show-buffer mh-show-show mh-show) -(mh-defun-show-buffer mh-show-show-preferred-alternative mh-show-preferred-alternative) -(mh-defun-show-buffer mh-show-write-message-to-file - mh-write-msg-to-file) -(mh-defun-show-buffer mh-show-extract-rejected-mail - mh-extract-rejected-mail t) -(mh-defun-show-buffer mh-show-delete-msg-no-motion - mh-delete-msg-no-motion) -(mh-defun-show-buffer mh-show-first-msg mh-first-msg) -(mh-defun-show-buffer mh-show-last-msg mh-last-msg) -(mh-defun-show-buffer mh-show-copy-msg mh-copy-msg) -(mh-defun-show-buffer mh-show-edit-again mh-edit-again t) -(mh-defun-show-buffer mh-show-goto-msg mh-goto-msg) -(mh-defun-show-buffer mh-show-inc-folder mh-inc-folder) -(mh-defun-show-buffer mh-show-delete-subject-or-thread - mh-delete-subject-or-thread) -(mh-defun-show-buffer mh-show-delete-subject mh-delete-subject) -(mh-defun-show-buffer mh-show-print-msg mh-print-msg) -(mh-defun-show-buffer mh-show-send mh-send t) -(mh-defun-show-buffer mh-show-toggle-showing mh-toggle-showing t) -(mh-defun-show-buffer mh-show-pipe-msg mh-pipe-msg t) -(mh-defun-show-buffer mh-show-sort-folder mh-sort-folder) -(mh-defun-show-buffer mh-show-visit-folder mh-visit-folder t) -(mh-defun-show-buffer mh-show-rescan-folder mh-rescan-folder) -(mh-defun-show-buffer mh-show-pack-folder mh-pack-folder) -(mh-defun-show-buffer mh-show-kill-folder mh-kill-folder t) -(mh-defun-show-buffer mh-show-list-folders mh-list-folders t) -(mh-defun-show-buffer mh-show-undo-folder mh-undo-folder) -(mh-defun-show-buffer mh-show-delete-msg-from-seq - mh-delete-msg-from-seq) -(mh-defun-show-buffer mh-show-delete-seq mh-delete-seq) -(mh-defun-show-buffer mh-show-list-sequences mh-list-sequences) -(mh-defun-show-buffer mh-show-narrow-to-seq mh-narrow-to-seq) -(mh-defun-show-buffer mh-show-put-msg-in-seq mh-put-msg-in-seq) -(mh-defun-show-buffer mh-show-msg-is-in-seq mh-msg-is-in-seq) -(mh-defun-show-buffer mh-show-widen mh-widen) -(mh-defun-show-buffer mh-show-narrow-to-subject mh-narrow-to-subject) -(mh-defun-show-buffer mh-show-narrow-to-from mh-narrow-to-from) -(mh-defun-show-buffer mh-show-narrow-to-cc mh-narrow-to-cc) -(mh-defun-show-buffer mh-show-narrow-to-range mh-narrow-to-range) -(mh-defun-show-buffer mh-show-narrow-to-to mh-narrow-to-to) -(mh-defun-show-buffer mh-show-store-msg mh-store-msg) -(mh-defun-show-buffer mh-show-page-digest mh-page-digest) -(mh-defun-show-buffer mh-show-page-digest-backwards - mh-page-digest-backwards) -(mh-defun-show-buffer mh-show-burst-digest mh-burst-digest) -(mh-defun-show-buffer mh-show-page-msg mh-page-msg) -(mh-defun-show-buffer mh-show-previous-page mh-previous-page) -(mh-defun-show-buffer mh-show-modify mh-modify t) -(mh-defun-show-buffer mh-show-next-button mh-next-button) -(mh-defun-show-buffer mh-show-prev-button mh-prev-button) -(mh-defun-show-buffer mh-show-toggle-mime-part mh-folder-toggle-mime-part) -(mh-defun-show-buffer mh-show-save-mime-part mh-folder-save-mime-part) -(mh-defun-show-buffer mh-show-inline-mime-part mh-folder-inline-mime-part) -(mh-defun-show-buffer mh-show-toggle-threads mh-toggle-threads) -(mh-defun-show-buffer mh-show-thread-delete mh-thread-delete) -(mh-defun-show-buffer mh-show-thread-refile mh-thread-refile) -(mh-defun-show-buffer mh-show-update-sequences mh-update-sequences) -(mh-defun-show-buffer mh-show-next-unread-msg mh-next-unread-msg) -(mh-defun-show-buffer mh-show-previous-unread-msg mh-previous-unread-msg) -(mh-defun-show-buffer mh-show-thread-ancestor mh-thread-ancestor) -(mh-defun-show-buffer mh-show-thread-next-sibling mh-thread-next-sibling) -(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-allowlist mh-junk-allowlist) -(mh-defun-show-buffer mh-show-junk-whitelist mh-junk-whitelist) -(mh-defun-show-buffer mh-show-junk-blocklist mh-junk-blocklist) -(mh-defun-show-buffer mh-show-index-new-messages mh-index-new-messages) -(mh-defun-show-buffer mh-show-index-ticked-messages mh-index-ticked-messages) -(mh-defun-show-buffer mh-show-index-sequenced-messages - mh-index-sequenced-messages) -(mh-defun-show-buffer mh-show-catchup mh-catchup) -(mh-defun-show-buffer mh-show-ps-print-toggle-color mh-ps-print-toggle-color) -(mh-defun-show-buffer mh-show-ps-print-toggle-faces mh-ps-print-toggle-faces) -(mh-defun-show-buffer mh-show-ps-print-msg-file mh-ps-print-msg-file) -(mh-defun-show-buffer mh-show-ps-print-msg mh-ps-print-msg) -(mh-defun-show-buffer mh-show-toggle-mime-buttons mh-toggle-mime-buttons) -(mh-defun-show-buffer mh-show-display-with-external-viewer - mh-display-with-external-viewer) - - - -;;; Sequence Menu - -(easy-menu-define - mh-show-sequence-menu mh-show-mode-map "Menu for MH-E folder-sequence." - '("Sequence" - ["Add Message to Sequence..." mh-show-put-msg-in-seq t] - ["List Sequences for Message" mh-show-msg-is-in-seq t] - ["Delete Message from Sequence..." mh-show-delete-msg-from-seq t] - ["List Sequences in Folder..." mh-show-list-sequences t] - ["Delete Sequence..." mh-show-delete-seq t] - ["Narrow to Sequence..." mh-show-narrow-to-seq t] - ["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 - (with-current-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])) - -;;; Message Menu - -(easy-menu-define - mh-show-message-menu mh-show-mode-map "Menu for MH-E folder-message." - '("Message" - ["Show Message" mh-show-show t] - ["Show Message with Header" mh-show-header-display t] - ["Show Message with Preferred Alternative" - mh-show-show-preferred-alternative t] - ["Next Message" mh-show-next-undeleted-msg t] - ["Previous Message" mh-show-previous-undeleted-msg t] - ["Go to First Message" mh-show-first-msg t] - ["Go to Last Message" mh-show-last-msg t] - ["Go to Message by Number..." mh-show-goto-msg t] - ["Modify Message" mh-show-modify t] - ["Delete Message" mh-show-delete-msg t] - ["Refile Message" mh-show-refile-msg t] - ["Undo Delete/Refile" mh-show-undo t] - ["Process Delete/Refile" mh-show-execute-commands t] - "--" - ["Compose a New Message" mh-send t] - ["Reply to Message..." mh-show-reply t] - ["Forward Message..." mh-show-forward t] - ["Redistribute Message..." mh-show-redistribute t] - ["Edit Message Again" mh-show-edit-again t] - ["Re-edit a Bounced Message" mh-show-extract-rejected-mail t] - "--" - ["Copy Message to Folder..." mh-show-copy-msg t] - ["Print Message" mh-show-print-msg t] - ["Write Message to File..." mh-show-write-msg-to-file t] - ["Pipe Message to Command..." mh-show-pipe-msg t] - ["Unpack Uuencoded Message..." mh-show-store-msg t] - ["Burst Digest Message" mh-show-burst-digest t])) - -;;; Folder Menu - -(easy-menu-define - mh-show-folder-menu mh-show-mode-map "Menu for MH-E folder." - '("Folder" - ["Incorporate New Mail" mh-show-inc-folder t] - ["Toggle Show/Folder" mh-show-toggle-showing t] - ["Execute Delete/Refile" mh-show-execute-commands t] - ["Rescan Folder" mh-show-rescan-folder t] - ["Thread Folder" mh-show-toggle-threads t] - ["Pack Folder" mh-show-pack-folder t] - ["Sort Folder" mh-show-sort-folder t] - "--" - ["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..." mh-search t] - "--" - ["Quit MH-E" mh-quit t])) - - - -;;; MH-Show Keys - -(define-keymap :keymap mh-show-mode-map - "SPC" #'mh-show-page-msg - "!" #'mh-show-refile-or-write-again - "'" #'mh-show-toggle-tick - "," #'mh-show-header-display - "." #'mh-show-show - ":" #'mh-show-show-preferred-alternative - ">" #'mh-show-write-message-to-file - "?" #'mh-help - "E" #'mh-show-extract-rejected-mail - "M" #'mh-show-modify - "DEL" #'mh-show-previous-page - "C-d" #'mh-show-delete-msg-no-motion - "TAB" #'mh-show-next-button - "" #'mh-show-prev-button - "C-M-i" #'mh-show-prev-button - "ESC d" #'mh-show-redistribute - "^" #'mh-show-refile-msg - "c" #'mh-show-copy-msg - "d" #'mh-show-delete-msg - "e" #'mh-show-edit-again - "f" #'mh-show-forward - "g" #'mh-show-goto-msg - "i" #'mh-show-inc-folder - "k" #'mh-show-delete-subject-or-thread - "m" #'mh-show-send - "n" #'mh-show-next-undeleted-msg - "M-n" #'mh-show-next-unread-msg - "o" #'mh-show-refile-msg - "p" #'mh-show-previous-undeleted-msg - "M-p" #'mh-show-previous-unread-msg - "q" #'mh-show-quit - "r" #'mh-show-reply - "s" #'mh-show-send - "t" #'mh-show-toggle-showing - "u" #'mh-show-undo - "x" #'mh-show-execute-commands - "v" #'mh-show-index-visit-folder - "|" #'mh-show-pipe-msg - - "F" (define-keymap :prefix 'mh-show-folder-map - "?" #'mh-prefix-help - "'" #'mh-index-ticked-messages - "S" #'mh-show-sort-folder - "c" #'mh-show-catchup - "f" #'mh-show-visit-folder - "k" #'mh-show-kill-folder - "l" #'mh-show-list-folders - "n" #'mh-index-new-messages - "o" #'mh-show-visit-folder - "p" #'mh-show-pack-folder - "q" #'mh-show-index-sequenced-messages - "r" #'mh-show-rescan-folder - "s" #'mh-search - "t" #'mh-show-toggle-threads - "u" #'mh-show-undo-folder - "v" #'mh-show-visit-folder) - - "S" (define-keymap :prefix 'mh-show-sequence-map - "'" #'mh-show-narrow-to-tick - "?" #'mh-prefix-help - "d" #'mh-show-delete-msg-from-seq - "k" #'mh-show-delete-seq - "l" #'mh-show-list-sequences - "n" #'mh-show-narrow-to-seq - "p" #'mh-show-put-msg-in-seq - "s" #'mh-show-msg-is-in-seq - "w" #'mh-show-widen) - - "I" mh-inc-spool-map - - "J" (define-keymap :prefix 'mh-show-junk-map - "?" #'mh-prefix-help - "a" #'mh-show-junk-allowlist - "b" #'mh-show-junk-blocklist - "w" #'mh-show-junk-whitelist) - - "P" (define-keymap :prefix 'mh-show-ps-print-map - "?" #'mh-prefix-help - "C" #'mh-show-ps-print-toggle-color - "F" #'mh-show-ps-print-toggle-faces - "f" #'mh-show-ps-print-msg-file - "l" #'mh-show-print-msg - "p" #'mh-show-ps-print-msg) - - "T" (define-keymap :prefix 'mh-show-thread-map - "?" #'mh-prefix-help - "u" #'mh-show-thread-ancestor - "p" #'mh-show-thread-previous-sibling - "n" #'mh-show-thread-next-sibling - "t" #'mh-show-toggle-threads - "d" #'mh-show-thread-delete - "o" #'mh-show-thread-refile) - - "/" (define-keymap :prefix 'mh-show-limit-map - "'" #'mh-show-narrow-to-tick - "?" #'mh-prefix-help - "c" #'mh-show-narrow-to-cc - "g" #'mh-show-narrow-to-range - "m" #'mh-show-narrow-to-from - "s" #'mh-show-narrow-to-subject - "t" #'mh-show-narrow-to-to - "w" #'mh-show-widen) - - "X" (define-keymap :prefix 'mh-show-extract-map - "?" #'mh-prefix-help - "s" #'mh-show-store-msg - "u" #'mh-show-store-msg) - - "D" (define-keymap :prefix 'mh-show-digest-map - "?" #'mh-prefix-help - "SPC" #'mh-show-page-digest - "DEL" #'mh-show-page-digest-backwards - "b" #'mh-show-burst-digest) - - "K" (define-keymap :prefix 'mh-show-mime-map - "?" #'mh-prefix-help - "a" #'mh-mime-save-parts - "e" #'mh-show-display-with-external-viewer - "v" #'mh-show-toggle-mime-part - "o" #'mh-show-save-mime-part - "i" #'mh-show-inline-mime-part - "t" #'mh-show-toggle-mime-buttons - "TAB" #'mh-show-next-button - "" #'mh-show-prev-button - "C-M-i" #'mh-show-prev-button)) - - - -;;; MH-Show Font Lock - -(defun mh-header-field-font-lock (field limit) - "Return the value of a header field FIELD to font-lock. -Argument LIMIT limits search." - (if (= (point) limit) - nil - (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 - (re-search-forward (format "^%s" field) lesser-limit t)) - (let ((match-one-b (match-beginning 0)) - (match-one-e (match-end 0))) - (mh-header-field-end) - (if (> (point) limit) ;Don't search for end beyond limit - (goto-char limit)) - (set-match-data (list match-one-b match-one-e - (1+ match-one-e) (point))) - t))))) - -(defun mh-header-to-font-lock (limit) - "Return the value of a header field To to font-lock. -Argument LIMIT limits search." - (mh-header-field-font-lock "To:" limit)) - -(defun mh-header-cc-font-lock (limit) - "Return the value of a header field cc to font-lock. -Argument LIMIT limits search." - (mh-header-field-font-lock "cc:" limit)) - -(defun mh-header-subject-font-lock (limit) - "Return the value of a header field Subject to font-lock. -Argument LIMIT limits search." - (mh-header-field-font-lock "Subject:" limit)) - -(defun mh-letter-header-font-lock (limit) - "Return the entire mail header to font-lock. -Argument LIMIT limits search." - (if (= (point) limit) - nil - (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)) - (goto-char lesser-limit) - t)))) - -(defun mh-show-font-lock-fontify-region (beg end loudly) - "Limit font-lock in `mh-show-mode' to the header. - -Used when the option `mh-highlight-citation-style' is set to -\"Gnus\", leaving the body to be 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 (mh-mail-header-end))) - (cond - ((and (< beg header-end)(< end header-end)) - (font-lock-default-fontify-region beg end loudly)) - ((and (< beg header-end)(>= end header-end)) - (font-lock-default-fontify-region beg header-end loudly)) - (t - nil)))) - -(defvar mh-show-font-lock-keywords - '(("^\\(From:\\|Sender:\\)\\(.*\\)" - (1 'default) - (2 'mh-show-from)) - (mh-header-to-font-lock - (0 'default) - (1 'mh-show-to)) - (mh-header-cc-font-lock - (0 'default) - (1 'mh-show-cc)) - ("^\\(Reply-To:\\|Return-Path:\\)\\(.*\\)$" - (1 'default) - (2 'mh-show-from)) - (mh-header-subject-font-lock - (0 'default) - (1 'mh-show-subject)) - ("^\\(Apparently-To:\\|Newsgroups:\\)\\(.*\\)" - (1 'default) - (2 'mh-show-cc)) - ("^\\(In-Reply-To\\|Date\\):\\(.*\\)$" - (1 'default) - (2 'mh-show-date)) - (mh-letter-header-font-lock - (0 'mh-show-header append t))) - "Additional expressions to highlight in MH-Show buffers.") - -;;;###mh-autoload -(defun mh-show-font-lock-keywords () - "Return variable `mh-show-font-lock-keywords'." - mh-show-font-lock-keywords) - -(defvar mh-show-font-lock-keywords-with-cite - (let* ((cite-chars "[>|}]") - (cite-prefix "A-Za-z") - (cite-suffix (concat cite-prefix "0-9_.@-`'\""))) - (append - mh-show-font-lock-keywords - (list - ;; Use MATCH-ANCHORED to effectively anchor the regexp left side. - `(,cite-chars - (,(concat "\\=[ \t]*" - "\\(\\([" cite-prefix "]+[" cite-suffix "]*\\)?" - "\\(" cite-chars "[ \t]*\\)\\)+" - "\\(.*\\)") - (beginning-of-line) (end-of-line) - (2 font-lock-constant-face nil t) - (4 font-lock-comment-face nil t)))))) - "Additional expressions to highlight in MH-Show buffers.") - -;;;###mh-autoload -(defun mh-show-font-lock-keywords-with-cite () - "Return variable `mh-show-font-lock-keywords-with-cite'." - mh-show-font-lock-keywords-with-cite) - - - -;;; MH-Show Mode - -;; Ensure new buffers won't get this mode if default major-mode is nil. -(put 'mh-show-mode 'mode-class 'special) - -;;;###mh-autoload -(define-derived-mode mh-show-mode text-mode "MH-Show" - "Major mode for showing messages in MH-E. -\\ -Email addresses and URLs in the message are highlighted if the -option `goto-address-highlight-p' is on, which it is by default. -To view the web page for a highlighted URL or to send a message -using a highlighted email address, use the middle mouse button or -\\[goto-address-at-point]. See Info node `(mh-e)Sending Mail' to -see how to configure Emacs to send the message using MH-E. - -The hook `mh-show-mode-hook' is called upon entry to this mode. - -See also `mh-folder-mode'. - -\\{mh-show-mode-map}" - (if (boundp 'tool-bar-map) - (setq-local tool-bar-map mh-show-tool-bar-map)) - (setq-local mail-header-separator mh-mail-header-separator) - (setq paragraph-start (default-value 'paragraph-start)) - (setq buffer-invisibility-spec '((vanish . t) t)) - (setq-local line-move-ignore-invisible t) - (make-local-variable 'font-lock-defaults) - ;;(setq-local font-lock-support-mode nil) - (cond - ((equal mh-highlight-citation-style 'font-lock) - (setq font-lock-defaults '(mh-show-font-lock-keywords-with-cite t))) - ((equal mh-highlight-citation-style 'gnus) - (setq font-lock-defaults '((mh-show-font-lock-keywords) - t nil nil nil - (font-lock-fontify-region-function - . mh-show-font-lock-fontify-region))) - (mh-gnus-article-highlight-citation)) - (t - (setq font-lock-defaults '(mh-show-font-lock-keywords t)))) - (when mh-decode-mime-flag - (add-hook 'kill-buffer-hook #'mh-mime-cleanup nil t)) - (make-local-variable 'mh-show-folder-buffer) - (buffer-disable-undo) - (use-local-map mh-show-mode-map)) - - - -;;; Support Routines - -(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) - (buffer-read-only nil)) - (goto-char (mh-mail-header-end)) - (while (re-search-forward "^>From" nil t) - (replace-match "From")) - (set-buffer-modified-p modified)))) - -;;;###mh-autoload -(defun mh-show-addr () - "Use `goto-address'." - (goto-address)) - -;;;###mh-autoload -(defun mh-gnus-article-highlight-citation () - "Highlight cited text in current buffer using Gnus." - (interactive) - ;; Don't allow Gnus to create buttons while highlighting, maybe this is bad - ;; style? - (mh-flet - ((gnus-article-add-button (&rest _args) nil)) - (let* ((modified (buffer-modified-p)) - (gnus-article-buffer (buffer-name)) - (gnus-cite-face-list `(,@(cdr gnus-cite-face-list) - ,(car gnus-cite-face-list)))) - (gnus-article-highlight-citation t) - (set-buffer-modified-p modified)))) - -(provide 'mh-show) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-show.el ends here diff --git a/lisp/mh-e/mh-speed.el b/lisp/mh-e/mh-speed.el deleted file mode 100644 index 5b5ad48a291..00000000000 --- a/lisp/mh-e/mh-speed.el +++ /dev/null @@ -1,574 +0,0 @@ -;;; mh-speed.el --- MH-E speedbar support -*- lexical-binding: t; -*- - -;; Copyright (C) 2002-2024 Free Software Foundation, Inc. - -;; Author: Satyaki Das -;; Maintainer: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Future versions should only use flists. - -;;; Code: - -(require 'mh-e) - -(require 'gnus-util) -(require 'speedbar) -(require 'timer) - -;; Global variables. -(defvar mh-speed-refresh-flag nil) -(defvar mh-speed-last-selected-folder nil) -(defvar mh-speed-folder-map (make-hash-table :test #'equal)) -(defvar mh-speed-flists-cache (make-hash-table :test #'equal)) -(defvar mh-speed-flists-process nil) -(defvar mh-speed-flists-timer nil) -(defvar mh-speed-partial-line "") - - - -;;; Speedbar Hook - -(unless (member 'mh-speed-stealth-update - (cdr (assoc "files" speedbar-stealthy-function-list))) - ;; Is changing constant lists in elisp safe? - (setq speedbar-stealthy-function-list - (copy-tree speedbar-stealthy-function-list)) - (push 'mh-speed-stealth-update - (cdr (assoc "files" speedbar-stealthy-function-list)))) - - - -;;; Speedbar Menus - -(defvar mh-folder-speedbar-menu-items - '("--" - ["Visit Folder" mh-speed-view - (with-current-buffer speedbar-buffer - (get-text-property (line-beginning-position) 'mh-folder))] - ["Expand Nested Folders" mh-speed-expand-folder - (and (get-text-property (line-beginning-position) 'mh-children-p) - (not (get-text-property (line-beginning-position) 'mh-expanded)))] - ["Contract Nested Folders" mh-speed-contract-folder - (and (get-text-property (line-beginning-position) 'mh-children-p) - (get-text-property (line-beginning-position) 'mh-expanded))] - ["Refresh Speedbar" mh-speed-refresh t]) - "Extra menu items for speedbar.") - -(defvar mh-show-speedbar-menu-items mh-folder-speedbar-menu-items) -(defvar mh-letter-speedbar-menu-items mh-folder-speedbar-menu-items) - - - -;;; Speedbar Keys - -(defvar mh-folder-speedbar-key-map (speedbar-make-specialized-keymap) - "Specialized speedbar keymap for MH-E buffers.") - -(define-keymap :keymap mh-folder-speedbar-key-map - "+" #'mh-speed-expand-folder - "-" #'mh-speed-contract-folder - "RET" #'mh-speed-view - "r" #'mh-speed-refresh) - -(defvar mh-show-speedbar-key-map mh-folder-speedbar-key-map) -(defvar mh-letter-speedbar-key-map mh-folder-speedbar-key-map) - - - -;;; Speedbar Commands - -;; Alphabetical. - -(defalias 'mh-speed-contract-folder #'mh-speed-toggle) - -(defalias 'mh-speed-expand-folder #'mh-speed-toggle) - -(defun mh-speed-refresh () - "Regenerates the list of folders in the speedbar. - -Run this command if you've added or deleted a folder, or want to -update the unseen message count before the next automatic -update." - (interactive) - (mh-speed-flists t) - (mh-speed-invalidate-map "")) - -(defun mh-speed-stealth-update (&optional force) - "Do stealth update. -With non-nil FORCE, the update is always carried out." - (cond ((with-current-buffer speedbar-buffer - (get-text-property (point-min) 'mh-level)) - ;; Execute this hook and *don't* run anything else - (mh-speed-update-current-folder force) - nil) - ;; Otherwise on to your regular programming - (t t))) - -(defun mh-speed-toggle (&rest _ignored) - "Toggle the display of child folders in the speedbar. -The optional arguments from speedbar are IGNORED." - (interactive) - (beginning-of-line) - (let ((parent (get-text-property (point) 'mh-folder)) - (kids-p (get-text-property (point) 'mh-children-p)) - (expanded (get-text-property (point) 'mh-expanded)) - (level (get-text-property (point) 'mh-level)) - (point (point)) - start-region) - (speedbar-with-writable - (cond ((not kids-p) nil) - (expanded - (forward-line) - (setq start-region (point)) - (while (and (get-text-property (point) 'mh-level) - (> (get-text-property (point) 'mh-level) level)) - (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) - (speedbar-change-expand-button-char ?+) - (add-text-properties - (line-beginning-position) (1+ (line-beginning-position)) - '(mh-expanded nil))) - (t - (forward-line) - (mh-speed-add-buttons parent (1+ level)) - (goto-char point) - (speedbar-change-expand-button-char ?-) - (add-text-properties - (line-beginning-position) (1+ (line-beginning-position)) - '(mh-expanded t))))))) - -(defun mh-speed-view (&rest _ignored) - "Visits the selected folder just as if you had used \\\\[mh-visit-folder]. -The optional arguments from speedbar are IGNORED." - (interactive) - (let* ((folder (get-text-property (line-beginning-position) 'mh-folder)) - (range (and (stringp folder) - (mh-read-range "Scan" folder t nil nil - mh-interpret-number-as-range-flag)))) - (when (stringp folder) - (dframe-with-attached-buffer - (mh-visit-folder folder range) - (delete-other-windows))))) - - - -;;; Support Routines - -;;;###mh-autoload -(defun mh-folder-speedbar-buttons (_buffer) - "Interface function to create MH-E speedbar buffer. -BUFFER is the MH-E buffer for which the speedbar buffer is to be -created." - (unless (get-text-property (point-min) 'mh-level) - (erase-buffer) - (clrhash mh-speed-folder-map) - (speedbar-make-tag-line 'bracket ?+ 'mh-speed-toggle nil " " 'ignore nil - 'mh-speedbar-folder 0) - (forward-line -1) - (setf (gethash nil mh-speed-folder-map) - (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)) - (mh-speed-stealth-update t) - (when (> mh-speed-update-interval 0) - (mh-speed-flists nil)))) - -;;;###mh-autoload -(defalias 'mh-show-speedbar-buttons #'mh-folder-speedbar-buttons) -;;;###mh-autoload -(defalias 'mh-letter-speedbar-buttons #'mh-folder-speedbar-buttons) - -(defmacro mh-speed-select-attached-frame () - "Compatibility macro to handle speedbar versions 0.11a and 0.14beta4." - (cond ((fboundp 'dframe-select-attached-frame) - '(dframe-select-attached-frame speedbar-frame)) - ((boundp 'speedbar-attached-frame) - '(select-frame speedbar-attached-frame)) - (t (error "Installed speedbar version not supported by MH-E")))) - -(defun mh-speed-update-current-folder (force) - "Update speedbar highlighting of the current folder. -The function tries to be smart so that work done is minimized. -The currently highlighted folder is cached and no highlighting -happens unless it changes. -Also highlighting is suspended while the speedbar frame is selected. -Otherwise you get the disconcerting behavior of folders popping open -on their own when you are trying to navigate around in the speedbar -buffer. - -The update is always carried out if FORCE is non-nil." - (let* ((lastf (selected-frame)) - (newcf (save-excursion - (mh-speed-select-attached-frame) - (prog1 (mh-speed-extract-folder-name (buffer-name)) - (select-frame lastf)))) - (lastb (current-buffer)) - (case-fold-search t)) - (when (or force - (and mh-speed-refresh-flag (not (eq lastf speedbar-frame))) - (and (stringp newcf) - (equal (substring newcf 0 1) "+") - (not (equal newcf mh-speed-last-selected-folder)))) - (setq mh-speed-refresh-flag nil) - (select-frame speedbar-frame) - (set-buffer speedbar-buffer) - - ;; Remove highlight from previous match... - (mh-speed-highlight mh-speed-last-selected-folder 'mh-speedbar-folder) - - ;; If we found a match highlight it... - (when (mh-speed-goto-folder newcf) - (mh-speed-highlight newcf 'mh-speedbar-selected-folder)) - - (setq mh-speed-last-selected-folder newcf) - (speedbar-position-cursor-on-line) - (set-window-point (frame-first-window speedbar-frame) (point)) - (set-buffer lastb) - (select-frame lastf)) - (when (eq lastf speedbar-frame) - (setq mh-speed-refresh-flag t)))) - -(defun mh-speed-highlight (folder face) - "Set FOLDER to FACE." - (save-excursion - (speedbar-with-writable - (goto-char (gethash folder mh-speed-folder-map (point))) - (beginning-of-line) - (if (re-search-forward "([1-9][0-9]*/[0-9]+)" (line-end-position) t) - (setq face (mh-speed-bold-face face)) - (setq face (mh-speed-normal-face face))) - (beginning-of-line) - (when (re-search-forward "\\[.\\] " (line-end-position) t) - (put-text-property (point) (line-end-position) 'face face))))) - -(defun mh-speed-normal-face (face) - "Return normal face for given FACE." - (cond ((eq face 'mh-speedbar-folder-with-unseen-messages) - 'mh-speedbar-folder) - ((eq face 'mh-speedbar-selected-folder-with-unseen-messages) - 'mh-speedbar-selected-folder) - (t face))) - -(defun mh-speed-bold-face (face) - "Return bold face for given FACE." - (cond ((eq face 'mh-speedbar-folder) - 'mh-speedbar-folder-with-unseen-messages) - ((eq face 'mh-speedbar-selected-folder) - 'mh-speedbar-selected-folder-with-unseen-messages) - (t face))) - -(defun mh-speed-goto-folder (folder) - "Move point to line containing FOLDER. -The function will expand out parent folders of FOLDER if needed." - (let ((prefix folder) - (suffix-list ()) - (last-slash t)) - (while (and (not (gethash prefix mh-speed-folder-map)) last-slash) - (setq last-slash (mh-search-from-end ?/ prefix)) - (when (integerp last-slash) - (push (substring prefix (1+ last-slash)) suffix-list) - (setq prefix (substring prefix 0 last-slash)))) - (let ((prefix-position (gethash prefix mh-speed-folder-map))) - (if prefix-position - (goto-char prefix-position) - (goto-char (point-min)) - (mh-speed-toggle) - (unless (get-text-property (point) 'mh-expanded) - (mh-speed-toggle)) - (goto-char (gethash prefix mh-speed-folder-map)))) - (while suffix-list - ;; We always need at least one toggle. We need two if the directory list - ;; is stale since a folder was added. - (when (equal prefix (get-text-property (line-beginning-position) - 'mh-folder)) - (mh-speed-toggle) - (unless (get-text-property (point) 'mh-expanded) - (mh-speed-toggle))) - (setq prefix (format "%s/%s" prefix (pop suffix-list))) - (goto-char (gethash prefix mh-speed-folder-map (point)))) - (beginning-of-line) - (equal folder (get-text-property (point) 'mh-folder)))) - -(defun mh-speed-extract-folder-name (buffer) - "Given an MH-E BUFFER find the folder that should be highlighted. -Do the right thing for the different kinds of buffers that MH-E -uses." - (with-current-buffer buffer - (cond ((eq major-mode 'mh-folder-mode) - mh-current-folder) - ((eq major-mode 'mh-show-mode) - (set-buffer mh-show-folder-buffer) - mh-current-folder) - ((eq major-mode 'mh-letter-mode) - (when (string-match mh-user-path buffer-file-name) - (let* ((rel-path (substring buffer-file-name (match-end 0))) - (directory-end (mh-search-from-end ?/ rel-path))) - (when directory-end - (format "+%s" (substring rel-path 0 directory-end))))))))) - -(defun mh-speed-add-buttons (folder level) - "Add speedbar button for FOLDER which is at indented by LEVEL amount." - (let ((folder-list (mh-sub-folders folder))) - (mapc - (lambda (f) - (let* ((folder-name (format "%s%s%s" (or folder "+") - (if folder "/" "") (car f))) - (counts (gethash folder-name mh-speed-flists-cache))) - (speedbar-with-writable - (speedbar-make-tag-line - 'bracket (if (cdr f) ?+ ? ) - 'mh-speed-toggle nil - (format "%s%s" - (car f) - (if counts - (format " (%s/%s)" (car counts) (cdr counts)) - "")) - 'mh-speed-view nil - (if (and counts (> (car counts) 0)) - 'mh-speedbar-folder-with-unseen-messages - 'mh-speedbar-folder) - level) - (save-excursion - (forward-line -1) - (setf (gethash folder-name mh-speed-folder-map) - (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 - mh-expanded nil - mh-children-p ,(not (not (cdr f))) - ,@(if counts `(mh-count - (,(car counts) . ,(cdr counts))) ()) - mh-level ,level)))))) - folder-list))) - -(defvar mh-speed-current-folder nil) -(defvar mh-speed-flists-folder nil) - -(defmacro mh-process-kill-without-query (process) - "PROCESS can be killed without query on Emacs exit." - (declare (obsolete set-process-query-on-exit-flag "29.1")) - `(set-process-query-on-exit-flag ,process nil)) - -;;;###mh-autoload -(defun mh-speed-flists (force &rest folders) - "Execute flists -recurse and update message counts. -If FORCE is non-nil the timer is reset. - -Any number of optional FOLDERS can be specified. If specified, -flists is run only for that one folder." - (interactive (list t)) - (when force - (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 folders) - (unless mh-speed-flists-timer - (setq mh-speed-flists-timer - (run-at-time - nil (if (> mh-speed-update-interval 0) - mh-speed-update-interval - nil) - (lambda () - (unless (and (processp mh-speed-flists-process) - (not (eq (process-status mh-speed-flists-process) - 'exit))) - (setq mh-speed-current-folder - (concat - (if mh-speed-flists-folder - (substring (car (reverse mh-speed-flists-folder)) 1) - (with-temp-buffer - (call-process (expand-file-name "folder" mh-progs) - nil '(t nil) nil "-fast") - (buffer-substring (point-min) (1- (point-max))))) - "+")) - (setq mh-speed-flists-process - (apply #'start-process "*flists*" nil - (expand-file-name "flists" mh-progs) - (if mh-speed-flists-folder "-noall" "-all") - "-sequence" (symbol-name mh-unseen-seq) - (or mh-speed-flists-folder '("-recurse")))) - ;; Run flists on all folders the next time around... - (setq mh-speed-flists-folder nil) - (set-process-query-on-exit-flag mh-speed-flists-process nil) - (set-process-filter mh-speed-flists-process - #'mh-speed-parse-flists-output))))))) - -;; Copied from mh-make-folder-list-filter... -;; XXX Refactor to use mh-make-folder-list-filer? -(defun mh-speed-parse-flists-output (_process output) - "Parse the incremental results from flists. -PROCESS is the flists process and OUTPUT is the results that must -be handled next." - (let ((prevailing-match-data (match-data)) - (position 0) - line-end line folder unseen total) - (unwind-protect - (while (setq line-end (string-search "\n" output position)) - (setq line (format "%s%s" - mh-speed-partial-line - (substring output position line-end)) - mh-speed-partial-line "") - (cl-multiple-value-setq (folder unseen total) - (cl-values-list - (mh-parse-flist-output-line line mh-speed-current-folder))) - (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)) - (when (buffer-live-p (get-buffer speedbar-buffer)) - (with-current-buffer speedbar-buffer - (speedbar-with-writable - (when (get-text-property (point-min) 'mh-level) - (let ((pos (gethash folder mh-speed-folder-map)) - face) - (when pos - (goto-char pos) - (goto-char (line-beginning-position)) - (cond - ((null (get-text-property (point) 'mh-count)) - (goto-char (line-end-position)) - (setq face (get-text-property (1- (point)) 'face)) - (insert (format " (%s/%s)" unseen total)) - (mh-speed-highlight 'unknown face) - (goto-char (line-beginning-position)) - (add-text-properties (point) (1+ (point)) - `(mh-count (,unseen . ,total)))) - ((not (equal (get-text-property (point) 'mh-count) - (cons unseen total))) - (goto-char (line-end-position)) - (setq face (get-text-property (1- (point)) 'face)) - (re-search-backward " " (line-beginning-position) t) - (delete-region (point) (line-end-position)) - (insert (format " (%s/%s)" unseen total)) - (mh-speed-highlight 'unknown face) - (goto-char (line-beginning-position)) - (add-text-properties - (point) (1+ (point)) - `(mh-count (,unseen . ,total)))))))))))) - (setq position (1+ line-end))) - (set-match-data prevailing-match-data)) - (setq mh-speed-partial-line (substring output position)))) - -;;;###mh-autoload -(defun mh-speed-invalidate-map (folder) - "Remove FOLDER from various optimization caches." - (interactive (list "")) - (with-current-buffer speedbar-buffer - (let* ((speedbar-update-flag nil) - (last-slash (mh-search-from-end ?/ folder)) - (parent (if last-slash (substring folder 0 last-slash) nil)) - (parent-position (gethash parent mh-speed-folder-map)) - (parent-change nil)) - (when parent-position - (let ((parent-kids (mh-sub-folders parent))) - (cond ((null parent-kids) - (setq parent-change ?+)) - ((and (null (cdr parent-kids)) - (equal (if last-slash - (substring folder (1+ last-slash)) - (substring folder 1)) - (caar parent-kids))) - (setq parent-change ? )))) - (goto-char parent-position) - (when (equal (get-text-property (line-beginning-position) 'mh-folder) - parent) - (when (get-text-property (line-beginning-position) 'mh-expanded) - (mh-speed-toggle)) - (when parent-change - (speedbar-with-writable - (mh-speedbar-change-expand-button-char parent-change) - (add-text-properties - (line-beginning-position) (1+ (line-beginning-position)) - `(mh-children-p ,(equal parent-change ?+))))) - (mh-speed-highlight mh-speed-last-selected-folder 'mh-speedbar-folder) - (setq mh-speed-last-selected-folder nil) - (setq mh-speed-refresh-flag t))) - (when (equal folder "") - (mh-clear-sub-folders-cache))))) - -;; Make it slightly more general to allow for [ ] buttons to be -;; changed to [+]. -(defun mh-speedbar-change-expand-button-char (char) - "Change the expansion button character to CHAR for the current line." - (save-excursion - (beginning-of-line) - (if (re-search-forward "\\[.\\]" (line-end-position) t) - (speedbar-with-writable - (backward-char 2) - (delete-char 1) - (insert-char char 1 t) - (put-text-property (point) (1- (point)) 'invisible nil) - ;; make sure we fix the image on the text here. - (when (fboundp 'speedbar-insert-image-button-maybe) - (speedbar-insert-image-button-maybe (- (point) 2) 3)))))) - -;;;###mh-autoload -(defun mh-speed-add-folder (folder) - "Add FOLDER since it is being created. -The function invalidates the latest ancestor that is present." - (with-current-buffer speedbar-buffer - (let ((speedbar-update-flag nil) - (last-slash (mh-search-from-end ?/ folder)) - (ancestor folder) - (ancestor-pos nil)) - (cl-block while-loop - (while last-slash - (setq ancestor (substring ancestor 0 last-slash)) - (setq ancestor-pos (gethash ancestor mh-speed-folder-map)) - (when ancestor-pos - (cl-return-from while-loop)) - (setq last-slash (mh-search-from-end ?/ ancestor)))) - (unless ancestor-pos (setq ancestor nil)) - (goto-char (or ancestor-pos (gethash nil mh-speed-folder-map))) - (speedbar-with-writable - (mh-speedbar-change-expand-button-char ?+) - (add-text-properties - (line-beginning-position) (1+ (line-beginning-position)) - '(mh-children-p t))) - (when (get-text-property (line-beginning-position) 'mh-expanded) - (mh-speed-toggle)) - (setq mh-speed-refresh-flag t)))) - -(provide 'mh-speed) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-speed.el ends here diff --git a/lisp/mh-e/mh-thread.el b/lisp/mh-e/mh-thread.el deleted file mode 100644 index 8119de486a1..00000000000 --- a/lisp/mh-e/mh-thread.el +++ /dev/null @@ -1,871 +0,0 @@ -;;; mh-thread.el --- MH-E threading support -*- lexical-binding: t; -*- - -;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc. - -;; Author: Satyaki Das -;; Maintainer: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; The threading portion of this files tries to implement the -;; algorithm described at: -;; https://www.jwz.org/doc/threading.html -;; It also begins to implement the threading section of the IMAP - -;; SORT and THREAD Extensions RFC at: -;; https://tools.ietf.org/html/rfc5256 -;; The implementation lacks the reference and subject canonicalization -;; of the RFC. - -;; In the presentation buffer, children messages are shown indented -;; with either [ ] or < > around them. Square brackets ([ ]) denote -;; that the algorithm can point out some headers which when taken -;; together implies that the unindented message is an ancestor of the -;; indented message. If no such proof exists then angles (< >) are -;; used. - -;; If threading is slow on your machine, compile this file. Of all the -;; files in MH-E, this one really benefits from compilation. - -;; Some issues and problems are as follows: - -;; (1) Scan truncates the fields at length 512. So longer -;; references: headers get mutilated. The same kind of MH -;; format string works when composing messages. Is there a way -;; to avoid this? My scan command is as follows: -;; scan +folder -width 10000 \ -;; -format "%(msg)\n%{message-id}\n%{references}\n%{subject}\n" -;; I would really appreciate it if someone would help me with this. - -;; (2) Implement heuristics to recognize message identifiers in -;; In-Reply-To: header. Right now it just assumes that the last -;; text between angles (< and >) is the message identifier. -;; There is the chance that this will incorrectly use an email -;; address like a message identifier. - -;; (3) Error checking of found message identifiers should be done. - -;; (4) Since this breaks the assumption that message indices -;; increase as one goes down the buffer, the binary search -;; based mh-goto-msg doesn't work. I have a simpler replacement -;; which may be less efficient. - -;; (5) Better canonicalizing for message identifier and subject -;; strings. - -;;; Code: - -(require 'mh-e) -(require 'mh-scan) - -(cl-defstruct (mh-thread-message (:conc-name mh-message-) - (:constructor mh-thread-make-message)) - (id nil) - (references ()) - (subject "") - (subject-re-p nil)) - -(cl-defstruct (mh-thread-container (:conc-name mh-container-) - (:constructor mh-thread-make-container)) - message parent children - (real-child-p t)) - -(defvar-local mh-thread-id-hash nil - "Hash table used to canonicalize message identifiers.") - -(defvar-local mh-thread-subject-hash nil - "Hash table used to canonicalize subject strings.") - -(defvar-local mh-thread-id-table nil - "Thread ID table maps from message identifiers to message containers.") - -(defvar-local mh-thread-index-id-map nil - "Table to look up message identifier from message index.") - -(defvar-local mh-thread-id-index-map nil - "Table to look up message index number from message identifier.") - -(defvar-local mh-thread-subject-container-hash nil - "Hash table used to group messages by subject.") - -(defvar-local mh-thread-duplicates nil - "Hash table used to associate messages with the same message identifier.") - -(defvar-local mh-thread-history () - "Variable to remember the transformations to the thread tree. -When new messages are added, these transformations are rewound, -then the links are added from the newly seen messages. Finally -the transformations are redone to get the new thread tree. This -makes incremental threading easier.") - -(defvar mh-thread-body-width nil - "Width of scan substring that contains subject and body of message.") - - - -;;; MH-Folder Commands - -;;;###mh-autoload -(defun mh-thread-ancestor (&optional thread-root-flag) - "Display ancestor of current message. - -If you do not care for the way a particular thread has turned, -you can move up the chain of messages with this command. This -command can also take a prefix argument THREAD-ROOT-FLAG to jump -to the message that started everything." - (interactive "P") - (beginning-of-line) - (cond ((not (memq 'unthread mh-view-ops)) - (error "Folder isn't threaded")) - ((eobp) - (error "No message at point"))) - (let ((current-level (mh-thread-current-indentation-level))) - (cond (thread-root-flag - (while (mh-thread-immediate-ancestor)) - (mh-maybe-show)) - ((equal current-level 0) - (message "Message has no ancestor")) - (t (mh-thread-immediate-ancestor) - (mh-maybe-show))))) - -;;;###mh-autoload -(defun mh-thread-delete () - "Delete thread." - (interactive) - (cond ((not (memq 'unthread mh-view-ops)) - (error "Folder isn't threaded")) - ((eobp) - (error "No message at point")) - (t (let ((region (mh-thread-find-children))) - (mh-iterate-on-messages-in-region () (car region) (cadr region) - (mh-delete-a-msg nil)) - (mh-next-msg))))) - -;;;###mh-autoload -(defun mh-thread-next-sibling (&optional previous-flag) - "Display next sibling. - -With non-nil optional argument PREVIOUS-FLAG jump to the previous -sibling." - (interactive) - (cond ((not (memq 'unthread mh-view-ops)) - (error "Folder isn't threaded")) - ((eobp) - (error "No message at point"))) - (beginning-of-line) - (let ((point (point)) - (done nil) - (my-level (mh-thread-current-indentation-level))) - (while (and (not done) - (equal (forward-line (if previous-flag -1 1)) 0) - (not (eobp))) - (let ((level (mh-thread-current-indentation-level))) - (cond ((equal level my-level) - (setq done 'success)) - ((< level my-level) - (message "No %s sibling" (if previous-flag "previous" "next")) - (setq done 'failure))))) - (cond ((eq done 'success) (mh-maybe-show)) - ((eq done 'failure) (goto-char point)) - (t (message "No %s sibling" (if previous-flag "previous" "next")) - (goto-char point))))) - -;;;###mh-autoload -(defun mh-thread-previous-sibling () - "Display previous sibling." - (interactive) - (mh-thread-next-sibling t)) - -;;;###mh-autoload -(defun mh-thread-refile (folder) - "Refile (output) thread into FOLDER." - (interactive (list (intern (mh-prompt-for-refile-folder)))) - (cond ((not (memq 'unthread mh-view-ops)) - (error "Folder isn't threaded")) - ((eobp) - (error "No message at point")) - (t (let ((region (mh-thread-find-children))) - (mh-iterate-on-messages-in-region () (car region) (cadr region) - (mh-refile-a-msg nil folder)) - (mh-next-msg))))) - -;;;###mh-autoload -(defun mh-toggle-threads () - "Toggle threaded view of folder." - (interactive) - (let ((msg-at-point (mh-get-msg-num nil)) - (old-buffer-modified-flag (buffer-modified-p)) - (buffer-read-only nil)) - (cond ((memq 'unthread mh-view-ops) - (unless (mh-valid-view-change-operation-p 'unthread) - (error "Can't unthread folder")) - (let ((msg-list ())) - (goto-char (point-min)) - (while (not (eobp)) - (let ((index (mh-get-msg-num nil))) - (when index - (push index msg-list))) - (forward-line)) - (mh-scan-folder mh-current-folder - (mapcar (lambda (x) (format "%s" x)) - (mh-coalesce-msg-list msg-list)) - t)) - (when mh-index-data - (mh-index-insert-folder-headers) - (mh-notate-cur))) - (t (mh-thread-folder) - (push 'unthread mh-view-ops))) - (when msg-at-point (mh-goto-msg msg-at-point t t)) - (set-buffer-modified-p old-buffer-modified-flag) - (mh-recenter nil))) - - - -;;; Support Routines - -(defun mh-thread-current-indentation-level () - "Find the number of spaces by which current message is indented." - (save-excursion - (let ((address-start-offset (+ mh-cmd-note - mh-scan-field-from-start-offset)) - (level 0)) - (beginning-of-line) - (forward-char address-start-offset) - (while (char-equal (char-after) ? ) - (cl-incf level) - (forward-char)) - level))) - -(defun mh-thread-immediate-ancestor () - "Jump to immediate ancestor in thread tree." - (beginning-of-line) - (let ((point (point)) - (ancestor-level (- (mh-thread-current-indentation-level) 2)) - (done nil)) - (if (< ancestor-level 0) - nil - (while (and (not done) (equal (forward-line -1) 0)) - (when (equal ancestor-level (mh-thread-current-indentation-level)) - (setq done t))) - (unless done - (goto-char point)) - done))) - -(defun mh-thread-find-children () - "Return a region containing the current message and its children. -The result is returned as a list of two elements. The first is -the point at the start of the region and the second is the point -at the end." - (beginning-of-line) - (if (eobp) - nil - (let ((address-start-offset (+ mh-cmd-note - mh-scan-field-from-start-offset)) - (level (mh-thread-current-indentation-level)) - spaces begin) - (setq begin (point)) - (setq spaces (format (format "%%%ss" (1+ level)) "")) - (forward-line) - (cl-block nil - (while (not (eobp)) - (forward-char address-start-offset) - (unless (equal (string-match spaces (buffer-substring-no-properties - (point) (line-end-position))) - 0) - (beginning-of-line) - (backward-char) - (cl-return)) - (forward-line))) - (list begin (point))))) - - - -;;; Thread Creation - -(defun mh-thread-folder () - "Generate thread view of folder." - (message "Threading %s..." (buffer-name)) - (mh-thread-initialize) - (goto-char (point-min)) - (mh-remove-all-notation) - (let ((msg-list ())) - (mh-iterate-on-range msg (cons (point-min) (point-max)) - (setf (gethash msg mh-thread-scan-line-map) (mh-thread-parse-scan-line)) - (push msg msg-list)) - (let* ((range (mh-coalesce-msg-list msg-list)) - (thread-tree (mh-thread-generate (buffer-name) range))) - (delete-region (point-min) (point-max)) - (mh-thread-print-scan-lines thread-tree) - (mh-notate-user-sequences) - (mh-notate-deleted-and-refiled) - (mh-notate-cur) - (message "Threading %s...done" (buffer-name))))) - -;;;###mh-autoload -(defun mh-thread-inc (folder start-point) - "Update thread tree for FOLDER. -All messages after START-POINT are added to the thread tree." - (mh-thread-rewind-pruning) - (mh-remove-all-notation) - (goto-char start-point) - (let ((msg-list ())) - (while (not (eobp)) - (let ((index (mh-get-msg-num nil))) - (when (numberp index) - (push index msg-list) - (setf (gethash index mh-thread-scan-line-map) - (mh-thread-parse-scan-line))) - (forward-line))) - (let ((thread-tree (mh-thread-generate folder msg-list)) - (buffer-read-only nil) - (old-buffer-modified-flag (buffer-modified-p))) - (delete-region (point-min) (point-max)) - (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)))) - -(defmacro mh-thread-initialize-hash (var test) - "Initialize the hash table in VAR. -TEST is the test to use when creating a new hash table." - (unless (symbolp var) (error "Expected a symbol: %s" var)) - `(if ,var (clrhash ,var) (setq ,var (make-hash-table :test ,test)))) - -(defun mh-thread-initialize () - "Make new hash tables, or clear them if already present." - (mh-thread-initialize-hash mh-thread-id-hash #'equal) - (mh-thread-initialize-hash mh-thread-subject-hash #'equal) - (mh-thread-initialize-hash mh-thread-id-table #'eq) - (mh-thread-initialize-hash mh-thread-id-index-map #'eq) - (mh-thread-initialize-hash mh-thread-index-id-map #'eql) - (mh-thread-initialize-hash mh-thread-scan-line-map #'eql) - (mh-thread-initialize-hash mh-thread-subject-container-hash #'eq) - (mh-thread-initialize-hash mh-thread-duplicates #'eq) - (setq mh-thread-history ())) - -(defsubst mh-thread-id-container (id) - "Given ID, return the corresponding container in `mh-thread-id-table'. -If no container exists then a suitable container is created and -the id-table is updated." - (when (not id) - (error "1")) - (or (gethash id mh-thread-id-table) - (setf (gethash id mh-thread-id-table) - (let ((message (mh-thread-make-message :id id))) - (mh-thread-make-container :message message))))) - -(defsubst mh-thread-remove-parent-link (child) - "Remove parent link of CHILD if it exists." - (let* ((child-container (if (mh-thread-container-p child) - child (mh-thread-id-container child))) - (parent-container (mh-container-parent child-container))) - (when parent-container - (setf (mh-container-children parent-container) - (cl-loop for elem in (mh-container-children parent-container) - unless (eq child-container elem) collect elem)) - (setf (mh-container-parent child-container) nil)))) - -(defsubst mh-thread-add-link (parent child &optional at-end-p) - "Add links so that PARENT becomes a parent of CHILD. -Doesn't make any changes if CHILD is already an ancestor of -PARENT. If optional argument AT-END-P is non-nil, the CHILD is -added to the end of the children list of PARENT." - (let ((parent-container (cond ((null parent) nil) - ((mh-thread-container-p parent) parent) - (t (mh-thread-id-container parent)))) - (child-container (if (mh-thread-container-p child) - child (mh-thread-id-container child)))) - (when (and parent-container - (not (mh-thread-ancestor-p child-container parent-container)) - (not (mh-thread-ancestor-p parent-container child-container))) - (mh-thread-remove-parent-link child-container) - (cond ((not at-end-p) - (push child-container (mh-container-children parent-container))) - ((null (mh-container-children parent-container)) - (push child-container (mh-container-children parent-container))) - (t (let ((last-child (mh-container-children parent-container))) - (while (cdr last-child) - (setq last-child (cdr last-child))) - (setcdr last-child (cons child-container nil))))) - (setf (mh-container-parent child-container) parent-container)) - (unless parent-container - (mh-thread-remove-parent-link child-container)))) - -(defun mh-thread-rewind-pruning () - "Restore the thread tree to its state before pruning." - (while mh-thread-history - (let ((action (pop mh-thread-history))) - (cond ((eq (car action) 'DROP) - (mh-thread-remove-parent-link (cadr action)) - (mh-thread-add-link (caddr action) (cadr action))) - ((eq (car action) 'PROMOTE) - (let ((node (cadr action)) - (parent (caddr action)) - (children (cdddr action))) - (dolist (child children) - (mh-thread-remove-parent-link child) - (mh-thread-add-link node child)) - (mh-thread-add-link parent node))) - ((eq (car action) 'SUBJECT) - (let ((node (cadr action))) - (mh-thread-remove-parent-link node) - (setf (mh-container-real-child-p node) t))))))) - -(defun mh-thread-ancestor-p (ancestor successor) - "Return t if ANCESTOR is really an ancestor of SUCCESSOR and nil otherwise. -In the limit, the function returns t if ANCESTOR and SUCCESSOR -are the same containers." - (cl-block nil - (while successor - (when (eq ancestor successor) (cl-return t)) - (setq successor (mh-container-parent successor))) - nil)) - -;; Another and may be better approach would be to generate all the info from -;; the scan which generates the threading info. For now this will have to do. -;;;###mh-autoload -(defun mh-thread-parse-scan-line (&optional string) - "Parse a scan line. -If optional argument STRING is given then that is assumed to be -the scan line. Otherwise uses the line at point as the scan line -to parse." - (let* ((string (or string (buffer-substring-no-properties - (line-beginning-position) - (line-end-position)))) - (address-start (+ mh-cmd-note mh-scan-field-from-start-offset)) - (body-start (+ mh-cmd-note mh-scan-field-from-end-offset)) - (first-string (substring string 0 address-start))) - (list first-string - (substring string address-start (- body-start 2)) - (substring string body-start) - string))) - -(defsubst mh-thread-canonicalize-id (id) - "Produce canonical string representation for ID. -This allows cheap string comparison with EQ." - (or (and (equal id "") (copy-sequence "")) - (gethash id mh-thread-id-hash) - (setf (gethash id mh-thread-id-hash) id))) - -(defsubst mh-thread-prune-subject (subject) - "Prune leading Re:'s, Fwd:'s etc. and trailing (fwd)'s from SUBJECT. -If the result after pruning is not the empty string then it is -canonicalized so that subjects can be tested for equality with -eq. This is done so that all the messages without a subject are -not put into a single thread." - (let ((case-fold-search t) - (subject-pruned-flag nil)) - ;; Prune subject leader - (while (or (string-match "^[ \t]*\\(re\\|fwd?\\)\\(\\[[0-9]*\\]\\)?:[ \t]*" - subject) - (string-match "^[ \t]*\\[[^\\]][ \t]*" subject)) - (setq subject-pruned-flag t) - (setq subject (substring subject (match-end 0)))) - ;; Prune subject trailer - (while (or (string-match "(fwd)$" subject) - (string-match "[ \t]+$" subject)) - (setq subject-pruned-flag t) - (setq subject (substring subject 0 (match-beginning 0)))) - ;; Canonicalize subject only if it is non-empty - (cond ((equal subject "") (list subject subject-pruned-flag)) - (t (list - (or (gethash subject mh-thread-subject-hash) - (setf (gethash subject mh-thread-subject-hash) subject)) - subject-pruned-flag))))) - -(defsubst mh-thread-group-by-subject (roots) - "Group the set of message containers, ROOTS based on subject. -Bug: Check for and make sure that something without Re: is made -the parent in preference to something that has it." - (clrhash mh-thread-subject-container-hash) - (let ((results ())) - (dolist (root roots) - (let* ((subject (mh-thread-container-subject root)) - (parent (gethash subject mh-thread-subject-container-hash))) - (cond (parent (mh-thread-remove-parent-link root) - (mh-thread-add-link parent root t) - (setf (mh-container-real-child-p root) nil) - (push `(SUBJECT ,root) mh-thread-history)) - (t - (setf (gethash subject mh-thread-subject-container-hash) root) - (push root results))))) - (nreverse results))) - -(defun mh-thread-container-subject (container) - "Return the subject of CONTAINER. -If CONTAINER is empty return the subject info of one of its -children." - (cond ((and (mh-container-message container) - (mh-message-id (mh-container-message container))) - (mh-message-subject (mh-container-message container))) - (t (cl-block nil - (dolist (kid (mh-container-children container)) - (when (and (mh-container-message kid) - (mh-message-id (mh-container-message kid))) - (let ((kid-message (mh-container-message kid))) - (cl-return (mh-message-subject kid-message))))) - (error "This can't happen"))))) - -(defsubst mh-thread-update-id-index-maps (id index) - "Message with id, ID is the message in INDEX. -The function also checks for duplicate messages (that is multiple -messages with the same ID). These messages are put in the -`mh-thread-duplicates' hash table." - (let ((old-index (gethash id mh-thread-id-index-map))) - (when old-index (push old-index (gethash id mh-thread-duplicates))) - (setf (gethash id mh-thread-id-index-map) index) - (setf (gethash index mh-thread-index-id-map) id))) - -(defsubst mh-thread-get-message-container (message) - "Return container which has MESSAGE in it. -If there is no container present then a new container is -allocated." - (let* ((id (mh-message-id message)) - (container (gethash id mh-thread-id-table))) - (cond (container (setf (mh-container-message container) message) - container) - (t (setf (gethash id mh-thread-id-table) - (mh-thread-make-container :message message)))))) - -(defsubst mh-thread-get-message (id subject-re-p subject refs) - "Return appropriate message. -Otherwise update message already present to have the proper ID, -SUBJECT-RE-P, SUBJECT and REFS fields." - (let* ((container (gethash id mh-thread-id-table)) - (message (if container (mh-container-message container) nil))) - (cond (message - (setf (mh-message-subject-re-p message) subject-re-p) - (setf (mh-message-subject message) subject) - (setf (mh-message-id message) id) - (setf (mh-message-references message) refs) - message) - (container - (setf (mh-container-message container) - (mh-thread-make-message :id id :references refs - :subject subject - :subject-re-p subject-re-p))) - (t (let ((message (mh-thread-make-message :id id :references refs - :subject-re-p subject-re-p - :subject subject))) - (prog1 message - (mh-thread-get-message-container message))))))) - -(defvar mh-message-id-regexp "^<.*@.*>$" - "Regexp to recognize whether a string is a message identifier.") - -;;;###mh-autoload -(defun mh-thread-generate (folder msg-list) - "Scan FOLDER to get info for threading. -Only information about messages in MSG-LIST are added to the tree." - (with-temp-buffer - (mh-thread-set-tables folder) - (when msg-list - (apply - #'call-process (expand-file-name mh-scan-prog mh-progs) nil '(t nil) nil - "-width" "10000" "-format" - "%(msg)\n%{message-id}\n%{references}\n%{in-reply-to}\n%{subject}\n" - folder (mapcar (lambda (x) (format "%s" x)) msg-list))) - (goto-char (point-min)) - (let ((roots ()) - (case-fold-search t)) - (cl-block nil - (while (not (eobp)) - (cl-block process-message - (let* ((index-line - (prog1 (buffer-substring (point) (line-end-position)) - (forward-line))) - (index (string-to-number index-line)) - (id (prog1 (buffer-substring (point) (line-end-position)) - (forward-line))) - (refs (prog1 - (buffer-substring (point) (line-end-position)) - (forward-line))) - (in-reply-to (prog1 (buffer-substring (point) - (line-end-position)) - (forward-line))) - (subject (prog1 - (buffer-substring - (point) (line-end-position)) - (forward-line))) - (subject-re-p nil)) - (unless (gethash index mh-thread-scan-line-map) - (cl-return-from process-message)) - (unless (integerp index) (cl-return)) ;Error message here - (cl-multiple-value-setq (subject subject-re-p) - (cl-values-list (mh-thread-prune-subject subject))) - (setq in-reply-to (mh-thread-process-in-reply-to in-reply-to)) - (setq refs - (cl-loop for x in (append (split-string refs) in-reply-to) - when (string-match mh-message-id-regexp x) - collect x)) - (setq id (mh-thread-canonicalize-id id)) - (mh-thread-update-id-index-maps id index) - (setq refs (mapcar #'mh-thread-canonicalize-id refs)) - (mh-thread-get-message id subject-re-p subject refs) - (cl-do ((ancestors refs (cdr ancestors))) - ((null (cdr ancestors)) - (when (car ancestors) - (mh-thread-remove-parent-link id) - (mh-thread-add-link (car ancestors) id))) - (mh-thread-add-link (car ancestors) (cadr ancestors))))))) - (maphash (lambda (_k v) - (when (null (mh-container-parent v)) - (push v roots))) - mh-thread-id-table) - (setq roots (mh-thread-prune-containers roots)) - (prog1 (setq roots (mh-thread-group-by-subject roots)) - (let ((history mh-thread-history)) - (set-buffer folder) - (setq mh-thread-history history)))))) - -(defun mh-thread-set-tables (folder) - "Use the tables of FOLDER in current buffer." - (dolist (v '(mh-thread-id-hash - mh-thread-subject-hash - mh-thread-id-table - mh-thread-id-index-map - mh-thread-index-id-map - mh-thread-scan-line-map - mh-thread-subject-container-hash - mh-thread-duplicates - mh-thread-history)) - ;; Emacs >= 22.1: (buffer-local-value v folder). - (set v (with-current-buffer folder (symbol-value v))))) - -(defun mh-thread-process-in-reply-to (reply-to-header) - "Extract message id's from REPLY-TO-HEADER. -Ideally this should have some regexp which will try to guess if a -string between < and > is a message id and not an email address. -For now it will take the last string inside angles." - (let ((end (mh-search-from-end ?> reply-to-header))) - (when (numberp end) - (let ((begin (mh-search-from-end ?< (substring reply-to-header 0 end)))) - (when (numberp begin) - (list (substring reply-to-header begin (1+ end)))))))) - -(defun mh-thread-prune-containers (roots) - "Prune empty containers in the containers ROOTS." - (let ((dfs-ordered-nodes ()) - (work-list roots)) - (while work-list - (let ((node (pop work-list))) - (dolist (child (mh-container-children node)) - (push child work-list)) - (push node dfs-ordered-nodes))) - (while dfs-ordered-nodes - (let ((node (pop dfs-ordered-nodes))) - (cond ((gethash (mh-message-id (mh-container-message node)) - mh-thread-id-index-map) - ;; Keep it - (setf (mh-container-children node) - (mh-thread-sort-containers (mh-container-children node)))) - ((and (mh-container-children node) - (or (null (cdr (mh-container-children node))) - (mh-container-parent node))) - ;; Promote kids - (let ((children ())) - (dolist (kid (mh-container-children node)) - (mh-thread-remove-parent-link kid) - (mh-thread-add-link (mh-container-parent node) kid) - (push kid children)) - (push `(PROMOTE ,node ,(mh-container-parent node) ,@children) - mh-thread-history) - (mh-thread-remove-parent-link node))) - ((mh-container-children node) - ;; Promote the first orphan to parent and add the other kids as - ;; his children - (setf (mh-container-children node) - (mh-thread-sort-containers (mh-container-children node))) - (let ((new-parent (car (mh-container-children node))) - (other-kids (cdr (mh-container-children node)))) - (mh-thread-remove-parent-link new-parent) - (dolist (kid other-kids) - (mh-thread-remove-parent-link kid) - (setf (mh-container-real-child-p kid) nil) - (mh-thread-add-link new-parent kid t)) - (push `(PROMOTE ,node ,(mh-container-parent node) - ,new-parent ,@other-kids) - mh-thread-history) - (mh-thread-remove-parent-link node))) - (t - ;; Drop it - (push `(DROP ,node ,(mh-container-parent node)) - mh-thread-history) - (mh-thread-remove-parent-link node))))) - (let ((results ())) - (maphash (lambda (_k v) - (when (and (null (mh-container-parent v)) - (gethash (mh-message-id (mh-container-message v)) - mh-thread-id-index-map)) - (push v results))) - mh-thread-id-table) - (mh-thread-sort-containers results)))) - -(defun mh-thread-sort-containers (containers) - "Sort a list of message CONTAINERS to be in ascending order wrt index." - (sort containers - (lambda (x y) - (when (and (mh-container-message x) (mh-container-message y)) - (let* ((id-x (mh-message-id (mh-container-message x))) - (id-y (mh-message-id (mh-container-message y))) - (index-x (gethash id-x mh-thread-id-index-map)) - (index-y (gethash id-y mh-thread-id-index-map))) - (and (integerp index-x) (integerp index-y) - (< index-x index-y))))))) - -(defvar mh-thread-last-ancestor) - -;;;###mh-autoload -(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) - (cl-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) - (cl-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)))) - (mh-index-create-imenu-index)))) - -(defun mh-thread-generate-scan-lines (tree level) - "Generate scan lines. -TREE is the hierarchical tree of messages, SCAN-LINE-MAP maps -message indices to the corresponding scan lines and LEVEL used to -determine indentation of the message." - (cond ((null tree) nil) - ((mh-thread-container-p tree) - (let* ((message (mh-container-message tree)) - (id (mh-message-id message)) - (index (gethash id mh-thread-id-index-map)) - (duplicates (gethash id mh-thread-duplicates)) - (new-level (+ level 2)) - (dupl-flag t) - (force-angle-flag nil) - (increment-level-flag nil)) - (dolist (scan-line (mapcar (lambda (x) - (gethash x mh-thread-scan-line-map)) - (reverse (cons index duplicates)))) - (when scan-line - (when (and dupl-flag (equal level 0) - (mh-thread-ancestor-p mh-thread-last-ancestor tree)) - (setq level (+ level 2) - new-level (+ new-level 2) - force-angle-flag t)) - (when (equal level 0) - (setq mh-thread-last-ancestor tree) - (while (mh-container-parent mh-thread-last-ancestor) - (setq mh-thread-last-ancestor - (mh-container-parent mh-thread-last-ancestor)))) - (let* ((lev (if dupl-flag level new-level)) - (square-flag (or (and (mh-container-real-child-p tree) - (not force-angle-flag) - dupl-flag) - (equal lev 0)))) - (insert (car scan-line) - (format (format "%%%ss" lev) "") - (if square-flag "[" "<") - (cadr scan-line) - (if square-flag "]" ">") - (truncate-string-to-width - (caddr scan-line) (- mh-thread-body-width lev)) - "\n")) - (setq increment-level-flag t) - (setq dupl-flag nil))) - (unless increment-level-flag (setq new-level level)) - (dolist (child (mh-container-children tree)) - (mh-thread-generate-scan-lines child new-level)))) - (t (let ((nlevel (+ level 2))) - (dolist (ch tree) - (mh-thread-generate-scan-lines ch nlevel)))))) - - - -;;; Additional Utilities - -;;;###mh-autoload -(defun mh-thread-update-scan-line-map (msg notation offset) - "In threaded view update `mh-thread-scan-line-map'. -MSG is the message being notated with NOTATION at OFFSET." - (let* ((msg (or msg (mh-get-msg-num nil))) - (cur-scan-line (and mh-thread-scan-line-map - (gethash msg mh-thread-scan-line-map))) - (old-scan-lines (cl-loop for map in mh-thread-scan-line-map-stack - collect (and map (gethash msg map))))) - (when cur-scan-line - (setf (aref (car cur-scan-line) offset) notation)) - (dolist (line old-scan-lines) - (when line (setf (aref (car line) offset) notation))))) - -;;;###mh-autoload -(defun mh-thread-find-msg-subject (msg) - "Find canonicalized subject of MSG. -This function can only be used the folder is threaded." - (ignore-errors - (mh-message-subject - (mh-container-message (gethash (gethash msg mh-thread-index-id-map) - mh-thread-id-table))))) - -;;;###mh-autoload -(defun mh-thread-add-spaces (count) - "Add COUNT spaces to each scan line in `mh-thread-scan-line-map'." - (let ((spaces (format (format "%%%ss" count) ""))) - (while (not (eobp)) - (let* ((msg-num (mh-get-msg-num nil)) - (old-line (nth 3 (gethash msg-num mh-thread-scan-line-map)))) - (when (numberp msg-num) - (setf (gethash msg-num mh-thread-scan-line-map) - (mh-thread-parse-scan-line (format "%s%s" spaces old-line))))) - (forward-line 1)))) - -;;;###mh-autoload -(defun mh-thread-forget-message (index) - "Forget the message INDEX from the threading tables." - (let* ((id (gethash index mh-thread-index-id-map)) - (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) - (setf (gethash id mh-thread-id-index-map) (car duplicates)) - (setf (gethash (car duplicates) mh-thread-index-id-map) id) - (setf (gethash id mh-thread-duplicates) (cdr duplicates))) - (t - (setf (gethash id mh-thread-duplicates) - (remove index duplicates)))))) - -(provide 'mh-thread) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-thread.el ends here diff --git a/lisp/mh-e/mh-tool-bar.el b/lisp/mh-e/mh-tool-bar.el deleted file mode 100644 index 580faf7c5df..00000000000 --- a/lisp/mh-e/mh-tool-bar.el +++ /dev/null @@ -1,382 +0,0 @@ -;;; mh-tool-bar.el --- MH-E tool bar support -*- lexical-binding: t; -*- - -;; Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc. - -;; Author: Satyaki Das -;; Maintainer: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;;; Code: - -(require 'mh-e) -(require 'mh-acros) -(require 'tool-bar) - -;;; Tool Bar Commands - -(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 tool bar." - (interactive) - (mh-customize t)) - -(defun mh-tool-bar-folder-help () - "Visit \"(mh-e)Top\"." - (interactive) - (info "(mh-e)Top") - (delete-other-windows)) - -(defun mh-tool-bar-letter-help () - "Visit \"(mh-e)Editing Drafts\"." - (interactive) - (info "(mh-e)Editing Drafts") - (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) - - - -;;; Tool Bar Creation - -(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 consisting of four mandatory -items and one optional item as follows: - - (FUNCTION MODES ICON DOC &optional ENABLE-EXPR) - -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. - - DOC is the documentation for the button. It is used in tool-tips and - in providing other help to the user. GNU Emacs uses only the first - line of the string. So the DOC should be formatted such that the - first line is useful and complete without the rest of the string. - - Optional item ENABLE-EXPR is an arbitrary lisp expression. If it - evaluates to nil, then the button is inactive, otherwise it is - active. If it isn't present then the button is always active." - ;; The following variable names have been carefully chosen to make code - ;; generation easier. Modifying the names should be done carefully. - (mh-dlet* (folder-buttons - folder-docs folder-button-setter sequence-button-setter - show-buttons show-button-setter show-seq-button-setter - letter-buttons letter-docs letter-button-setter - folder-defaults letter-defaults - folder-vectors show-vectors letter-vectors) - (dolist (x defaults) - (cond ((eq (car x) :folder) (setq folder-defaults (cdr x))) - ((eq (car x) :letter) (setq letter-defaults (cdr x))))) - (dolist (button buttons) - (unless (and (listp button) - (or (equal (length button) 4) (equal (length button) 5))) - (error "Incorrect MH-E tool-bar button specification: %s" button)) - (let* ((name (nth 0 button)) - (name-str (symbol-name name)) - (icon (nth 2 button)) - (full-doc (nth 3 button)) - (doc (if (string-match "\\(.*\\)\n" full-doc) - (match-string 1 full-doc) - full-doc)) - (enable-expr (if (eql (length button) 4) t (nth 4 button))) - (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))) - (cl-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 "-tool-bar-" 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 `(vector nil ',function t ,full-doc)) - (add-to-list - setter `(when (member ',name ,list) - (tool-bar-add-item ,icon ',function ',key - :help ,doc :enable ',enable-expr))) - (add-to-list mbuttons name) - (if docs (add-to-list docs doc)))))) - (setq folder-buttons (nreverse folder-buttons) - letter-buttons (nreverse letter-buttons) - show-buttons (nreverse show-buttons) - letter-docs (nreverse letter-docs) - folder-docs (nreverse folder-docs) - folder-vectors (nreverse folder-vectors) - show-vectors (nreverse show-vectors) - letter-vectors (nreverse letter-vectors)) - (dolist (x folder-defaults) - (unless (memq x folder-buttons) - (error "Folder defaults contains unknown button %s" x))) - (dolist (x letter-defaults) - (unless (memq x letter-buttons) - (error "Letter defaults contains unknown button %s" x))) - `(eval-and-compile - (defun mh-buffer-exists-p (mode) - "Test whether a buffer with major mode MODE is present." - (cl-loop for buf in (buffer-list) - when (with-current-buffer buf - (eq major-mode mode)) - return t)) - ;; Tool bar initialization functions - (defun mh-tool-bar-folder-buttons-init () - (when (mh-buffer-exists-p 'mh-folder-mode) - (mh--with-image-load-path - (setq mh-folder-tool-bar-map - (let ((tool-bar-map (make-sparse-keymap))) - ,@(nreverse folder-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)) - (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))))) - (defun mh-tool-bar-letter-buttons-init () - (when (mh-buffer-exists-p 'mh-letter-mode) - (mh--with-image-load-path - (setq mh-letter-tool-bar-map - (let ((tool-bar-map (make-sparse-keymap))) - ,@(nreverse letter-button-setter) - tool-bar-map))))) - ;; Custom setter functions - (defun mh-tool-bar-update (mode default-map sequence-map) - "Update `tool-bar-map' in all buffers of MODE. -Use SEQUENCE-MAP if display is limited; DEFAULT-MAP otherwise." - (cl-loop for buf in (buffer-list) - do (with-current-buffer buf - (when (eq mode major-mode) ;FIXME: derived-mode-p? - (let ((map (if mh-folder-view-stack - sequence-map - default-map))) - ;; Yes, make-local-variable is necessary since we - ;; get here during initialization when loading - ;; mh-e.el, after the +inbox buffer has been - ;; created, but before mh-folder-mode has run and - ;; created the local map. - (setq-local tool-bar-map map)))))) - (defun mh-tool-bar-folder-buttons-set (symbol value) - "Construct tool bar for `mh-folder-mode' and `mh-show-mode'." - (set-default symbol value) - (mh-tool-bar-folder-buttons-init) - (mh-tool-bar-update 'mh-folder-mode mh-folder-tool-bar-map - mh-folder-seq-tool-bar-map) - (mh-tool-bar-update 'mh-show-mode mh-show-tool-bar-map - mh-show-seq-tool-bar-map)) - (defun mh-tool-bar-letter-buttons-set (symbol value) - "Construct tool bar for `mh-letter-mode'." - (set-default symbol value) - (mh-tool-bar-letter-buttons-init) - (mh-tool-bar-update 'mh-letter-mode mh-letter-tool-bar-map - mh-letter-tool-bar-map)) - ;; Declare customizable tool bars - (custom-declare-variable - 'mh-tool-bar-folder-buttons - '(list ,@(mapcar (lambda (x) `(quote ,x)) folder-defaults)) - "List of buttons to include in MH-Folder tool bar." - :group 'mh-tool-bar - :set #'mh-tool-bar-folder-buttons-set - :type '(set ,@(cl-loop for x in folder-buttons - for y in folder-docs - collect `(const :tag ,y ,x))) - ;;:package-version '(MH-E "7.1") - ) - (custom-declare-variable - 'mh-tool-bar-letter-buttons - '(list ,@(mapcar (lambda (x) `(quote ,x)) letter-defaults)) - "List of buttons to include in MH-Letter tool bar." - :group 'mh-tool-bar - :set #'mh-tool-bar-letter-buttons-set - :type '(set ,@(cl-loop for x in letter-buttons - for y in letter-docs - collect `(const :tag ,y ,x))) - ;;:package-version '(MH-E "7.1") - )))) - -(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 save-buffer mh-fully-kill-draft - mh-compose-insertion ispell-message undo - clipboard-kill-region clipboard-kill-ring-save - clipboard-yank mh-tool-bar-customize - mh-tool-bar-letter-help)) - ;; Folder/Show buffer buttons - (mh-inc-folder (folder) "mail/inbox" "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) "next-page" "Page the current message forwards -This button runs `mh-page-msg'") - (mh-next-undeleted-msg (folder) "right-arrow" "Go to the next undeleted message -The button runs `mh-next-undeleted-msg'") - (mh-delete-msg (folder) "delete" "Mark this message for deletion -This button runs `mh-delete-msg'") - (mh-refile-msg (folder) "mail/move" "Refile this message -This button runs `mh-refile-msg'") - (mh-undo (folder) "undo" "Undo last operation -This button runs `undo'" - (mh-outstanding-commands-p)) - (mh-execute-commands (folder) "data-save" "Perform moves and deletes -This button runs `mh-execute-commands'" - (mh-outstanding-commands-p)) - (mh-toggle-tick (folder) "mail/flag-for-followup" "Toggle tick mark -This button runs `mh-toggle-tick'") - (mh-toggle-showing (folder) "show" "Toggle showing message -This button runs `mh-toggle-showing'") - (mh-reply (folder) "mail/reply" "Reply to this message -This button runs `mh-reply'") - (mh-tool-bar-reply-from (folder) "mail/reply-from" "Reply to \"from\"") - (mh-tool-bar-reply-to (folder) "mail/reply-to" "Reply to \"to\"") - (mh-tool-bar-reply-all (folder) "mail/reply-all" "Reply to \"all\"") - (mh-alias-grab-from-field (folder) "contact" "Create alias for sender -This button runs `mh-alias-grab-from-field'" - (and (mh-extract-from-header-value) - (not (mh-alias-for-from-p)))) - (mh-send (folder) "mail/compose" "Compose new message -This button runs `mh-send'") - (mh-rescan-folder (folder) "refresh" "Rescan this folder -This button runs `mh-rescan-folder'") - (mh-pack-folder (folder) "mail/repack" "Repack this folder -This button runs `mh-pack-folder'") - (mh-tool-bar-search (folder) "search" "Search -This button runs `mh-tool-bar-search-function'") - (mh-visit-folder (folder) "open" "Visit other folder -This button runs `mh-visit-folder'") - ;; Letter buffer buttons - (mh-send-letter (letter) "mail/send" "Send this letter") - (save-buffer (letter) "save" "Save current buffer to its file" - (buffer-modified-p)) - (mh-fully-kill-draft (letter) "delete" "Kill this draft") - (mh-compose-insertion (letter) "attach" "Insert attachment") - (ispell-message (letter) "spell" "Check spelling") - (undo (letter) "undo" "Undo last operation") - (clipboard-kill-region (letter) "cut" - "Cut (kill) text in region") - (clipboard-kill-ring-save (letter) "copy" - "Copy text in region") - (clipboard-yank (letter) "paste" - "Paste (yank) text cut or copied earlier") - ;; Common buttons - (mh-tool-bar-customize (folder letter) "preferences" "MH-E Preferences") - (mh-tool-bar-folder-help (folder) "help" "Help! (general help) -This button runs `info'") - (mh-tool-bar-letter-help (letter) "help" "Help! (general help) -This button runs `info'") - ;; Folder narrowed to sequence buttons - (mh-widen (sequence) "zoom-out" "Widen from the sequence -This button runs `mh-widen'")) - -(provide 'mh-tool-bar) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-tool-bar.el ends here diff --git a/lisp/mh-e/mh-utils.el b/lisp/mh-e/mh-utils.el deleted file mode 100644 index 9d5711105ba..00000000000 --- a/lisp/mh-e/mh-utils.el +++ /dev/null @@ -1,1010 +0,0 @@ -;;; mh-utils.el --- MH-E general utilities -*- lexical-binding: t; -*- - -;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation, -;; Inc. - -;; Author: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;;; Code: - -(require 'mh-e) - -(require 'font-lock) -(require 'mailabbrev) - -;;; CL Replacements - -;;;###mh-autoload -(defun mh-search-from-end (char string) - "Return the position of last occurrence of CHAR in STRING. -If CHAR is not present in STRING then return nil. The function is -used in lieu of `search' in the CL package." - (cl-loop for index from (1- (length string)) downto 0 - when (equal (aref string index) char) return index - finally return nil)) - - - -;;; General Utilities - -;;;###mh-autoload -(defun mh-beginning-of-word (&optional n) - "Return position of the N th word backwards." - (unless n (setq n 1)) - (let ((syntax-table (syntax-table))) - (unwind-protect - (save-excursion - (mail-abbrev-make-syntax-table) - (set-syntax-table mail-abbrev-syntax-table) - (backward-word n) - (point)) - (set-syntax-table syntax-table)))) - -;;;###mh-autoload -(defun mh-colors-in-use-p () - "Check if colors are being used in the folder buffer." - (and mh-colors-available-flag font-lock-mode)) - -;;;###mh-autoload -(defun mh-delete-line (lines) - "Delete the next LINES lines." - (delete-region (point) (progn (forward-line lines) (point)))) - -;;;###mh-autoload -(defun mh-make-local-vars (&rest pairs) - "Initialize local variables according to the variable-value PAIRS." - (declare (obsolete setq-local "29.1")) - (while pairs - (set (make-local-variable (car pairs)) (car (cdr pairs))) - (setq pairs (cdr (cdr pairs))))) - -;;;###mh-autoload -(define-obsolete-function-alias 'mh-mapc #'mapc "29.1") - -(defvar mh-pick-regexp-chars ".*$[" - "List of special characters in pick regular expressions.") - -;;;###mh-autoload -(defun mh-quote-pick-expr (pick-expr) - "Quote `mh-pick-regexp-chars' in PICK-EXPR. -PICK-EXPR is a list of strings. Return nil if PICK-EXPR is nil." - (let ((quoted-pick-expr)) - (dolist (string pick-expr) - (when (and string - (not (string-equal string ""))) - (cl-loop for i from 0 to (1- (length mh-pick-regexp-chars)) do - (let ((s (string ?\\ (aref mh-pick-regexp-chars i)))) - (setq string (replace-regexp-in-string s s string t t)))) - (setq quoted-pick-expr (append quoted-pick-expr (list string))))) - quoted-pick-expr)) - -;;;###mh-autoload -(defun mh-replace-string (old new) - "Replace all occurrences of OLD with NEW in the current buffer. -Ignores case when searching for OLD." - (goto-char (point-min)) - (let ((case-fold-search t)) - (while (search-forward old nil t) - (replace-match new t t)))) - - - -;;; Logo Display - -;;;###mh-autoload -(defmacro mh--with-image-load-path (&rest body) - "Load `image' and eval BODY with `image-load-path' set appropriately." - (declare (debug t) (indent 0)) - `(progn - ;; Not preloaded in without-x builds. - (require 'image) - (defvar image-load-path) - (declare-function image-load-path-for-library "image") - (let* ((load-path (image-load-path-for-library "mh-e" "mh-logo.xpm")) - (image-load-path (cons (car load-path) image-load-path))) - ,@body))) - -(defvar mh-logo-cache nil) - -;;;###mh-autoload -(defun mh-logo-display () - "Modify mode line to display MH-E logo." - (mh--with-image-load-path - (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)))) - - - -;;; Read MH Profile - -(defvar mh-find-path-run nil - "Non-nil if `mh-find-path' has been run already. -Do not access this variable; `mh-find-path' already uses it to -avoid running more than once.") - -;;;###mh-autoload -(defun mh-find-path () - "Set variables from user's MH profile. - -This function sets `mh-user-path' from your \"Path:\" MH profile -component (but defaults to \"Mail\" if one isn't present), -`mh-draft-folder' from \"Draft-Folder:\", `mh-unseen-seq' from -\"Unseen-Sequence:\", `mh-previous-seq' from -\"Previous-Sequence:\", and `mh-inbox' from \"Inbox:\" (defaults -to \"+inbox\"). - -The hook `mh-find-path-hook' is run after these variables have -been set. This hook can be used the change the value of these -variables if you need to run with different values between MH and -MH-E." - (unless mh-find-path-run - (or mh-variant-in-use (mh-variant-set mh-variant)) - ;; Sanity checks. - (if (and (getenv "MH") - (not (file-readable-p (getenv "MH")))) - (error "MH environment variable contains unreadable file %s" - (getenv "MH"))) - (if (null (mh-variants)) - (error "Install MH and run install-mh before running MH-E")) - (if (not (or (getenv "MH") (file-readable-p "~/.mh_profile"))) - (error "Run install-mh before running MH-E")) - ;; Read MH profile. - (setq mh-user-path (mh-profile-component "Path")) - (if (not mh-user-path) - (setq mh-user-path "Mail")) - (setq mh-user-path - (file-name-as-directory - (expand-file-name mh-user-path (expand-file-name "~")))) - (mh-set-x-image-cache-directory (expand-file-name ".mhe-x-image-cache" - mh-user-path)) - (setq mh-draft-folder (mh-profile-component "Draft-Folder")) - (if mh-draft-folder - (progn - (if (not (mh-folder-name-p mh-draft-folder)) - (setq mh-draft-folder (format "+%s" mh-draft-folder))) - (if (not (file-exists-p (mh-expand-file-name mh-draft-folder))) - (error - "Draft folder \"%s\" not found; create it and try again" - (mh-expand-file-name mh-draft-folder))))) - (setq mh-inbox (mh-profile-component "Inbox")) - (cond ((not mh-inbox) - (setq mh-inbox "+inbox")) - ((not (mh-folder-name-p mh-inbox)) - (setq mh-inbox (format "+%s" mh-inbox)))) - (setq mh-unseen-seq (mh-profile-component "Unseen-Sequence")) - (if mh-unseen-seq - (setq mh-unseen-seq (intern mh-unseen-seq)) - (setq mh-unseen-seq 'unseen)) ;old MH default? - (setq mh-previous-seq (mh-profile-component "Previous-Sequence")) - (if mh-previous-seq - (setq mh-previous-seq (intern mh-previous-seq))) - (run-hooks 'mh-find-path-hook) - (mh-collect-folder-names) - (setq mh-find-path-run t))) - - - -;;; Help Functions - -;;;###mh-autoload -(defun mh-ephem-message (string) - "Display STRING in the minibuffer momentarily." - (message "%s" string) - (sit-for 5) - (message "")) - -(defvar mh-help-default nil - "Mode to use if messages are not present for the current mode.") - -(defvar mh-help-messages nil - "Help messages for all modes. -This is an alist of alists. The primary key is a symbol -representing the mode; the value is described in `mh-set-help'.") - -;;;###mh-autoload -(defun mh-set-help (messages &optional default) - "Set help messages. - -The MESSAGES are assumed to be an associative array. It is used -to show help for the most common commands in the current mode. -The key is a prefix char. The value is one or more strings which -are concatenated together and displayed in a help buffer if ? is -pressed after the prefix character. The special key nil is used -to display the non-prefixed commands. - -The substitutions described in `substitute-command-keys' are performed as -well. - -If optional argument DEFAULT is non-nil, then these messages will -be used if help is asked for an unknown mode." - (add-to-list 'mh-help-messages (cons major-mode messages)) - (if default - (setq mh-help-default major-mode))) - -;;;###mh-autoload -(defun mh-help (&optional help-messages) - "Display cheat sheet for the MH-E commands. -See `mh-set-help' for setting the help messages. -HELP-MESSAGES are used instead if given. -This is a list of one or more strings which are concatenated together -and displayed in a help buffer." - (interactive) - (let* ((help (or help-messages - (cdr (assoc nil (assoc major-mode mh-help-messages))))) - (text (substitute-command-keys (mapconcat #'identity help "")))) - (with-electric-help - (lambda () - (insert text)) - mh-help-buffer))) - -;;;###mh-autoload -(defun mh-prefix-help () - "Display cheat sheet for the commands of the current prefix in minibuffer." - (interactive) - ;; We got here because the user pressed a "?", but he pressed a prefix key - ;; before that. Since the key vector starts at index 0, the index of the - ;; last keystroke is length-1 and thus the second to last keystroke is at - ;; length-2. We use that information to obtain a suitable prefix character - ;; from the recent keys. - (let* ((keys (recent-keys)) - (prefix-char (elt keys (- (length keys) 2))) - (help (cdr (assoc prefix-char (assoc major-mode mh-help-messages))))) - (mh-help help))) - - - -;;; Message Number Utilities - -;;;###mh-autoload -(defun mh-coalesce-msg-list (messages) - "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) - (ranges nil)) - (while prev - (if range-high - (if (or (not (numberp prev)) - (not (equal (car msgs) (1- prev)))) - (progn ;non-sequential, flush old range - (if (eq prev range-high) - (setq ranges (cons range-high ranges)) - (setq ranges (cons (format "%s-%s" prev range-high) ranges))) - (setq range-high nil)))) - (or range-high - (setq range-high (car msgs))) ;start new or first range - (setq prev (car msgs)) - (setq msgs (cdr msgs))) - ranges)) - -(defun mh-greaterp (msg1 msg2) - "Return the greater of two message indicators MSG1 and MSG2. -Strings are \"smaller\" than numbers. -Valid values are things like \"cur\", \"last\", 1, and 1820." - (if (numberp msg1) - (if (numberp msg2) - (> msg1 msg2) - t) - (if (numberp msg2) - nil - (string-lessp msg2 msg1)))) - -;;;###mh-autoload -(defun mh-lessp (msg1 msg2) - "Return the lesser of two message indicators MSG1 and MSG2. -Strings are \"smaller\" than numbers. -Valid values are things like \"cur\", \"last\", 1, and 1820." - (not (mh-greaterp msg1 msg2))) - -;;;###mh-autoload -(defun mh-get-msg-num (error-if-no-message) - "Return the message number of the displayed message. -If the argument ERROR-IF-NO-MESSAGE is non-nil, then complain if -the cursor is not pointing to a message." - (save-excursion - (beginning-of-line) - (cond ((looking-at (mh-scan-msg-number-regexp)) - (string-to-number (buffer-substring (match-beginning 1) - (match-end 1)))) - (error-if-no-message - (user-error "Cursor not pointing to message")) - (t nil)))) - - - -;;; Folder Cache and Access - -(defvar mh-sub-folders-cache (make-hash-table :test #'equal)) -(defvar mh-current-folder-name nil) -(defvar mh-flists-partial-line "") -(defvar mh-flists-process nil) - -;;;###mh-autoload -(defun mh-clear-sub-folders-cache () - "Clear `mh-sub-folders-cache'." - (clrhash mh-sub-folders-cache)) - -;; Initialize mh-sub-folders-cache... -(defun mh-collect-folder-names () - "Collect folder names by running \"folders\"." - (unless mh-flists-process - (setq mh-flists-process - (mh-exec-cmd-daemon "folders" 'mh-collect-folder-names-filter - "-recurse" "-fast")))) - -(defun mh-collect-folder-names-filter (_process output) - "Read folder names. -PROCESS is the flists process that was run to collect folder -names and the function is called when OUTPUT is available." - (let ((position 0) - (prevailing-match-data (match-data)) - line-end folder) - (unwind-protect - (while (setq line-end (string-search "\n" output position)) - (setq folder (format "+%s%s" - mh-flists-partial-line - (substring output position line-end))) - (setq mh-flists-partial-line "") - (unless (equal (aref folder 1) ?.) - (mh-populate-sub-folders-cache folder)) - (setq position (1+ line-end))) - (set-match-data prevailing-match-data)) - (setq mh-flists-partial-line (substring output position)))) - -(defun mh-populate-sub-folders-cache (folder) - "Tell `mh-sub-folders-cache' about FOLDER." - (let* ((last-slash (mh-search-from-end ?/ folder)) - (child1 (substring folder (1+ (or last-slash 0)))) - (parent (and last-slash (substring folder 0 last-slash))) - (parent-slash (and parent (mh-search-from-end ?/ parent))) - (child2 (and parent (substring parent (1+ (or parent-slash 0))))) - (grand-parent (and parent-slash (substring parent 0 parent-slash))) - (cache-entry (gethash parent mh-sub-folders-cache))) - (unless (cl-loop for x in cache-entry when (equal (car x) child1) return t - finally return nil) - (push (list child1) cache-entry) - (setf (gethash parent mh-sub-folders-cache) - (sort cache-entry (lambda (x y) (string< (car x) (car y))))) - (when parent - (cl-loop for x in (gethash grand-parent mh-sub-folders-cache) - when (equal (car x) child2) - do (progn (setf (cdr x) t) (cl-return))))))) - -(defun mh-normalize-folder-name (folder &optional empty-string-okay - dont-remove-trailing-slash - return-nil-if-folder-empty) - "Normalizes FOLDER name. - -Makes sure that two `/' characters never occur next to each -other. Also all occurrences of `..' and `.' are suitably -processed. So \"+inbox/../news\" will be normalized to \"+news\". - -If optional argument EMPTY-STRING-OKAY is nil then a `+' is added -at the front if FOLDER lacks one. If non-nil and FOLDER is the -empty string then nothing is added. - -If optional argument DONT-REMOVE-TRAILING-SLASH is non-nil then a -trailing `/' if present is retained (if present), otherwise it is -removed. - -If optional argument RETURN-NIL-IF-FOLDER-EMPTY is non-nil, then -return nil if FOLDER is \"\" or \"+\". This is useful when -normalizing the folder for the `folders' command which displays -the directories in / if passed \"+\". This is usually not -desired. If this argument is non-nil, then EMPTY-STRING-OKAY has -no effect." - (cond - ((if (and (or (equal folder "+") (equal folder "")) - return-nil-if-folder-empty) - (setq folder nil))) - ((stringp folder) - ;; Replace two or more consecutive '/' characters with a single '/' - (while (string-match "//" folder) - (setq folder (replace-match "/" nil t folder))) - (let* ((length (length folder)) - (trailing-slash-present (and (> length 0) - (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 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) - (cond ((and (equal component "..") result) - (pop result)) - ((equal component "..")) - ((equal component ".")) - (t (push component result)))) - (setq folder "") - (dolist (component result) - (setq folder (concat component "/" folder))) - ;; 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)))))) - (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)))))) - folder) - -(defmacro mh-children-p (folder) - "Return t if FOLDER from sub-folders cache has children." -;; The car of folder is the name, and the cdr is either t or some -;; sort of count that I do not understand. It's too small to be the -;; number of messages in the sub-folders and too large to be the -;; number of sub-folders. XXX - `(if (cdr ,folder) - t - nil)) - -;;;###mh-autoload -(defun mh-folder-list (folder) - "Return FOLDER and its descendants. -FOLDER may have a + prefix. Returns a list of strings without the -+ prefix. If FOLDER is nil, then all folders are considered. For -example, if your Mail directory only contains the folders +inbox, -+outbox, +lists, and +lists/mh-e, then - - (mh-folder-list nil) - => (\"inbox\" \"lists\" \"lists/mh-e\" \"outbox\") - (mh-folder-list \"+lists\") - => (\"lists\" \"lists/mh-e\") - -Respects the value of `mh-recursive-folders-flag'. If this flag -is nil, and the sub-folders have not been explicitly viewed, then -they will not be returned." - (let ((folder-list)) - ;; Normalize folder. Strip leading + and trailing slash(es). If no - ;; folder is specified, ensure it is nil to avoid adding the - ;; folder to the folder-list and adding a slash to it. - (when folder - (setq folder (replace-regexp-in-string "^\\+" "" folder)) - (setq folder (replace-regexp-in-string "/+$" "" folder)) - (if (equal folder "") - (setq folder nil))) - ;; Add provided folder to list, unless all folders are asked for. - ;; Then append slash to separate sub-folders. - (unless (null folder) - (setq folder-list (list folder)) - (setq folder (concat folder "/"))) - (cl-loop for f in (mh-sub-folders folder) do - (setq folder-list - (append folder-list - (if (mh-children-p f) - (mh-folder-list (concat folder (car f))) - (list (concat folder (car f))))))) - folder-list)) - -;;;###mh-autoload -(defun mh-sub-folders (folder &optional add-trailing-slash-flag) - "Find the subfolders of FOLDER. -The function avoids running folders unnecessarily by caching the -results of the actual folders call. - -If optional argument ADD-TRAILING-SLASH-FLAG is non-nil then a -slash is added to each of the sub-folder names that may have -nested folders within them." - ;; In most cases we want to remove a trailing slash. We keep the - ;; slash for "+/", because it refers to folders in the system root - ;; directory, whereas "+" refers to the user's top-level folders. - (let* ((folder (mh-normalize-folder-name folder nil - (string= folder "+/") - t)) - (match (gethash folder mh-sub-folders-cache 'no-result)) - (sub-folders (cond ((eq match 'no-result) - (setf (gethash folder mh-sub-folders-cache) - (mh-sub-folders-actual folder))) - (t match)))) - (if add-trailing-slash-flag - (mapcar (lambda (x) - (if (cdr x) (cons (concat (car x) "/") (cdr x)) x)) - sub-folders) - sub-folders))) - -;; FIXME: This function does not do well if FOLDER does not exist. It -;; then changes the context to that folder which causes problems down -;; the line. Since a folder in the cache could later be deleted, it -;; would be good for mh-sub-folders-actual to return nil in this case -;; so that mh-sub-folders could delete it from the cache. This -;; function could protect itself by using a temporary context. -(defun mh-sub-folders-actual (folder) - "Execute the command folders to return the sub-folders of FOLDER. -Filters out the folder names that start with \".\" so that -directories that aren't usually mail folders are hidden. -Expects FOLDER to have already been normalized with - (mh-normalize-folder-name folder nil nil t)" - (let ((arg-list `(,(expand-file-name "folders" mh-progs) - nil (t nil) nil "-noheader" "-norecurse" "-nototal" - ,@(if (stringp folder) (list folder) ()))) - (current-folder (concat - (with-temp-buffer - (call-process (expand-file-name "folder" mh-progs) - nil '(t nil) nil "-fast") - (buffer-substring (point-min) (1- (point-max)))) - "+"))) - (with-temp-buffer - (apply #'call-process arg-list) - (mh-sub-folders-parse folder current-folder)))) - -(defun mh-sub-folders-parse (folder current-folder) - "Parse the results of \"folders FOLDER\" and return a list of sub-folders. -CURRENT-FOLDER is the result of \"folder -fast\". -FOLDER will be nil or start with '+'; CURRENT-FOLDER will end with '+'. -This function is a testable helper of `mh-sub-folders-actual'." - (let ((results ())) - (goto-char (point-min)) - (while (not (and (eolp) (bolp))) - (goto-char (line-end-position)) - (let ((start-pos (line-beginning-position)) - (has-pos (search-backward " has " - (line-beginning-position) t))) - (when (integerp has-pos) - (while (equal (char-after has-pos) ? ) - (cl-decf has-pos)) - (cl-incf has-pos) - (while (equal (char-after start-pos) ? ) - (cl-incf start-pos)) - (let* ((name (buffer-substring start-pos has-pos)) - (first-char (aref name 0)) - (second-char (and (length> name 1) (aref name 1))) - (last-char (aref name (1- (length name))))) - (unless (member first-char '(?. ?# ?,)) - (when (and (equal last-char ?+) (equal name current-folder)) - (setq name (substring name 0 (1- (length name))))) - ;; nmh outputs double slash in root folder, e.g., "//tmp" - (when (and (equal first-char ?/) (equal second-char ?/)) - (setq name (substring name 1))) - (push - (cons name - (search-forward "(others)" (line-end-position) t)) - results)))) - (forward-line 1))) - (setq results (nreverse results)) - (when (stringp folder) - (setq results (cdr results)) - (let ((folder-name-len (length (format "%s/" (substring folder 1))))) - (when (equal "+/" folder) - ;; folder "+/" includes a trailing slash - (cl-decf folder-name-len)) - (setq results (mapcar (lambda (f) - (cons (substring (car f) folder-name-len) - (cdr f))) - results)))) - results)) - -;;;###mh-autoload -(defun mh-remove-from-sub-folders-cache (folder) - "Remove FOLDER and its parent from `mh-sub-folders-cache'. -FOLDER should be unconditionally removed from the cache. Also the -last ancestor of FOLDER present in the cache must be removed as -well. - -To see why this is needed assume we have a folder +foo which has -a single sub-folder qux. Now we create the folder +foo/bar/baz. -Here we will need to invalidate the cached sub-folders of +foo, -otherwise completion on +foo won't tell us about the option -+foo/bar!" - (remhash folder mh-sub-folders-cache) - (cl-block ancestor-found - (let ((parent folder) - (one-ancestor-found nil) - last-slash) - (while (setq last-slash (mh-search-from-end ?/ parent)) - (setq parent (substring parent 0 last-slash)) - (unless (eq (gethash parent mh-sub-folders-cache 'none) 'none) - (remhash parent mh-sub-folders-cache) - (if one-ancestor-found - (cl-return-from ancestor-found) - (setq one-ancestor-found t)))) - (remhash nil mh-sub-folders-cache)))) - - - -;;; Folder Utilities - -;;;###mh-autoload -(defun mh-folder-name-p (name) - "Return non-nil if NAME is the name of a folder. -A name (a string or symbol) can be a folder name if it begins -with \"+\"." - (if (symbolp name) - (eq (aref (symbol-name name) 0) ?+) - (and (> (length name) 0) - (eq (aref name 0) ?+)))) - -;;;###mh-autoload -(defun mh-expand-file-name (filename &optional default) - "Expand FILENAME like `expand-file-name', but also handle MH folder names. -Any filename that starts with `+' is treated as a folder name. -See `expand-file-name' for description of DEFAULT." - (if (mh-folder-name-p filename) - (expand-file-name (substring filename 1) mh-user-path) - (expand-file-name filename default))) - -(defvar mh-folder-hist nil) - -;; Shush compiler. -(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) ;Why??? - -(defvar mh-speed-flists-inhibit-flag nil) - -;;;###mh-autoload -(defun mh-speed-flists-active-p () - "Check if speedbar is running with message counts enabled." - (and (featurep 'mh-speed) - (not mh-speed-flists-inhibit-flag) - (> (hash-table-count mh-speed-flists-cache) 0))) - -;;;###mh-autoload -(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 function that is used to filter the possible -choices. FLAG is nil to indicate `try-completion', t for -`all-completions', or the symbol lambda for `test-completion'. -See Info node `(elisp) Programmed Completion' for details." - (let* ((orig-name name) - ;; After normalization, name is nil, +, or +something. If a - ;; trailing slash is present, it is preserved. - (name (mh-normalize-folder-name name nil t)) - (last-slash (mh-search-from-end ?/ name)) - ;; nil if + or +folder; +folder/ if slash present. - (last-complete (if last-slash (substring name 0 (1+ last-slash)) nil)) - ;; Either +folder/remainder, +remainder, or "". - (remainder (cond (last-complete (substring name (1+ last-slash))) - (name (substring name 1)) - (t "")))) - (cond ((eq (car-safe flag) 'boundaries) - (cl-list* 'boundaries - (let ((slash (mh-search-from-end ?/ orig-name))) - (if slash (1+ slash) - (if (string-match "\\`\\+" orig-name) 1 0))) - (if (cdr flag) (string-search "/" (cdr flag))))) - ((eq flag nil) - (let ((try-res - (try-completion - remainder - (mh-sub-folders last-complete t) - predicate))) - (cond ((eq try-res nil) nil) - ((and (eq try-res t) (equal name orig-name)) t) - ((eq try-res t) name) - (t (concat (or last-complete "+") try-res))))) - ((eq flag t) - (all-completions - remainder (mh-sub-folders last-complete t) predicate)) - ((eq flag 'lambda) - ;; FIXME: if name starts with "/", `path' will end - ;; being a relative name without a leading + nor / !? --Stef - (let ((path (concat (unless (and (> (length name) 1) - (eq (aref name 1) ?/)) - mh-user-path) - (substring name 1)))) - (cond (mh-allow-root-folder-flag (file-directory-p path)) - ((equal path mh-user-path) nil) - (t (file-directory-p path)))))))) - -(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) - (mh-allow-root-folder-flag allow-root-folder-flag)) - (completing-read prompt 'mh-folder-completion-function nil nil nil - 'mh-folder-hist default)) - t)) - -;;;###mh-autoload -(defun mh-prompt-for-folder (prompt default can-create - &optional default-string allow-root-folder-flag) - "Prompt for a folder name with PROMPT. -Returns the folder's name as a string. DEFAULT is used if the -folder exists and the user types return. If the CAN-CREATE flag -is t, then a folder is created if it doesn't already exist. If -optional argument DEFAULT-STRING is non-nil, use it in the prompt -instead of DEFAULT. If ALLOW-ROOT-FOLDER-FLAG is non-nil then the -function will accept the folder +, which means all folders when -used in searching." - (if (null default) - (setq default "")) - (let* ((default-string (or default-string - (if (equal default "") nil default))) - (prompt (format-prompt "%s folder" default-string prompt)) - (mh-current-folder-name mh-current-folder) - read-name folder-name) - (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 "") - (and (equal read-name "+") (not allow-root-folder-flag))) - (setq read-name default)) - ((not (mh-folder-name-p read-name)) - (setq read-name (format "+%s" read-name)))) - (if (or (not read-name) (equal "" read-name)) - (error "No folder specified")) - (setq folder-name read-name) - (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 - can-create - (y-or-n-p - (format "Folder %s does not exist. Create it? " - folder-name))) - (message "Creating %s" folder-name) - (mh-exec-cmd-error nil "folder" folder-name) - (mh-remove-from-sub-folders-cache folder-name) - (when (and (boundp 'speedbar-buffer) speedbar-buffer) - (mh-speed-add-folder folder-name)) - (message "Creating %s...done" folder-name)) - (new-file-flag - (error "Folder %s does not exist" folder-name)) - ((not (file-directory-p (mh-expand-file-name folder-name))) - (error "%s is not a directory" - (mh-expand-file-name folder-name))))) - folder-name)) - - - -;;; Message Utilities - -;; Functions that would ordinarily be in mh-letter.el that are needed -;; by mh-show.el are found here in order to prevent the loading of -;; mh-letter.el until a message is actually composed. - -;;;###mh-autoload -(defun mh-in-header-p () - "Return non-nil if the point is in the header of a draft message." - (< (point) (mh-mail-header-end))) - -;;;###mh-autoload -(defun mh-extract-from-header-value () - "Extract From: string from header." - (save-excursion - (if (not (mh-goto-header-field "From:")) - nil - (skip-chars-forward " \t") - (buffer-substring-no-properties - (point) (progn (mh-header-field-end)(point)))))) - -;;;###mh-autoload -(defun mh-get-header-field (field) - "Find and return the body of FIELD in the mail header. -Returns the empty string if the field is not in the header of the -current buffer." - (if (mh-goto-header-field field) - (progn - (skip-chars-forward " \t") ;strip leading white space in body - (let ((start (point))) - (mh-header-field-end) - (buffer-substring-no-properties start (point)))) - "")) - -;;;###mh-autoload -(defun mh-goto-header-field (field) - "Move to FIELD in the message header. -Move to the end of the FIELD name, which should end in a colon. -Returns t if found, nil if not." - (goto-char (point-min)) - (let ((case-fold-search t) - (headers-end (save-excursion - (mh-goto-header-end 0) - (point)))) - (re-search-forward (format "^%s" field) headers-end t))) - -;;;###mh-autoload -(defun mh-goto-header-end (arg) - "Move the cursor ARG lines after the header." - (if (re-search-forward (concat "^\\(" (regexp-quote mh-mail-header-separator) - "\\)?$") nil nil) - (forward-line arg))) - -;;;###mh-autoload -(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 - ;; XXX: The following replaces a call to rfc822-goto-eoh. Occasionally, - ;; mail headers that MH-E has to read contains lines of the form: - ;; From xxx@yyy Mon May 10 11:48:07 2004 - ;; In this situation, rfc822-goto-eoh doesn't go to the end of the - ;; header. The replacement allows From_ lines in the mail header. - (goto-char (point-min)) - (cl-loop for p = (re-search-forward - "^\\([:\n]\\|[^: \t\n]+[ \t\n]\\)" nil 'move) - do (cond ((null p) (cl-return)) - (t (goto-char (match-beginning 0)) - (unless (looking-at "From ") (cl-return)) - (goto-char p)))) - (point))) - -;;;###mh-autoload -(defun mh-header-field-beginning () - "Move to the beginning of the current header field. -Handle RFC 822 (or later) continuation lines." - (beginning-of-line) - (while (looking-at "^[ \t]") - (forward-line -1))) - -;;;###mh-autoload -(defun mh-header-field-end () - "Move to the end of the current header field. -Handle RFC 822 (or later) continuation lines." - (forward-line 1) - (while (looking-at "^[ \t]") - (forward-line 1)) - (backward-char 1)) ;to end of previous line - -;;;###mh-autoload -(defun mh-letter-hide-all-skipped-fields () - "Hide all skipped fields." - (save-excursion - (goto-char (point-min)) - (save-restriction - (narrow-to-region (point) (mh-mail-header-end)) - (while (re-search-forward mh-letter-header-field-regexp nil t) - (if (mh-letter-skipped-header-field-p (match-string 1)) - (mh-letter-toggle-header-field-display -1) - (mh-letter-toggle-header-field-display 'long)) - (beginning-of-line 2))))) - -;;;###mh-autoload -(defun mh-letter-skipped-header-field-p (field) - "Check if FIELD is to be skipped." - (let ((field (downcase field))) - (cl-loop for x in mh-compose-skipped-header-fields - when (equal (downcase x) field) return t - finally return nil))) - -(defvar mh-hidden-header-keymap - (let ((map (make-sparse-keymap))) - (define-key map [mouse-2] #'mh-letter-toggle-header-field-display-button) - map)) - -;;;###mh-autoload -(defun mh-letter-toggle-header-field-display (arg) - "Toggle display of header field at point. - -Use this command to display truncated header fields. This command -is a toggle so entering it again will hide the field. This -command takes a prefix argument ARG: if negative then the field -is hidden, if positive then the field is displayed." - (interactive (list nil)) - (when (and (mh-in-header-p) - (progn - (end-of-line) - (re-search-backward mh-letter-header-field-regexp nil t))) - (let ((buffer-read-only nil) - (modified-flag (buffer-modified-p)) - (begin (point)) - end) - (end-of-line) - (setq end (1- (if (re-search-forward "^[^ \t]" nil t) - (match-beginning 0) - (point-max)))) - (goto-char begin) - ;; Make it clickable... - (add-text-properties begin end `(keymap ,mh-hidden-header-keymap - mouse-face highlight)) - (unwind-protect - (cond ((or (and (not arg) - (text-property-any begin end 'invisible 'vanish)) - (and (numberp arg) - (>= arg 0)) - (and (eq arg 'long) - (> (line-beginning-position 5) end))) - (remove-text-properties begin end '(invisible nil)) - (search-forward ":" (line-end-position) t) - (mh-letter-skip-leading-whitespace-in-header-field)) - ;; XXX Redesign to make usable by user. Perhaps use a positive - ;; numeric prefix to make that many lines visible. - ((eq arg 'long) - (end-of-line 4) - (mh-letter-truncate-header-field end) - (beginning-of-line)) - (t (end-of-line) - (mh-letter-truncate-header-field end) - (beginning-of-line))) - (set-buffer-modified-p modified-flag))))) - -;;;###mh-autoload -(defun mh-letter-skip-leading-whitespace-in-header-field () - "Skip leading whitespace in a header field. -If the header field doesn't have at least one space after the -colon then a space character is added." - (let ((need-space t)) - (while (memq (char-after) '(?\t ?\ )) - (forward-char) - (setq need-space nil)) - (when need-space (insert " ")))) - -(defun mh-letter-truncate-header-field (end) - "Replace text from current line till END with an ellipsis. -If the current line is too long truncate a part of it as well." - (let ((max-len (min (window-width) 62))) - (when (> (+ (current-column) 4) max-len) - (backward-char (- (+ (current-column) 5) max-len))) - (when (> end (point)) - (add-text-properties (point) end '(invisible vanish))))) - -;;;###mh-autoload -(defun mh-signature-separator-p () - "Return non-nil if buffer includes \"^-- $\"." - (save-excursion - (goto-char (point-min)) - (re-search-forward mh-signature-separator-regexp nil t))) - -;;;###mh-autoload -(define-obsolete-function-alias 'mh-colors-available-p #'display-color-p "29.1") - -(provide 'mh-utils) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-utils.el ends here diff --git a/lisp/mh-e/mh-xface.el b/lisp/mh-e/mh-xface.el deleted file mode 100644 index 83269146c41..00000000000 --- a/lisp/mh-e/mh-xface.el +++ /dev/null @@ -1,420 +0,0 @@ -;;; mh-xface.el --- MH-E X-Face and Face header field display -*- lexical-binding: t; -*- - -;; Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc. - -;; Author: Bill Wohler -;; 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 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;;; Code: - -(require 'mh-e) - -(autoload 'mail-header-parse-address "mail-parse") -(autoload 'message-fetch-field "message") - -(defvar mh-show-xface-function #'mh-face-display-function - "Determine at run time what function should be called to display X-Face.") -(make-obsolete-variable 'mh-show-xface-function nil "29.1") - -(defvar mh-uncompface-executable (executable-find "uncompface")) - - - -;;; X-Face Display - -;;;###mh-autoload -(defun mh-show-xface () - "Display X-Face." - (when (and window-system mh-show-use-xface-flag - (or mh-decode-mime-flag mh-mhl-format-file - mh-clean-message-header-flag)) - (mh-face-display-function))) - -(defun mh-face-display-function () - "Display a Face, X-Face, or X-Image-URL header field. -If more than one of these are present, then the first one found -in this order is used." - (save-restriction - (goto-char (point-min)) - (re-search-forward "\n\n" (point-max) t) - (narrow-to-region (point-min) (point)) - (let* ((case-fold-search t) - (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)) - (t (cl-multiple-value-setq (type raw) - (cl-values-list (mh-picon-get-image))))) - (when type - (goto-char (point-min)) - (when (re-search-forward "^from:" (point-max) t) - (if (eq type 'url) - (mh-x-image-url-display url) - (insert-image (create-image - raw type t - :foreground - (face-foreground 'mh-show-xface nil t) - :background - (face-background 'mh-show-xface nil t)) - " "))))))) - -(defun mh-face-to-png (data) - "Convert base64 encoded DATA to png image." - (with-temp-buffer - (set-buffer-multibyte nil) - (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 - (set-buffer-multibyte nil) - (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"))) - - - -;;; Picon Display - -;; XXX: This should be customizable. As a side-effect of setting this -;; variable, arrange to reset mh-picon-existing-directory-list to 'unset. -(defvar mh-picon-directory-list - '("~/.picons" "~/.picons/users" "~/.picons/usenix" "~/.picons/news" - "~/.picons/domains" "~/.picons/misc" - "/usr/share/picons/" "/usr/share/picons/users" "/usr/share/picons/usenix" - "/usr/share/picons/news" "/usr/share/picons/domains" - "/usr/share/picons/misc") - "List of directories where picons reside. -The directories are searched for in the order they appear in the list.") - -(defvar mh-picon-existing-directory-list 'unset - "List of directories to search in.") - -(defvar mh-picon-cache (make-hash-table :test #'equal)) - -(defvar mh-picon-image-types - (cl-loop for type in '(xpm xbm gif) - when (ignore-errors - (image-type-available-p type)) - collect type)) - -(autoload 'message-tokenize-header "sendmail") - -(defun mh-picon-get-image () - "Find the best possible match and return contents." - (mh-picon-set-directory-list) - (save-restriction - (let* ((from-field (ignore-errors (car (message-tokenize-header - (mh-get-header-field "from:"))))) - (from (car (ignore-errors - (mail-header-parse-address from-field)))) - (host (and from - (string-match "\\([^+]*\\)\\(\\+.*\\)?@\\(.*\\)" from) - (downcase (match-string 3 from)))) - (user (and host (downcase (match-string 1 from)))) - (canonical-address (format "%s@%s" user host)) - (cached-value (gethash canonical-address mh-picon-cache)) - (host-list (and host (delete "" (split-string host "\\."))))) - (cond - (cached-value cached-value) - ((not host-list) nil) - (t - (let ((match - (cl-block loop - ;; u@h search - (dolist (dir mh-picon-existing-directory-list) - (cl-loop for type in mh-picon-image-types - ;; [path]user@host - for file1 = (format "%s/%s.%s" - dir canonical-address type) - when (file-exists-p file1) - do (cl-return-from loop file1) - ;; [path]user - for file2 = (format "%s/%s.%s" dir user type) - when (file-exists-p file2) - do (cl-return-from loop file2) - ;; [path]host - for file3 = (format "%s/%s.%s" dir host type) - when (file-exists-p file3) - do (cl-return-from loop file3))) - ;; facedb search - ;; Search order for user@foo.net: - ;; [path]net/foo/user - ;; [path]net/foo/user/face - ;; [path]net/user - ;; [path]net/user/face - ;; [path]net/foo/unknown - ;; [path]net/foo/unknown/face - ;; [path]net/unknown - ;; [path]net/unknown/face - (dolist (u (list user "unknown")) - (dolist (dir mh-picon-existing-directory-list) - (cl-loop for x on host-list by #'cdr - for y = (mh-picon-generate-path x u dir) - do (cl-loop for type in mh-picon-image-types - for z1 = (format "%s.%s" y type) - when (file-exists-p z1) - do (cl-return-from loop z1) - for z2 = (format "%s/face.%s" - y type) - when (file-exists-p z2) - do (cl-return-from loop z2)))))))) - (setf (gethash canonical-address mh-picon-cache) - (mh-picon-file-contents match)))))))) - -(defun mh-picon-set-directory-list () - "Update `mh-picon-existing-directory-list' if needed." - (when (eq mh-picon-existing-directory-list 'unset) - (setq mh-picon-existing-directory-list - (cl-loop for x in mh-picon-directory-list - when (file-directory-p x) collect x)))) - -(defun mh-picon-generate-path (host-list user directory) - "Generate the image file path. -HOST-LIST is the parsed host address of the email address, USER -the username and DIRECTORY is the directory relative to which the -path is generated." - (cl-loop with acc = "" - for elem in host-list - do (setq acc (format "%s/%s" elem acc)) - finally return (format "%s/%s%s" directory acc user))) - -(defun mh-picon-file-contents (file) - "Return details about FILE. -A list of consisting of a symbol for the type of the file and the -file contents as a string is returned. If FILE is nil, then both -elements of the list are nil." - (if (stringp file) - (with-temp-buffer - (set-buffer-multibyte nil) - (let ((type (and (string-match ".*\\.\\(...\\)$" file) - (intern (match-string 1 file))))) - (insert-file-contents-literally file) - (list type (buffer-string)))) - (list nil nil))) - - - -;;; X-Image-URL Display - -(defvar mh-x-image-scaling-function - (cond ((executable-find "convert") - 'mh-x-image-scale-with-convert) - ((and (executable-find "anytopnm") (executable-find "pnmscale") - (executable-find "pnmtopng")) - 'mh-x-image-scale-with-pnm) - (t 'ignore)) - "Function to use to scale image to proper size.") - -(defun mh-x-image-scale-with-pnm (input output) - "Scale image in INPUT file and write to OUTPUT file using pnm tools." - (let ((res (shell-command-to-string - (format "anytopnm < %s | pnmscale -xysize 96 48 | pnmtopng > %s" - input output)))) - (unless (equal res "") - (delete-file output)))) - -(defun mh-x-image-scale-with-convert (input output) - "Scale image in INPUT file and write to OUTPUT file using ImageMagick." - (call-process "convert" nil nil nil "-geometry" "96x48" input output)) - -(defvar mh-wget-executable nil) -(defvar mh-wget-choice - (or (and (setq mh-wget-executable (executable-find "wget")) 'wget) - (and (setq mh-wget-executable (executable-find "fetch")) 'fetch) - (and (setq mh-wget-executable (executable-find "curl")) 'curl))) -(defvar mh-wget-option - (cdr (assoc mh-wget-choice '((curl . "-o") (fetch . "-o") (wget . "-O"))))) -(defvar mh-x-image-temp-file nil) -(defvar mh-x-image-url nil) -(defvar mh-x-image-marker nil) -(defvar mh-x-image-url-cache-file nil) - -(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)) - (state (mh-x-image-get-download-state cache-filename)) - (marker (point-marker))) - (setq-local mh-x-image-marker marker) - (cond ((not (mh-x-image-url-sane-p url))) - ((eq state 'ok) - (mh-x-image-display cache-filename marker)) - ((or (not mh-wget-executable) - (eq mh-x-image-scaling-function 'ignore))) - ((eq state 'never)) - ((not mh-fetch-x-image-url) - (set-marker marker nil)) - ((eq state 'try-again) - (mh-x-image-set-download-state cache-filename nil) - (mh-x-image-url-fetch-image url cache-filename marker - 'mh-x-image-scale-and-display)) - ((and (eq mh-fetch-x-image-url 'ask) - (not (y-or-n-p (format "Fetch %s? " url)))) - (mh-x-image-set-download-state cache-filename 'never)) - ((eq state nil) - (mh-x-image-url-fetch-image url cache-filename marker - 'mh-x-image-scale-and-display))))) - -(defvar mh-x-image-cache-directory nil - "Directory where X-Image-URL images are cached.") - -;;;###mh-autoload -(defun mh-set-x-image-cache-directory (directory) - "Set the DIRECTORY where X-Image-URL images are cached. -This is only done if `mh-x-image-cache-directory' is nil." - ;; XXX This is the code that used to be in find-user-path. Is there - ;; a good reason why the variable is set conditionally? Do we expect - ;; the user to have set this variable directly? - (unless mh-x-image-cache-directory - (setq mh-x-image-cache-directory directory))) - -(defun mh-x-image-url-cache-canonicalize (url) - "Canonicalize URL. -Replace the ?/ character with a ?! character and append .png. -Also replaces special characters with `url-hexify-string' -since not all characters, such as :, are valid within Windows -filenames. In addition, replaces * with %2a. See URL -`https://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/iitemnamelimits/GetValidCharacters.asp'." - (format "%s/%s.png" mh-x-image-cache-directory - (replace-regexp-in-string - "\\*" "%2a" - (url-hexify-string - (with-temp-buffer - (insert url) - (mh-replace-string "/" "!") - (buffer-string)))))) - -(defun mh-x-image-get-download-state (file) - "Check the state of FILE by following any symbolic links." - (unless (file-exists-p mh-x-image-cache-directory) - (call-process "mkdir" nil nil nil mh-x-image-cache-directory)) - (cond ((file-symlink-p file) - (intern (file-name-nondirectory (file-chase-links file)))) - ((not (file-exists-p file)) nil) - (t 'ok))) - -(defun mh-x-image-set-download-state (file data) - "Setup a symbolic link from FILE to DATA." - (if data - (make-symbolic-link (symbol-name data) file t) - (delete-file file))) - -(defun mh-x-image-url-sane-p (url) - "Check if URL is something sensible." - (let ((len (length url))) - (cond ((> len 100) nil) - ((and (>= len 5) - (equal (substring url 0 5) "http:") t)) - ((and (>= len 6) - (equal (substring url 0 6) "https:") t)) - (t nil)))) - -(defun mh-x-image-display (image marker) - "Display IMAGE at MARKER." - (with-current-buffer (marker-buffer marker) - (let ((inhibit-read-only t) - (buffer-modified-flag (buffer-modified-p))) - (unwind-protect - (when (and (file-readable-p image) (not (file-symlink-p image)) - (eq marker mh-x-image-marker)) - (goto-char marker) - (insert-image (create-image image 'png))) - (set-buffer-modified-p buffer-modified-flag))))) - -(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 mh-wget-executable - (let ((buffer (generate-new-buffer mh-temp-fetch-buffer)) - (filename (make-temp-file "mhe-fetch"))) - (with-current-buffer buffer - (setq-local mh-x-image-url-cache-file cache-file) - (setq-local mh-x-image-marker marker) - (setq-local mh-x-image-temp-file filename)) - (set-process-sentinel - (start-process "*mh-x-image-url-fetch*" buffer - mh-wget-executable mh-wget-option filename url) - sentinel)) - ;; Temporary failure - (mh-x-image-set-download-state cache-file 'try-again))) - -(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) - (with-current-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)) - (cond - ;; Check if we have `convert' - ((eq mh-x-image-scaling-function 'ignore) - (message "The \"convert\" program is needed to display X-Image-URL") - (mh-x-image-set-download-state cache-filename 'try-again)) - ;; Scale fetched image - ((and (funcall mh-x-image-scaling-function temp-file cache-filename) - nil)) - ;; Attempt to display image if we have it - ((file-exists-p cache-filename) - (mh-x-image-display cache-filename marker)) - ;; We didn't find the image. Should we try to display it the next time? - (t (mh-x-image-set-download-state cache-filename 'try-again))) - (ignore-errors - (set-marker marker nil) - (delete-process process) - (kill-buffer wget-buffer) - (delete-file temp-file))))) - -(provide 'mh-xface) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-xface.el ends here diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 1c636a5fab9..9eac9b4a37c 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -1184,7 +1184,8 @@ styles for specific categories, such as files, buffers, etc." (predicate-description (sort-function . identity)) (search (sort-function . identity)) (keybinding (sort-function . minibuffer-sort-alphabetically)) - (function (sort-function . minibuffer-sort-alphabetically) + (function (styles partial-completion substring) + (sort-function . minibuffer-sort-alphabetically) (affixation-function . minibuffer-function-affixation)) (library (sort-function . minibuffer-sort-alphabetically))) "Default settings for specific completion categories. diff --git a/lisp/msb.el b/lisp/msb.el index 4252d631335..eab7ba7423b 100644 --- a/lisp/msb.el +++ b/lisp/msb.el @@ -108,7 +108,6 @@ "WWW (%d)") ((or (memq major-mode '(rmail-mode rmail-edit-mode vm-summary-mode vm-mode mail-mode)) - (memq major-mode '(mh-letter-mode mh-show-mode mh-folder-mode)) (memq major-mode '(gnus-summary-mode message-mode gnus-group-mode gnus-article-mode score-mode gnus-browse-killed-mode))) @@ -159,7 +158,6 @@ "WWW (%d)") ((or (memq major-mode '(rmail-mode rmail-edit-mode vm-summary-mode vm-mode mail-mode)) - (memq major-mode '(mh-letter-mode mh-show-mode mh-folder-mode)) (memq major-mode '(gnus-summary-mode message-mode gnus-group-mode gnus-article-mode score-mode gnus-browse-killed-mode))) diff --git a/lisp/obsolete/mh-compat.el b/lisp/obsolete/mh-compat.el deleted file mode 100644 index ca72bf3b22d..00000000000 --- a/lisp/obsolete/mh-compat.el +++ /dev/null @@ -1,136 +0,0 @@ -;;; mh-compat.el --- make MH-E compatible with various versions of Emacs -*- lexical-binding: t; -*- - -;; Copyright (C) 2006-2024 Free Software Foundation, Inc. - -;; Author: Bill Wohler -;; Keywords: mail -;; See: mh-e.el -;; Obsolete-since: 29.1 - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;;; Code: - -;; This is a good place to gather code that is used for compatibility -;; between different versions of Emacs. Please document which versions -;; of Emacs that the defsubst, defalias, or defmacro applies. That -;; way, it's easy to occasionally go through this file and see which -;; macros we can retire. - -;; Please use mh-gnus.el when providing compatibility with different -;; versions of Gnus. - -;; Items are listed alphabetically. - -(eval-when-compile (require 'mh-acros)) - -(define-obsolete-function-alias 'mh-require #'require "29.1") -(define-obsolete-function-alias 'mh-assoc-string #'assoc-string "29.1") -(define-obsolete-function-alias 'mh-cancel-timer #'cancel-timer "29.1") - -(define-obsolete-function-alias 'mh-display-color-cells - #'display-color-cells "29.1") - -(defmacro mh-display-completion-list (completions &optional common-substring) - "Display the list of COMPLETIONS. -See documentation for `display-completion-list' for a description of the -arguments COMPLETIONS. -The optional argument COMMON-SUBSTRING, if non-nil, should be a string -specifying a common substring for adding the faces -`completions-first-difference' and `completions-common-part' to -the completions." - (declare (obsolete nil "29.1")) - `(display-completion-list - (completion-hilit-commonality ,completions - ,(length common-substring) nil))) - -(define-obsolete-function-alias 'mh-face-foreground - #'face-foreground "29.1") - -(define-obsolete-function-alias 'mh-face-background - #'face-background "29.1") - -(define-obsolete-function-alias 'mh-font-lock-add-keywords - #'font-lock-add-keywords "29.1") - -;; Not preloaded in without-x builds. -(declare-function image-load-path-for-library "image") -(define-obsolete-function-alias 'mh-image-load-path-for-library - #'image-load-path-for-library "29.1") - -;; Not preloaded in without-x builds. -(declare-function image-search-load-path "image") -(define-obsolete-function-alias 'mh-image-search-load-path - #'image-search-load-path "29.1") - -(define-obsolete-function-alias 'mh-line-beginning-position - #'line-beginning-position "29.1") - -(define-obsolete-function-alias 'mh-line-end-position - #'line-end-position "29.1") - -(require 'mailabbrev) -(define-obsolete-function-alias 'mh-mail-abbrev-make-syntax-table - #'mail-abbrev-make-syntax-table "29.1") - -(define-obsolete-function-alias 'mh-define-obsolete-variable-alias - #'define-obsolete-variable-alias "29.1") - -(define-obsolete-function-alias 'mh-make-obsolete-variable - #'make-obsolete-variable "29.1") - -(define-obsolete-function-alias 'mh-match-string-no-properties - #'match-string-no-properties "29.1") - -(define-obsolete-function-alias 'mh-replace-regexp-in-string - #'replace-regexp-in-string "29.1") - -(define-obsolete-function-alias 'mh-test-completion - #'test-completion "29.1") - -(defconst mh-url-unreserved-chars - '( - ?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z - ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z - ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 - ?- ?_ ?. ?! ?~ ?* ?' ?\( ?\)) - "A list of characters that are _NOT_ reserved in the URL spec. -This is taken from RFC 2396.") -(make-obsolete-variable 'mh-url-unreserved-chars 'url-unreserved-chars "29.1") - -(define-obsolete-function-alias 'mh-url-hexify-string - #'url-hexify-string "29.1") - -(define-obsolete-function-alias 'mh-view-mode-enter - #'view-mode-enter "29.1") - -(define-obsolete-function-alias 'mh-window-full-height-p - #'window-full-height-p "29.1") - -(defmacro mh-write-file-functions () - "Return `write-file-functions'." - (declare (obsolete nil "29.1")) - ''write-file-functions) - -(provide 'mh-compat) - -;; Local Variables: -;; sentence-end-double-space: nil -;; End: - -;;; mh-compat.el ends here diff --git a/lisp/obsolete/terminal.el b/lisp/obsolete/terminal.el index 13667589c9e..f5382ec8faf 100644 --- a/lisp/obsolete/terminal.el +++ b/lisp/obsolete/terminal.el @@ -43,7 +43,6 @@ ;;>> One probably wants to do setenv MORE -c when running with ;;>> more-processing enabled. -(require 'ehelp) (require 'shell) (defgroup terminal nil @@ -124,8 +123,6 @@ performance." (define-key map "x" #'te-escape-extended-command) ;;>> What use is this? Why is it in the default terminal-emulator map? (define-key map "w" #'te-edit) - (define-key map "?" #'te-escape-help) - (define-key map (char-to-string help-char) #'te-escape-help) (setq terminal-escape-map map))) (defvar te-escape-command-alist nil) @@ -148,7 +145,6 @@ performance." ("Switch To Buffer" . switch-to-buffer) ("Other Window" . other-window) ("Kill Buffer" . kill-buffer) - ("Help" . te-escape-help) ("Set Redisplay Interval" . te-set-redisplay-interval) ))) @@ -157,7 +153,6 @@ performance." nil (let ((map (make-sparse-keymap))) (define-key map [t] #'te-more-break-unread) - (define-key map (char-to-string help-char) #'te-more-break-help) (define-key map " " #'te-more-break-resume) (define-key map "\C-l" #'redraw-display) (define-key map "\C-o" #'te-more-break-flush-pending-output) @@ -205,13 +200,9 @@ performance." (use-local-map terminal-escape-map) (setq s (read-key-sequence (if current-prefix-arg - (format "Emacs Terminal escape[%s for help]> %d " - (substitute-command-keys - "\\\\[te-escape-help]") + (format "Emacs Terminal escape> %d " (prefix-numeric-value current-prefix-arg)) - (format "Emacs Terminal escape[%s for help]> " - (substitute-command-keys - "\\\\[te-escape-help]")))))) + "Emacs Terminal escape> ")))) (use-global-map global) (use-local-map local)) @@ -231,44 +222,6 @@ performance." )) - -(defun te-escape-help () - "Provide help on commands available after terminal-escape-char is typed." - (interactive) - (message "Terminal emulator escape help...") - (let ((char (single-key-description terminal-escape-char))) - (with-electric-help - (function (lambda () - (princ (format "Terminal-emulator escape, invoked by \"%s\" -Type \"%s\" twice to send a single \"%s\" through. - -Other chars following \"%s\" are interpreted as follows:\n" - char char char char)) - - (princ (substitute-command-keys "\\{terminal-escape-map}\n")) - (princ (format "\nSubcommands of \"%s\" (%s)\n" - (where-is-internal 'te-escape-extended-command - terminal-escape-map t) - 'te-escape-extended-command)) - (let ((l (sort (copy-sequence te-escape-command-alist) - (function (lambda (a b) - (string< (car a) (car b))))))) - (while l - (let ((doc (or (documentation (cdr (car l))) - "Not documented"))) - (if (string-match "\n" doc) - ;; just use first line of documentation - (setq doc (substring doc 0 (match-beginning 0)))) - (princ " \"") - (princ (car (car l))) - (princ "\":\n ") - (princ doc) - (write-char ?\n)) - (setq l (cdr l)))) - nil))))) - - - (defun te-escape-extended-command () (interactive) (let ((c (let ((completion-ignore-case t)) @@ -411,25 +364,6 @@ allowing the next page of output to appear" (message "Continuing from more break") (te-more-break-unwind)) -(defun te-more-break-help () - "Provide help on commands available in a terminal-emulator **MORE** break" - (interactive) - (message "Terminal-emulator more break help...") - (sit-for 0) - (with-electric-help - (function (lambda () - (princ "Terminal-emulator more break.\n\n") - (princ (format "Type \"%s\" (te-more-break-resume)\n%s\n" - (where-is-internal 'te-more-break-resume - terminal-more-break-map t) - (documentation 'te-more-break-resume))) - (princ (substitute-command-keys "\\{terminal-more-break-map}\n")) - (princ "Any other key is passed through to the program -running under the terminal emulator and disables more processing until -all pending output has been dealt with.") - nil)))) - - (defun te-more-break-advance-one-line () "Allow one more line of text to be output before doing another more break." (interactive) @@ -1146,11 +1080,7 @@ subprocess started." (setq inhibit-quit t) ;sport death (use-local-map terminal-map) (run-hooks 'terminal-mode-hook) - (message "Entering Emacs terminal-emulator... Type %s %s for help" - (single-key-description terminal-escape-char) - (mapconcat #'single-key-description - (where-is-internal #'te-escape-help terminal-escape-map t) - " "))) + (message "Entering Emacs terminal-emulator...")) (defun te-parse-program-and-args (s) diff --git a/lisp/org/ol-info.el b/lisp/org/ol-info.el index 2c2b48ebb88..ff9156c5296 100644 --- a/lisp/org/ol-info.el +++ b/lisp/org/ol-info.el @@ -129,10 +129,10 @@ If LINK is not an info link then DESC is returned." (defconst org-info-emacs-documents '("ada-mode" "auth" "autotype" "bovine" "calc" "ccmode" "cl" "dbus" "dired-x" - "ede" "ediff" "edt" "efaq-w32" "efaq" "eglot" "eieio" "eintr" + "ede" "ediff" "efaq-w32" "efaq" "eglot" "eieio" "eintr" "elisp" "emacs-gnutls" "emacs-mime" "emacs" "epa" "erc" "ert" "eshell" "eudc" "eww" "flymake" "forms" "gnus" "htmlfontify" "idlwave" "ido" "info" - "mairix-el" "message" "mh-e" "modus-themes" "newsticker" "nxml-mode" "octave-mode" + "mairix-el" "message" "modus-themes" "newsticker" "nxml-mode" "octave-mode" "org" "pcl-cvs" "pgg" "rcirc" "reftex" "remember" "sasl" "sc" "semantic" "ses" "sieve" "smtpmail" "speedbar" "srecode" "todo-mode" "tramp" "transient" "url" "use-package" "vhdl-mode" "vip" "viper" "vtable" "widget" "wisent" "woman") diff --git a/lisp/org/ol-mhe.el b/lisp/org/ol-mhe.el deleted file mode 100644 index b715f6a08b4..00000000000 --- a/lisp/org/ol-mhe.el +++ /dev/null @@ -1,222 +0,0 @@ -;;; ol-mhe.el --- Links to MH-E Messages -*- lexical-binding: t; -*- - -;; Copyright (C) 2004-2024 Free Software Foundation, Inc. - -;; Author: Thomas Baumann -;; Keywords: outlines, hypermedia, calendar, text -;; URL: https://orgmode.org -;; -;; This file is part of GNU Emacs. -;; -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;; Commentary: - -;; This file implements links to MH-E messages from within Org. -;; Org mode loads this module by default - if this is not what you want, -;; configure the variable `org-modules'. - -;;; Code: - -(require 'org-macs) -(org-assert-version) - -(require 'org-macs) -(require 'ol) - -;; Customization variables - -(defcustom org-mhe-search-all-folders nil - "Non-nil means the search for the mh-message may extend to all folders. -When non-nil, the search for a message will extend to all other -folders if it cannot be found in the folder given in the link. -Searching all folders may be slow with the default pick based -search but is very efficient with one of the other search engines -supported by MH-E." - :group 'org-link-follow - :type 'boolean) - -;; Declare external functions and variables -(declare-function mh-display-msg "mh-show" (msg-num folder-name)) -(declare-function mh-find-path "mh-utils" ()) -(declare-function mh-get-header-field "mh-utils" (field)) -(declare-function mh-get-msg-num "mh-utils" (error-if-no-message)) -(declare-function mh-header-display "mh-show" ()) -(declare-function mh-index-previous-folder "mh-search" ()) -(declare-function mh-normalize-folder-name "mh-utils" - (folder &optional empty-string-okay dont-remove-trailing-slash - return-nil-if-folder-empty)) -(declare-function mh-search "mh-search" - (folder search-regexp &optional redo-search-flag - window-config)) -(declare-function mh-search-choose "mh-search" (&optional searcher)) -(declare-function mh-show "mh-show" (&optional message redisplay-flag)) -(declare-function mh-show-buffer-message-number "mh-comp" (&optional buffer)) -(declare-function mh-show-header-display "mh-show" t t) -(declare-function mh-show-msg "mh-show" (msg)) -(declare-function mh-show-show "mh-show" t t) -(declare-function mh-visit-folder "mh-folder" (folder &optional - range index-data)) -(defvar mh-progs) -(defvar mh-current-folder) -(defvar mh-show-folder-buffer) -(defvar mh-index-folder) -(defvar mh-searcher) -(defvar mh-search-regexp-builder) - -;; Install the link type -(org-link-set-parameters "mhe" :follow #'org-mhe-open :store #'org-mhe-store-link) - -;; Implementation -(defun org-mhe-store-link (&optional _interactive?) - "Store a link to an MH-E folder or message." - (when (or (eq major-mode 'mh-folder-mode) - (eq major-mode 'mh-show-mode)) - (save-window-excursion - (let* ((from (org-mhe-get-header "From:")) - (to (org-mhe-get-header "To:")) - (message-id (org-mhe-get-header "Message-Id:")) - (subject (org-mhe-get-header "Subject:")) - (date (org-mhe-get-header "Date:")) - link desc) - (org-link-store-props :type "mh" :from from :to to :date date - :subject subject :message-id message-id) - (setq desc (org-link-email-description)) - (setq link (concat "mhe:" (org-mhe-get-message-real-folder) "#" - (org-unbracket-string "<" ">" message-id))) - (org-link-add-props :link link :description desc) - link)))) - -(defun org-mhe-open (path _) - "Follow an MH-E message link specified by PATH." - (let (folder article) - (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) - (error "Error in MH-E link")) - (setq folder (match-string 1 path) - article (match-string 3 path)) - (org-mhe-follow-link folder article))) - -;;; mh-e integration based on planner-mode -(defun org-mhe-get-message-real-folder () - "Return the name of the real folder for the current message. -So if you use sequences, it will now work." - (save-excursion - (let* ((folder - (if (eq major-mode 'mh-folder-mode) - mh-current-folder - ;; Refer to the show buffer - mh-show-folder-buffer)) - (end-index - (if (boundp 'mh-index-folder) - (min (length mh-index-folder) (length folder)))) - ) - ;; a simple test on mh-index-data does not work, because - ;; mh-index-data is always nil in a show buffer. - (if (and (boundp 'mh-index-folder) - (string= mh-index-folder (substring folder 0 end-index))) - (if (eq major-mode 'mh-show-mode) - (save-window-excursion - (let (pop-up-frames) - (when (buffer-live-p (get-buffer folder)) - (progn - (pop-to-buffer folder) - (org-mhe-get-message-folder-from-index) - ) - ))) - (org-mhe-get-message-folder-from-index) - ) - folder - ) - ))) - -(defun org-mhe-get-message-folder-from-index () - "Return the name of the message folder in an index folder buffer." - (save-excursion - (mh-index-previous-folder) - (if (re-search-forward "^\\(\\+.*\\)$" nil t) - (message "%s" (match-string 1))))) - -(defun org-mhe-get-message-folder () - "Return the name of the current message folder. -Be careful if you use sequences." - (save-excursion - (if (eq major-mode 'mh-folder-mode) - mh-current-folder - ;; Refer to the show buffer - mh-show-folder-buffer))) - -(defun org-mhe-get-message-num () - "Return the number of the current message. -Be careful if you use sequences." - (save-excursion - (if (eq major-mode 'mh-folder-mode) - (mh-get-msg-num nil) - ;; Refer to the show buffer - (mh-show-buffer-message-number)))) - -(defun org-mhe-get-header (header) - "Return the field for HEADER of the message in folder mode. -This will create a show buffer for the corresponding message. If -you have a better idea of how to do this then please let us know." - (let* ((folder (org-mhe-get-message-folder)) - (num (org-mhe-get-message-num)) - (buffer (get-buffer-create (concat "show-" folder))) - (header-field)) - (with-current-buffer buffer - (mh-display-msg num folder) - (if (eq major-mode 'mh-folder-mode) - (mh-header-display) - (mh-show-header-display)) - (set-buffer buffer) - (setq header-field (mh-get-header-field header)) - (if (eq major-mode 'mh-folder-mode) - (mh-show) - (mh-show-show)) - (org-trim header-field)))) - -(defun org-mhe-follow-link (folder article) - "Follow an MH-E link to FOLDER and ARTICLE. -If ARTICLE is nil FOLDER is shown. If the configuration variable -`org-mhe-search-all-folders' is t and `mh-searcher' is pick, -ARTICLE is searched in all folders. Indexed searches (swish++, -namazu, and others supported by MH-E) will always search in all -folders." - (require 'mh-e) - (require 'mh-search) - (require 'mh-utils) - (mh-find-path) - (if (not article) - (mh-visit-folder (mh-normalize-folder-name folder)) - (mh-search-choose) - (if (eq mh-searcher 'pick) - (progn - (setq article (org-link-add-angle-brackets article)) - (mh-search folder (list "--message-id" article)) - (when (and org-mhe-search-all-folders - (not (org-mhe-get-message-real-folder))) - (kill-buffer) - (mh-search "+" (list "--message-id" article)))) - (if mh-search-regexp-builder - (mh-search "+" (funcall mh-search-regexp-builder - (list (cons 'message-id article)))) - (mh-search "+" article))) - (if (org-mhe-get-message-real-folder) - (mh-show-msg 1) - (kill-buffer) - (error "Message not found")))) - -(provide 'ol-mhe) - -;;; ol-mhe.el ends here diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 11a1ecd01e8..52534950601 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -375,32 +375,32 @@ happens in interactive invocations." :type 'boolean :group 'lisp) +(defun elisp-fontify-symbol (type sym len bind) + (if (null bind) + (when-let ((face (cl-case type + (variable 'elisp-free-variable) + (function 'font-lock-function-call-face) + (defun 'font-lock-function-name-face) + (defvar 'font-lock-variable-name-face)))) + (add-face-text-property sym (+ sym len) face t)) + (add-face-text-property sym (+ sym len) + (if (equal sym bind) + 'elisp-binding-variable + 'elisp-bound-variable) + t) + (put-text-property sym (+ sym len 1) 'cursor-sensor-functions + ;; Get a fresh list with SYM hardcoded, + ;; so that the value is distinguishable + ;; from the value in adjacent regions. + (elisp-cursor-sensor sym)))) + (defun elisp-fontify-region-semantically (beg end) "Fontify symbols between BEG and END according to their semantics." (save-excursion (goto-char beg) (while (< (point) end) (ignore-errors - (scope - (lambda (type sym len bind) - (if (null bind) - (when-let ((face (cl-case type - (variable 'elisp-free-variable) - (function 'font-lock-function-call-face) - (defun 'font-lock-function-name-face) - (defvar 'font-lock-variable-name-face)))) - (add-face-text-property sym (+ sym len) face t)) - (add-face-text-property sym (+ sym len) - (if (equal sym bind) - 'elisp-binding-variable - 'elisp-bound-variable) - t) - (put-text-property sym (+ sym len 1) 'cursor-sensor-functions - ;; Get a fresh list with SYM hardcoded, - ;; so that the value is distinguishable - ;; from the value in adjacent regions. - (elisp-cursor-sensor sym)))) - (current-buffer)))))) + (scope #'elisp-fontify-symbol (current-buffer)))))) (defun elisp-fontify-region (beg end &optional loudly) "Fontify ELisp code between BEG and END. diff --git a/lisp/term.el b/lisp/term.el index 9a8dc25e1a2..cc896acaabf 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -304,7 +304,6 @@ (require 'cl-lib)) (require 'comint) ; Password regexp. (require 'ansi-color) -(require 'ehelp) (require 'ring) (require 'shell) @@ -674,8 +673,6 @@ Do not change it directly; use `term-set-escape-char' instead.") (define-key map "\C-u" (lookup-key (current-global-map) "\C-u")) (define-key map " " 'term-pager-page) (define-key map "\r" 'term-pager-line) - (define-key map "?" 'term-pager-help) - (define-key map "h" 'term-pager-help) (define-key map "b" 'term-pager-back-page) (define-key map "\177" 'term-pager-back-line) (define-key map "q" 'term-pager-discard) @@ -1022,8 +1019,7 @@ For custom keybindings purposes please note there is also ["Goto to beginning" term-pager-bob t] ["Goto to end" term-pager-eob t] ["Discard remaining output" term-pager-discard t] - ["Disable paging" term-pager-toggle t] - ["Help" term-pager-help t])) + ["Disable paging" term-pager-toggle t])) (defvar term-raw-escape-map (let ((map (make-sparse-keymap))) @@ -3874,33 +3870,6 @@ The top-most line is line 0." (interactive) (if (term-pager-enabled) (term-pager-disable) (term-pager-enable))) -(defun term-pager-help () - "Provide help on commands available in a terminal-emulator **MORE** break." - (interactive) - (message "Terminal-emulator pager break help...") - (sit-for 0) - (with-electric-help - (lambda () - (princ (substitute-command-keys -"\\\ -Terminal-emulator MORE break.\n\ -Type one of the following keys:\n\n\ -\\[term-pager-page]\t\tMove forward one page.\n\ -\\[term-pager-line]\t\tMove forward one line.\n\ -\\[universal-argument] N \\[term-pager-page]\tMove N pages forward.\n\ -\\[universal-argument] N \\[term-pager-line]\tMove N lines forward.\n\ -\\[universal-argument] N \\[term-pager-back-line]\tMove N lines back.\n\ -\\[universal-argument] N \\[term-pager-back-page]\t\tMove N pages back.\n\ -\\[term-pager-bob]\t\tMove to the beginning of the buffer.\n\ -\\[term-pager-eob]\t\tMove to the end of the buffer.\n\ -\\[term-pager-discard]\t\tKill pending output and kill process.\n\ -\\[term-pager-disable]\t\tDisable PAGER handling.\n\n\ -\\{term-pager-break-map}\n\ -Any other key is passed through to the program -running under the terminal emulator and disables pager processing until -all pending output has been dealt with.")) - nil))) - (defun term-pager-continue (new-count) (let ((process (get-buffer-process (current-buffer)))) (use-local-map term-pager-old-local-map) diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el index 74058b47907..f7b283b4afb 100644 --- a/lisp/textmodes/ispell.el +++ b/lisp/textmodes/ispell.el @@ -292,10 +292,8 @@ The following values are supported: nil Expand the minibuffer and display a short help message there for a couple of seconds. t Pop up a new buffer and display a short help message there - for a couple of seconds. - electric Pop up a new buffer and display a long help message there. - User can browse and then exit the help mode." - :type '(choice (const electric) (const :tag "off" nil) (const :tag "on" t))) + for a couple of seconds." + :type '(choice (const :tag "off" nil) (const :tag "on" t))) (defcustom ispell-quietly nil "Non-nil means suppress messages in `ispell-word'." @@ -2467,67 +2465,30 @@ Selections are: \\`C-l' Redraw screen. \\`C-r' Recursive edit. \\`C-z' Suspend Emacs or iconify frame." - - (if (equal ispell-help-in-bufferp 'electric) - (progn - (require 'ehelp) - (with-electric-help - (lambda () - ;;This shouldn't be necessary: with-electric-help needs - ;; an optional argument telling it about the smallest - ;; acceptable window-height of the help buffer. - ;;(if (< (window-height) 15) - ;; (enlarge-window - ;; (- 15 (ispell-adjusted-window-height)))) - (princ - (substitute-command-keys - "Selections are: - -\\`0'..\\`9' Replace the word with a digit offered in the *Choices* buffer. -\\`SPC' Accept word this time. -\\`i' Accept word and insert into private dictionary. -\\`a' Accept word for this session. -\\`A' Accept word and place in `buffer-local dictionary'. -\\`r' Replace word with typed-in value. Rechecked. -\\`R' Replace word with typed-in value. Query-replaced in buffer. Rechecked. -\\`?' Show these commands. -\\`x' Exit spelling buffer. Move cursor to original point. -\\`X' Exit spelling buffer. Leaves cursor at the current point, and permits - the aborted check to be completed later. -\\`q' Quit spelling session (Kills ispell process). -\\`l' Look up typed-in replacement in alternate dictionary. Wildcards okay. -\\`u' Like \\`i', but the word is lower-cased first. -\\`m' Place typed-in value in personal dictionary, then recheck current word. -\\`C-l' Redraw screen. -\\`C-r' Recursive edit. -\\`C-z' Suspend Emacs or iconify frame.")) - nil))) - - - (let ((help-1 (concat "[r/R]eplace word; [a/A]ccept for this session; " - "[i]nsert into private dictionary")) - (help-2 (concat "[l]ook a word up in alternate dictionary; " - "e[x/X]it; [q]uit session")) - (help-3 (concat "[u]ncapitalized insert into dict. " - "Type `x C-h f ispell-help' for more help"))) - (save-window-excursion - (if ispell-help-in-bufferp - (let ((buffer (get-buffer-create "*Ispell Help*"))) - (with-current-buffer buffer - (insert (concat help-1 "\n" help-2 "\n" help-3))) - (ispell-display-buffer buffer) - (sit-for ispell-help-timeout) - (kill-buffer "*Ispell Help*")) - (unwind-protect - (let ((resize-mini-windows 'grow-only)) - (select-window (minibuffer-window)) - (erase-buffer) - (message nil) - ;;(set-minibuffer-window (selected-window)) - (enlarge-window 2) - (insert (concat help-1 "\n" help-2 "\n" help-3)) - (sit-for ispell-help-timeout)) - (erase-buffer))))))) + (let ((help-1 (concat "[r/R]eplace word; [a/A]ccept for this session; " + "[i]nsert into private dictionary")) + (help-2 (concat "[l]ook a word up in alternate dictionary; " + "e[x/X]it; [q]uit session")) + (help-3 (concat "[u]ncapitalized insert into dict. " + "Type `x C-h f ispell-help' for more help"))) + (save-window-excursion + (if ispell-help-in-bufferp + (let ((buffer (get-buffer-create "*Ispell Help*"))) + (with-current-buffer buffer + (insert (concat help-1 "\n" help-2 "\n" help-3))) + (ispell-display-buffer buffer) + (sit-for ispell-help-timeout) + (kill-buffer "*Ispell Help*")) + (unwind-protect + (let ((resize-mini-windows 'grow-only)) + (select-window (minibuffer-window)) + (erase-buffer) + (message nil) + ;;(set-minibuffer-window (selected-window)) + (enlarge-window 2) + (insert (concat help-1 "\n" help-2 "\n" help-3)) + (sit-for ispell-help-timeout)) + (erase-buffer)))))) (define-obsolete-function-alias 'lookup-words 'ispell-lookup-words "24.4") @@ -4042,10 +4003,6 @@ You can bind this to a key in GNUS or mail by adding to (with-no-warnings message-cite-prefix-regexp) "\\|" default-prefix)) - ((equal major-mode 'mh-letter-mode) ; mh mail message - (concat "[^,;&+=\n]+ writes:" "\\|" - (with-no-warnings - (ispell-non-empty-string mh-ins-buf-prefix)))) ((not internal-messagep) ; Assume nn sent us this message. (concat "In [a-zA-Z.]+ you write:" "\\|" "In <[^,;&+=]+> [^,;&+=]+ writes:" "\\|" diff --git a/lisp/vc/ediff-util.el b/lisp/vc/ediff-util.el index 597d8a5e643..1071705b393 100644 --- a/lisp/vc/ediff-util.el +++ b/lisp/vc/ediff-util.el @@ -3766,8 +3766,7 @@ Ediff Control Panel to restore highlighting." ((memq (ediff-with-current-buffer x major-mode) '(rmail-mode vm-mode - gnus-article-mode - mh-show-mode)) + gnus-article-mode)) x) ((string-match "^[ *]" (buffer-name x)) nil) ((string= "*scratch*" (buffer-name x)) nil)