comparison lisp/gnus/message.el @ 108:360340f9fd5f r20-1b6

Import from CVS: tag r20-1b6
author cvs
date Mon, 13 Aug 2007 09:18:39 +0200
parents cf808b4c4290
children fe104dbd9147
comparison
equal deleted inserted replaced
107:523141596bda 108:360340f9fd5f
27 ;; consists mainly of large chunks of code from the sendmail.el, 27 ;; consists mainly of large chunks of code from the sendmail.el,
28 ;; gnus-msg.el and rnewspost.el files. 28 ;; gnus-msg.el and rnewspost.el files.
29 29
30 ;;; Code: 30 ;;; Code:
31 31
32 (eval-when-compile 32 (require 'cl)
33 (require 'cl))
34 (require 'mailheader) 33 (require 'mailheader)
35 (require 'rmail) 34 (require 'rmail)
36 (require 'nnheader) 35 (require 'nnheader)
37 (require 'timezone) 36 (require 'timezone)
38 (require 'easymenu) 37 (require 'easymenu)
165 approved sender empty empty-headers message-id from subject 164 approved sender empty empty-headers message-id from subject
166 shorten-followup-to existing-newsgroups." 165 shorten-followup-to existing-newsgroups."
167 :group 'message-news) 166 :group 'message-news)
168 167
169 (defcustom message-required-news-headers 168 (defcustom message-required-news-headers
170 '(From Newsgroups Subject Date Message-ID 169 '(From Newsgroups Subject Date Message-ID
171 (optional . Organization) Lines 170 (optional . Organization) Lines
172 (optional . X-Newsreader)) 171 (optional . X-Newsreader))
173 "Headers to be generated or prompted for when posting an article. 172 "Headers to be generated or prompted for when posting an article.
174 RFC977 and RFC1036 require From, Date, Newsgroups, Subject, 173 RFC977 and RFC1036 require From, Date, Newsgroups, Subject,
175 Message-ID. Organization, Lines, In-Reply-To, Expires, and 174 Message-ID. Organization, Lines, In-Reply-To, Expires, and
176 X-Newsreader are optional. If don't you want message to insert some 175 X-Newsreader are optional. If don't you want message to insert some
177 header, remove it from this list." 176 header, remove it from this list."
178 :group 'message-news 177 :group 'message-news
179 :group 'message-headers 178 :group 'message-headers
180 :type '(repeat sexp)) 179 :type '(repeat sexp))
181 180
182 (defcustom message-required-mail-headers 181 (defcustom message-required-mail-headers
183 '(From Subject Date (optional . In-Reply-To) Message-ID Lines 182 '(From Subject Date (optional . In-Reply-To) Message-ID Lines
184 (optional . X-Mailer)) 183 (optional . X-Mailer))
185 "Headers to be generated or prompted for when mailing a message. 184 "Headers to be generated or prompted for when mailing a message.
186 RFC822 required that From, Date, To, Subject and Message-ID be 185 RFC822 required that From, Date, To, Subject and Message-ID be
187 included. Organization, Lines and X-Mailer are optional." 186 included. Organization, Lines and X-Mailer are optional."
192 (defcustom message-deletable-headers '(Message-ID Date Lines) 191 (defcustom message-deletable-headers '(Message-ID Date Lines)
193 "Headers to be deleted if they already exist and were generated by message previously." 192 "Headers to be deleted if they already exist and were generated by message previously."
194 :group 'message-headers 193 :group 'message-headers
195 :type 'sexp) 194 :type 'sexp)
196 195
197 (defcustom message-ignored-news-headers 196 (defcustom message-ignored-news-headers
198 "^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:\\|^Fcc:\\|^Resent-Fcc:" 197 "^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:\\|^Fcc:\\|^Resent-Fcc:"
199 "*Regexp of headers to be removed unconditionally before posting." 198 "*Regexp of headers to be removed unconditionally before posting."
200 :group 'message-news 199 :group 'message-news
201 :group 'message-headers 200 :group 'message-headers
202 :type 'regexp) 201 :type 'regexp)
221 :group 'message-various) 220 :group 'message-various)
222 221
223 (defcustom message-elide-elipsis "\n[...]\n\n" 222 (defcustom message-elide-elipsis "\n[...]\n\n"
224 "*The string which is inserted for elided text.") 223 "*The string which is inserted for elided text.")
225 224
226 (defcustom message-interactive nil 225 (defcustom message-interactive nil
227 "Non-nil means when sending a message wait for and display errors. 226 "Non-nil means when sending a message wait for and display errors.
228 nil means let mailer mail back a message to report errors." 227 nil means let mailer mail back a message to report errors."
229 :group 'message-sending 228 :group 'message-sending
230 :group 'message-mail 229 :group 'message-mail
231 :type 'boolean) 230 :type 'boolean)
244 "*Non-nil means that the message buffer will be killed after sending a message." 243 "*Non-nil means that the message buffer will be killed after sending a message."
245 :group 'message-buffers 244 :group 'message-buffers
246 :type 'boolean) 245 :type 'boolean)
247 246
248 (defvar gnus-local-organization) 247 (defvar gnus-local-organization)
249 (defcustom message-user-organization 248 (defcustom message-user-organization
250 (or (and (boundp 'gnus-local-organization) 249 (or (and (boundp 'gnus-local-organization)
251 (stringp gnus-local-organization) 250 (stringp gnus-local-organization)
252 gnus-local-organization) 251 gnus-local-organization)
253 (getenv "ORGANIZATION") 252 (getenv "ORGANIZATION")
254 t) 253 t)
269 "*Directory where message autosaves buffers. 268 "*Directory where message autosaves buffers.
270 If nil, message won't autosave." 269 If nil, message won't autosave."
271 :group 'message-buffers 270 :group 'message-buffers
272 :type 'directory) 271 :type 'directory)
273 272
274 (defcustom message-forward-start-separator 273 (defcustom message-forward-start-separator
275 "------- Start of forwarded message -------\n" 274 "------- Start of forwarded message -------\n"
276 "*Delimiter inserted before forwarded messages." 275 "*Delimiter inserted before forwarded messages."
277 :group 'message-forwarding 276 :group 'message-forwarding
278 :type 'string) 277 :type 'string)
279 278
286 (defcustom message-signature-before-forwarded-message t 285 (defcustom message-signature-before-forwarded-message t
287 "*If non-nil, put the signature before any included forwarded message." 286 "*If non-nil, put the signature before any included forwarded message."
288 :group 'message-forwarding 287 :group 'message-forwarding
289 :type 'boolean) 288 :type 'boolean)
290 289
291 (defcustom message-included-forward-headers 290 (defcustom message-included-forward-headers
292 "^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:" 291 "^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:"
293 "*Regexp matching headers to be included in forwarded messages." 292 "*Regexp matching headers to be included in forwarded messages."
294 :group 'message-forwarding 293 :group 'message-forwarding
295 :type 'regexp) 294 :type 'regexp)
296 295
388 :group 'message-sending 387 :group 'message-sending
389 :type '(repeat string)) 388 :type '(repeat string))
390 389
391 (defvar gnus-post-method) 390 (defvar gnus-post-method)
392 (defvar gnus-select-method) 391 (defvar gnus-select-method)
393 (defcustom message-post-method 392 (defcustom message-post-method
394 (cond ((and (boundp 'gnus-post-method) 393 (cond ((and (boundp 'gnus-post-method)
395 gnus-post-method) 394 gnus-post-method)
396 gnus-post-method) 395 gnus-post-method)
397 ((boundp 'gnus-select-method) 396 ((boundp 'gnus-select-method)
398 gnus-select-method) 397 gnus-select-method)
415 :group 'message-various 414 :group 'message-various
416 :type 'hook) 415 :type 'hook)
417 416
418 (defcustom message-signature-setup-hook nil 417 (defcustom message-signature-setup-hook nil
419 "Normal hook, run each time a new outgoing message is initialized. 418 "Normal hook, run each time a new outgoing message is initialized.
420 It is run after the headers have been inserted and before 419 It is run after the headers have been inserted and before
421 the signature is inserted." 420 the signature is inserted."
422 :group 'message-various 421 :group 'message-various
423 :type 'hook) 422 :type 'hook)
424 423
425 (defcustom message-mode-hook nil 424 (defcustom message-mode-hook nil
554 :type 'string) 553 :type 'string)
555 554
556 ;; Note: could use /usr/ucb/mail instead of sendmail; 555 ;; Note: could use /usr/ucb/mail instead of sendmail;
557 ;; options -t, and -v if not interactive. 556 ;; options -t, and -v if not interactive.
558 (defcustom message-mailer-swallows-blank-line 557 (defcustom message-mailer-swallows-blank-line
559 (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)" 558 (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)"
560 system-configuration) 559 system-configuration)
561 (file-readable-p "/etc/sendmail.cf") 560 (file-readable-p "/etc/sendmail.cf")
562 (let ((buffer (get-buffer-create " *temp*"))) 561 (let ((buffer (get-buffer-create " *temp*")))
563 (unwind-protect 562 (unwind-protect
564 (save-excursion 563 (save-excursion
580 :group 'message-sending 579 :group 'message-sending
581 :type 'sexp) 580 :type 'sexp)
582 581
583 (ignore-errors 582 (ignore-errors
584 (define-mail-user-agent 'message-user-agent 583 (define-mail-user-agent 'message-user-agent
585 'message-mail 'message-send-and-exit 584 'message-mail 'message-send-and-exit
586 'message-kill-buffer 'message-send-hook)) 585 'message-kill-buffer 'message-send-hook))
587 586
588 (defvar message-mh-deletable-headers '(Message-ID Date Lines Sender) 587 (defvar message-mh-deletable-headers '(Message-ID Date Lines Sender)
589 "If non-nil, delete the deletable headers before feeding to mh.") 588 "If non-nil, delete the deletable headers before feeding to mh.")
590 589
591 ;;; Internal variables. 590 ;;; Internal variables.
592 ;;; Well, not really internal. 591 ;;; Well, not really internal.
593 592
594 (defvar message-mode-syntax-table 593 (defvar message-mode-syntax-table
595 (let ((table (copy-syntax-table text-mode-syntax-table))) 594 (let ((table (copy-syntax-table text-mode-syntax-table)))
596 (modify-syntax-entry ?% ". " table) 595 (modify-syntax-entry ?% ". " table)
597 table) 596 table)
598 "Syntax table used while in Message mode.") 597 "Syntax table used while in Message mode.")
599 598
600 (defvar message-mode-abbrev-table text-mode-abbrev-table 599 (defvar message-mode-abbrev-table text-mode-abbrev-table
601 "Abbrev table used in Message mode buffers. 600 "Abbrev table used in Message mode buffers.
602 Defaults to `text-mode-abbrev-table'.") 601 Defaults to `text-mode-abbrev-table'.")
602 (defgroup message-headers nil
603 "Message headers."
604 :link '(custom-manual "(message)Variables")
605 :group 'message)
606
607 (defface message-header-to-face
608 '((((class color)
609 (background dark))
610 (:foreground "green2" :bold t))
611 (((class color)
612 (background light))
613 (:foreground "MidnightBlue" :bold t))
614 (t
615 (:bold t :italic t)))
616 "Face used for displaying From headers."
617 :group 'message-headers)
618
619 (defface message-header-cc-face
620 '((((class color)
621 (background dark))
622 (:foreground "green4" :bold t))
623 (((class color)
624 (background light))
625 (:foreground "MidnightBlue"))
626 (t
627 (:bold t)))
628 "Face used for displaying Cc headers."
629 :group 'message-headers)
630
631 (defface message-header-subject-face
632 '((((class color)
633 (background dark))
634 (:foreground "green3"))
635 (((class color)
636 (background light))
637 (:foreground "navy blue" :bold t))
638 (t
639 (:bold t)))
640 "Face used for displaying subject headers."
641 :group 'message-headers)
642
643 (defface message-header-newsgroups-face
644 '((((class color)
645 (background dark))
646 (:foreground "yellow" :bold t :italic t))
647 (((class color)
648 (background light))
649 (:foreground "blue4" :bold t :italic t))
650 (t
651 (:bold t :italic t)))
652 "Face used for displaying newsgroups headers."
653 :group 'message-headers)
654
655 (defface message-header-other-face
656 '((((class color)
657 (background dark))
658 (:foreground "red4"))
659 (((class color)
660 (background light))
661 (:foreground "steel blue"))
662 (t
663 (:bold t :italic t)))
664 "Face used for displaying newsgroups headers."
665 :group 'message-headers)
666
667 (defface message-header-name-face
668 '((((class color)
669 (background dark))
670 (:foreground "DarkGreen"))
671 (((class color)
672 (background light))
673 (:foreground "cornflower blue"))
674 (t
675 (:bold t)))
676 "Face used for displaying header names."
677 :group 'message-headers)
678
679 (defface message-header-xheader-face
680 '((((class color)
681 (background dark))
682 (:foreground "blue"))
683 (((class color)
684 (background light))
685 (:foreground "blue"))
686 (t
687 (:bold t)))
688 "Face used for displaying X-Header headers."
689 :group 'message-headers)
690
691 (defface message-separator-face
692 '((((class color)
693 (background dark))
694 (:foreground "blue4"))
695 (((class color)
696 (background light))
697 (:foreground "brown"))
698 (t
699 (:bold t)))
700 "Face used for displaying the separator."
701 :group 'message-headers)
702
703 (defface message-cited-text-face
704 '((((class color)
705 (background dark))
706 (:foreground "red"))
707 (((class color)
708 (background light))
709 (:foreground "red"))
710 (t
711 (:bold t)))
712 "Face used for displaying cited text names."
713 :group 'message-headers)
603 714
604 (defvar message-font-lock-keywords 715 (defvar message-font-lock-keywords
605 (let* ((cite-prefix "A-Za-z") (cite-suffix (concat cite-prefix "0-9_.@-"))) 716 (let* ((cite-prefix "A-Za-z")
606 (list '("^To:" . font-lock-function-name-face) 717 (cite-suffix (concat cite-prefix "0-9_.@-"))
607 '("^[GBF]?[Cc][Cc]:\\|^Reply-To:" . font-lock-keyword-face) 718 (content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)"))
608 '("^\\(Subject:\\)[ \t]*\\(.+\\)?" 719 `((,(concat "^\\(To:\\)" content)
609 (1 font-lock-comment-face) (2 font-lock-type-face nil t)) 720 (1 'message-header-name-face)
610 (list (concat "^\\(" (regexp-quote mail-header-separator) "\\)$") 721 (2 'message-header-to-face nil t))
611 1 'font-lock-comment-face) 722 (,(concat "^\\(^[GBF]?[Cc][Cc]:\\|^Reply-To:\\)" content)
612 (cons (concat "^[ \t]*" 723 (1 'message-header-name-face)
613 "\\([" cite-prefix "]+[" cite-suffix "]*\\)?" 724 (2 'message-header-cc-face nil t))
614 "[>|}].*") 725 (,(concat "^\\(Subject:\\)" content)
615 'font-lock-reference-face) 726 (1 'message-header-name-face)
616 '("^\\(X-[A-Za-z0-9-]+\\|In-Reply-To\\):.*" 727 (2 'message-header-subject-face nil t))
617 . font-lock-string-face))) 728 (,(concat "^\\(Newsgroups:\\|Followup-to:\\)" content)
729 (1 'message-header-name-face)
730 (2 'message-header-newsgroups-face nil t))
731 (,(concat "^\\([^: \n\t]+:\\)" content)
732 (1 'message-header-name-face)
733 (2 'message-header-other-face nil t))
734 (,(concat "^\\(X-[A-Za-z0-9-]+\\|In-Reply-To\\):" content)
735 (1 'message-header-name-face)
736 (2 'message-header-name-face))
737 (,(concat "^\\(" (regexp-quote mail-header-separator) "\\)$")
738 1 'message-separator-face)
739 (,(concat "^[ \t]*"
740 "\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
741 "[>|}].*")
742 (0 'message-cited-text-face))))
618 "Additional expressions to highlight in Message mode.") 743 "Additional expressions to highlight in Message mode.")
619 744
620 (defvar message-face-alist 745 (defvar message-face-alist
621 '((bold . bold-region) 746 '((bold . bold-region)
622 (underline . underline-region) 747 (underline . underline-region)
623 (default . (lambda (b e) 748 (default . (lambda (b e)
624 (unbold-region b e) 749 (unbold-region b e)
625 (ununderline-region b e)))) 750 (ununderline-region b e))))
626 "Alist of mail and news faces for facemenu. 751 "Alist of mail and news faces for facemenu.
627 The cdr of ech entry is a function for applying the face to a region.") 752 The cdr of ech entry is a function for applying the face to a region.")
628 753
656 ;; Byte-compiler warning 781 ;; Byte-compiler warning
657 (defvar gnus-active-hashtb) 782 (defvar gnus-active-hashtb)
658 (defvar gnus-read-active-file) 783 (defvar gnus-read-active-file)
659 784
660 ;;; Regexp matching the delimiter of messages in UNIX mail format 785 ;;; Regexp matching the delimiter of messages in UNIX mail format
661 ;;; (UNIX From lines), minus the initial ^. 786 ;;; (UNIX From lines), minus the initial ^.
662 (defvar message-unix-mail-delimiter 787 (defvar message-unix-mail-delimiter
663 (let ((time-zone-regexp 788 (let ((time-zone-regexp
664 (concat "\\([A-Z]?[A-Z]?[A-Z][A-Z]\\( DST\\)?" 789 (concat "\\([A-Z]?[A-Z]?[A-Z][A-Z]\\( DST\\)?"
665 "\\|[-+]?[0-9][0-9][0-9][0-9]" 790 "\\|[-+]?[0-9][0-9][0-9][0-9]"
666 "\\|" 791 "\\|"
704 "^ *--+ +begin message +--+ *$\\|" 829 "^ *--+ +begin message +--+ *$\\|"
705 "^ *---+ +Original message follows +---+ *$\\|" 830 "^ *---+ +Original message follows +---+ *$\\|"
706 "^|? *---+ +Message text follows: +---+ *|?$") 831 "^|? *---+ +Message text follows: +---+ *|?$")
707 "A regexp that matches the separator before the text of a failed message.") 832 "A regexp that matches the separator before the text of a failed message.")
708 833
709 (defvar message-header-format-alist 834 (defvar message-header-format-alist
710 `((Newsgroups) 835 `((Newsgroups)
711 (To . message-fill-address) 836 (To . message-fill-address)
712 (Cc . message-fill-address) 837 (Cc . message-fill-address)
713 (Subject) 838 (Subject)
714 (In-Reply-To) 839 (In-Reply-To)
715 (Fcc) 840 (Fcc)
716 (Bcc) 841 (Bcc)
729 (autoload 'message-setup-toolbar "messagexmas") 854 (autoload 'message-setup-toolbar "messagexmas")
730 (autoload 'mh-send-letter "mh-comp") 855 (autoload 'mh-send-letter "mh-comp")
731 (autoload 'gnus-point-at-eol "gnus-util") 856 (autoload 'gnus-point-at-eol "gnus-util")
732 (autoload 'gnus-point-at-bol "gnus-util") 857 (autoload 'gnus-point-at-bol "gnus-util")
733 (autoload 'gnus-output-to-mail "gnus-util") 858 (autoload 'gnus-output-to-mail "gnus-util")
734 (autoload 'gnus-output-to-rmail "gnus-util")) 859 (autoload 'gnus-output-to-rmail "gnus-util")
860 (autoload 'mail-abbrev-in-expansion-header-p "mailabbrev"))
735 861
736 862
737 863
738 ;;; 864 ;;;
739 ;;; Utility functions. 865 ;;; Utility functions.
740 ;;; 866 ;;;
741 867
742 (defmacro message-y-or-n-p (question show &rest text) 868 (defmacro message-y-or-n-p (question show &rest text)
743 "Ask QUESTION, displaying the rest of the arguments in a temp. buffer if SHOW" 869 "Ask QUESTION, displaying the rest of the arguments in a temp. buffer if SHOW"
780 ((and (= (following-char) ?\)) 906 ((and (= (following-char) ?\))
781 (not quoted)) 907 (not quoted))
782 (setq paren nil)))) 908 (setq paren nil))))
783 (nreverse elems))))) 909 (nreverse elems)))))
784 910
911 (defun message-mail-file-mbox-p (file)
912 "Say whether FILE looks like a Unix mbox file."
913 (when (and (file-exists-p file)
914 (file-readable-p file)
915 (file-regular-p file))
916 (nnheader-temp-write nil
917 (nnheader-insert-file-contents file)
918 (goto-char (point-min))
919 (looking-at message-unix-mail-delimiter))))
920
785 (defun message-fetch-field (header &optional not-all) 921 (defun message-fetch-field (header &optional not-all)
786 "The same as `mail-fetch-field', only remove all newlines." 922 "The same as `mail-fetch-field', only remove all newlines."
787 (let ((value (mail-fetch-field header nil (not not-all)))) 923 (let ((value (mail-fetch-field header nil (not not-all))))
788 (when value 924 (when value
789 (nnheader-replace-chars-in-string value ?\n ? )))) 925 (nnheader-replace-chars-in-string value ?\n ? ))))
894 (beginning-of-line) 1030 (beginning-of-line)
895 (or (eobp) (forward-char 1)) 1031 (or (eobp) (forward-char 1))
896 (not (if (re-search-forward "^[^ \t]" nil t) 1032 (not (if (re-search-forward "^[^ \t]" nil t)
897 (beginning-of-line) 1033 (beginning-of-line)
898 (goto-char (point-max))))) 1034 (goto-char (point-max)))))
899 1035
900 (defun message-sort-headers-1 () 1036 (defun message-sort-headers-1 ()
901 "Sort the buffer as headers using `message-rank' text props." 1037 "Sort the buffer as headers using `message-rank' text props."
902 (goto-char (point-min)) 1038 (goto-char (point-min))
903 (sort-subr 1039 (sort-subr
904 nil 'message-next-header 1040 nil 'message-next-header
905 (lambda () 1041 (lambda ()
906 (message-next-header) 1042 (message-next-header)
907 (unless (bobp) 1043 (unless (bobp)
908 (forward-char -1))) 1044 (forward-char -1)))
909 (lambda () 1045 (lambda ()
959 (define-key message-mode-map "\C-c\C-b" 'message-goto-body) 1095 (define-key message-mode-map "\C-c\C-b" 'message-goto-body)
960 (define-key message-mode-map "\C-c\C-i" 'message-goto-signature) 1096 (define-key message-mode-map "\C-c\C-i" 'message-goto-signature)
961 1097
962 (define-key message-mode-map "\C-c\C-t" 'message-insert-to) 1098 (define-key message-mode-map "\C-c\C-t" 'message-insert-to)
963 (define-key message-mode-map "\C-c\C-n" 'message-insert-newsgroups) 1099 (define-key message-mode-map "\C-c\C-n" 'message-insert-newsgroups)
964 1100
965 (define-key message-mode-map "\C-c\C-y" 'message-yank-original) 1101 (define-key message-mode-map "\C-c\C-y" 'message-yank-original)
966 (define-key message-mode-map "\C-c\C-q" 'message-fill-yanked-message) 1102 (define-key message-mode-map "\C-c\C-q" 'message-fill-yanked-message)
967 (define-key message-mode-map "\C-c\C-w" 'message-insert-signature) 1103 (define-key message-mode-map "\C-c\C-w" 'message-insert-signature)
968 (define-key message-mode-map "\C-c\C-r" 'message-caesar-buffer-body) 1104 (define-key message-mode-map "\C-c\C-r" 'message-caesar-buffer-body)
969 (define-key message-mode-map "\C-c\C-o" 'message-sort-headers) 1105 (define-key message-mode-map "\C-c\C-o" 'message-sort-headers)
976 1112
977 (define-key message-mode-map "\C-c\C-e" 'message-elide-region) 1113 (define-key message-mode-map "\C-c\C-e" 'message-elide-region)
978 1114
979 (define-key message-mode-map "\t" 'message-tab)) 1115 (define-key message-mode-map "\t" 'message-tab))
980 1116
981 (easy-menu-define 1117 (easy-menu-define
982 message-mode-menu message-mode-map "Message Menu." 1118 message-mode-menu message-mode-map "Message Menu."
983 '("Message" 1119 '("Message"
984 ["Sort Headers" message-sort-headers t] 1120 ["Sort Headers" message-sort-headers t]
985 ["Yank Original" message-yank-original t] 1121 ["Yank Original" message-yank-original t]
986 ["Fill Yanked Message" message-fill-yanked-message t] 1122 ["Fill Yanked Message" message-fill-yanked-message t]
992 ["Spellcheck" ispell-message t] 1128 ["Spellcheck" ispell-message t]
993 "----" 1129 "----"
994 ["Send Message" message-send-and-exit t] 1130 ["Send Message" message-send-and-exit t]
995 ["Abort Message" message-dont-send t])) 1131 ["Abort Message" message-dont-send t]))
996 1132
997 (easy-menu-define 1133 (easy-menu-define
998 message-mode-field-menu message-mode-map "" 1134 message-mode-field-menu message-mode-map ""
999 '("Field" 1135 '("Field"
1000 ["Fetch To" message-insert-to t] 1136 ["Fetch To" message-insert-to t]
1001 ["Fetch Newsgroups" message-insert-newsgroups t] 1137 ["Fetch Newsgroups" message-insert-newsgroups t]
1002 "----" 1138 "----"
1175 1311
1176 (defun message-insert-to () 1312 (defun message-insert-to ()
1177 "Insert a To header that points to the author of the article being replied to." 1313 "Insert a To header that points to the author of the article being replied to."
1178 (interactive) 1314 (interactive)
1179 (let ((co (message-fetch-field "courtesy-copies-to"))) 1315 (let ((co (message-fetch-field "courtesy-copies-to")))
1180 (when (and co 1316 (when (and co
1181 (equal (downcase co) "never")) 1317 (equal (downcase co) "never"))
1182 (error "The user has requested not to have copies sent via mail"))) 1318 (error "The user has requested not to have copies sent via mail")))
1183 (when (and (message-position-on-field "To") 1319 (when (and (message-position-on-field "To")
1184 (mail-fetch-field "to") 1320 (mail-fetch-field "to")
1185 (not (string-match "\\` *\\'" (mail-fetch-field "to")))) 1321 (not (string-match "\\` *\\'" (mail-fetch-field "to"))))
1201 ;;; Various commands 1337 ;;; Various commands
1202 1338
1203 (defun message-insert-signature (&optional force) 1339 (defun message-insert-signature (&optional force)
1204 "Insert a signature. See documentation for the `message-signature' variable." 1340 "Insert a signature. See documentation for the `message-signature' variable."
1205 (interactive (list 0)) 1341 (interactive (list 0))
1206 (let* ((signature 1342 (let* ((signature
1207 (cond 1343 (cond
1208 ((and (null message-signature) 1344 ((and (null message-signature)
1209 (eq force 0)) 1345 (eq force 0))
1210 (save-excursion 1346 (save-excursion
1211 (goto-char (point-max)) 1347 (goto-char (point-max))
1264 ;; We build the table, if necessary. 1400 ;; We build the table, if necessary.
1265 (when (or (not message-caesar-translation-table) 1401 (when (or (not message-caesar-translation-table)
1266 (/= (aref message-caesar-translation-table ?a) (+ ?a n))) 1402 (/= (aref message-caesar-translation-table ?a) (+ ?a n)))
1267 (setq message-caesar-translation-table 1403 (setq message-caesar-translation-table
1268 (message-make-caesar-translation-table n))) 1404 (message-make-caesar-translation-table n)))
1269 ;; Then we translate the region. Do it this way to retain 1405 ;; Then we translate the region. Do it this way to retain
1270 ;; text properties. 1406 ;; text properties.
1271 (while (< b e) 1407 (while (< b e)
1272 (subst-char-in-region 1408 (subst-char-in-region
1273 b (1+ b) (char-after b) 1409 b (1+ b) (char-after b)
1274 (aref message-caesar-translation-table (char-after b))) 1410 (aref message-caesar-translation-table (char-after b)))
1275 (incf b)))) 1411 (incf b))))
1276 1412
1277 (defun message-make-caesar-translation-table (n) 1413 (defun message-make-caesar-translation-table (n)
1278 "Create a rot table with offset N." 1414 "Create a rot table with offset N."
1279 (let ((i -1) 1415 (let ((i -1)
1280 (table (make-string 256 0))) 1416 (table (make-string 256 0)))
1281 (while (< (incf i) 256) 1417 (while (< (incf i) 256)
1282 (aset table i i)) 1418 (aset table i i))
1283 (concat 1419 (concat
1284 (substring table 0 ?A) 1420 (substring table 0 ?A)
1311 (narrow-to-region (point) (point-max))) 1447 (narrow-to-region (point) (point-max)))
1312 (let ((body (buffer-substring (point-min) (point-max)))) 1448 (let ((body (buffer-substring (point-min) (point-max))))
1313 (unless (equal 0 (call-process-region 1449 (unless (equal 0 (call-process-region
1314 (point-min) (point-max) program t t)) 1450 (point-min) (point-max) program t t))
1315 (insert body) 1451 (insert body)
1316 (gnus-message 1 "%s failed." program)))))) 1452 (message "%s failed." program))))))
1317 1453
1318 (defun message-rename-buffer (&optional enter-string) 1454 (defun message-rename-buffer (&optional enter-string)
1319 "Rename the *message* buffer to \"*message* RECIPIENT\". 1455 "Rename the *message* buffer to \"*message* RECIPIENT\".
1320 If the function is run with a prefix, it will ask for a new buffer 1456 If the function is run with a prefix, it will ask for a new buffer
1321 name, rather than giving an automatic name." 1457 name, rather than giving an automatic name."
1322 (interactive "Pbuffer name: ") 1458 (interactive "Pbuffer name: ")
1323 (save-excursion 1459 (save-excursion
1324 (save-restriction 1460 (save-restriction
1325 (goto-char (point-min)) 1461 (goto-char (point-min))
1326 (narrow-to-region (point) 1462 (narrow-to-region (point)
1327 (search-forward mail-header-separator nil 'end)) 1463 (search-forward mail-header-separator nil 'end))
1328 (let* ((mail-to (or 1464 (let* ((mail-to (or
1329 (if (message-news-p) (message-fetch-field "Newsgroups") 1465 (if (message-news-p) (message-fetch-field "Newsgroups")
1330 (message-fetch-field "To")) 1466 (message-fetch-field "To"))
1331 "")) 1467 ""))
1360 However, if `message-yank-prefix' is non-nil, insert that prefix on each line." 1496 However, if `message-yank-prefix' is non-nil, insert that prefix on each line."
1361 (let ((start (point))) 1497 (let ((start (point)))
1362 ;; Remove unwanted headers. 1498 ;; Remove unwanted headers.
1363 (when message-ignored-cited-headers 1499 (when message-ignored-cited-headers
1364 (save-restriction 1500 (save-restriction
1365 (narrow-to-region 1501 (narrow-to-region
1366 (goto-char start) 1502 (goto-char start)
1367 (if (search-forward "\n\n" nil t) 1503 (if (search-forward "\n\n" nil t)
1368 (1- (point)) 1504 (1- (point))
1369 (point))) 1505 (point)))
1370 (message-remove-header message-ignored-cited-headers t) 1506 (message-remove-header message-ignored-cited-headers t)
1415 (setq message-checksum (cons (message-checksum) (buffer-size))))))) 1551 (setq message-checksum (cons (message-checksum) (buffer-size)))))))
1416 1552
1417 (defun message-cite-original () 1553 (defun message-cite-original ()
1418 "Cite function in the standard Message manner." 1554 "Cite function in the standard Message manner."
1419 (let ((start (point)) 1555 (let ((start (point))
1420 (functions 1556 (functions
1421 (when message-indent-citation-function 1557 (when message-indent-citation-function
1422 (if (listp message-indent-citation-function) 1558 (if (listp message-indent-citation-function)
1423 message-indent-citation-function 1559 message-indent-citation-function
1424 (list message-indent-citation-function))))) 1560 (list message-indent-citation-function)))))
1425 (goto-char start) 1561 (goto-char start)
1439 (let ((case-fold-search t)) 1575 (let ((case-fold-search t))
1440 (save-restriction 1576 (save-restriction
1441 (narrow-to-region 1577 (narrow-to-region
1442 (goto-char (point-min)) 1578 (goto-char (point-min))
1443 (progn 1579 (progn
1444 (re-search-forward 1580 (re-search-forward
1445 (concat "^" (regexp-quote mail-header-separator) "$")) 1581 (concat "^" (regexp-quote mail-header-separator) "$"))
1446 (match-beginning 0))) 1582 (match-beginning 0)))
1447 (goto-char (point-min)) 1583 (goto-char (point-min))
1448 (if (re-search-forward (concat "^" (regexp-quote header) ":") nil t) 1584 (if (re-search-forward (concat "^" (regexp-quote header) ":") nil t)
1449 (progn 1585 (progn
1450 (re-search-forward "^[^ \t]" nil 'move) 1586 (re-search-forward "^[^ \t]" nil 'move)
1451 (beginning-of-line) 1587 (beginning-of-line)
1452 (skip-chars-backward "\n") 1588 (skip-chars-backward "\n")
1453 t) 1589 t)
1454 (while (and afters 1590 (while (and afters
1455 (not (re-search-forward 1591 (not (re-search-forward
1456 (concat "^" (regexp-quote (car afters)) ":") 1592 (concat "^" (regexp-quote (car afters)) ":")
1457 nil t))) 1593 nil t)))
1458 (pop afters)) 1594 (pop afters))
1459 (when afters 1595 (when afters
1460 (re-search-forward "^[^ \t]" nil 'move) 1596 (re-search-forward "^[^ \t]" nil 'move)
1513 (message-do-actions actions))) 1649 (message-do-actions actions)))
1514 1650
1515 (defun message-kill-buffer () 1651 (defun message-kill-buffer ()
1516 "Kill the current buffer." 1652 "Kill the current buffer."
1517 (interactive) 1653 (interactive)
1518 (let ((actions message-kill-actions)) 1654 (when (yes-or-no-p "Kill the buffer? ")
1519 (kill-buffer (current-buffer)) 1655 (let ((actions message-kill-actions))
1520 (message-do-actions actions))) 1656 (kill-buffer (current-buffer))
1657 (message-do-actions actions))))
1521 1658
1522 (defun message-bury (buffer) 1659 (defun message-bury (buffer)
1523 "Bury this mail buffer." 1660 "Bury this mail buffer."
1524 (let ((newbuf (other-buffer buffer))) 1661 (let ((newbuf (other-buffer buffer)))
1525 (bury-buffer buffer) 1662 (bury-buffer buffer)
1592 (defun message-do-actions (actions) 1729 (defun message-do-actions (actions)
1593 "Perform all actions in ACTIONS." 1730 "Perform all actions in ACTIONS."
1594 ;; Now perform actions on successful sending. 1731 ;; Now perform actions on successful sending.
1595 (while actions 1732 (while actions
1596 (ignore-errors 1733 (ignore-errors
1597 (cond 1734 (cond
1598 ;; A simple function. 1735 ;; A simple function.
1599 ((message-functionp (car actions)) 1736 ((message-functionp (car actions))
1600 (funcall (car actions))) 1737 (funcall (car actions)))
1601 ;; Something to be evaled. 1738 ;; Something to be evaled.
1602 (t 1739 (t
1620 (unwind-protect 1757 (unwind-protect
1621 (save-excursion 1758 (save-excursion
1622 (set-buffer tembuf) 1759 (set-buffer tembuf)
1623 (erase-buffer) 1760 (erase-buffer)
1624 ;; Avoid copying text props. 1761 ;; Avoid copying text props.
1625 (insert (format 1762 (insert (format
1626 "%s" (save-excursion 1763 "%s" (save-excursion
1627 (set-buffer mailbuf) 1764 (set-buffer mailbuf)
1628 (buffer-string)))) 1765 (buffer-string))))
1629 ;; Remove some headers. 1766 ;; Remove some headers.
1630 (save-restriction 1767 (save-restriction
1730 ;; reading a formatted (i. e., at least a To: or Resent-To header) 1867 ;; reading a formatted (i. e., at least a To: or Resent-To header)
1731 ;; message from stdin. 1868 ;; message from stdin.
1732 ;; 1869 ;;
1733 ;; qmail also has the advantage of not having been raped by 1870 ;; qmail also has the advantage of not having been raped by
1734 ;; various vendors, so we don't have to allow for that, either -- 1871 ;; various vendors, so we don't have to allow for that, either --
1735 ;; compare this with message-send-mail-with-sendmail and weep 1872 ;; compare this with message-send-mail-with-sendmail and weep
1736 ;; for sendmail's lost innocence. 1873 ;; for sendmail's lost innocence.
1737 ;; 1874 ;;
1738 ;; all this is way cool coz it lets us keep the arguments entirely 1875 ;; all this is way cool coz it lets us keep the arguments entirely
1739 ;; free for -inject-arguments -- a big win for the user and for us 1876 ;; free for -inject-arguments -- a big win for the user and for us
1740 ;; since we don't have to play that double-guessing game and the user 1877 ;; since we don't have to play that double-guessing game and the user
1750 1887
1751 (defun message-send-mail-with-mh () 1888 (defun message-send-mail-with-mh ()
1752 "Send the prepared message buffer with mh." 1889 "Send the prepared message buffer with mh."
1753 (let ((mh-previous-window-config nil) 1890 (let ((mh-previous-window-config nil)
1754 (name (make-temp-name 1891 (name (make-temp-name
1755 (concat (file-name-as-directory 1892 (concat (file-name-as-directory
1756 (expand-file-name message-autosave-directory)) 1893 (expand-file-name message-autosave-directory))
1757 "msg.")))) 1894 "msg."))))
1758 (setq buffer-file-name name) 1895 (setq buffer-file-name name)
1759 ;; MH wants to generate these headers itself. 1896 ;; MH wants to generate these headers itself.
1760 (when message-mh-deletable-headers 1897 (when message-mh-deletable-headers
1761 (let ((headers message-mh-deletable-headers)) 1898 (let ((headers message-mh-deletable-headers))
1762 (while headers 1899 (while headers
1763 (goto-char (point-min)) 1900 (goto-char (point-min))
1764 (and (re-search-forward 1901 (and (re-search-forward
1765 (concat "^" (symbol-name (car headers)) ": *") nil t) 1902 (concat "^" (symbol-name (car headers)) ": *") nil t)
1766 (message-delete-line)) 1903 (message-delete-line))
1767 (pop headers)))) 1904 (pop headers))))
1768 (run-hooks 'message-send-mail-hook) 1905 (run-hooks 'message-send-mail-hook)
1769 ;; Pass it on to mh. 1906 ;; Pass it on to mh.
1795 nil) 1932 nil)
1796 (unwind-protect 1933 (unwind-protect
1797 (save-excursion 1934 (save-excursion
1798 (set-buffer tembuf) 1935 (set-buffer tembuf)
1799 (buffer-disable-undo (current-buffer)) 1936 (buffer-disable-undo (current-buffer))
1800 (erase-buffer) 1937 (erase-buffer)
1801 ;; Avoid copying text props. 1938 ;; Avoid copying text props.
1802 (insert (format 1939 (insert (format
1803 "%s" (save-excursion 1940 "%s" (save-excursion
1804 (set-buffer messbuf) 1941 (set-buffer messbuf)
1805 (buffer-string)))) 1942 (buffer-string))))
1806 ;; Remove some headers. 1943 ;; Remove some headers.
1807 (save-restriction 1944 (save-restriction
1857 (defun message-check-news-syntax () 1994 (defun message-check-news-syntax ()
1858 "Check the syntax of the message." 1995 "Check the syntax of the message."
1859 (save-excursion 1996 (save-excursion
1860 (save-restriction 1997 (save-restriction
1861 (widen) 1998 (widen)
1862 (and 1999 (and
1863 ;; We narrow to the headers and check them first. 2000 ;; We narrow to the headers and check them first.
1864 (save-excursion 2001 (save-excursion
1865 (save-restriction 2002 (save-restriction
1866 (message-narrow-to-headers) 2003 (message-narrow-to-headers)
1867 (message-check-news-header-syntax))) 2004 (message-check-news-header-syntax)))
1868 ;; Check the body. 2005 ;; Check the body.
1869 (message-check-news-body-syntax))))) 2006 (message-check-news-body-syntax)))))
1870 2007
1871 (defun message-check-news-header-syntax () 2008 (defun message-check-news-header-syntax ()
1872 (and 2009 (and
1873 ;; Check for commands in Subject. 2010 ;; Check for commands in Subject.
1874 (message-check 'subject-cmsg 2011 (message-check 'subject-cmsg
1875 (if (string-match "^cmsg " (message-fetch-field "subject")) 2012 (if (string-match "^cmsg " (message-fetch-field "subject"))
1876 (y-or-n-p 2013 (y-or-n-p
1877 "The control code \"cmsg\" is in the subject. Really post? ") 2014 "The control code \"cmsg\" is in the subject. Really post? ")
1878 t)) 2015 t))
1879 ;; Check for multiple identical headers. 2016 ;; Check for multiple identical headers.
1880 (message-check 'multiple-headers 2017 (message-check 'multiple-headers
1881 (let (found) 2018 (let (found)
1882 (while (and (not found) 2019 (while (and (not found)
1883 (re-search-forward "^[^ \t:]+: " nil t)) 2020 (re-search-forward "^[^ \t:]+: " nil t))
1884 (save-excursion 2021 (save-excursion
1885 (or (re-search-forward 2022 (or (re-search-forward
1886 (concat "^" 2023 (concat "^"
1887 (regexp-quote 2024 (regexp-quote
1888 (setq found 2025 (setq found
1889 (buffer-substring 2026 (buffer-substring
1890 (match-beginning 0) (- (match-end 0) 2)))) 2027 (match-beginning 0) (- (match-end 0) 2))))
1891 ":") 2028 ":")
1897 ;; Check for Version and Sendsys. 2034 ;; Check for Version and Sendsys.
1898 (message-check 'sendsys 2035 (message-check 'sendsys
1899 (if (re-search-forward "^Sendsys:\\|^Version:" nil t) 2036 (if (re-search-forward "^Sendsys:\\|^Version:" nil t)
1900 (y-or-n-p 2037 (y-or-n-p
1901 (format "The article contains a %s command. Really post? " 2038 (format "The article contains a %s command. Really post? "
1902 (buffer-substring (match-beginning 0) 2039 (buffer-substring (match-beginning 0)
1903 (1- (match-end 0))))) 2040 (1- (match-end 0)))))
1904 t)) 2041 t))
1905 ;; See whether we can shorten Followup-To. 2042 ;; See whether we can shorten Followup-To.
1906 (message-check 'shorten-followup-to 2043 (message-check 'shorten-followup-to
1907 (let ((newsgroups (message-fetch-field "newsgroups")) 2044 (let ((newsgroups (message-fetch-field "newsgroups"))
1911 (string-match "," newsgroups) 2048 (string-match "," newsgroups)
1912 (not followup-to) 2049 (not followup-to)
1913 (not 2050 (not
1914 (zerop 2051 (zerop
1915 (length 2052 (length
1916 (setq to (completing-read 2053 (setq to (completing-read
1917 "Followups to: (default all groups) " 2054 "Followups to: (default all groups) "
1918 (mapcar (lambda (g) (list g)) 2055 (mapcar (lambda (g) (list g))
1919 (cons "poster" 2056 (cons "poster"
1920 (message-tokenize-header 2057 (message-tokenize-header
1921 newsgroups))))))))) 2058 newsgroups)))))))))
1922 (goto-char (point-min)) 2059 (goto-char (point-min))
1923 (insert "Followup-To: " to "\n")) 2060 (insert "Followup-To: " to "\n"))
1924 t)) 2061 t))
1925 ;; Check "Shoot me". 2062 ;; Check "Shoot me".
1949 (subject (message-fetch-field "subject"))) 2086 (subject (message-fetch-field "subject")))
1950 (or 2087 (or
1951 (and subject 2088 (and subject
1952 (not (string-match "\\`[ \t]*\\'" subject))) 2089 (not (string-match "\\`[ \t]*\\'" subject)))
1953 (ignore 2090 (ignore
1954 (message 2091 (message
1955 "The subject field is empty or missing. Posting is denied."))))) 2092 "The subject field is empty or missing. Posting is denied.")))))
1956 ;; Check the Newsgroups & Followup-To headers. 2093 ;; Check the Newsgroups & Followup-To headers.
1957 (message-check 'existing-newsgroups 2094 (message-check 'existing-newsgroups
1958 (let* ((case-fold-search t) 2095 (let* ((case-fold-search t)
1959 (newsgroups (message-fetch-field "newsgroups")) 2096 (newsgroups (message-fetch-field "newsgroups"))
1989 (headers '("Newsgroups" "Followup-To")) 2126 (headers '("Newsgroups" "Followup-To"))
1990 header error) 2127 header error)
1991 (while (and headers (not error)) 2128 (while (and headers (not error))
1992 (when (setq header (mail-fetch-field (car headers))) 2129 (when (setq header (mail-fetch-field (car headers)))
1993 (if (or 2130 (if (or
1994 (not 2131 (not
1995 (string-match 2132 (string-match
1996 "\\`\\([-+_&.a-zA-Z0-9]+\\)?\\(,[-+_&.a-zA-Z0-9]+\\)*\\'" 2133 "\\`\\([-+_&.a-zA-Z0-9]+\\)?\\(,[-+_&.a-zA-Z0-9]+\\)*\\'"
1997 header)) 2134 header))
1998 (memq 2135 (memq
1999 nil (mapcar 2136 nil (mapcar
2000 (lambda (g) 2137 (lambda (g)
2001 (not (string-match "\\.\\'\\|\\.\\." g))) 2138 (not (string-match "\\.\\'\\|\\.\\." g)))
2002 (message-tokenize-header header ",")))) 2139 (message-tokenize-header header ","))))
2003 (setq error t))) 2140 (setq error t)))
2004 (unless error 2141 (unless error
2057 (or (re-search-backward "[^ \n\t]" b t) 2194 (or (re-search-backward "[^ \n\t]" b t)
2058 (y-or-n-p "Empty article. Really post? ")))) 2195 (y-or-n-p "Empty article. Really post? "))))
2059 ;; Check for control characters. 2196 ;; Check for control characters.
2060 (message-check 'control-chars 2197 (message-check 'control-chars
2061 (if (re-search-forward "[\000-\007\013\015-\037\200-\237]" nil t) 2198 (if (re-search-forward "[\000-\007\013\015-\037\200-\237]" nil t)
2062 (y-or-n-p 2199 (y-or-n-p
2063 "The article contains control characters. Really post? ") 2200 "The article contains control characters. Really post? ")
2064 t)) 2201 t))
2065 ;; Check excessive size. 2202 ;; Check excessive size.
2066 (message-check 'size 2203 (message-check 'size
2067 (if (> (buffer-size) 60000) 2204 (if (> (buffer-size) 60000)
2138 (funcall message-fcc-handler-function file) 2275 (funcall message-fcc-handler-function file)
2139 (if (and (file-readable-p file) (mail-file-babyl-p file)) 2276 (if (and (file-readable-p file) (mail-file-babyl-p file))
2140 (rmail-output file 1 nil t) 2277 (rmail-output file 1 nil t)
2141 (let ((mail-use-rfc822 t)) 2278 (let ((mail-use-rfc822 t))
2142 (rmail-output file 1 t t)))))) 2279 (rmail-output file 1 t t))))))
2143 2280
2144 (kill-buffer (current-buffer))))) 2281 (kill-buffer (current-buffer)))))
2145 2282
2146 (defun message-output (filename) 2283 (defun message-output (filename)
2147 "Append this article to Unix/babyl mail file.." 2284 "Append this article to Unix/babyl mail file.."
2148 (if (and (file-readable-p filename) 2285 (if (and (file-readable-p filename)
2182 (replace-match "" t t))))) 2319 (replace-match "" t t)))))
2183 2320
2184 (defun message-make-date () 2321 (defun message-make-date ()
2185 "Make a valid data header." 2322 "Make a valid data header."
2186 (let ((now (current-time))) 2323 (let ((now (current-time)))
2187 (timezone-make-date-arpa-standard 2324 (timezone-make-date-arpa-standard
2188 (current-time-string now) (current-time-zone now)))) 2325 (current-time-string now) (current-time-zone now))))
2189 2326
2190 (defun message-make-message-id () 2327 (defun message-make-message-id ()
2191 "Make a unique Message-ID." 2328 "Make a unique Message-ID."
2192 (concat "<" (message-unique-id) 2329 (concat "<" (message-unique-id)
2193 (let ((psubject (save-excursion (message-fetch-field "subject")))) 2330 (let ((psubject (save-excursion (message-fetch-field "subject"))))
2194 (if (and message-reply-headers 2331 (if (and message-reply-headers
2195 (mail-header-references message-reply-headers) 2332 (mail-header-references message-reply-headers)
2196 (mail-header-subject message-reply-headers) 2333 (mail-header-subject message-reply-headers)
2197 psubject 2334 psubject
2198 (mail-header-subject message-reply-headers) 2335 (mail-header-subject message-reply-headers)
2199 (not (string= 2336 (not (string=
2200 (message-strip-subject-re 2337 (message-strip-subject-re
2201 (mail-header-subject message-reply-headers)) 2338 (mail-header-subject message-reply-headers))
2202 (message-strip-subject-re psubject)))) 2339 (message-strip-subject-re psubject))))
2203 "_-_" "")) 2340 "_-_" ""))
2204 "@" (message-make-fqdn) ">")) 2341 "@" (message-make-fqdn) ">"))
2223 (let ((user (downcase (user-login-name)))) 2360 (let ((user (downcase (user-login-name))))
2224 (while (string-match "[^a-z0-9_]" user) 2361 (while (string-match "[^a-z0-9_]" user)
2225 (aset user (match-beginning 0) ?_)) 2362 (aset user (match-beginning 0) ?_))
2226 user) 2363 user)
2227 (message-number-base36 (user-uid) -1)) 2364 (message-number-base36 (user-uid) -1))
2228 (message-number-base36 (+ (car tm) 2365 (message-number-base36 (+ (car tm)
2229 (lsh (% message-unique-id-char 25) 16)) 4) 2366 (lsh (% message-unique-id-char 25) 16)) 4)
2230 (message-number-base36 (+ (nth 1 tm) 2367 (message-number-base36 (+ (nth 1 tm)
2231 (lsh (/ message-unique-id-char 25) 16)) 4) 2368 (lsh (/ message-unique-id-char 25) 16)) 4)
2232 ;; Append the newsreader name, because while the generated 2369 ;; Append the newsreader name, because while the generated
2233 ;; ID is unique to this newsreader, other newsreaders might 2370 ;; ID is unique to this newsreader, other newsreaders might
2243 (char-to-string (aref "zyxwvutsrqponmlkjihgfedcba9876543210" 2380 (char-to-string (aref "zyxwvutsrqponmlkjihgfedcba9876543210"
2244 (% num 36)))))) 2381 (% num 36))))))
2245 2382
2246 (defun message-make-organization () 2383 (defun message-make-organization ()
2247 "Make an Organization header." 2384 "Make an Organization header."
2248 (let* ((organization 2385 (let* ((organization
2249 (or (getenv "ORGANIZATION") 2386 (or (getenv "ORGANIZATION")
2250 (when message-user-organization 2387 (when message-user-organization
2251 (if (message-functionp message-user-organization) 2388 (if (message-functionp message-user-organization)
2252 (funcall message-user-organization) 2389 (funcall message-user-organization)
2253 message-user-organization))))) 2390 message-user-organization)))))
2269 "Count the number of lines and return numeric string." 2406 "Count the number of lines and return numeric string."
2270 (save-excursion 2407 (save-excursion
2271 (save-restriction 2408 (save-restriction
2272 (widen) 2409 (widen)
2273 (goto-char (point-min)) 2410 (goto-char (point-min))
2274 (re-search-forward 2411 (re-search-forward
2275 (concat "^" (regexp-quote mail-header-separator) "$")) 2412 (concat "^" (regexp-quote mail-header-separator) "$"))
2276 (forward-line 1) 2413 (forward-line 1)
2277 (int-to-string (count-lines (point) (point-max)))))) 2414 (int-to-string (count-lines (point) (point-max))))))
2278 2415
2279 (defun message-make-in-reply-to () 2416 (defun message-make-in-reply-to ()
2280 "Return the In-Reply-To header for this message." 2417 "Return the In-Reply-To header for this message."
2281 (when message-reply-headers 2418 (when message-reply-headers
2282 (let ((from (mail-header-from message-reply-headers)) 2419 (let ((from (mail-header-from message-reply-headers))
2283 (date (mail-header-date message-reply-headers))) 2420 (date (mail-header-date message-reply-headers)))
2284 (when from 2421 (when from
2285 (let ((stop-pos 2422 (let ((stop-pos
2286 (string-match " *at \\| *@ \\| *(\\| *<" from))) 2423 (string-match " *at \\| *@ \\| *(\\| *<" from)))
2287 (concat (if stop-pos (substring from 0 stop-pos) from) 2424 (concat (if stop-pos (substring from 0 stop-pos) from)
2288 "'s message of " 2425 "'s message of "
2289 (if (or (not date) (string= date "")) 2426 (if (or (not date) (string= date ""))
2290 "(unknown date)" date))))))) 2427 "(unknown date)" date)))))))
2291 2428
2292 (defun message-make-distribution () 2429 (defun message-make-distribution ()
2293 "Make a Distribution header." 2430 "Make a Distribution header."
2302 (future (* 1.0 message-expires 60 60 24))) 2439 (future (* 1.0 message-expires 60 60 24)))
2303 ;; Add the future to current. 2440 ;; Add the future to current.
2304 (setcar current (+ (car current) (round (/ future (expt 2 16))))) 2441 (setcar current (+ (car current) (round (/ future (expt 2 16)))))
2305 (setcar (cdr current) (+ (nth 1 current) (% (round future) (expt 2 16)))) 2442 (setcar (cdr current) (+ (nth 1 current) (% (round future) (expt 2 16))))
2306 ;; Return the date in the future in UT. 2443 ;; Return the date in the future in UT.
2307 (timezone-make-date-arpa-standard 2444 (timezone-make-date-arpa-standard
2308 (current-time-string current) (current-time-zone current) '(0 "UT")))) 2445 (current-time-string current) (current-time-zone current) '(0 "UT"))))
2309 2446
2310 (defun message-make-path () 2447 (defun message-make-path ()
2311 "Return uucp path." 2448 "Return uucp path."
2312 (let ((login-name (user-login-name))) 2449 (let ((login-name (user-login-name)))
2318 (t login-name)))) 2455 (t login-name))))
2319 2456
2320 (defun message-make-from () 2457 (defun message-make-from ()
2321 "Make a From header." 2458 "Make a From header."
2322 (let* ((login (message-make-address)) 2459 (let* ((login (message-make-address))
2323 (fullname 2460 (fullname
2324 (or (and (boundp 'user-full-name) 2461 (or (and (boundp 'user-full-name)
2325 user-full-name) 2462 user-full-name)
2326 (user-full-name)))) 2463 (user-full-name))))
2327 (when (string= fullname "&") 2464 (when (string= fullname "&")
2328 (setq fullname (user-login-name))) 2465 (setq fullname (user-login-name)))
2329 (save-excursion 2466 (save-excursion
2330 (message-set-work-buffer) 2467 (message-set-work-buffer)
2331 (cond 2468 (cond
2332 ((or (null message-from-style) 2469 ((or (null message-from-style)
2333 (equal fullname "")) 2470 (equal fullname ""))
2334 (insert login)) 2471 (insert login))
2335 ((or (eq message-from-style 'angles) 2472 ((or (eq message-from-style 'angles)
2336 (and (not (eq message-from-style 'parens)) 2473 (and (not (eq message-from-style 'parens))
2365 (while (re-search-forward "[()\\]" nil 1) 2502 (while (re-search-forward "[()\\]" nil 1)
2366 (replace-match "\\\\\\&" t)) 2503 (replace-match "\\\\\\&" t))
2367 ;; ... then undo escaping of matching parentheses, 2504 ;; ... then undo escaping of matching parentheses,
2368 ;; including matching nested parentheses. 2505 ;; including matching nested parentheses.
2369 (goto-char fullname-start) 2506 (goto-char fullname-start)
2370 (while (re-search-forward 2507 (while (re-search-forward
2371 "\\(\\=\\|[^\\]\\(\\\\\\\\\\)*\\)\\\\(\\(\\([^\\]\\|\\\\\\\\\\)*\\)\\\\)" 2508 "\\(\\=\\|[^\\]\\(\\\\\\\\\\)*\\)\\\\(\\(\\([^\\]\\|\\\\\\\\\\)*\\)\\\\)"
2372 nil 1) 2509 nil 1)
2373 (replace-match "\\1(\\3)" t) 2510 (replace-match "\\1(\\3)" t)
2374 (goto-char fullname-start))) 2511 (goto-char fullname-start)))
2375 (insert ")"))) 2512 (insert ")")))
2376 (buffer-string)))) 2513 (buffer-string))))
2377 2514
2378 (defun message-make-sender () 2515 (defun message-make-sender ()
2379 "Return the \"real\" user address. 2516 "Return the \"real\" user address.
2380 This function tries to ignore all user modifications, and 2517 This function tries to ignore all user modifications, and
2381 give as trustworthy answer as possible." 2518 give as trustworthy answer as possible."
2382 (concat (user-login-name) "@" (system-name))) 2519 (concat (user-login-name) "@" (system-name)))
2383 2520
2384 (defun message-make-address () 2521 (defun message-make-address ()
2385 "Make the address of the user." 2522 "Make the address of the user."
2395 2532
2396 (defun message-make-fqdn () 2533 (defun message-make-fqdn ()
2397 "Return user's fully qualified domain name." 2534 "Return user's fully qualified domain name."
2398 (let ((system-name (system-name)) 2535 (let ((system-name (system-name))
2399 (user-mail (message-user-mail-address))) 2536 (user-mail (message-user-mail-address)))
2400 (cond 2537 (cond
2401 ((string-match "[^.]\\.[^.]" system-name) 2538 ((string-match "[^.]\\.[^.]" system-name)
2402 ;; `system-name' returned the right result. 2539 ;; `system-name' returned the right result.
2403 system-name) 2540 system-name)
2404 ;; Try `mail-host-address'. 2541 ;; Try `mail-host-address'.
2405 ((and (boundp 'mail-host-address) 2542 ((and (boundp 'mail-host-address)
2449 header value elem) 2586 header value elem)
2450 ;; First we remove any old generated headers. 2587 ;; First we remove any old generated headers.
2451 (let ((headers message-deletable-headers)) 2588 (let ((headers message-deletable-headers))
2452 (while headers 2589 (while headers
2453 (goto-char (point-min)) 2590 (goto-char (point-min))
2454 (and (re-search-forward 2591 (and (re-search-forward
2455 (concat "^" (symbol-name (car headers)) ": *") nil t) 2592 (concat "^" (symbol-name (car headers)) ": *") nil t)
2456 (get-text-property (1+ (match-beginning 0)) 'message-deletable) 2593 (get-text-property (1+ (match-beginning 0)) 'message-deletable)
2457 (message-delete-line)) 2594 (message-delete-line))
2458 (pop headers))) 2595 (pop headers)))
2459 ;; Go through all the required headers and see if they are in the 2596 ;; Go through all the required headers and see if they are in the
2460 ;; articles already. If they are not, or are empty, they are 2597 ;; articles already. If they are not, or are empty, they are
2461 ;; inserted automatically - except for Subject, Newsgroups and 2598 ;; inserted automatically - except for Subject, Newsgroups and
2462 ;; Distribution. 2599 ;; Distribution.
2463 (while headers 2600 (while headers
2464 (goto-char (point-min)) 2601 (goto-char (point-min))
2465 (setq elem (pop headers)) 2602 (setq elem (pop headers))
2466 (if (consp elem) 2603 (if (consp elem)
2467 (if (eq (car elem) 'optional) 2604 (if (eq (car elem) 'optional)
2468 (setq header (cdr elem)) 2605 (setq header (cdr elem))
2469 (setq header (car elem))) 2606 (setq header (car elem)))
2470 (setq header elem)) 2607 (setq header elem))
2471 (when (or (not (re-search-forward 2608 (when (or (not (re-search-forward
2472 (concat "^" (downcase (symbol-name header)) ":") 2609 (concat "^" (downcase (symbol-name header)) ":")
2473 nil t)) 2610 nil t))
2474 (progn 2611 (progn
2475 ;; The header was found. We insert a space after the 2612 ;; The header was found. We insert a space after the
2476 ;; colon, if there is none. 2613 ;; colon, if there is none.
2477 (if (/= (following-char) ? ) (insert " ") (forward-char 1)) 2614 (if (/= (following-char) ? ) (insert " ") (forward-char 1))
2478 ;; Find out whether the header is empty... 2615 ;; Find out whether the header is empty...
2479 (looking-at "[ \t]*$"))) 2616 (looking-at "[ \t]*$")))
2480 ;; So we find out what value we should insert. 2617 ;; So we find out what value we should insert.
2481 (setq value 2618 (setq value
2482 (cond 2619 (cond
2483 ((and (consp elem) (eq (car elem) 'optional)) 2620 ((and (consp elem) (eq (car elem) 'optional))
2484 ;; This is an optional header. If the cdr of this 2621 ;; This is an optional header. If the cdr of this
2485 ;; is something that is nil, then we do not insert 2622 ;; is something that is nil, then we do not insert
2486 ;; this header. 2623 ;; this header.
2487 (setq header (cdr elem)) 2624 (setq header (cdr elem))
2502 ;; We couldn't generate a value for this header, 2639 ;; We couldn't generate a value for this header,
2503 ;; so we just ask the user. 2640 ;; so we just ask the user.
2504 (read-from-minibuffer 2641 (read-from-minibuffer
2505 (format "Empty header for %s; enter value: " header))))) 2642 (format "Empty header for %s; enter value: " header)))))
2506 ;; Finally insert the header. 2643 ;; Finally insert the header.
2507 (when (and value 2644 (when (and value
2508 (not (equal value ""))) 2645 (not (equal value "")))
2509 (save-excursion 2646 (save-excursion
2510 (if (bolp) 2647 (if (bolp)
2511 (progn 2648 (progn
2512 ;; This header didn't exist, so we insert it. 2649 ;; This header didn't exist, so we insert it.
2518 (delete-region (point) (gnus-point-at-eol)) 2655 (delete-region (point) (gnus-point-at-eol))
2519 (insert value)) 2656 (insert value))
2520 ;; Add the deletable property to the headers that require it. 2657 ;; Add the deletable property to the headers that require it.
2521 (and (memq header message-deletable-headers) 2658 (and (memq header message-deletable-headers)
2522 (progn (beginning-of-line) (looking-at "[^:]+: ")) 2659 (progn (beginning-of-line) (looking-at "[^:]+: "))
2523 (add-text-properties 2660 (add-text-properties
2524 (point) (match-end 0) 2661 (point) (match-end 0)
2525 '(message-deletable t face italic) (current-buffer))))))) 2662 '(message-deletable t face italic) (current-buffer)))))))
2526 ;; Insert new Sender if the From is strange. 2663 ;; Insert new Sender if the From is strange.
2527 (let ((from (message-fetch-field "from")) 2664 (let ((from (message-fetch-field "from"))
2528 (sender (message-fetch-field "sender")) 2665 (sender (message-fetch-field "sender"))
2529 (secure-sender (message-make-sender))) 2666 (secure-sender (message-make-sender)))
2530 (when (and from 2667 (when (and from
2531 (not (message-check-element 'sender)) 2668 (not (message-check-element 'sender))
2532 (not (string= 2669 (not (string=
2533 (downcase 2670 (downcase
2534 (cadr (mail-extract-address-components from))) 2671 (cadr (mail-extract-address-components from)))
2535 (downcase secure-sender))) 2672 (downcase secure-sender)))
2536 (or (null sender) 2673 (or (null sender)
2537 (not 2674 (not
2538 (string= 2675 (string=
2539 (downcase 2676 (downcase
2540 (cadr (mail-extract-address-components sender))) 2677 (cadr (mail-extract-address-components sender)))
2541 (downcase secure-sender))))) 2678 (downcase secure-sender)))))
2542 (goto-char (point-min)) 2679 (goto-char (point-min))
2543 ;; Rename any old Sender headers to Original-Sender. 2680 ;; Rename any old Sender headers to Original-Sender.
2544 (when (re-search-forward "^\\(Original-\\)*Sender:" nil t) 2681 (when (re-search-forward "^\\(Original-\\)*Sender:" nil t)
2545 (beginning-of-line) 2682 (beginning-of-line)
2546 (insert "Original-") 2683 (insert "Original-")
2547 (beginning-of-line)) 2684 (beginning-of-line))
2561 (cond 2698 (cond
2562 ((string-match "%s" message-courtesy-message) 2699 ((string-match "%s" message-courtesy-message)
2563 (insert (format message-courtesy-message newsgroups))) 2700 (insert (format message-courtesy-message newsgroups)))
2564 (t 2701 (t
2565 (insert message-courtesy-message))))))) 2702 (insert message-courtesy-message)))))))
2566 2703
2567 ;;; 2704 ;;;
2568 ;;; Setting up a message buffer 2705 ;;; Setting up a message buffer
2569 ;;; 2706 ;;;
2570 2707
2571 (defun message-fill-address (header value) 2708 (defun message-fill-address (header value)
2620 (goto-char (point-max))))) 2757 (goto-char (point-max)))))
2621 2758
2622 (defun message-position-point () 2759 (defun message-position-point ()
2623 "Move point to where the user probably wants to find it." 2760 "Move point to where the user probably wants to find it."
2624 (message-narrow-to-headers) 2761 (message-narrow-to-headers)
2625 (cond 2762 (cond
2626 ((re-search-forward "^[^:]+:[ \t]*$" nil t) 2763 ((re-search-forward "^[^:]+:[ \t]*$" nil t)
2627 (search-backward ":" ) 2764 (search-backward ":" )
2628 (widen) 2765 (widen)
2629 (forward-char 1) 2766 (forward-char 1)
2630 (if (= (following-char) ? ) 2767 (if (= (following-char) ? )
2639 (sit-for 0))) 2776 (sit-for 0)))
2640 2777
2641 (defun message-buffer-name (type &optional to group) 2778 (defun message-buffer-name (type &optional to group)
2642 "Return a new (unique) buffer name based on TYPE and TO." 2779 "Return a new (unique) buffer name based on TYPE and TO."
2643 (cond 2780 (cond
2644 ;; Check whether `message-generate-new-buffers' is a function, 2781 ;; Check whether `message-generate-new-buffers' is a function,
2645 ;; and if so, call it. 2782 ;; and if so, call it.
2646 ((message-functionp message-generate-new-buffers) 2783 ((message-functionp message-generate-new-buffers)
2647 (funcall message-generate-new-buffers type to group)) 2784 (funcall message-generate-new-buffers type to group))
2648 ;; Generate a new buffer name The Message Way. 2785 ;; Generate a new buffer name The Message Way.
2649 (message-generate-new-buffers 2786 (message-generate-new-buffers
2690 (kill-buffer buffer)))) 2827 (kill-buffer buffer))))
2691 ;; Rename the buffer. 2828 ;; Rename the buffer.
2692 (if message-send-rename-function 2829 (if message-send-rename-function
2693 (funcall message-send-rename-function) 2830 (funcall message-send-rename-function)
2694 (when (string-match "\\`\\*" (buffer-name)) 2831 (when (string-match "\\`\\*" (buffer-name))
2695 (rename-buffer 2832 (rename-buffer
2696 (concat "*sent " (substring (buffer-name) (match-end 0))) t))) 2833 (concat "*sent " (substring (buffer-name) (match-end 0))) t)))
2697 ;; Push the current buffer onto the list. 2834 ;; Push the current buffer onto the list.
2698 (when message-max-buffers 2835 (when message-max-buffers
2699 (setq message-buffer-list 2836 (setq message-buffer-list
2700 (nconc message-buffer-list (list (current-buffer)))))) 2837 (nconc message-buffer-list (list (current-buffer))))))
2701 2838
2702 (defvar mc-modes-alist) 2839 (defvar mc-modes-alist)
2703 (defun message-setup (headers &optional replybuffer actions) 2840 (defun message-setup (headers &optional replybuffer actions)
2704 (when (and (boundp 'mc-modes-alist) 2841 (when (and (boundp 'mc-modes-alist)
2709 (when actions 2846 (when actions
2710 (setq message-send-actions actions)) 2847 (setq message-send-actions actions))
2711 (setq message-reply-buffer replybuffer) 2848 (setq message-reply-buffer replybuffer)
2712 (goto-char (point-min)) 2849 (goto-char (point-min))
2713 ;; Insert all the headers. 2850 ;; Insert all the headers.
2714 (mail-header-format 2851 (mail-header-format
2715 (let ((h headers) 2852 (let ((h headers)
2716 (alist message-header-format-alist)) 2853 (alist message-header-format-alist))
2717 (while h 2854 (while h
2718 (unless (assq (caar h) message-header-format-alist) 2855 (unless (assq (caar h) message-header-format-alist)
2719 (push (list (caar h)) alist)) 2856 (push (list (caar h)) alist))
2787 yank-action send-actions) 2924 yank-action send-actions)
2788 "Start editing a mail message to be sent." 2925 "Start editing a mail message to be sent."
2789 (interactive) 2926 (interactive)
2790 (let ((message-this-is-mail t)) 2927 (let ((message-this-is-mail t))
2791 (message-pop-to-buffer (message-buffer-name "mail" to)) 2928 (message-pop-to-buffer (message-buffer-name "mail" to))
2792 (message-setup 2929 (message-setup
2793 (nconc 2930 (nconc
2794 `((To . ,(or to "")) (Subject . ,(or subject ""))) 2931 `((To . ,(or to "")) (Subject . ,(or subject "")))
2795 (when other-headers other-headers))))) 2932 (when other-headers other-headers)))))
2796 2933
2797 ;;;###autoload 2934 ;;;###autoload
2798 (defun message-news (&optional newsgroups subject) 2935 (defun message-news (&optional newsgroups subject)
2799 "Start editing a news article to be sent." 2936 "Start editing a news article to be sent."
2800 (interactive) 2937 (interactive)
2801 (let ((message-this-is-news t)) 2938 (let ((message-this-is-news t))
2802 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups)) 2939 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups))
2803 (message-setup `((Newsgroups . ,(or newsgroups "")) 2940 (message-setup `((Newsgroups . ,(or newsgroups ""))
2804 (Subject . ,(or subject "")))))) 2941 (Subject . ,(or subject ""))))))
2805 2942
2806 ;;;###autoload 2943 ;;;###autoload
2807 (defun message-reply (&optional to-address wide ignore-reply-to) 2944 (defun message-reply (&optional to-address wide ignore-reply-to)
2808 "Start editing a reply to the article in the current buffer." 2945 "Start editing a reply to the article in the current buffer."
2809 (interactive) 2946 (interactive)
2810 (let ((cur (current-buffer)) 2947 (let ((cur (current-buffer))
2811 from subject date reply-to to cc 2948 from subject date reply-to to cc
2812 references message-id follow-to 2949 references message-id follow-to
2813 (inhibit-point-motion-hooks t) 2950 (inhibit-point-motion-hooks t)
2814 mct never-mct gnus-warning) 2951 mct never-mct gnus-warning)
2815 (save-restriction 2952 (save-restriction
2816 (message-narrow-to-head) 2953 (message-narrow-to-head)
2817 ;; Allow customizations to have their say. 2954 ;; Allow customizations to have their say.
2824 (save-excursion 2961 (save-excursion
2825 (setq follow-to 2962 (setq follow-to
2826 (funcall message-wide-reply-to-function))))) 2963 (funcall message-wide-reply-to-function)))))
2827 ;; Find all relevant headers we need. 2964 ;; Find all relevant headers we need.
2828 (setq from (message-fetch-field "from") 2965 (setq from (message-fetch-field "from")
2829 date (message-fetch-field "date") 2966 date (message-fetch-field "date")
2830 subject (or (message-fetch-field "subject") "none") 2967 subject (or (message-fetch-field "subject") "none")
2831 to (message-fetch-field "to") 2968 to (message-fetch-field "to")
2832 cc (message-fetch-field "cc") 2969 cc (message-fetch-field "cc")
2833 mct (message-fetch-field "mail-copies-to") 2970 mct (message-fetch-field "mail-copies-to")
2834 reply-to (unless ignore-reply-to (message-fetch-field "reply-to")) 2971 reply-to (unless ignore-reply-to (message-fetch-field "reply-to"))
2841 (setq subject (concat "Re: " subject)) 2978 (setq subject (concat "Re: " subject))
2842 2979
2843 (when (and (setq gnus-warning (message-fetch-field "gnus-warning")) 2980 (when (and (setq gnus-warning (message-fetch-field "gnus-warning"))
2844 (string-match "<[^>]+>" gnus-warning)) 2981 (string-match "<[^>]+>" gnus-warning))
2845 (setq message-id (match-string 0 gnus-warning))) 2982 (setq message-id (match-string 0 gnus-warning)))
2846 2983
2847 ;; Handle special values of Mail-Copies-To. 2984 ;; Handle special values of Mail-Copies-To.
2848 (when mct 2985 (when mct
2849 (cond ((equal (downcase mct) "never") 2986 (cond ((equal (downcase mct) "never")
2850 (setq never-mct t) 2987 (setq never-mct t)
2851 (setq mct nil)) 2988 (setq mct nil))
2862 (unless never-mct 2999 (unless never-mct
2863 (insert (or reply-to from ""))) 3000 (insert (or reply-to from "")))
2864 (insert (if (bolp) "" ", ") (or to "")) 3001 (insert (if (bolp) "" ", ") (or to ""))
2865 (insert (if mct (concat (if (bolp) "" ", ") mct) "")) 3002 (insert (if mct (concat (if (bolp) "" ", ") mct) ""))
2866 (insert (if cc (concat (if (bolp) "" ", ") cc) "")) 3003 (insert (if cc (concat (if (bolp) "" ", ") cc) ""))
2867 ;; Remove addresses that match `rmail-dont-reply-to-names'. 3004 ;; Remove addresses that match `rmail-dont-reply-to-names'.
2868 (insert (prog1 (rmail-dont-reply-to (buffer-string)) 3005 (insert (prog1 (rmail-dont-reply-to (buffer-string))
2869 (erase-buffer))) 3006 (erase-buffer)))
2870 (goto-char (point-min)) 3007 (goto-char (point-min))
2871 ;; Perhaps Mail-Copies-To: never removed the only address? 3008 ;; Perhaps Mail-Copies-To: never removed the only address?
2872 (when (eobp) 3009 (when (eobp)
2879 (let ((s ccalist)) 3016 (let ((s ccalist))
2880 (while s 3017 (while s
2881 (setq ccalist (delq (assoc (car (pop s)) s) ccalist))))) 3018 (setq ccalist (delq (assoc (car (pop s)) s) ccalist)))))
2882 (setq follow-to (list (cons 'To (cdr (pop ccalist))))) 3019 (setq follow-to (list (cons 'To (cdr (pop ccalist)))))
2883 (when ccalist 3020 (when ccalist
2884 (let ((ccs (cons 'Cc (mapconcat 3021 (let ((ccs (cons 'Cc (mapconcat
2885 (lambda (addr) (cdr addr)) ccalist ", ")))) 3022 (lambda (addr) (cdr addr)) ccalist ", "))))
2886 (when (string-match "^ +" (cdr ccs)) 3023 (when (string-match "^ +" (cdr ccs))
2887 (setcdr ccs (substring (cdr ccs) (match-end 0)))) 3024 (setcdr ccs (substring (cdr ccs) (match-end 0))))
2888 (push ccs follow-to)))))) 3025 (push ccs follow-to))))))
2889 (widen)) 3026 (widen))
2895 (setq message-reply-headers 3032 (setq message-reply-headers
2896 (vector 0 subject from date message-id references 0 0 "")) 3033 (vector 0 subject from date message-id references 0 0 ""))
2897 3034
2898 (message-setup 3035 (message-setup
2899 `((Subject . ,subject) 3036 `((Subject . ,subject)
2900 ,@follow-to 3037 ,@follow-to
2901 ,@(if (or references message-id) 3038 ,@(if (or references message-id)
2902 `((References . ,(concat (or references "") (and references " ") 3039 `((References . ,(concat (or references "") (and references " ")
2903 (or message-id "")))) 3040 (or message-id ""))))
2904 nil)) 3041 nil))
2905 cur))) 3042 cur)))
2915 "Follow up to the message in the current buffer. 3052 "Follow up to the message in the current buffer.
2916 If TO-NEWSGROUPS, use that as the new Newsgroups line." 3053 If TO-NEWSGROUPS, use that as the new Newsgroups line."
2917 (interactive) 3054 (interactive)
2918 (let ((cur (current-buffer)) 3055 (let ((cur (current-buffer))
2919 from subject date reply-to mct 3056 from subject date reply-to mct
2920 references message-id follow-to 3057 references message-id follow-to
2921 (inhibit-point-motion-hooks t) 3058 (inhibit-point-motion-hooks t)
2922 (message-this-is-news t) 3059 (message-this-is-news t)
2923 followup-to distribution newsgroups gnus-warning posted-to) 3060 followup-to distribution newsgroups gnus-warning posted-to)
2924 (save-restriction 3061 (save-restriction
2925 (narrow-to-region 3062 (narrow-to-region
2929 (point-max))) 3066 (point-max)))
2930 (when (message-functionp message-followup-to-function) 3067 (when (message-functionp message-followup-to-function)
2931 (setq follow-to 3068 (setq follow-to
2932 (funcall message-followup-to-function))) 3069 (funcall message-followup-to-function)))
2933 (setq from (message-fetch-field "from") 3070 (setq from (message-fetch-field "from")
2934 date (message-fetch-field "date") 3071 date (message-fetch-field "date")
2935 subject (or (message-fetch-field "subject") "none") 3072 subject (or (message-fetch-field "subject") "none")
2936 references (message-fetch-field "references") 3073 references (message-fetch-field "references")
2937 message-id (message-fetch-field "message-id" t) 3074 message-id (message-fetch-field "message-id" t)
2938 followup-to (message-fetch-field "followup-to") 3075 followup-to (message-fetch-field "followup-to")
2939 newsgroups (message-fetch-field "newsgroups") 3076 newsgroups (message-fetch-field "newsgroups")
2958 3095
2959 (message-pop-to-buffer (message-buffer-name "followup" from newsgroups)) 3096 (message-pop-to-buffer (message-buffer-name "followup" from newsgroups))
2960 3097
2961 (message-setup 3098 (message-setup
2962 `((Subject . ,subject) 3099 `((Subject . ,subject)
2963 ,@(cond 3100 ,@(cond
2964 (to-newsgroups 3101 (to-newsgroups
2965 (list (cons 'Newsgroups to-newsgroups))) 3102 (list (cons 'Newsgroups to-newsgroups)))
2966 (follow-to follow-to) 3103 (follow-to follow-to)
2967 ((and followup-to message-use-followup-to) 3104 ((and followup-to message-use-followup-to)
2968 (list 3105 (list
2969 (cond 3106 (cond
2970 ((equal (downcase followup-to) "poster") 3107 ((equal (downcase followup-to) "poster")
2971 (if (or (eq message-use-followup-to 'use) 3108 (if (or (eq message-use-followup-to 'use)
2972 (message-y-or-n-p "Obey Followup-To: poster? " t "\ 3109 (message-y-or-n-p "Obey Followup-To: poster? " t "\
2973 You should normally obey the Followup-To: header. 3110 You should normally obey the Followup-To: header.
2974 3111
3066 "Start composing a message to supersede the current message. 3203 "Start composing a message to supersede the current message.
3067 This is done simply by taking the old article and adding a Supersedes 3204 This is done simply by taking the old article and adding a Supersedes
3068 header line with the old Message-ID." 3205 header line with the old Message-ID."
3069 (interactive) 3206 (interactive)
3070 (let ((cur (current-buffer))) 3207 (let ((cur (current-buffer)))
3071 ;; Check whether the user owns the article that is to be superseded. 3208 ;; Check whether the user owns the article that is to be superseded.
3072 (unless (string-equal 3209 (unless (string-equal
3073 (downcase (cadr (mail-extract-address-components 3210 (downcase (cadr (mail-extract-address-components
3074 (message-fetch-field "from")))) 3211 (message-fetch-field "from"))))
3075 (downcase (message-make-address))) 3212 (downcase (message-make-address)))
3076 (error "This article is not yours")) 3213 (error "This article is not yours"))
3114 "Return a Subject header suitable for the message in the current buffer." 3251 "Return a Subject header suitable for the message in the current buffer."
3115 (save-excursion 3252 (save-excursion
3116 (save-restriction 3253 (save-restriction
3117 (current-buffer) 3254 (current-buffer)
3118 (message-narrow-to-head) 3255 (message-narrow-to-head)
3119 (concat "[" (or (message-fetch-field 3256 (concat "[" (or (message-fetch-field
3120 (if (message-news-p) "newsgroups" "from")) 3257 (if (message-news-p) "newsgroups" "from"))
3121 "(nowhere)") 3258 "(nowhere)")
3122 "] " (or (message-fetch-field "Subject") ""))))) 3259 "] " (or (message-fetch-field "Subject") "")))))
3123 3260
3124 ;;;###autoload 3261 ;;;###autoload
3125 (defun message-forward (&optional news) 3262 (defun message-forward (&optional news)
3126 "Forward the current message via mail. 3263 "Forward the current message via mail.
3127 Optional NEWS will use news to forward instead of mail." 3264 Optional NEWS will use news to forward instead of mail."
3128 (interactive "P") 3265 (interactive "P")
3129 (let ((cur (current-buffer)) 3266 (let ((cur (current-buffer))
3130 (subject (message-make-forward-subject)) 3267 (subject (message-make-forward-subject))
3131 art-beg) 3268 art-beg)
3132 (if news (message-news nil subject) (message-mail nil subject)) 3269 (if news (message-news nil subject) (message-mail nil subject))
3133 ;; Put point where we want it before inserting the forwarded 3270 ;; Put point where we want it before inserting the forwarded
3134 ;; message. 3271 ;; message.
3135 (if message-signature-before-forwarded-message 3272 (if message-signature-before-forwarded-message
3136 (goto-char (point-max)) 3273 (goto-char (point-max))
3137 (message-goto-body)) 3274 (message-goto-body))
3138 ;; Make sure we're at the start of the line. 3275 ;; Make sure we're at the start of the line.
3139 (unless (eolp) 3276 (unless (eolp)
3232 (and (re-search-forward message-unsent-separator nil t) 3369 (and (re-search-forward message-unsent-separator nil t)
3233 (forward-line 1)) 3370 (forward-line 1))
3234 (and (search-forward "\n\n" nil t) 3371 (and (search-forward "\n\n" nil t)
3235 (re-search-forward "^Return-Path:.*\n" nil t))) 3372 (re-search-forward "^Return-Path:.*\n" nil t)))
3236 ;; We remove everything before the bounced mail. 3373 ;; We remove everything before the bounced mail.
3237 (delete-region 3374 (delete-region
3238 (point-min) 3375 (point-min)
3239 (if (re-search-forward "^[^ \n\t]+:" nil t) 3376 (if (re-search-forward "^[^ \n\t]+:" nil t)
3240 (match-beginning 0) 3377 (match-beginning 0)
3241 (point))) 3378 (point)))
3242 (save-restriction 3379 (save-restriction
3282 (special-display-buffer-names nil) 3419 (special-display-buffer-names nil)
3283 (special-display-regexps nil) 3420 (special-display-regexps nil)
3284 (same-window-buffer-names nil) 3421 (same-window-buffer-names nil)
3285 (same-window-regexps nil)) 3422 (same-window-regexps nil))
3286 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups))) 3423 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups)))
3287 (message-setup `((Newsgroups . ,(or newsgroups "")) 3424 (message-setup `((Newsgroups . ,(or newsgroups ""))
3288 (Subject . ,(or subject ""))))) 3425 (Subject . ,(or subject "")))))
3289 3426
3290 ;;;###autoload 3427 ;;;###autoload
3291 (defun message-news-other-frame (&optional newsgroups subject) 3428 (defun message-news-other-frame (&optional newsgroups subject)
3292 "Start editing a news article to be sent." 3429 "Start editing a news article to be sent."
3295 (special-display-buffer-names nil) 3432 (special-display-buffer-names nil)
3296 (special-display-regexps nil) 3433 (special-display-regexps nil)
3297 (same-window-buffer-names nil) 3434 (same-window-buffer-names nil)
3298 (same-window-regexps nil)) 3435 (same-window-regexps nil))
3299 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups))) 3436 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups)))
3300 (message-setup `((Newsgroups . ,(or newsgroups "")) 3437 (message-setup `((Newsgroups . ,(or newsgroups ""))
3301 (Subject . ,(or subject ""))))) 3438 (Subject . ,(or subject "")))))
3302 3439
3303 ;;; underline.el 3440 ;;; underline.el
3304 3441
3305 ;; This code should be moved to underline.el (from which it is stolen). 3442 ;; This code should be moved to underline.el (from which it is stolen).
3306 3443
3307 ;;;###autoload 3444 ;;;###autoload
3308 (defun bold-region (start end) 3445 (defun bold-region (start end)
3309 "Bold all nonblank characters in the region. 3446 "Bold all nonblank characters in the region.
3310 Works by overstriking characters. 3447 Works by overstriking characters.
3327 which specify the range to operate on." 3464 which specify the range to operate on."
3328 (interactive "r") 3465 (interactive "r")
3329 (save-excursion 3466 (save-excursion
3330 (let ((end1 (make-marker))) 3467 (let ((end1 (make-marker)))
3331 (move-marker end1 (max start end)) 3468 (move-marker end1 (max start end))
3332 (goto-char (min start end)) 3469 (goto-char (min start end))
3333 (while (re-search-forward "\b" end1 t) 3470 (while (re-search-forward "\b" end1 t)
3334 (if (eq (following-char) (char-after (- (point) 2))) 3471 (if (eq (following-char) (char-after (- (point) 2)))
3335 (delete-char -2)))))) 3472 (delete-char -2))))))
3336 3473
3337 (defalias 'message-exchange-point-and-mark 'exchange-point-and-mark) 3474 (defalias 'message-exchange-point-and-mark 'exchange-point-and-mark)
3341 (require 'messagexmas)) 3478 (require 'messagexmas))
3342 3479
3343 ;;; Group name completion. 3480 ;;; Group name completion.
3344 3481
3345 (defvar message-newgroups-header-regexp 3482 (defvar message-newgroups-header-regexp
3346 "^\\(Newsgroups\\|Followup-To\\|Posted-To\\):" 3483 "^\\(Newsgroups\\|Followup-To\\|Posted-To\\|Gcc\\):"
3347 "Regexp that match headers that lists groups.") 3484 "Regexp that match headers that lists groups.")
3348 3485
3349 (defun message-tab () 3486 (defun message-tab ()
3350 "Expand group names in Newsgroups and Followup-To headers. 3487 "Expand group names in Newsgroups and Followup-To headers.
3351 Do a `tab-to-tab-stop' if not in those headers." 3488 Do a `tab-to-tab-stop' if not in those headers."
3355 (message-expand-group) 3492 (message-expand-group)
3356 (tab-to-tab-stop))) 3493 (tab-to-tab-stop)))
3357 3494
3358 (defvar gnus-active-hashtb) 3495 (defvar gnus-active-hashtb)
3359 (defun message-expand-group () 3496 (defun message-expand-group ()
3360 (let* ((b (save-excursion 3497 (let* ((b (save-excursion
3361 (save-restriction 3498 (save-restriction
3362 (narrow-to-region 3499 (narrow-to-region
3363 (save-excursion 3500 (save-excursion
3364 (beginning-of-line) 3501 (beginning-of-line)
3365 (skip-chars-forward "^:") 3502 (skip-chars-forward "^:")
3366 (1+ (point))) 3503 (1+ (point)))
3367 (point)) 3504 (point))
3371 (hashtb (and (boundp 'gnus-active-hashtb) gnus-active-hashtb)) 3508 (hashtb (and (boundp 'gnus-active-hashtb) gnus-active-hashtb))
3372 (completions (all-completions string hashtb)) 3509 (completions (all-completions string hashtb))
3373 (cur (current-buffer)) 3510 (cur (current-buffer))
3374 comp) 3511 comp)
3375 (delete-region b (point)) 3512 (delete-region b (point))
3376 (cond 3513 (cond
3377 ((= (length completions) 1) 3514 ((= (length completions) 1)
3378 (if (string= (car completions) string) 3515 (if (string= (car completions) string)
3379 (progn 3516 (progn
3380 (insert string) 3517 (insert string)
3381 (message "Only matching group")) 3518 (message "Only matching group"))
3397 (pop-to-buffer cur))))))) 3534 (pop-to-buffer cur)))))))
3398 3535
3399 ;;; Help stuff. 3536 ;;; Help stuff.
3400 3537
3401 (defun message-talkative-question (ask question show &rest text) 3538 (defun message-talkative-question (ask question show &rest text)
3402 "Call FUNCTION with argument QUESTION, displaying the rest of the arguments in a temporary buffer if SHOW. 3539 "Call FUNCTION with argument QUESTION, displaying the rest of the arguments in a temporary buffer if SHOW.
3403 The following arguments may contain lists of values." 3540 The following arguments may contain lists of values."
3404 (if (and show 3541 (if (and show
3405 (setq text (message-flatten-list text))) 3542 (setq text (message-flatten-list text)))
3406 (save-window-excursion 3543 (save-window-excursion
3407 (save-excursion 3544 (save-excursion
3415 (defun message-flatten-list (list) 3552 (defun message-flatten-list (list)
3416 "Return a new, flat list that contains all elements of LIST. 3553 "Return a new, flat list that contains all elements of LIST.
3417 3554
3418 \(message-flatten-list '(1 (2 3 (4 5 (6))) 7)) 3555 \(message-flatten-list '(1 (2 3 (4 5 (6))) 7))
3419 => (1 2 3 4 5 6 7)" 3556 => (1 2 3 4 5 6 7)"
3420 (cond ((consp list) 3557 (cond ((consp list)
3421 (apply 'append (mapcar 'message-flatten-list list))) 3558 (apply 'append (mapcar 'message-flatten-list list)))
3422 (list 3559 (list
3423 (list list)))) 3560 (list list))))
3424 3561
3425 (defun message-generate-new-buffer-clone-locals (name &optional varstr) 3562 (defun message-generate-new-buffer-clone-locals (name &optional varstr)