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