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