Upgraded to MH-E version 7.3.
See etc/MH-E-NEWS and lisp/mh-e/ChangeLog for details.
This commit is contained in:
parent
0b325c12a2
commit
924df20809
23 changed files with 6383 additions and 1546 deletions
|
@ -1,3 +1,8 @@
|
|||
2003-04-24 Bill Wohler <wohler@newt.com>
|
||||
|
||||
* MH-E-NEWS: Upgraded to MH-E version 7.3.
|
||||
|
||||
|
||||
2003-04-03 Kenichi Handa <handa@etlken2>
|
||||
|
||||
* HELLO: Fix the malayalam line.
|
||||
|
|
257
etc/MH-E-NEWS
257
etc/MH-E-NEWS
|
@ -1,3 +1,260 @@
|
|||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved.
|
||||
|
||||
|
||||
* Changes in MH-E 7.3
|
||||
|
||||
** New Features in MH-E 7.3
|
||||
|
||||
*** Unified function arguments
|
||||
|
||||
Any function with MSG-OR-SEQ in its docstring uses the displayed
|
||||
message by default for this argument. However, if a prefix argument is
|
||||
provided, then the user is prompted for a message sequence. If the
|
||||
variable `transient-mark-mode' is non-nil and the mark is active, then
|
||||
the function operates on the messages in the selected region. In a
|
||||
program, MSG-OR-SEQ can be a message number, a list of message
|
||||
numbers, a region in a cons cell, or a sequence.
|
||||
|
||||
*** MH-Index view of unseen messages
|
||||
|
||||
Use "F n (mh-index-new-messages)" or Folder -> View New Messages menu
|
||||
item to display messages in the `mh-unseen-seq' sequence in folders
|
||||
specified by `mh-index-new-messages-folders'. With a prefix argument,
|
||||
enter a space-separated list of folders, or nothing to search all
|
||||
folders.
|
||||
|
||||
Like other MH-Index folders, use "v (mh-index-visit-folder)" if you
|
||||
wish to visit the original folder with the unseen message. This is
|
||||
usually not necessary since the original message is annotated if you
|
||||
reply, deleted if you delete the message, or refiled if you refile the
|
||||
message (closes SF #701756).
|
||||
|
||||
*** Spam software support
|
||||
|
||||
MH-E now supports several spam filters including Bogofilter,
|
||||
SpamProbe, and SpamAssassin. Spam that is mistakenly considered to be
|
||||
good mail can be reclassified as spam with "J b (mh-junk-blacklist)".
|
||||
Conversely, good mail that is accidently considered to be spam can be
|
||||
reclassified with "J w (mh-junk-whitelist)" (closes SF #669518).
|
||||
|
||||
If a message is blacklisted, and `mh-junk-mail-folder' is a string,
|
||||
then the message is refiled to that folder. If this variable is nil,
|
||||
the message is deleted. If a message is whitelisted, then the message
|
||||
is refiled to `mh-inbox'.
|
||||
|
||||
To change the spam program being used, customize `mh-junk-program'.
|
||||
This should only be necessary if you have multiple filters on your
|
||||
system and MH-E picked the wrong one. These customization variables
|
||||
are found in the new customization group `mh-junk'.
|
||||
|
||||
The documentation for the following functions describes what setup is
|
||||
needed for the different spam fighting programs:
|
||||
|
||||
- `mh-bogofilter-blacklist'
|
||||
- `mh-spamprobe-blacklist'
|
||||
- `mh-spamassassin-blacklist'
|
||||
|
||||
*** Relative folder specification @ supported
|
||||
|
||||
You can now use the relative folder marker @ in folder names (closes
|
||||
SF #666774).
|
||||
|
||||
*** Marking messages
|
||||
|
||||
Messages can now be highlighted with "' (mh-toggle-tick)", Sequence ->
|
||||
Toggle Tick Mark menu item or the "Toggle tick mark" button. These
|
||||
messages are added to the "tick" sequence, although this sequence can
|
||||
be changed in `mh-tick-seq'. The highlighting effect can be modified
|
||||
by customizing `mh-folder-tick-face' (closes SF #623367).
|
||||
|
||||
There is also a new keybinding "/ ' (mh-narrow-to-tick)" and menu item
|
||||
Sequence -> Narrow to Tick Sequence to narrow the view to the
|
||||
highlighted messages.
|
||||
|
||||
*** mh-default-folder-list now takes recipients
|
||||
|
||||
If you wish to file a message based upon the recipient of a message
|
||||
(such as a mailing list), you can now indicate that when filling out
|
||||
the address in the `mh-default-folder-list' customization variable.
|
||||
|
||||
*** Face header field supported
|
||||
|
||||
In addition to the X-Face header field, the Face header field, which
|
||||
can display color images, is now supported. As a bonus, the external
|
||||
xface-e21 library is no longer required.
|
||||
|
||||
*** X-Image-URL support
|
||||
|
||||
Images specified in X-Image-URL header fields are now supported.
|
||||
See the customization variable `mh-fetch-x-image-url' to enable this
|
||||
support.
|
||||
|
||||
*** Fcc completion
|
||||
|
||||
Folders in Fcc fields in message drafts can now be completed with
|
||||
M-TAB.
|
||||
|
||||
** New Variables in MH-E 7.3
|
||||
|
||||
Variables that have been added to MH-E that have not been discussed
|
||||
elsewhere are listed here.
|
||||
|
||||
*** mh-auto-fields-list
|
||||
|
||||
Alist of addresses for which header lines are automatically inserted.
|
||||
When a regular expression matches in the To or cc fields of a message,
|
||||
the corresponding header field is automatically inserted in the
|
||||
message header. It also allows the automatic setting of an identity
|
||||
(using `mh-insert-identity') to set an alternate identity when sending
|
||||
messages to a certain person or mailing list.
|
||||
|
||||
Since this is a more general use of `mh-insert-mail-followup-to-flag'
|
||||
and `mh-insert-mail-followup-to-list', these variables have been removed.
|
||||
|
||||
*** mh-show-xface-face
|
||||
|
||||
Face for displaying the X-Face image.
|
||||
|
||||
*** mh-xemacs-toolbar-position
|
||||
|
||||
This customization variable allows the user to place the toolbar on
|
||||
the four edges of the frame.
|
||||
|
||||
*** mh-xemacs-use-toolbar-flag
|
||||
|
||||
This customization variable is used to enable or disable the toolbar
|
||||
under XEmacs.
|
||||
|
||||
** Variables Deleted in MH-E 7.3
|
||||
|
||||
Variables that have been removed from MH-E that have not been
|
||||
discussed elsewhere are listed here.
|
||||
|
||||
*** mh-decode-content-transfer-encoded-message-flag
|
||||
|
||||
No longer needed since the external program mimencode is no longer
|
||||
used.
|
||||
|
||||
*** mh-index-show-hook
|
||||
|
||||
This hook was never used, so it was removed.
|
||||
|
||||
*** mh-tool-bar-reply-3-buttons-flag
|
||||
|
||||
Obsolete. This functionality is present `mh-tool-bar-folder-buttons'.
|
||||
|
||||
** Bug Fixes in MH-E 7.3
|
||||
|
||||
*** Can't refile message
|
||||
|
||||
Messages with invalid addresses were causing errors in ali which
|
||||
prevented the refiling of messages. The ali error is now shown in the
|
||||
"*MH-E Log*" buffer and refiling suggests the last folder used (closes
|
||||
SF #680388).
|
||||
|
||||
*** Empty body triggers duped header
|
||||
|
||||
If the body was empty the header would be treated like the body and
|
||||
was therefore displayed twice. This has been fixed (closes SF
|
||||
#681162).
|
||||
|
||||
*** mml or mhl directives not always processed
|
||||
|
||||
The mml and mhl directives used to create body parts were not
|
||||
processed if one re-edited a draft, or if they added the directives
|
||||
manually. The directives are now always processed upon sending the
|
||||
letter. You may still, of course, use "C-c C-m m (mh-mml-to-mime)" or
|
||||
"C-c C-e (mh-edit-mhn)" to manually create the MIME body parts from
|
||||
the directives and then send the draft.
|
||||
|
||||
*** mh-alias-grab-from-field fails
|
||||
|
||||
MH-E was adding aliases with angle brackets around the address when
|
||||
there wasn't a phrase (usually, the user's name), to go with it. This
|
||||
caused ali to fail which caused problems in MH-E. This is probably a
|
||||
bug in ali, but MH-E no longer inserts angle brackets around the
|
||||
address unless there is a phrase, which avoids the problem (closes SF
|
||||
#690216).
|
||||
|
||||
*** XEmacs fixes
|
||||
|
||||
MH-E is now fully supported under XEmacs and compiles without any
|
||||
warnings.
|
||||
|
||||
In particular, the following now work under XEmacs:
|
||||
|
||||
- X-Face, Face, and X-Image-URL header fields
|
||||
- MH-E logo in mode line
|
||||
- Emphasis (bold, italics, etc.)
|
||||
- Smilies
|
||||
- Toolbar
|
||||
|
||||
*** Indexed folders should respect mh-show-threads-flag
|
||||
|
||||
Indexed folders are now threaded if `mh-show-threads-flag' is non-nil
|
||||
(closes SF #709667).
|
||||
|
||||
*** Threading index view loses folder info
|
||||
|
||||
This has been fixed (closes SF #709672).
|
||||
|
||||
*** No undo information when re-editing drafts
|
||||
|
||||
Undo is turned on in the draft buffer when using "e (mh-edit-again)"
|
||||
(closes SF #712777).
|
||||
|
||||
*** Forwarded base64 encoded messages are incorrectly displayed
|
||||
|
||||
This has been fixed (closes SF #681518).
|
||||
|
||||
*** Append to *MH-E Log* buffer
|
||||
|
||||
The last 100 lines of log messages are kept in the *MH-E Log* buffer.
|
||||
Previously, the buffer was erased every time it was written (closes SF
|
||||
#685476). In addition, many of the MH-E commands now send their output
|
||||
into this buffer instead of a plethora of other special-purpose
|
||||
buffers.
|
||||
|
||||
*** mh-inc-folder complains if no mail and no current message
|
||||
|
||||
The function `mh-inc-folder' no longer calls `mh-show' if point is not
|
||||
on a valid scan line. This keeps `mh-inc-folder' from complaining
|
||||
(closes SF #678115).
|
||||
|
||||
*** Folder normalization strips leading slash
|
||||
|
||||
Leading "/" characters in folder names entered by the user were being
|
||||
lost. This has been fixed (closes SF #676890).
|
||||
|
||||
*** Print header doesn't show message
|
||||
|
||||
When printing a sequence, the header simply indicated that a sequence,
|
||||
but not which one, was being printed and did not show the message
|
||||
number. This has been fixed. If more than one message is printed, a
|
||||
page of the scan lines is printed and its header indicates the
|
||||
sequence or message range. The pages with the actual messages all set
|
||||
the header to the folder and message displayed on that page.
|
||||
|
||||
*** Aliases constantly reloaded
|
||||
|
||||
Empty lists are now handled properly (closes SF #693859).
|
||||
|
||||
*** Remove RCS keywords
|
||||
|
||||
Removed RCS keywords per Emacs conventions (closes SF #680731).
|
||||
|
||||
*** Replace mimencode
|
||||
|
||||
MH-E was enhanced to decode message based on charset and
|
||||
Content-Transfer-Encoding. This eliminates the need for the external
|
||||
program mimencode (closes SF #674857).
|
||||
|
||||
|
||||
|
||||
* Changes in MH-E 7.2
|
||||
|
||||
This release includes the new features of filing hints, hierarchical
|
||||
|
|
2
etc/NEWS
2
etc/NEWS
|
@ -100,7 +100,7 @@ You can now put the init files .emacs and .emacs_SHELL under
|
|||
|
||||
** MH-E changes.
|
||||
|
||||
Upgraded to MH-E version 7.2. There have been major changes since
|
||||
Upgraded to MH-E version 7.3. There have been major changes since
|
||||
version 5.0.2; see MH-E-NEWS for details.
|
||||
|
||||
+++
|
||||
|
|
1569
lisp/mh-e/ChangeLog
1569
lisp/mh-e/ChangeLog
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,7 @@
|
|||
;;; mh-alias.el --- MH-E mail alias completion and expansion
|
||||
;;
|
||||
;; Copyright (C) 1994, 1995, 1996, 1997, 2001, 2002 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 1994, 95, 96, 1997,
|
||||
;; 2001, 02, 2003 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Peter S. Galbraith <psg@debian.org>
|
||||
;; Maintainer: Bill Wohler <wohler@newt.com>
|
||||
|
@ -93,8 +94,6 @@
|
|||
|
||||
;;; Change Log:
|
||||
|
||||
;; $Id: mh-alias.el,v 1.2 2003/02/03 20:55:30 wohler Exp $
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'mh-e)
|
||||
|
@ -103,10 +102,12 @@
|
|||
(eval-when-compile (defvar mail-abbrev-syntax-table))
|
||||
|
||||
;;; Autoloads
|
||||
(autoload 'mail-abbrev-complete-alias "mailabbrev")
|
||||
(autoload 'multi-prompt "multi-prompt")
|
||||
(eval-when (compile load eval)
|
||||
(ignore-errors
|
||||
(require 'mailabbrev)
|
||||
(require 'multi-prompt)))
|
||||
|
||||
(defvar mh-alias-alist nil
|
||||
(defvar mh-alias-alist 'not-read
|
||||
"Alist of MH aliases.")
|
||||
(defvar mh-alias-blind-alist nil
|
||||
"Alist of MH aliases that are blind lists.")
|
||||
|
@ -180,7 +181,7 @@ If ARG is non-nil, filenames listed in `mh-alias-system-aliases' are appended."
|
|||
(insert-file-contents "/etc/passwd")))
|
||||
((stringp mh-alias-local-users)
|
||||
(insert mh-alias-local-users "\n")
|
||||
(shell-command-on-region (point-min)(point-max) mh-alias-local-users t)
|
||||
(shell-command-on-region (point-min) (point-max) mh-alias-local-users t)
|
||||
(goto-char (point-min))))
|
||||
(while (< (point) (point-max))
|
||||
(cond
|
||||
|
@ -241,7 +242,7 @@ If ARG is non-nil, filenames listed in `mh-alias-system-aliases' are appended."
|
|||
|
||||
(defun mh-alias-reload-maybe ()
|
||||
"Load new MH aliases."
|
||||
(if (or (not mh-alias-alist) ; Doesn't exist, so create it.
|
||||
(if (or (eq mh-alias-alist 'not-read) ; Doesn't exist, so create it.
|
||||
(mh-alias-tstamp nil)) ; Out of date, so recreate it.
|
||||
(mh-alias-reload)))
|
||||
|
||||
|
@ -253,12 +254,16 @@ If ARG is non-nil, filenames listed in `mh-alias-system-aliases' are appended."
|
|||
ALIAS must be a string for a single alias.
|
||||
If USER is t, then assume ALIAS is an address and call ali -user.
|
||||
ali returns the string unchanged if not defined. The same is done here."
|
||||
(save-excursion
|
||||
(let ((user-arg (if user "-user" "-nouser")))
|
||||
(mh-exec-cmd-quiet t "ali" user-arg "-nolist" alias))
|
||||
(goto-char (point-max))
|
||||
(if (looking-at "^$") (delete-backward-char 1))
|
||||
(buffer-substring (point-min)(point-max))))
|
||||
(condition-case err
|
||||
(save-excursion
|
||||
(let ((user-arg (if user "-user" "-nouser")))
|
||||
(mh-exec-cmd-quiet t "ali" user-arg "-nolist" alias))
|
||||
(goto-char (point-max))
|
||||
(if (looking-at "^$") (delete-backward-char 1))
|
||||
(buffer-substring (point-min)(point-max)))
|
||||
(error (progn
|
||||
(message (error-message-string err))
|
||||
alias))))
|
||||
|
||||
(defun mh-alias-expand (alias)
|
||||
"Return expansion for ALIAS.
|
||||
|
@ -280,15 +285,14 @@ Blind aliases or users from /etc/passwd are not expanded."
|
|||
(let* ((minibuffer-local-completion-map mh-alias-read-address-map)
|
||||
(completion-ignore-case mh-alias-completion-ignore-case-flag)
|
||||
(the-answer
|
||||
(or (cond
|
||||
((fboundp 'completing-read-multiple)
|
||||
(completing-read-multiple prompt mh-alias-alist nil nil))
|
||||
((featurep 'multi-prompt)
|
||||
(multi-prompt "," nil prompt mh-alias-alist nil nil))
|
||||
(t
|
||||
(split-string
|
||||
(completing-read prompt mh-alias-alist nil nil)
|
||||
","))))))
|
||||
(cond ((fboundp 'completing-read-multiple)
|
||||
(mh-funcall-if-exists
|
||||
completing-read-multiple prompt mh-alias-alist nil nil))
|
||||
((featurep 'multi-prompt)
|
||||
(mh-funcall-if-exists
|
||||
multi-prompt "," nil prompt mh-alias-alist nil nil))
|
||||
(t (split-string
|
||||
(completing-read prompt mh-alias-alist nil nil) ",")))))
|
||||
(if (not mh-alias-expand-aliases-flag)
|
||||
(mapconcat 'identity the-answer ", ")
|
||||
;; Loop over all elements, checking if in passwd aliast or blind first
|
||||
|
@ -325,12 +329,14 @@ Blind aliases or users from /etc/passwd are not expanded."
|
|||
(message "No alias for %s" the-name))))))
|
||||
(self-insert-command 1))
|
||||
|
||||
(mh-do-in-xemacs (defvar mail-abbrevs))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-alias-letter-expand-alias ()
|
||||
"Expand mail alias before point."
|
||||
(mh-alias-reload-maybe)
|
||||
(let ((mail-abbrevs mh-alias-alist))
|
||||
(mail-abbrev-complete-alias))
|
||||
(mh-funcall-if-exists mail-abbrev-complete-alias))
|
||||
(when mh-alias-expand-aliases-flag
|
||||
(let* ((end (point))
|
||||
(syntax-table (syntax-table))
|
||||
|
@ -350,6 +356,9 @@ Blind aliases or users from /etc/passwd are not expanded."
|
|||
(defun mh-alias-suggest-alias (string)
|
||||
"Suggest an alias for STRING."
|
||||
(cond
|
||||
((string-match "^<\\(.*\\)>$" string)
|
||||
;; <somename@foo.bar> -> recurse, stripping brackets.
|
||||
(mh-alias-suggest-alias (match-string 1 string)))
|
||||
((string-match "^\\sw+$" string)
|
||||
;; One word -> downcase it.
|
||||
(downcase string))
|
||||
|
@ -389,9 +398,25 @@ Blind aliases or users from /etc/passwd are not expanded."
|
|||
(format "%s %s" (match-string 2 string) (match-string 1 string))))
|
||||
(t
|
||||
;; Output string, with spaces replaced by dots.
|
||||
(downcase (replace-regexp-in-string
|
||||
"\\.\\.+" "."
|
||||
(replace-regexp-in-string " +" "." string))))))
|
||||
(mh-alias-canonicalize-suggestion string))))
|
||||
|
||||
(defun mh-alias-canonicalize-suggestion (string)
|
||||
"Process STRING to replace spacess by periods.
|
||||
First all spaces are replaced by periods. Then every run of consecutive periods
|
||||
are replaced with a single period. Finally the string is converted to lower
|
||||
case."
|
||||
(with-temp-buffer
|
||||
(insert string)
|
||||
;; Replace spaces with periods
|
||||
(goto-char (point-min))
|
||||
(replace-regexp " +" ".")
|
||||
;; Replace consecutive periods with a single period
|
||||
(goto-char (point-min))
|
||||
(replace-regexp "\\.\\.+" ".")
|
||||
;; Convert to lower case
|
||||
(downcase-region (point-min) (point-max))
|
||||
;; Whew! all done...
|
||||
(buffer-string)))
|
||||
|
||||
(defun mh-alias-which-file-has-alias (alias file-list)
|
||||
"Return the name of writable file which defines ALIAS from list FILE-LIST."
|
||||
|
@ -403,7 +428,7 @@ Blind aliases or users from /etc/passwd are not expanded."
|
|||
(erase-buffer)
|
||||
(when (file-writable-p (car file-list))
|
||||
(insert-file-contents (car file-list))
|
||||
(if (re-search-forward (concat "^" (regexp-quote alias) ":"))
|
||||
(if (re-search-forward (concat "^" (regexp-quote alias) ":") nil t)
|
||||
(setq found (car file-list)
|
||||
the-list nil)
|
||||
(setq the-list (cdr the-list)))))
|
||||
|
@ -470,14 +495,18 @@ Set `mh-alias-insert-file' or set AliasFile in your .mh_profile file"))
|
|||
|
||||
;;;###mh-autoload
|
||||
(defun mh-alias-from-has-no-alias-p ()
|
||||
"Return t is From has no current alias set."
|
||||
"Return t is From has no current alias set.
|
||||
In the exceptional situation where there isn't a From header in the message the
|
||||
function returns nil."
|
||||
(mh-alias-reload-maybe)
|
||||
(save-excursion
|
||||
(if (not (mh-folder-line-matches-show-buffer-p))
|
||||
nil ;No corresponding show buffer
|
||||
(if (eq major-mode 'mh-folder-mode)
|
||||
(set-buffer mh-show-buffer))
|
||||
(not (mh-alias-address-to-alias (mh-extract-from-header-value))))))
|
||||
(let ((from-header (mh-extract-from-header-value)))
|
||||
(and from-header
|
||||
(not (mh-alias-address-to-alias from-header)))))))
|
||||
|
||||
(defun mh-alias-add-alias-to-file (alias address &optional file)
|
||||
"Add ALIAS for ADDRESS in alias FILE without alias check or prompts.
|
||||
|
@ -491,7 +520,6 @@ after it."
|
|||
(goto-char (point-min))
|
||||
(let ((alias-search (concat alias ":"))
|
||||
(letter)
|
||||
(here (point))
|
||||
(case-fold-search t))
|
||||
(cond
|
||||
;; Search for exact match (if we had the same alias before)
|
||||
|
@ -538,7 +566,11 @@ If the alias is already is use, `mh-alias-add-alias-to-file' will prompt."
|
|||
(interactive "P\nP")
|
||||
(mh-alias-reload-maybe)
|
||||
(setq alias (completing-read "Alias: " mh-alias-alist nil nil alias))
|
||||
(if (and address (string-match "^<\\(.*\\)>$" address))
|
||||
(setq address (match-string 1 address)))
|
||||
(setq address (read-string "Address: " address))
|
||||
(if (string-match "^<\\(.*\\)>$" address)
|
||||
(setq address (match-string 1 address)))
|
||||
(let ((address-alias (mh-alias-address-to-alias address))
|
||||
(alias-address (mh-alias-expand alias)))
|
||||
(if (string-equal alias-address alias)
|
||||
|
@ -571,7 +603,8 @@ already has an alias."
|
|||
(insert-file-contents (mh-msg-filename (mh-get-msg-num t))))
|
||||
((eq major-mode 'mh-folder-mode)
|
||||
(error "Cursor not pointing to a message")))
|
||||
(let* ((address (mh-extract-from-header-value))
|
||||
(let* ((address (or (mh-extract-from-header-value)
|
||||
(error "Message has no From: header")))
|
||||
(alias (mh-alias-suggest-alias address)))
|
||||
(mh-alias-add-alias alias address))))
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
;;; mh-comp.el --- MH-E functions for composing messages
|
||||
|
||||
;; Copyright (C) 1993,1995,1997,2000,2001,2002 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 1993, 95, 1997,
|
||||
;; 2000, 01, 02, 2003 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Bill Wohler <wohler@newt.com>
|
||||
;; Maintainer: Bill Wohler <wohler@newt.com>
|
||||
|
@ -30,14 +31,14 @@
|
|||
|
||||
;;; Change Log:
|
||||
|
||||
;; $Id: mh-comp.el,v 1.2 2003/02/03 20:55:30 wohler Exp $
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'mh-e)
|
||||
(require 'gnus-util)
|
||||
(require 'easymenu)
|
||||
(require 'cl)
|
||||
(eval-when (compile load eval)
|
||||
(ignore-errors (require 'mailabbrev)))
|
||||
|
||||
;; Shush the byte-compiler
|
||||
(defvar adaptive-fill-first-line-regexp)
|
||||
|
@ -309,27 +310,21 @@ See also documentation for `\\[mh-send]' function."
|
|||
|
||||
;;;###mh-autoload
|
||||
(defun mh-forward (to cc &optional msg-or-seq)
|
||||
"Forward one or more messages to the recipients TO and CC.
|
||||
"Forward messages to the recipients TO and CC.
|
||||
Use optional MSG-OR-SEQ argument to specify a message or sequence to forward.
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is forwarded.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence.
|
||||
|
||||
Use the optional MSG-OR-SEQ to specify a message or sequence to forward.
|
||||
|
||||
Default is the displayed message. If optional prefix argument is given then
|
||||
prompt for the message sequence. If variable `transient-mark-mode' is non-nil
|
||||
and the mark is active, then the selected region is forwarded.
|
||||
See also documentation for `\\[mh-send]' function."
|
||||
(interactive (list (mh-read-address "To: ")
|
||||
(mh-read-address "Cc: ")
|
||||
(cond
|
||||
((mh-mark-active-p t)
|
||||
(mh-region-to-msg-list (region-beginning) (region-end)))
|
||||
(current-prefix-arg
|
||||
(mh-read-seq-default "Forward" t))
|
||||
(t
|
||||
(mh-get-msg-num t)))))
|
||||
(mh-interactive-msg-or-seq "Forward")))
|
||||
(let* ((folder mh-current-folder)
|
||||
(msgs (cond ((numberp msg-or-seq) (list msg-or-seq))
|
||||
((listp msg-or-seq) msg-or-seq)
|
||||
(t (mh-seq-to-msgs msg-or-seq))))
|
||||
(msgs (mh-msg-or-seq-to-msg-list msg-or-seq))
|
||||
(config (current-window-configuration))
|
||||
(fwd-msg-file (mh-msg-filename (car msgs) folder))
|
||||
;; forw always leaves file in "draft" since it doesn't have -draft
|
||||
|
@ -337,7 +332,8 @@ See also documentation for `\\[mh-send]' function."
|
|||
(draft (cond ((or (not (file-exists-p draft-name))
|
||||
(y-or-n-p "The file 'draft' exists. Discard it? "))
|
||||
(mh-exec-cmd "forw" "-build" (if mh-nmh-flag "-mime")
|
||||
mh-current-folder msgs)
|
||||
mh-current-folder
|
||||
(mh-coalesce-msg-list msgs))
|
||||
(prog1
|
||||
(mh-read-draft "" draft-name t)
|
||||
(mh-insert-fields "To:" to "Cc:" cc)
|
||||
|
@ -353,14 +349,12 @@ See also documentation for `\\[mh-send]' function."
|
|||
(setq orig-from (mh-get-header-field "From:"))
|
||||
(setq orig-subject (mh-get-header-field "Subject:")))
|
||||
(let ((forw-subject
|
||||
(mh-forwarded-letter-subject orig-from orig-subject))
|
||||
(compose))
|
||||
(mh-forwarded-letter-subject orig-from orig-subject)))
|
||||
(mh-insert-fields "Subject:" forw-subject)
|
||||
(goto-char (point-min))
|
||||
;; If using MML, translate mhn
|
||||
(if (equal mh-compose-insertion 'gnus)
|
||||
(save-excursion
|
||||
(setq compose t)
|
||||
(re-search-forward (format "^\\(%s\\)?$"
|
||||
mh-mail-header-separator))
|
||||
(while
|
||||
|
@ -386,12 +380,10 @@ See also documentation for `\\[mh-send]' function."
|
|||
(forward-line 1))
|
||||
(delete-other-windows)
|
||||
(mh-add-msgs-to-seq msgs 'forwarded t)
|
||||
(mh-compose-and-send-mail draft "" folder msg-or-seq
|
||||
(mh-compose-and-send-mail draft "" folder msgs
|
||||
to forw-subject cc
|
||||
mh-note-forw "Forwarded:"
|
||||
config)
|
||||
(if compose
|
||||
(setq mh-mml-compose-insert-flag t))
|
||||
(mh-letter-mode-message)))))
|
||||
|
||||
(defun mh-forwarded-letter-subject (from subject)
|
||||
|
@ -439,38 +431,27 @@ setting of the variable `mh-redist-full-contents'. See its documentation."
|
|||
(mh-goto-header-end 0)
|
||||
(insert "Resent-To: " to "\n")
|
||||
(if (not (equal cc "")) (insert "Resent-cc: " cc "\n"))
|
||||
(mh-clean-msg-header (point-min)
|
||||
"^Message-Id:\\|^Received:\\|^Return-Path:\\|^Sender:\\|^Date:\\|^From:"
|
||||
nil)
|
||||
(mh-clean-msg-header
|
||||
(point-min)
|
||||
"^Message-Id:\\|^Received:\\|^Return-Path:\\|^Sender:\\|^Date:\\|^From:"
|
||||
nil)
|
||||
(save-buffer)
|
||||
(message "Redistributing...")
|
||||
(if (not mh-redist-background)
|
||||
(if mh-redist-full-contents
|
||||
(call-process "/bin/sh" nil 0 nil "-c"
|
||||
(format "mhdist=1 mhaltmsg=%s %s -push %s"
|
||||
buffer-file-name
|
||||
(expand-file-name mh-send-prog mh-progs)
|
||||
buffer-file-name))
|
||||
(call-process "/bin/sh" nil 0 nil "-c"
|
||||
(format
|
||||
"mhdist=1 mhaltmsg=%s mhannotate=1 %s -push %s"
|
||||
(mh-msg-filename msg folder)
|
||||
(expand-file-name mh-send-prog mh-progs)
|
||||
buffer-file-name))))
|
||||
(mh-annotate-msg msg folder mh-note-dist
|
||||
"-component" "Resent:"
|
||||
"-text" (format "\"%s %s\"" to cc))
|
||||
(if mh-redist-background
|
||||
(mh-exec-cmd-daemon "/bin/sh" nil "-c"
|
||||
(format "mhdist=1 mhaltmsg=%s %s %s %s"
|
||||
(if mh-redist-full-contents
|
||||
buffer-file-name
|
||||
(mh-msg-filename msg folder))
|
||||
(if mh-redist-full-contents
|
||||
""
|
||||
"mhannotate=1")
|
||||
(mh-expand-file-name "send" mh-progs)
|
||||
buffer-file-name)))
|
||||
(let ((env "mhdist=1"))
|
||||
;; Setup environment...
|
||||
(setq env (concat env " mhaltmsg=" (if mh-redist-full-contents
|
||||
buffer-file-name
|
||||
(mh-msg-filename msg folder))))
|
||||
(unless mh-redist-full-contents
|
||||
(setq env (concat env " mhannotate=1")))
|
||||
;; Redistribute...
|
||||
(if mh-redist-background
|
||||
(mh-exec-cmd-env-daemon env mh-send-prog nil buffer-file-name)
|
||||
(mh-exec-cmd-error env mh-send-prog "-push" buffer-file-name))
|
||||
;; Annotate...
|
||||
(mh-annotate-msg msg folder mh-note-dist
|
||||
"-component" "Resent:"
|
||||
"-text" (format "\"%s %s\"" to cc)))
|
||||
(kill-buffer draft)
|
||||
(message "Redistributing...done"))))
|
||||
|
||||
|
@ -501,7 +482,8 @@ Optional argument BUFFER can be used to specify the buffer."
|
|||
|
||||
;;;###mh-autoload
|
||||
(defun mh-reply (message &optional reply-to includep)
|
||||
"Reply to MESSAGE (default: current message).
|
||||
"Reply to MESSAGE.
|
||||
Default is the displayed message.
|
||||
If the optional argument REPLY-TO is not given, prompts for type of addresses
|
||||
to reply to:
|
||||
from sender only,
|
||||
|
@ -706,14 +688,15 @@ reused."
|
|||
(buffer-substring (point-min) (1- (point-max)))))
|
||||
|
||||
(defun mh-annotate-msg (msg buffer note &rest args)
|
||||
"Mark MSG in BUFFER with character NOTE and annotate message with ARGS."
|
||||
(apply 'mh-exec-cmd "anno" buffer msg args)
|
||||
"Mark MSG in BUFFER with character NOTE and annotate message with ARGS.
|
||||
MSG can be a message number, a list of message numbers, or a sequence."
|
||||
(apply 'mh-exec-cmd "anno" buffer
|
||||
(if (listp msg) (append msg args) (cons msg args)))
|
||||
(save-excursion
|
||||
(cond ((get-buffer buffer) ; Buffer may be deleted
|
||||
(set-buffer buffer)
|
||||
(if (numberp msg)
|
||||
(mh-notate msg note (1+ mh-cmd-note))
|
||||
(mh-notate-seq msg note (1+ mh-cmd-note)))))))
|
||||
(mh-iterate-on-msg-or-seq nil msg
|
||||
(mh-notate nil note (1+ mh-cmd-note)))))))
|
||||
|
||||
(defun mh-insert-fields (&rest name-values)
|
||||
"Insert the NAME-VALUES pairs in the current buffer.
|
||||
|
@ -776,7 +759,7 @@ Returns t if found, nil if not."
|
|||
"Extract From: string from header."
|
||||
(save-excursion
|
||||
(if (not (mh-goto-header-field "From:"))
|
||||
(error "No From header line found")
|
||||
nil
|
||||
(skip-chars-forward " \t")
|
||||
(buffer-substring-no-properties
|
||||
(point) (progn (mh-header-field-end)(point))))))
|
||||
|
@ -812,9 +795,9 @@ Returns t if found, nil if not."
|
|||
;; The next two will have to be merged. But I also need to make sure the
|
||||
;; user can't mix directives of both types.
|
||||
["Pull in All Compositions (mhn)"
|
||||
mh-edit-mhn mh-mhn-compose-insert-flag]
|
||||
mh-edit-mhn (mh-mhn-directive-present-p)]
|
||||
["Pull in All Compositions (gnus)"
|
||||
mh-mml-to-mime mh-mml-compose-insert-flag]
|
||||
mh-mml-to-mime (mh-mml-directive-present-p)]
|
||||
["Revert to Non-MIME Edit (mhn)"
|
||||
mh-revert-mhn-edit (equal mh-compose-insertion 'mhn)]
|
||||
["Kill This Draft" mh-fully-kill-draft t]))))
|
||||
|
@ -857,6 +840,11 @@ work better in MH-Letter mode."
|
|||
(mail-mode-fill-paragraph arg)
|
||||
(fill-paragraph arg))))
|
||||
|
||||
;; Avoid compiler warnings in XEmacs and Emacs 20
|
||||
(eval-when-compile
|
||||
(defvar tool-bar-mode)
|
||||
(defvar tool-bar-map))
|
||||
|
||||
;;;###autoload
|
||||
(define-derived-mode mh-letter-mode text-mode "MH-Letter"
|
||||
"Mode for composing letters in MH-E.\\<mh-letter-mode-map>
|
||||
|
@ -918,8 +906,11 @@ When a message is composed, the hooks `text-mode-hook' and
|
|||
(setq paragraph-separate paragraph-start)
|
||||
;; --- End of code from sendmail.el ---
|
||||
|
||||
;; Enable undo since a show-mode buffer might have been reused.
|
||||
(buffer-enable-undo)
|
||||
(if (and (boundp 'tool-bar-mode) tool-bar-mode)
|
||||
(set (make-local-variable 'tool-bar-map) mh-letter-tool-bar-map))
|
||||
(mh-funcall-if-exists mh-toolbar-init :letter)
|
||||
(make-local-variable 'font-lock-defaults)
|
||||
(cond
|
||||
((or (equal mh-highlight-citation-p 'font-lock)
|
||||
|
@ -933,16 +924,6 @@ When a message is composed, the hooks `text-mode-hook' and
|
|||
;; ...or the header only
|
||||
(setq font-lock-defaults '(mh-show-font-lock-keywords t))))
|
||||
(easy-menu-add mh-letter-menu)
|
||||
;; See if a "forw: -mime" message containing a MIME composition.
|
||||
;; Mode clears local vars, so can't do this in mh-forward.
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(when (and (re-search-forward
|
||||
(format "^\\(%s\\)?$" mail-header-separator) nil t)
|
||||
(= 0 (forward-line 1))
|
||||
(looking-at "^#forw"))
|
||||
(require 'mh-mime) ;Need mh-mhn-compose-insert-flag local var
|
||||
(setq mh-mhn-compose-insert-flag t)))
|
||||
(setq fill-column mh-letter-fill-column)
|
||||
;; If text-mode-hook turned on auto-fill, tune it for messages
|
||||
(when auto-fill-function
|
||||
|
@ -1055,16 +1036,25 @@ called, with no arguments, before the signature is actually inserted."
|
|||
;;; Routines to compose and send a letter.
|
||||
|
||||
(defun mh-insert-x-face ()
|
||||
"Append X-Face field to header.
|
||||
"Append X-Face, Face or X-Image-URL field to header.
|
||||
If the field already exists, this function does nothing."
|
||||
(when (and (file-exists-p mh-x-face-file)
|
||||
(file-readable-p mh-x-face-file))
|
||||
(save-excursion
|
||||
(when (null (mh-position-on-field "X-Face"))
|
||||
(insert "X-Face: ")
|
||||
(goto-char (+ (point) (cadr (insert-file-contents mh-x-face-file))))
|
||||
(if (not (looking-at "^"))
|
||||
(insert "\n"))))))
|
||||
(unless (or (mh-position-on-field "X-Face")
|
||||
(mh-position-on-field "Face")
|
||||
(mh-position-on-field "X-Image-URL"))
|
||||
(save-excursion
|
||||
(goto-char (+ (point) (cadr (insert-file-contents mh-x-face-file))))
|
||||
(if (not (looking-at "^"))
|
||||
(insert "\n")))
|
||||
(unless (looking-at "\\(X-Face\\|Face\\|X-Image-URL\\): ")
|
||||
(insert "X-Face: "))))))
|
||||
|
||||
(defvar mh-x-mailer-string nil
|
||||
"*String containing the contents of the X-Mailer header field.
|
||||
If nil, this variable is initialized to show the version of MH-E, Emacs, and
|
||||
MH the first time a message is composed.")
|
||||
|
||||
(defun mh-insert-x-mailer ()
|
||||
"Append an X-Mailer field to the header.
|
||||
|
@ -1116,21 +1106,39 @@ The versions of MH-E, Emacs, and MH are shown."
|
|||
(setq fields (cdr fields))))
|
||||
search-result)))
|
||||
|
||||
(defun mh-insert-mail-followup-to ()
|
||||
"Insert Mail-Followup-To: if To or Cc match `mh-insert-mail-followup-to-list'."
|
||||
(defun mh-insert-auto-fields ()
|
||||
"Insert custom fields if To or Cc match `mh-auto-fields-list'."
|
||||
(save-excursion
|
||||
(if (and (or (mh-goto-header-field "To:")(mh-goto-header-field "cc:"))
|
||||
(not (mh-goto-header-field "Mail-Followup-To: ")))
|
||||
(let ((list mh-insert-mail-followup-to-list))
|
||||
(while list
|
||||
(let ((regexp (nth 0 (car list)))
|
||||
(entry (nth 1 (car list))))
|
||||
(when (mh-regexp-in-field-p regexp "To:" "cc:")
|
||||
(if (mh-goto-header-field "Mail-Followup-To: ")
|
||||
(insert entry ", ")
|
||||
(mh-goto-header-end 0)
|
||||
(insert "Mail-Followup-To: " entry "\n")))
|
||||
(setq list (cdr list))))))))
|
||||
(when (and (or (mh-goto-header-field "To:")(mh-goto-header-field "cc:")))
|
||||
(let ((list mh-auto-fields-list))
|
||||
(while list
|
||||
(let ((regexp (nth 0 (car list)))
|
||||
(entries (nth 1 (car list))))
|
||||
(when (mh-regexp-in-field-p regexp "To:" "cc:")
|
||||
(let ((entry-list entries))
|
||||
(while entry-list
|
||||
(let ((field (caar entry-list))
|
||||
(value (cdar entry-list)))
|
||||
(cond
|
||||
((equal "identity" field)
|
||||
(when (assoc value mh-identity-list)
|
||||
(mh-insert-identity value)))
|
||||
(t
|
||||
(mh-modify-header-field field value
|
||||
(equal field "From")))))
|
||||
(setq entry-list (cdr entry-list))))))
|
||||
(setq list (cdr list)))))))
|
||||
|
||||
(defun mh-modify-header-field (field value &optional overwrite-flag)
|
||||
"To header FIELD add VALUE.
|
||||
If OVERWRITE-FLAG is non-nil then the old value, if present, is discarded."
|
||||
(cond ((mh-goto-header-field (concat field ":"))
|
||||
(insert value)
|
||||
(if overwrite-flag
|
||||
(delete-region (point) (line-end-position))
|
||||
(insert ", ")))
|
||||
(t (mh-goto-header-end 0)
|
||||
(insert field ": " value "\n"))))
|
||||
|
||||
(defun mh-compose-and-send-mail (draft send-args
|
||||
sent-from-folder sent-from-msg
|
||||
|
@ -1149,12 +1157,13 @@ 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)
|
||||
(if mh-insert-mail-followup-to-flag (mh-insert-mail-followup-to))
|
||||
(mh-insert-auto-fields)
|
||||
(mh-letter-mode)
|
||||
|
||||
;; mh-identity support
|
||||
(if (and (boundp 'mh-identity-default)
|
||||
mh-identity-default)
|
||||
mh-identity-default
|
||||
(not mh-identity-local))
|
||||
(mh-insert-identity mh-identity-default))
|
||||
(when (and (boundp 'mh-identity-list)
|
||||
mh-identity-list)
|
||||
|
@ -1169,6 +1178,7 @@ CONFIG is the window configuration to restore after sending the letter."
|
|||
(setq mh-previous-window-config config)
|
||||
(setq mode-line-buffer-identification (list " {%b}"))
|
||||
(mh-logo-display)
|
||||
(mh-make-local-hook 'kill-buffer-hook)
|
||||
(add-hook 'kill-buffer-hook 'mh-tidy-draft-buffer nil t)
|
||||
(if (and (boundp 'mh-compose-letter-function)
|
||||
mh-compose-letter-function)
|
||||
|
@ -1193,19 +1203,16 @@ This should be the last function called when composing the draft."
|
|||
If optional prefix argument ARG is provided, monitor delivery.
|
||||
The value of `mh-before-send-letter-hook' is a list of functions to be called,
|
||||
with no arguments, before doing anything.
|
||||
Run `\\[mh-edit-mhn]' if variable `mh-mhn-compose-insert-flag' is set.
|
||||
Run `\\[mh-mml-to-mime]' if variable `mh-mml-compose-insert-flag' is set.
|
||||
Run `\\[mh-edit-mhn]' if mhn directives are present; otherwise
|
||||
run `\\[mh-mml-to-mime]' if mml directives are present.
|
||||
Insert X-Mailer field if variable `mh-insert-x-mailer-flag' is set.
|
||||
Insert X-Face field if the file specified by `mh-x-face-file' exists."
|
||||
(interactive "P")
|
||||
(run-hooks 'mh-before-send-letter-hook)
|
||||
(cond
|
||||
((and (boundp 'mh-mhn-compose-insert-flag)
|
||||
mh-mhn-compose-insert-flag)
|
||||
(mh-edit-mhn))
|
||||
((and (boundp 'mh-mml-compose-insert-flag)
|
||||
mh-mml-compose-insert-flag)
|
||||
(mh-mml-to-mime)))
|
||||
(cond ((mh-mhn-directive-present-p)
|
||||
(mh-edit-mhn))
|
||||
((mh-mml-directive-present-p)
|
||||
(mh-mml-to-mime)))
|
||||
(if mh-insert-x-mailer-flag (mh-insert-x-mailer))
|
||||
(mh-insert-x-face)
|
||||
(save-buffer)
|
||||
|
@ -1232,7 +1239,7 @@ Insert X-Face field if the file specified by `mh-x-face-file' exists."
|
|||
(mh-goto-header-field "Content-Type:"))
|
||||
(setq mh-send-args (format "-mime %s" mh-send-args)))
|
||||
(cond (arg
|
||||
(pop-to-buffer "MH mail delivery")
|
||||
(pop-to-buffer mh-mail-delivery-buffer)
|
||||
(erase-buffer)
|
||||
(mh-exec-cmd-output mh-send-prog t "-watch" "-nopush"
|
||||
"-nodraftfolder" mh-send-args file-name)
|
||||
|
@ -1339,7 +1346,7 @@ yanked message will be deleted."
|
|||
(eq t mh-yank-from-start-of-msg)))
|
||||
;; supercite needs the full header
|
||||
(concat
|
||||
(buffer-substring (point-min) (mail-header-end))
|
||||
(buffer-substring (point-min) (mh-mail-header-end))
|
||||
"\n"
|
||||
(buffer-substring (region-beginning) (region-end))))
|
||||
(yank-region
|
||||
|
@ -1472,6 +1479,33 @@ This is useful in breaking up paragraphs in replies."
|
|||
(insert " "))
|
||||
(forward-line -1))))
|
||||
|
||||
(mh-do-in-xemacs (defvar mail-abbrevs))
|
||||
|
||||
(defun mh-folder-expand-at-point ()
|
||||
"Do folder name completion in Fcc header field."
|
||||
(let* ((end (point))
|
||||
(syntax-table (syntax-table))
|
||||
(beg (unwind-protect
|
||||
(save-excursion
|
||||
(mh-funcall-if-exists mail-abbrev-make-syntax-table)
|
||||
(set-syntax-table mail-abbrev-syntax-table)
|
||||
(backward-word 1)
|
||||
(point))
|
||||
(set-syntax-table syntax-table)))
|
||||
(folder (buffer-substring beg end))
|
||||
(leading-plus (and (> (length folder) 0) (equal (aref folder 0) ?+)))
|
||||
(last-slash (mh-search-from-end ?/ folder))
|
||||
(prefix (and last-slash (substring folder 0 last-slash)))
|
||||
(mail-abbrevs
|
||||
(mapcar #'(lambda (x)
|
||||
(list (cond (prefix (format "%s/%s" prefix x))
|
||||
(leading-plus (format "+%s" x))
|
||||
(t x))))
|
||||
(mh-folder-completion-function folder nil t))))
|
||||
(if (fboundp 'mail-abbrev-complete-alias)
|
||||
(mh-funcall-if-exists mail-abbrev-complete-alias)
|
||||
(error "Fcc completion not supported in your version of Emacs"))))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-letter-complete (arg)
|
||||
"Perform completion on header field or word preceding point.
|
||||
|
@ -1480,12 +1514,19 @@ by the function designated by `mh-letter-complete-function' elsewhere,
|
|||
passing the prefix ARG if any."
|
||||
(interactive "P")
|
||||
(let ((case-fold-search t))
|
||||
(if (and (mh-in-header-p)
|
||||
(save-excursion
|
||||
(mh-header-field-beginning)
|
||||
(looking-at "^.*\\(to\\|cc\\|from\\):")))
|
||||
(mh-alias-letter-expand-alias)
|
||||
(funcall mh-letter-complete-function arg))))
|
||||
(cond
|
||||
((and (mh-in-header-p)
|
||||
(save-excursion
|
||||
(mh-header-field-beginning)
|
||||
(looking-at "^fcc:")))
|
||||
(mh-folder-expand-at-point))
|
||||
((and (mh-in-header-p)
|
||||
(save-excursion
|
||||
(mh-header-field-beginning)
|
||||
(looking-at "^.*\\(to\\|cc\\|from\\):")))
|
||||
(mh-alias-letter-expand-alias))
|
||||
(t
|
||||
(funcall mh-letter-complete-function arg)))))
|
||||
|
||||
;;; Build the letter-mode keymap:
|
||||
;;; If this changes, modify mh-letter-mode-help-messages accordingly, above.
|
||||
|
@ -1532,6 +1573,8 @@ passing the prefix ARG if any."
|
|||
|
||||
;; "C-c /" prefix is used in mh-letter-mode by pgp.el and mailcrypt.el.
|
||||
|
||||
;;;###autoload(add-to-list 'auto-mode-alist '("/drafts/[0-9]+\\'" . mh-letter-mode))
|
||||
|
||||
(provide 'mh-comp)
|
||||
|
||||
;;; Local Variables:
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,11 @@
|
|||
;;; mh-e.el --- GNU Emacs interface to the MH mail system
|
||||
|
||||
;; Copyright (C) 1985,86,87,88,90,92,93,94,95,97,2000,2001,2002 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 1985, 86, 87, 88, 90, 92, 93, 94, 95, 97, 1999,
|
||||
;; 2000, 01, 02, 2003 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Bill Wohler <wohler@newt.com>
|
||||
;; Maintainer: Bill Wohler <wohler@newt.com>
|
||||
;; Version: 7.2
|
||||
;; Version: 7.3
|
||||
;; Keywords: mail
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
@ -79,8 +80,6 @@
|
|||
;; Maintenance picked up by Bill Wohler <wohler@newt.com> and the
|
||||
;; SourceForge Crew <http://mh-e.sourceforge.net/>. 2001.
|
||||
|
||||
;; $Id: mh-e.el,v 1.262 2003/02/03 19:11:43 wohler Exp $
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl)
|
||||
|
@ -92,6 +91,7 @@
|
|||
(> 50 recursive-load-depth-limit))
|
||||
(setq recursive-load-depth-limit 50)))
|
||||
|
||||
(require 'mh-inc)
|
||||
(require 'mh-utils)
|
||||
(require 'gnus-util)
|
||||
(require 'easymenu)
|
||||
|
@ -102,7 +102,7 @@
|
|||
(defvar font-lock-auto-fontify)
|
||||
(defvar font-lock-defaults)
|
||||
|
||||
(defconst mh-version "7.2" "Version number of MH-E.")
|
||||
(defconst mh-version "7.3" "Version number of MH-E.")
|
||||
|
||||
;;; Autoloads
|
||||
(autoload 'Info-goto-node "info")
|
||||
|
@ -413,7 +413,7 @@ is done highlighting.")
|
|||
(cond
|
||||
((not mh-folder-unseen-seq-cache)
|
||||
nil)
|
||||
((not cur-msg) ;Presumably at end of buffer
|
||||
((>= (point) limit) ;Presumably at end of buffer
|
||||
(setq mh-folder-unseen-seq-cache nil)
|
||||
nil)
|
||||
((member cur-msg mh-folder-unseen-seq-cache)
|
||||
|
@ -432,8 +432,7 @@ is done highlighting.")
|
|||
;; Examine how we must have exited the loop...
|
||||
(let ((cur-msg (mh-get-msg-num nil)))
|
||||
(cond
|
||||
((or (not cur-msg)
|
||||
(<= limit (point))
|
||||
((or (<= limit (point))
|
||||
(not (member cur-msg mh-folder-unseen-seq-cache)))
|
||||
(setq mh-folder-unseen-seq-cache nil)
|
||||
nil)
|
||||
|
@ -468,6 +467,10 @@ is done highlighting.")
|
|||
(defvar mh-narrowed-to-seq nil) ;Sequence display is narrowed to or
|
||||
;nil if not narrowed.
|
||||
|
||||
(defvar mh-tick-seq-changed-when-narrowed-flag nil)
|
||||
;Has tick sequence changed while the
|
||||
;folder was narrowed to it?
|
||||
|
||||
(defvar mh-view-ops ()) ;Stack of ops that change the folder
|
||||
;view (such as narrowing or threading).
|
||||
|
||||
|
@ -535,34 +538,27 @@ the Emacs front end to the MH mail system."
|
|||
|
||||
(defun mh-delete-msg (msg-or-seq)
|
||||
"Mark the specified MSG-OR-SEQ for subsequent deletion and move to the next.
|
||||
|
||||
Default is the displayed message. If optional prefix argument is given then
|
||||
prompt for the message sequence. If variable `transient-mark-mode' is non-nil
|
||||
and the mark is active, then the selected region is marked for deletion."
|
||||
(interactive (list (cond
|
||||
((mh-mark-active-p t)
|
||||
(cons (region-beginning) (region-end)))
|
||||
(current-prefix-arg
|
||||
(mh-read-seq-default "Delete" t))
|
||||
(t
|
||||
(cons (line-beginning-position) (line-end-position))))))
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is marked for deletion.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence."
|
||||
(interactive (list (mh-interactive-msg-or-seq "Delete")))
|
||||
(mh-delete-msg-no-motion msg-or-seq)
|
||||
(mh-next-msg))
|
||||
|
||||
(defun mh-delete-msg-no-motion (msg-or-seq)
|
||||
"Mark the specified MSG-OR-SEQ for subsequent deletion.
|
||||
Default is the displayed message. If optional prefix argument is provided,
|
||||
then prompt for the message sequence."
|
||||
(interactive (list (if current-prefix-arg
|
||||
(mh-read-seq-default "Delete" t)
|
||||
(mh-get-msg-num t))))
|
||||
(cond ((numberp msg-or-seq)
|
||||
(mh-delete-a-msg msg-or-seq))
|
||||
((and (consp msg-or-seq)
|
||||
(numberp (car msg-or-seq)) (numberp (cdr msg-or-seq)))
|
||||
(mh-iterate-on-messages-in-region () (car msg-or-seq) (cdr msg-or-seq)
|
||||
(mh-delete-a-msg nil)))
|
||||
(t (mh-map-to-seq-msgs 'mh-delete-a-msg msg-or-seq))))
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is marked for deletion.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence."
|
||||
(interactive (list (mh-interactive-msg-or-seq "Delete")))
|
||||
(mh-iterate-on-msg-or-seq () msg-or-seq
|
||||
(mh-delete-a-msg nil)))
|
||||
|
||||
(defun mh-execute-commands ()
|
||||
"Process outstanding delete and refile requests."
|
||||
|
@ -593,7 +589,6 @@ Type \"\\[mh-show]\" to show the message normally again."
|
|||
(mh-invalidate-show-buffer))
|
||||
(let ((mh-decode-mime-flag nil)
|
||||
(mhl-formfile nil)
|
||||
(mh-decode-content-transfer-encoded-message-flag nil)
|
||||
(mh-clean-message-header-flag nil))
|
||||
(mh-show-msg nil)
|
||||
(mh-in-show-buffer (mh-show-buffer)
|
||||
|
@ -601,28 +596,31 @@ Type \"\\[mh-show]\" to show the message normally again."
|
|||
(mh-recenter 0))
|
||||
(setq mh-showing-with-headers t)))
|
||||
|
||||
(defun mh-inc-folder (&optional maildrop-name)
|
||||
(defun mh-inc-folder (&optional maildrop-name folder)
|
||||
"Inc(orporate)s new mail into the Inbox folder.
|
||||
Optional argument MAILDROP-NAME specifies an alternate maildrop from the
|
||||
default. If the prefix argument is given, incorporates mail into the current
|
||||
folder, otherwise uses the folder named by `mh-inbox'.
|
||||
default. The optional argument FOLDER specifies where to incorporate mail
|
||||
instead of the default named by `mh-inbox'.
|
||||
The value of `mh-inc-folder-hook' is a list of functions to be called, with no
|
||||
arguments, after incorporating new mail.
|
||||
Do not call this function from outside MH-E; use \\[mh-rmail] instead."
|
||||
(interactive (list (if current-prefix-arg
|
||||
(expand-file-name
|
||||
(read-file-name "inc mail from file: "
|
||||
mh-user-path)))))
|
||||
mh-user-path)))
|
||||
(if current-prefix-arg
|
||||
(mh-prompt-for-folder "inc mail into" mh-inbox t))))
|
||||
(if (not folder)
|
||||
(setq folder mh-inbox))
|
||||
(let ((threading-needed-flag nil))
|
||||
(let ((config (current-window-configuration)))
|
||||
(if (not maildrop-name)
|
||||
(cond ((not (get-buffer mh-inbox))
|
||||
(mh-make-folder mh-inbox)
|
||||
(setq threading-needed-flag mh-show-threads-flag)
|
||||
(setq mh-previous-window-config config))
|
||||
((not (eq (current-buffer) (get-buffer mh-inbox)))
|
||||
(switch-to-buffer mh-inbox)
|
||||
(setq mh-previous-window-config config)))))
|
||||
(cond ((not (get-buffer folder))
|
||||
(mh-make-folder folder)
|
||||
(setq threading-needed-flag mh-show-threads-flag)
|
||||
(setq mh-previous-window-config config))
|
||||
((not (eq (current-buffer) (get-buffer folder)))
|
||||
(switch-to-buffer folder)
|
||||
(setq mh-previous-window-config config))))
|
||||
(mh-get-new-mail maildrop-name)
|
||||
(when (and threading-needed-flag
|
||||
(save-excursion
|
||||
|
@ -632,7 +630,8 @@ Do not call this function from outside MH-E; use \\[mh-rmail] instead."
|
|||
(and (message "Not threading since the number of messages exceeds `mh-large-folder'")
|
||||
nil))))
|
||||
(mh-toggle-threads))
|
||||
(if mh-showing-mode (mh-show))
|
||||
(beginning-of-line)
|
||||
(if (and mh-showing-mode (looking-at mh-scan-valid-regexp)) (mh-show))
|
||||
(run-hooks 'mh-inc-folder-hook)))
|
||||
|
||||
(defun mh-last-msg ()
|
||||
|
@ -643,8 +642,10 @@ Do not call this function from outside MH-E; use \\[mh-rmail] instead."
|
|||
(forward-line -1))
|
||||
(mh-recenter nil))
|
||||
|
||||
(defun mh-next-undeleted-msg (&optional arg)
|
||||
"Move to the next undeleted message ARG in window."
|
||||
(defun mh-next-undeleted-msg (&optional arg wait-after-complaining-flag)
|
||||
"Move to the next undeleted message ARG in window.
|
||||
If optional argument WAIT-AFTER-COMPLAINING-FLAG is non-nil and we are at the
|
||||
last undeleted message then pause for a second after printing message."
|
||||
(interactive "p")
|
||||
(setq mh-next-direction 'forward)
|
||||
(forward-line 1)
|
||||
|
@ -652,38 +653,73 @@ Do not call this function from outside MH-E; use \\[mh-rmail] instead."
|
|||
(beginning-of-line)
|
||||
(mh-maybe-show))
|
||||
(t (forward-line -1)
|
||||
(message "No more undeleted messages"))))
|
||||
(message "No more undeleted messages")
|
||||
(if wait-after-complaining-flag (sit-for 1)))))
|
||||
|
||||
(defun mh-folder-from-address ()
|
||||
"Determine folder name from address in From field.
|
||||
Takes the address in the From: header field, and returns one of:
|
||||
|
||||
a) The folder name associated with the address in the alist
|
||||
`mh-default-folder-list'.
|
||||
`mh-default-folder-list'. If the `Check Recipient' boolean
|
||||
is set, then the `mh-default-folder-list' addresses are
|
||||
checked against the recipient instead of the originator
|
||||
(making possible to use this feature for mailing lists).
|
||||
The first match found in `mh-default-folder-list' is used.
|
||||
|
||||
b) The address' corresponding alias from the user's personal
|
||||
aliases file prefixed by `mh-default-folder-prefix'.
|
||||
|
||||
Returns nil if the address was not found in either place or if the variable
|
||||
`mh-default-folder-must-exist-flag' is nil and the folder does not exist."
|
||||
;; Is address in mh-default-folder-list?
|
||||
(let* ((address
|
||||
(nth 1 (mail-extract-address-components
|
||||
(mh-extract-from-header-value))))
|
||||
(folder-name
|
||||
(nth 1 (assoc-ignore-case address mh-default-folder-list))))
|
||||
;; Loop for all entries in mh-default-folder-list
|
||||
(save-excursion
|
||||
(let ((folder-name
|
||||
(car
|
||||
(delq nil
|
||||
(mapcar
|
||||
(lambda (list)
|
||||
(let ((address-regexp (nth 0 list))
|
||||
(folder (nth 1 list))
|
||||
(to-flag (nth 2 list)))
|
||||
(when (or
|
||||
(mh-goto-header-field (if to-flag "To:" "From:"))
|
||||
; if the To: field is missing, try Cc:
|
||||
(and to-flag (mh-goto-header-field "cc:")))
|
||||
(let ((endfield (save-excursion
|
||||
(mh-header-field-end)(point))))
|
||||
(if (re-search-forward address-regexp endfield t)
|
||||
folder
|
||||
(when to-flag ;Try Cc: as well
|
||||
(mh-goto-header-field "cc:")
|
||||
(let ((endfield (save-excursion
|
||||
(mh-header-field-end)(point))))
|
||||
(when (re-search-forward
|
||||
address-regexp endfield t)
|
||||
folder))))))))
|
||||
mh-default-folder-list)))))
|
||||
|
||||
;; If not, is there an alias for the address?
|
||||
(if (not folder-name)
|
||||
(let* ((alias (mh-alias-address-to-alias address)))
|
||||
(setq folder-name
|
||||
(and alias (concat "+" mh-default-folder-prefix alias)))))
|
||||
;; Make sure a result from `mh-default-folder-list' begins with "+"
|
||||
;; since 'mh-expand-file-name below depends on it
|
||||
(when (and folder-name (not (eq (aref folder-name 0) ?+)))
|
||||
(setq folder-name (concat "+" folder-name)))
|
||||
|
||||
;; If mh-default-folder-must-exist-flag set, check that folder exists.
|
||||
(if (and folder-name
|
||||
(or (not mh-default-folder-must-exist-flag)
|
||||
(file-exists-p (mh-expand-file-name folder-name))))
|
||||
folder-name)))
|
||||
;; If not, is there an alias for the address?
|
||||
(when (not folder-name)
|
||||
(let* ((from-header (mh-extract-from-header-value))
|
||||
(address (and from-header
|
||||
(nth 1 (mail-extract-address-components
|
||||
from-header))))
|
||||
(alias (and address (mh-alias-address-to-alias address))))
|
||||
(when alias
|
||||
(setq folder-name
|
||||
(and alias (concat "+" mh-default-folder-prefix alias))))))
|
||||
|
||||
;; If mh-default-folder-must-exist-flag set, check that folder exists.
|
||||
(if (and folder-name
|
||||
(or (not mh-default-folder-must-exist-flag)
|
||||
(file-exists-p (mh-expand-file-name folder-name))))
|
||||
folder-name))))
|
||||
|
||||
(defun mh-prompt-for-refile-folder ()
|
||||
"Prompt the user for a folder in which the message should be filed.
|
||||
|
@ -710,29 +746,26 @@ Otherwise, a default folder name is generated by `mh-folder-from-address'."
|
|||
"")))
|
||||
t))
|
||||
|
||||
(defun mh-refile-msg (msg-or-seq folder)
|
||||
"Refile MSG-OR-SEQ (default: displayed message) into FOLDER.
|
||||
If optional prefix argument provided, then prompt for message sequence.
|
||||
(defun mh-refile-msg (msg-or-seq folder
|
||||
&optional dont-update-last-destination-flag)
|
||||
"Refile MSG-OR-SEQ into FOLDER.
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is marked for refiling."
|
||||
(interactive
|
||||
(list (cond
|
||||
((mh-mark-active-p t)
|
||||
(cons (region-beginning) (region-end)))
|
||||
(current-prefix-arg
|
||||
(mh-read-seq-default "Refile" t))
|
||||
(t
|
||||
(cons (line-beginning-position) (line-end-position))))
|
||||
(intern (mh-prompt-for-refile-folder))))
|
||||
(setq mh-last-destination (cons 'refile folder)
|
||||
mh-last-destination-folder mh-last-destination)
|
||||
(cond ((numberp msg-or-seq)
|
||||
(mh-refile-a-msg msg-or-seq folder))
|
||||
((and (consp msg-or-seq)
|
||||
(numberp (car msg-or-seq)) (numberp (cdr msg-or-seq)))
|
||||
(mh-iterate-on-messages-in-region () (car msg-or-seq) (cdr msg-or-seq)
|
||||
(mh-refile-a-msg nil folder)))
|
||||
(t (mh-map-to-seq-msgs 'mh-refile-a-msg msg-or-seq folder)))
|
||||
selected region is marked for refiling.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence.
|
||||
|
||||
If optional argument DONT-UPDATE-LAST-DESTINATION-FLAG is non-nil then the
|
||||
variables `mh-last-destination' and `mh-last-destination-folder' are not
|
||||
updated."
|
||||
(interactive (list (mh-interactive-msg-or-seq "Refile")
|
||||
(intern (mh-prompt-for-refile-folder))))
|
||||
(unless dont-update-last-destination-flag
|
||||
(setq mh-last-destination (cons 'refile folder)
|
||||
mh-last-destination-folder mh-last-destination))
|
||||
(mh-iterate-on-msg-or-seq () msg-or-seq
|
||||
(mh-refile-a-msg nil folder))
|
||||
(mh-next-msg))
|
||||
|
||||
(defun mh-refile-or-write-again (message)
|
||||
|
@ -742,13 +775,16 @@ refile or write command."
|
|||
(interactive (list (mh-get-msg-num t)))
|
||||
(if (null mh-last-destination)
|
||||
(error "No previous refile or write"))
|
||||
(cond ((eq (car mh-last-destination) 'refile)
|
||||
(mh-refile-a-msg message (cdr mh-last-destination))
|
||||
(message "Destination folder: %s" (cdr mh-last-destination)))
|
||||
(t
|
||||
(apply 'mh-write-msg-to-file message (cdr mh-last-destination))
|
||||
(message "Destination: %s" (cdr mh-last-destination))))
|
||||
(mh-next-msg))
|
||||
(let (output)
|
||||
(setq output
|
||||
(cond ((eq (car mh-last-destination) 'refile)
|
||||
(mh-refile-a-msg message (cdr mh-last-destination))
|
||||
(format "Destination folder: %s" (cdr mh-last-destination)))
|
||||
(t
|
||||
(apply 'mh-write-msg-to-file message (cdr mh-last-destination))
|
||||
(format "Destination: %s" (cdr mh-last-destination)))))
|
||||
(mh-next-msg (interactive-p))
|
||||
(message output)))
|
||||
|
||||
(defun mh-quit ()
|
||||
"Quit the current MH-E folder.
|
||||
|
@ -809,14 +845,17 @@ Scrolls ARG lines or a full screen if no argument is supplied."
|
|||
(mh-in-show-buffer (mh-show-buffer)
|
||||
(scroll-down arg)))
|
||||
|
||||
(defun mh-previous-undeleted-msg (&optional arg)
|
||||
"Move to the previous undeleted message ARG in window."
|
||||
(defun mh-previous-undeleted-msg (&optional arg wait-after-complaining-flag)
|
||||
"Move to the previous undeleted message ARG in window.
|
||||
If optional argument WAIT-AFTER-COMPLAINING-FLAG is non-nil and we are at the
|
||||
first undeleted message then pause for a second after printing message."
|
||||
(interactive "p")
|
||||
(setq mh-next-direction 'backward)
|
||||
(beginning-of-line)
|
||||
(cond ((re-search-backward mh-scan-good-msg-regexp nil t arg)
|
||||
(mh-maybe-show))
|
||||
(t (message "No previous undeleted message"))))
|
||||
(t (message "No previous undeleted message")
|
||||
(if wait-after-complaining-flag (sit-for 1)))))
|
||||
|
||||
(defun mh-previous-unread-msg (&optional count)
|
||||
"Move to previous unread message.
|
||||
|
@ -994,7 +1033,6 @@ refiles aren't carried out."
|
|||
nil)))
|
||||
(setq mh-next-direction 'forward)
|
||||
(let ((threaded-flag (memq 'unthread mh-view-ops)))
|
||||
(mh-reset-threads-and-narrowing)
|
||||
(mh-scan-folder mh-current-folder (or range "all") dont-exec-pending)
|
||||
(cond (threaded-flag (mh-toggle-threads))
|
||||
(mh-index-data (mh-index-insert-folder-headers)))))
|
||||
|
@ -1040,14 +1078,10 @@ Otherwise send the entire message including the headers."
|
|||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is unmarked."
|
||||
(interactive (list (cond
|
||||
((mh-mark-active-p t)
|
||||
(cons (region-beginning) (region-end)))
|
||||
(current-prefix-arg
|
||||
(mh-read-seq-default "Undo" t))
|
||||
(t
|
||||
(mh-get-msg-num t)))))
|
||||
selected region is unmarked.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence."
|
||||
(interactive (list (mh-interactive-msg-or-seq "Undo")))
|
||||
(cond ((numberp msg-or-seq)
|
||||
(let ((original-position (point)))
|
||||
(beginning-of-line)
|
||||
|
@ -1064,12 +1098,8 @@ selected region is unmarked."
|
|||
(mh-maybe-show))
|
||||
(goto-char original-position)
|
||||
(error "Nothing to undo"))))
|
||||
((and (consp msg-or-seq)
|
||||
(numberp (car msg-or-seq)) (numberp (cdr msg-or-seq)))
|
||||
(mh-iterate-on-messages-in-region () (car msg-or-seq) (cdr msg-or-seq)
|
||||
(mh-undo-msg nil)))
|
||||
(t
|
||||
(mh-map-to-seq-msgs 'mh-undo-msg msg-or-seq)))
|
||||
(t (mh-iterate-on-msg-or-seq () msg-or-seq
|
||||
(mh-undo-msg nil))))
|
||||
(if (not (mh-outstanding-commands-p))
|
||||
(mh-set-folder-modified-p nil)))
|
||||
|
||||
|
@ -1176,10 +1206,10 @@ used to avoid problems in corner cases involving folders whose names end with a
|
|||
(call-process (expand-file-name "flist" mh-progs) nil t nil
|
||||
"-norecurse" folder "-sequence" (symbol-name mh-unseen-seq))
|
||||
(goto-char (point-min))
|
||||
(multiple-value-bind (folder1 unseen total)
|
||||
(multiple-value-bind (folder unseen total)
|
||||
(mh-parse-flist-output-line
|
||||
(buffer-substring (point) (line-end-position)))
|
||||
(values total unseen))))
|
||||
(values total unseen folder))))
|
||||
|
||||
(defun mh-visit-folder (folder &optional range index-data)
|
||||
"Visit FOLDER and display RANGE of messages.
|
||||
|
@ -1197,12 +1227,12 @@ regardless of the size of the `mh-large-folder' variable."
|
|||
(list folder-name
|
||||
(mh-read-msg-range folder-name current-prefix-arg))))
|
||||
(let ((config (current-window-configuration))
|
||||
(current-buffer (current-buffer))
|
||||
(threaded-view-flag mh-show-threads-flag))
|
||||
(save-excursion
|
||||
(when (get-buffer folder)
|
||||
(set-buffer folder)
|
||||
(setq threaded-view-flag (memq 'unthread mh-view-ops))
|
||||
(mh-reset-threads-and-narrowing)))
|
||||
(setq threaded-view-flag (memq 'unthread mh-view-ops))))
|
||||
(when index-data
|
||||
(mh-make-folder folder)
|
||||
(setq mh-index-data (car index-data)
|
||||
|
@ -1221,7 +1251,8 @@ regardless of the size of the `mh-large-folder' variable."
|
|||
(mh-index-data
|
||||
(mh-index-insert-folder-headers)))
|
||||
(unless mh-showing-mode (delete-other-windows))
|
||||
(setq mh-previous-window-config config))
|
||||
(unless (eq current-buffer (current-buffer))
|
||||
(setq mh-previous-window-config config)))
|
||||
nil)
|
||||
|
||||
;;;###mh-autoload
|
||||
|
@ -1305,11 +1336,14 @@ arguments, after the message has been refiled."
|
|||
(mh-notate nil mh-note-refiled mh-cmd-note)
|
||||
(run-hooks 'mh-refile-msg-hook)))))
|
||||
|
||||
(defun mh-next-msg ()
|
||||
"Move backward or forward to the next undeleted message in the buffer."
|
||||
(defun mh-next-msg (&optional wait-after-complaining-flag)
|
||||
"Move backward or forward to the next undeleted message in the buffer.
|
||||
If optional argument WAIT-AFTER-COMPLAINING-FLAG is non-nil and we are at the
|
||||
last message, then wait for a second after telling the user that there aren't
|
||||
any more unread messages."
|
||||
(if (eq mh-next-direction 'forward)
|
||||
(mh-next-undeleted-msg 1)
|
||||
(mh-previous-undeleted-msg 1)))
|
||||
(mh-next-undeleted-msg 1 wait-after-complaining-flag)
|
||||
(mh-previous-undeleted-msg 1 wait-after-complaining-flag)))
|
||||
|
||||
(defun mh-next-unread-msg (&optional count)
|
||||
"Move to next unread message.
|
||||
|
@ -1406,7 +1440,10 @@ Make it the current folder."
|
|||
["Widen from Sequence" mh-widen mh-narrowed-to-seq]
|
||||
"--"
|
||||
["Narrow to Subject Sequence" mh-narrow-to-subject t]
|
||||
["Narrow to Tick Sequence" mh-narrow-to-tick
|
||||
(and mh-tick-seq (mh-seq-msgs (mh-find-seq mh-tick-seq)))]
|
||||
["Delete Rest of Same Subject" mh-delete-subject t]
|
||||
["Toggle Tick Mark" mh-toggle-tick t]
|
||||
"--"
|
||||
["Push State Out to MH" mh-update-sequences t]))
|
||||
|
||||
|
@ -1459,6 +1496,7 @@ Make it the current folder."
|
|||
"--"
|
||||
["List Folders" mh-list-folders t]
|
||||
["Visit a Folder..." mh-visit-folder t]
|
||||
["View New Messages" mh-index-new-messages t]
|
||||
["Search a Folder..." mh-search-folder t]
|
||||
["Indexed Search..." mh-index-search t]
|
||||
"--"
|
||||
|
@ -1474,6 +1512,9 @@ Make it the current folder."
|
|||
(set-specifier horizontal-scrollbar-visible-p nil
|
||||
(cons (current-buffer) nil)))))
|
||||
|
||||
;; Avoid compiler warnings in XEmacs and GNU Emacs 20
|
||||
(eval-when-compile (defvar tool-bar-mode))
|
||||
|
||||
(defmacro mh-write-file-functions-compat ()
|
||||
"Return `write-file-functions' if it exists.
|
||||
Otherwise return `local-write-file-hooks'. This macro exists purely for
|
||||
|
@ -1483,6 +1524,9 @@ is used in previous versions and XEmacs."
|
|||
''write-file-functions ;Emacs 21.4
|
||||
''local-write-file-hooks)) ;<Emacs 21.4, XEmacs
|
||||
|
||||
;; Avoid compiler warning
|
||||
(defvar tool-bar-map)
|
||||
|
||||
(define-derived-mode mh-folder-mode fundamental-mode "MH-Folder"
|
||||
"Major MH-E mode for \"editing\" an MH folder scan listing.\\<mh-folder-mode-map>
|
||||
|
||||
|
@ -1519,6 +1563,8 @@ When a folder is visited, the hook `mh-folder-mode-hook' is run.
|
|||
'mh-seen-list nil ; List of displayed messages
|
||||
'mh-next-direction 'forward ; Direction to move to next message
|
||||
'mh-narrowed-to-seq nil ; Sequence display is narrowed to
|
||||
'mh-tick-seq-changed-when-narrowed-flag nil
|
||||
; Tick seq changed while narrowed
|
||||
'mh-view-ops () ; Stack that keeps track of the order
|
||||
; in which narrowing/threading has been
|
||||
; carried out.
|
||||
|
@ -1537,11 +1583,11 @@ When a folder is visited, the hook `mh-folder-mode-hook' is run.
|
|||
(setq truncate-lines t)
|
||||
(auto-save-mode -1)
|
||||
(setq buffer-offer-save t)
|
||||
(mh-make-local-hook (mh-write-file-functions-compat))
|
||||
(add-hook (mh-write-file-functions-compat) 'mh-execute-commands nil t)
|
||||
(make-local-variable 'revert-buffer-function)
|
||||
(make-local-variable 'hl-line-mode) ; avoid pollution
|
||||
(if (fboundp 'hl-line-mode)
|
||||
(hl-line-mode 1))
|
||||
(mh-funcall-if-exists hl-line-mode 1)
|
||||
(setq revert-buffer-function 'mh-undo-folder)
|
||||
(or (assq 'mh-showing-mode minor-mode-alist)
|
||||
(setq minor-mode-alist
|
||||
|
@ -1551,6 +1597,7 @@ When a folder is visited, the hook `mh-folder-mode-hook' is run.
|
|||
(easy-menu-add mh-folder-folder-menu)
|
||||
(if (and (boundp 'tool-bar-mode) tool-bar-mode)
|
||||
(set (make-local-variable 'tool-bar-map) mh-folder-tool-bar-map))
|
||||
(mh-funcall-if-exists mh-toolbar-init :folder)
|
||||
(if (and mh-xemacs-flag
|
||||
font-lock-auto-fontify)
|
||||
(turn-on-font-lock))) ; Force font-lock in XEmacs.
|
||||
|
@ -1570,7 +1617,9 @@ Return in the folder's buffer."
|
|||
(cond ((null (get-buffer folder))
|
||||
(mh-make-folder folder))
|
||||
(t
|
||||
(or dont-exec-pending (mh-process-or-undo-commands folder))
|
||||
(unless dont-exec-pending
|
||||
(mh-process-or-undo-commands folder)
|
||||
(mh-reset-threads-and-narrowing))
|
||||
(switch-to-buffer folder)))
|
||||
(mh-regenerate-headers range)
|
||||
(if (zerop (buffer-size))
|
||||
|
@ -1578,7 +1627,7 @@ Return in the folder's buffer."
|
|||
(message "Folder %s is empty" folder)
|
||||
(message "No messages in %s, range %s" folder range))
|
||||
(mh-goto-cur-msg))
|
||||
(when dont-exec-pending
|
||||
(when (mh-outstanding-commands-p)
|
||||
(mh-notate-deleted-and-refiled)))
|
||||
|
||||
(defun mh-set-cmd-note (width)
|
||||
|
@ -1742,6 +1791,8 @@ Return in the current buffer."
|
|||
(if new-mail-flag
|
||||
(progn
|
||||
(mh-make-folder-mode-line)
|
||||
(when (mh-speed-flists-active-p)
|
||||
(mh-speed-flists t mh-current-folder))
|
||||
(when (memq 'unthread mh-view-ops)
|
||||
(mh-thread-inc folder start-of-inc))
|
||||
(mh-goto-cur-msg))
|
||||
|
@ -1861,8 +1912,9 @@ Called by functions like `mh-sort-folder', so also invalidate show buffer."
|
|||
(if (mh-outstanding-commands-p)
|
||||
(if (or mh-do-not-confirm-flag
|
||||
(y-or-n-p
|
||||
"Process outstanding deletes and refiles (or lose them)? "))
|
||||
"Process outstanding deletes and refiles? "))
|
||||
(mh-process-commands folder)
|
||||
(set-buffer folder)
|
||||
(mh-undo-folder)))
|
||||
(mh-update-unseen)
|
||||
(mh-invalidate-show-buffer))
|
||||
|
@ -1914,6 +1966,8 @@ with no arguments, before the commands are processed."
|
|||
|
||||
;; Redraw folder buffer if needed
|
||||
(when (and redraw-needed-flag)
|
||||
(when (mh-speed-flists-active-p)
|
||||
(mh-speed-flists t mh-current-folder))
|
||||
(cond ((memq 'unthread mh-view-ops) (mh-thread-inc folder (point-max)))
|
||||
(mh-index-data (mh-index-insert-folder-headers)))))
|
||||
|
||||
|
@ -1962,10 +2016,10 @@ with no arguments, after the unseen sequence is updated."
|
|||
(or mh-delete-list mh-refile-list))
|
||||
|
||||
(defun mh-coalesce-msg-list (messages)
|
||||
"Give a list of MESSAGES, return a list of message number ranges.
|
||||
Sort of the opposite of `mh-read-msg-list', which expands ranges.
|
||||
Message lists passed to MH programs go through this so
|
||||
command line arguments won't exceed system limits."
|
||||
"Given a list of MESSAGES, return a list of message number ranges.
|
||||
This is the inverse of `mh-read-msg-list', which expands ranges.
|
||||
Message lists passed to MH programs should be processed by this function
|
||||
to avoid exceeding system command line argument limits."
|
||||
(let ((msgs (sort (copy-sequence messages) 'mh-greaterp))
|
||||
(range-high nil)
|
||||
(prev -1)
|
||||
|
@ -2059,44 +2113,84 @@ Expands ranges into set of individual numbers."
|
|||
(setq msgs (cons num msgs)))))
|
||||
msgs))
|
||||
|
||||
(defun mh-notate-user-sequences ()
|
||||
"Mark the scan listing of all messages in user-defined sequences."
|
||||
(defun mh-notate-user-sequences (&optional msg-or-seq)
|
||||
"Mark user-defined sequences in the messages specified by MSG-OR-SEQ.
|
||||
The optional argument MSG-OR-SEQ can be a message number, a list of message
|
||||
numbers, a sequence, a region in a cons cell, or nil in which case all
|
||||
messages in the folder buffer are notated."
|
||||
(unless msg-or-seq
|
||||
(setq msg-or-seq (cons (point-min) (point-max))))
|
||||
(let ((seqs mh-seq-list)
|
||||
(msg-hash (make-hash-table)))
|
||||
(msg-hash (make-hash-table))
|
||||
(tick-msgs (and mh-tick-seq (mh-seq-msgs (mh-find-seq mh-tick-seq)))))
|
||||
(dolist (seq seqs)
|
||||
(unless (mh-internal-seq (mh-seq-name seq))
|
||||
(dolist (msg (mh-seq-msgs seq))
|
||||
(setf (gethash msg msg-hash) t))))
|
||||
(mh-iterate-on-messages-in-region msg (point-min) (point-max)
|
||||
(mh-iterate-on-msg-or-seq msg msg-or-seq
|
||||
(when (gethash msg msg-hash)
|
||||
(mh-notate nil mh-note-seq (1+ mh-cmd-note))))))
|
||||
(mh-notate nil mh-note-seq (1+ mh-cmd-note)))
|
||||
(mh-notate-tick msg tick-msgs))))
|
||||
|
||||
(defun mh-internal-seq (name)
|
||||
"Return non-nil if NAME is the name of an internal MH-E sequence."
|
||||
(or (memq name '(answered cur deleted forwarded printed))
|
||||
(eq name mh-unseen-seq)
|
||||
(and mh-tick-seq (eq name mh-tick-seq))
|
||||
(eq name mh-previous-seq)
|
||||
(mh-folder-name-p name)))
|
||||
|
||||
(defun mh-delete-msg-from-seq (message sequence &optional internal-flag)
|
||||
"Delete MESSAGE from SEQUENCE.
|
||||
MESSAGE defaults to displayed message. From Lisp, optional third arg
|
||||
INTERNAL-FLAG non-nil means do not inform MH of the change."
|
||||
(interactive (list (mh-get-msg-num t)
|
||||
(defun mh-delete-msg-from-seq (msg-or-seq sequence &optional internal-flag)
|
||||
"Delete MSG-OR-SEQ from SEQUENCE.
|
||||
Default value of MSG-OR-SEQ is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is deleted from SEQUENCE..
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence; optional third arg INTERNAL-FLAG non-nil
|
||||
means do not inform MH of the change."
|
||||
(interactive (list (mh-interactive-msg-or-seq "Delete")
|
||||
(mh-read-seq-default "Delete from" t)
|
||||
nil))
|
||||
(let ((entry (mh-find-seq sequence)))
|
||||
(cond (entry
|
||||
(mh-notate-if-in-one-seq message ? (1+ mh-cmd-note) sequence)
|
||||
(if (not internal-flag)
|
||||
(mh-undefine-sequence sequence (list message)))
|
||||
(setcdr entry (delq message (mh-seq-msgs entry)))))))
|
||||
(when entry
|
||||
(mh-iterate-on-msg-or-seq msg msg-or-seq
|
||||
(when (memq msg (mh-seq-msgs entry))
|
||||
(mh-notate nil ? (1+ mh-cmd-note)))
|
||||
(mh-delete-a-msg-from-seq msg sequence internal-flag)
|
||||
(mh-clear-text-properties nil))
|
||||
(mh-notate-user-sequences msg-or-seq)
|
||||
(when (and (eq sequence mh-unseen-seq) (mh-speed-flists-active-p))
|
||||
(mh-speed-flists t mh-current-folder)))))
|
||||
|
||||
(defun mh-delete-a-msg-from-seq (msg sequence internal-flag)
|
||||
"Delete MSG from SEQUENCE.
|
||||
If INTERNAL-FLAG is non-nil, then do not inform MH of the change."
|
||||
(let ((entry (mh-find-seq sequence)))
|
||||
(when (and entry (memq msg (mh-seq-msgs entry)))
|
||||
(if (not internal-flag)
|
||||
(mh-undefine-sequence sequence (list msg)))
|
||||
(setcdr entry (delq msg (mh-seq-msgs entry))))))
|
||||
|
||||
(defun mh-clear-text-properties (message)
|
||||
"Clear all text properties (except mh-tick) from the scan line for MESSAGE."
|
||||
(save-excursion
|
||||
(with-mh-folder-updating (t)
|
||||
(when (or (not message) (mh-goto-msg message t t))
|
||||
(beginning-of-line)
|
||||
(let ((tick-property (get-text-property (point) 'mh-tick)))
|
||||
(set-text-properties (point) (line-end-position) nil)
|
||||
(when tick-property
|
||||
(add-text-properties (point) (line-end-position)
|
||||
`(mh-tick ,tick-property))))))))
|
||||
|
||||
(defun mh-undefine-sequence (seq msgs)
|
||||
"Remove from the SEQ the list of MSGS."
|
||||
(mh-exec-cmd "mark" mh-current-folder "-delete"
|
||||
"-sequence" (symbol-name seq)
|
||||
(mh-coalesce-msg-list msgs)))
|
||||
(prog1 (mh-exec-cmd "mark" mh-current-folder "-delete"
|
||||
"-sequence" (symbol-name seq)
|
||||
(mh-coalesce-msg-list msgs))
|
||||
(when (and (eq seq mh-unseen-seq) (mh-speed-flists-active-p))
|
||||
(mh-speed-flists t mh-current-folder))))
|
||||
|
||||
(defun mh-define-sequence (seq msgs)
|
||||
"Define the SEQ to contain the list of MSGS.
|
||||
|
@ -2181,6 +2275,7 @@ range."
|
|||
(gnus-define-keys mh-folder-mode-map
|
||||
" " mh-page-msg
|
||||
"!" mh-refile-or-write-again
|
||||
"'" mh-toggle-tick
|
||||
"," mh-header-display
|
||||
"." mh-alt-show
|
||||
">" mh-write-msg-to-file
|
||||
|
@ -2227,6 +2322,7 @@ range."
|
|||
"i" mh-index-search
|
||||
"k" mh-kill-folder
|
||||
"l" mh-list-folders
|
||||
"n" mh-index-new-messages
|
||||
"o" mh-alt-visit-folder
|
||||
"p" mh-pack-folder
|
||||
"r" mh-rescan-folder
|
||||
|
@ -2234,6 +2330,13 @@ range."
|
|||
"u" mh-undo-folder
|
||||
"v" mh-visit-folder)
|
||||
|
||||
(define-key mh-folder-mode-map "I" mh-inc-spool-map)
|
||||
|
||||
(gnus-define-keys (mh-junk-map "J" mh-folder-mode-map)
|
||||
"?" mh-prefix-help
|
||||
"b" mh-junk-blacklist
|
||||
"w" mh-junk-whitelist)
|
||||
|
||||
(gnus-define-keys (mh-sequence-map "S" mh-folder-mode-map)
|
||||
"?" mh-prefix-help
|
||||
"d" mh-delete-msg-from-seq
|
||||
|
@ -2254,6 +2357,7 @@ range."
|
|||
"o" mh-thread-refile)
|
||||
|
||||
(gnus-define-keys (mh-limit-map "/" mh-folder-mode-map)
|
||||
"'" mh-narrow-to-tick
|
||||
"?" mh-prefix-help
|
||||
"s" mh-narrow-to-subject
|
||||
"w" mh-widen)
|
||||
|
@ -2304,8 +2408,8 @@ range."
|
|||
'((nil "[i]nc, [.]show, [,]show all, [n]ext, [p]revious,\n"
|
||||
"[d]elete, [o]refile, e[x]ecute,\n"
|
||||
"[s]end, [r]eply.\n"
|
||||
"Prefix characters:\n [F]older, [S]equence, MIME [K]eys, "
|
||||
"[T]hread, / Limit, e[X]tract, [D]igest.")
|
||||
"Prefix characters:\n [F]older, [S]equence, [J]unk, MIME [K]eys,"
|
||||
"\n [T]hread, / Limit, e[X]tract, [D]igest, [I]nc spools.")
|
||||
|
||||
(?F "[l]ist, [v]isit folder;\n"
|
||||
"[t]hread; [s]earch; [i]ndexed search;\n"
|
||||
|
@ -2318,7 +2422,8 @@ range."
|
|||
(?X "un[s]har, [u]udecode message")
|
||||
(?D "[b]urst digest")
|
||||
(?K "[v]iew, [i]nline, [o]utput/save MIME part; save [a]ll parts; \n"
|
||||
"[TAB] next; [SHIFT-TAB] previous"))
|
||||
"[TAB] next; [SHIFT-TAB] previous")
|
||||
(?J "[b]lacklist, [w]hitelist message"))
|
||||
"Key binding cheat sheet.
|
||||
|
||||
This is an associative array which is used to show the most common commands.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
;;; mh-funcs.el --- MH-E functions not everyone will use right away
|
||||
|
||||
;; Copyright (C) 1993, 1995, 2001, 2002 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 1993, 1995, 2001, 02, 2003 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Bill Wohler <wohler@newt.com>
|
||||
;; Maintainer: Bill Wohler <wohler@newt.com>
|
||||
|
@ -32,8 +32,6 @@
|
|||
|
||||
;;; Change Log:
|
||||
|
||||
;; $Id: mh-funcs.el,v 1.2 2003/02/03 20:55:30 wohler Exp $
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'mh-e)
|
||||
|
@ -76,33 +74,21 @@ digest are inserted into the folder after that message."
|
|||
;;;###mh-autoload
|
||||
(defun mh-copy-msg (msg-or-seq folder)
|
||||
"Copy the specified MSG-OR-SEQ to another FOLDER without deleting them.
|
||||
Default is the displayed message. If optional prefix argument is provided,
|
||||
then prompt for the message sequence."
|
||||
(interactive (list (cond
|
||||
((mh-mark-active-p t)
|
||||
(cons (region-beginning) (region-end)))
|
||||
(current-prefix-arg
|
||||
(mh-read-seq-default "Copy" t))
|
||||
(t
|
||||
(cons (line-beginning-position) (line-end-position))))
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is copied.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence."
|
||||
(interactive (list (mh-interactive-msg-or-seq "Copy")
|
||||
(mh-prompt-for-folder "Copy to" "" t)))
|
||||
(let ((msg-list (cond ((numberp msg-or-seq) (list msg-or-seq))
|
||||
((symbolp msg-or-seq) (mh-seq-to-msgs msg-or-seq))
|
||||
((and (consp msg-or-seq) (numberp (car msg-or-seq))
|
||||
(numberp (cdr msg-or-seq)))
|
||||
(let ((result ()))
|
||||
(mh-iterate-on-messages-in-region msg
|
||||
(car msg-or-seq) (cdr msg-or-seq)
|
||||
(mh-notate nil mh-note-copied mh-cmd-note)
|
||||
(push msg result))
|
||||
result))
|
||||
(t msg-or-seq))))
|
||||
(let ((msg-list (let ((result ()))
|
||||
(mh-iterate-on-msg-or-seq msg msg-or-seq
|
||||
(mh-notate nil mh-note-copied mh-cmd-note)
|
||||
(push msg result))
|
||||
result)))
|
||||
(mh-exec-cmd "refile" (mh-coalesce-msg-list msg-list)
|
||||
"-link" "-src" mh-current-folder folder)
|
||||
(cond ((numberp msg-or-seq)
|
||||
(mh-notate msg-or-seq mh-note-copied mh-cmd-note))
|
||||
((symbolp msg-or-seq)
|
||||
(mh-notate-seq msg-or-seq mh-note-copied mh-cmd-note)))))
|
||||
"-link" "-src" mh-current-folder folder)))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-kill-folder ()
|
||||
|
@ -111,7 +97,7 @@ Removes all of the messages (files) within the specified current folder,
|
|||
and then removes the folder (directory) itself."
|
||||
(interactive)
|
||||
(if (or mh-index-data
|
||||
(yes-or-no-p (format "Remove folder %s (and all included messages)?"
|
||||
(yes-or-no-p (format "Remove folder %s (and all included messages)? "
|
||||
mh-current-folder)))
|
||||
(let ((folder mh-current-folder)
|
||||
(window-config mh-previous-window-config))
|
||||
|
@ -246,57 +232,60 @@ Otherwise just send the message's body without the headers."
|
|||
|
||||
;;;###mh-autoload
|
||||
(defun mh-print-msg (msg-or-seq)
|
||||
"Print MSG-OR-SEQ (default: displayed message) on printer.
|
||||
If optional prefix argument provided, then prompt for the message sequence.
|
||||
"Print MSG-OR-SEQ on printer.
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is printed.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence.
|
||||
|
||||
The variable `mh-lpr-command-format' is used to generate the print command.
|
||||
The messages are formatted by mhl. See the variable `mhl-formfile'."
|
||||
(interactive (list (if current-prefix-arg
|
||||
(reverse (mh-seq-to-msgs
|
||||
(mh-read-seq-default "Print" t)))
|
||||
(mh-get-msg-num t))))
|
||||
(if (numberp msg-or-seq)
|
||||
(message "Printing message...")
|
||||
(message "Printing sequence..."))
|
||||
(let ((print-command
|
||||
(if (numberp msg-or-seq)
|
||||
(format "%s -nobell -clear %s %s | %s"
|
||||
(expand-file-name "mhl" mh-lib-progs)
|
||||
(mh-msg-filename msg-or-seq)
|
||||
(if (stringp mhl-formfile)
|
||||
(format "-form %s" mhl-formfile)
|
||||
"")
|
||||
(format mh-lpr-command-format
|
||||
(if (numberp msg-or-seq)
|
||||
(format "%s/%d" mh-current-folder
|
||||
msg-or-seq)
|
||||
(format "Sequence from %s" mh-current-folder))))
|
||||
(format "(scan -clear %s ; %s -nobell -clear %s %s) | %s"
|
||||
(mapconcat (function (lambda (msg) msg)) msg-or-seq " ")
|
||||
(expand-file-name "mhl" mh-lib-progs)
|
||||
(if (stringp mhl-formfile)
|
||||
(format "-form %s" mhl-formfile)
|
||||
"")
|
||||
(mh-msg-filenames msg-or-seq)
|
||||
(format mh-lpr-command-format
|
||||
(if (numberp msg-or-seq)
|
||||
(format "%s/%d" mh-current-folder
|
||||
msg-or-seq)
|
||||
(format "Sequence from %s"
|
||||
mh-current-folder)))))))
|
||||
(if mh-print-background-flag
|
||||
(mh-exec-cmd-daemon shell-file-name nil "-c" print-command)
|
||||
(call-process shell-file-name nil nil nil "-c" print-command))
|
||||
(if (numberp msg-or-seq)
|
||||
(mh-notate msg-or-seq mh-note-printed mh-cmd-note)
|
||||
(mh-notate-seq msg-or-seq mh-note-printed mh-cmd-note))
|
||||
(mh-add-msgs-to-seq msg-or-seq 'printed t)
|
||||
(if (numberp msg-or-seq)
|
||||
(message "Printing message...done")
|
||||
(message "Printing sequence...done"))))
|
||||
|
||||
(defun mh-msg-filenames (msgs &optional folder)
|
||||
"Return a list of file names for MSGS in FOLDER (default current folder)."
|
||||
(mapconcat (function (lambda (msg) (mh-msg-filename msg folder))) msgs " "))
|
||||
(interactive (list (mh-interactive-msg-or-seq "Print")))
|
||||
(message "Printing...")
|
||||
(let (msgs)
|
||||
;; Gather message numbers and add them to "printed" sequence.
|
||||
(mh-iterate-on-msg-or-seq msg msg-or-seq
|
||||
(mh-add-msgs-to-seq msg 'printed t)
|
||||
(mh-notate nil mh-note-printed mh-cmd-note)
|
||||
(push msg msgs))
|
||||
(setq msgs (nreverse msgs))
|
||||
;; Print scan listing if we have more than one message.
|
||||
(if (> (length msgs) 1)
|
||||
(let* ((msgs-string
|
||||
(mapconcat 'identity (mh-list-to-string
|
||||
(mh-coalesce-msg-list msgs)) " "))
|
||||
(lpr-command
|
||||
(format mh-lpr-command-format
|
||||
(cond ((listp msg-or-seq)
|
||||
(format "Folder: %s, Messages: %s"
|
||||
mh-current-folder msgs-string))
|
||||
((symbolp msg-or-seq)
|
||||
(format "Folder: %s, Sequence: %s"
|
||||
mh-current-folder msg-or-seq)))))
|
||||
(scan-command
|
||||
(format "scan %s | %s" msgs-string lpr-command)))
|
||||
(if mh-print-background-flag
|
||||
(mh-exec-cmd-daemon shell-file-name nil "-c" scan-command)
|
||||
(call-process shell-file-name nil nil nil "-c" scan-command))))
|
||||
;; Print the messages
|
||||
(dolist (msg msgs)
|
||||
(let* ((mhl-command (format "%s %s %s"
|
||||
(expand-file-name "mhl" mh-lib-progs)
|
||||
(if mhl-formfile
|
||||
(format " -form %s" mhl-formfile)
|
||||
"")
|
||||
(mh-msg-filename msg)))
|
||||
(lpr-command
|
||||
(format mh-lpr-command-format
|
||||
(format "%s/%s" mh-current-folder msg)))
|
||||
(print-command
|
||||
(format "%s | %s" mhl-command lpr-command)))
|
||||
(if mh-print-background-flag
|
||||
(mh-exec-cmd-daemon shell-file-name nil "-c" print-command)
|
||||
(call-process shell-file-name nil nil nil "-c" print-command)))))
|
||||
(message "Printing...done"))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-sort-folder (&optional extra-args)
|
||||
|
@ -314,7 +303,6 @@ argument EXTRA-ARGS is given."
|
|||
(when mh-index-data
|
||||
(mh-index-update-maps mh-current-folder))
|
||||
(message "Sorting folder...done")
|
||||
(mh-reset-threads-and-narrowing)
|
||||
(mh-scan-folder mh-current-folder "all")
|
||||
(cond (threaded-flag (mh-toggle-threads))
|
||||
(mh-index-data (mh-index-insert-folder-headers)))))
|
||||
|
@ -334,7 +322,9 @@ Argument IGNORE is deprecated."
|
|||
(mh-unmark-all-headers t)))
|
||||
(t
|
||||
(message "Commands not undone.")
|
||||
(sit-for 2))))
|
||||
;; Remove by 2003-06-30 if nothing seems amiss. XXX
|
||||
;; (sit-for 2)
|
||||
)))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-store-msg (directory)
|
||||
|
@ -378,9 +368,9 @@ Default directory is the last directory used, or initially the value of
|
|||
(if (looking-at "^[#:]....+\n\\( ?\n\\)?end$")
|
||||
nil ;most likely end of a uuencode
|
||||
(point))))))
|
||||
(log-buffer (get-buffer-create "*Store Output*"))
|
||||
(command "sh")
|
||||
(uudecode-filename "(unknown filename)"))
|
||||
(uudecode-filename "(unknown filename)")
|
||||
log-begin)
|
||||
(if (not sh-start)
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
|
@ -389,31 +379,33 @@ Default directory is the last directory used, or initially the value of
|
|||
(buffer-substring (point)
|
||||
(progn (end-of-line) (point)))))))
|
||||
(save-excursion
|
||||
(set-buffer log-buffer)
|
||||
(erase-buffer)
|
||||
(set-buffer (get-buffer-create mh-log-buffer))
|
||||
(setq log-begin (mh-truncate-log-buffer))
|
||||
(if (not (file-directory-p store-directory))
|
||||
(progn
|
||||
(insert "mkdir " directory "\n")
|
||||
(call-process "mkdir" nil log-buffer t store-directory)))
|
||||
(call-process "mkdir" nil mh-log-buffer t store-directory)))
|
||||
(insert "cd " directory "\n")
|
||||
(setq mh-store-default-directory directory)
|
||||
(if (not sh-start)
|
||||
(progn
|
||||
(setq command "uudecode")
|
||||
(insert uudecode-filename " being uudecoded...\n"))))
|
||||
(set-window-start (display-buffer log-buffer) 0) ;watch progress
|
||||
(let (value)
|
||||
(let ((default-directory (file-name-as-directory store-directory)))
|
||||
(setq value (call-process-region sh-start (point-max) command
|
||||
nil log-buffer t)))
|
||||
(set-buffer log-buffer)
|
||||
(mh-handle-process-error command value))
|
||||
(insert "\n(mh-store finished)\n")))
|
||||
(set-window-start (display-buffer mh-log-buffer) log-begin) ;watch progress
|
||||
(let ((default-directory (file-name-as-directory store-directory)))
|
||||
(if (equal (call-process-region sh-start (point-max) command
|
||||
nil mh-log-buffer t)
|
||||
0)
|
||||
(save-excursion
|
||||
(set-buffer mh-log-buffer)
|
||||
(insert "\n(mh-store finished)\n"))
|
||||
(error "Error occurred during execution of %s" command)))))
|
||||
|
||||
|
||||
|
||||
;;; Help Functions
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-ephem-message (string)
|
||||
"Display STRING in the minibuffer momentarily."
|
||||
(message "%s" string)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
;;; mh-identity.el --- Multiple Identify support for MH-E.
|
||||
;;; mh-identity.el --- Multiple identify support for MH-E.
|
||||
|
||||
;; Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Peter S. Galbraith <psg@debian.org>
|
||||
;; Maintainer: Bill Wohler <wohler@newt.com>
|
||||
|
@ -37,8 +37,6 @@
|
|||
|
||||
;;; Change Log:
|
||||
|
||||
;; $Id: mh-identity.el,v 1.2 2003/02/03 20:55:30 wohler Exp $
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
||||
|
@ -169,11 +167,9 @@ Edit the `mh-identity-list' variable to define identity."
|
|||
(cond
|
||||
;; If MIME composition done, insert signature at the end as
|
||||
;; an inline MIME part.
|
||||
((and (boundp 'mh-mhn-compose-insert-flag)
|
||||
mh-mhn-compose-insert-flag)
|
||||
((mh-mhn-directive-present-p)
|
||||
(insert "#\n" "Content-Description: Signature\n"))
|
||||
((and (boundp 'mh-mml-compose-insert-flag)
|
||||
mh-mml-compose-insert-flag)
|
||||
((mh-mml-directive-present-p)
|
||||
(mml-insert-tag 'part 'type "text/plain"
|
||||
'disposition "inline"
|
||||
'description "Signature")))
|
||||
|
@ -182,12 +178,10 @@ Edit the `mh-identity-list' variable to define identity."
|
|||
(funcall value))
|
||||
(goto-char (point-min))
|
||||
(when (not (re-search-forward "^--" nil t))
|
||||
(if (and (boundp 'mh-mhn-compose-insert-flag)
|
||||
mh-mhn-compose-insert-flag)
|
||||
(forward-line 2))
|
||||
(if (and (boundp 'mh-mml-compose-insert-flag)
|
||||
mh-mml-compose-insert-flag)
|
||||
(forward-line 1))
|
||||
(cond ((mh-mhn-directive-present-p)
|
||||
(forward-line 2))
|
||||
((mh-mml-directive-present-p)
|
||||
(forward-line 1)))
|
||||
(insert "-- \n"))
|
||||
(set (make-local-variable 'mh-identity-signature-end)
|
||||
(make-marker))
|
||||
|
|
104
lisp/mh-e/mh-inc.el
Normal file
104
lisp/mh-e/mh-inc.el
Normal file
|
@ -0,0 +1,104 @@
|
|||
;;; mh-inc.el --- MH-E `inc' and separate mail spool handling
|
||||
;;
|
||||
;; Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Peter S. Galbraith <psg@debian.org>
|
||||
;; Maintainer: Bill Wohler <wohler@newt.com>
|
||||
;; Keywords: mail
|
||||
;; See: mh-e.el
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2, or (at your option)
|
||||
;; any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs; see the file COPYING. If not, write to the
|
||||
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
;; Boston, MA 02111-1307, USA.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Support for inc. In addition to reading from the system mailbox, inc can
|
||||
;; also be used to incorporate mail from multiple spool files into separate
|
||||
;; folders. See `C-h v mh-inc-spool-list'.
|
||||
|
||||
;;; Change Log:
|
||||
|
||||
;;; Code:
|
||||
|
||||
(eval-when-compile (require 'cl))
|
||||
|
||||
(defvar mh-inc-spool-map (make-sparse-keymap)
|
||||
"Keymap for MH-E's mh-inc-spool commands.")
|
||||
|
||||
(defvar mh-inc-spool-map-help nil
|
||||
"Help text to for `mh-inc-spool-map'.")
|
||||
|
||||
(define-key mh-inc-spool-map "?"
|
||||
'(lambda ()
|
||||
(interactive)
|
||||
(if mh-inc-spool-map-help
|
||||
(mh-ephem-message (substring mh-inc-spool-map-help 0 -1))
|
||||
(mh-ephem-message
|
||||
"There are no keys defined yet. Customize `mh-inc-spool-list'"))))
|
||||
|
||||
(defun mh-inc-spool-generator (folder spool)
|
||||
"Create a command to inc into FOLDER from SPOOL file."
|
||||
(let ((folder1 (make-symbol "folder"))
|
||||
(spool1 (make-symbol "spool")))
|
||||
(set folder1 folder)
|
||||
(set spool1 spool)
|
||||
(setf (symbol-function (intern (concat "mh-inc-spool-" folder)))
|
||||
`(lambda ()
|
||||
,(format "Inc spool file %s into folder %s" spool folder)
|
||||
(interactive)
|
||||
(mh-inc-folder ,spool1 (concat "+" ,folder1))))))
|
||||
|
||||
(defun mh-inc-spool-def-key (key folder)
|
||||
"Define a KEY in `mh-inc-spool-map' to inc FOLDER and collect help string."
|
||||
(when (not (= 0 key))
|
||||
(define-key mh-inc-spool-map (format "%c" key)
|
||||
(intern (concat "mh-inc-spool-" folder)))
|
||||
(setq mh-inc-spool-map-help (concat mh-inc-spool-map-help "["
|
||||
(char-to-string key)
|
||||
"] inc " folder " folder\n"))))
|
||||
|
||||
;; Avoid compiler warning
|
||||
(eval-when-compile (defvar mh-inc-spool-list))
|
||||
|
||||
(defun mh-inc-spool-make ()
|
||||
"Make all commands and defines keys for contents of `mh-inc-spool-list'."
|
||||
(when mh-inc-spool-list
|
||||
(setq mh-inc-spool-map-help nil)
|
||||
(loop for elem in mh-inc-spool-list
|
||||
do (let ((spool (nth 0 elem))
|
||||
(folder (nth 1 elem))
|
||||
(key (nth 2 elem)))
|
||||
(progn
|
||||
(mh-inc-spool-generator folder spool)
|
||||
(mh-inc-spool-def-key key folder))))))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-inc-spool-list-set (symbol value)
|
||||
"Set-default SYMBOL to VALUE to update the `mh-inc-spool-list' variable.
|
||||
Also rebuilds the user commands.
|
||||
This is called after 'customize is used to alter `mh-inc-spool-list'."
|
||||
(set-default symbol value)
|
||||
(mh-inc-spool-make))
|
||||
|
||||
(provide 'mh-inc)
|
||||
|
||||
;;; Local Variables:
|
||||
;;; indent-tabs-mode: nil
|
||||
;;; sentence-end-double-space: nil
|
||||
;;; End:
|
||||
|
||||
;;; mh-inc.el ends here
|
|
@ -1,6 +1,6 @@
|
|||
;;; mh-index -- MH-E interface to indexing programs
|
||||
|
||||
;; Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
|
||||
;; Maintainer: Bill Wohler <wohler@newt.com>
|
||||
|
@ -29,6 +29,7 @@
|
|||
;;; (1) The following search engines are supported:
|
||||
;;; swish++
|
||||
;;; swish-e
|
||||
;;; mairix
|
||||
;;; namazu
|
||||
;;; glimpse
|
||||
;;; grep
|
||||
|
@ -40,8 +41,6 @@
|
|||
|
||||
;;; Change Log:
|
||||
|
||||
;; $Id: mh-index.el,v 1.2 2003/02/03 20:55:30 wohler Exp $
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl)
|
||||
|
@ -165,21 +164,22 @@ 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 ((out (get-buffer-create " *mh-xargs-output*")))
|
||||
(save-excursion
|
||||
(set-buffer out)
|
||||
(erase-buffer))
|
||||
(while (not (eobp))
|
||||
(let ((arg-list (reverse args))
|
||||
(count 0))
|
||||
(while (and (not (eobp)) (< count mh-index-max-cmdline-args))
|
||||
(push (buffer-substring-no-properties (point) (line-end-position))
|
||||
arg-list)
|
||||
(incf count)
|
||||
(forward-line))
|
||||
(apply #'call-process cmd nil (list out nil) nil (nreverse arg-list))))
|
||||
(erase-buffer)
|
||||
(insert-buffer-substring out)))
|
||||
(let ((current-buffer (current-buffer)))
|
||||
(with-temp-buffer
|
||||
(let ((out (current-buffer)))
|
||||
(set-buffer current-buffer)
|
||||
(while (not (eobp))
|
||||
(let ((arg-list (reverse args))
|
||||
(count 0))
|
||||
(while (and (not (eobp)) (< count mh-index-max-cmdline-args))
|
||||
(push (buffer-substring-no-properties (point) (line-end-position))
|
||||
arg-list)
|
||||
(incf count)
|
||||
(forward-line))
|
||||
(apply #'call-process cmd nil (list out nil) nil
|
||||
(nreverse arg-list))))
|
||||
(erase-buffer)
|
||||
(insert-buffer-substring out)))))
|
||||
|
||||
|
||||
|
||||
|
@ -230,7 +230,8 @@ checksum -> (origin-folder, origin-index) map is updated too."
|
|||
(point) (line-end-position)))
|
||||
(forward-line)
|
||||
(save-excursion
|
||||
(cond ((eolp)
|
||||
(cond ((not (string-match "^[0-9]*$" msg)))
|
||||
((eolp)
|
||||
;; need to compute checksum
|
||||
(set-buffer mh-checksum-buffer)
|
||||
(insert mh-user-path (substring folder 1) "/" msg "\n"))
|
||||
|
@ -260,6 +261,9 @@ checksum -> (origin-folder, origin-index) map is updated too."
|
|||
(mh-index-update-single-msg msg checksum origin-map)))
|
||||
(forward-line))))))
|
||||
|
||||
(defvar mh-flists-results-folder "new"
|
||||
"Subfolder for `mh-index-folder' where flists output is placed.")
|
||||
|
||||
(defun mh-index-generate-pretty-name (string)
|
||||
"Given STRING generate a name which is suitable for use as a folder name.
|
||||
White space from the beginning and end are removed. All spaces in the name are
|
||||
|
@ -288,19 +292,24 @@ they are concatenated to construct the base name."
|
|||
(subst-char-in-region (point-min) (point-max) ?\n ?_ t)
|
||||
(subst-char-in-region (point-min) (point-max) ?\r ?_ t)
|
||||
(subst-char-in-region (point-min) (point-max) ?/ ?$ t)
|
||||
(truncate-string-to-width (buffer-substring (point-min) (point-max)) 20)))
|
||||
(let ((out (truncate-string-to-width (buffer-string) 20)))
|
||||
(cond ((eq mh-indexer 'flists) mh-flists-results-folder)
|
||||
((equal out mh-flists-results-folder) (concat out "1"))
|
||||
(t out)))))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun* mh-index-search (redo-search-flag folder search-regexp
|
||||
&optional window-config)
|
||||
&optional window-config unseen-flag)
|
||||
"Perform an indexed search in an MH mail folder.
|
||||
Use a prefix argument to repeat the search, as in REDO-SEARCH-FLAG below.
|
||||
|
||||
If REDO-SEARCH-FLAG is non-nil and the current folder buffer was generated by a
|
||||
index search, then the search is repeated. Otherwise, FOLDER is searched with
|
||||
SEARCH-REGEXP and the results are presented in an MH-E folder. If FOLDER is
|
||||
\"+\" then mail in all folders are searched. Optional argument WINDOW-CONFIG
|
||||
stores the window configuration that will be restored after the user quits the
|
||||
folder containing the index search results.
|
||||
folder containing the index search results. If optional argument UNSEEN-FLAG
|
||||
is non-nil, then all the messages are marked as unseen.
|
||||
|
||||
Four indexing programs are supported; if none of these are present, then grep
|
||||
is used. This function picks the first program that is available on your
|
||||
|
@ -381,7 +390,7 @@ This has the effect of renaming already present X-MHE-Checksum headers."
|
|||
(message "Processing %s output... " mh-indexer)
|
||||
(goto-char (point-min))
|
||||
(loop for next-result = (funcall mh-index-next-result-function)
|
||||
when (null next-result) return nil
|
||||
while next-result
|
||||
do (unless (eq next-result 'error)
|
||||
(unless (gethash (car next-result) folder-results-map)
|
||||
(setf (gethash (car next-result) folder-results-map)
|
||||
|
@ -403,9 +412,13 @@ This has the effect of renaming already present X-MHE-Checksum headers."
|
|||
(cons folder msg)))))
|
||||
folder-results-map)
|
||||
|
||||
;; Mark messages as unseen (if needed)
|
||||
(when (and unseen-flag (> result-count 0))
|
||||
(mh-exec-cmd "mark" index-folder "all"
|
||||
"-sequence" (symbol-name mh-unseen-seq) "-add"))
|
||||
|
||||
;; Generate scan lines for the hits.
|
||||
(let ((mh-show-threads-flag nil))
|
||||
(mh-visit-folder index-folder () (list folder-results-map origin-map)))
|
||||
(mh-visit-folder index-folder () (list folder-results-map origin-map))
|
||||
|
||||
(goto-char (point-min))
|
||||
(forward-line)
|
||||
|
@ -548,9 +561,8 @@ The function is only applicable to folders displaying index search results.
|
|||
With non-nil optional argument BACKWARD-FLAG, jump to the previous group of
|
||||
results."
|
||||
(interactive "P")
|
||||
(if (or (null mh-index-data)
|
||||
(memq 'unthread mh-view-ops))
|
||||
(message "Only applicable in an unthreaded MH-E index search buffer")
|
||||
(if (null mh-index-data)
|
||||
(message "Only applicable in an MH-E index search buffer")
|
||||
(let ((point (point)))
|
||||
(forward-line (if backward-flag -1 1))
|
||||
(cond ((if backward-flag
|
||||
|
@ -627,6 +639,22 @@ we find a new folder name."
|
|||
(when cur-msg (mh-goto-msg cur-msg t))
|
||||
(set-buffer-modified-p old-buffer-modified-flag)))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-index-group-by-folder ()
|
||||
"Partition the messages based on source folder.
|
||||
Returns an alist with the the folder names in the car and the cdr being the
|
||||
list of messages originally from that folder."
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(let ((result-table (make-hash-table)))
|
||||
(loop for msg being hash-keys of mh-index-msg-checksum-map
|
||||
do (push msg (gethash (car (gethash
|
||||
(gethash msg mh-index-msg-checksum-map)
|
||||
mh-index-checksum-origin-map))
|
||||
result-table)))
|
||||
(loop for x being the hash-keys of result-table
|
||||
collect (cons x (nreverse (gethash x result-table)))))))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-index-delete-folder-headers ()
|
||||
"Delete the folder headers."
|
||||
|
@ -662,9 +690,28 @@ we find a new folder name."
|
|||
(when (not folder)
|
||||
(setq folder (car (gethash (gethash msg mh-index-msg-checksum-map)
|
||||
mh-index-checksum-origin-map))))
|
||||
(mh-visit-folder
|
||||
folder (loop for x being the hash-keys of (gethash folder mh-index-data)
|
||||
when (mh-msg-exists-p x folder) collect x))))
|
||||
(when (or (not (get-buffer folder))
|
||||
(y-or-n-p (format "Reuse buffer displaying %s? " folder)))
|
||||
(mh-visit-folder
|
||||
folder (loop for x being the hash-keys of (gethash folder mh-index-data)
|
||||
when (mh-msg-exists-p x folder) collect x)))))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-index-update-unseen (msg)
|
||||
"Remove counterpart of MSG in source folder from `mh-unseen-seq'.
|
||||
Also `mh-update-unseen' is called in the original folder, if we have it open."
|
||||
(let* ((checksum (gethash msg mh-index-msg-checksum-map))
|
||||
(folder-msg-pair (gethash checksum mh-index-checksum-origin-map))
|
||||
(orig-folder (car folder-msg-pair))
|
||||
(orig-msg (cdr folder-msg-pair)))
|
||||
(when (mh-index-match-checksum orig-msg orig-folder checksum)
|
||||
(when (get-buffer orig-folder)
|
||||
(save-excursion
|
||||
(set-buffer orig-folder)
|
||||
(unless (member orig-msg mh-seen-list) (push orig-msg mh-seen-list))
|
||||
(mh-update-unseen)))
|
||||
(mh-exec-cmd-daemon "mark" #'ignore orig-folder (format "%s" orig-msg)
|
||||
"-sequence" (symbol-name mh-unseen-seq) "-del"))))
|
||||
|
||||
(defun mh-index-match-checksum (msg folder checksum)
|
||||
"Check if MSG in FOLDER has X-MHE-Checksum header value of CHECKSUM."
|
||||
|
@ -918,7 +965,7 @@ FOLDER-PATH is the directory in which SEARCH-REGEXP-LIST is used to search."
|
|||
(when (or (eobp) (and (bolp) (eolp)))
|
||||
(return nil))
|
||||
(unless (eq (char-after) ?/)
|
||||
(return error))
|
||||
(return 'error))
|
||||
(let ((start (point))
|
||||
end msg-start)
|
||||
(setq end (line-end-position))
|
||||
|
@ -1000,6 +1047,68 @@ REGEXP-LIST is an alist of fields and values."
|
|||
|
||||
|
||||
|
||||
;; Interface to unseen messages script
|
||||
|
||||
(defvar mh-flists-search-folders)
|
||||
|
||||
(defun mh-flists-execute (&rest args)
|
||||
"Search for unseen messages in `mh-flists-search-folders'.
|
||||
If `mh-recursive-folders-flag' is t, then the folders are searched
|
||||
recursively. All parameters ARGS are ignored."
|
||||
(set-buffer (get-buffer-create mh-index-temp-buffer))
|
||||
(erase-buffer)
|
||||
(unless (executable-find "sh")
|
||||
(error "Didn't find sh"))
|
||||
(with-temp-buffer
|
||||
(let ((unseen (symbol-name mh-unseen-seq)))
|
||||
(insert "for folder in `flists "
|
||||
(cond ((eq mh-flists-search-folders t) mh-inbox)
|
||||
((eq mh-flists-search-folders nil) "")
|
||||
((listp mh-flists-search-folders)
|
||||
(loop for folder in mh-flists-search-folders
|
||||
concat (concat " " folder))))
|
||||
(if mh-recursive-folders-flag " -recurse" "")
|
||||
" -sequence " unseen " -noshowzero -fast` ; do\n"
|
||||
"mhpath \"+$folder\" " unseen "\n" "done\n"))
|
||||
(call-process-region
|
||||
(point-min) (point-max) "sh" nil (get-buffer mh-index-temp-buffer))))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-index-new-messages (folders)
|
||||
"Display new messages.
|
||||
All messages in the `mh-unseen-seq' sequence from FOLDERS are displayed.
|
||||
By default the folders specified by `mh-index-new-messages-folders' are
|
||||
searched. With a prefix argument, enter a space-separated list of folders, or
|
||||
nothing to search all folders."
|
||||
(interactive
|
||||
(list (if current-prefix-arg
|
||||
(split-string (read-string "Folders to search: "))
|
||||
mh-index-new-messages-folders)))
|
||||
(let* ((mh-flists-search-folders folders)
|
||||
(mh-indexer 'flists)
|
||||
(mh-index-execute-search-function 'mh-flists-execute)
|
||||
(mh-index-next-result-function 'mh-mairix-next-result)
|
||||
(mh-mairix-folder mh-user-path)
|
||||
(mh-index-regexp-builder nil)
|
||||
(new-folder (format "%s/%s" mh-index-folder mh-flists-results-folder))
|
||||
(window-config (if (equal new-folder mh-current-folder)
|
||||
mh-previous-window-config
|
||||
(current-window-configuration)))
|
||||
(redo-flag nil))
|
||||
(cond ((buffer-live-p (get-buffer new-folder))
|
||||
;; The destination folder is being visited. Trick `mh-index-search'
|
||||
;; into thinking that the folder was the result of a previous search.
|
||||
(set-buffer new-folder)
|
||||
(setq mh-index-previous-search (list "+" mh-flists-results-folder))
|
||||
(setq redo-flag t))
|
||||
((mh-folder-exists-p new-folder)
|
||||
;; Folder exists but we don't have it open. That means they are
|
||||
;; stale results from a old flists search. Clear it out.
|
||||
(mh-exec-cmd-quiet nil "rmf" new-folder)))
|
||||
(mh-index-search redo-flag "+" mh-flists-results-folder window-config t)))
|
||||
|
||||
|
||||
|
||||
;; Swish interface
|
||||
|
||||
(defvar mh-swish-binary (executable-find "swish-e"))
|
||||
|
@ -1163,7 +1272,7 @@ FOLDER-PATH is the directory in which SEARCH-REGEXP is used to search."
|
|||
(defun mh-swish++-regexp-builder (regexp-list)
|
||||
"Generate query for swish++.
|
||||
REGEXP-LIST is an alist of fields and values."
|
||||
(let ((regexp "") meta)
|
||||
(let ((regexp ""))
|
||||
(dolist (elem regexp-list)
|
||||
(when (cdr elem)
|
||||
(setq regexp (concat regexp " and "
|
||||
|
@ -1264,6 +1373,7 @@ FOLDER-PATH is the directory in which SEARCH-REGEXP is used to search."
|
|||
|
||||
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-index-choose ()
|
||||
"Choose an indexing function.
|
||||
The side-effects of this function are that the variables `mh-indexer',
|
||||
|
|
416
lisp/mh-e/mh-junk.el
Normal file
416
lisp/mh-e/mh-junk.el
Normal file
|
@ -0,0 +1,416 @@
|
|||
;;; mh-junk.el --- Interface to anti-spam measures
|
||||
|
||||
;; Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Satyaki Das <satyaki@theforce.stanford.edu>,
|
||||
;; Bill Wohler <wohler@newt.com>
|
||||
;; Maintainer: Bill Wohler <wohler@newt.com>
|
||||
;; Keywords: mail, spam
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2, or (at your option)
|
||||
;; any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs; see the file COPYING. If not, write to the
|
||||
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
;; Boston, MA 02111-1307, USA.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Spam handling in MH-E.
|
||||
|
||||
;;; Change Log:
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'mh-e)
|
||||
|
||||
;; Interactive functions callable from the folder buffer
|
||||
;;;###mh-autoload
|
||||
(defun mh-junk-blacklist (msg-or-seq)
|
||||
"Blacklist MSG-OR-SEQ as spam.
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is blacklisted.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence.
|
||||
|
||||
First the appropriate function is called depending on the value of
|
||||
`mh-junk-choice'. Then if `mh-junk-mail-folder' is a string then the message is
|
||||
refiled to that folder. If nil, the message is deleted.
|
||||
|
||||
To change the spam program being used, customize `mh-junk-program'. Directly
|
||||
setting `mh-junk-choice' is not recommended.
|
||||
|
||||
The documentation for the following functions describes what setup is needed
|
||||
for the different spam fighting programs:
|
||||
|
||||
- `mh-bogofilter-blacklist'
|
||||
- `mh-spamprobe-blacklist'
|
||||
- `mh-spamassassin-blacklist'"
|
||||
(interactive (list (mh-interactive-msg-or-seq "Blacklist")))
|
||||
(let ((blacklist-func (nth 1 (assoc mh-junk-choice mh-junk-function-alist))))
|
||||
(unless blacklist-func
|
||||
(error "Customize `mh-junk-program' appropriately"))
|
||||
(let ((dest (cond ((null mh-junk-mail-folder) nil)
|
||||
((equal mh-junk-mail-folder "") "+")
|
||||
((eq (aref mh-junk-mail-folder 0) ?+)
|
||||
mh-junk-mail-folder)
|
||||
((eq (aref mh-junk-mail-folder 0) ?@)
|
||||
(concat mh-current-folder "/"
|
||||
(substring mh-junk-mail-folder 1)))
|
||||
(t (concat "+" mh-junk-mail-folder)))))
|
||||
(mh-iterate-on-msg-or-seq msg msg-or-seq
|
||||
(funcall (symbol-function blacklist-func) msg)
|
||||
(if dest
|
||||
(mh-refile-a-msg nil (intern dest))
|
||||
(mh-delete-a-msg nil)))
|
||||
(mh-next-msg))))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-junk-whitelist (msg-or-seq)
|
||||
"Whitelist MSG-OR-SEQ incorrectly classified as spam.
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is whitelisted.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence.
|
||||
|
||||
First the appropriate function is called depending on the value of
|
||||
`mh-junk-choice'. Then the message is refiled to `mh-inbox'.
|
||||
|
||||
To change the spam program being used, customize `mh-junk-program'. Directly
|
||||
setting `mh-junk-choice' is not recommended."
|
||||
(interactive (list (mh-interactive-msg-or-seq "Whitelist")))
|
||||
(let ((whitelist-func (nth 2 (assoc mh-junk-choice mh-junk-function-alist))))
|
||||
(unless whitelist-func
|
||||
(error "Customize `mh-junk-program' appropriately"))
|
||||
(mh-iterate-on-msg-or-seq msg msg-or-seq
|
||||
(funcall (symbol-function whitelist-func) msg)
|
||||
(mh-refile-a-msg nil (intern mh-inbox)))
|
||||
(mh-next-msg)))
|
||||
|
||||
|
||||
|
||||
;; Bogofilter Interface
|
||||
|
||||
(defvar mh-bogofilter-executable (executable-find "bogofilter"))
|
||||
|
||||
(defun mh-bogofilter-blacklist (msg)
|
||||
"Classify MSG as spam.
|
||||
Tell bogofilter that the message is spam.
|
||||
|
||||
Bogofilter is a Bayesian spam filtering program. Get it from your local
|
||||
distribution or from:
|
||||
http://bogofilter.sourceforge.net/
|
||||
|
||||
You first need to teach bogofilter. This is done by running
|
||||
|
||||
bogofilter -n < good-message
|
||||
|
||||
on every good message, and
|
||||
|
||||
bogofilter -s < spam-message
|
||||
|
||||
on every spam message. Most Bayesian filters need 1000 to 5000 of each to
|
||||
start doing a good job.
|
||||
|
||||
To use bogofilter, add the following .procmailrc recipes which you can also
|
||||
find in the bogofilter man page:
|
||||
|
||||
# Bogofilter
|
||||
:0fw
|
||||
| bogofilter -u -e -p
|
||||
|
||||
:0
|
||||
* ^X-Bogosity: Yes, tests=bogofilter
|
||||
$SPAM
|
||||
|
||||
Bogofilter continues to feed the messages it classifies back into its
|
||||
database. Occasionally it misses, and those messages need to be reclassified.
|
||||
MH-E can do this for you. Use \\[mh-junk-blacklist] to reclassify messges in
|
||||
your +inbox as spam, and \\[mh-junk-whitelist] to reclassify messages in your
|
||||
spambox as good messages."
|
||||
(unless mh-bogofilter-executable
|
||||
(error "Couldn't find the bogofilter executable"))
|
||||
(let ((msg-file (mh-msg-filename msg mh-current-folder)))
|
||||
(call-process mh-bogofilter-executable msg-file 0 nil "-Ns")))
|
||||
|
||||
(defun mh-bogofilter-whitelist (msg)
|
||||
"Reinstate incorrectly filtered MSG.
|
||||
Train bogofilter to think of the message as non-spam."
|
||||
(unless mh-bogofilter-executable
|
||||
(error "Couldn't find the bogofilter executable"))
|
||||
(let ((msg-file (mh-msg-filename msg mh-current-folder)))
|
||||
(call-process mh-bogofilter-executable msg-file 0 nil "-Sn")))
|
||||
|
||||
|
||||
|
||||
;; Spamprobe Interface
|
||||
|
||||
(defvar mh-spamprobe-executable (executable-find "spamprobe"))
|
||||
|
||||
(defun mh-spamprobe-blacklist (msg)
|
||||
"Classify MSG as spam.
|
||||
Tell spamprobe that the message is spam.
|
||||
|
||||
Spamprobe is a Bayesian spam filtering program. More info about the program can
|
||||
be found at:
|
||||
http://spamprobe.sourceforge.net
|
||||
|
||||
Here is a procmail recipe to stores incoming spam mail into the folder +spam
|
||||
and good mail in /home/user/Mail/mdrop/mbox. This recipe is provided as an
|
||||
example in the spamprobe man page.
|
||||
|
||||
PATH=/bin:/usr/bin:/usr/local/bin
|
||||
DEFAULT=/home/user/Mail/mdrop/mbox
|
||||
SPAM=/home/user/Mail/spam/.
|
||||
|
||||
# Spamprobe filtering
|
||||
:0
|
||||
SCORE=| spamprobe receive
|
||||
:0 wf
|
||||
| formail -I \"X-SpamProbe: $SCORE\"
|
||||
:0 a:
|
||||
*^X-SpamProbe: SPAM
|
||||
$SPAM
|
||||
|
||||
Occasionally some good mail gets misclassified as spam. You can use
|
||||
\\[mh-junk-whitelist] to reclassify that as good mail."
|
||||
(unless mh-spamprobe-executable
|
||||
(error "Couldn't find the spamprobe executable"))
|
||||
(let ((msg-file (mh-msg-filename msg mh-current-folder)))
|
||||
(call-process mh-spamprobe-executable msg-file 0 nil "spam")))
|
||||
|
||||
(defun mh-spamprobe-whitelist (msg)
|
||||
"Reinstate incorrectly filtered MSG.
|
||||
Train spamprobe to think of the message as non-spam."
|
||||
(unless mh-spamprobe-executable
|
||||
(error "Couldn't find the spamprobe executable"))
|
||||
(let ((msg-file (mh-msg-filename msg mh-current-folder)))
|
||||
(call-process mh-spamprobe-executable msg-file 0 nil "good")))
|
||||
|
||||
|
||||
|
||||
;; Spamassassin Interface
|
||||
|
||||
(defvar mh-spamassassin-executable (executable-find "spamassassin"))
|
||||
(defvar mh-sa-learn-executable (executable-find "sa-learn"))
|
||||
|
||||
(defun mh-spamassassin-blacklist (msg)
|
||||
"Blacklist MSG.
|
||||
This is done by sending the message to Razor and by appending the sender to
|
||||
~/.spamassassin/user_prefs in a blacklist_from rule. If sa-learn is available,
|
||||
the message is also recategorized as spam.
|
||||
|
||||
Spamassassin is an excellent spam filter. For more information, see:
|
||||
http://spamassassin.org/.
|
||||
|
||||
I ran \"spamassassin -t\" on every mail message in my archive and ran an
|
||||
analysis in Gnumeric to find that the standard deviation of good mail
|
||||
scored under 5 (coincidentally, the spamassassin default for \"spam\").
|
||||
|
||||
Furthermore, I observed that there weren't any messages with a score of 8
|
||||
or more that were interesting, so I added a couple of points to be
|
||||
conservative and send any message with a score of 10 or more down the
|
||||
drain. You might want to use a score of 12 or 13 to be really conservative.
|
||||
I have found that this really decreases the amount of junk to review.
|
||||
|
||||
Messages with a score of 5-9 are set aside for later review. The major
|
||||
weakness of rules-based filters is a plethora of false positives\; I catch one
|
||||
or two legitimate messages in here a week, so it is worthwhile to check.
|
||||
|
||||
You might choose to do this analysis yourself to pick a good score for
|
||||
deleting spam sight unseen, or you might pick a score out of a hat, or you
|
||||
might choose to be very conservative and not delete any messages at all.
|
||||
|
||||
Based upon this discussion, here is what the associated ~/.procmailrc
|
||||
entries look like. These rules appear before my list filters so that spam
|
||||
sent to mailing lists gets pruned too.
|
||||
|
||||
#
|
||||
# Spam
|
||||
#
|
||||
:0fw
|
||||
| spamc
|
||||
|
||||
# Anything with a spam level of 10 or more is junked immediately.
|
||||
:0:
|
||||
* ^X-Spam-Level: ..........
|
||||
/dev/null
|
||||
|
||||
:0
|
||||
* ^X-Spam-Status: Yes
|
||||
$SPAM
|
||||
|
||||
If you don't use \"spamc\", use \"spamassassin -P -a\".
|
||||
|
||||
A handful of spam does find its way into +inbox. In this case, use
|
||||
\\[mh-junk-blacklist] to add a \"blacklist_from\" line to
|
||||
~/spamassassin/user_prefs, delete the message, and send the message to the
|
||||
Razor, so that others might not see this spam.
|
||||
|
||||
Over time, you see some patterns in the blacklisted addresses and can
|
||||
replace several lines with wildcards. For example, it is clear that High
|
||||
Speed Media is the biggest bunch of jerks on the Net. Here are some of the
|
||||
entries I have for them, and the list continues to grow.
|
||||
|
||||
blacklist_from *@*-hsm-*.com
|
||||
blacklist_from *@*182*643*.com
|
||||
blacklist_from *@*antarhsm*.com
|
||||
blacklist_from *@*h*speed*
|
||||
blacklist_from *@*hsm*182*.com
|
||||
blacklist_from *@*hsm*643*.com
|
||||
blacklist_from *@*hsmridi2983cslt227.com
|
||||
blacklist_from *@*list*hsm*.com
|
||||
blacklist_from *@h*s*media*
|
||||
blacklist_from *@hsmdrct.com
|
||||
blacklist_from *@hsmridi2983csltsite.com
|
||||
|
||||
The function `mh-spamassassin-identify-spammers' is provided that shows the
|
||||
frequency counts of the host and domain names in your blacklist_from
|
||||
entries. This can be helpful when editing the blacklist_from entries.
|
||||
|
||||
In versions of spamassassin (2.50 and on) that support a Bayesian classifier,
|
||||
\\[mh-junk-blacklist] uses the sa-learn program to recategorize the message as
|
||||
spam. Neither MH-E, nor spamassassin, rebuilds the database after adding
|
||||
words, so you will need to run \"sa-learn --rebuild\" periodically. This can
|
||||
be done by adding the following to your crontab:
|
||||
|
||||
0 * * * * sa-learn --rebuild > /dev/null 2>&1"
|
||||
(unless mh-spamassassin-executable
|
||||
(error "Couldn't find the spamassassin executable"))
|
||||
(let ((current-folder mh-current-folder)
|
||||
(msg-file (mh-msg-filename msg mh-current-folder))
|
||||
(sender))
|
||||
(save-excursion
|
||||
(message "Giving this message the Razor...")
|
||||
(mh-truncate-log-buffer)
|
||||
(call-process mh-spamassassin-executable msg-file mh-log-buffer nil
|
||||
"--report" "--remove-from-whitelist")
|
||||
(when mh-sa-learn-executable
|
||||
(message "Recategorizing this message as spam...")
|
||||
(call-process mh-sa-learn-executable msg-file mh-log-buffer nil
|
||||
"--single" "--spam" "--local --no-rebuild"))
|
||||
(message "Blacklisting address...")
|
||||
(set-buffer (get-buffer-create mh-temp-buffer))
|
||||
(erase-buffer)
|
||||
(call-process (expand-file-name mh-scan-prog mh-progs) nil t nil
|
||||
(format "%s" msg) current-folder
|
||||
"-format" "%<(mymbox{from})%|%(addr{from})%>")
|
||||
(goto-char (point-min))
|
||||
(if (search-forward-regexp "^\\(.+\\)$" nil t)
|
||||
(progn
|
||||
(setq sender (match-string 0))
|
||||
(mh-spamassassin-add-rule "blacklist_from" sender)
|
||||
(message "Blacklisting address...done"))
|
||||
(message "Blacklisting address...not done (from my address)")))))
|
||||
|
||||
(defun mh-spamassassin-whitelist (msg)
|
||||
"Whitelist MSG.
|
||||
Add a whitelist_from rule to the ~/.spamassassin/user_prefs file. If sa-learn
|
||||
is available, then the message is recategorized as ham."
|
||||
(unless mh-spamassassin-executable
|
||||
(error "Couldn't find the spamassassin executable"))
|
||||
(let ((msg-file (mh-msg-filename msg mh-current-folder))
|
||||
(show-buffer (get-buffer mh-show-buffer))
|
||||
from)
|
||||
(save-excursion
|
||||
(set-buffer (get-buffer-create mh-temp-buffer))
|
||||
(erase-buffer)
|
||||
(message "Removing spamassassin markup from message...")
|
||||
(call-process mh-spamassassin-executable msg-file mh-temp-buffer nil
|
||||
"--remove-markup")
|
||||
(if show-buffer
|
||||
(kill-buffer show-buffer))
|
||||
(write-file msg-file)
|
||||
(when mh-sa-learn-executable
|
||||
(message "Recategorizing this message as ham...")
|
||||
(call-process mh-sa-learn-executable msg-file mh-temp-buffer nil
|
||||
"--single" "--ham" "--local --no-rebuild"))
|
||||
(message "Whitelisting address...")
|
||||
(setq from (car (ietf-drums-parse-address (mh-get-header-field "From:"))))
|
||||
(kill-buffer nil)
|
||||
(unless (equal from "")
|
||||
(mh-spamassassin-add-rule "whitelist_from" from))
|
||||
(message "Whitelisting address...done"))))
|
||||
|
||||
(defun mh-spamassassin-add-rule (rule body)
|
||||
"Add a new rule to ~/.spamassassin/user_prefs.
|
||||
The name of the rule is RULE and its body is BODY."
|
||||
(save-window-excursion
|
||||
(let* ((line (format "%s\t%s\n" rule body))
|
||||
(case-fold-search t)
|
||||
(file (expand-file-name "~/.spamassassin/user_prefs"))
|
||||
(buffer-exists (find-buffer-visiting file)))
|
||||
(find-file file)
|
||||
(if (not (search-forward (format "\n%s" line) nil t))
|
||||
(progn
|
||||
(goto-char (point-max))
|
||||
(insert (if (bolp) "" "\n") line)
|
||||
(save-buffer)))
|
||||
(if (not buffer-exists)
|
||||
(kill-buffer nil)))))
|
||||
|
||||
(defun mh-spamassassin-identify-spammers ()
|
||||
"Identifies spammers who are repeat offenders.
|
||||
|
||||
For each blacklist_from entry from the last blank line of
|
||||
~/.spamassassin/user_prefs to the end of the file, a list of host and domain
|
||||
names along with their frequency counts is displayed. This information can be
|
||||
used to replace multiple blacklist_from entries with a single wildcard entry
|
||||
such as:
|
||||
|
||||
blacklist_from *@*amazingoffersdirect2u.com"
|
||||
(interactive)
|
||||
(let* ((file (expand-file-name "~/.spamassassin/user_prefs"))
|
||||
(domains (make-hash-table :test 'equal)))
|
||||
(find-file file)
|
||||
;; Only consider entries between last blank line and end of file.
|
||||
(goto-char (1- (point-max)))
|
||||
(search-backward-regexp "^$")
|
||||
;; Perform frequency count.
|
||||
(save-excursion
|
||||
(while (search-forward-regexp "^blacklist_from\\s-*\\(.*\\)@\\(.*\\)$"
|
||||
nil t)
|
||||
(let ((host (match-string 2))
|
||||
value)
|
||||
;; Remove top-level-domain from hostname.
|
||||
(setq host (cdr (reverse (split-string host "\\."))))
|
||||
;; Add counts for each host and domain part.
|
||||
(while host
|
||||
(setq value (gethash (car host) domains))
|
||||
(puthash (car host) (1+ (if (not value) 0 value)) domains)
|
||||
(setq host (cdr host))))))
|
||||
|
||||
;; Output
|
||||
(delete-other-windows)
|
||||
(pop-to-buffer (get-buffer-create "*MH-E Spammer Frequencies*"))
|
||||
(erase-buffer)
|
||||
(maphash '(lambda (key value) ""
|
||||
(if (> value 2)
|
||||
(insert (format "%s %s\n" key value))))
|
||||
domains)
|
||||
(sort-numeric-fields 2 (point-min) (point-max))
|
||||
(reverse-region (point-min) (point-max))
|
||||
(goto-char (point-min))))
|
||||
|
||||
(provide 'mh-junk)
|
||||
|
||||
;;; Local Variables:
|
||||
;;; indent-tabs-mode: nil
|
||||
;;; sentence-end-double-space: nil
|
||||
;;; End:
|
||||
|
||||
;;; mh-junk.el ends here
|
|
@ -5,7 +5,6 @@
|
|||
;;; Keywords: mail
|
||||
;;; Commentary:
|
||||
;;; Change Log:
|
||||
;; $Id: mh-loaddefs.el,v 1.36 2003/02/03 19:15:13 wohler Exp $
|
||||
;;; Code:
|
||||
|
||||
;;;### (autoloads (mh-letter-complete mh-open-line mh-fully-kill-draft
|
||||
|
@ -13,7 +12,7 @@
|
|||
;;;;;; mh-insert-signature mh-to-fcc mh-to-field mh-fill-paragraph-function
|
||||
;;;;;; mh-send-other-window mh-send mh-reply mh-redistribute mh-forward
|
||||
;;;;;; mh-extract-rejected-mail mh-edit-again) "mh-comp" "mh-comp.el"
|
||||
;;;;;; (15924 43423))
|
||||
;;;;;; (16039 39609))
|
||||
;;; Generated autoloads from mh-comp.el
|
||||
|
||||
(autoload (quote mh-edit-again) "mh-comp" "\
|
||||
|
@ -29,13 +28,15 @@ gives the headers to clean out of the original message.
|
|||
See also documentation for `\\[mh-send]' function." t nil)
|
||||
|
||||
(autoload (quote mh-forward) "mh-comp" "\
|
||||
Forward one or more messages to the recipients TO and CC.
|
||||
Forward messages to the recipients TO and CC.
|
||||
Use optional MSG-OR-SEQ argument to specify a message or sequence to forward.
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is forwarded.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence.
|
||||
|
||||
Use the optional MSG-OR-SEQ to specify a message or sequence to forward.
|
||||
|
||||
Default is the displayed message. If optional prefix argument is given then
|
||||
prompt for the message sequence. If variable `transient-mark-mode' is non-nil
|
||||
and the mark is active, then the selected region is forwarded.
|
||||
See also documentation for `\\[mh-send]' function." t nil)
|
||||
|
||||
(autoload (quote mh-redistribute) "mh-comp" "\
|
||||
|
@ -45,7 +46,8 @@ Depending on how your copy of MH was compiled, you may need to change the
|
|||
setting of the variable `mh-redist-full-contents'. See its documentation." t nil)
|
||||
|
||||
(autoload (quote mh-reply) "mh-comp" "\
|
||||
Reply to MESSAGE (default: current message).
|
||||
Reply to MESSAGE.
|
||||
Default is the displayed message.
|
||||
If the optional argument REPLY-TO is not given, prompts for type of addresses
|
||||
to reply to:
|
||||
from sender only,
|
||||
|
@ -107,8 +109,8 @@ Send the draft letter in the current buffer.
|
|||
If optional prefix argument ARG is provided, monitor delivery.
|
||||
The value of `mh-before-send-letter-hook' is a list of functions to be called,
|
||||
with no arguments, before doing anything.
|
||||
Run `\\[mh-edit-mhn]' if variable `mh-mhn-compose-insert-flag' is set.
|
||||
Run `\\[mh-mml-to-mime]' if variable `mh-mml-compose-insert-flag' is set.
|
||||
Run `\\[mh-edit-mhn]' if mhn directives are present; otherwise
|
||||
run `\\[mh-mml-to-mime]' if mml directives are present.
|
||||
Insert X-Mailer field if variable `mh-insert-x-mailer-flag' is set.
|
||||
Insert X-Face field if the file specified by `mh-x-face-file' exists." t nil)
|
||||
|
||||
|
@ -149,8 +151,8 @@ passing the prefix ARG if any." t nil)
|
|||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads (mh-tool-bar-folder-set mh-tool-bar-letter-set
|
||||
;;;;;; mh-customize) "mh-customize" "mh-customize.el" (15933 21842))
|
||||
;;;### (autoloads (mh-customize) "mh-customize" "mh-customize.el"
|
||||
;;;;;; (16038 15647))
|
||||
;;; Generated autoloads from mh-customize.el
|
||||
|
||||
(autoload (quote mh-customize) "mh-customize" "\
|
||||
|
@ -158,16 +160,10 @@ Customize MH-E variables.
|
|||
With optional argument DELETE-OTHER-WINDOWS-FLAG, other windows in the frame
|
||||
are removed." t nil)
|
||||
|
||||
(autoload (quote mh-tool-bar-letter-set) "mh-customize" "\
|
||||
Construct toolbar for `mh-letter-mode'." nil nil)
|
||||
|
||||
(autoload (quote mh-tool-bar-folder-set) "mh-customize" "\
|
||||
Construct toolbar for `mh-folder-mode'." nil nil)
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads (mh-goto-cur-msg mh-update-sequences mh-folder-line-matches-show-buffer-p)
|
||||
;;;;;; "mh-e" "mh-e.el" (15934 48879))
|
||||
;;;;;; "mh-e" "mh-e.el" (16040 30321))
|
||||
;;; Generated autoloads from mh-e.el
|
||||
|
||||
(autoload (quote mh-folder-line-matches-show-buffer-p) "mh-e" "\
|
||||
|
@ -186,11 +182,11 @@ recenter the folder buffer." nil nil)
|
|||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads (mh-prefix-help mh-help mh-store-buffer mh-store-msg
|
||||
;;;;;; mh-undo-folder mh-sort-folder mh-print-msg mh-page-digest-backwards
|
||||
;;;### (autoloads (mh-prefix-help mh-help mh-ephem-message mh-store-buffer
|
||||
;;;;;; mh-store-msg mh-undo-folder mh-sort-folder mh-print-msg mh-page-digest-backwards
|
||||
;;;;;; mh-page-digest mh-pipe-msg mh-pack-folder mh-list-folders
|
||||
;;;;;; mh-kill-folder mh-copy-msg mh-burst-digest) "mh-funcs" "mh-funcs.el"
|
||||
;;;;;; (15923 15465))
|
||||
;;;;;; (16039 39632))
|
||||
;;; Generated autoloads from mh-funcs.el
|
||||
|
||||
(autoload (quote mh-burst-digest) "mh-funcs" "\
|
||||
|
@ -200,8 +196,12 @@ digest are inserted into the folder after that message." t nil)
|
|||
|
||||
(autoload (quote mh-copy-msg) "mh-funcs" "\
|
||||
Copy the specified MSG-OR-SEQ to another FOLDER without deleting them.
|
||||
Default is the displayed message. If optional prefix argument is provided,
|
||||
then prompt for the message sequence." t nil)
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is copied.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence." t nil)
|
||||
|
||||
(autoload (quote mh-kill-folder) "mh-funcs" "\
|
||||
Remove the current folder and all included messages.
|
||||
|
@ -229,8 +229,14 @@ Advance displayed message to next digested message." t nil)
|
|||
Back up displayed message to previous digested message." t nil)
|
||||
|
||||
(autoload (quote mh-print-msg) "mh-funcs" "\
|
||||
Print MSG-OR-SEQ (default: displayed message) on printer.
|
||||
If optional prefix argument provided, then prompt for the message sequence.
|
||||
Print MSG-OR-SEQ on printer.
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is printed.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence.
|
||||
|
||||
The variable `mh-lpr-command-format' is used to generate the print command.
|
||||
The messages are formatted by mhl. See the variable `mhl-formfile'." t nil)
|
||||
|
||||
|
@ -256,6 +262,9 @@ The buffer can contain a shar file or uuencoded file.
|
|||
Default directory is the last directory used, or initially the value of
|
||||
`mh-store-default-directory' or the current directory." t nil)
|
||||
|
||||
(autoload (quote mh-ephem-message) "mh-funcs" "\
|
||||
Display STRING in the minibuffer momentarily." nil nil)
|
||||
|
||||
(autoload (quote mh-help) "mh-funcs" "\
|
||||
Display cheat sheet for the MH-Folder commands in minibuffer." t nil)
|
||||
|
||||
|
@ -265,7 +274,7 @@ Display cheat sheet for the commands of the current prefix in minibuffer." t nil
|
|||
;;;***
|
||||
|
||||
;;;### (autoloads (mh-insert-identity mh-identity-list-set mh-identity-make-menu)
|
||||
;;;;;; "mh-identity" "mh-identity.el" (15900 46388))
|
||||
;;;;;; "mh-identity" "mh-identity.el" (16039 39644))
|
||||
;;; Generated autoloads from mh-identity.el
|
||||
|
||||
(autoload (quote mh-identity-make-menu) "mh-identity" "\
|
||||
|
@ -283,12 +292,24 @@ Edit the `mh-identity-list' variable to define identity." t nil)
|
|||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads (mh-namazu-execute-search mh-swish++-execute-search
|
||||
;;;;;; mh-swish-execute-search mh-glimpse-execute-search mh-index-execute-commands
|
||||
;;;;;; mh-index-visit-folder mh-index-delete-folder-headers mh-index-insert-folder-headers
|
||||
;;;### (autoloads (mh-inc-spool-list-set) "mh-inc" "mh-inc.el" (16040
|
||||
;;;;;; 51164))
|
||||
;;; Generated autoloads from mh-inc.el
|
||||
|
||||
(autoload (quote mh-inc-spool-list-set) "mh-inc" "\
|
||||
Set-default SYMBOL to VALUE to update the `mh-inc-spool-list' variable.
|
||||
Also rebuilds the user commands.
|
||||
This is called after 'customize is used to alter `mh-inc-spool-list'." nil nil)
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads (mh-index-choose mh-namazu-execute-search mh-swish++-execute-search
|
||||
;;;;;; mh-swish-execute-search mh-index-new-messages mh-glimpse-execute-search
|
||||
;;;;;; mh-index-execute-commands mh-index-update-unseen mh-index-visit-folder
|
||||
;;;;;; mh-index-delete-folder-headers mh-index-group-by-folder mh-index-insert-folder-headers
|
||||
;;;;;; mh-index-previous-folder mh-index-next-folder mh-index-parse-search-regexp
|
||||
;;;;;; mh-index-do-search mh-index-search mh-index-update-maps)
|
||||
;;;;;; "mh-index" "mh-index.el" (15924 45743))
|
||||
;;;;;; "mh-index" "mh-index.el" (16038 15647))
|
||||
;;; Generated autoloads from mh-index.el
|
||||
|
||||
(autoload (quote mh-index-update-maps) "mh-index" "\
|
||||
|
@ -300,13 +321,15 @@ checksum -> (origin-folder, origin-index) map is updated too." nil nil)
|
|||
|
||||
(autoload (quote mh-index-search) "mh-index" "\
|
||||
Perform an indexed search in an MH mail folder.
|
||||
Use a prefix argument to repeat the search, as in REDO-SEARCH-FLAG below.
|
||||
|
||||
If REDO-SEARCH-FLAG is non-nil and the current folder buffer was generated by a
|
||||
index search, then the search is repeated. Otherwise, FOLDER is searched with
|
||||
SEARCH-REGEXP and the results are presented in an MH-E folder. If FOLDER is
|
||||
\"+\" then mail in all folders are searched. Optional argument WINDOW-CONFIG
|
||||
stores the window configuration that will be restored after the user quits the
|
||||
folder containing the index search results.
|
||||
folder containing the index search results. If optional argument UNSEEN-FLAG
|
||||
is non-nil, then all the messages are marked as unseen.
|
||||
|
||||
Four indexing programs are supported; if none of these are present, then grep
|
||||
is used. This function picks the first program that is available on your
|
||||
|
@ -358,12 +381,21 @@ Jump to the previous folder marker." t nil)
|
|||
(autoload (quote mh-index-insert-folder-headers) "mh-index" "\
|
||||
Annotate the search results with original folder names." nil nil)
|
||||
|
||||
(autoload (quote mh-index-group-by-folder) "mh-index" "\
|
||||
Partition the messages based on source folder.
|
||||
Returns an alist with the the folder names in the car and the cdr being the
|
||||
list of messages originally from that folder." nil nil)
|
||||
|
||||
(autoload (quote mh-index-delete-folder-headers) "mh-index" "\
|
||||
Delete the folder headers." nil nil)
|
||||
|
||||
(autoload (quote mh-index-visit-folder) "mh-index" "\
|
||||
Visit original folder from where the message at point was found." t nil)
|
||||
|
||||
(autoload (quote mh-index-update-unseen) "mh-index" "\
|
||||
Remove counterpart of MSG in source folder from `mh-unseen-seq'.
|
||||
Also `mh-update-unseen' is called in the original folder, if we have it open." nil nil)
|
||||
|
||||
(autoload (quote mh-index-execute-commands) "mh-index" "\
|
||||
Delete/refile the actual messages.
|
||||
The copies in the searched folder are then deleted/refiled to get the desired
|
||||
|
@ -403,6 +435,13 @@ daily from cron:
|
|||
|
||||
FOLDER-PATH is the directory in which SEARCH-REGEXP is used to search." nil nil)
|
||||
|
||||
(autoload (quote mh-index-new-messages) "mh-index" "\
|
||||
Display new messages.
|
||||
All messages in the `mh-unseen-seq' sequence from FOLDERS are displayed.
|
||||
By default the folders specified by `mh-index-new-messages-folders' are
|
||||
searched. With a prefix argument, enter a space-separated list of folders, or
|
||||
nothing to search all folders." t nil)
|
||||
|
||||
(autoload (quote mh-swish-execute-search) "mh-index" "\
|
||||
Execute swish-e and read the results.
|
||||
|
||||
|
@ -515,16 +554,69 @@ daily from cron:
|
|||
|
||||
FOLDER-PATH is the directory in which SEARCH-REGEXP is used to search." nil nil)
|
||||
|
||||
(autoload (quote mh-index-choose) "mh-index" "\
|
||||
Choose an indexing function.
|
||||
The side-effects of this function are that the variables `mh-indexer',
|
||||
`mh-index-execute-search-function', and `mh-index-next-result-function' are
|
||||
set according to the first indexer in `mh-indexer-choices' present on the
|
||||
system." nil nil)
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads (mh-junk-whitelist mh-junk-blacklist) "mh-junk"
|
||||
;;;;;; "mh-junk.el" (16023 25085))
|
||||
;;; Generated autoloads from mh-junk.el
|
||||
|
||||
(autoload (quote mh-junk-blacklist) "mh-junk" "\
|
||||
Blacklist MSG-OR-SEQ as spam.
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is blacklisted.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence.
|
||||
|
||||
First the appropriate function is called depending on the value of
|
||||
`mh-junk-choice'. Then if `mh-junk-mail-folder' is a string then the message is
|
||||
refiled to that folder. If nil, the message is deleted.
|
||||
|
||||
To change the spam program being used, customize `mh-junk-program'. Directly
|
||||
setting `mh-junk-choice' is not recommended.
|
||||
|
||||
The documentation for the following functions describes what setup is needed
|
||||
for the different spam fighting programs:
|
||||
|
||||
- `mh-bogofilter-blacklist'
|
||||
- `mh-spamprobe-blacklist'
|
||||
- `mh-spamassassin-blacklist'" t nil)
|
||||
|
||||
(autoload (quote mh-junk-whitelist) "mh-junk" "\
|
||||
Whitelist MSG-OR-SEQ incorrectly classified as spam.
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is whitelisted.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence.
|
||||
|
||||
First the appropriate function is called depending on the value of
|
||||
`mh-junk-choice'. Then the message is refiled to `mh-inbox'.
|
||||
|
||||
To change the spam program being used, customize `mh-junk-program'. Directly
|
||||
setting `mh-junk-choice' is not recommended." t nil)
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads (mh-mime-inline-part mh-mime-save-part mh-push-button
|
||||
;;;;;; mh-press-button mh-mime-display mh-mime-save-parts mh-display-emphasis
|
||||
;;;;;; mh-display-smileys mh-add-missing-mime-version-header mh-destroy-postponed-handles
|
||||
;;;;;; mh-mime-cleanup mh-mml-secure-message-encrypt-pgpmime mh-mml-secure-message-sign-pgpmime
|
||||
;;;;;; mh-mml-attach-file mh-mml-forward-message mh-mml-to-mime
|
||||
;;;;;; mh-revert-mhn-edit mh-edit-mhn mh-mhn-compose-forw mh-mhn-compose-external-compressed-tar
|
||||
;;;;;; mh-press-button mh-mime-display mh-decode-message-header
|
||||
;;;;;; mh-mime-save-parts mh-display-emphasis mh-display-smileys
|
||||
;;;;;; mh-add-missing-mime-version-header mh-destroy-postponed-handles
|
||||
;;;;;; mh-mime-cleanup mh-mml-directive-present-p mh-mml-secure-message-encrypt-pgpmime
|
||||
;;;;;; mh-mml-secure-message-sign-pgpmime mh-mml-attach-file mh-mml-forward-message
|
||||
;;;;;; mh-mml-to-mime mh-mhn-directive-present-p mh-revert-mhn-edit
|
||||
;;;;;; mh-edit-mhn mh-mhn-compose-forw mh-mhn-compose-external-compressed-tar
|
||||
;;;;;; mh-mhn-compose-anon-ftp mh-mhn-compose-insertion mh-compose-forward
|
||||
;;;;;; mh-compose-insertion) "mh-mime" "mh-mime.el" (15923 15465))
|
||||
;;;;;; mh-compose-insertion) "mh-mime" "mh-mime.el" (16039 39680))
|
||||
;;; Generated autoloads from mh-mime.el
|
||||
|
||||
(autoload (quote mh-compose-insertion) "mh-mime" "\
|
||||
|
@ -591,7 +683,8 @@ Process the current draft with the mhn program, which, using directives
|
|||
already inserted in the draft, fills in all the MIME components and header
|
||||
fields.
|
||||
|
||||
This step should be done last just before sending the message.
|
||||
This step is performed automatically when sending the message, but this
|
||||
function may be called manually before sending the draft as well.
|
||||
|
||||
The `\\[mh-revert-mhn-edit]' command undoes this command. The arguments in the
|
||||
list `mh-mhn-args' are passed to mhn if this function is passed an optional
|
||||
|
@ -602,8 +695,7 @@ components in a message, see \\[mh-mhn-compose-insertion] (generic insertion
|
|||
from a file), \\[mh-mhn-compose-anon-ftp] (external reference to file via
|
||||
anonymous ftp), \\[mh-mhn-compose-external-compressed-tar] (reference to
|
||||
compressed tar file via anonymous ftp), and \\[mh-mhn-compose-forw] (forward
|
||||
message). If these helper functions are used, `mh-edit-mhn' is run
|
||||
automatically when the draft is sent.
|
||||
message).
|
||||
|
||||
The value of `mh-edit-mhn-hook' is a list of functions to be called, with no
|
||||
arguments, after performing the conversion.
|
||||
|
@ -614,8 +706,13 @@ The mhn program is part of MH version 6.8 or later." t nil)
|
|||
Undo the effect of \\[mh-edit-mhn] by reverting to the backup file.
|
||||
Optional non-nil argument NOCONFIRM means don't ask for confirmation." t nil)
|
||||
|
||||
(autoload (quote mh-mhn-directive-present-p) "mh-mime" "\
|
||||
Check if the current buffer has text which might be a MHN directive." nil nil)
|
||||
|
||||
(autoload (quote mh-mml-to-mime) "mh-mime" "\
|
||||
Compose MIME message from mml directives." t nil)
|
||||
Compose MIME message from mml directives.
|
||||
This step is performed automatically when sending the message, but this
|
||||
function may be called manually before sending the draft as well." t nil)
|
||||
|
||||
(autoload (quote mh-mml-forward-message) "mh-mime" "\
|
||||
Forward a message as attachment.
|
||||
|
@ -640,6 +737,9 @@ Add directive to encrypt/sign the entire message." t nil)
|
|||
Add directive to encrypt and sign the entire message.
|
||||
If called with a prefix argument DONTSIGN, only encrypt (do NOT sign)." t nil)
|
||||
|
||||
(autoload (quote mh-mml-directive-present-p) "mh-mime" "\
|
||||
Check if the current buffer has text which may be an MML directive." nil nil)
|
||||
|
||||
(autoload (quote mh-mime-cleanup) "mh-mime" "\
|
||||
Free the decoded MIME parts." nil nil)
|
||||
|
||||
|
@ -663,6 +763,9 @@ If ARG, prompt for directory, else use that specified by the variable
|
|||
mh_profile directives, since this function calls on mhstore or mhn to do the
|
||||
actual storing." t nil)
|
||||
|
||||
(autoload (quote mh-decode-message-header) "mh-mime" "\
|
||||
Decode RFC2047 encoded message header fields." nil nil)
|
||||
|
||||
(autoload (quote mh-mime-display) "mh-mime" "\
|
||||
Display (and possibly decode) MIME handles.
|
||||
Optional argument, PRE-DISSECTED-HANDLES is a list of MIME handles. If
|
||||
|
@ -689,7 +792,7 @@ Toggle display of the raw MIME part." t nil)
|
|||
;;;***
|
||||
|
||||
;;;### (autoloads (mh-do-search mh-pick-do-search mh-do-pick-search
|
||||
;;;;;; mh-search-folder) "mh-pick" "mh-pick.el" (15924 45743))
|
||||
;;;;;; mh-search-folder) "mh-pick" "mh-pick.el" (16037 44490))
|
||||
;;; Generated autoloads from mh-pick.el
|
||||
|
||||
(autoload (quote mh-search-folder) "mh-pick" "\
|
||||
|
@ -719,14 +822,16 @@ indexing program specified in `mh-index-program' is used." t nil)
|
|||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads (mh-thread-refile mh-thread-delete mh-thread-ancestor
|
||||
;;;;;; mh-thread-previous-sibling mh-thread-next-sibling mh-thread-forget-message
|
||||
;;;;;; mh-toggle-threads mh-thread-add-spaces mh-thread-inc mh-delete-subject-or-thread
|
||||
;;;### (autoloads (mh-narrow-to-tick mh-toggle-tick mh-notate-tick
|
||||
;;;;;; mh-thread-refile mh-thread-delete mh-thread-ancestor mh-thread-previous-sibling
|
||||
;;;;;; mh-thread-next-sibling mh-thread-forget-message mh-toggle-threads
|
||||
;;;;;; mh-thread-add-spaces mh-thread-inc mh-delete-subject-or-thread
|
||||
;;;;;; mh-delete-subject mh-narrow-to-subject mh-region-to-msg-list
|
||||
;;;;;; mh-interactive-msg-or-seq mh-msg-or-seq-to-msg-list mh-iterate-on-msg-or-seq
|
||||
;;;;;; mh-iterate-on-messages-in-region mh-add-to-sequence mh-notate-cur
|
||||
;;;;;; mh-notate-seq mh-map-to-seq-msgs mh-rename-seq mh-widen mh-put-msg-in-seq
|
||||
;;;;;; mh-narrow-to-seq mh-msg-is-in-seq mh-list-sequences mh-delete-seq)
|
||||
;;;;;; "mh-seq" "mh-seq.el" (15923 15465))
|
||||
;;;;;; "mh-seq" "mh-seq.el" (16039 39691))
|
||||
;;; Generated autoloads from mh-seq.el
|
||||
|
||||
(autoload (quote mh-delete-seq) "mh-seq" "\
|
||||
|
@ -736,17 +841,21 @@ Delete the SEQUENCE." t nil)
|
|||
List the sequences defined in the folder being visited." t nil)
|
||||
|
||||
(autoload (quote mh-msg-is-in-seq) "mh-seq" "\
|
||||
Display the sequences that contain MESSAGE (default: current message)." t nil)
|
||||
Display the sequences that contain MESSAGE.
|
||||
Default is the displayed message." t nil)
|
||||
|
||||
(autoload (quote mh-narrow-to-seq) "mh-seq" "\
|
||||
Restrict display of this folder to just messages in SEQUENCE.
|
||||
Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command." t nil)
|
||||
|
||||
(autoload (quote mh-put-msg-in-seq) "mh-seq" "\
|
||||
Add MSG-OR-SEQ (default: displayed message) to SEQUENCE.
|
||||
If optional prefix argument provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then
|
||||
the selected region is added to the sequence." t nil)
|
||||
Add MSG-OR-SEQ to SEQUENCE.
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is added to the sequence.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence." t nil)
|
||||
|
||||
(autoload (quote mh-widen) "mh-seq" "\
|
||||
Remove restrictions from current folder, thereby showing all messages." t nil)
|
||||
|
@ -779,6 +888,34 @@ till END. In each step BODY is executed.
|
|||
|
||||
If VAR is nil then the loop is executed without any binding." nil (quote macro))
|
||||
|
||||
(autoload (quote mh-iterate-on-msg-or-seq) "mh-seq" "\
|
||||
Iterate an operation over a region or sequence.
|
||||
|
||||
VAR is bound to each message in turn in a loop over MSG-OR-SEQ, which can be a
|
||||
message number, a list of message numbers, a sequence, or a region in a cons
|
||||
cell. In each iteration, BODY is executed.
|
||||
|
||||
The parameter MSG-OR-SEQ is usually created with `mh-interactive-msg-or-seq'
|
||||
in order to provide a uniform interface to MH-E functions." nil (quote macro))
|
||||
|
||||
(autoload (quote mh-msg-or-seq-to-msg-list) "mh-seq" "\
|
||||
Return a list of messages for MSG-OR-SEQ.
|
||||
MSG-OR-SEQ can be a message number, a list of message numbers, a sequence, or
|
||||
a region in a cons cell." nil nil)
|
||||
|
||||
(autoload (quote mh-interactive-msg-or-seq) "mh-seq" "\
|
||||
Return interactive specification for message, sequence, or region.
|
||||
By convention, the name of this argument is msg-or-seq.
|
||||
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then this
|
||||
function returns a cons-cell of the region.
|
||||
If optional prefix argument provided, then prompt for message sequence with
|
||||
SEQUENCE-PROMPT and return sequence.
|
||||
Otherwise, the message number at point is returned.
|
||||
|
||||
This function is usually used with `mh-iterate-on-msg-or-seq' in order to
|
||||
provide a uniform interface to MH-E functions." nil nil)
|
||||
|
||||
(autoload (quote mh-region-to-msg-list) "mh-seq" "\
|
||||
Return a list of messages within the region between BEGIN and END." nil nil)
|
||||
|
||||
|
@ -829,11 +966,23 @@ Mark current message and all its children for subsequent deletion." t nil)
|
|||
(autoload (quote mh-thread-refile) "mh-seq" "\
|
||||
Mark current message and all its children for refiling to FOLDER." t nil)
|
||||
|
||||
(autoload (quote mh-notate-tick) "mh-seq" "\
|
||||
Highlight current line if MSG is in TICKED-MSGS.
|
||||
If optional argument IGNORE-NARROWING is non-nil then highlighting is carried
|
||||
out even if folder is narrowed to `mh-tick-seq'." nil nil)
|
||||
|
||||
(autoload (quote mh-toggle-tick) "mh-seq" "\
|
||||
Toggle tick mark of all messages in region BEGIN to END." t nil)
|
||||
|
||||
(autoload (quote mh-narrow-to-tick) "mh-seq" "\
|
||||
Restrict display of this folder to just messages in `mh-tick-seq'.
|
||||
Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command." t nil)
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads (mh-speed-add-folder mh-speed-invalidate-map mh-speed-flists
|
||||
;;;;;; mh-speed-view mh-speed-toggle mh-folder-speedbar-buttons)
|
||||
;;;;;; "mh-speed" "mh-speed.el" (15933 21584))
|
||||
;;;;;; "mh-speed" "mh-speed.el" (16037 44491))
|
||||
;;; Generated autoloads from mh-speed.el
|
||||
|
||||
(autoload (quote mh-folder-speedbar-buttons) "mh-speed" "\
|
||||
|
@ -854,7 +1003,8 @@ Optional ARGS are ignored." t nil)
|
|||
|
||||
(autoload (quote mh-speed-flists) "mh-speed" "\
|
||||
Execute flists -recurse and update message counts.
|
||||
If FORCE is non-nil the timer is reset." t nil)
|
||||
If FORCE is non-nil the timer is reset. If FOLDER is non-nil then flists is run
|
||||
only for that one folder." t nil)
|
||||
|
||||
(autoload (quote mh-speed-invalidate-map) "mh-speed" "\
|
||||
Remove FOLDER from various optimization caches." t nil)
|
||||
|
@ -866,7 +1016,7 @@ The function invalidates the latest ancestor that is present." nil nil)
|
|||
;;;***
|
||||
|
||||
;;;### (autoloads (mh-get-msg-num mh-goto-address-find-address-at-point)
|
||||
;;;;;; "mh-utils" "mh-utils.el" (15924 47279))
|
||||
;;;;;; "mh-utils" "mh-utils.el" (16039 40655))
|
||||
;;; Generated autoloads from mh-utils.el
|
||||
|
||||
(autoload (quote mh-goto-address-find-address-at-point) "mh-utils" "\
|
||||
|
@ -885,7 +1035,7 @@ not pointing to a message." nil nil)
|
|||
;;;;;; mh-alias-add-alias mh-alias-from-has-no-alias-p mh-alias-address-to-alias
|
||||
;;;;;; mh-alias-letter-expand-alias mh-alias-minibuffer-confirm-address
|
||||
;;;;;; mh-read-address mh-alias-reload) "mh-alias" "mh-alias.el"
|
||||
;;;;;; (15924 45743))
|
||||
;;;;;; (16039 39579))
|
||||
;;; Generated autoloads from mh-alias.el
|
||||
|
||||
(autoload (quote mh-alias-reload) "mh-alias" "\
|
||||
|
@ -904,7 +1054,9 @@ Expand mail alias before point." nil nil)
|
|||
Return the ADDRESS alias if defined, or nil." nil nil)
|
||||
|
||||
(autoload (quote mh-alias-from-has-no-alias-p) "mh-alias" "\
|
||||
Return t is From has no current alias set." nil nil)
|
||||
Return t is From has no current alias set.
|
||||
In the exceptional situation where there isn't a From header in the message the
|
||||
function returns nil." nil nil)
|
||||
|
||||
(autoload (quote mh-alias-add-alias) "mh-alias" "\
|
||||
*Add ALIAS for ADDRESS in personal alias file.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
;;; mh-mime.el --- MH-E support for composing MIME messages
|
||||
|
||||
;; Copyright (C) 1993, 1995, 2001, 2002 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 1993, 1995, 2001, 02, 2003 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Bill Wohler <wohler@newt.com>
|
||||
;; Maintainer: Bill Wohler <wohler@newt.com>
|
||||
|
@ -32,8 +32,6 @@
|
|||
|
||||
;;; Change Log:
|
||||
|
||||
;; $Id: mh-mime.el,v 1.100 2003/01/25 19:18:51 satyaki Exp $
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl)
|
||||
|
@ -58,6 +56,7 @@
|
|||
(autoload 'mml-insert-empty-tag "mml")
|
||||
(autoload 'mml-to-mime "mml")
|
||||
(autoload 'mml-attach-file "mml")
|
||||
(autoload 'rfc2047-decode-region "rfc2047")
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-compose-insertion (&optional inline)
|
||||
|
@ -235,7 +234,6 @@ See also \\[mh-edit-mhn]."
|
|||
The file specified by FILENAME is encoded as TYPE. An optional DESCRIPTION is
|
||||
used as the Content-Description field, optional set of ATTRIBUTES and an
|
||||
optional COMMENT can also be included."
|
||||
(setq mh-mhn-compose-insert-flag t)
|
||||
(beginning-of-line)
|
||||
(insert "#" type)
|
||||
(and attributes
|
||||
|
@ -306,7 +304,6 @@ DESCRIPTION, a line of text for the Content-description header, ATTRIBUTES,
|
|||
EXTRA-PARAMS, and COMMENT.
|
||||
|
||||
See also \\[mh-edit-mhn]."
|
||||
(setq mh-mhn-compose-insert-flag t)
|
||||
(beginning-of-line)
|
||||
(insert "#@" type)
|
||||
(and attributes
|
||||
|
@ -341,7 +338,6 @@ See also \\[mh-edit-mhn]."
|
|||
(if mh-sent-from-msg
|
||||
(format " [%d]" mh-sent-from-msg)
|
||||
"")))))
|
||||
(setq mh-mhn-compose-insert-flag t)
|
||||
(beginning-of-line)
|
||||
(insert "#forw [")
|
||||
(and description
|
||||
|
@ -368,7 +364,8 @@ Process the current draft with the mhn program, which, using directives
|
|||
already inserted in the draft, fills in all the MIME components and header
|
||||
fields.
|
||||
|
||||
This step should be done last just before sending the message.
|
||||
This step is performed automatically when sending the message, but this
|
||||
function may be called manually before sending the draft as well.
|
||||
|
||||
The `\\[mh-revert-mhn-edit]' command undoes this command. The arguments in the
|
||||
list `mh-mhn-args' are passed to mhn if this function is passed an optional
|
||||
|
@ -379,8 +376,7 @@ components in a message, see \\[mh-mhn-compose-insertion] (generic insertion
|
|||
from a file), \\[mh-mhn-compose-anon-ftp] (external reference to file via
|
||||
anonymous ftp), \\[mh-mhn-compose-external-compressed-tar] \ \(reference to
|
||||
compressed tar file via anonymous ftp), and \\[mh-mhn-compose-forw] (forward
|
||||
message). If these helper functions are used, `mh-edit-mhn' is run
|
||||
automatically when the draft is sent.
|
||||
message).
|
||||
|
||||
The value of `mh-edit-mhn-hook' is a list of functions to be called, with no
|
||||
arguments, after performing the conversion.
|
||||
|
@ -396,7 +392,6 @@ The mhn program is part of MH version 6.8 or later."
|
|||
(t
|
||||
(mh-exec-cmd-error (format "mhdraft=%s" buffer-file-name)
|
||||
"mhn" (if extra-args mh-mhn-args) buffer-file-name)))
|
||||
(setq mh-mhn-compose-insert-flag nil)
|
||||
(revert-buffer t t)
|
||||
(message "mhn editing...done")
|
||||
(run-hooks 'mh-edit-mhn-hook))
|
||||
|
@ -429,18 +424,35 @@ Optional non-nil argument NOCONFIRM means don't ask for confirmation."
|
|||
(insert-file-contents backup-file))
|
||||
(after-find-file nil)))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-mhn-directive-present-p ()
|
||||
"Check if the current buffer has text which might be a MHN directive."
|
||||
(save-excursion
|
||||
(block 'search-for-mhn-directive
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^#" nil t)
|
||||
(let ((s (buffer-substring-no-properties (point) (line-end-position))))
|
||||
(cond ((equal s ""))
|
||||
((string-match "^forw[ \t\n]+" s)
|
||||
(return-from 'search-for-mhn-directive t))
|
||||
(t (let ((first-token (car (split-string s "[ \t;@]"))))
|
||||
(when (string-match mh-media-type-regexp first-token)
|
||||
(return-from 'search-for-mhn-directive t)))))))
|
||||
nil)))
|
||||
|
||||
|
||||
|
||||
;;; MIME composition functions
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-mml-to-mime ()
|
||||
"Compose MIME message from mml directives."
|
||||
"Compose MIME message from mml directives.
|
||||
This step is performed automatically when sending the message, but this
|
||||
function may be called manually before sending the draft as well."
|
||||
(interactive)
|
||||
(when mh-gnus-pgp-support-flag ;; This is only needed for PGP
|
||||
(message-options-set-recipient))
|
||||
(mml-to-mime)
|
||||
(setq mh-mml-compose-insert-flag nil))
|
||||
(mml-to-mime))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-mml-forward-message (description folder message)
|
||||
|
@ -460,8 +472,7 @@ number."
|
|||
(mml-attach-file (format "%s%s/%d"
|
||||
mh-user-path (substring folder 1) msg)
|
||||
"message/rfc822"
|
||||
description))
|
||||
(setq mh-mml-compose-insert-flag t))
|
||||
description)))
|
||||
(t (error "The message number, %s is not a integer!" msg)))))
|
||||
|
||||
;;;###mh-autoload
|
||||
|
@ -488,8 +499,7 @@ automatically."
|
|||
nil t nil nil
|
||||
"attachment"))))
|
||||
(mml-insert-empty-tag 'part 'type type 'filename file
|
||||
'disposition dispos 'description description)
|
||||
(setq mh-mml-compose-insert-flag t)))
|
||||
'disposition dispos 'description description)))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-mml-secure-message-sign-pgpmime ()
|
||||
|
@ -497,8 +507,7 @@ automatically."
|
|||
(interactive)
|
||||
(if (not mh-gnus-pgp-support-flag)
|
||||
(error "Sorry. Your version of gnus does not support PGP/GPG")
|
||||
(mml-secure-message-sign-pgpmime)
|
||||
(setq mh-mml-compose-insert-flag t)))
|
||||
(mml-secure-message-sign-pgpmime)))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-mml-secure-message-encrypt-pgpmime (&optional dontsign)
|
||||
|
@ -507,8 +516,16 @@ If called with a prefix argument DONTSIGN, only encrypt (do NOT sign)."
|
|||
(interactive "P")
|
||||
(if (not mh-gnus-pgp-support-flag)
|
||||
(error "Sorry. Your version of gnus does not support PGP/GPG")
|
||||
(mml-secure-message-encrypt-pgpmime dontsign)
|
||||
(setq mh-mml-compose-insert-flag t)))
|
||||
(mml-secure-message-encrypt-pgpmime dontsign)))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-mml-directive-present-p ()
|
||||
"Check if the current buffer has text which may be an MML directive."
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(re-search-forward
|
||||
"\\(<#part\\(.\\|\n\\)*>[ \n\t]*<#/part>\\|^<#secure.+>$\\)"
|
||||
nil t)))
|
||||
|
||||
|
||||
|
||||
|
@ -547,6 +564,8 @@ BODY."
|
|||
(mh-defun-compat mm-handle-multipart-ctl-parameter (handle parameter)
|
||||
(get-text-property 0 parameter (car handle)))
|
||||
|
||||
(mh-do-in-xemacs (defvar default-enable-multibyte-characters))
|
||||
|
||||
;; Copy of original function in mm-decode.el
|
||||
(mh-defun-compat mm-readable-p (handle)
|
||||
"Say whether the content of HANDLE is readable."
|
||||
|
@ -610,8 +629,7 @@ BODY."
|
|||
"Free the decoded MIME parts."
|
||||
(let ((mime-data (gethash (current-buffer) mh-globals-hash)))
|
||||
;; This is for Emacs, what about XEmacs?
|
||||
(cond ((fboundp 'remove-images)
|
||||
(remove-images (point-min) (point-max))))
|
||||
(mh-funcall-if-exists remove-images (point-min) (point-max))
|
||||
(when mime-data
|
||||
(mm-destroy-parts (mh-mime-handles mime-data))
|
||||
(remhash (current-buffer) mh-globals-hash))))
|
||||
|
@ -662,6 +680,7 @@ I have seen this only in spam, so maybe we shouldn't fix this ;-)"
|
|||
(when (and mh-graphical-smileys-flag
|
||||
(fboundp 'smiley-region)
|
||||
(boundp 'font-lock-maximum-size)
|
||||
font-lock-maximum-size
|
||||
(>= (/ font-lock-maximum-size 8) (buffer-size)))
|
||||
(smiley-region (point-min) (point-max))))
|
||||
|
||||
|
@ -669,8 +688,8 @@ I have seen this only in spam, so maybe we shouldn't fix this ;-)"
|
|||
(defun mh-display-emphasis ()
|
||||
"Function to display graphical emphasis."
|
||||
(when (and mh-graphical-emphasis-flag
|
||||
(boundp 'font-lock-maximum-size)
|
||||
(>= (/ font-lock-maximum-size 8) (buffer-size)))
|
||||
(if font-lock-maximum-size
|
||||
(>= (/ font-lock-maximum-size 8) (buffer-size))))
|
||||
(flet ((article-goto-body ())) ; shadow this function to do nothing
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
|
@ -685,7 +704,10 @@ I have seen this only in spam, so maybe we shouldn't fix this ;-)"
|
|||
(unless (>= (string-to-number emacs-version) 21)
|
||||
;; XEmacs doesn't care.
|
||||
(set-keymap-parent map mh-show-mode-map))
|
||||
(define-key map [mouse-2] 'mh-push-button)
|
||||
(mh-do-in-gnu-emacs
|
||||
(define-key map [mouse-2] 'mh-push-button))
|
||||
(mh-do-in-xemacs
|
||||
(define-key map '(button2) 'mh-push-button))
|
||||
(dolist (c mh-mime-button-commands)
|
||||
(define-key map (cadr c) (car c)))
|
||||
map))
|
||||
|
@ -708,7 +730,10 @@ I have seen this only in spam, so maybe we shouldn't fix this ;-)"
|
|||
(unless (>= (string-to-number emacs-version) 21)
|
||||
(set-keymap-parent map mh-show-mode-map))
|
||||
(define-key map "\r" 'mh-press-button)
|
||||
(define-key map [mouse-2] 'mh-push-button)
|
||||
(mh-do-in-gnu-emacs
|
||||
(define-key map [mouse-2] 'mh-push-button))
|
||||
(mh-do-in-xemacs
|
||||
(define-key map '(button2) 'mh-push-button))
|
||||
map))
|
||||
|
||||
(defvar mh-mime-save-parts-directory nil
|
||||
|
@ -755,22 +780,46 @@ actual storing."
|
|||
(if (equal nil mh-mime-save-parts-default-directory)
|
||||
(setq mh-mime-save-parts-directory directory))
|
||||
(save-excursion
|
||||
(set-buffer (get-buffer-create " *mh-store*"))
|
||||
(set-buffer (get-buffer-create mh-log-buffer))
|
||||
(cd directory)
|
||||
(setq mh-mime-save-parts-directory directory)
|
||||
(erase-buffer)
|
||||
(apply 'call-process
|
||||
(expand-file-name command mh-progs) nil t nil
|
||||
(mh-list-to-string (list folder msg "-auto")))
|
||||
(if (> (buffer-size) 0)
|
||||
(save-window-excursion
|
||||
(switch-to-buffer-other-window " *mh-store*")
|
||||
(sit-for 3)))))))
|
||||
(let ((initial-size (mh-truncate-log-buffer)))
|
||||
(apply 'call-process
|
||||
(expand-file-name command mh-progs) nil t nil
|
||||
(mh-list-to-string (list folder msg "-auto")))
|
||||
(if (> (buffer-size) initial-size)
|
||||
(save-window-excursion
|
||||
(switch-to-buffer-other-window mh-log-buffer)
|
||||
(sit-for 3))))))))
|
||||
|
||||
;; Avoid errors if gnus-sum isn't loaded yet...
|
||||
(defvar gnus-newsgroup-charset nil)
|
||||
(defvar gnus-newsgroup-name nil)
|
||||
|
||||
(defun mh-decode-message-body ()
|
||||
"Decode message based on charset.
|
||||
If message has been encoded for transfer take that into account."
|
||||
(let* ((ct (ignore-errors (mail-header-parse-content-type
|
||||
(message-fetch-field "Content-Type" t))))
|
||||
(charset (mail-content-type-get ct 'charset))
|
||||
(cte (message-fetch-field "Content-Transfer-Encoding")))
|
||||
(when (stringp cte) (setq cte (mail-header-strip cte)))
|
||||
(when (or (not ct) (equal (car ct) "text/plain"))
|
||||
(save-restriction
|
||||
(narrow-to-region (min (1+ (mh-mail-header-end)) (point-max))
|
||||
(point-max))
|
||||
(mm-decode-body charset
|
||||
(and cte (intern (downcase
|
||||
(gnus-strip-whitespace cte))))
|
||||
(car ct))))))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-decode-message-header ()
|
||||
"Decode RFC2047 encoded message header fields."
|
||||
(when mh-decode-mime-flag
|
||||
(let ((buffer-read-only nil))
|
||||
(rfc2047-decode-region (point-min) (mh-mail-header-end)))))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-mime-display (&optional pre-dissected-handles)
|
||||
"Display (and possibly decode) MIME handles.
|
||||
|
@ -778,36 +827,43 @@ 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))
|
||||
(folder mh-show-folder-buffer)
|
||||
(raw-message-data (buffer-string)))
|
||||
(flet ((mm-handle-set-external-undisplayer
|
||||
(handle function)
|
||||
(mh-handle-set-external-undisplayer folder handle function)))
|
||||
;; If needed dissect the current buffer
|
||||
(if pre-dissected-handles
|
||||
(setq handles pre-dissected-handles)
|
||||
(setq handles (or (mm-dissect-buffer nil) (mm-uu-dissect)))
|
||||
(setf (mh-mime-handles (mh-buffer-data))
|
||||
(mm-merge-handles handles (mh-mime-handles (mh-buffer-data))))
|
||||
(goto-char (point-min))
|
||||
(unless (search-forward "\n\n" nil t)
|
||||
(goto-char (point-max))
|
||||
(insert "\n\n"))
|
||||
|
||||
;; Use charset to decode body...
|
||||
(unless handles
|
||||
(let* ((ct (ignore-errors
|
||||
(mail-header-parse-content-type
|
||||
(message-fetch-field "Content-Type" t))))
|
||||
(charset (mail-content-type-get ct 'charset)))
|
||||
(when (stringp charset)
|
||||
(mm-decode-body charset)))))
|
||||
(condition-case err
|
||||
(progn
|
||||
;; If needed dissect the current buffer
|
||||
(if pre-dissected-handles
|
||||
(setq handles pre-dissected-handles)
|
||||
(setq handles (or (mm-dissect-buffer nil) (mm-uu-dissect)))
|
||||
(setf (mh-mime-handles (mh-buffer-data))
|
||||
(mm-merge-handles handles
|
||||
(mh-mime-handles (mh-buffer-data))))
|
||||
(unless handles (mh-decode-message-body)))
|
||||
|
||||
(when (and handles (or (not (stringp (car handles))) (cdr handles)))
|
||||
;; Goto start of message body
|
||||
(goto-char (point-min))
|
||||
(or (search-forward "\n\n" nil t) (goto-char (point-max)))
|
||||
(when (and handles
|
||||
(or (not (stringp (car handles))) (cdr handles)))
|
||||
;; Goto start of message body
|
||||
(goto-char (point-min))
|
||||
(or (search-forward "\n\n" nil t) (goto-char (point-max)))
|
||||
|
||||
;; Delete the body
|
||||
(delete-region (point) (point-max))
|
||||
;; Delete the body
|
||||
(delete-region (point) (point-max))
|
||||
|
||||
;; Display the MIME handles
|
||||
(mh-mime-display-part handles)))))
|
||||
;; Display the MIME handles
|
||||
(mh-mime-display-part handles)))
|
||||
(error
|
||||
(message "Please report this error. The error message is:\n %s"
|
||||
(error-message-string err))
|
||||
(delete-region (point-min) (point-max))
|
||||
(insert raw-message-data))))))
|
||||
|
||||
(defun mh-mime-display-part (handle)
|
||||
"Decides the viewer to call based on the type of HANDLE."
|
||||
|
@ -868,7 +924,8 @@ This is only useful if a Content-Disposition header is not present."
|
|||
(let* ((image (mm-get-image handle)))
|
||||
(cond ((fboundp 'glyph-width)
|
||||
;; XEmacs -- totally untested, copied from gnus
|
||||
(and (< (glyph-width image)
|
||||
(and (mh-funcall-if-exists glyphp image)
|
||||
(< (glyph-width image)
|
||||
(or mh-max-inline-image-width
|
||||
(window-pixel-width)))
|
||||
(< (glyph-height image)
|
||||
|
@ -876,8 +933,9 @@ This is only useful if a Content-Disposition header is not present."
|
|||
(window-pixel-height)))))
|
||||
((fboundp 'image-size)
|
||||
;; Emacs21 -- copied from gnus
|
||||
(let ((size (image-size image)))
|
||||
(and (< (cdr size)
|
||||
(let ((size (mh-funcall-if-exists image-size image)))
|
||||
(and size
|
||||
(< (cdr size)
|
||||
(or mh-max-inline-image-height
|
||||
(1- (window-height))))
|
||||
(< (car size)
|
||||
|
@ -889,7 +947,8 @@ This is only useful if a Content-Disposition header is not present."
|
|||
(defun mh-inline-vcard-p (handle)
|
||||
"Decide if HANDLE is a vcard that must be displayed inline."
|
||||
(let ((type (mm-handle-type handle)))
|
||||
(and (consp type)
|
||||
(and (or (featurep 'vcard) (fboundp 'vcard-pretty-print))
|
||||
(consp type)
|
||||
(equal (car type) "text/x-vcard")
|
||||
(save-excursion
|
||||
(save-restriction
|
||||
|
@ -933,6 +992,10 @@ This is only useful if a Content-Disposition header is not present."
|
|||
(mh-mm-display-part handle)))
|
||||
(goto-char (point-max)))))
|
||||
|
||||
(mh-do-in-xemacs
|
||||
(defvar dots)
|
||||
(defvar type))
|
||||
|
||||
(defun mh-insert-mime-button (handle index displayed)
|
||||
"Insert MIME button for HANDLE.
|
||||
INDEX is the part number that will be DISPLAYED. It is also used by commands
|
||||
|
@ -999,9 +1062,9 @@ like \"K v\" which operate on individual MIME parts."
|
|||
(progn
|
||||
;; Delete the button and displayed part (if any)
|
||||
(let ((region (get-text-property point 'mh-region)))
|
||||
(when region
|
||||
(when (fboundp 'remove-images)
|
||||
(remove-images (car region) (cdr region))))
|
||||
(when (and region (fboundp 'remove-images))
|
||||
(mh-funcall-if-exists
|
||||
remove-images (car region) (cdr region)))
|
||||
(mm-display-part handle)
|
||||
(when region
|
||||
(delete-region (car region) (cdr region))))
|
||||
|
@ -1067,20 +1130,33 @@ 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")
|
||||
(set-buffer (window-buffer (posn-window (event-start event))))
|
||||
(select-window (posn-window (event-start event)))
|
||||
(let* ((pos (posn-point (event-start event)))
|
||||
(folder mh-show-folder-buffer)
|
||||
(mm-inline-media-tests mh-mm-inline-media-tests)
|
||||
(data (get-text-property pos 'mh-data))
|
||||
(function (get-text-property pos 'mh-callback))
|
||||
(buffer-read-only nil))
|
||||
(flet ((mm-handle-set-external-undisplayer
|
||||
(handle function)
|
||||
(mh-handle-set-external-undisplayer folder handle function)))
|
||||
(goto-char pos)
|
||||
(unwind-protect (and function (funcall function data))
|
||||
(set-buffer-modified-p nil)))))
|
||||
(save-excursion
|
||||
(let* ((event-window
|
||||
(or (mh-funcall-if-exists posn-window (event-start event));GNU Emacs
|
||||
(mh-funcall-if-exists event-window event))) ;XEmacs
|
||||
(event-position
|
||||
(or (mh-funcall-if-exists posn-point (event-start event)) ;GNU Emacs
|
||||
(mh-funcall-if-exists event-closest-point event))) ;XEmacs
|
||||
(original-window (selected-window))
|
||||
(original-position (progn
|
||||
(set-buffer (window-buffer event-window))
|
||||
(set-marker (make-marker) (point))))
|
||||
(folder mh-show-folder-buffer)
|
||||
(mm-inline-media-tests mh-mm-inline-media-tests)
|
||||
(data (get-text-property event-position 'mh-data))
|
||||
(function (get-text-property event-position 'mh-callback))
|
||||
(buffer-read-only nil))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(select-window event-window)
|
||||
(flet ((mm-handle-set-external-undisplayer (handle func)
|
||||
(mh-handle-set-external-undisplayer folder handle func)))
|
||||
(goto-char event-position)
|
||||
(and function (funcall function data))))
|
||||
(set-buffer-modified-p nil)
|
||||
(goto-char original-position)
|
||||
(set-marker original-position nil)
|
||||
(select-window original-window)))))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-mime-save-part ()
|
||||
|
@ -1242,6 +1318,7 @@ message multiple times."
|
|||
handles))))
|
||||
|
||||
(goto-char (point-min))
|
||||
(mh-show-xface)
|
||||
(cond (clean-message-header
|
||||
(mh-clean-msg-header (point-min)
|
||||
invisible-headers
|
||||
|
@ -1249,7 +1326,7 @@ message multiple times."
|
|||
(goto-char (point-min)))
|
||||
(t
|
||||
(mh-start-of-uncleaned-message)))
|
||||
(mh-show-xface)
|
||||
(mh-decode-message-header)
|
||||
(mh-show-addr)
|
||||
;; The other highlighting types don't need anything special
|
||||
(when (eq mh-highlight-citation-p 'gnus)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
;;; mh-pick.el --- make a search pattern and search for a message in MH-E
|
||||
|
||||
;; Copyright (C) 1993, 1995, 2001 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 1993, 1995, 2001, 2003 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Bill Wohler <wohler@newt.com>
|
||||
;; Maintainer: Bill Wohler <wohler@newt.com>
|
||||
|
@ -30,8 +30,6 @@
|
|||
|
||||
;;; Change Log:
|
||||
|
||||
;; $Id: mh-pick.el,v 1.30 2003/01/27 04:16:47 wohler Exp $
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'mh-e)
|
||||
|
@ -62,9 +60,9 @@ the search folder is dismissed."
|
|||
(mh-make-pick-template)
|
||||
(message ""))
|
||||
(setq mh-searching-function 'mh-pick-do-search
|
||||
mh-searching-folder pick-folder
|
||||
mh-current-folder folder
|
||||
mh-previous-window-config window-config)
|
||||
mh-searching-folder pick-folder)
|
||||
(mh-make-local-vars 'mh-current-folder folder
|
||||
'mh-previous-window-config window-config)
|
||||
(message "%s" (substitute-command-keys
|
||||
(concat "Type \\[mh-do-search] to search messages, "
|
||||
"\\[mh-help] for help.")))))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
;;; mh-seq.el --- MH-E sequences support
|
||||
|
||||
;; Copyright (C) 1993, 1995, 2001, 2002 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 1993, 1995, 2001, 02, 2003 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Bill Wohler <wohler@newt.com>
|
||||
;; Maintainer: Bill Wohler <wohler@newt.com>
|
||||
|
@ -68,8 +68,6 @@
|
|||
|
||||
;;; Change Log:
|
||||
|
||||
;; $Id: mh-seq.el,v 1.101 2003/01/26 00:57:35 jchonig Exp $
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl)
|
||||
|
@ -146,8 +144,10 @@ redone to get the new thread tree. This makes incremental threading easier.")
|
|||
(mh-undefine-sequence sequence '("all"))
|
||||
(mh-delete-seq-locally sequence)
|
||||
(mh-iterate-on-messages-in-region msg (point-min) (point-max)
|
||||
(when (and (member msg msg-list) (not (mh-seq-containing-msg msg nil)))
|
||||
(mh-notate nil ? (1+ mh-cmd-note))))))
|
||||
(cond ((and mh-tick-seq (eq sequence mh-tick-seq))
|
||||
(mh-notate-tick msg ()))
|
||||
((and (member msg msg-list) (not (mh-seq-containing-msg msg nil)))
|
||||
(mh-notate nil ? (1+ mh-cmd-note)))))))
|
||||
|
||||
;; Avoid compiler warnings
|
||||
(defvar view-exit-action)
|
||||
|
@ -195,10 +195,12 @@ redone to get the new thread tree. This makes incremental threading easier.")
|
|||
|
||||
;;;###mh-autoload
|
||||
(defun mh-msg-is-in-seq (message)
|
||||
"Display the sequences that contain MESSAGE (default: current message)."
|
||||
"Display the sequences that contain MESSAGE.
|
||||
Default is the displayed message."
|
||||
(interactive (list (mh-get-msg-num t)))
|
||||
(let* ((dest-folder (loop for seq in mh-refile-list
|
||||
when (member message (cdr seq)) return (car seq)))
|
||||
until (member message (cdr seq))
|
||||
finally return (car seq)))
|
||||
(deleted-flag (unless dest-folder (member message mh-delete-list))))
|
||||
(message "Message %d%s is in sequences: %s"
|
||||
message
|
||||
|
@ -209,6 +211,9 @@ redone to get the new thread tree. This makes incremental threading easier.")
|
|||
(mh-list-to-string (mh-seq-containing-msg message t))
|
||||
" "))))
|
||||
|
||||
;; Avoid compiler warning
|
||||
(defvar tool-bar-map)
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-narrow-to-seq (sequence)
|
||||
"Restrict display of this folder to just messages in SEQUENCE.
|
||||
|
@ -224,6 +229,7 @@ Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
|
|||
(setq mh-thread-scan-line-map (make-hash-table :test #'eql))
|
||||
(mh-copy-seq-to-eob sequence)
|
||||
(narrow-to-region eob (point-max))
|
||||
(setq mh-narrowed-to-seq sequence)
|
||||
(mh-notate-user-sequences)
|
||||
(mh-notate-deleted-and-refiled)
|
||||
(mh-notate-cur)
|
||||
|
@ -233,44 +239,42 @@ Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
|
|||
(setq mh-mode-line-annotation (symbol-name sequence))
|
||||
(mh-make-folder-mode-line)
|
||||
(mh-recenter nil)
|
||||
(if (and (boundp 'tool-bar-mode) tool-bar-mode)
|
||||
(set (make-local-variable 'tool-bar-map)
|
||||
mh-folder-seq-tool-bar-map))
|
||||
(setq mh-narrowed-to-seq sequence)
|
||||
(when (and (boundp 'tool-bar-mode) tool-bar-mode)
|
||||
(set (make-local-variable 'tool-bar-map)
|
||||
mh-folder-seq-tool-bar-map)
|
||||
(when (buffer-live-p (get-buffer mh-show-buffer))
|
||||
(save-excursion
|
||||
(set-buffer (get-buffer mh-show-buffer))
|
||||
(set (make-local-variable 'tool-bar-map)
|
||||
mh-show-seq-tool-bar-map))))
|
||||
(push 'widen mh-view-ops)))
|
||||
(t
|
||||
(error "No messages in sequence `%s'" (symbol-name sequence))))))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-put-msg-in-seq (msg-or-seq sequence)
|
||||
"Add MSG-OR-SEQ (default: displayed message) to SEQUENCE.
|
||||
If optional prefix argument provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then
|
||||
the selected region is added to the sequence."
|
||||
(interactive (list (cond
|
||||
((mh-mark-active-p t)
|
||||
(cons (region-beginning) (region-end)))
|
||||
(current-prefix-arg
|
||||
(mh-read-seq-default "Add messages from" t))
|
||||
(t
|
||||
(cons (line-beginning-position) (line-end-position))))
|
||||
"Add MSG-OR-SEQ to SEQUENCE.
|
||||
Default is the displayed message.
|
||||
If optional prefix argument is provided, then prompt for the message sequence.
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then the
|
||||
selected region is added to the sequence.
|
||||
In a program, MSG-OR-SEQ can be a message number, a list of message numbers, a
|
||||
region in a cons cell, or a sequence."
|
||||
(interactive (list (mh-interactive-msg-or-seq "Add messages from")
|
||||
(mh-read-seq-default "Add to" nil)))
|
||||
(let ((internal-seq-flag (mh-internal-seq sequence))
|
||||
msg-list)
|
||||
(cond ((and (consp msg-or-seq)
|
||||
(numberp (car msg-or-seq)) (numberp (cdr msg-or-seq)))
|
||||
(mh-iterate-on-messages-in-region m (car msg-or-seq) (cdr msg-or-seq)
|
||||
(push m msg-list)
|
||||
(unless internal-seq-flag
|
||||
(mh-notate nil mh-note-seq (1+ mh-cmd-note))))
|
||||
(mh-add-msgs-to-seq msg-list sequence internal-seq-flag t))
|
||||
((or (numberp msg-or-seq) (listp msg-or-seq))
|
||||
(when (numberp msg-or-seq)
|
||||
(setq msg-or-seq (list msg-or-seq)))
|
||||
(mh-add-msgs-to-seq msg-or-seq sequence internal-seq-flag))
|
||||
(t (mh-add-msgs-to-seq (mh-seq-to-msgs msg-or-seq) sequence)))
|
||||
(when (and (interactive-p) mh-tick-seq (eq sequence mh-tick-seq))
|
||||
(error "Use `mh-toggle-tick' to add messages to %s" mh-tick-seq))
|
||||
(let* ((internal-seq-flag (mh-internal-seq sequence))
|
||||
(note-seq (if internal-seq-flag nil mh-note-seq))
|
||||
(msg-list ()))
|
||||
(mh-iterate-on-msg-or-seq m msg-or-seq
|
||||
(push m msg-list)
|
||||
(mh-notate nil note-seq (1+ mh-cmd-note)))
|
||||
(mh-add-msgs-to-seq msg-list sequence nil t)
|
||||
(if (not internal-seq-flag)
|
||||
(setq mh-last-seq-used sequence))))
|
||||
(setq mh-last-seq-used sequence))
|
||||
(when (and (eq sequence mh-unseen-seq) (mh-speed-flists-active-p))
|
||||
(mh-speed-flists t mh-current-folder))))
|
||||
|
||||
(defun mh-valid-view-change-operation-p (op)
|
||||
"Check if the view change operation can be performed.
|
||||
|
@ -300,13 +304,18 @@ OP is one of 'widen and 'unthread."
|
|||
(mh-make-folder-mode-line))
|
||||
(if msg
|
||||
(mh-goto-msg msg t t))
|
||||
(setq mh-narrowed-to-seq nil)
|
||||
(setq mh-tick-seq-changed-when-narrowed-flag nil)
|
||||
(mh-notate-deleted-and-refiled)
|
||||
(mh-notate-user-sequences)
|
||||
(mh-notate-cur)
|
||||
(mh-recenter nil)))
|
||||
(if (and (boundp 'tool-bar-mode) tool-bar-mode)
|
||||
(set (make-local-variable 'tool-bar-map) mh-folder-tool-bar-map))
|
||||
(setq mh-narrowed-to-seq nil))
|
||||
(when (and (boundp 'tool-bar-mode) tool-bar-mode)
|
||||
(set (make-local-variable 'tool-bar-map) mh-folder-tool-bar-map)
|
||||
(when (buffer-live-p (get-buffer mh-show-buffer))
|
||||
(save-excursion
|
||||
(set-buffer (get-buffer mh-show-buffer))
|
||||
(set (make-local-variable 'tool-bar-map) mh-show-tool-bar-map)))))
|
||||
|
||||
;; FIXME? We may want to clear all notations and add one for current-message
|
||||
;; and process user sequences.
|
||||
|
@ -408,8 +417,9 @@ 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))
|
||||
(mh-notate nil mh-note-cur mh-cmd-note)
|
||||
(beginning-of-line)
|
||||
(when (looking-at mh-scan-good-msg-regexp)
|
||||
(mh-notate nil mh-note-cur mh-cmd-note))
|
||||
(setq mh-arrow-marker (set-marker mh-arrow-marker (point)))
|
||||
(setq overlay-arrow-position mh-arrow-marker))))
|
||||
|
||||
|
@ -431,6 +441,8 @@ uses `overlay-arrow-position' to put a marker in the fringe."
|
|||
; ;; LOCATION in the current buffer.
|
||||
; (mh-map-to-seq-msgs 'mh-copy-line-to-point seq location))
|
||||
|
||||
(defvar mh-thread-last-ancestor)
|
||||
|
||||
(defun mh-copy-seq-to-eob (seq)
|
||||
"Copy SEQ to the end of the buffer."
|
||||
;; It is quite involved to write something which will work at any place in
|
||||
|
@ -455,12 +467,8 @@ uses `overlay-arrow-position' to put a marker in the fringe."
|
|||
(forward-line))
|
||||
;; Remove scan lines and read results from pre-computed tree
|
||||
(delete-region (point-min) (point-max))
|
||||
(let ((thread-tree (mh-thread-generate mh-current-folder ()))
|
||||
(mh-thread-body-width
|
||||
(- (window-width) mh-cmd-note
|
||||
(1- mh-scan-field-subject-start-offset)))
|
||||
(mh-thread-last-ancestor nil))
|
||||
(mh-thread-generate-scan-lines thread-tree -2)))
|
||||
(mh-thread-print-scan-lines
|
||||
(mh-thread-generate mh-current-folder ())))
|
||||
(mh-index-data
|
||||
(mh-index-insert-folder-headers)))))))
|
||||
|
||||
|
@ -491,12 +499,83 @@ If VAR is nil then the loop is executed without any binding."
|
|||
(let ((binding-needed-flag var))
|
||||
`(save-excursion
|
||||
(goto-char ,begin)
|
||||
(beginning-of-line)
|
||||
(while (and (<= (point) ,end) (not (eobp)))
|
||||
(when (looking-at mh-scan-valid-regexp)
|
||||
(let ,(if binding-needed-flag `((,var (mh-get-msg-num t))) ())
|
||||
,@body))
|
||||
(forward-line 1)))))
|
||||
|
||||
(put 'mh-iterate-on-messages-in-region 'lisp-indent-hook 'defun)
|
||||
|
||||
;;;###mh-autoload
|
||||
(defmacro mh-iterate-on-msg-or-seq (var msg-or-seq &rest body)
|
||||
"Iterate an operation over a region or sequence.
|
||||
|
||||
VAR is bound to each message in turn in a loop over MSG-OR-SEQ, which can be a
|
||||
message number, a list of message numbers, a sequence, or a region in a cons
|
||||
cell. In each iteration, BODY is executed.
|
||||
|
||||
The parameter MSG-OR-SEQ is usually created with `mh-interactive-msg-or-seq'
|
||||
in order to provide a uniform interface to MH-E functions."
|
||||
(unless (symbolp var)
|
||||
(error "Can not bind the non-symbol %s" var))
|
||||
(let ((binding-needed-flag var)
|
||||
(msgs (make-symbol "msgs"))
|
||||
(seq-hash-table (make-symbol "seq-hash-table")))
|
||||
`(cond ((numberp ,msg-or-seq)
|
||||
(when (mh-goto-msg ,msg-or-seq t t)
|
||||
(let ,(if binding-needed-flag `((,var ,msg-or-seq)) ())
|
||||
,@body)))
|
||||
((and (consp ,msg-or-seq)
|
||||
(numberp (car ,msg-or-seq)) (numberp (cdr ,msg-or-seq)))
|
||||
(mh-iterate-on-messages-in-region ,var
|
||||
(car ,msg-or-seq) (cdr ,msg-or-seq)
|
||||
,@body))
|
||||
(t (let ((,msgs (if (and ,msg-or-seq (symbolp ,msg-or-seq))
|
||||
(mh-seq-to-msgs ,msg-or-seq)
|
||||
,msg-or-seq))
|
||||
(,seq-hash-table (make-hash-table)))
|
||||
(dolist (msg ,msgs)
|
||||
(setf (gethash msg ,seq-hash-table) t))
|
||||
(mh-iterate-on-messages-in-region v (point-min) (point-max)
|
||||
(when (gethash v ,seq-hash-table)
|
||||
(let ,(if binding-needed-flag `((,var v)) ())
|
||||
,@body))))))))
|
||||
|
||||
(put 'mh-iterate-on-msg-or-seq 'lisp-indent-hook 'defun)
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-msg-or-seq-to-msg-list (msg-or-seq)
|
||||
"Return a list of messages for MSG-OR-SEQ.
|
||||
MSG-OR-SEQ can be a message number, a list of message numbers, a sequence, or
|
||||
a region in a cons cell."
|
||||
(let (msg-list)
|
||||
(mh-iterate-on-msg-or-seq msg msg-or-seq
|
||||
(push msg msg-list))
|
||||
(nreverse msg-list)))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-interactive-msg-or-seq (sequence-prompt)
|
||||
"Return interactive specification for message, sequence, or region.
|
||||
By convention, the name of this argument is msg-or-seq.
|
||||
|
||||
If variable `transient-mark-mode' is non-nil and the mark is active, then this
|
||||
function returns a cons-cell of the region.
|
||||
If optional prefix argument provided, then prompt for message sequence with
|
||||
SEQUENCE-PROMPT and return sequence.
|
||||
Otherwise, the message number at point is returned.
|
||||
|
||||
This function is usually used with `mh-iterate-on-msg-or-seq' in order to
|
||||
provide a uniform interface to MH-E functions."
|
||||
(cond
|
||||
((mh-mark-active-p t)
|
||||
(cons (region-beginning) (region-end)))
|
||||
(current-prefix-arg
|
||||
(mh-read-seq-default sequence-prompt t))
|
||||
(t
|
||||
(mh-get-msg-num t))))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-region-to-msg-list (begin end)
|
||||
"Return a list of messages within the region between BEGIN and END."
|
||||
|
@ -1005,17 +1084,12 @@ All messages after START-POINT are added to the thread tree."
|
|||
(buffer-read-only nil)
|
||||
(old-buffer-modified-flag (buffer-modified-p)))
|
||||
(delete-region (point-min) (point-max))
|
||||
(let ((mh-thread-body-width (- (window-width) mh-cmd-note
|
||||
(1- mh-scan-field-subject-start-offset)))
|
||||
(mh-thread-last-ancestor nil))
|
||||
(mh-thread-generate-scan-lines thread-tree -2))
|
||||
(mh-thread-print-scan-lines thread-tree)
|
||||
(mh-notate-user-sequences)
|
||||
(mh-notate-deleted-and-refiled)
|
||||
(mh-notate-cur)
|
||||
(set-buffer-modified-p old-buffer-modified-flag))))
|
||||
|
||||
(defvar mh-thread-last-ancestor)
|
||||
|
||||
(defun mh-thread-generate-scan-lines (tree level)
|
||||
"Generate scan lines.
|
||||
TREE is the hierarchical tree of messages, SCAN-LINE-MAP maps message indices
|
||||
|
@ -1099,6 +1173,25 @@ Otherwise uses the line at point as the scan line to parse."
|
|||
(mh-thread-parse-scan-line (format "%s%s" spaces old-line)))))
|
||||
(forward-line 1))))
|
||||
|
||||
(defun mh-thread-print-scan-lines (thread-tree)
|
||||
"Print scan lines in THREAD-TREE in threaded mode."
|
||||
(let ((mh-thread-body-width (- (window-width) mh-cmd-note
|
||||
(1- mh-scan-field-subject-start-offset)))
|
||||
(mh-thread-last-ancestor nil))
|
||||
(if (null mh-index-data)
|
||||
(mh-thread-generate-scan-lines thread-tree -2)
|
||||
(loop for x in (mh-index-group-by-folder)
|
||||
do (let* ((old-map mh-thread-scan-line-map)
|
||||
(mh-thread-scan-line-map (make-hash-table)))
|
||||
(setq mh-thread-last-ancestor nil)
|
||||
(loop for msg in (cdr x)
|
||||
do (let ((v (gethash msg old-map)))
|
||||
(when v
|
||||
(setf (gethash msg mh-thread-scan-line-map) v))))
|
||||
(when (> (hash-table-count mh-thread-scan-line-map) 0)
|
||||
(insert (if (bobp) "" "\n") (car x) "\n")
|
||||
(mh-thread-generate-scan-lines thread-tree -2)))))))
|
||||
|
||||
(defun mh-thread-folder ()
|
||||
"Generate thread view of folder."
|
||||
(message "Threading %s..." (buffer-name))
|
||||
|
@ -1115,10 +1208,7 @@ Otherwise uses the line at point as the scan line to parse."
|
|||
(let* ((range (mh-coalesce-msg-list msg-list))
|
||||
(thread-tree (mh-thread-generate (buffer-name) range)))
|
||||
(delete-region (point-min) (point-max))
|
||||
(let ((mh-thread-body-width (- (window-width) mh-cmd-note
|
||||
(1- mh-scan-field-subject-start-offset)))
|
||||
(mh-thread-last-ancestor nil))
|
||||
(mh-thread-generate-scan-lines thread-tree -2))
|
||||
(mh-thread-print-scan-lines thread-tree)
|
||||
(mh-notate-user-sequences)
|
||||
(mh-notate-deleted-and-refiled)
|
||||
(mh-notate-cur)
|
||||
|
@ -1137,7 +1227,7 @@ Otherwise uses the line at point as the scan line to parse."
|
|||
(let ((msg-list ()))
|
||||
(goto-char (point-min))
|
||||
(while (not (eobp))
|
||||
(let ((index (mh-get-msg-num t)))
|
||||
(let ((index (mh-get-msg-num nil)))
|
||||
(when index
|
||||
(push index msg-list)))
|
||||
(forward-line))
|
||||
|
@ -1161,6 +1251,7 @@ Otherwise uses the line at point as the scan line to parse."
|
|||
(id-index (gethash id mh-thread-id-index-map))
|
||||
(duplicates (gethash id mh-thread-duplicates)))
|
||||
(remhash index mh-thread-index-id-map)
|
||||
(remhash index mh-thread-scan-line-map)
|
||||
(cond ((and (eql index id-index) (null duplicates))
|
||||
(remhash id mh-thread-id-index-map))
|
||||
((eql index id-index)
|
||||
|
@ -1308,6 +1399,85 @@ start of the region and the second is the point at the end."
|
|||
(mh-refile-a-msg nil folder))
|
||||
(mh-next-msg)))))
|
||||
|
||||
|
||||
|
||||
;; Tick mark handling
|
||||
|
||||
;; Functions to highlight and unhighlight ticked messages.
|
||||
(defun mh-tick-add-overlay ()
|
||||
"Add tick overlay to current line."
|
||||
(with-mh-folder-updating (t)
|
||||
(let ((overlay
|
||||
(or (mh-funcall-if-exists make-overlay (point) (line-end-position))
|
||||
(mh-funcall-if-exists make-extent (point) (line-end-position)))))
|
||||
(or (mh-funcall-if-exists overlay-put overlay 'face 'mh-folder-tick-face)
|
||||
(mh-funcall-if-exists set-extent-face overlay 'mh-folder-tick-face))
|
||||
(mh-funcall-if-exists set-extent-priority overlay 10)
|
||||
(add-text-properties (point) (line-end-position) `(mh-tick ,overlay)))))
|
||||
|
||||
(defun mh-tick-remove-overlay ()
|
||||
"Remove tick overlay from current line."
|
||||
(let ((overlay (get-text-property (point) 'mh-tick)))
|
||||
(when overlay
|
||||
(with-mh-folder-updating (t)
|
||||
(or (mh-funcall-if-exists delete-overlay overlay)
|
||||
(mh-funcall-if-exists delete-extent overlay))
|
||||
(remove-text-properties (point) (line-end-position) `(mh-tick nil))))))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-notate-tick (msg ticked-msgs &optional ignore-narrowing)
|
||||
"Highlight current line if MSG is in TICKED-MSGS.
|
||||
If optional argument IGNORE-NARROWING is non-nil then highlighting is carried
|
||||
out even if folder is narrowed to `mh-tick-seq'."
|
||||
(when mh-tick-seq
|
||||
(let ((narrowed-to-tick (and (not ignore-narrowing)
|
||||
(eq mh-narrowed-to-seq mh-tick-seq)))
|
||||
(overlay (get-text-property (point) 'mh-tick))
|
||||
(in-tick (member msg ticked-msgs)))
|
||||
(cond (narrowed-to-tick (mh-tick-remove-overlay))
|
||||
((and (not overlay) in-tick) (mh-tick-add-overlay))
|
||||
((and overlay (not in-tick)) (mh-tick-remove-overlay))))))
|
||||
|
||||
;; Interactive function to toggle tick.
|
||||
;;;###mh-autoload
|
||||
(defun mh-toggle-tick (begin end)
|
||||
"Toggle tick mark of all messages in region BEGIN to END."
|
||||
(interactive (cond ((mh-mark-active-p t)
|
||||
(list (region-beginning) (region-end)))
|
||||
(t (list (line-beginning-position) (line-end-position)))))
|
||||
(unless mh-tick-seq
|
||||
(error "Enable ticking by customizing `mh-tick-seq'"))
|
||||
(let* ((tick-seq (mh-find-seq mh-tick-seq))
|
||||
(tick-seq-msgs (mh-seq-msgs tick-seq)))
|
||||
(mh-iterate-on-messages-in-region msg begin end
|
||||
(cond ((member msg tick-seq-msgs)
|
||||
(mh-undefine-sequence mh-tick-seq (list msg))
|
||||
(setcdr tick-seq (delq msg (cdr tick-seq)))
|
||||
(when (null (cdr tick-seq)) (setq mh-last-seq-used nil))
|
||||
(mh-tick-remove-overlay))
|
||||
(t
|
||||
(mh-add-msgs-to-seq (list msg) mh-tick-seq nil t)
|
||||
(setq mh-last-seq-used mh-tick-seq)
|
||||
(mh-tick-add-overlay))))
|
||||
(when (and (eq mh-tick-seq mh-narrowed-to-seq)
|
||||
(not mh-tick-seq-changed-when-narrowed-flag))
|
||||
(setq mh-tick-seq-changed-when-narrowed-flag t)
|
||||
(let ((ticked-msgs (mh-seq-msgs (mh-find-seq mh-tick-seq))))
|
||||
(mh-iterate-on-messages-in-region msg (point-min) (point-max)
|
||||
(mh-notate-tick msg ticked-msgs t))))))
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-narrow-to-tick ()
|
||||
"Restrict display of this folder to just messages in `mh-tick-seq'.
|
||||
Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
|
||||
(interactive)
|
||||
(cond ((not mh-tick-seq)
|
||||
(error "Enable ticking by customizing `mh-tick-seq'"))
|
||||
((null (mh-seq-msgs (mh-find-seq mh-tick-seq)))
|
||||
(message "No messages in tick sequence"))
|
||||
(t (mh-narrow-to-seq mh-tick-seq))))
|
||||
|
||||
|
||||
(provide 'mh-seq)
|
||||
|
||||
;;; Local Variables:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
;;; mh-speed.el --- Speedbar interface for MH-E.
|
||||
|
||||
;; Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
|
||||
;; Maintainer: Bill Wohler <wohler@newt.com>
|
||||
|
@ -31,8 +31,6 @@
|
|||
|
||||
;;; Change Log:
|
||||
|
||||
;; $Id: mh-speed.el,v 1.37 2003/01/31 03:18:18 satyaki Exp $
|
||||
|
||||
;;; Code:
|
||||
|
||||
;; Requires
|
||||
|
@ -70,7 +68,8 @@ BUFFER is the MH-E buffer for which the speedbar buffer is to be created."
|
|||
'mh-speedbar-folder-face 0)
|
||||
(forward-line -1)
|
||||
(setf (gethash nil mh-speed-folder-map)
|
||||
(set-marker (make-marker) (1+ (line-beginning-position))))
|
||||
(set-marker (or (gethash nil mh-speed-folder-map) (make-marker))
|
||||
(1+ (line-beginning-position))))
|
||||
(add-text-properties
|
||||
(line-beginning-position) (1+ (line-beginning-position))
|
||||
`(mh-folder nil mh-expanded nil mh-children-p t mh-level 0))
|
||||
|
@ -278,7 +277,9 @@ Do the right thing for the different kinds of buffers that MH-E uses."
|
|||
(save-excursion
|
||||
(forward-line -1)
|
||||
(setf (gethash folder-name mh-speed-folder-map)
|
||||
(set-marker (make-marker) (1+ (line-beginning-position))))
|
||||
(set-marker (or (gethash folder-name mh-speed-folder-map)
|
||||
(make-marker))
|
||||
(1+ (line-beginning-position))))
|
||||
(add-text-properties
|
||||
(line-beginning-position) (1+ (line-beginning-position))
|
||||
`(mh-folder ,folder-name
|
||||
|
@ -309,8 +310,10 @@ The otional ARGS are ignored and there for compatibilty with speedbar."
|
|||
(setq start-region (point))
|
||||
(while (and (get-text-property (point) 'mh-level)
|
||||
(> (get-text-property (point) 'mh-level) level))
|
||||
(remhash (get-text-property (point) 'mh-folder)
|
||||
mh-speed-folder-map)
|
||||
(let ((folder (get-text-property (point) 'mh-folder)))
|
||||
(when (gethash folder mh-speed-folder-map)
|
||||
(set-marker (gethash folder mh-speed-folder-map) nil)
|
||||
(remhash folder mh-speed-folder-map)))
|
||||
(forward-line))
|
||||
(delete-region start-region (point))
|
||||
(forward-line -1)
|
||||
|
@ -344,24 +347,29 @@ Optional ARGS are ignored."
|
|||
(delete-other-windows)))))
|
||||
|
||||
(defvar mh-speed-current-folder nil)
|
||||
(defvar mh-speed-flists-folder nil)
|
||||
|
||||
;;;###mh-autoload
|
||||
(defun mh-speed-flists (force)
|
||||
(defun mh-speed-flists (force &optional folder)
|
||||
"Execute flists -recurse and update message counts.
|
||||
If FORCE is non-nil the timer is reset."
|
||||
If FORCE is non-nil the timer is reset. If FOLDER is non-nil then flists is run
|
||||
only for that one folder."
|
||||
(interactive (list t))
|
||||
(when force
|
||||
(when (timerp mh-speed-flists-timer)
|
||||
(cancel-timer mh-speed-flists-timer))
|
||||
(setq mh-speed-flists-timer nil)
|
||||
(when mh-speed-flists-timer
|
||||
(cancel-timer mh-speed-flists-timer)
|
||||
(setq mh-speed-flists-timer nil))
|
||||
(when (and (processp mh-speed-flists-process)
|
||||
(not (eq (process-status mh-speed-flists-process) 'exit)))
|
||||
(set-process-filter mh-speed-flists-process t)
|
||||
(kill-process mh-speed-flists-process)
|
||||
(setq mh-speed-partial-line "")
|
||||
(setq mh-speed-flists-process nil)))
|
||||
(setq mh-speed-flists-folder folder)
|
||||
(unless mh-speed-flists-timer
|
||||
(setq mh-speed-flists-timer
|
||||
(run-at-time
|
||||
nil mh-speed-flists-interval
|
||||
nil (and mh-speed-run-flists-flag mh-speed-flists-interval)
|
||||
(lambda ()
|
||||
(unless (and (processp mh-speed-flists-process)
|
||||
(not (eq (process-status mh-speed-flists-process)
|
||||
|
@ -376,8 +384,11 @@ If FORCE is non-nil the timer is reset."
|
|||
(setq mh-speed-flists-process
|
||||
(start-process "*flists*" nil
|
||||
(expand-file-name "flists" mh-progs)
|
||||
"-recurse"
|
||||
(or mh-speed-flists-folder "-recurse")
|
||||
(if mh-speed-flists-folder "-noall" "-all")
|
||||
"-sequence" (symbol-name mh-unseen-seq)))
|
||||
;; Run flists on all folders the next time around...
|
||||
(setq mh-speed-flists-folder nil)
|
||||
(set-process-filter mh-speed-flists-process
|
||||
'mh-speed-parse-flists-output)))))))
|
||||
|
||||
|
@ -397,7 +408,10 @@ next."
|
|||
mh-speed-partial-line "")
|
||||
(multiple-value-setq (folder unseen total)
|
||||
(mh-parse-flist-output-line line mh-speed-current-folder))
|
||||
(when (and folder unseen total)
|
||||
(when (and folder unseen total
|
||||
(let ((old-pair (gethash folder mh-speed-flists-cache)))
|
||||
(or (not (equal (car old-pair) unseen))
|
||||
(not (equal (cdr old-pair) total)))))
|
||||
(setf (gethash folder mh-speed-flists-cache) (cons unseen total))
|
||||
(save-excursion
|
||||
(when (buffer-live-p (get-buffer speedbar-buffer))
|
||||
|
@ -514,7 +528,8 @@ The function invalidates the latest ancestor that is present."
|
|||
(insert-char char 1 t)
|
||||
(put-text-property (point) (1- (point)) 'invisible nil)
|
||||
;; make sure we fix the image on the text here.
|
||||
(speedbar-insert-image-button-maybe (- (point) 2) 3)))))
|
||||
(mh-funcall-if-exists
|
||||
speedbar-insert-image-button-maybe (- (point) 2) 3)))))
|
||||
|
||||
(provide 'mh-speed)
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
;;; mh-utils.el --- MH-E code needed for both sending and reading
|
||||
|
||||
;; Copyright (C) 1993, 1995, 1997, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 1993, 95, 1997,
|
||||
;; 2000, 01, 02, 2003 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Bill Wohler <wohler@newt.com>
|
||||
;; Maintainer: Bill Wohler <wohler@newt.com>
|
||||
|
@ -30,8 +31,6 @@
|
|||
|
||||
;;; Change Log:
|
||||
|
||||
;; $Id: mh-utils.el,v 1.2 2003/02/03 20:55:30 wohler Exp $
|
||||
|
||||
;;; Code:
|
||||
|
||||
;; Is this XEmacs-land? Located here since needed by mh-customize.el.
|
||||
|
@ -57,7 +56,7 @@
|
|||
|
||||
;;; Autoloads
|
||||
(autoload 'gnus-article-highlight-citation "gnus-cite")
|
||||
(autoload 'mail-header-end "sendmail")
|
||||
(require 'sendmail)
|
||||
(autoload 'Info-goto-node "info")
|
||||
(unless (fboundp 'make-hash-table)
|
||||
(autoload 'make-hash-table "cl"))
|
||||
|
@ -100,7 +99,30 @@ of `search' in the CL package."
|
|||
when (equal (aref string index) char) return index
|
||||
finally return nil))
|
||||
|
||||
;;; Macro to generate correct code for different emacs variants
|
||||
;;; Macros to generate correct code for different emacs variants
|
||||
|
||||
(defmacro mh-do-in-gnu-emacs (&rest body)
|
||||
"Execute BODY if in GNU Emacs."
|
||||
(unless mh-xemacs-flag `(progn ,@body)))
|
||||
(put 'mh-do-in-gnu-emacs 'lisp-indent-hook 'defun)
|
||||
|
||||
(defmacro mh-do-in-xemacs (&rest body)
|
||||
"Execute BODY if in GNU Emacs."
|
||||
(when mh-xemacs-flag `(progn ,@body)))
|
||||
(put 'mh-do-in-xemacs 'lisp-indent-hook 'defun)
|
||||
|
||||
(defmacro mh-funcall-if-exists (function &rest args)
|
||||
"Call FUNCTION with ARGS as parameters if it exists."
|
||||
(if (fboundp function)
|
||||
`(funcall ',function ,@args)))
|
||||
|
||||
(defmacro mh-make-local-hook (hook)
|
||||
"Make HOOK local if needed.
|
||||
XEmacs and versions of GNU Emacs before 21.1 require `make-local-hook' to be
|
||||
called."
|
||||
(when (and (fboundp 'make-local-hook)
|
||||
(not (get 'make-local-hook 'byte-obsolete-info)))
|
||||
`(make-local-hook ,hook)))
|
||||
|
||||
(defmacro mh-mark-active-p (check-transient-mark-mode-flag)
|
||||
"A macro that expands into appropriate code in XEmacs and nil in GNU Emacs.
|
||||
|
@ -287,19 +309,6 @@ passed through `regexp-quote' before being used by functions like
|
|||
(".*" mm-inline-text mm-readable-p))
|
||||
"Alist of media types/tests saying whether types can be displayed inline.")
|
||||
|
||||
;; Needed by mh-comp.el and mh-mime.el
|
||||
(defvar mh-mhn-compose-insert-flag nil
|
||||
"Non-nil means MIME insertion was done.
|
||||
Triggers an automatic call to `mh-edit-mhn' in `mh-send-letter'.
|
||||
This variable is buffer-local.")
|
||||
(make-variable-buffer-local 'mh-mhn-compose-insert-flag)
|
||||
|
||||
(defvar mh-mml-compose-insert-flag nil
|
||||
"Non-nil means that a MIME insertion was done.
|
||||
This buffer-local variable is used to remember if a MIME insertion was done.
|
||||
Triggers an automatic call to `mh-mml-to-mime' in `mh-send-letter'.")
|
||||
(make-variable-buffer-local 'mh-mml-compose-insert-flag)
|
||||
|
||||
;; Copy of `goto-address-mail-regexp'
|
||||
(defvar mh-address-mail-regexp
|
||||
"[-a-zA-Z0-9._]+@[-a-zA-z0-9_]+\\.+[a-zA-Z0-9]+"
|
||||
|
@ -318,9 +327,17 @@ address. If no e-mail address found, return nil."
|
|||
(goto-char (match-beginning 0))))
|
||||
(match-string-no-properties 0)))
|
||||
|
||||
(defun mh-mail-header-end ()
|
||||
"Substitute for `mail-header-end' that doesn't widen the buffer.
|
||||
In MH-E we frequently need to find the end of headers in nested messages, where
|
||||
the buffer has been narrowed. This function works in this situation."
|
||||
(save-excursion
|
||||
(rfc822-goto-eoh)
|
||||
(point)))
|
||||
|
||||
(defun mh-in-header-p ()
|
||||
"Return non-nil if the point is in the header of a draft message."
|
||||
(< (point) (mail-header-end)))
|
||||
(< (point) (mh-mail-header-end)))
|
||||
|
||||
(defun mh-header-field-beginning ()
|
||||
"Move to the beginning of the current header field.
|
||||
|
@ -342,7 +359,7 @@ Handles RFC 822 continuation lines."
|
|||
Argument LIMIT limits search."
|
||||
(if (= (point) limit)
|
||||
nil
|
||||
(let* ((mail-header-end (save-match-data (mail-header-end)))
|
||||
(let* ((mail-header-end (save-match-data (mh-mail-header-end)))
|
||||
(lesser-limit (if (< mail-header-end limit) mail-header-end limit)))
|
||||
(when (mh-in-header-p)
|
||||
(set-match-data (list 1 lesser-limit))
|
||||
|
@ -354,7 +371,7 @@ Argument LIMIT limits search."
|
|||
Argument LIMIT limits search."
|
||||
(if (= (point) limit)
|
||||
nil
|
||||
(let* ((mail-header-end (mail-header-end))
|
||||
(let* ((mail-header-end (mh-mail-header-end))
|
||||
(lesser-limit (if (< mail-header-end limit) mail-header-end limit))
|
||||
(case-fold-search t))
|
||||
(when (and (< (point) mail-header-end) ;Only within header
|
||||
|
@ -424,7 +441,7 @@ Used when `mh-highlight-citation-p' 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 (mail-header-end)))
|
||||
(let ((header-end (mh-mail-header-end)))
|
||||
(cond
|
||||
((and (< beg header-end)(< end header-end))
|
||||
(font-lock-default-fontify-region beg end loudly))
|
||||
|
@ -501,6 +518,10 @@ message about the fontification operation."
|
|||
(defconst mh-log-buffer "*MH-E Log*") ;output of MH commands and so on
|
||||
(defconst mh-recipients-buffer "*MH-E Recipients*") ;killed when draft sent
|
||||
(defconst mh-sequences-buffer "*MH-E Sequences*") ;sequences list
|
||||
(defconst mh-mail-delivery-buffer "*MH-E Mail Delivery*") ;mail delivery log
|
||||
|
||||
;; Number of lines to keep in mh-log-buffer.
|
||||
(defvar mh-log-buffer-lines 100)
|
||||
|
||||
;; Window configuration before MH-E command.
|
||||
(defvar mh-previous-window-config nil)
|
||||
|
@ -535,14 +556,23 @@ message about the fontification operation."
|
|||
|
||||
(defun mh-logo-display ()
|
||||
"Modify mode line to display MH-E logo."
|
||||
(when (fboundp 'find-image)
|
||||
(add-text-properties
|
||||
0 2
|
||||
`(display ,(or mh-logo-cache
|
||||
(setq mh-logo-cache
|
||||
(find-image '((:type xpm :ascent center
|
||||
:file "mh-logo.xpm"))))))
|
||||
(car mode-line-buffer-identification))))
|
||||
(mh-do-in-gnu-emacs
|
||||
(add-text-properties
|
||||
0 2
|
||||
`(display ,(or mh-logo-cache
|
||||
(setq mh-logo-cache
|
||||
(mh-funcall-if-exists
|
||||
find-image '((:type xpm :ascent center
|
||||
:file "mh-logo.xpm"))))))
|
||||
(car mode-line-buffer-identification)))
|
||||
(mh-do-in-xemacs
|
||||
(setq modeline-buffer-identification
|
||||
(list
|
||||
(if mh-modeline-glyph
|
||||
(cons modeline-buffer-id-left-extent mh-modeline-glyph)
|
||||
(cons modeline-buffer-id-left-extent "XEmacs%N:"))
|
||||
(cons modeline-buffer-id-right-extent " %17b")))))
|
||||
|
||||
|
||||
;;; This holds a documentation string used by describe-mode.
|
||||
(defun mh-showing-mode (&optional arg)
|
||||
|
@ -585,7 +615,7 @@ flag is unchanged, otherwise it is cleared."
|
|||
,@(if (not save-modification-flag)
|
||||
'((mh-set-folder-modified-p nil)))))
|
||||
|
||||
(put 'with-mh-folder-updating 'lisp-indent-hook 1)
|
||||
(put 'with-mh-folder-updating 'lisp-indent-hook 'defun)
|
||||
|
||||
(defmacro mh-in-show-buffer (show-buffer &rest body)
|
||||
"Format is (mh-in-show-buffer (SHOW-BUFFER) &body BODY).
|
||||
|
@ -600,7 +630,7 @@ Stronger than `save-excursion', weaker than `save-window-excursion'."
|
|||
,@body)
|
||||
(select-window mh-in-show-buffer-saved-window))))
|
||||
|
||||
(put 'mh-in-show-buffer 'lisp-indent-hook 1)
|
||||
(put 'mh-in-show-buffer 'lisp-indent-hook 'defun)
|
||||
|
||||
(defmacro mh-make-seq (name msgs)
|
||||
"Create sequence NAME with the given MSGS."
|
||||
|
@ -726,11 +756,11 @@ still visible.\n")
|
|||
folder-buffer)
|
||||
(delete-other-windows))
|
||||
(mh-goto-cur-msg t)
|
||||
(and (fboundp 'deactivate-mark) (deactivate-mark))
|
||||
(mh-funcall-if-exists deactivate-mark)
|
||||
(unwind-protect
|
||||
(prog1 (call-interactively (function ,original-function))
|
||||
(setq normal-exit t))
|
||||
(and (fboundp 'deactivate-mark) (deactivate-mark))
|
||||
(mh-funcall-if-exists deactivate-mark)
|
||||
(cond ((not normal-exit)
|
||||
(set-window-configuration config))
|
||||
,(if dont-return
|
||||
|
@ -819,11 +849,17 @@ still visible.\n")
|
|||
(mh-defun-show-buffer mh-show-thread-previous-sibling
|
||||
mh-thread-previous-sibling)
|
||||
(mh-defun-show-buffer mh-show-index-visit-folder mh-index-visit-folder t)
|
||||
(mh-defun-show-buffer mh-show-toggle-tick mh-toggle-tick)
|
||||
(mh-defun-show-buffer mh-show-narrow-to-tick mh-narrow-to-tick)
|
||||
(mh-defun-show-buffer mh-show-junk-blacklist mh-junk-blacklist)
|
||||
(mh-defun-show-buffer mh-show-junk-whitelist mh-junk-whitelist)
|
||||
(mh-defun-show-buffer mh-show-index-new-messages mh-index-new-messages)
|
||||
|
||||
;;; Populate mh-show-mode-map
|
||||
(gnus-define-keys mh-show-mode-map
|
||||
" " mh-show-page-msg
|
||||
"!" mh-show-refile-or-write-again
|
||||
"'" mh-show-toggle-tick
|
||||
"," mh-show-header-display
|
||||
"." mh-show-show
|
||||
">" mh-show-write-message-to-file
|
||||
|
@ -867,6 +903,7 @@ still visible.\n")
|
|||
"i" mh-index-search
|
||||
"k" mh-show-kill-folder
|
||||
"l" mh-show-list-folders
|
||||
"n" mh-index-new-messages
|
||||
"o" mh-show-visit-folder
|
||||
"r" mh-show-rescan-folder
|
||||
"s" mh-show-search-folder
|
||||
|
@ -884,6 +921,13 @@ still visible.\n")
|
|||
"s" mh-show-msg-is-in-seq
|
||||
"w" mh-show-widen)
|
||||
|
||||
(define-key mh-show-mode-map "I" mh-inc-spool-map)
|
||||
|
||||
(gnus-define-keys (mh-show-junk-map "J" mh-show-mode-map)
|
||||
"?" mh-prefix-help
|
||||
"b" mh-show-junk-blacklist
|
||||
"w" mh-show-junk-whitelist)
|
||||
|
||||
(gnus-define-keys (mh-show-thread-map "T" mh-show-mode-map)
|
||||
"?" mh-prefix-help
|
||||
"u" mh-show-thread-ancestor
|
||||
|
@ -894,6 +938,7 @@ still visible.\n")
|
|||
"o" mh-show-thread-refile)
|
||||
|
||||
(gnus-define-keys (mh-show-limit-map "/" mh-show-mode-map)
|
||||
"'" mh-show-narrow-to-tick
|
||||
"?" mh-prefix-help
|
||||
"s" mh-show-narrow-to-subject
|
||||
"w" mh-show-widen)
|
||||
|
@ -932,7 +977,12 @@ still visible.\n")
|
|||
["Widen from Sequence" mh-show-widen t]
|
||||
"--"
|
||||
["Narrow to Subject Sequence" mh-show-narrow-to-subject t]
|
||||
["Narrow to Tick Sequence" mh-show-narrow-to-tick
|
||||
(save-excursion
|
||||
(set-buffer mh-show-folder-buffer)
|
||||
(and mh-tick-seq (mh-seq-msgs (mh-find-seq mh-tick-seq))))]
|
||||
["Delete Rest of Same Subject" mh-show-delete-subject t]
|
||||
["Toggle Tick Mark" mh-show-toggle-tick t]
|
||||
"--"
|
||||
["Push State Out to MH" mh-show-update-sequences t]))
|
||||
|
||||
|
@ -979,6 +1029,7 @@ still visible.\n")
|
|||
"--"
|
||||
["List Folders" mh-show-list-folders t]
|
||||
["Visit a Folder..." mh-show-visit-folder t]
|
||||
["View New Messages" mh-show-index-new-messages t]
|
||||
["Search a Folder..." mh-show-search-folder t]
|
||||
["Indexed Search..." mh-index-search t]
|
||||
"--"
|
||||
|
@ -988,6 +1039,9 @@ still visible.\n")
|
|||
;;; Ensure new buffers won't get this mode if default-major-mode is nil.
|
||||
(put 'mh-show-mode 'mode-class 'special)
|
||||
|
||||
;; Avoid compiler warning
|
||||
(defvar tool-bar-map)
|
||||
|
||||
(define-derived-mode mh-show-mode text-mode "MH-Show"
|
||||
"Major mode for showing messages in MH-E.\\<mh-show-mode-map>
|
||||
The value of `mh-show-mode-hook' is a list of functions to
|
||||
|
@ -1015,7 +1069,9 @@ be called, with no arguments, upon entry to this mode."
|
|||
(turn-on-font-lock))
|
||||
(if (and (boundp 'tool-bar-mode) tool-bar-mode)
|
||||
(set (make-local-variable 'tool-bar-map) mh-show-tool-bar-map))
|
||||
(mh-funcall-if-exists mh-toolbar-init :show)
|
||||
(when mh-decode-mime-flag
|
||||
(mh-make-local-hook 'kill-buffer-hook)
|
||||
(add-hook 'kill-buffer-hook 'mh-mime-cleanup nil t))
|
||||
(easy-menu-add mh-show-sequence-menu)
|
||||
(easy-menu-add mh-show-message-menu)
|
||||
|
@ -1034,27 +1090,226 @@ be called, with no arguments, upon entry to this mode."
|
|||
(if (fboundp 'goto-address)
|
||||
(goto-address))))
|
||||
|
||||
|
||||
|
||||
;; X-Face and Face display
|
||||
(defvar mh-show-xface-function
|
||||
(cond ((and mh-xemacs-flag (locate-library "x-face"))
|
||||
(cond ((and mh-xemacs-flag (locate-library "x-face") (not (featurep 'xface)))
|
||||
(load "x-face" t t)
|
||||
(if (fboundp 'x-face-xmas-wl-display-x-face)
|
||||
#'x-face-xmas-wl-display-x-face
|
||||
#'ignore))
|
||||
((and (not mh-xemacs-flag) (>= emacs-major-version 21))
|
||||
(load "x-face-e21" t t)
|
||||
(if (fboundp 'x-face-decode-message-header)
|
||||
#'x-face-decode-message-header
|
||||
#'ignore))
|
||||
#'mh-face-display-function)
|
||||
((>= emacs-major-version 21)
|
||||
#'mh-face-display-function)
|
||||
(t #'ignore))
|
||||
"Determine at run time what function should be called to display X-Face.")
|
||||
|
||||
(defvar mh-uncompface-executable
|
||||
(and (fboundp 'executable-find) (executable-find "uncompface")))
|
||||
|
||||
(defun mh-face-to-png (data)
|
||||
"Convert base64 encoded DATA to png image."
|
||||
(with-temp-buffer
|
||||
(insert data)
|
||||
(ignore-errors (base64-decode-region (point-min) (point-max)))
|
||||
(buffer-string)))
|
||||
|
||||
(defun mh-uncompface (data)
|
||||
"Run DATA through `uncompface' to generate bitmap."
|
||||
(with-temp-buffer
|
||||
(insert data)
|
||||
(when (and mh-uncompface-executable
|
||||
(equal (call-process-region (point-min) (point-max)
|
||||
mh-uncompface-executable t '(t nil))
|
||||
0))
|
||||
(mh-icontopbm)
|
||||
(buffer-string))))
|
||||
|
||||
(defun mh-icontopbm ()
|
||||
"Elisp substitute for `icontopbm'."
|
||||
(goto-char (point-min))
|
||||
(let ((end (point-max)))
|
||||
(while (re-search-forward "0x\\(..\\)\\(..\\)," nil t)
|
||||
(save-excursion
|
||||
(goto-char (point-max))
|
||||
(insert (string-to-number (match-string 1) 16))
|
||||
(insert (string-to-number (match-string 2) 16))))
|
||||
(delete-region (point-min) end)
|
||||
(goto-char (point-min))
|
||||
(insert "P4\n48 48\n")))
|
||||
|
||||
(mh-do-in-xemacs (defvar default-enable-multibyte-characters))
|
||||
|
||||
(defun mh-face-display-function ()
|
||||
"Display a Face or X-Face header field.
|
||||
Display Face if both are present."
|
||||
(save-restriction
|
||||
(goto-char (point-min))
|
||||
(re-search-forward "\n\n" (point-max) t)
|
||||
(narrow-to-region (point-min) (point))
|
||||
(let* ((case-fold-search t)
|
||||
(default-enable-multibyte-characters nil)
|
||||
(face (message-fetch-field "face" t))
|
||||
(x-face (message-fetch-field "x-face" t))
|
||||
(url (message-fetch-field "x-image-url" t))
|
||||
raw type)
|
||||
(cond (face (setq raw (mh-face-to-png face)
|
||||
type 'png))
|
||||
(x-face (setq raw (mh-uncompface x-face)
|
||||
type 'pbm))
|
||||
(url (setq type 'url)))
|
||||
(when type
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward "^from:" (point-max) t)
|
||||
;; GNU Emacs
|
||||
(mh-do-in-gnu-emacs
|
||||
(if (eq type 'url)
|
||||
(mh-x-image-url-display url)
|
||||
(mh-funcall-if-exists
|
||||
insert-image (create-image
|
||||
raw type t
|
||||
:foreground (face-foreground 'mh-show-xface-face)
|
||||
:background (face-background 'mh-show-xface-face))
|
||||
" ")))
|
||||
;; XEmacs
|
||||
(mh-do-in-xemacs
|
||||
(cond
|
||||
((eq type 'url)
|
||||
(mh-x-image-url-display url))
|
||||
((eq type 'png)
|
||||
(when (featurep 'png)
|
||||
(set-extent-begin-glyph
|
||||
(make-extent (point) (point))
|
||||
(make-glyph (vector 'png ':data (mh-face-to-png face))))))
|
||||
;; Try internal xface support if available...
|
||||
((and (eq type 'pbm) (featurep 'xface))
|
||||
(set-glyph-face
|
||||
(set-extent-begin-glyph
|
||||
(make-extent (point) (point))
|
||||
(make-glyph (vector 'xface ':data (concat "X-Face: " x-face))))
|
||||
'mh-show-xface-face))
|
||||
;; Otherwise try external support with x-face...
|
||||
((and (eq type 'pbm)
|
||||
(fboundp 'x-face-xmas-wl-display-x-face)
|
||||
(fboundp 'executable-find) (executable-find "uncompface"))
|
||||
(mh-funcall-if-exists x-face-xmas-wl-display-x-face)))
|
||||
(when raw (insert " "))))))))
|
||||
|
||||
|
||||
(defun mh-show-xface ()
|
||||
"Display X-Face."
|
||||
(when (and mh-show-use-xface-flag
|
||||
(when (and window-system mh-show-use-xface-flag
|
||||
(or mh-decode-mime-flag mhl-formfile
|
||||
mh-clean-message-header-flag))
|
||||
(funcall mh-show-xface-function)))
|
||||
|
||||
|
||||
|
||||
;; X-Image-URL display
|
||||
|
||||
(defvar mh-x-image-cache-directory nil
|
||||
"Directory where X-Image-URL images are cached.")
|
||||
|
||||
(defvar mh-convert-executable (executable-find "convert"))
|
||||
(defvar mh-wget-executable (executable-find "wget"))
|
||||
(defvar mh-x-image-temp-file nil)
|
||||
(defvar mh-x-image-url nil)
|
||||
(defvar mh-x-image-marker nil)
|
||||
(defvar mh-x-image-url-cache-file nil)
|
||||
|
||||
(defun mh-x-image-url-cache-canonicalize (url)
|
||||
"Canonicalize URL.
|
||||
Replace the ?/ character with a ?! character."
|
||||
(with-temp-buffer
|
||||
(insert url)
|
||||
(goto-char (point-min))
|
||||
(while (search-forward "/" nil t) (replace-match "!"))
|
||||
(format "%s/%s.png" mh-x-image-cache-directory (buffer-string))))
|
||||
|
||||
(defun mh-x-image-url-fetch-image (url cache-file marker sentinel)
|
||||
"Fetch and display the image specified by URL.
|
||||
After the image is fetched, it is stored in CACHE-FILE. It will be displayed
|
||||
in a buffer and position specified by MARKER. The actual display is carried
|
||||
out by the SENTINEL function."
|
||||
(if (and mh-wget-executable
|
||||
mh-fetch-x-image-url
|
||||
(or (eq mh-fetch-x-image-url t)
|
||||
(y-or-n-p (format "Fetch %s? " url))))
|
||||
(let ((buffer (get-buffer-create (generate-new-buffer-name " *mh-url*")))
|
||||
(filename (make-temp-name "/tmp/mhe-wget")))
|
||||
(save-excursion
|
||||
(set-buffer buffer)
|
||||
(set (make-local-variable 'mh-x-image-url-cache-file) cache-file)
|
||||
(set (make-local-variable 'mh-x-image-marker) marker)
|
||||
(set (make-local-variable 'mh-x-image-temp-file) filename))
|
||||
(set-process-sentinel
|
||||
(start-process "*wget*" buffer mh-wget-executable "-O" filename url)
|
||||
sentinel))
|
||||
;; Make sure we don't ask about this image again
|
||||
(when (and mh-wget-executable (eq mh-fetch-x-image-url 'ask))
|
||||
(make-symbolic-link mh-x-image-cache-directory cache-file t))))
|
||||
|
||||
(defun mh-x-image-display (image marker)
|
||||
"Display IMAGE at MARKER."
|
||||
(save-excursion
|
||||
(set-buffer (marker-buffer marker))
|
||||
(let ((buffer-read-only nil)
|
||||
(default-enable-multibyte-characters nil)
|
||||
(buffer-modified-flag (buffer-modified-p)))
|
||||
(unwind-protect
|
||||
(when (and (file-readable-p image) (not (file-symlink-p image)))
|
||||
(goto-char marker)
|
||||
(mh-do-in-gnu-emacs
|
||||
(mh-funcall-if-exists insert-image (create-image image 'png)))
|
||||
(mh-do-in-xemacs
|
||||
(when (featurep 'png)
|
||||
(set-extent-begin-glyph
|
||||
(make-extent (point) (point))
|
||||
(make-glyph
|
||||
(vector 'png ':data (with-temp-buffer
|
||||
(insert-file-contents-literally image)
|
||||
(buffer-string))))))))
|
||||
(set-buffer-modified-p buffer-modified-flag)))))
|
||||
|
||||
(defun mh-x-image-scale-and-display (process change)
|
||||
"When the wget PROCESS terminates scale and display image.
|
||||
The argument CHANGE is ignored."
|
||||
(when (eq (process-status process) 'exit)
|
||||
(let (marker temp-file cache-filename wget-buffer)
|
||||
(save-excursion
|
||||
(set-buffer (setq wget-buffer (process-buffer process)))
|
||||
(setq marker mh-x-image-marker
|
||||
cache-filename mh-x-image-url-cache-file
|
||||
temp-file mh-x-image-temp-file))
|
||||
(when mh-convert-executable
|
||||
(call-process mh-convert-executable nil nil nil "-resize" "96x48"
|
||||
temp-file cache-filename))
|
||||
(if (file-exists-p cache-filename)
|
||||
(mh-x-image-display cache-filename marker)
|
||||
(make-symbolic-link mh-x-image-cache-directory cache-filename t))
|
||||
(ignore-errors
|
||||
(set-marker marker nil)
|
||||
(delete-process process)
|
||||
(kill-buffer wget-buffer)
|
||||
(delete-file temp-file)))))
|
||||
|
||||
(defun mh-x-image-url-display (url)
|
||||
"Display image from location URL.
|
||||
If the URL isn't present in the cache then it is fetched with wget."
|
||||
(let ((cache-filename (mh-x-image-url-cache-canonicalize url))
|
||||
(marker (set-marker (make-marker) (point))))
|
||||
(cond ((file-exists-p cache-filename)
|
||||
(mh-x-image-display cache-filename marker))
|
||||
((not mh-fetch-x-image-url)
|
||||
(set-marker marker nil))
|
||||
((and (not (file-exists-p mh-x-image-cache-directory))
|
||||
(call-process "mkdir" nil nil nil mh-x-image-cache-directory)
|
||||
nil))
|
||||
((and (file-exists-p mh-x-image-cache-directory)
|
||||
(file-directory-p mh-x-image-cache-directory))
|
||||
(mh-x-image-url-fetch-image url cache-filename marker
|
||||
'mh-x-image-scale-and-display)))))
|
||||
|
||||
|
||||
|
||||
(defun mh-maybe-show (&optional msg)
|
||||
"Display message at cursor, but only if in show mode.
|
||||
If optional arg MSG is non-nil, display that message instead."
|
||||
|
@ -1110,6 +1365,7 @@ arguments, after the message has been displayed."
|
|||
(if (not (memq msg mh-seen-list))
|
||||
(setq mh-seen-list (cons msg mh-seen-list)))
|
||||
(when mh-update-sequences-after-mh-show-flag
|
||||
(if mh-index-data (mh-index-update-unseen msg))
|
||||
(mh-update-sequences))
|
||||
(run-hooks 'mh-show-hook))
|
||||
|
||||
|
@ -1147,32 +1403,12 @@ The message is displayed in raw form."
|
|||
(delete-other-windows)
|
||||
(switch-to-buffer edit-buffer)))
|
||||
|
||||
(defun mh-decode-content-transfer-encoded-message ()
|
||||
"Run mimencode on message body, if needed."
|
||||
(let ((case-fold-search t)
|
||||
(header-end (mail-header-end)))
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward "^content-transfer-encoding: " header-end t)
|
||||
(let ((enc (buffer-substring-no-properties (point) (line-end-position)))
|
||||
cmdline)
|
||||
(setq cmdline
|
||||
(cond ((string-match "base64" enc) (list "-u" "-b" "-p"))
|
||||
((string-match "quoted-printable" enc) (list "-u" "-q"))
|
||||
(t nil)))
|
||||
(when cmdline
|
||||
(beginning-of-line)
|
||||
(insert "Removed-")
|
||||
(setq header-end (mail-header-end))
|
||||
(goto-char (1+ header-end))
|
||||
(apply #'call-process-region (1+ header-end) (point-max) "mimencode"
|
||||
t t nil cmdline))))))
|
||||
|
||||
(defun mh-show-unquote-From ()
|
||||
"Decode >From at beginning of lines for `mh-show-mode'."
|
||||
(save-excursion
|
||||
(let ((modified (buffer-modified-p))
|
||||
(case-fold-search nil))
|
||||
(goto-char (mail-header-end))
|
||||
(goto-char (mh-mail-header-end))
|
||||
(while (re-search-forward "^>From" nil t)
|
||||
(replace-match "From"))
|
||||
(set-buffer-modified-p modified))))
|
||||
|
@ -1226,8 +1462,6 @@ Sets the current buffer to the show buffer."
|
|||
(list "-form" formfile))
|
||||
msg-filename)
|
||||
(insert-file-contents-literally msg-filename))
|
||||
(if mh-decode-content-transfer-encoded-message-flag
|
||||
(mh-decode-content-transfer-encoded-message))
|
||||
;; Cleanup old mime handles
|
||||
(mh-mime-cleanup)
|
||||
;; Use mm to display buffer
|
||||
|
@ -1235,6 +1469,7 @@ Sets the current buffer to the show buffer."
|
|||
(mh-add-missing-mime-version-header)
|
||||
(setf (mh-buffer-data) (mh-make-buffer-data))
|
||||
(mh-mime-display))
|
||||
(mh-show-mode)
|
||||
;; Header cleanup
|
||||
(goto-char (point-min))
|
||||
(cond (clean-message-header
|
||||
|
@ -1244,6 +1479,7 @@ Sets the current buffer to the show buffer."
|
|||
(goto-char (point-min)))
|
||||
(t
|
||||
(mh-start-of-uncleaned-message)))
|
||||
(mh-decode-message-header)
|
||||
;; the parts of visiting we want to do (no locking)
|
||||
(or (eq buffer-undo-list t) ;don't save undo info for prev msgs
|
||||
(setq buffer-undo-list nil))
|
||||
|
@ -1253,7 +1489,6 @@ Sets the current buffer to the show buffer."
|
|||
(setq buffer-backed-up nil)
|
||||
(auto-save-mode 1)
|
||||
(set-mark nil)
|
||||
(mh-show-mode)
|
||||
(unwind-protect
|
||||
(when (and mh-decode-mime-flag (not formfile))
|
||||
(setq buffer-read-only nil)
|
||||
|
@ -1276,6 +1511,7 @@ 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."
|
||||
(let ((case-fold-search t)
|
||||
(buffer-read-only nil)
|
||||
(after-change-functions nil)) ;Work around emacs-20 font-lock bug
|
||||
;causing an endless loop.
|
||||
(save-restriction
|
||||
|
@ -1306,15 +1542,17 @@ lines to display. INVISIBLE-HEADERS is ignored if VISIBLE-HEADERS is non-nil."
|
|||
|
||||
(defun mh-notate (msg notation offset)
|
||||
"Mark MSG with the character NOTATION at position OFFSET.
|
||||
Null MSG means the message at cursor."
|
||||
Null MSG means the message at cursor.
|
||||
If NOTATION is nil then no change in the buffer occurs."
|
||||
(save-excursion
|
||||
(if (or (null msg)
|
||||
(mh-goto-msg msg t t))
|
||||
(with-mh-folder-updating (t)
|
||||
(beginning-of-line)
|
||||
(forward-char offset)
|
||||
(delete-char 1)
|
||||
(insert notation)))))
|
||||
(let ((notation (or notation (char-after))))
|
||||
(delete-char 1)
|
||||
(insert notation))))))
|
||||
|
||||
(defun mh-find-msg-get-num (step)
|
||||
"Return the message number of the message nearest the cursor.
|
||||
|
@ -1405,6 +1643,9 @@ arguments, after these variable have been set."
|
|||
(setq mh-user-path
|
||||
(file-name-as-directory
|
||||
(expand-file-name mh-user-path (expand-file-name "~"))))
|
||||
(unless mh-x-image-cache-directory
|
||||
(setq mh-x-image-cache-directory
|
||||
(expand-file-name ".mhe-x-image-cache" mh-user-path)))
|
||||
(setq mh-draft-folder (mh-get-profile-field "Draft-Folder:"))
|
||||
(if mh-draft-folder
|
||||
(progn
|
||||
|
@ -1542,7 +1783,7 @@ The message number width portion of the format is discovered using
|
|||
(set-buffer tmp-buffer)
|
||||
(erase-buffer)
|
||||
(apply 'call-process
|
||||
(expand-file-name "scan" mh-progs) nil '(t nil) nil
|
||||
(expand-file-name mh-scan-prog mh-progs) nil '(t nil) nil
|
||||
(list folder "last" "-format" "%(msg)"))
|
||||
(goto-char (point-min))
|
||||
(if (re-search-forward mh-scan-msg-number-regexp nil 0 1)
|
||||
|
@ -1582,6 +1823,7 @@ not updated."
|
|||
sorted-msgs))
|
||||
|
||||
(defvar mh-sub-folders-cache (make-hash-table :test #'equal))
|
||||
(defvar mh-current-folder-name nil)
|
||||
|
||||
(defun mh-normalize-folder-name (folder &optional empty-string-okay
|
||||
dont-remove-trailing-slash)
|
||||
|
@ -1602,8 +1844,18 @@ if present is retained (if present), otherwise it is removed."
|
|||
(setq folder (replace-match "/" nil t folder)))
|
||||
(let* ((length (length folder))
|
||||
(trailing-slash-present (and (> length 0)
|
||||
(equal (aref folder (1- length)) ?/))))
|
||||
(let ((components (split-string folder "/"))
|
||||
(equal (aref folder (1- length)) ?/)))
|
||||
(leading-slash-present (and (> length 0)
|
||||
(equal (aref folder 0) ?/))))
|
||||
(when (and (> length 0) (equal (aref folder 0) ?@)
|
||||
(stringp mh-current-folder-name))
|
||||
(setq folder (format "%s/%s/" mh-current-folder-name
|
||||
(substring folder 1))))
|
||||
;; XXX: Purge empty strings from the list that split-string returns. In
|
||||
;; XEmacs, (split-string "+foo/" "/") returns ("+foo" "") while in GNU
|
||||
;; Emacs it returns ("+foo"). In the code it is assumed that the
|
||||
;; components list has no empty strings.
|
||||
(let ((components (delete "" (split-string folder "/")))
|
||||
(result ()))
|
||||
;; Remove .. and . from the pathname.
|
||||
(dolist (component components)
|
||||
|
@ -1618,7 +1870,9 @@ if present is retained (if present), otherwise it is removed."
|
|||
;; Remove trailing '/' if needed.
|
||||
(unless (and trailing-slash-present dont-remove-trailing-slash)
|
||||
(when (not (equal folder ""))
|
||||
(setq folder (substring folder 0 (1- (length folder))))))))
|
||||
(setq folder (substring folder 0 (1- (length folder))))))
|
||||
(when leading-slash-present
|
||||
(setq folder (concat "/" folder)))))
|
||||
(cond ((and empty-string-okay (equal folder "")))
|
||||
((equal folder "") (setq folder "+"))
|
||||
((not (equal (aref folder 0) ?+)) (setq folder (concat "+" folder)))))
|
||||
|
@ -1713,9 +1967,23 @@ tell us about the option +foo/bar!"
|
|||
|
||||
(defvar mh-folder-hist nil)
|
||||
(defvar mh-speed-folder-map)
|
||||
(defvar mh-speed-flists-cache)
|
||||
|
||||
(defvar mh-allow-root-folder-flag nil
|
||||
"Non-nil means \"+\" is an acceptable folder name.
|
||||
This variable is used to communicate with `mh-folder-completion-function'. That
|
||||
function can have exactly three arguments so we bind this variable to t or nil.
|
||||
|
||||
This variable should never be set.")
|
||||
|
||||
(defvar mh-folder-completion-map (copy-keymap minibuffer-local-completion-map))
|
||||
(define-key mh-folder-completion-map " " 'minibuffer-complete)
|
||||
|
||||
(defun mh-speed-flists-active-p ()
|
||||
"Check if speedbar is running with message counts enabled."
|
||||
(and (featurep 'mh-speed)
|
||||
(> (hash-table-count mh-speed-flists-cache) 0)))
|
||||
|
||||
(defun mh-folder-completion-function (name predicate flag)
|
||||
"Programmable completion for folder names.
|
||||
NAME is the partial folder name that has been input. PREDICATE if non-nil is a
|
||||
|
@ -1747,14 +2015,19 @@ whether the completion is over."
|
|||
(all-completions
|
||||
remainder (mh-sub-folders last-complete t) predicate))
|
||||
((eq flag 'lambda)
|
||||
(file-exists-p
|
||||
(concat mh-user-path
|
||||
(substring (mh-normalize-folder-name name) 1)))))))
|
||||
(let ((path (concat mh-user-path
|
||||
(substring (mh-normalize-folder-name name) 1))))
|
||||
(cond (mh-allow-root-folder-flag (file-exists-p path))
|
||||
((equal path mh-user-path) nil)
|
||||
(t (file-exists-p path))))))))
|
||||
|
||||
(defun mh-folder-completing-read (prompt default)
|
||||
"Read folder name with PROMPT and default result DEFAULT."
|
||||
(defun mh-folder-completing-read (prompt default allow-root-folder-flag)
|
||||
"Read folder name with PROMPT and default result DEFAULT.
|
||||
If ALLOW-ROOT-FOLDER-FLAG is non-nil then \"+\" is allowed to be a folder name
|
||||
corresponding to `mh-user-path'."
|
||||
(mh-normalize-folder-name
|
||||
(let ((minibuffer-local-completion-map mh-folder-completion-map))
|
||||
(let ((minibuffer-local-completion-map mh-folder-completion-map)
|
||||
(mh-allow-root-folder-flag allow-root-folder-flag))
|
||||
(completing-read prompt 'mh-folder-completion-function nil nil nil
|
||||
'mh-folder-hist default))
|
||||
t))
|
||||
|
@ -1775,8 +2048,10 @@ when used in searching."
|
|||
((equal "" default) "? ")
|
||||
(t (format " [%s]? " default))))
|
||||
(prompt (format "%s folder%s" prompt default-string))
|
||||
(mh-current-folder-name mh-current-folder)
|
||||
read-name folder-name)
|
||||
(while (and (setq read-name (mh-folder-completing-read prompt default))
|
||||
(while (and (setq read-name (mh-folder-completing-read
|
||||
prompt default allow-root-folder-flag))
|
||||
(equal read-name "")
|
||||
(equal default "")))
|
||||
(cond ((or (equal read-name "")
|
||||
|
@ -1790,6 +2065,14 @@ when used in searching."
|
|||
(cond ((and (> (length folder-name) 0)
|
||||
(eq (aref folder-name (1- (length folder-name))) ?/))
|
||||
(setq folder-name (substring folder-name 0 -1))))
|
||||
(let* ((last-slash (mh-search-from-end ?/ folder-name))
|
||||
(parent (and last-slash (substring folder-name 0 last-slash)))
|
||||
(child (if last-slash
|
||||
(substring folder-name (1+ last-slash))
|
||||
(substring folder-name 1))))
|
||||
(unless (member child
|
||||
(mapcar #'car (gethash parent mh-sub-folders-cache)))
|
||||
(mh-remove-from-sub-folders-cache folder-name)))
|
||||
(let ((new-file-flag
|
||||
(not (file-exists-p (mh-expand-file-name folder-name)))))
|
||||
(cond ((and new-file-flag
|
||||
|
@ -1809,6 +2092,24 @@ when used in searching."
|
|||
(mh-expand-file-name folder-name)))))
|
||||
folder-name))
|
||||
|
||||
(defun mh-truncate-log-buffer ()
|
||||
"If `mh-log-buffer' is too big then truncate it.
|
||||
If the number of lines in `mh-log-buffer' exceeds `mh-log-buffer-lines' then
|
||||
keep only the last `mh-log-buffer-lines'. As a side effect the point is set to
|
||||
the end of the log buffer.
|
||||
|
||||
The function returns the size of the final size of the log buffer."
|
||||
(with-current-buffer (get-buffer-create mh-log-buffer)
|
||||
(goto-char (point-max))
|
||||
(save-excursion
|
||||
(when (equal (forward-line (- mh-log-buffer-lines)) 0)
|
||||
(delete-region (point-min) (point))))
|
||||
(unless (or (bobp)
|
||||
(save-excursion
|
||||
(and (equal (forward-line -1) 0) (equal (char-after) ?))))
|
||||
(insert "\n\n"))
|
||||
(buffer-size)))
|
||||
|
||||
;;; Issue commands to MH.
|
||||
|
||||
(defun mh-exec-cmd (command &rest args)
|
||||
|
@ -1818,14 +2119,14 @@ Any output is assumed to be an error and is shown to the user.
|
|||
The output is not read or parsed by MH-E."
|
||||
(save-excursion
|
||||
(set-buffer (get-buffer-create mh-log-buffer))
|
||||
(erase-buffer)
|
||||
(apply 'call-process
|
||||
(expand-file-name command mh-progs) nil t nil
|
||||
(mh-list-to-string args))
|
||||
(if (> (buffer-size) 0)
|
||||
(save-window-excursion
|
||||
(switch-to-buffer-other-window mh-log-buffer)
|
||||
(sit-for 5)))))
|
||||
(let ((initial-size (mh-truncate-log-buffer)))
|
||||
(apply 'call-process
|
||||
(expand-file-name command mh-progs) nil t nil
|
||||
(mh-list-to-string args))
|
||||
(if (> (buffer-size) initial-size)
|
||||
(save-window-excursion
|
||||
(switch-to-buffer-other-window mh-log-buffer)
|
||||
(sit-for 5))))))
|
||||
|
||||
(defun mh-exec-cmd-error (env command &rest args)
|
||||
"In environment ENV, execute mh-command COMMAND with ARGS.
|
||||
|
@ -1834,19 +2135,15 @@ Signals an error if process does not complete successfully."
|
|||
(save-excursion
|
||||
(set-buffer (get-buffer-create mh-temp-buffer))
|
||||
(erase-buffer)
|
||||
(let ((status
|
||||
(if env
|
||||
;; the shell hacks necessary here shows just how broken Unix is
|
||||
(apply 'call-process "/bin/sh" nil t nil "-c"
|
||||
(format "%s %s ${1+\"$@\"}"
|
||||
env
|
||||
(expand-file-name command mh-progs))
|
||||
command
|
||||
(mh-list-to-string args))
|
||||
(apply 'call-process
|
||||
(expand-file-name command mh-progs) nil t nil
|
||||
(mh-list-to-string args)))))
|
||||
(mh-handle-process-error command status))))
|
||||
(let ((process-environment process-environment))
|
||||
;; XXX: We should purge the list that split-string returns of empty
|
||||
;; strings. This can happen in XEmacs if leading or trailing spaces
|
||||
;; are present.
|
||||
(dolist (elem (if (stringp env) (split-string env " ") ()))
|
||||
(push elem process-environment))
|
||||
(mh-handle-process-error
|
||||
command (apply #'call-process (expand-file-name command mh-progs)
|
||||
nil t nil (mh-list-to-string args))))))
|
||||
|
||||
(defun mh-exec-cmd-daemon (command filter &rest args)
|
||||
"Execute MH command COMMAND in the background.
|
||||
|
@ -1858,7 +2155,7 @@ details of FILTER.
|
|||
ARGS are passed to COMMAND as command line arguments."
|
||||
(save-excursion
|
||||
(set-buffer (get-buffer-create mh-log-buffer))
|
||||
(erase-buffer))
|
||||
(mh-truncate-log-buffer))
|
||||
(let* ((process-connection-type nil)
|
||||
(process (apply 'start-process
|
||||
command nil
|
||||
|
@ -1866,6 +2163,22 @@ ARGS are passed to COMMAND as command line arguments."
|
|||
(mh-list-to-string args))))
|
||||
(set-process-filter process (or filter 'mh-process-daemon))))
|
||||
|
||||
(defun mh-exec-cmd-env-daemon (env command filter &rest args)
|
||||
"In ennvironment ENV, execute mh-command COMMAND in the background.
|
||||
|
||||
ENV is nil or a string of space-separated \"var=value\" elements.
|
||||
Signals an error if process does not complete successfully.
|
||||
|
||||
If FILTER is non-nil then it is used to process the output otherwise the
|
||||
default filter `mh-process-daemon' is used. See `set-process-filter' for more
|
||||
details of FILTER.
|
||||
|
||||
ARGS are passed to COMMAND as command line arguments."
|
||||
(let ((process-environment process-environment))
|
||||
(dolist (elem (if (stringp env) (split-string env " ") ()))
|
||||
(push elem process-environment))
|
||||
(apply #'mh-exec-cmd-daemon command filter args)))
|
||||
|
||||
(defun mh-process-daemon (process output)
|
||||
"PROCESS daemon that puts OUTPUT into a temporary buffer.
|
||||
Any output from the process is displayed in an asynchronous pop-up window."
|
||||
|
@ -1933,30 +2246,20 @@ 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.
|
||||
STATUS is return value from `call-process'.
|
||||
Program output is in current buffer.
|
||||
If output is too long to include in error message, display the buffer."
|
||||
(cond ((eq status 0) ;success
|
||||
status)
|
||||
((stringp status) ;kill string
|
||||
(error "%s: %s" command status))
|
||||
(t ;exit code
|
||||
(cond
|
||||
((= (buffer-size) 0) ;program produced no error message
|
||||
(error "%s: exit code %d" command status))
|
||||
(t
|
||||
;; will error message fit on one line?
|
||||
(goto-line 2)
|
||||
(if (and (< (buffer-size) (frame-width))
|
||||
(eobp))
|
||||
(error "%s"
|
||||
(buffer-substring 1 (progn (goto-char 1)
|
||||
(end-of-line)
|
||||
(point))))
|
||||
(display-buffer (current-buffer))
|
||||
(error "%s failed with status %d. See error message in other window"
|
||||
command status)))))))
|
||||
"Raise error if COMMAND returned non-zero STATUS, otherwise return STATUS."
|
||||
(if (equal status 0)
|
||||
status
|
||||
(goto-char (point-min))
|
||||
(insert (if (integerp status)
|
||||
(format "%s: exit code %d\n" command status)
|
||||
(format "%s: %s\n" command status)))
|
||||
(save-excursion
|
||||
(let ((error-message (buffer-substring (point-min) (point-max))))
|
||||
(set-buffer (get-buffer-create mh-log-buffer))
|
||||
(mh-truncate-log-buffer)
|
||||
(insert error-message)))
|
||||
(error "%s failed, check %s buffer for error message"
|
||||
command mh-log-buffer)))
|
||||
|
||||
(defun mh-list-to-string (l)
|
||||
"Flatten the list L and make every element of the new list into a string."
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
;;; mh-xemacs-compat.el --- GNU Emacs Functions needed by XEmacs
|
||||
|
||||
;; Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2001, 02, 2003 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: FSF
|
||||
;; Maintainer: Bill Wohler <wohler@newt.com>
|
||||
|
@ -28,13 +28,13 @@
|
|||
|
||||
;;; Change Log:
|
||||
|
||||
;; $Id: mh-xemacs-compat.el,v 1.13 2002/11/30 01:21:42 wohler Exp $
|
||||
|
||||
;;; Code:
|
||||
|
||||
;;; Some requires:
|
||||
(require 'rfc822)
|
||||
|
||||
(eval-when-compile (require 'mh-utils))
|
||||
|
||||
;;; Simple compatibility:
|
||||
|
||||
(unless (fboundp 'match-string-no-properties)
|
||||
|
@ -52,6 +52,42 @@
|
|||
(unless (fboundp 'cancel-timer)
|
||||
(defalias 'cancel-timer 'delete-itimer))
|
||||
|
||||
;; Set up the modeline glyph
|
||||
(defconst mh-modeline-logo
|
||||
"/* XPM */
|
||||
static char * file[] = {
|
||||
\"18 13 2 1\",
|
||||
\"# c #666699\",
|
||||
\". c None s None\",
|
||||
\"........##........\",
|
||||
\".......####.......\",
|
||||
\"......######......\",
|
||||
\"......######......\",
|
||||
\"....#########.....\",
|
||||
\"..##############..\",
|
||||
\".##...######....#.\",
|
||||
\"##...#.#.####...#.\",
|
||||
\"....#..#.##.#...#.\",
|
||||
\"...#..##.#.#.#....\",
|
||||
\"...#..#..#..#.#...\",
|
||||
\"...#..#.##..#.##..\",
|
||||
\"...#..#.#..#....#.\"};"
|
||||
"The image for the modeline logo.")
|
||||
|
||||
(mh-do-in-xemacs
|
||||
(defvar mh-modeline-glyph
|
||||
(progn
|
||||
(let* ((data mh-modeline-logo)
|
||||
(glyph (make-glyph
|
||||
(cond ((and (featurep 'xpm)
|
||||
(device-on-window-system-p)
|
||||
has-modeline-p)
|
||||
`[xpm :data ,data])
|
||||
(t [string :data "MH-E"])))))
|
||||
(set-glyph-face glyph 'modeline-buffer-id)
|
||||
glyph))
|
||||
"Cute little logo to put in the modeline of MH-E buffers."))
|
||||
|
||||
(provide 'mh-xemacs-compat)
|
||||
|
||||
;;; Local Variables:
|
||||
|
|
1306
lisp/mh-e/mh-xemacs-icons.el
Normal file
1306
lisp/mh-e/mh-xemacs-icons.el
Normal file
File diff suppressed because it is too large
Load diff
BIN
lisp/toolbar/highlight.pbm
Normal file
BIN
lisp/toolbar/highlight.pbm
Normal file
Binary file not shown.
33
lisp/toolbar/highlight.xpm
Normal file
33
lisp/toolbar/highlight.xpm
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* XPM */
|
||||
static char * highlight_xpm[] = {
|
||||
/* columns rows colors chars-per-pixel */
|
||||
"24 24 4 1",
|
||||
" c None",
|
||||
". c black",
|
||||
"X c #828282827474",
|
||||
"o c #dd00df007e00",
|
||||
/* pixels */
|
||||
" ..... ",
|
||||
" ..XXX.. ",
|
||||
" .XXXXX. ",
|
||||
" .XXXXX.. ",
|
||||
" .XXXXX. ",
|
||||
" .XXXXX. ",
|
||||
" .XXXXX. ",
|
||||
" .ooXX. ",
|
||||
" ..ooo. ",
|
||||
" oooo .... ",
|
||||
"oo.ooo....oo ... ",
|
||||
"o.o.ooo.oo.o.ooo.o ",
|
||||
".ooo.oo.oo.o.ooooo ",
|
||||
".ooo.oo.oo.o.ooooo ",
|
||||
".ooo.oo...oo.ooooo ",
|
||||
".....oo.oo.o.ooooo ",
|
||||
".ooo.oo.oo.o.ooooo ",
|
||||
".ooo.oo.oo.o.ooo.o ",
|
||||
". oo.o....ooo...o ",
|
||||
" oo oooo ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
Loading…
Add table
Reference in a new issue