2000-11-16 Justin Sheehy <justin@iago.org>
[gnus] / lisp / message.el
index 3e5e7ed..f7a32fe 100644 (file)
@@ -33,6 +33,7 @@
 (eval-when-compile
   (require 'cl)
   (defvar gnus-list-identifiers))      ; gnus-sum is required where necessary
+
 (require 'mailheader)
 (require 'nnheader)
 ;; This is apparently necessary even though things are autoloaded:
@@ -330,6 +331,13 @@ The provided functions are:
   :group 'message-insertion
   :type 'regexp)
 
+(defcustom message-cite-prefix-regexp
+  ;; ?-, ?_ or ?. MUST NOT be in syntax entry w.
+  "\\([ \t]*\\(\\w\\|[-_.]\\)+>+\\|[ \t]*[]>»|:}+]\\)+"
+  "*Regexp matching the longest possible citation prefix on a line."
+  :group 'message-insertion
+  :type 'regexp)
+
 (defcustom message-cancel-message "I am canceling my own article.\n"
   "Message to be inserted in the cancel message."
   :group 'message-interface
@@ -819,9 +827,7 @@ Defaults to `text-mode-abbrev-table'.")
   :group 'message-faces)
 
 (defvar message-font-lock-keywords
-  (let* ((cite-prefix "A-Za-z")
-        (cite-suffix (concat cite-prefix "0-9_.@-"))
-        (content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)"))
+  (let ((content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)\n?"))
     `((,(concat "^\\([Tt]o:\\)" content)
        (1 'message-header-name-face)
        (2 'message-header-to-face nil t))
@@ -845,9 +851,7 @@ Defaults to `text-mode-abbrev-table'.")
            `((,(concat "^\\(" (regexp-quote mail-header-separator) "\\)$")
               1 'message-separator-face))
          nil)
-      (,(concat "^[ \t]*"
-               "\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
-               "[:>|}].*")
+      (,(concat "^\\(" message-cite-prefix-regexp "\\).*")
        (0 'message-cited-text-face))
       ("<#/?\\(multipart\\|part\\|external\\|mml\\).*>"
        (0 'message-mml-face))))
@@ -1007,6 +1011,9 @@ The first matched address (not primary one) is used in the From field."
     (User-Agent))
   "Alist used for formatting headers.")
 
+(defvar        message-options nil
+  "Some saved answers when sending message.")
+
 (eval-and-compile
   (autoload 'message-setup-toolbar "messagexmas")
   (autoload 'mh-new-draft-name "mh-comp")
@@ -1515,7 +1522,7 @@ M-RET    message-newline-and-reformat (break the line and reformat)."
          (concat
           "[ \t]*"                      ; possible initial space
           "\\(\\(" (regexp-quote message-yank-prefix) "\\|" ; user's prefix
-          "\\w+>\\|"                    ; supercite-style prefix
+          "\\(\\w\\|[-_.]\\)+>\\|"      ; supercite-style prefix
           "[|:>]"                       ; standard prefix
           "\\)[ \t]*\\)+")))            ; possible space after each prefix
     (setq paragraph-start
@@ -1641,7 +1648,8 @@ With the prefix argument FORCE, insert the header anyway."
             (mail-fetch-field "to")
             (not (string-match "\\` *\\'" (mail-fetch-field "to"))))
     (insert ", "))
-  (insert (or (message-fetch-reply-field "reply-to")
+  (insert (or (message-fetch-reply-field "mail-reply-to")
+             (message-fetch-reply-field "reply-to")
              (message-fetch-reply-field "from") "")))
 
 (defun message-widen-reply ()
@@ -1706,14 +1714,11 @@ With the prefix argument FORCE, insert the header anyway."
 (defun message-newline-and-reformat ()
   "Insert four newlines, and then reformat if inside quoted text."
   (interactive)
-  (let ((prefix "[]>»|:}+ \t]*")
-       (supercite-thing "[-._a-zA-Z0-9]*[>]+[ \t]*")
-       quoted point)
+  (let (quoted point)
     (unless (bolp)
       (save-excursion
        (beginning-of-line)
-       (when (looking-at (concat prefix
-                                 supercite-thing))
+       (when (looking-at message-cite-prefix-regexp)
          (setq quoted (match-string 0))))
       (insert "\n"))
     (setq point (point))
@@ -2123,7 +2128,9 @@ It should typically alter the sending method in some way or other."
   (message message-sending-message)
   (let ((alist message-send-method-alist)
        (success t)
-       elem sent)
+       elem sent
+       (message-options message-options))
+    (message-options-set-recipient)
     (while (and success
                (setq elem (pop alist)))
       (when (funcall (cadr elem))
@@ -3667,13 +3674,15 @@ OTHER-HEADERS is an alist of header/value pairs."
                     (Subject . ,(or subject ""))))))
 
 (defun message-get-reply-headers (wide &optional to-address)
-  (let (follow-to mct never-mct from to cc reply-to ccalist)
+  (let (follow-to mct never-mct from to cc reply-to mrt mft ccalist)
     ;; Find all relevant headers we need.
     (setq from (message-fetch-field "from")
          to (message-fetch-field "to")
          cc (message-fetch-field "cc")
          mct (message-fetch-field "mail-copies-to")
-         reply-to (message-fetch-field "reply-to"))
+         reply-to (message-fetch-field "reply-to")
+         mrt (message-fetch-field "mail-reply-to")
+         mft (message-fetch-field "mail-followup-to"))
 
     ;; Handle special values of Mail-Copies-To.
     (when mct
@@ -3683,22 +3692,44 @@ OTHER-HEADERS is an alist of header/value pairs."
             (setq mct nil))
            ((or (equal (downcase mct) "always")
                 (equal (downcase mct) "poster"))
-            (setq mct (or reply-to from)))))
+            (setq mct (or mrt reply-to from)))))
 
     (if (or (not wide)
            to-address)
        (progn
-         (setq follow-to (list (cons 'To (or to-address reply-to from))))
-         (when (and wide mct)
-           (push (cons 'Cc mct) follow-to)))
+         (setq follow-to (list (cons 'To (or to-address mrt reply-to from))))
+         (when (and wide (or mft mct))
+           (push (cons 'Cc (or mft mct)) follow-to)))
       (let (ccalist)
        (save-excursion
          (message-set-work-buffer)
-         (unless never-mct
-           (insert (or reply-to from "")))
-         (insert (if to (concat (if (bolp) "" ", ") to "") ""))
-         (insert (if mct (concat (if (bolp) "" ", ") mct) ""))
-         (insert (if cc (concat (if (bolp) "" ", ") cc) ""))
+          (if (and mft
+                   message-use-followup-to
+                   (or (not (eq message-use-followup-to 'ask))
+                       (message-y-or-n-p
+                       (concat "Obey Mail-Followup-To? ") t "\
+You should normally obey the Mail-Followup-To: header.  In this
+article, it has the value of
+
+" mft "
+
+which directs your response to " (if (string-match "," mft)
+                              "the specified addresses"
+                            "that address only") ".
+
+If a message is posted to several mailing lists, Mail-Followup-To is
+often used to direct the following discussion to one list only,
+because discussions that are spread over several lists tend to be
+fragmented and very difficult to follow.
+
+Also, some source/announcement lists are not indented for discussion;
+responses here are directed to other addresses.")))
+              (insert mft)
+           (unless never-mct
+             (insert (or mrt reply-to from "")))
+           (insert (if to (concat (if (bolp) "" ", ") to "") ""))
+           (insert (if mct (concat (if (bolp) "" ", ") mct) ""))
+           (insert (if cc (concat (if (bolp) "" ", ") cc) "")))
          (goto-char (point-min))
          (while (re-search-forward "[ \t]+" nil t)
            (replace-match " " t t))
@@ -3709,7 +3740,7 @@ OTHER-HEADERS is an alist of header/value pairs."
          (goto-char (point-min))
          ;; Perhaps "Mail-Copies-To: never" removed the only address?
          (when (eobp)
-           (insert (or reply-to from "")))
+           (insert (or mrt reply-to from "")))
          (setq ccalist
                (mapcar
                 (lambda (addr)
@@ -3727,7 +3758,6 @@ OTHER-HEADERS is an alist of header/value pairs."
            (push ccs follow-to)))))
     follow-to))
 
-
 ;;;###autoload
 (defun message-reply (&optional to-address wide)
   "Start editing a reply to the article in the current buffer."
@@ -3797,7 +3827,7 @@ If TO-NEWSGROUPS, use that as the new Newsgroups line."
   (interactive)
   (require 'gnus-sum)                  ; for gnus-list-identifiers
   (let ((cur (current-buffer))
-       from subject date reply-to mct
+       from subject date reply-to mrt mct
        references message-id follow-to
        (inhibit-point-motion-hooks t)
        (message-this-is-news t)
@@ -3820,6 +3850,7 @@ If TO-NEWSGROUPS, use that as the new Newsgroups line."
            newsgroups (message-fetch-field "newsgroups")
            posted-to (message-fetch-field "posted-to")
            reply-to (message-fetch-field "reply-to")
+           mrt (message-fetch-field "mail-reply-to")
            distribution (message-fetch-field "distribution")
            mct (message-fetch-field "mail-copies-to"))
       (when (and (setq gnus-warning (message-fetch-field "gnus-warning"))
@@ -3857,7 +3888,7 @@ A typical situation where `Followup-To: poster' is used is when the poster
 does not read the newsgroup, so he wouldn't see any replies sent to it."))
                  (progn
                    (setq message-this-is-news nil)
-                   (cons 'To (or reply-to from "")))
+                   (cons 'To (or mrt reply-to from "")))
                (cons 'Newsgroups newsgroups)))
             (t
              (if (or (equal followup-to newsgroups)
@@ -3893,7 +3924,7 @@ responses here are directed to other newsgroups."))
                             (equal (downcase mct) "nobody"))))
           (list (cons 'Cc (if (or (equal (downcase mct) "always")
                                   (equal (downcase mct) "poster"))
-                              (or reply-to from "")
+                              (or mrt reply-to from "")
                             mct)))))
 
      cur)
@@ -4444,21 +4475,8 @@ regexp varstr."
 
 ;;; Miscellaneous functions
 
-;; stolen (and renamed) from nnheader.el
-(if (fboundp 'subst-char-in-string)
-    (defsubst message-replace-chars-in-string (string from to)
-      (subst-char-in-string from to string))
-  (defun message-replace-chars-in-string (string from to)
-    "Replace characters in STRING from FROM to TO."
-    (let ((string (substring string 0))        ;Copy string.
-         (len (length string))
-         (idx 0))
-      ;; Replace all occurrences of FROM with TO.
-      (while (< idx len)
-       (when (= (aref string idx) from)
-         (aset string idx to))
-       (setq idx (1+ idx)))
-      string)))
+(defsubst message-replace-chars-in-string (string from to)
+  (mm-subst-char-in-string from to string))
 
 ;;;
 ;;; MIME functions
@@ -4536,6 +4554,29 @@ regexp varstr."
       (goto-char (point-max))
       (insert "From: " email "\n"))))
 
+(defun message-options-get (symbol)
+  (cdr (assq symbol message-options)))
+
+(defun message-options-set (symbol value)
+  (let ((the-cons (assq symbol message-options)))
+    (if the-cons
+       (if value 
+           (setcdr the-cons value)
+         (setq message-options (delq the-cons message-options)))
+      (and value
+          (push (cons symbol value) message-options))))
+  value)
+
+(defun message-options-set-recipient ()
+  (save-restriction
+    (message-narrow-to-headers-or-head)
+    (message-options-set 'message-sender
+                        (mail-strip-quoted-names 
+                         (message-fetch-field "from")))
+    (message-options-set 'message-recipients
+                         (mail-strip-quoted-names 
+                          (message-fetch-field "to")))))
+
 (provide 'message)
 
 (run-hooks 'message-load-hook)