* nxml/xsd-regexp.el (xsdre-gen-categories):
[bpt/emacs.git] / lisp / mh-e / mh-comp.el
CommitLineData
dda00b2c 1;;; mh-comp.el --- MH-E functions for composing and sending messages
c26cf6c8 2
e495eaec 3;; Copyright (C) 1993, 1995, 1997,
dcf71371
BW
4;; 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
5;; Free Software Foundation, Inc.
7382bcae 6
a1b4049d 7;; Author: Bill Wohler <wohler@newt.com>
6e65a812 8;; Maintainer: Bill Wohler <wohler@newt.com>
7382bcae 9;; Keywords: mail
a1b4049d 10;; See: mh-e.el
c26cf6c8 11
60370d40 12;; This file is part of GNU Emacs.
c26cf6c8 13
5e809f55 14;; GNU Emacs is free software: you can redistribute it and/or modify
c26cf6c8 15;; it under the terms of the GNU General Public License as published by
5e809f55
GM
16;; the Free Software Foundation, either version 3 of the License, or
17;; (at your option) any later version.
c26cf6c8 18
9b7bc076 19;; GNU Emacs is distributed in the hope that it will be useful,
c26cf6c8
RS
20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;; GNU General Public License for more details.
23
24;; You should have received a copy of the GNU General Public License
5e809f55 25;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
c26cf6c8
RS
26
27;;; Commentary:
28
dda00b2c
BW
29;; This file includes the functions in the MH-Folder maps that get us
30;; into MH-Letter mode, as well the functions in the MH-Letter mode
31;; that are used to send the mail. Other that those, functions that
32;; are needed in mh-letter.el should be found there.
c26cf6c8 33
847b8219
KH
34;;; Change Log:
35
c26cf6c8
RS
36;;; Code:
37
7094eefe 38(require 'mh-e)
dda00b2c
BW
39(require 'mh-gnus) ;needed because mh-gnus.el not compiled
40(require 'mh-scan)
7094eefe 41
dda00b2c 42(require 'sendmail)
bdcfe844 43
dda00b2c
BW
44(autoload 'easy-menu-add "easymenu")
45(autoload 'mml-insert-tag "mml")
c26cf6c8 46
cee9f5c6
BW
47\f
48
dda00b2c 49;;; Site Customization
847b8219
KH
50
51(defvar mh-send-prog "send"
52 "Name of the MH send program.
53Some sites need to change this because of a name conflict.")
54
fbf62741
BW
55(defvar mh-send-uses-spost-flag nil
56 "Non-nil means \"send\" uses \"spost\" to submit messages.
57
58If the value of \"postproc:\" is \"spost\", you may need to set
59this variable to t to tell MH-E to avoid using features of
60\"post\" that are not supported by \"spost\". You'll know that
61you'll need to do this if sending mail fails with an error of
62\"spost: -msgid unknown\".")
63
a1b4049d
BW
64(defvar mh-redist-background nil
65 "If non-nil redist will be done in background like send.
2dcf34f9
BW
66This allows transaction log to be visible if -watch, -verbose or
67-snoop are used.")
847b8219 68
cee9f5c6
BW
69\f
70
dda00b2c 71;;; Variables
c26cf6c8 72
c26cf6c8
RS
73(defvar mh-comp-formfile "components"
74 "Name of file to be used as a skeleton for composing messages.
2dcf34f9
BW
75
76Default is \"components\".
77
78If not an absolute file name, the file is searched for first in the
79user's MH directory, then in the system MH lib directory.")
c26cf6c8 80
847b8219
KH
81(defvar mh-repl-formfile "replcomps"
82 "Name of file to be used as a skeleton for replying to messages.
2dcf34f9
BW
83
84Default is \"replcomps\".
85
86If not an absolute file name, the file is searched for first in the
87user's MH directory, then in the system MH lib directory.")
847b8219 88
c3d6278e 89(defvar mh-repl-group-formfile "replgroupcomps"
bdcfe844 90 "Name of file to be used as a skeleton for replying to messages.
2dcf34f9 91
f0d73c14 92Default is \"replgroupcomps\".
2dcf34f9
BW
93
94This file is used to form replies to the sender and all recipients of
95a message. Only used if `(mh-variant-p 'nmh)' is non-nil.
96If not an absolute file name, the file is searched for first in the
97user's MH directory, then in the system MH lib directory.")
a1b4049d 98
c26cf6c8 99(defvar mh-rejected-letter-start
bdcfe844 100 (format "^%s$"
c3d9274a
BW
101 (regexp-opt
102 '("Content-Type: message/rfc822" ;MIME MDN
f0d73c14 103 "------ This is a copy of the message, including all the headers. ------";from exim
dda00b2c 104 "--- Below this line is a copy of the message."; from qmail
c3d9274a
BW
105 " ----- Unsent message follows -----" ;from sendmail V5
106 " --------Unsent Message below:" ; from sendmail at BU
107 " ----- Original message follows -----" ;from sendmail V8
108 "------- Unsent Draft" ;from MH itself
109 "---------- Original Message ----------" ;from zmailer
110 " --- The unsent message follows ---" ;from AIX mail system
111 " Your message follows:" ;from MMDF-II
112 "Content-Description: Returned Content" ;1993 KJ sendmail
113 ))))
c26cf6c8
RS
114
115(defvar mh-new-draft-cleaned-headers
847b8219 116 "^Date:\\|^Received:\\|^Message-Id:\\|^From:\\|^Sender:\\|^Errors-To:\\|^Delivery-Date:\\|^Return-Path:"
5a4aad03
BW
117 "Regexp of header lines to remove before offering a message as a new draft\\<mh-folder-mode-map>.
118Used by the \\[mh-edit-again] and \\[mh-extract-rejected-mail] commands.")
c26cf6c8 119
88b8b41d
JPW
120(defvar mh-letter-mode-syntax-table
121 (let ((syntax-table (make-syntax-table text-mode-syntax-table)))
122 (modify-syntax-entry ?% "." syntax-table)
123 syntax-table)
bdcfe844 124 "Syntax table used by MH-E while in MH-Letter mode.")
c26cf6c8 125
799f7c09 126(defvar mh-send-args ""
bdcfe844
BW
127 "Extra args to pass to \"send\" command.")
128
129(defvar mh-annotate-char nil
130 "Character to use to annotate `mh-sent-from-msg'.")
131
132(defvar mh-annotate-field nil
133 "Field name for message annotation.")
c26cf6c8 134
aad5673d
SG
135(defvar mh-annotate-list nil
136 "Messages annotated, either a sequence name or a list of message numbers.
137This variable can be used by `mh-annotate-msg-hook'.")
138
a66894d8 139(defvar mh-insert-auto-fields-done-local nil
f0d73c14 140 "Buffer-local variable set when `mh-insert-auto-fields' called successfully.")
a66894d8
BW
141(make-variable-buffer-local 'mh-insert-auto-fields-done-local)
142
dda00b2c
BW
143\f
144
145;;; MH-E Entry Points
146
c26cf6c8
RS
147;;;###autoload
148(defun mh-smail ()
b2064e08 149 "Compose a message with the MH mail system.
f0d73c14 150See `mh-send' for more details on composing mail."
c26cf6c8
RS
151 (interactive)
152 (mh-find-path)
153 (call-interactively 'mh-send))
154
b2064e08
BW
155;;;###autoload
156(defun mh-smail-other-window ()
157 "Compose a message with the MH mail system in other window.
158See `mh-send' for more details on composing mail."
159 (interactive)
160 (mh-find-path)
161 (call-interactively 'mh-send-other-window))
162
dda00b2c
BW
163(defun mh-send-other-window (to cc subject)
164 "Compose a message in another window.
165
166See `mh-send' for more information and a description of how the
167TO, CC, and SUBJECT arguments are used."
168 (interactive (list
169 (mh-interactive-read-address "To: ")
170 (mh-interactive-read-address "Cc: ")
171 (mh-interactive-read-string "Subject: ")))
172 (let ((pop-up-windows t))
173 (mh-send-sub to cc subject (current-window-configuration))))
174
c3d9274a 175(defvar mh-error-if-no-draft nil) ;raise error over using old draft
283b03f4 176
283b03f4 177;;;###autoload
c3d6278e 178(defun mh-smail-batch (&optional to subject other-headers &rest ignored)
b2064e08
BW
179 "Compose a message with the MH mail system.
180
2dcf34f9
BW
181This function does not prompt the user for any header fields, and
182thus is suitable for use by programs that want to create a mail
183buffer. Users should use \\[mh-smail] to compose mail.
f0d73c14 184
2dcf34f9 185Optional arguments for setting certain fields include TO,
0d887b77
BW
186SUBJECT, and OTHER-HEADERS. Additional arguments are IGNORED.
187
188This function remains for Emacs 21 compatibility. New
189applications should use `mh-user-agent-compose'."
283b03f4
KH
190 (mh-find-path)
191 (let ((mh-error-if-no-draft t))
016fbe59 192 (mh-send (or to "") "" (or subject ""))))
283b03f4 193
0d887b77
BW
194;;;###autoload
195(define-mail-user-agent 'mh-e-user-agent
196 'mh-user-agent-compose 'mh-send-letter 'mh-fully-kill-draft
197 'mh-before-send-letter-hook)
198
a1b4049d
BW
199;;;###autoload
200(defun mh-user-agent-compose (&optional to subject other-headers continue
c3d9274a
BW
201 switch-function yank-action
202 send-actions)
a1b4049d 203 "Set up mail composition draft with the MH mail system.
0d887b77
BW
204This is the `mail-user-agent' entry point to MH-E. This function
205conforms to the contract specified by `define-mail-user-agent'
206which means that this function should accept the same arguments
207as `compose-mail'.
a1b4049d
BW
208
209The optional arguments TO and SUBJECT specify recipients and the
210initial Subject field, respectively.
211
2dcf34f9
BW
212OTHER-HEADERS is an alist specifying additional header fields.
213Elements look like (HEADER . VALUE) where both HEADER and VALUE
214are strings.
a1b4049d 215
2dcf34f9
BW
216CONTINUE, SWITCH-FUNCTION, YANK-ACTION and SEND-ACTIONS are
217ignored."
a1b4049d
BW
218 (mh-find-path)
219 (let ((mh-error-if-no-draft t))
220 (mh-send to "" subject)
221 (while other-headers
222 (mh-insert-fields (concat (car (car other-headers)) ":")
c3d9274a 223 (cdr (car other-headers)))
a1b4049d 224 (setq other-headers (cdr other-headers)))))
283b03f4 225
dda00b2c 226;; Shush compiler.
42f8c37f 227(defvar sendmail-coding-system) ; XEmacs
dda00b2c
BW
228
229;;;###autoload
230(defun mh-send-letter (&optional arg)
231 "Save draft and send message.
232
233When you are all through editing a message, you send it with this
234command. You can give a prefix argument ARG to monitor the first stage
235of the delivery\; this output can be found in a buffer called \"*MH-E
236Mail Delivery*\".
237
238The hook `mh-before-send-letter-hook' is run at the beginning of
239this command. For example, if you want to check your spelling in
240your message before sending, add the function `ispell-message'.
241
3fbc098d
BW
242Unless `mh-insert-auto-fields' had previously been called
243manually, the function `mh-insert-auto-fields' is called to
244insert fields based upon the recipients. If fields are added, you
245are given a chance to see and to confirm these fields before the
246message is actually sent. You can do away with this confirmation
247by turning off the option `mh-auto-fields-prompt-flag'.
248
dda00b2c 249In case the MH \"send\" program is installed under a different name,
d0f1af4d
BW
250use `mh-send-prog' to tell MH-E the name.
251
252The hook `mh-annotate-msg-hook' is run after annotating the
253message and scan line."
dda00b2c
BW
254 (interactive "P")
255 (run-hooks 'mh-before-send-letter-hook)
256 (if (and (mh-insert-auto-fields t)
257 mh-auto-fields-prompt-flag
258 (goto-char (point-min)))
259 (if (not (y-or-n-p "Auto fields inserted, send? "))
260 (error "Send aborted")))
261 (cond ((mh-mh-directive-present-p)
262 (mh-mh-to-mime))
263 ((or (mh-mml-tag-present-p) (not (mh-ascii-buffer-p)))
264 (mh-mml-to-mime)))
265 (save-buffer)
266 (message "Sending...")
267 (let ((draft-buffer (current-buffer))
268 (file-name buffer-file-name)
269 (config mh-previous-window-config)
270 (coding-system-for-write
271 (if (and (local-variable-p 'buffer-file-coding-system
272 (current-buffer)) ;XEmacs needs two args
273 ;; We're not sure why, but buffer-file-coding-system
274 ;; tends to get set to undecided-unix.
275 (not (memq buffer-file-coding-system
276 '(undecided undecided-unix undecided-dos))))
277 buffer-file-coding-system
278 (or (and (boundp 'sendmail-coding-system) sendmail-coding-system)
b56a5ae0
SM
279 (and (default-boundp 'buffer-file-coding-system)
280 (default-value 'buffer-file-coding-system))
dda00b2c 281 'iso-latin-1))))
fbf62741
BW
282 ;; Older versions of spost do not support -msgid and -mime.
283 (unless mh-send-uses-spost-flag
284 ;; Adding a Message-ID field looks good, makes it easier to search for
285 ;; message in your +outbox, and best of all doesn't break threading for
286 ;; the recipient if you reply to a message in your +outbox.
287 (setq mh-send-args (concat "-msgid " mh-send-args))
288 ;; The default BCC encapsulation will make a MIME message unreadable.
289 ;; With nmh use the -mime arg to prevent this.
290 (if (and (mh-variant-p 'nmh)
291 (mh-goto-header-field "Bcc:")
292 (mh-goto-header-field "Content-Type:"))
293 (setq mh-send-args (concat "-mime " mh-send-args))))
dda00b2c
BW
294 (cond (arg
295 (pop-to-buffer mh-mail-delivery-buffer)
296 (erase-buffer)
0103690e
BW
297 (mh-exec-cmd-output mh-send-prog t
298 "-nodraftfolder" "-watch" "-nopush"
299 (split-string mh-send-args) file-name)
dda00b2c
BW
300 (goto-char (point-max)) ; show the interesting part
301 (recenter -1)
302 (set-buffer draft-buffer)) ; for annotation below
303 (t
0103690e
BW
304 (mh-exec-cmd-daemon mh-send-prog nil
305 "-nodraftfolder" "-noverbose"
16b9a476 306 (split-string mh-send-args) file-name)))
dda00b2c
BW
307 (if mh-annotate-char
308 (mh-annotate-msg mh-sent-from-msg
309 mh-sent-from-folder
310 mh-annotate-char
311 "-component" mh-annotate-field
312 "-text" (format "\"%s %s\""
313 (mh-get-header-field "To:")
314 (mh-get-header-field "Cc:"))))
315
316 (cond ((or (not arg)
317 (y-or-n-p "Kill draft buffer? "))
318 (kill-buffer draft-buffer)
319 (if config
320 (set-window-configuration config))))
321 (if arg
322 (message "Sending...done")
323 (message "Sending...backgrounded"))))
324
325;;;###autoload
326(defun mh-fully-kill-draft ()
327 "Quit editing and delete draft message.
328
329If for some reason you are not happy with the draft, you can use
330this command to kill the draft buffer and delete the draft
331message. Use the command \\[kill-buffer] if you don't want to
332delete the draft message."
333 (interactive)
334 (if (y-or-n-p "Kill draft message? ")
335 (let ((config mh-previous-window-config))
336 (if (file-exists-p buffer-file-name)
337 (delete-file buffer-file-name))
338 (set-buffer-modified-p nil)
339 (kill-buffer (buffer-name))
340 (message "")
341 (if config
342 (set-window-configuration config)))
343 (error "Message not killed")))
344
345\f
346
347;;; MH-Folder Commands
348
349;; Alphabetical.
350
c3d9274a 351;;;###mh-autoload
b2064e08
BW
352(defun mh-edit-again (message)
353 "Edit a MESSAGE to send it again.
354
2dcf34f9
BW
355If you don't complete a draft for one reason or another, and if
356the draft buffer is no longer available, you can pick your draft
357up again with this command. If you don't use a draft folder, your
358last \"draft\" file will be used. If you use draft folders,
359you'll need to visit the draft folder with \"\\[mh-visit-folder]
360drafts <RET>\", use \\[mh-next-undeleted-msg] to move to the
361appropriate message, and then use \\[mh-edit-again] to prepare
362the message for editing.
b2064e08 363
2dcf34f9
BW
364This command can also be used to take messages that were sent to
365you and to send them to more people.
b2064e08 366
2dcf34f9
BW
367Don't use this command to re-edit a message from a Mailer-Daemon
368who complained that your mail wasn't posted for some reason or
369another (see `mh-extract-rejected-mail').
b2064e08
BW
370
371The default message is the current message.
f0d73c14
BW
372
373See also `mh-send'."
c26cf6c8
RS
374 (interactive (list (mh-get-msg-num t)))
375 (let* ((from-folder mh-current-folder)
c3d9274a
BW
376 (config (current-window-configuration))
377 (draft
378 (cond ((and mh-draft-folder (equal from-folder mh-draft-folder))
b2064e08
BW
379 (pop-to-buffer (find-file-noselect (mh-msg-filename message))
380 t)
381 (rename-buffer (format "draft-%d" message))
bdcfe844
BW
382 ;; Make buffer writable...
383 (setq buffer-read-only nil)
384 ;; If buffer was being used to display the message reinsert
385 ;; from file...
386 (when (eq major-mode 'mh-show-mode)
387 (erase-buffer)
388 (insert-file-contents buffer-file-name))
c3d9274a
BW
389 (buffer-name))
390 (t
b2064e08 391 (mh-read-draft "clean-up" (mh-msg-filename message) nil)))))
c26cf6c8 392 (mh-clean-msg-header (point-min) mh-new-draft-cleaned-headers nil)
a1b4049d 393 (mh-insert-header-separator)
c26cf6c8 394 (goto-char (point-min))
283b03f4 395 (save-buffer)
c26cf6c8 396 (mh-compose-and-send-mail draft "" from-folder nil nil nil nil nil nil
c3d9274a 397 config)
a66894d8
BW
398 (mh-letter-mode-message)
399 (mh-letter-adjust-point)))
c26cf6c8 400
c3d9274a 401;;;###mh-autoload
b2064e08
BW
402(defun mh-extract-rejected-mail (message)
403 "Edit a MESSAGE that was returned by the mail system.
404
2dcf34f9
BW
405This command prepares the message for editing by removing the
406Mailer-Daemon envelope and unneeded header fields. Fix whatever
407addressing problem you had, and send the message again with
408\\[mh-send-letter].
b2064e08
BW
409
410The default message is the current message.
f0d73c14
BW
411
412See also `mh-send'."
c26cf6c8
RS
413 (interactive (list (mh-get-msg-num t)))
414 (let ((from-folder mh-current-folder)
c3d9274a 415 (config (current-window-configuration))
b2064e08 416 (draft (mh-read-draft "extraction" (mh-msg-filename message) nil)))
c26cf6c8
RS
417 (goto-char (point-min))
418 (cond ((re-search-forward mh-rejected-letter-start nil t)
c3d9274a
BW
419 (skip-chars-forward " \t\n")
420 (delete-region (point-min) (point))
421 (mh-clean-msg-header (point-min) mh-new-draft-cleaned-headers nil))
422 (t
f0d73c14 423 (message "Does not appear to be a rejected letter")))
a1b4049d 424 (mh-insert-header-separator)
c26cf6c8 425 (goto-char (point-min))
283b03f4 426 (save-buffer)
b2064e08 427 (mh-compose-and-send-mail draft "" from-folder message
c3d9274a
BW
428 (mh-get-header-field "To:")
429 (mh-get-header-field "From:")
430 (mh-get-header-field "Cc:")
431 nil nil config)
bdcfe844 432 (mh-letter-mode-message)))
c26cf6c8 433
c3d9274a 434;;;###mh-autoload
a66894d8 435(defun mh-forward (to cc &optional range)
2be362c2 436 "Forward message.
a66894d8 437
2dcf34f9
BW
438You are prompted for the TO and CC recipients. You are given a
439draft to edit that looks like it would if you had run the MH
440command \"forw\". You can then add some text.
bdcfe844 441
2dcf34f9
BW
442You can forward several messages by using a RANGE. All of the
443messages in the range are inserted into your draft. Check the
444documentation of `mh-interactive-range' to see how RANGE is read
445in interactive use.
b2064e08 446
d1699462
BW
447The hook `mh-forward-hook' is called on the draft.
448
449See also `mh-compose-forward-as-mime-flag',
450`mh-forward-subject-format', and `mh-send'."
a66894d8
BW
451 (interactive (list (mh-interactive-read-address "To: ")
452 (mh-interactive-read-address "Cc: ")
453 (mh-interactive-range "Forward")))
c26cf6c8 454 (let* ((folder mh-current-folder)
a66894d8 455 (msgs (mh-range-to-msg-list range))
c3d9274a
BW
456 (config (current-window-configuration))
457 (fwd-msg-file (mh-msg-filename (car msgs) folder))
458 ;; forw always leaves file in "draft" since it doesn't have -draft
459 (draft-name (expand-file-name "draft" mh-user-path))
460 (draft (cond ((or (not (file-exists-p draft-name))
00b6a079 461 (y-or-n-p "The file draft exists; discard it? "))
f0d73c14
BW
462 (mh-exec-cmd "forw" "-build"
463 (if (and (mh-variant-p 'nmh)
464 mh-compose-forward-as-mime-flag)
465 "-mime")
924df208
BW
466 mh-current-folder
467 (mh-coalesce-msg-list msgs))
c3d9274a
BW
468 (prog1
469 (mh-read-draft "" draft-name t)
470 (mh-insert-fields "To:" to "Cc:" cc)
471 (save-buffer)))
472 (t
473 (mh-read-draft "" draft-name nil)))))
847b8219 474 (let (orig-from
c3d9274a 475 orig-subject)
41b9a988 476 (save-excursion
c3d9274a
BW
477 (set-buffer (get-buffer-create mh-temp-buffer))
478 (erase-buffer)
479 (insert-file-contents fwd-msg-file)
480 (setq orig-from (mh-get-header-field "From:"))
481 (setq orig-subject (mh-get-header-field "Subject:")))
c26cf6c8 482 (let ((forw-subject
924df208 483 (mh-forwarded-letter-subject orig-from orig-subject)))
c3d9274a
BW
484 (mh-insert-fields "Subject:" forw-subject)
485 (goto-char (point-min))
0c47b17c
BW
486 ;; If using MML, translate MH-style directive
487 (if (equal mh-compose-insertion 'mml)
c3d9274a 488 (save-excursion
a66894d8 489 (goto-char (mh-mail-header-end))
c3d9274a
BW
490 (while
491 (re-search-forward
492 "^#forw \\[\\([^]]+\\)\\] \\(+\\S-+\\) \\(.*\\)$"
493 (point-max) t)
494 (let ((description (if (equal (match-string 1)
495 "forwarded messages")
496 "forwarded message %d"
497 (match-string 1)))
498 (msgs (split-string (match-string 3)))
499 (i 0))
500 (beginning-of-line)
501 (delete-region (point) (progn (forward-line 1) (point)))
502 (dolist (msg msgs)
503 (setq i (1+ i))
504 (mh-mml-forward-message (format description i)
d5926104
JH
505 folder msg)
506 ;; Was inserted before us, move to end of file to preserve order
507 (goto-char (point-max)))))))
c3d9274a
BW
508 ;; Postition just before forwarded message
509 (if (re-search-forward "^------- Forwarded Message" nil t)
510 (forward-line -1)
a66894d8 511 (goto-char (mh-mail-header-end))
c3d9274a
BW
512 (forward-line 1))
513 (delete-other-windows)
514 (mh-add-msgs-to-seq msgs 'forwarded t)
924df208 515 (mh-compose-and-send-mail draft "" folder msgs
c3d9274a
BW
516 to forw-subject cc
517 mh-note-forw "Forwarded:"
518 config)
a66894d8 519 (mh-letter-mode-message)
f0d73c14
BW
520 (mh-letter-adjust-point)
521 (run-hooks 'mh-forward-hook)))))
c26cf6c8
RS
522
523(defun mh-forwarded-letter-subject (from subject)
bdcfe844
BW
524 "Return a Subject suitable for a forwarded message.
525Original message has headers FROM and SUBJECT."
c26cf6c8 526 (let ((addr-start (string-match "<" from))
c3d9274a 527 (comment (string-match "(" from)))
c26cf6c8 528 (cond ((and addr-start (> addr-start 0))
c3d9274a
BW
529 ;; Full Name <luser@host>
530 (setq from (substring from 0 (1- addr-start))))
531 (comment
532 ;; luser@host (Full Name)
533 (setq from (substring from (1+ comment) (1- (length from)))))))
c26cf6c8
RS
534 (format mh-forward-subject-format from subject))
535
b2064e08
BW
536;;;###mh-autoload
537(defun mh-redistribute (to cc &optional message)
538 "Redistribute a message.
847b8219 539
2dcf34f9
BW
540This command is similar in function to forwarding mail, but it
541does not allow you to edit the message, nor does it add your name
542to the \"From\" header field. It appears to the recipient as if
543the message had come from the original sender. When you run this
544command, you are prompted for the TO and CC recipients. The
545default MESSAGE is the current message.
c26cf6c8 546
af435184 547Also investigate the command \\[mh-edit-again] for another way to
2dcf34f9 548redistribute messages.
b2064e08 549
d0f1af4d
BW
550See also `mh-redist-full-contents-flag'.
551
552The hook `mh-annotate-msg-hook' is run after annotating the
553message and scan line."
c26cf6c8 554 (interactive (list (mh-read-address "Redist-To: ")
c3d9274a
BW
555 (mh-read-address "Redist-Cc: ")
556 (mh-get-msg-num t)))
b2064e08
BW
557 (or message
558 (setq message (mh-get-msg-num t)))
c26cf6c8
RS
559 (save-window-excursion
560 (let ((folder mh-current-folder)
c3d9274a 561 (draft (mh-read-draft "redistribution"
b2064e08
BW
562 (if mh-redist-full-contents-flag
563 (mh-msg-filename message)
c3d9274a
BW
564 nil)
565 nil)))
c26cf6c8
RS
566 (mh-goto-header-end 0)
567 (insert "Resent-To: " to "\n")
568 (if (not (equal cc "")) (insert "Resent-cc: " cc "\n"))
924df208
BW
569 (mh-clean-msg-header
570 (point-min)
571 "^Message-Id:\\|^Received:\\|^Return-Path:\\|^Sender:\\|^Date:\\|^From:"
572 nil)
c26cf6c8
RS
573 (save-buffer)
574 (message "Redistributing...")
924df208
BW
575 (let ((env "mhdist=1"))
576 ;; Setup environment...
b2064e08
BW
577 (setq env (concat env " mhaltmsg="
578 (if mh-redist-full-contents-flag
579 buffer-file-name
580 (mh-msg-filename message folder))))
581 (unless mh-redist-full-contents-flag
924df208
BW
582 (setq env (concat env " mhannotate=1")))
583 ;; Redistribute...
584 (if mh-redist-background
585 (mh-exec-cmd-env-daemon env mh-send-prog nil buffer-file-name)
586 (mh-exec-cmd-error env mh-send-prog "-push" buffer-file-name))
587 ;; Annotate...
b2064e08 588 (mh-annotate-msg message folder mh-note-dist
924df208
BW
589 "-component" "Resent:"
590 "-text" (format "\"%s %s\"" to cc)))
c26cf6c8
RS
591 (kill-buffer draft)
592 (message "Redistributing...done"))))
593
c3d9274a 594;;;###mh-autoload
bdcfe844 595(defun mh-reply (message &optional reply-to includep)
b2064e08 596 "Reply to a MESSAGE.
f0d73c14 597
2dcf34f9
BW
598When you reply to a message, you are first prompted with \"Reply
599to whom?\" (unless the optional argument REPLY-TO is provided).
600You have several choices here.
b2064e08
BW
601
602 Response Reply Goes To
603
72cf2f2e 604 from The person who sent the message. This is the
2dcf34f9 605 default, so <RET> is sufficient.
b2064e08
BW
606
607 to Replies to the sender, plus all recipients in the
608 \"To:\" header field.
609
72cf2f2e
BW
610 all cc Forms a reply to the addresses in the
611 \"Mail-Followup-To:\" header field if one
612 exists; otherwise forms a reply to the sender,
613 plus all recipients.
b2064e08 614
2dcf34f9
BW
615Depending on your answer, \"repl\" is given a different argument
616to form your reply. Specifically, a choice of \"from\" or none at
617all runs \"repl -nocc all\", and a choice of \"to\" runs \"repl
618-cc to\". Finally, either \"cc\" or \"all\" runs \"repl -cc all
619-nocc me\".
b2064e08 620
2dcf34f9
BW
621Two windows are then created. One window contains the message to
622which you are replying in an MH-Show buffer. Your draft, in
72cf2f2e
BW
623MH-Letter mode (*note `mh-letter-mode'), is in the other window.
624If the reply draft was not one that you expected, check the
625things that affect the behavior of \"repl\" which include the
626\"repl:\" profile component and the \"replcomps\" and
627\"replgroupcomps\" files.
b2064e08 628
2dcf34f9
BW
629If you supply a prefix argument INCLUDEP, the message you are
630replying to is inserted in your reply after having first been run
631through \"mhl\" with the format file \"mhl.reply\".
b2064e08 632
2dcf34f9
BW
633Alternatively, you can customize the option `mh-yank-behavior'
634and choose one of its \"Automatically\" variants to do the same
635thing. If you do so, the prefix argument has no effect.
b2064e08 636
2dcf34f9
BW
637Another way to include the message automatically in your draft is
638to use \"repl: -filter repl.filter\" in your MH profile.
b2064e08 639
2dcf34f9
BW
640If you wish to customize the header or other parts of the reply
641draft, please see \"repl\" and \"mh-format\".
b2064e08 642
2dcf34f9
BW
643See also `mh-reply-show-message-flag',
644`mh-reply-default-reply-to', and `mh-send'."
bdcfe844
BW
645 (interactive (list
646 (mh-get-msg-num t)
647 (let ((minibuffer-help-form
648 "from => Sender only\nto => Sender and primary recipients\ncc or all => Sender and all recipients"))
649 (or mh-reply-default-reply-to
078cb314 650 (completing-read "Reply to whom (default from): "
bdcfe844
BW
651 '(("from") ("to") ("cc") ("all"))
652 nil
653 t)))
654 current-prefix-arg))
655 (let* ((folder mh-current-folder)
656 (show-buffer mh-show-buffer)
657 (config (current-window-configuration))
658 (group-reply (or (equal reply-to "cc") (equal reply-to "all")))
d1c1d7c1 659 (form-file (cond ((and (mh-variant-p 'nmh 'gnu-mh) group-reply
bdcfe844
BW
660 (stringp mh-repl-group-formfile))
661 mh-repl-group-formfile)
662 ((stringp mh-repl-formfile) mh-repl-formfile)
663 (t nil))))
664 (message "Composing a reply...")
665 (mh-exec-cmd "repl" "-build" "-noquery" "-nodraftfolder"
666 (if form-file
667 (list "-form" form-file))
668 mh-current-folder message
669 (cond ((or (equal reply-to "from") (equal reply-to ""))
670 '("-nocc" "all"))
671 ((equal reply-to "to")
672 '("-cc" "to"))
d1c1d7c1 673 (group-reply (if (mh-variant-p 'nmh 'gnu-mh)
bdcfe844
BW
674 '("-group" "-nocc" "me")
675 '("-cc" "all" "-nocc" "me"))))
0c47b17c
BW
676 (cond ((or (eq mh-yank-behavior 'autosupercite)
677 (eq mh-yank-behavior 'autoattrib))
c3d9274a
BW
678 '("-noformat"))
679 (includep '("-filter" "mhl.reply"))
680 (t '())))
bdcfe844
BW
681 (let ((draft (mh-read-draft "reply"
682 (expand-file-name "reply" mh-user-path)
683 t)))
684 (delete-other-windows)
685 (save-buffer)
a1506d29 686
bdcfe844
BW
687 (let ((to (mh-get-header-field "To:"))
688 (subject (mh-get-header-field "Subject:"))
689 (cc (mh-get-header-field "Cc:")))
690 (goto-char (point-min))
691 (mh-goto-header-end 1)
692 (or includep
693 (not mh-reply-show-message-flag)
694 (mh-in-show-buffer (show-buffer)
695 (mh-display-msg message folder)))
696 (mh-add-msgs-to-seq message 'answered t)
697 (message "Composing a reply...done")
698 (mh-compose-and-send-mail draft "" folder message to subject cc
699 mh-note-repl "Replied:" config))
0c47b17c
BW
700 (when (and (or (eq 'autosupercite mh-yank-behavior)
701 (eq 'autoattrib mh-yank-behavior))
bdcfe844
BW
702 (eq (mh-show-buffer-message-number) mh-sent-from-msg))
703 (undo-boundary)
704 (mh-yank-cur-msg))
705 (mh-letter-mode-message))))
c26cf6c8 706
c3d9274a 707;;;###mh-autoload
c26cf6c8 708(defun mh-send (to cc subject)
b2064e08
BW
709 "Compose a message.
710
2dcf34f9
BW
711Your letter appears in an Emacs buffer whose mode is
712MH-Letter (see `mh-letter-mode').
b2064e08 713
2dcf34f9
BW
714The arguments TO, CC, and SUBJECT can be used to prefill the
715draft fields or suppress the prompts if `mh-compose-prompt-flag'
716is on. They are also passed to the function set in the option
717`mh-compose-letter-function'.
b2064e08
BW
718
719See also `mh-insert-x-mailer-flag' and `mh-letter-mode-hook'.
720
2dcf34f9
BW
721Outside of an MH-Folder buffer (`mh-folder-mode'), you must call
722either \\[mh-smail] or \\[mh-smail-other-window] to compose a new
723message."
c26cf6c8 724 (interactive (list
a66894d8
BW
725 (mh-interactive-read-address "To: ")
726 (mh-interactive-read-address "Cc: ")
727 (mh-interactive-read-string "Subject: ")))
c26cf6c8
RS
728 (let ((config (current-window-configuration)))
729 (delete-other-windows)
730 (mh-send-sub to cc subject config)))
731
dda00b2c
BW
732\f
733
734;;; Support Routines
735
736(defun mh-interactive-read-address (prompt)
737 "Read an address.
738If `mh-compose-prompt-flag' is non-nil, then read an address with
739PROMPT.
740Otherwise return the empty string."
741 (if mh-compose-prompt-flag (mh-read-address prompt) ""))
742
743(defun mh-interactive-read-string (prompt)
744 "Read a string.
745If `mh-compose-prompt-flag' is non-nil, then read a string with
746PROMPT.
747Otherwise return the empty string."
748 (if mh-compose-prompt-flag (read-string prompt) ""))
749
c3d9274a 750;;;###mh-autoload
dda00b2c
BW
751(defun mh-show-buffer-message-number (&optional buffer)
752 "Message number of displayed message in corresponding show buffer.
b2064e08 753
dda00b2c
BW
754Return nil if show buffer not displayed.
755If in `mh-letter-mode', don't display the message number being replied
756to, but rather the message number of the show buffer associated with
757our originating folder buffer.
758Optional argument BUFFER can be used to specify the buffer."
759 (save-excursion
760 (if buffer
761 (set-buffer buffer))
762 (cond ((eq major-mode 'mh-show-mode)
763 (let ((number-start (mh-search-from-end ?/ buffer-file-name)))
764 (string-to-number (substring buffer-file-name
765 (1+ number-start)))))
766 ((and (eq major-mode 'mh-folder-mode)
767 mh-show-buffer
768 (get-buffer mh-show-buffer))
769 (mh-show-buffer-message-number mh-show-buffer))
770 ((and (eq major-mode 'mh-letter-mode)
771 mh-sent-from-folder
772 (get-buffer mh-sent-from-folder))
773 (mh-show-buffer-message-number mh-sent-from-folder))
774 (t
775 nil))))
c26cf6c8 776
c26cf6c8 777(defun mh-send-sub (to cc subject config)
bdcfe844
BW
778 "Do the real work of composing and sending a letter.
779Expects the TO, CC, and SUBJECT fields as arguments.
780CONFIG is the window configuration before sending mail."
c26cf6c8 781 (let ((folder mh-current-folder)
c3d9274a 782 (msg-num (mh-get-msg-num nil)))
c26cf6c8
RS
783 (message "Composing a message...")
784 (let ((draft (mh-read-draft
c3d9274a
BW
785 "message"
786 (let (components)
787 (cond
788 ((file-exists-p
789 (setq components
790 (expand-file-name mh-comp-formfile mh-user-path)))
791 components)
792 ((file-exists-p
793 (setq components
794 (expand-file-name mh-comp-formfile mh-lib)))
795 components)
c3d9274a 796 (t
05227fbe
BW
797 (error "Can't find %s in %s or %s"
798 mh-comp-formfile mh-user-path mh-lib))))
c3d9274a 799 nil)))
c26cf6c8
RS
800 (mh-insert-fields "To:" to "Subject:" subject "Cc:" cc)
801 (goto-char (point-max))
c26cf6c8 802 (mh-compose-and-send-mail draft "" folder msg-num
c3d9274a
BW
803 to subject cc
804 nil nil config)
a66894d8
BW
805 (mh-letter-mode-message)
806 (mh-letter-adjust-point))))
c26cf6c8
RS
807
808(defun mh-read-draft (use initial-contents delete-contents-file)
bdcfe844 809 "Read draft file into a draft buffer and make that buffer the current one.
2dcf34f9
BW
810
811USE is a message used for prompting about the intended use of the
812message.
bdcfe844 813INITIAL-CONTENTS is filename that is read into an empty buffer, or nil
2dcf34f9 814if buffer should not be modified. Delete the initial-contents file if
bdcfe844
BW
815DELETE-CONTENTS-FILE flag is set.
816Returns the draft folder's name.
2dcf34f9
BW
817If the draft folder facility is enabled in ~/.mh_profile, a new buffer
818is used each time and saved in the draft folder. The draft file can
819then be reused."
c26cf6c8 820 (cond (mh-draft-folder
c3d9274a
BW
821 (let ((orig-default-dir default-directory)
822 (draft-file-name (mh-new-draft-name)))
823 (pop-to-buffer (generate-new-buffer
824 (format "draft-%s"
825 (file-name-nondirectory draft-file-name))))
826 (condition-case ()
827 (insert-file-contents draft-file-name t)
828 (file-error))
829 (setq default-directory orig-default-dir)))
830 (t
831 (let ((draft-name (expand-file-name "draft" mh-user-path)))
832 (pop-to-buffer "draft") ; Create if necessary
833 (if (buffer-modified-p)
834 (if (y-or-n-p "Draft has been modified; kill anyway? ")
835 (set-buffer-modified-p nil)
836 (error "Draft preserved")))
837 (setq buffer-file-name draft-name)
838 (clear-visited-file-modtime)
839 (unlock-buffer)
840 (cond ((and (file-exists-p draft-name)
841 (not (equal draft-name initial-contents)))
842 (insert-file-contents draft-name)
843 (delete-file draft-name))))))
c26cf6c8 844 (cond ((and initial-contents
c3d9274a
BW
845 (or (zerop (buffer-size))
846 (if (y-or-n-p
847 (format "A draft exists. Use for %s? " use))
848 (if mh-error-if-no-draft
849 (error "A prior draft exists"))
850 t)))
851 (erase-buffer)
852 (insert-file-contents initial-contents)
853 (if delete-contents-file (delete-file initial-contents))))
c26cf6c8
RS
854 (auto-save-mode 1)
855 (if mh-draft-folder
c3d9274a 856 (save-buffer)) ; Do not reuse draft name
c26cf6c8
RS
857 (buffer-name))
858
c26cf6c8 859(defun mh-new-draft-name ()
bdcfe844 860 "Return the pathname of folder for draft messages."
c26cf6c8
RS
861 (save-excursion
862 (mh-exec-cmd-quiet t "mhpath" mh-draft-folder "new")
863 (buffer-substring (point-min) (1- (point-max)))))
864
c26cf6c8 865(defun mh-insert-fields (&rest name-values)
bdcfe844
BW
866 "Insert the NAME-VALUES pairs in the current buffer.
867If the field exists, append the value to it.
868Do not insert any pairs whose value is the empty string."
c26cf6c8
RS
869 (let ((case-fold-search t))
870 (while name-values
871 (let ((field-name (car name-values))
c3d9274a 872 (value (car (cdr name-values))))
f0d73c14
BW
873 (if (not (string-match "^.*:$" field-name))
874 (setq field-name (concat field-name ":")))
a2c30782
BW
875 (cond ((or (null value)
876 (equal value ""))
c3d9274a
BW
877 nil)
878 ((mh-position-on-field field-name)
879 (insert " " (or value "")))
880 (t
881 (insert field-name " " value "\n")))
882 (setq name-values (cdr (cdr name-values)))))))
c26cf6c8 883
dda00b2c
BW
884(defun mh-compose-and-send-mail (draft send-args
885 sent-from-folder sent-from-msg
886 to subject cc
887 annotate-char annotate-field
888 config)
889 "Edit and compose a draft message in buffer DRAFT and send or save it.
890SEND-ARGS is the argument passed to the send command.
891SENT-FROM-FOLDER is buffer containing scan listing of current folder,
892or nil if none exists.
893SENT-FROM-MSG is the message number or sequence name or nil.
894The TO, SUBJECT, and CC fields are passed to the
895`mh-compose-letter-function'.
896If ANNOTATE-CHAR is non-null, it is used to notate the scan listing of
897the message. In that case, the ANNOTATE-FIELD is used to build a
898string for `mh-annotate-msg'.
899CONFIG is the window configuration to restore after sending the
900letter."
901 (pop-to-buffer draft)
902 (mh-letter-mode)
847b8219 903
dda00b2c
BW
904 ;; Insert identity.
905 (mh-insert-identity mh-identity-default t)
906 (mh-identity-make-menu)
907 (mh-identity-add-menu)
c26cf6c8 908
dda00b2c
BW
909 ;; Insert extra fields.
910 (mh-insert-x-mailer)
911 (mh-insert-x-face)
c26cf6c8 912
dda00b2c 913 (mh-letter-hide-all-skipped-fields)
924df208 914
dda00b2c
BW
915 (setq mh-sent-from-folder sent-from-folder)
916 (setq mh-sent-from-msg sent-from-msg)
917 (setq mh-send-args send-args)
918 (setq mh-annotate-char annotate-char)
919 (setq mh-annotate-field annotate-field)
920 (setq mh-previous-window-config config)
921 (setq mode-line-buffer-identification (list " {%b}"))
922 (mh-logo-display)
923 (mh-make-local-hook 'kill-buffer-hook)
924 (add-hook 'kill-buffer-hook 'mh-tidy-draft-buffer nil t)
16b9a476 925 (run-hook-with-args 'mh-compose-letter-function to subject cc))
bdcfe844 926
a1b4049d 927(defun mh-insert-x-mailer ()
bdcfe844
BW
928 "Append an X-Mailer field to the header.
929The versions of MH-E, Emacs, and MH are shown."
a1b4049d 930 ;; Lazily initialize mh-x-mailer-string.
a66894d8 931 (when (and mh-insert-x-mailer-flag (null mh-x-mailer-string))
f0d73c14
BW
932 (setq mh-x-mailer-string
933 (format "MH-E %s; %s; %sEmacs %s"
934 mh-version mh-variant-in-use
a3269bc4
DN
935 (if (featurep 'xemacs) "X" "GNU ")
936 (cond ((not (featurep 'xemacs))
d5468dff
BW
937 (string-match "[0-9]+\\.[0-9]+\\(\\.[0-9]+\\)?"
938 emacs-version)
939 (match-string 0 emacs-version))
f0d73c14
BW
940 ((string-match "[0-9.]*\\( +\([ a-z]+[0-9]+\)\\)?"
941 emacs-version)
942 (match-string 0 emacs-version))
943 (t (format "%s.%s" emacs-major-version
944 emacs-minor-version))))))
a1b4049d
BW
945 ;; Insert X-Mailer, but only if it doesn't already exist.
946 (save-excursion
a66894d8
BW
947 (when (and mh-insert-x-mailer-flag
948 (null (mh-goto-header-field "X-Mailer")))
c3d9274a 949 (mh-insert-fields "X-Mailer:" mh-x-mailer-string))))
a1b4049d 950
dda00b2c
BW
951(defun mh-insert-x-face ()
952 "Append X-Face, Face or X-Image-URL field to header.
953If the field already exists, this function does nothing."
954 (when (and (file-exists-p mh-x-face-file)
955 (file-readable-p mh-x-face-file))
956 (save-excursion
957 (unless (or (mh-position-on-field "X-Face")
958 (mh-position-on-field "Face")
959 (mh-position-on-field "X-Image-URL"))
960 (save-excursion
961 (goto-char (+ (point) (cadr (insert-file-contents mh-x-face-file))))
962 (if (not (looking-at "^"))
963 (insert "\n")))
964 (unless (looking-at "\\(X-Face\\|Face\\|X-Image-URL\\): ")
965 (insert "X-Face: "))))))
966
dda00b2c
BW
967(defun mh-tidy-draft-buffer ()
968 "Run when a draft buffer is destroyed."
969 (let ((buffer (get-buffer mh-recipients-buffer)))
970 (if buffer
971 (kill-buffer buffer))))
972
973(defun mh-letter-mode-message ()
974 "Display a help message for users of `mh-letter-mode'.
975This should be the last function called when composing the draft."
976 (message "%s" (substitute-command-keys
977 (concat "Type \\[mh-send-letter] to send message, "
978 "\\[mh-help] for help"))))
979
980(defun mh-letter-adjust-point ()
981 "Move cursor to first header field if are using the no prompt mode."
982 (unless mh-compose-prompt-flag
983 (goto-char (point-max))
984 (mh-letter-next-header-field)))
985
aad5673d
SG
986(defun mh-annotate-msg (msg folder note &rest args)
987 "Mark MSG in FOLDER with character NOTE and annotate message with ARGS.
662c14da 988MSG can be a message number, a list of message numbers, or a sequence.
aad5673d
SG
989The hook `mh-annotate-msg-hook' is run after annotating; see its
990documentation for variables it can use."
991 (apply 'mh-exec-cmd "anno" folder
dda00b2c
BW
992 (if (listp msg) (append msg args) (cons msg args)))
993 (save-excursion
aad5673d
SG
994 (cond ((get-buffer folder) ; Buffer may be deleted
995 (set-buffer folder)
dda00b2c
BW
996 (mh-iterate-on-range nil msg
997 (mh-notate nil note
aad5673d
SG
998 (+ mh-cmd-note mh-scan-field-destination-offset))))))
999 (let ((mh-current-folder folder)
1000 ;; mh-annotate-list is a sequence name or a list of message numbers
1001 (mh-annotate-list (if (numberp msg) (list msg) msg)))
1002 (run-hooks 'mh-annotate-msg-hook)))
dda00b2c 1003
dda00b2c
BW
1004(defun mh-insert-header-separator ()
1005 "Insert `mh-mail-header-separator', if absent."
1006 (save-excursion
1007 (goto-char (point-min))
1008 (rfc822-goto-eoh)
1009 (if (looking-at "$")
1010 (insert mh-mail-header-separator))))
bdcfe844 1011
a66894d8
BW
1012;;;###mh-autoload
1013(defun mh-insert-auto-fields (&optional non-interactive)
3b463df0 1014 "Insert custom fields if recipient is found in `mh-auto-fields-list'.
a66894d8 1015
3fbc098d
BW
1016Once the header contains one or more recipients, you may run this
1017command to insert these fields manually. However, if you use this
1018command, the automatic insertion when the message is sent is
1019disabled.
f0d73c14 1020
3fbc098d
BW
1021In a program, set buffer-local `mh-insert-auto-fields-done-local'
1022if header fields were added. If NON-INTERACTIVE is non-nil,
1023perform actions quietly and only if
1024`mh-insert-auto-fields-done-local' is nil. Return t if fields
1025added; otherwise return nil."
a66894d8 1026 (interactive)
f0d73c14
BW
1027 (when (or (not non-interactive)
1028 (not mh-insert-auto-fields-done-local))
a66894d8 1029 (save-excursion
f0d73c14
BW
1030 (when (and (or (mh-goto-header-field "To:")
1031 (mh-goto-header-field "cc:")))
1032 (let ((list mh-auto-fields-list)
1033 (fields-inserted nil))
a66894d8
BW
1034 (while list
1035 (let ((regexp (nth 0 (car list)))
1036 (entries (nth 1 (car list))))
1037 (when (mh-regexp-in-field-p regexp "To:" "cc:")
1038 (setq mh-insert-auto-fields-done-local t)
f0d73c14 1039 (setq fields-inserted t)
a66894d8 1040 (if (not non-interactive)
f0d73c14 1041 (message "Fields for %s added" regexp))
a66894d8
BW
1042 (let ((entry-list entries))
1043 (while entry-list
1044 (let ((field (caar entry-list))
1045 (value (cdar entry-list)))
1046 (cond
f0d73c14 1047 ((equal ":identity" field)
dda00b2c
BW
1048 (when
1049 ;;(and (not mh-identity-local)
a05fcb7d 1050 ;; Bug 1204506. But do we need to be able
dda00b2c
BW
1051 ;; to set an identity manually that won't be
1052 ;; overridden by mh-insert-auto-fields?
1053 (assoc value mh-identity-list)
1054 ;;)
a66894d8
BW
1055 (mh-insert-identity value)))
1056 (t
1057 (mh-modify-header-field field value
1058 (equal field "From")))))
1059 (setq entry-list (cdr entry-list))))))
f0d73c14
BW
1060 (setq list (cdr list)))
1061 fields-inserted)))))
924df208
BW
1062
1063(defun mh-modify-header-field (field value &optional overwrite-flag)
1064 "To header FIELD add VALUE.
2dcf34f9
BW
1065If OVERWRITE-FLAG is non-nil then the old value, if present, is
1066discarded."
a66894d8
BW
1067 (cond ((and overwrite-flag
1068 (mh-goto-header-field (concat field ":")))
1069 (insert " " value)
d5dc8c56 1070 (delete-region (point) (mh-line-end-position)))
a66894d8
BW
1071 ((and (not overwrite-flag)
1072 (mh-regexp-in-field-p (concat "\\b" value "\\b") field))
1073 ;; Already there, do nothing.
1074 )
1075 ((and (not overwrite-flag)
1076 (mh-goto-header-field (concat field ":")))
1077 (insert " " value ","))
1078 (t
1079 (mh-goto-header-end 0)
1080 (insert field ": " value "\n"))))
1081
dda00b2c
BW
1082(defun mh-regexp-in-field-p (regexp &rest fields)
1083 "Non-nil means REGEXP was found in FIELDS."
1084 (save-excursion
1085 (let ((search-result nil)
1086 (field))
1087 (while fields
1088 (setq field (car fields))
1089 (if (and (mh-goto-header-field field)
1090 (re-search-forward
1091 regexp (save-excursion (mh-header-field-end)(point)) t))
1092 (setq fields nil
1093 search-result t)
1094 (setq fields (cdr fields))))
1095 search-result)))
f0d73c14
BW
1096
1097(defun mh-ascii-buffer-p ()
1098 "Check if current buffer is entirely composed of ASCII.
2dcf34f9
BW
1099The function doesn't work for XEmacs since `find-charset-region'
1100doesn't exist there."
f0d73c14
BW
1101 (loop for charset in (mh-funcall-if-exists
1102 find-charset-region (point-min) (point-max))
1103 unless (eq charset 'ascii) return nil
1104 finally return t))
c26cf6c8 1105
bdcfe844
BW
1106(provide 'mh-comp)
1107
cee9f5c6
BW
1108;; Local Variables:
1109;; indent-tabs-mode: nil
1110;; sentence-end-double-space: nil
1111;; End:
60370d40 1112
cee9f5c6 1113;; arch-tag: 62865511-e610-4923-b0b5-f45a8ab70a34
60370d40 1114;;; mh-comp.el ends here