*** empty log message ***
[gnus] / lisp / message.el
1 ;;; message.el --- composing mail and news messages
2 ;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
3
4 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
5 ;; Keywords: mail, news
6
7 ;; This file is part of GNU Emacs.
8
9 ;; GNU Emacs is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
13
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
21 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
23
24 ;;; Commentary:
25
26 ;; This mode provides mail-sending facilities from within Emacs.  It
27 ;; consists mainly of large chunks of code from the sendmail.el,
28 ;; gnus-msg.el and rnewspost.el files.
29
30 ;;; Code:
31
32 (eval-when-compile (require 'cl))
33
34 (require 'mailheader)
35 (require 'nnheader)
36 (require 'timezone)
37 (require 'easymenu)
38 (require 'custom)
39 (if (string-match "XEmacs\\|Lucid" emacs-version)
40     (require 'mail-abbrevs)
41   (require 'mailabbrev))
42
43 (defgroup message '((user-mail-address custom-variable)
44                     (user-full-name custom-variable))
45   "Mail and news message composing."
46   :link '(custom-manual "(message)Top")
47   :group 'mail
48   :group 'news)
49
50 (put 'user-mail-address 'custom-type 'string)
51 (put 'user-full-name 'custom-type 'string)
52
53 (defgroup message-various nil
54   "Various Message Variables"
55   :link '(custom-manual "(message)Various Message Variables")
56   :group 'message)
57
58 (defgroup message-buffers nil
59   "Message Buffers"
60   :link '(custom-manual "(message)Message Buffers")
61   :group 'message)
62
63 (defgroup message-sending nil
64   "Message Sending"
65   :link '(custom-manual "(message)Sending Variables")
66   :group 'message)
67
68 (defgroup message-interface nil
69   "Message Interface"
70   :link '(custom-manual "(message)Interface")
71   :group 'message)
72
73 (defgroup message-forwarding nil
74   "Message Forwarding"
75   :link '(custom-manual "(message)Forwarding")
76   :group 'message-interface)
77
78 (defgroup message-insertion nil
79   "Message Insertion"
80   :link '(custom-manual "(message)Insertion")
81   :group 'message)
82
83 (defgroup message-headers nil
84   "Message Headers"
85   :link '(custom-manual "(message)Message Headers")
86   :group 'message)
87
88 (defgroup message-news nil
89   "Composing News Messages"
90   :group 'message)
91
92 (defgroup message-mail nil
93   "Composing Mail Messages"
94   :group 'message)
95
96 (defgroup message-faces nil
97   "Faces used for message composing."
98   :group 'message
99   :group 'faces)
100
101 (defcustom message-directory "~/Mail/"
102   "*Directory from which all other mail file variables are derived."
103   :group 'message-various
104   :type 'directory)
105
106 (defcustom message-max-buffers 10
107   "*How many buffers to keep before starting to kill them off."
108   :group 'message-buffers
109   :type 'integer)
110
111 (defcustom message-send-rename-function nil
112   "Function called to rename the buffer after sending it."
113   :group 'message-buffers
114   :type 'function)
115
116 (defcustom message-fcc-handler-function 'message-output
117   "*A function called to save outgoing articles.
118 This function will be called with the name of the file to store the
119 article in.  The default function is `message-output' which saves in Unix
120 mailbox format."
121   :type '(radio (function-item message-output)
122                 (function :tag "Other"))
123   :group 'message-sending)
124
125 (defcustom message-courtesy-message
126   "The following message is a courtesy copy of an article\nthat has been posted to %s as well.\n\n"
127   "*This is inserted at the start of a mailed copy of a posted message.
128 If the string contains the format spec \"%s\", the Newsgroups
129 the article has been posted to will be inserted there.
130 If this variable is nil, no such courtesy message will be added."
131   :group 'message-sending
132   :type 'string)
133
134 (defcustom message-ignored-bounced-headers "^\\(Received\\|Return-Path\\):"
135   "*Regexp that matches headers to be removed in resent bounced mail."
136   :group 'message-interface
137   :type 'regexp)
138
139 ;;;###autoload
140 (defcustom message-from-style 'default
141   "*Specifies how \"From\" headers look.
142
143 If `nil', they contain just the return address like:
144         king@grassland.com
145 If `parens', they look like:
146         king@grassland.com (Elvis Parsley)
147 If `angles', they look like:
148         Elvis Parsley <king@grassland.com>
149
150 Otherwise, most addresses look like `angles', but they look like
151 `parens' if `angles' would need quoting and `parens' would not."
152   :type '(choice (const :tag "simple" nil)
153                  (const parens)
154                  (const angles)
155                  (const default))
156   :group 'message-headers)
157
158 (defcustom message-syntax-checks nil
159   ; Guess this one shouldn't be easy to customize...
160   "*Controls what syntax checks should not be performed on outgoing posts.
161 To disable checking of long signatures, for instance, add
162  `(signature . disabled)' to this list.
163
164 Don't touch this variable unless you really know what you're doing.
165
166 Checks include subject-cmsg multiple-headers sendsys message-id from
167 long-lines control-chars size new-text redirected-followup signature
168 approved sender empty empty-headers message-id from subject
169 shorten-followup-to existing-newsgroups buffer-file-name unchanged."
170   :group 'message-news)
171
172 (defcustom message-required-news-headers
173   '(From Newsgroups Subject Date Message-ID
174          (optional . Organization) Lines
175          (optional . X-Newsreader))
176   "*Headers to be generated or prompted for when posting an article.
177 RFC977 and RFC1036 require From, Date, Newsgroups, Subject,
178 Message-ID.  Organization, Lines, In-Reply-To, Expires, and
179 X-Newsreader are optional.  If don't you want message to insert some
180 header, remove it from this list."
181   :group 'message-news
182   :group 'message-headers
183   :type '(repeat sexp))
184
185 (defcustom message-required-mail-headers
186   '(From Subject Date (optional . In-Reply-To) Message-ID Lines
187          (optional . X-Mailer))
188   "*Headers to be generated or prompted for when mailing a message.
189 RFC822 required that From, Date, To, Subject and Message-ID be
190 included.  Organization, Lines and X-Mailer are optional."
191   :group 'message-mail
192   :group 'message-headers
193   :type '(repeat sexp))
194
195 (defcustom message-deletable-headers '(Message-ID Date Lines)
196   "Headers to be deleted if they already exist and were generated by message previously."
197   :group 'message-headers
198   :type 'sexp)
199
200 (defcustom message-ignored-news-headers
201   "^NNTP-Posting-Host:\\|^Xref:\\|^[BGF]cc:\\|^Resent-Fcc:"
202   "*Regexp of headers to be removed unconditionally before posting."
203   :group 'message-news
204   :group 'message-headers
205   :type 'regexp)
206
207 (defcustom message-ignored-mail-headers "^[GF]cc:\\|^Resent-Fcc:\\|^Xref:"
208   "*Regexp of headers to be removed unconditionally before mailing."
209   :group 'message-mail
210   :group 'message-headers
211   :type 'regexp)
212
213 (defcustom message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|^X-Trace:\\|^X-Complaints-To:\\|Return-Path:\\|^Supersedes:\\|^X-Trace:\\|^X-Complaints-To:"
214   "*Header lines matching this regexp will be deleted before posting.
215 It's best to delete old Path and Date headers before posting to avoid
216 any confusion."
217   :group 'message-interface
218   :type 'regexp)
219
220 (defcustom message-subject-re-regexp "^[ \t]*\\([Rr][Ee]:[ \t]*\\)*[ \t]*"
221   "*Regexp matching \"Re: \" in the subject line."
222   :group 'message-various
223   :type 'regexp)
224
225 ;;;###autoload
226 (defcustom message-signature-separator "^-- *$"
227   "Regexp matching the signature separator."
228   :type 'regexp
229   :group 'message-various)
230
231 (defcustom message-elide-elipsis "\n[...]\n\n"
232   "*The string which is inserted for elided text."
233   :type 'string
234   :group 'message-various)
235
236 (defcustom message-interactive nil
237   "Non-nil means when sending a message wait for and display errors.
238 nil means let mailer mail back a message to report errors."
239   :group 'message-sending
240   :group 'message-mail
241   :type 'boolean)
242
243 (defcustom message-generate-new-buffers t
244   "*Non-nil means that a new message buffer will be created whenever `message-setup' is called.
245 If this is a function, call that function with three parameters:  The type,
246 the to address and the group name.  (Any of these may be nil.)  The function
247 should return the new buffer name."
248   :group 'message-buffers
249   :type '(choice (const :tag "off" nil)
250                  (const :tag "on" t)
251                  (function fun)))
252
253 (defcustom message-kill-buffer-on-exit nil
254   "*Non-nil means that the message buffer will be killed after sending a message."
255   :group 'message-buffers
256   :type 'boolean)
257
258 (defvar gnus-local-organization)
259 (defcustom message-user-organization
260   (or (and (boundp 'gnus-local-organization)
261            (stringp gnus-local-organization)
262            gnus-local-organization)
263       (getenv "ORGANIZATION")
264       t)
265   "*String to be used as an Organization header.
266 If t, use `message-user-organization-file'."
267   :group 'message-headers
268   :type '(choice string
269                  (const :tag "consult file" t)))
270
271 ;;;###autoload
272 (defcustom message-user-organization-file "/usr/lib/news/organization"
273   "*Local news organization file."
274   :type 'file
275   :group 'message-headers)
276
277 (defcustom message-forward-start-separator
278   "------- Start of forwarded message -------\n"
279   "*Delimiter inserted before forwarded messages."
280   :group 'message-forwarding
281   :type 'string)
282
283 (defcustom message-forward-end-separator
284   "------- End of forwarded message -------\n"
285   "*Delimiter inserted after forwarded messages."
286   :group 'message-forwarding
287   :type 'string)
288
289 (defcustom message-signature-before-forwarded-message t
290   "*If non-nil, put the signature before any included forwarded message."
291   :group 'message-forwarding
292   :type 'boolean)
293
294 (defcustom message-included-forward-headers
295   "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-\\|^Message-ID:\\|^References:\\|^Content-Transfer-Encoding:\\|^Content-Type:\\|^Mime-Version:"
296   "*Regexp matching headers to be included in forwarded messages."
297   :group 'message-forwarding
298   :type 'regexp)
299
300 (defcustom message-make-forward-subject-function 
301   'message-forward-subject-author-subject
302  "*A list of functions that are called to generate a subject header for forwarded messages.
303 The subject generated by the previous function is passed into each
304 successive function.
305
306 The provided functions are:
307
308 * message-forward-subject-author-subject (Source of article (author or
309       newsgroup)), in brackets followed by the subject
310 * message-forward-subject-fwd (Subject of article with 'Fwd:' prepended
311       to it."
312  :group 'message-forwarding
313  :type '(radio (function-item message-forward-subject-author-subject)
314                (function-item message-forward-subject-fwd)))
315
316 (defcustom message-wash-forwarded-subjects nil
317   "*If non-nil, try to remove as much old cruft as possible from the subject of messages before generating the new subject of a forward."
318   :group 'message-forwarding
319   :type 'boolean)
320
321 (defcustom message-ignored-resent-headers "^Return-receipt"
322   "*All headers that match this regexp will be deleted when resending a message."
323   :group 'message-interface
324   :type 'regexp)
325
326 (defcustom message-ignored-cited-headers "."
327   "*Delete these headers from the messages you yank."
328   :group 'message-insertion
329   :type 'regexp)
330
331 (defcustom message-cancel-message "I am canceling my own article."
332   "Message to be inserted in the cancel message."
333   :group 'message-interface
334   :type 'string)
335
336 ;; Useful to set in site-init.el
337 ;;;###autoload
338 (defcustom message-send-mail-function 'message-send-mail-with-sendmail
339   "Function to call to send the current buffer as mail.
340 The headers should be delimited by a line whose contents match the
341 variable `mail-header-separator'.
342
343 Legal values include `message-send-mail-with-sendmail' (the default),
344 `message-send-mail-with-mh', `message-send-mail-with-qmail' and
345 `smtpmail-send-it'."
346   :type '(radio (function-item message-send-mail-with-sendmail)
347                 (function-item message-send-mail-with-mh)
348                 (function-item message-send-mail-with-qmail)
349                 (function-item smtpmail-send-it)
350                 (function :tag "Other"))
351   :group 'message-sending
352   :group 'message-mail)
353
354 (defcustom message-send-news-function 'message-send-news
355   "Function to call to send the current buffer as news.
356 The headers should be delimited by a line whose contents match the
357 variable `mail-header-separator'."
358   :group 'message-sending
359   :group 'message-news
360   :type 'function)
361
362 (defcustom message-reply-to-function nil
363   "Function that should return a list of headers.
364 This function should pick out addresses from the To, Cc, and From headers
365 and respond with new To and Cc headers."
366   :group 'message-interface
367   :type 'function)
368
369 (defcustom message-wide-reply-to-function nil
370   "Function that should return a list of headers.
371 This function should pick out addresses from the To, Cc, and From headers
372 and respond with new To and Cc headers."
373   :group 'message-interface
374   :type 'function)
375
376 (defcustom message-followup-to-function nil
377   "Function that should return a list of headers.
378 This function should pick out addresses from the To, Cc, and From headers
379 and respond with new To and Cc headers."
380   :group 'message-interface
381   :type 'function)
382
383 (defcustom message-use-followup-to 'ask
384   "*Specifies what to do with Followup-To header.
385 If nil, always ignore the header.  If it is t, use its value, but
386 query before using the \"poster\" value.  If it is the symbol `ask',
387 always query the user whether to use the value.  If it is the symbol
388 `use', always use the value."
389   :group 'message-interface
390   :type '(choice (const :tag "ignore" nil)
391                  (const use)
392                  (const ask)))
393
394 ;; stuff relating to broken sendmail in MMDF
395 (defcustom message-sendmail-f-is-evil nil
396   "*Non-nil means that \"-f username\" should not be added to the sendmail
397 command line, because it is even more evil than leaving it out."
398   :group 'message-sending
399   :type 'boolean)
400
401 ;; qmail-related stuff
402 (defcustom message-qmail-inject-program "/var/qmail/bin/qmail-inject"
403   "Location of the qmail-inject program."
404   :group 'message-sending
405   :type 'file)
406
407 (defcustom message-qmail-inject-args nil
408   "Arguments passed to qmail-inject programs.
409 This should be a list of strings, one string for each argument.
410
411 For e.g., if you wish to set the envelope sender address so that bounces
412 go to the right place or to deal with listserv's usage of that address, you
413 might set this variable to '(\"-f\" \"you@some.where\")."
414   :group 'message-sending
415   :type '(repeat string))
416
417 (defvar gnus-post-method)
418 (defvar gnus-select-method)
419 (defcustom message-post-method
420   (cond ((and (boundp 'gnus-post-method)
421               (listp gnus-post-method)
422               gnus-post-method)
423          gnus-post-method)
424         ((boundp 'gnus-select-method)
425          gnus-select-method)
426         (t '(nnspool "")))
427   "*Method used to post news.
428 Note that when posting from inside Gnus, for instance, this
429 variable isn't used."
430   :group 'message-news
431   :group 'message-sending
432   ;; This should be the `gnus-select-method' widget, but that might
433   ;; create a dependence to `gnus.el'.
434   :type 'sexp)
435
436 (defcustom message-generate-headers-first nil
437   "*If non-nil, generate all possible headers before composing."
438   :group 'message-headers
439   :type 'boolean)
440
441 (defcustom message-setup-hook nil
442   "Normal hook, run each time a new outgoing message is initialized.
443 The function `message-setup' runs this hook."
444   :group 'message-various
445   :type 'hook)
446
447 (defcustom message-signature-setup-hook nil
448   "Normal hook, run each time a new outgoing message is initialized.
449 It is run after the headers have been inserted and before
450 the signature is inserted."
451   :group 'message-various
452   :type 'hook)
453
454 (defcustom message-mode-hook nil
455   "Hook run in message mode buffers."
456   :group 'message-various
457   :type 'hook)
458
459 (defcustom message-header-hook nil
460   "Hook run in a message mode buffer narrowed to the headers."
461   :group 'message-various
462   :type 'hook)
463
464 (defcustom message-header-setup-hook nil
465   "Hook called narrowed to the headers when setting up a message buffer."
466   :group 'message-various
467   :type 'hook)
468
469 ;;;###autoload
470 (defcustom message-citation-line-function 'message-insert-citation-line
471   "*Function called to insert the \"Whomever writes:\" line."
472   :type 'function
473   :group 'message-insertion)
474
475 ;;;###autoload
476 (defcustom message-yank-prefix "> "
477   "*Prefix inserted on the lines of yanked messages.
478 nil means use indentation."
479   :type 'string
480   :group 'message-insertion)
481
482 (defcustom message-indentation-spaces 3
483   "*Number of spaces to insert at the beginning of each cited line.
484 Used by `message-yank-original' via `message-yank-cite'."
485   :group 'message-insertion
486   :type 'integer)
487
488 ;;;###autoload
489 (defcustom message-cite-function 'message-cite-original
490   "*Function for citing an original message.
491 Predefined functions include `message-cite-original' and
492 `message-cite-original-without-signature'.
493 Note that `message-cite-original' uses `mail-citation-hook' if that is non-nil."
494   :type '(radio (function-item message-cite-original)
495                 (function-item sc-cite-original)
496                 (function :tag "Other"))
497   :group 'message-insertion)
498
499 ;;;###autoload
500 (defcustom message-indent-citation-function 'message-indent-citation
501   "*Function for modifying a citation just inserted in the mail buffer.
502 This can also be a list of functions.  Each function can find the
503 citation between (point) and (mark t).  And each function should leave
504 point and mark around the citation text as modified."
505   :type 'function
506   :group 'message-insertion)
507
508 (defvar message-abbrevs-loaded nil)
509
510 ;;;###autoload
511 (defcustom message-signature t
512   "*String to be inserted at the end of the message buffer.
513 If t, the `message-signature-file' file will be inserted instead.
514 If a function, the result from the function will be used instead.
515 If a form, the result from the form will be used instead."
516   :type 'sexp
517   :group 'message-insertion)
518
519 ;;;###autoload
520 (defcustom message-signature-file "~/.signature"
521   "*File containing the text inserted at end of message buffer."
522   :type 'file
523   :group 'message-insertion)
524
525 (defcustom message-distribution-function nil
526   "*Function called to return a Distribution header."
527   :group 'message-news
528   :group 'message-headers
529   :type 'function)
530
531 (defcustom message-expires 14
532   "Number of days before your article expires."
533   :group 'message-news
534   :group 'message-headers
535   :link '(custom-manual "(message)News Headers")
536   :type 'integer)
537
538 (defcustom message-user-path nil
539   "If nil, use the NNTP server name in the Path header.
540 If stringp, use this; if non-nil, use no host name (user name only)."
541   :group 'message-news
542   :group 'message-headers
543   :link '(custom-manual "(message)News Headers")
544   :type '(choice (const :tag "nntp" nil)
545                  (string :tag "name")
546                  (sexp :tag "none" :format "%t" t)))
547
548 (defvar message-reply-buffer nil)
549 (defvar message-reply-headers nil)
550 (defvar message-newsreader nil)
551 (defvar message-mailer nil)
552 (defvar message-sent-message-via nil)
553 (defvar message-checksum nil)
554 (defvar message-send-actions nil
555   "A list of actions to be performed upon successful sending of a message.")
556 (defvar message-exit-actions nil
557   "A list of actions to be performed upon exiting after sending a message.")
558 (defvar message-kill-actions nil
559   "A list of actions to be performed before killing a message buffer.")
560 (defvar message-postpone-actions nil
561   "A list of actions to be performed after postponing a message.")
562
563 (define-widget 'message-header-lines 'text
564   "All header lines must be LFD terminated."
565   :format "%t:%n%v"
566   :valid-regexp "^\\'"
567   :error "All header lines must be newline terminated")
568
569 (defcustom message-default-headers ""
570   "*A string containing header lines to be inserted in outgoing messages.
571 It is inserted before you edit the message, so you can edit or delete
572 these lines."
573   :group 'message-headers
574   :type 'message-header-lines)
575
576 (defcustom message-default-mail-headers ""
577   "*A string of header lines to be inserted in outgoing mails."
578   :group 'message-headers
579   :group 'message-mail
580   :type 'message-header-lines)
581
582 (defcustom message-default-news-headers ""
583   "*A string of header lines to be inserted in outgoing news
584 articles."
585   :group 'message-headers
586   :group 'message-news
587   :type 'message-header-lines)
588
589 ;; Note: could use /usr/ucb/mail instead of sendmail;
590 ;; options -t, and -v if not interactive.
591 (defcustom message-mailer-swallows-blank-line
592   (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)"
593                          system-configuration)
594            (file-readable-p "/etc/sendmail.cf")
595            (let ((buffer (get-buffer-create " *temp*")))
596              (unwind-protect
597                  (save-excursion
598                    (set-buffer buffer)
599                    (insert-file-contents "/etc/sendmail.cf")
600                    (goto-char (point-min))
601                    (let ((case-fold-search nil))
602                      (re-search-forward "^OR\\>" nil t)))
603                (kill-buffer buffer))))
604       ;; According to RFC822, "The field-name must be composed of printable
605       ;; ASCII characters (i. e., characters that have decimal values between
606       ;; 33 and 126, except colon)", i. e., any chars except ctl chars,
607       ;; space, or colon.
608       '(looking-at "[ \t]\\|[][!\"#$%&'()*+,-./0-9;<=>?@A-Z\\\\^_`a-z{|}~]+:"))
609   "*Set this non-nil if the system's mailer runs the header and body together.
610 \(This problem exists on Sunos 4 when sendmail is run in remote mode.)
611 The value should be an expression to test whether the problem will
612 actually occur."
613   :group 'message-sending
614   :type 'sexp)
615
616 ;; Ignore errors in case this is used in Emacs 19.
617 ;; Don't use ignore-errors because this is copied into loaddefs.el.
618 ;;;###autoload
619 (condition-case nil
620     (define-mail-user-agent 'message-user-agent
621       'message-mail 'message-send-and-exit
622       'message-kill-buffer 'message-send-hook)
623   (error nil))
624
625 (defvar message-mh-deletable-headers '(Message-ID Date Lines Sender)
626   "If non-nil, delete the deletable headers before feeding to mh.")
627
628 (defvar message-send-method-alist
629   '((news message-news-p message-send-via-news)
630     (mail message-mail-p message-send-via-mail))
631   "Alist of ways to send outgoing messages.
632 Each element has the form
633
634   \(TYPE PREDICATE FUNCTION)
635
636 where TYPE is a symbol that names the method; PREDICATE is a function
637 called without any parameters to determine whether the message is
638 a message of type TYPE; and FUNCTION is a function to be called if
639 PREDICATE returns non-nil.  FUNCTION is called with one parameter --
640 the prefix.")
641
642 (defvar message-mail-alias-type 'abbrev
643   "*What alias expansion type to use in Message buffers.
644 The default is `abbrev', which uses mailabbrev.  nil switches
645 mail aliases off.")
646
647 (defcustom message-autosave-directory
648   (nnheader-concat message-directory "drafts/")
649   "*Directory where Message autosaves buffers if Gnus isn't running.
650 If nil, Message won't autosave."
651   :group 'message-buffers
652   :type 'directory)
653
654 ;;; Internal variables.
655 ;;; Well, not really internal.
656
657 (defvar message-mode-syntax-table
658   (let ((table (copy-syntax-table text-mode-syntax-table)))
659     (modify-syntax-entry ?% ". " table)
660     table)
661   "Syntax table used while in Message mode.")
662
663 (defvar message-mode-abbrev-table text-mode-abbrev-table
664   "Abbrev table used in Message mode buffers.
665 Defaults to `text-mode-abbrev-table'.")
666 (defgroup message-headers nil
667   "Message headers."
668   :link '(custom-manual "(message)Variables")
669   :group 'message)
670
671 (defface message-header-to-face
672   '((((class color)
673       (background dark))
674      (:foreground "green2" :bold t))
675     (((class color)
676       (background light))
677      (:foreground "MidnightBlue" :bold t))
678     (t
679      (:bold t :italic t)))
680   "Face used for displaying From headers."
681   :group 'message-faces)
682
683 (defface message-header-cc-face
684   '((((class color)
685       (background dark))
686      (:foreground "green4" :bold t))
687     (((class color)
688       (background light))
689      (:foreground "MidnightBlue"))
690     (t
691      (:bold t)))
692   "Face used for displaying Cc headers."
693   :group 'message-faces)
694
695 (defface message-header-subject-face
696   '((((class color)
697       (background dark))
698      (:foreground "green3"))
699     (((class color)
700       (background light))
701      (:foreground "navy blue" :bold t))
702     (t
703      (:bold t)))
704   "Face used for displaying subject headers."
705   :group 'message-faces)
706
707 (defface message-header-newsgroups-face
708   '((((class color)
709       (background dark))
710      (:foreground "yellow" :bold t :italic t))
711     (((class color)
712       (background light))
713      (:foreground "blue4" :bold t :italic t))
714     (t
715      (:bold t :italic t)))
716   "Face used for displaying newsgroups headers."
717   :group 'message-faces)
718
719 (defface message-header-other-face
720   '((((class color)
721       (background dark))
722      (:foreground "#b00000"))
723     (((class color)
724       (background light))
725      (:foreground "steel blue"))
726     (t
727      (:bold t :italic t)))
728   "Face used for displaying newsgroups headers."
729   :group 'message-faces)
730
731 (defface message-header-name-face
732   '((((class color)
733       (background dark))
734      (:foreground "DarkGreen"))
735     (((class color)
736       (background light))
737      (:foreground "cornflower blue"))
738     (t
739      (:bold t)))
740   "Face used for displaying header names."
741   :group 'message-faces)
742
743 (defface message-header-xheader-face
744   '((((class color)
745       (background dark))
746      (:foreground "blue"))
747     (((class color)
748       (background light))
749      (:foreground "blue"))
750     (t
751      (:bold t)))
752   "Face used for displaying X-Header headers."
753   :group 'message-faces)
754
755 (defface message-separator-face
756   '((((class color)
757       (background dark))
758      (:foreground "blue3"))
759     (((class color)
760       (background light))
761      (:foreground "brown"))
762     (t
763      (:bold t)))
764   "Face used for displaying the separator."
765   :group 'message-faces)
766
767 (defface message-cited-text-face
768   '((((class color)
769       (background dark))
770      (:foreground "red"))
771     (((class color)
772       (background light))
773      (:foreground "red"))
774     (t
775      (:bold t)))
776   "Face used for displaying cited text names."
777   :group 'message-faces)
778
779 (defvar message-font-lock-keywords
780   (let* ((cite-prefix "A-Za-z")
781          (cite-suffix (concat cite-prefix "0-9_.@-"))
782          (content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)"))
783     `((,(concat "^\\([Tt]o:\\)" content)
784        (1 'message-header-name-face)
785        (2 'message-header-to-face nil t))
786       (,(concat "^\\(^[GBF]?[Cc][Cc]:\\|^[Rr]eply-[Tt]o:\\)" content)
787        (1 'message-header-name-face)
788        (2 'message-header-cc-face nil t))
789       (,(concat "^\\([Ss]ubject:\\)" content)
790        (1 'message-header-name-face)
791        (2 'message-header-subject-face nil t))
792       (,(concat "^\\([Nn]ewsgroups:\\|Followup-[Tt]o:\\)" content)
793        (1 'message-header-name-face)
794        (2 'message-header-newsgroups-face nil t))
795       (,(concat "^\\([A-Z][^: \n\t]+:\\)" content)
796        (1 'message-header-name-face)
797        (2 'message-header-other-face nil t))
798       (,(concat "^\\(X-[A-Za-z0-9-]+\\|In-Reply-To\\):" content)
799        (1 'message-header-name-face)
800        (2 'message-header-name-face))
801       ,@(if (and mail-header-separator
802                  (not (equal mail-header-separator "")))
803             `((,(concat "^\\(" (regexp-quote mail-header-separator) "\\)$")
804                1 'message-separator-face))
805           nil)
806       (,(concat "^[ \t]*"
807                 "\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
808                 "[:>|}].*")
809        (0 'message-cited-text-face))))
810   "Additional expressions to highlight in Message mode.")
811
812 ;; XEmacs does it like this.  For Emacs, we have to set the
813 ;; `font-lock-defaults' buffer-local variable.
814 (put 'message-mode 'font-lock-defaults '(message-font-lock-keywords t))
815
816 (defvar message-face-alist
817   '((bold . bold-region)
818     (underline . underline-region)
819     (default . (lambda (b e)
820                  (unbold-region b e)
821                  (ununderline-region b e))))
822   "Alist of mail and news faces for facemenu.
823 The cdr of ech entry is a function for applying the face to a region.")
824
825 (defcustom message-send-hook nil
826   "Hook run before sending messages."
827   :group 'message-various
828   :options '(ispell-message)
829   :type 'hook)
830
831 (defcustom message-send-mail-hook nil
832   "Hook run before sending mail messages."
833   :group 'message-various
834   :type 'hook)
835
836 (defcustom message-send-news-hook nil
837   "Hook run before sending news messages."
838   :group 'message-various
839   :type 'hook)
840
841 (defcustom message-sent-hook nil
842   "Hook run after sending messages."
843   :group 'message-various
844   :type 'hook)
845
846 ;;; Internal variables.
847
848 (defvar message-buffer-list nil)
849 (defvar message-this-is-news nil)
850 (defvar message-this-is-mail nil)
851 (defvar message-draft-article nil)
852
853 ;; Byte-compiler warning
854 (defvar gnus-active-hashtb)
855 (defvar gnus-read-active-file)
856
857 ;;; Regexp matching the delimiter of messages in UNIX mail format
858 ;;; (UNIX From lines), minus the initial ^.  It should be a copy
859 ;;; of rmail.el's rmail-unix-mail-delimiter.
860 (defvar message-unix-mail-delimiter
861   (let ((time-zone-regexp
862          (concat "\\([A-Z]?[A-Z]?[A-Z][A-Z]\\( DST\\)?"
863                  "\\|[-+]?[0-9][0-9][0-9][0-9]"
864                  "\\|"
865                  "\\) *")))
866     (concat
867      "From "
868
869      ;; Many things can happen to an RFC 822 mailbox before it is put into
870      ;; a `From' line.  The leading phrase can be stripped, e.g.
871      ;; `Joe <@w.x:joe@y.z>' -> `<@w.x:joe@y.z>'.  The <> can be stripped, e.g.
872      ;; `<@x.y:joe@y.z>' -> `@x.y:joe@y.z'.  Everything starting with a CRLF
873      ;; can be removed, e.g.
874      ;;         From: joe@y.z (Joe      K
875      ;;                 User)
876      ;; can yield `From joe@y.z (Joe    K Fri Mar 22 08:11:15 1996', and
877      ;;         From: Joe User
878      ;;                 <joe@y.z>
879      ;; can yield `From Joe User Fri Mar 22 08:11:15 1996'.
880      ;; The mailbox can be removed or be replaced by white space, e.g.
881      ;;         From: "Joe User"{space}{tab}
882      ;;                 <joe@y.z>
883      ;; can yield `From {space}{tab} Fri Mar 22 08:11:15 1996',
884      ;; where {space} and {tab} represent the Ascii space and tab characters.
885      ;; We want to match the results of any of these manglings.
886      ;; The following regexp rejects names whose first characters are
887      ;; obviously bogus, but after that anything goes.
888      "\\([^\0-\b\n-\r\^?].*\\)? "
889
890      ;; The time the message was sent.
891      "\\([^\0-\r \^?]+\\) +"                            ; day of the week
892      "\\([^\0-\r \^?]+\\) +"                            ; month
893      "\\([0-3]?[0-9]\\) +"                              ; day of month
894      "\\([0-2][0-9]:[0-5][0-9]\\(:[0-6][0-9]\\)?\\) *"  ; time of day
895
896      ;; Perhaps a time zone, specified by an abbreviation, or by a
897      ;; numeric offset.
898      time-zone-regexp
899
900      ;; The year.
901      " \\([0-9][0-9]+\\) *"
902
903      ;; On some systems the time zone can appear after the year, too.
904      time-zone-regexp
905
906      ;; Old uucp cruft.
907      "\\(remote from .*\\)?"
908
909      "\n"))
910   "Regexp matching the delimiter of messages in UNIX mail format.")
911
912 (defvar message-unsent-separator
913   (concat "^ *---+ +Unsent message follows +---+ *$\\|"
914           "^ *---+ +Returned message +---+ *$\\|"
915           "^Start of returned message$\\|"
916           "^ *---+ +Original message +---+ *$\\|"
917           "^ *--+ +begin message +--+ *$\\|"
918           "^ *---+ +Original message follows +---+ *$\\|"
919           "^|? *---+ +Message text follows: +---+ *|?$")
920   "A regexp that matches the separator before the text of a failed message.")
921
922 (defvar message-header-format-alist
923   `((Newsgroups)
924     (To . message-fill-address)
925     (Cc . message-fill-address)
926     (Subject)
927     (In-Reply-To)
928     (Fcc)
929     (Bcc)
930     (Date)
931     (Organization)
932     (Distribution)
933     (Lines)
934     (Expires)
935     (Message-ID)
936     (References . message-shorten-references)
937     (X-Mailer)
938     (X-Newsreader))
939   "Alist used for formatting headers.")
940
941 (eval-and-compile
942   (autoload 'message-setup-toolbar "messagexmas")