*** empty log message ***
[gnus] / lisp / message.el
index f104384..22f2a30 100644 (file)
@@ -1,5 +1,5 @@
 ;;; message.el --- composing mail and news messages
 ;;; message.el --- composing mail and news messages
-;; Copyright (C) 1996 Free Software Foundation, Inc.
+;; Copyright (C) 1996,97 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: mail, news
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: mail, news
 
 ;;; Code:
 
 
 ;;; Code:
 
-(eval-when-compile 
-  (require 'cl))
+(require 'cl)
 (require 'mailheader)
 (require 'rmail)
 (require 'nnheader)
 (require 'timezone)
 (require 'easymenu)
 (require 'mailheader)
 (require 'rmail)
 (require 'nnheader)
 (require 'timezone)
 (require 'easymenu)
+(require 'custom)
 (if (string-match "XEmacs\\|Lucid" emacs-version)
     (require 'mail-abbrevs)
   (require 'mailabbrev))
 
 (if (string-match "XEmacs\\|Lucid" emacs-version)
     (require 'mail-abbrevs)
   (require 'mailabbrev))
 
-(defvar message-directory "~/Mail/"
-  "*Directory from which all other mail file variables are derived.")
-
-(defvar message-max-buffers 10
-  "*How many buffers to keep before starting to kill them off.")
-
-(defvar message-send-rename-function nil
-  "Function called to rename the buffer after sending it.")
-
-;;;###autoload
-(defvar message-fcc-handler-function 'rmail-output
+(defgroup message '((user-mail-address custom-variable)
+                   (user-full-name custom-variable))
+  "Mail and news message composing."
+  :link '(custom-manual "(message)Top")
+  :group 'mail
+  :group 'news)
+
+(put 'user-mail-address 'custom-type 'string)
+(put 'user-full-name 'custom-type 'string)
+
+(defgroup message-various nil
+  "Various Message Variables"
+  :link '(custom-manual "(message)Various Message Variables")
+  :group 'message)
+
+(defgroup message-buffers nil
+  "Message Buffers"
+  :link '(custom-manual "(message)Message Buffers")
+  :group 'message)
+
+(defgroup message-sending nil
+  "Message Sending"
+  :link '(custom-manual "(message)Sending Variables")
+  :group 'message)
+
+(defgroup message-interface nil
+  "Message Interface"
+  :link '(custom-manual "(message)Interface")
+  :group 'message)
+
+(defgroup message-forwarding nil
+  "Message Forwarding"
+  :link '(custom-manual "(message)Forwarding")
+  :group 'message-interface)
+
+(defgroup message-insertion nil
+  "Message Insertion"
+  :link '(custom-manual "(message)Insertion")
+  :group 'message)
+
+(defgroup message-headers nil
+  "Message Headers"
+  :link '(custom-manual "(message)Message Headers")
+  :group 'message)
+
+(defgroup message-news nil
+  "Composing News Messages"
+  :group 'message)
+
+(defgroup message-mail nil
+  "Composing Mail Messages"
+  :group 'message)
+
+(defgroup message-faces nil
+  "Faces used for message composing."
+  :group 'message
+  :group 'faces)
+
+(defcustom message-directory "~/Mail/"
+  "*Directory from which all other mail file variables are derived."
+  :group 'message-various
+  :type 'directory)
+
+(defcustom message-max-buffers 10
+  "*How many buffers to keep before starting to kill them off."
+  :group 'message-buffers
+  :type 'integer)
+
+(defcustom message-send-rename-function nil
+  "Function called to rename the buffer after sending it."
+  :group 'message-buffers
+  :type 'function)
+
+(defcustom message-fcc-handler-function 'message-output
   "*A function called to save outgoing articles.
 This function will be called with the name of the file to store the
   "*A function called to save outgoing articles.
 This function will be called with the name of the file to store the
-article in. The default function is `rmail-output' which saves in Unix
-mailbox format.")
+article in.  The default function is `message-output' which saves in Unix
+mailbox format."
+  :type '(radio (function-item message-output)
+               (function :tag "Other"))
+  :group 'message-sending)
 
 
-;;;###autoload
-(defvar message-courtesy-message
+(defcustom message-courtesy-message
   "The following message is a courtesy copy of an article\nthat has been posted to %s as well.\n\n"
   "*This is inserted at the start of a mailed copy of a posted message.
 If the string contains the format spec \"%s\", the Newsgroups
 the article has been posted to will be inserted there.
   "The following message is a courtesy copy of an article\nthat has been posted to %s as well.\n\n"
   "*This is inserted at the start of a mailed copy of a posted message.
 If the string contains the format spec \"%s\", the Newsgroups
 the article has been posted to will be inserted there.
-If this variable is nil, no such courtesy message will be added.")
+If this variable is nil, no such courtesy message will be added."
+  :group 'message-sending
+  :type 'string)
 
 
-;;;###autoload
-(defvar message-ignored-bounced-headers "^\\(Received\\|Return-Path\\):"
-  "*Regexp that matches headers to be removed in resent bounced mail.")
+(defcustom message-ignored-bounced-headers "^\\(Received\\|Return-Path\\):"
+  "*Regexp that matches headers to be removed in resent bounced mail."
+  :group 'message-interface
+  :type 'regexp)
 
 ;;;###autoload
 
 ;;;###autoload
-(defvar message-from-style 'default
+(defcustom message-from-style 'default
   "*Specifies how \"From\" headers look.
 
 If `nil', they contain just the return address like:
   "*Specifies how \"From\" headers look.
 
 If `nil', they contain just the return address like:
@@ -80,10 +148,15 @@ If `angles', they look like:
        Elvis Parsley <king@grassland.com>
 
 Otherwise, most addresses look like `angles', but they look like
        Elvis Parsley <king@grassland.com>
 
 Otherwise, most addresses look like `angles', but they look like
-`parens' if `angles' would need quoting and `parens' would not.")
-
-;;;###autoload
-(defvar message-syntax-checks nil
+`parens' if `angles' would need quoting and `parens' would not."
+  :type '(choice (const :tag "simple" nil)
+                (const parens)
+                (const angles)
+                (const default))
+  :group 'message-headers)
+
+(defcustom message-syntax-checks nil
+  ;; Guess this one shouldn't be easy to customize...
   "Controls what syntax checks should not be performed on outgoing posts.
 To disable checking of long signatures, for instance, add
  `(signature . disabled)' to this list.
   "Controls what syntax checks should not be performed on outgoing posts.
 To disable checking of long signatures, for instance, add
  `(signature . disabled)' to this list.
@@ -92,246 +165,361 @@ Don't touch this variable unless you really know what you're doing.
 
 Checks include subject-cmsg multiple-headers sendsys message-id from
 long-lines control-chars size new-text redirected-followup signature
 
 Checks include subject-cmsg multiple-headers sendsys message-id from
 long-lines control-chars size new-text redirected-followup signature
-approved sender empty empty-headers message-id from subject.")
+approved sender empty empty-headers message-id from subject
+shorten-followup-to existing-newsgroups."
+  :group 'message-news)
 
 
-;;;###autoload
-(defvar message-required-news-headers
-  '(From Newsgroups Subject Date Message-ID 
-        (optional . Organization) Lines 
+(defcustom message-required-news-headers
+  '(From Newsgroups Subject Date Message-ID
+        (optional . Organization) Lines
         (optional . X-Newsreader))
         (optional . X-Newsreader))
-  "*Headers to be generated or prompted for when posting an article.
+  "Headers to be generated or prompted for when posting an article.
 RFC977 and RFC1036 require From, Date, Newsgroups, Subject,
 Message-ID.  Organization, Lines, In-Reply-To, Expires, and
 X-Newsreader are optional.  If don't you want message to insert some
 RFC977 and RFC1036 require From, Date, Newsgroups, Subject,
 Message-ID.  Organization, Lines, In-Reply-To, Expires, and
 X-Newsreader are optional.  If don't you want message to insert some
-header, remove it from this list.")
+header, remove it from this list."
+  :group 'message-news
+  :group 'message-headers
+  :type '(repeat sexp))
 
 
-;;;###autoload
-(defvar message-required-mail-headers 
+(defcustom message-required-mail-headers
   '(From Subject Date (optional . In-Reply-To) Message-ID Lines
         (optional . X-Mailer))
   '(From Subject Date (optional . In-Reply-To) Message-ID Lines
         (optional . X-Mailer))
-  "*Headers to be generated or prompted for when mailing a message.
+  "Headers to be generated or prompted for when mailing a message.
 RFC822 required that From, Date, To, Subject and Message-ID be
 RFC822 required that From, Date, To, Subject and Message-ID be
-included.  Organization, Lines and X-Mailer are optional.")
-
-;;;###autoload
-(defvar message-deletable-headers '(Message-ID Date Lines)
-  "*Headers to be deleted if they already exist and were generated by message previously.")
-
-;;;###autoload
-(defvar message-ignored-news-headers 
-  "^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:\\|^Fcc:"
-  "*Regexp of headers to be removed unconditionally before posting.")
-
-;;;###autoload
-(defvar message-ignored-mail-headers "^Gcc:\\|^Fcc:"
-  "*Regexp of headers to be removed unconditionally before mailing.")
-
-;;;###autoload
-(defvar message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|Return-Path:\\|^Supersedes:"
+included.  Organization, Lines and X-Mailer are optional."
+  :group 'message-mail
+  :group 'message-headers
+  :type '(repeat sexp))
+
+(defcustom message-deletable-headers '(Message-ID Date Lines)
+  "Headers to be deleted if they already exist and were generated by message previously."
+  :group 'message-headers
+  :type 'sexp)
+
+(defcustom message-ignored-news-headers
+  "^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:\\|^Fcc:\\|^Resent-Fcc:"
+  "*Regexp of headers to be removed unconditionally before posting."
+  :group 'message-news
+  :group 'message-headers
+  :type 'regexp)
+
+(defcustom message-ignored-mail-headers "^Gcc:\\|^Fcc:\\|^Resent-Fcc:"
+  "*Regexp of headers to be removed unconditionally before mailing."
+  :group 'message-mail
+  :group 'message-headers
+  :type 'regexp)
+
+(defcustom message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|Return-Path:\\|^Supersedes:"
   "*Header lines matching this regexp will be deleted before posting.
 It's best to delete old Path and Date headers before posting to avoid
   "*Header lines matching this regexp will be deleted before posting.
 It's best to delete old Path and Date headers before posting to avoid
-any confusion.")
+any confusion."
+  :group 'message-interface
+  :type 'regexp)
 
 ;;;###autoload
 
 ;;;###autoload
-(defvar message-signature-separator "^-- *$"
-  "Regexp matching the signature separator.")
+(defcustom message-signature-separator "^-- *$"
+  "Regexp matching the signature separator."
+  :type 'regexp
+  :group 'message-various)
 
 
-;;;###autoload
-(defvar message-interactive nil 
+(defcustom message-elide-elipsis "\n[...]\n\n"
+  "*The string which is inserted for elided text.")
+
+(defcustom message-interactive nil
   "Non-nil means when sending a message wait for and display errors.
   "Non-nil means when sending a message wait for and display errors.
-nil means let mailer mail back a message to report errors.")
+nil means let mailer mail back a message to report errors."
+  :group 'message-sending
+  :group 'message-mail
+  :type 'boolean)
 
 
-;;;###autoload
-(defvar message-generate-new-buffers t
+(defcustom message-generate-new-buffers t
   "*Non-nil means that a new message buffer will be created whenever `mail-setup' is called.
 If this is a function, call that function with three parameters:  The type,
 the to address and the group name.  (Any of these may be nil.)  The function
   "*Non-nil means that a new message buffer will be created whenever `mail-setup' is called.
 If this is a function, call that function with three parameters:  The type,
 the to address and the group name.  (Any of these may be nil.)  The function
-should return the new buffer name.")
+should return the new buffer name."
+  :group 'message-buffers
+  :type '(choice (const :tag "off" nil)
+                (const :tag "on" t)
+                (function fun)))
 
 
-;;;###autoload
-(defvar message-kill-buffer-on-exit nil
-  "*Non-nil means that the message buffer will be killed after sending a message.")
+(defcustom message-kill-buffer-on-exit nil
+  "*Non-nil means that the message buffer will be killed after sending a message."
+  :group 'message-buffers
+  :type 'boolean)
 
 (defvar gnus-local-organization)
 
 (defvar gnus-local-organization)
-(defvar message-user-organization 
+(defcustom message-user-organization
   (or (and (boundp 'gnus-local-organization)
   (or (and (boundp 'gnus-local-organization)
+          (stringp gnus-local-organization)
           gnus-local-organization)
       (getenv "ORGANIZATION")
       t)
   "*String to be used as an Organization header.
           gnus-local-organization)
       (getenv "ORGANIZATION")
       t)
   "*String to be used as an Organization header.
-If t, use `message-user-organization-file'.")
+If t, use `message-user-organization-file'."
+  :group 'message-headers
+  :type '(choice string
+                (const :tag "consult file" t)))
 
 ;;;###autoload
 
 ;;;###autoload
-(defvar message-user-organization-file "/usr/lib/news/organization"
-  "*Local news organization file.")
+(defcustom message-user-organization-file "/usr/lib/news/organization"
+  "*Local news organization file."
+  :type 'file
+  :group 'message-headers)
 
 
-(defvar message-autosave-directory "~/"
+(defcustom message-autosave-directory "~/"
   ; (concat (file-name-as-directory message-directory) "drafts/")
   "*Directory where message autosaves buffers.
   ; (concat (file-name-as-directory message-directory) "drafts/")
   "*Directory where message autosaves buffers.
-If nil, message won't autosave.")
+If nil, message won't autosave."
+  :group 'message-buffers
+  :type 'directory)
 
 
-(defvar message-forward-start-separator 
+(defcustom message-forward-start-separator
   "------- Start of forwarded message -------\n"
   "------- Start of forwarded message -------\n"
-  "*Delimiter inserted before forwarded messages.")
+  "*Delimiter inserted before forwarded messages."
+  :group 'message-forwarding
+  :type 'string)
 
 
-(defvar message-forward-end-separator
+(defcustom message-forward-end-separator
   "------- End of forwarded message -------\n"
   "------- End of forwarded message -------\n"
-  "*Delimiter inserted after forwarded messages.")
+  "*Delimiter inserted after forwarded messages."
+  :group 'message-forwarding
+  :type 'string)
 
 
-;;;###autoload
-(defvar message-signature-before-forwarded-message t
-  "*If non-nil, put the signature before any included forwarded message.")
+(defcustom message-signature-before-forwarded-message t
+  "*If non-nil, put the signature before any included forwarded message."
+  :group 'message-forwarding
+  :type 'boolean)
 
 
-;;;###autoload
-(defvar message-included-forward-headers 
+(defcustom message-included-forward-headers
   "^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:"
   "^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:"
-  "*Regexp matching headers to be included in forwarded messages.")
+  "*Regexp matching headers to be included in forwarded messages."
+  :group 'message-forwarding
+  :type 'regexp)
 
 
-;;;###autoload
-(defvar message-ignored-resent-headers "^Return-receipt"
-  "*All headers that match this regexp will be deleted when resending a message.")
+(defcustom message-ignored-resent-headers "^Return-receipt"
+  "*All headers that match this regexp will be deleted when resending a message."
+  :group 'message-interface
+  :type 'regexp)
 
 
-;;;###autoload
-(defvar message-ignored-cited-headers "."
-  "Delete these headers from the messages you yank.")
+(defcustom message-ignored-cited-headers "."
+  "*Delete these headers from the messages you yank."
+  :group 'message-insertion
+  :type 'regexp)
 
 
-(defvar message-cancel-message "I am canceling my own article."
-  "Message to be inserted in the cancel message.")
+(defcustom message-cancel-message "I am canceling my own article."
+  "Message to be inserted in the cancel message."
+  :group 'message-interface
+  :type 'string)
 
 ;; Useful to set in site-init.el
 ;;;###autoload
 
 ;; Useful to set in site-init.el
 ;;;###autoload
-(defvar message-send-mail-function 'message-send-mail-with-sendmail
+(defcustom message-send-mail-function 'message-send-mail-with-sendmail
   "Function to call to send the current buffer as mail.
 The headers should be delimited by a line whose contents match the
 variable `mail-header-separator'.
 
 Legal values include `message-send-mail-with-sendmail' (the default),
   "Function to call to send the current buffer as mail.
 The headers should be delimited by a line whose contents match the
 variable `mail-header-separator'.
 
 Legal values include `message-send-mail-with-sendmail' (the default),
-`message-send-mail-with-mh' and `message-send-mail-with-qmail'.")
-
-;;;###autoload
-(defvar message-send-news-function 'message-send-news
+`message-send-mail-with-mh' and `message-send-mail-with-qmail'."
+  :type '(radio (function-item message-send-mail-with-sendmail)
+               (function-item message-send-mail-with-mh)
+               (function-item message-send-mail-with-qmail)
+               (function :tag "Other"))
+  :group 'message-sending
+  :group 'message-mail)
+
+(defcustom message-send-news-function 'message-send-news
   "Function to call to send the current buffer as news.
 The headers should be delimited by a line whose contents match the
   "Function to call to send the current buffer as news.
 The headers should be delimited by a line whose contents match the
-variable `mail-header-separator'.")
+variable `mail-header-separator'."
+  :group 'message-sending
+  :group 'message-news
+  :type 'function)
 
 
-;;;###autoload
-(defvar message-reply-to-function nil
+(defcustom message-reply-to-function nil
   "Function that should return a list of headers.
 This function should pick out addresses from the To, Cc, and From headers
   "Function that should return a list of headers.
 This function should pick out addresses from the To, Cc, and From headers
-and respond with new To and Cc headers.")
+and respond with new To and Cc headers."
+  :group 'message-interface
+  :type 'function)
 
 
-;;;###autoload
-(defvar message-wide-reply-to-function nil
+(defcustom message-wide-reply-to-function nil
   "Function that should return a list of headers.
 This function should pick out addresses from the To, Cc, and From headers
   "Function that should return a list of headers.
 This function should pick out addresses from the To, Cc, and From headers
-and respond with new To and Cc headers.")
+and respond with new To and Cc headers."
+  :group 'message-interface
+  :type 'function)
 
 
-;;;###autoload
-(defvar message-followup-to-function nil
+(defcustom message-followup-to-function nil
   "Function that should return a list of headers.
 This function should pick out addresses from the To, Cc, and From headers
   "Function that should return a list of headers.
 This function should pick out addresses from the To, Cc, and From headers
-and respond with new To and Cc headers.")
+and respond with new To and Cc headers."
+  :group 'message-interface
+  :type 'function)
 
 
-;;;###autoload
-(defvar message-use-followup-to 'ask
+(defcustom message-use-followup-to 'ask
   "*Specifies what to do with Followup-To header.
   "*Specifies what to do with Followup-To header.
-If nil, ignore the header. If it is t, use its value, but query before
-using the \"poster\" value.  If it is the symbol `ask', query the user
-whether to ignore the \"poster\" value.  If it is the symbol `use',
-always use the value.")
+If nil, always ignore the header.  If it is t, use its value, but
+query before using the \"poster\" value.  If it is the symbol `ask',
+always query the user whether to use the value.  If it is the symbol
+`use', always use the value."
+  :group 'message-interface
+  :type '(choice (const :tag "ignore" nil)
+                (const use)
+                (const ask)))
+
+;; stuff relating to broken sendmail in MMDF
+(defcustom message-sendmail-f-is-evil nil
+  "*Non-nil means that \"-f username\" should not be added to the sendmail
+command line, because it is even more evil than leaving it out."
+  :group 'message-sending
+  :type 'boolean)
 
 ;; qmail-related stuff
 
 ;; qmail-related stuff
-(defvar message-qmail-inject-program "/var/qmail/bin/qmail-inject"
-  "Location of the qmail-inject program.")
+(defcustom message-qmail-inject-program "/var/qmail/bin/qmail-inject"
+  "Location of the qmail-inject program."
+  :group 'message-sending
+  :type 'file)
 
 
-(defvar message-qmail-inject-args nil
+(defcustom message-qmail-inject-args nil
   "Arguments passed to qmail-inject programs.
 This should be a list of strings, one string for each argument.
 
 For e.g., if you wish to set the envelope sender address so that bounces
 go to the right place or to deal with listserv's usage of that address, you
   "Arguments passed to qmail-inject programs.
 This should be a list of strings, one string for each argument.
 
 For e.g., if you wish to set the envelope sender address so that bounces
 go to the right place or to deal with listserv's usage of that address, you
-might set this variable to '(\"-f\" \"you@some.where\").")
+might set this variable to '(\"-f\" \"you@some.where\")."
+  :group 'message-sending
+  :type '(repeat string))
 
 (defvar gnus-post-method)
 (defvar gnus-select-method)
 
 (defvar gnus-post-method)
 (defvar gnus-select-method)
-;;;###autoload
-(defvar message-post-method 
+(defcustom message-post-method
   (cond ((and (boundp 'gnus-post-method)
              gnus-post-method)
         gnus-post-method)
        ((boundp 'gnus-select-method)
         gnus-select-method)
        (t '(nnspool "")))
   (cond ((and (boundp 'gnus-post-method)
              gnus-post-method)
         gnus-post-method)
        ((boundp 'gnus-select-method)
         gnus-select-method)
        (t '(nnspool "")))
-  "Method used to post news.")
-
-;;;###autoload
-(defvar message-generate-headers-first nil
-  "*If non-nil, generate all possible headers before composing.")
-
-(defvar message-setup-hook nil
+  "Method used to post news."
+  :group 'message-news
+  :group 'message-sending
+  ;; This should be the `gnus-select-method' widget, but that might
+  ;; create a dependence to `gnus.el'.
+  :type 'sexp)
+
+(defcustom message-generate-headers-first nil
+  "*If non-nil, generate all possible headers before composing."
+  :group 'message-headers
+  :type 'boolean)
+
+(defcustom message-setup-hook nil
   "Normal hook, run each time a new outgoing message is initialized.
   "Normal hook, run each time a new outgoing message is initialized.
-The function `message-setup' runs this hook.")
+The function `message-setup' runs this hook."
+  :group 'message-various
+  :type 'hook)
 
 
-(defvar message-signature-setup-hook nil
+(defcustom message-signature-setup-hook nil
   "Normal hook, run each time a new outgoing message is initialized.
   "Normal hook, run each time a new outgoing message is initialized.
-It is run after the headers have been inserted and before 
-the signature is inserted.")
-
-(defvar message-mode-hook nil
-  "Hook run in message mode buffers.")
-
-(defvar message-header-hook nil
-  "Hook run in a message mode buffer narrowed to the headers.")
-
-(defvar message-header-setup-hook nil
-  "Hook called narrowed to the headers when setting up a message buffer.")
+It is run after the headers have been inserted and before
+the signature is inserted."
+  :group 'message-various
+  :type 'hook)
+
+(defcustom message-mode-hook nil
+  "Hook run in message mode buffers."
+  :group 'message-various
+  :type 'hook)
+
+(defcustom message-header-hook nil
+  "Hook run in a message mode buffer narrowed to the headers."
+  :group 'message-various
+  :type 'hook)
+
+(defcustom message-header-setup-hook nil
+  "Hook called narrowed to the headers when setting up a message
+buffer."
+  :group 'message-various
+  :type 'hook)
 
 ;;;###autoload
 
 ;;;###autoload
-(defvar message-citation-line-function 'message-insert-citation-line
-  "*Function called to insert the \"Whomever writes:\" line.")
+(defcustom message-citation-line-function 'message-insert-citation-line
+  "*Function called to insert the \"Whomever writes:\" line."
+  :type 'function
+  :group 'message-insertion)
 
 ;;;###autoload
 
 ;;;###autoload
-(defvar message-yank-prefix "> "
+(defcustom message-yank-prefix "> "
   "*Prefix inserted on the lines of yanked messages.
   "*Prefix inserted on the lines of yanked messages.
-nil means use indentation.")
+nil means use indentation."
+  :type 'string
+  :group 'message-insertion)
 
 
-(defvar message-indentation-spaces 3
+(defcustom message-indentation-spaces 3
   "*Number of spaces to insert at the beginning of each cited line.
   "*Number of spaces to insert at the beginning of each cited line.
-Used by `message-yank-original' via `message-yank-cite'.")
+Used by `message-yank-original' via `message-yank-cite'."
+  :group 'message-insertion
+  :type 'integer)
 
 ;;;###autoload
 
 ;;;###autoload
-(defvar message-cite-function 'message-cite-original
-  "*Function for citing an original message.")
+(defcustom message-cite-function
+  (if (and (boundp 'mail-citation-hook)
+          mail-citation-hook)
+      mail-citation-hook
+    'message-cite-original)
+  "*Function for citing an original message."
+  :type '(radio (function-item message-cite-original)
+               (function-item sc-cite-original)
+               (function :tag "Other"))
+  :group 'message-insertion)
 
 ;;;###autoload
 
 ;;;###autoload
-(defvar message-indent-citation-function 'message-indent-citation
+(defcustom message-indent-citation-function 'message-indent-citation
   "*Function for modifying a citation just inserted in the mail buffer.
 This can also be a list of functions.  Each function can find the
 citation between (point) and (mark t).  And each function should leave
   "*Function for modifying a citation just inserted in the mail buffer.
 This can also be a list of functions.  Each function can find the
 citation between (point) and (mark t).  And each function should leave
-point and mark around the citation text as modified.")
+point and mark around the citation text as modified."
+  :type 'function
+  :group 'message-insertion)
 
 (defvar message-abbrevs-loaded nil)
 
 ;;;###autoload
 
 (defvar message-abbrevs-loaded nil)
 
 ;;;###autoload
-(defvar message-signature t
+(defcustom message-signature t
   "*String to be inserted at the end of the message buffer.
 If t, the `message-signature-file' file will be inserted instead.
 If a function, the result from the function will be used instead.
   "*String to be inserted at the end of the message buffer.
 If t, the `message-signature-file' file will be inserted instead.
 If a function, the result from the function will be used instead.
-If a form, the result from the form will be used instead.")
+If a form, the result from the form will be used instead."
+  :type 'sexp
+  :group 'message-insertion)
 
 ;;;###autoload
 
 ;;;###autoload
-(defvar message-signature-file "~/.signature"
-  "*File containing the text inserted at end of message buffer.")
-
-(defvar message-distribution-function nil
-  "*Function called to return a Distribution header.")
-
-(defvar message-expires 14
-  "*Number of days before your article expires.")
-
-(defvar message-user-path nil
+(defcustom message-signature-file "~/.signature"
+  "*File containing the text inserted at end of message buffer."
+  :type 'file
+  :group 'message-insertion)
+
+(defcustom message-distribution-function nil
+  "*Function called to return a Distribution header."
+  :group 'message-news
+  :group 'message-headers
+  :type 'function)
+
+(defcustom message-expires 14
+  "Number of days before your article expires."
+  :group 'message-news
+  :group 'message-headers
+  :link '(custom-manual "(message)News Headers")
+  :type 'integer)
+
+(defcustom message-user-path nil
   "If nil, use the NNTP server name in the Path header.
   "If nil, use the NNTP server name in the Path header.
-If stringp, use this; if non-nil, use no host name (user name only).")
+If stringp, use this; if non-nil, use no host name (user name only)."
+  :group 'message-news
+  :group 'message-headers
+  :link '(custom-manual "(message)News Headers")
+  :type '(choice (const :tag "nntp" nil)
+                (string :tag "name")
+                (sexp :tag "none" :format "%t" t)))
 
 (defvar message-reply-buffer nil)
 (defvar message-reply-headers nil)
 
 (defvar message-reply-buffer nil)
 (defvar message-reply-headers nil)
@@ -348,24 +536,30 @@ If stringp, use this; if non-nil, use no host name (user name only).")
 (defvar message-postpone-actions nil
   "A list of actions to be performed after postponing a message.")
 
 (defvar message-postpone-actions nil
   "A list of actions to be performed after postponing a message.")
 
-;;;###autoload
-(defvar message-default-headers nil
+(defcustom message-default-headers ""
   "*A string containing header lines to be inserted in outgoing messages.
 It is inserted before you edit the message, so you can edit or delete
   "*A string containing header lines to be inserted in outgoing messages.
 It is inserted before you edit the message, so you can edit or delete
-these lines.")
-
-;;;###autoload
-(defvar message-default-mail-headers nil
-  "*A string of header lines to be inserted in outgoing mails.")
-
-;;;###autoload
-(defvar message-default-news-headers nil
-  "*A string of header lines to be inserted in outgoing news articles.")
+these lines."
+  :group 'message-headers
+  :type 'string)
+
+(defcustom message-default-mail-headers ""
+  "*A string of header lines to be inserted in outgoing mails."
+  :group 'message-headers
+  :group 'message-mail
+  :type 'string)
+
+(defcustom message-default-news-headers ""
+  "*A string of header lines to be inserted in outgoing news
+articles."
+  :group 'message-headers
+  :group 'message-news
+  :type 'string)
 
 ;; Note: could use /usr/ucb/mail instead of sendmail;
 ;; options -t, and -v if not interactive.
 
 ;; Note: could use /usr/ucb/mail instead of sendmail;
 ;; options -t, and -v if not interactive.
-(defvar message-mailer-swallows-blank-line
-  (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)" 
+(defcustom message-mailer-swallows-blank-line
+  (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)"
                         system-configuration)
           (file-readable-p "/etc/sendmail.cf")
           (let ((buffer (get-buffer-create " *temp*")))
                         system-configuration)
           (file-readable-p "/etc/sendmail.cf")
           (let ((buffer (get-buffer-create " *temp*")))
@@ -378,19 +572,48 @@ these lines.")
                     (re-search-forward "^OR\\>" nil t)))
               (kill-buffer buffer))))
       ;; According to RFC822, "The field-name must be composed of printable
                     (re-search-forward "^OR\\>" nil t)))
               (kill-buffer buffer))))
       ;; According to RFC822, "The field-name must be composed of printable
-      ;; ASCII characters (i.e. characters that have decimal values between
-      ;; 33 and 126, except colon)", i.e. any chars except ctl chars,
+      ;; ASCII characters (i. e., characters that have decimal values between
+      ;; 33 and 126, except colon)", i. e., any chars except ctl chars,
       ;; space, or colon.
       '(looking-at "[ \t]\\|[][!\"#$%&'()*+,-./0-9;<=>?@A-Z\\\\^_`a-z{|}~]+:"))
   "Set this non-nil if the system's mailer runs the header and body together.
 \(This problem exists on Sunos 4 when sendmail is run in remote mode.)
 The value should be an expression to test whether the problem will
       ;; space, or colon.
       '(looking-at "[ \t]\\|[][!\"#$%&'()*+,-./0-9;<=>?@A-Z\\\\^_`a-z{|}~]+:"))
   "Set this non-nil if the system's mailer runs the header and body together.
 \(This problem exists on Sunos 4 when sendmail is run in remote mode.)
 The value should be an expression to test whether the problem will
-actually occur.")
+actually occur."
+  :group 'message-sending
+  :type 'sexp)
+
+(ignore-errors
+  (define-mail-user-agent 'message-user-agent
+    'message-mail 'message-send-and-exit
+    'message-kill-buffer 'message-send-hook))
+
+(defvar message-mh-deletable-headers '(Message-ID Date Lines Sender)
+  "If non-nil, delete the deletable headers before feeding to mh.")
+
+(defvar message-send-method-alist
+  '((news message-news-p message-send-via-news)
+    (mail message-mail-p message-send-via-mail))
+  "Alist of ways to send outgoing messages.
+Each element has the form
+
+  \(TYPE PREDICATE FUNCTION)
+
+where TYPE is a symbol that names the method; PREDICATE is a function
+called without any parameters to determine whether the message is
+a message of type TYPE; and FUNCTION is a function to be called if
+PREDICATE returns non-nil.  FUNCTION is called with one parameter --
+the prefix.")
+
+(defvar message-mail-alias-type 'abbrev
+  "*What alias expansion type to use in Message buffers.
+The default is `abbrev', which uses mailabbrev.  nil switches
+mail aliases off.")
 
 ;;; Internal variables.
 ;;; Well, not really internal.
 
 
 ;;; Internal variables.
 ;;; Well, not really internal.
 
-(defvar message-mode-syntax-table 
+(defvar message-mode-syntax-table
   (let ((table (copy-syntax-table text-mode-syntax-table)))
     (modify-syntax-entry ?% ". " table)
     table)
   (let ((table (copy-syntax-table text-mode-syntax-table)))
     (modify-syntax-entry ?% ". " table)
     table)
@@ -399,47 +622,191 @@ actually occur.")
 (defvar message-mode-abbrev-table text-mode-abbrev-table
   "Abbrev table used in Message mode buffers.
 Defaults to `text-mode-abbrev-table'.")
 (defvar message-mode-abbrev-table text-mode-abbrev-table
   "Abbrev table used in Message mode buffers.
 Defaults to `text-mode-abbrev-table'.")
+(defgroup message-headers nil
+  "Message headers."
+  :link '(custom-manual "(message)Variables")
+  :group 'message)
+
+(defface message-header-to-face
+  '((((class color)
+      (background dark))
+     (:foreground "green2" :bold t))
+    (((class color)
+      (background light))
+     (:foreground "MidnightBlue" :bold t))
+    (t
+     (:bold t :italic t)))
+  "Face used for displaying From headers."
+  :group 'message-faces)
+
+(defface message-header-cc-face
+  '((((class color)
+      (background dark))
+     (:foreground "green4" :bold t))
+    (((class color)
+      (background light))
+     (:foreground "MidnightBlue"))
+    (t
+     (:bold t)))
+  "Face used for displaying Cc headers."
+  :group 'message-faces)
+
+(defface message-header-subject-face
+  '((((class color)
+      (background dark))
+     (:foreground "green3"))
+    (((class color)
+      (background light))
+     (:foreground "navy blue" :bold t))
+    (t
+     (:bold t)))
+  "Face used for displaying subject headers."
+  :group 'message-faces)
+
+(defface message-header-newsgroups-face
+  '((((class color)
+      (background dark))
+     (:foreground "yellow" :bold t :italic t))
+    (((class color)
+      (background light))
+     (:foreground "blue4" :bold t :italic t))
+    (t
+     (:bold t :italic t)))
+  "Face used for displaying newsgroups headers."
+  :group 'message-faces)
+
+(defface message-header-other-face
+  '((((class color)
+      (background dark))
+     (:foreground "red4"))
+    (((class color)
+      (background light))
+     (:foreground "steel blue"))
+    (t
+     (:bold t :italic t)))
+  "Face used for displaying newsgroups headers."
+  :group 'message-faces)
+
+(defface message-header-name-face
+  '((((class color)
+      (background dark))
+     (:foreground "DarkGreen"))
+    (((class color)
+      (background light))
+     (:foreground "cornflower blue"))
+    (t
+     (:bold t)))
+  "Face used for displaying header names."
+  :group 'message-faces)
+
+(defface message-header-xheader-face
+  '((((class color)
+      (background dark))
+     (:foreground "blue"))
+    (((class color)
+      (background light))
+     (:foreground "blue"))
+    (t
+     (:bold t)))
+  "Face used for displaying X-Header headers."
+  :group 'message-faces)
+
+(defface message-separator-face
+  '((((class color)
+      (background dark))
+     (:foreground "blue4"))
+    (((class color)
+      (background light))
+     (:foreground "brown"))
+    (t
+     (:bold t)))
+  "Face used for displaying the separator."
+  :group 'message-faces)
+
+(defface message-cited-text-face
+  '((((class color)
+      (background dark))
+     (:foreground "red"))
+    (((class color)
+      (background light))
+     (:foreground "red"))
+    (t
+     (:bold t)))
+  "Face used for displaying cited text names."
+  :group 'message-faces)
 
 (defvar message-font-lock-keywords
 
 (defvar message-font-lock-keywords
-  (let* ((cite-prefix "A-Za-z") (cite-suffix (concat cite-prefix "0-9_.@-")))
-    (list '("^To:" . font-lock-function-name-face)
-          '("^[GBF]?[Cc][Cc]:\\|^Reply-To:" . font-lock-keyword-face)
-         '("^\\(Subject:\\)[ \t]*\\(.+\\)?"
-           (1 font-lock-comment-face) (2 font-lock-type-face nil t))
-         (list (concat "^\\(" (regexp-quote mail-header-separator) "\\)$")
-               1 'font-lock-comment-face)
-         (cons (concat "^[ \t]*"
-                       "\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
-                       "[>|}].*")
-               'font-lock-reference-face)
-         '("^\\(X-[A-Za-z0-9-]+\\|In-reply-to\\):.*"
-           . font-lock-string-face)))
+  (let* ((cite-prefix "A-Za-z")
+        (cite-suffix (concat cite-prefix "0-9_.@-"))
+        (content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)"))
+    `((,(concat "^\\([Tt]o:\\)" content)
+       (1 'message-header-name-face)
+       (2 'message-header-to-face nil t))
+      (,(concat "^\\(^[GBF]?[Cc][Cc]:\\|^[Rr]eply-[Tt]o:\\)" content)
+       (1 'message-header-name-face)
+       (2 'message-header-cc-face nil t))
+      (,(concat "^\\([Ss]ubject:\\)" content)
+       (1 'message-header-name-face)
+       (2 'message-header-subject-face nil t))
+      (,(concat "^\\([Nn]ewsgroups:\\|Followup-[Tt]o:\\)" content)
+       (1 'message-header-name-face)
+       (2 'message-header-newsgroups-face nil t))
+      (,(concat "^\\([A-Z][^: \n\t]+:\\)" content)
+       (1 'message-header-name-face)
+       (2 'message-header-other-face nil t))
+      (,(concat "^\\(X-[A-Za-z0-9-]+\\|In-Reply-To\\):" content)
+       (1 'message-header-name-face)
+       (2 'message-header-name-face))
+      (,(concat "^\\(" (regexp-quote mail-header-separator) "\\)$")
+       1 'message-separator-face)
+      (,(concat "^[ \t]*"
+               "\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
+               "[>|}].*")
+       (0 'message-cited-text-face))))
   "Additional expressions to highlight in Message mode.")
 
 (defvar message-face-alist
   '((bold . bold-region)
     (underline . underline-region)
   "Additional expressions to highlight in Message mode.")
 
 (defvar message-face-alist
   '((bold . bold-region)
     (underline . underline-region)
-    (default . (lambda (b e) 
+    (default . (lambda (b e)
                 (unbold-region b e)
                 (ununderline-region b e))))
   "Alist of mail and news faces for facemenu.
 The cdr of ech entry is a function for applying the face to a region.")
 
                 (unbold-region b e)
                 (ununderline-region b e))))
   "Alist of mail and news faces for facemenu.
 The cdr of ech entry is a function for applying the face to a region.")
 
-(defvar message-send-hook nil
-  "Hook run before sending messages.")
+(defcustom message-send-hook nil
+  "Hook run before sending messages."
+  :group 'message-various
+  :options '(ispell-message)
+  :type 'hook)
+
+(defcustom message-send-mail-hook nil
+  "Hook run before sending mail messages."
+  :group 'message-various
+  :type 'hook)
 
 
-(defvar message-sent-hook nil
-  "Hook run after sending messages.")
+(defcustom message-send-news-hook nil
+  "Hook run before sending news messages."
+  :group 'message-various
+  :type 'hook)
+
+(defcustom message-sent-hook nil
+  "Hook run after sending messages."
+  :group 'message-various
+  :type 'hook)
 
 ;;; Internal variables.
 
 (defvar message-buffer-list nil)
 
 ;;; Internal variables.
 
 (defvar message-buffer-list nil)
+(defvar message-this-is-news nil)
+(defvar message-this-is-mail nil)
 
 ;; Byte-compiler warning
 (defvar gnus-active-hashtb)
 
 ;; Byte-compiler warning
 (defvar gnus-active-hashtb)
+(defvar gnus-read-active-file)
 
 ;;; Regexp matching the delimiter of messages in UNIX mail format
 
 ;;; Regexp matching the delimiter of messages in UNIX mail format
-;;; (UNIX From lines), minus the initial ^.  
+;;; (UNIX From lines), minus the initial ^.
 (defvar message-unix-mail-delimiter
   (let ((time-zone-regexp
         (concat "\\([A-Z]?[A-Z]?[A-Z][A-Z]\\( DST\\)?"
 (defvar message-unix-mail-delimiter
   (let ((time-zone-regexp
         (concat "\\([A-Z]?[A-Z]?[A-Z][A-Z]\\( DST\\)?"
@@ -487,9 +854,9 @@ The cdr of ech entry is a function for applying the face to a region.")
          "^|? *---+ +Message text follows: +---+ *|?$")
   "A regexp that matches the separator before the text of a failed message.")
 
          "^|? *---+ +Message text follows: +---+ *|?$")
   "A regexp that matches the separator before the text of a failed message.")
 
-(defvar message-header-format-alist 
+(defvar message-header-format-alist
   `((Newsgroups)
   `((Newsgroups)
-    (To . message-fill-address) 
+    (To . message-fill-address)
     (Cc . message-fill-address)
     (Subject)
     (In-Reply-To)
     (Cc . message-fill-address)
     (Subject)
     (In-Reply-To)
@@ -501,37 +868,26 @@ The cdr of ech entry is a function for applying the face to a region.")
     (Lines)
     (Expires)
     (Message-ID)
     (Lines)
     (Expires)
     (Message-ID)
-    (References . message-fill-header)
+    (References)
     (X-Mailer)
     (X-Newsreader))
   "Alist used for formatting headers.")
 
 (eval-and-compile
   (autoload 'message-setup-toolbar "messagexmas")
     (X-Mailer)
     (X-Newsreader))
   "Alist used for formatting headers.")
 
 (eval-and-compile
   (autoload 'message-setup-toolbar "messagexmas")
-  (autoload 'mh-send-letter "mh-comp"))
+  (autoload 'mh-send-letter "mh-comp")
+  (autoload 'gnus-point-at-eol "gnus-util")
+  (autoload 'gnus-point-at-bol "gnus-util")
+  (autoload 'gnus-output-to-mail "gnus-util")
+  (autoload 'gnus-output-to-rmail "gnus-util")
+  (autoload 'mail-abbrev-in-expansion-header-p "mailabbrev"))
 
 \f
 
 
 \f
 
-;;; 
+;;;
 ;;; Utility functions.
 ;;;
 
 ;;; Utility functions.
 ;;;
 
-(defun message-point-at-bol ()
-  "Return point at the beginning of the line."
-  (let ((p (point)))
-    (beginning-of-line)
-    (prog1
-       (point)
-      (goto-char p))))
-
-(defun message-point-at-eol ()
-  "Return point at the end of the line."
-  (let ((p (point)))
-    (end-of-line)
-    (prog1
-       (point)
-      (goto-char p))))
-
 (defmacro message-y-or-n-p (question show &rest text)
   "Ask QUESTION, displaying the rest of the arguments in a temp. buffer if SHOW"
   `(message-talkative-question 'y-or-n-p ,question ,show ,@text))
 (defmacro message-y-or-n-p (question show &rest text)
   "Ask QUESTION, displaying the rest of the arguments in a temp. buffer if SHOW"
   `(message-talkative-question 'y-or-n-p ,question ,show ,@text))
@@ -544,41 +900,66 @@ The cdr of ech entry is a function for applying the face to a region.")
 (defun message-tokenize-header (header &optional separator)
   "Split HEADER into a list of header elements.
 \",\" is used as the separator."
 (defun message-tokenize-header (header &optional separator)
   "Split HEADER into a list of header elements.
 \",\" is used as the separator."
-  (let ((regexp (format "[%s]+" (or separator ",")))
-       (beg 1)
-       (first t)
-       quoted elems paren)
-    (save-excursion
-      (message-set-work-buffer)
-      (insert header)
+  (if (not header)
+      nil
+    (let ((regexp (format "[%s]+" (or separator ",")))
+         (beg 1)
+         (first t)
+         quoted elems paren)
+      (save-excursion
+       (message-set-work-buffer)
+       (insert header)
+       (goto-char (point-min))
+       (while (not (eobp))
+         (if first
+             (setq first nil)
+           (forward-char 1))
+         (cond ((and (> (point) beg)
+                     (or (eobp)
+                         (and (looking-at regexp)
+                              (not quoted)
+                              (not paren))))
+                (push (buffer-substring beg (point)) elems)
+                (setq beg (match-end 0)))
+               ((= (char-after (point)) ?\")
+                (setq quoted (not quoted)))
+               ((and (= (char-after (point)) ?\()
+                     (not quoted))
+                (setq paren t))
+               ((and (= (char-after (point)) ?\))
+                     (not quoted))
+                (setq paren nil))))
+       (nreverse elems)))))
+
+(defun message-mail-file-mbox-p (file)
+  "Say whether FILE looks like a Unix mbox file."
+  (when (and (file-exists-p file)
+            (file-readable-p file)
+            (file-regular-p file))
+    (nnheader-temp-write nil
+      (nnheader-insert-file-contents file)
       (g