Quassia Gnus v0.25.
[elisp/gnus.git-] / lisp / message.el
index 55e3d8e..21b9229 100644 (file)
@@ -2,8 +2,7 @@
 ;; Copyright (C) 1996,97 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
-;; Keywords: mail, news, MIME
+;; Keywords: mail, news
 
 ;; This file is part of GNU Emacs.
 
@@ -40,7 +39,6 @@
 (if (string-match "XEmacs\\|Lucid" emacs-version)
     (require 'mail-abbrevs)
   (require 'mailabbrev))
-(require 'mime-edit)
 
 (defgroup message '((user-mail-address custom-variable)
                    (user-full-name custom-variable))
@@ -124,11 +122,6 @@ mailbox format."
                (function :tag "Other"))
   :group 'message-sending)
 
-(defcustom message-encode-function 'message-maybe-encode
-  "*A function called to encode messages."
-  :group 'message-sending
-  :type 'function)
-
 (defcustom message-courtesy-message
   "The following message is a courtesy copy of an article\nthat has been posted to %s as well.\n\n"
   "*This is inserted at the start of a mailed copy of a posted message.
@@ -211,7 +204,7 @@ included.  Organization, Lines and X-Mailer are optional."
   :group 'message-headers
   :type 'regexp)
 
-(defcustom message-ignored-mail-headers "^[GF]cc:\\|^Resent-Fcc:"
+(defcustom message-ignored-mail-headers "^[GF]cc:\\|^Resent-Fcc:\\|^Xref:"
   "*Regexp of headers to be removed unconditionally before mailing."
   :group 'message-mail
   :group 'message-headers
@@ -282,13 +275,13 @@ If nil, Message won't autosave."
   :type 'directory)
 
 (defcustom message-forward-start-separator
-  (concat (mime-make-tag "message" "rfc822") "\n")
+  "------- Start of forwarded message -------\n"
   "*Delimiter inserted before forwarded messages."
   :group 'message-forwarding
   :type 'string)
 
 (defcustom message-forward-end-separator
-  ""
+  "------- End of forwarded message -------\n"
   "*Delimiter inserted after forwarded messages."
   :group 'message-forwarding
   :type 'string)
@@ -327,16 +320,17 @@ The headers should be delimited by a line whose contents match the
 variable `mail-header-separator'.
 
 Legal values include `message-send-mail-with-sendmail' (the default),
-`message-send-mail-with-mh' and `message-send-mail-with-qmail'."
+`message-send-mail-with-mh', `message-send-mail-with-qmail' and
+`smtpmail-send-it'."
   :type '(radio (function-item message-send-mail-with-sendmail)
                (function-item message-send-mail-with-mh)
                (function-item message-send-mail-with-qmail)
+               (function-item smtpmail-send-it)
                (function :tag "Other"))
   :group 'message-sending
   :group 'message-mail)
 
-;; 1997-09-29 by MORIOKA Tomohiko
-(defcustom message-send-news-function 'message-send-news-with-gnus
+(defcustom message-send-news-function 'message-send-news
   "Function to call to send the current buffer as news.
 The headers should be delimited by a line whose contents match the
 variable `mail-header-separator'."
@@ -420,8 +414,7 @@ might set this variable to '(\"-f\" \"you@some.where\")."
   :group 'message-headers
   :type 'boolean)
 
-(defcustom message-setup-hook
-  '(message-maybe-setup-default-charset turn-on-mime-edit)
+(defcustom message-setup-hook nil
   "Normal hook, run each time a new outgoing message is initialized.
 The function `message-setup' runs this hook."
   :group 'message-various
@@ -439,7 +432,7 @@ the signature is inserted."
   :group 'message-various
   :type 'hook)
 
-(defcustom message-header-hook '(eword-encode-header)
+(defcustom message-header-hook nil
   "Hook run in a message mode buffer narrowed to the headers."
   :group 'message-various
   :type 'hook)
@@ -475,8 +468,11 @@ Used by `message-yank-original' via `message-yank-cite'."
           mail-citation-hook)
       mail-citation-hook
     'message-cite-original)
-  "*Function for citing an original message."
+  "*Function for citing an original message.
+Pre-defined functions include `message-cite-original' and
+`message-cite-original-without-signature'."
   :type '(radio (function-item message-cite-original)
+               (function-item message-cite-original-without-signature)
                (function-item sc-cite-original)
                (function :tag "Other"))
   :group 'message-insertion)
@@ -779,10 +775,12 @@ Defaults to `text-mode-abbrev-table'.")
        1 'message-separator-face)
       (,(concat "^[ \t]*"
                "\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
-               "[>|}].*")
+               "[:>|}].*")
        (0 'message-cited-text-face))))
   "Additional expressions to highlight in Message mode.")
 
+;; XEmacs does it like this.  For Emacs, we have to set the
+;; `font-lock-defaults' buffer-local variable.
 (put 'message-mode 'font-lock-defaults '(message-font-lock-keywords t))
 
 (defvar message-face-alist
@@ -905,7 +903,7 @@ The cdr of ech entry is a function for applying the face to a region.")
     (Lines)
     (Expires)
     (Message-ID)
-    (References)
+    (References . message-fill-header)
     (X-Mailer)
     (X-Newsreader))
   "Alist used for formatting headers.")
@@ -1190,6 +1188,7 @@ Return the number of headers removed."
 
   (define-key message-mode-map "\C-c\C-e" 'message-elide-region)
   (define-key message-mode-map "\C-c\C-v" 'message-delete-not-region)
+  (define-key message-mode-map "\C-c\C-z" 'message-kill-to-signature)
   (define-key message-mode-map "\M-\r" 'message-newline-and-reformat)
 
   (define-key message-mode-map "\t" 'message-tab))
@@ -1205,6 +1204,7 @@ Return the number of headers removed."
    ["Caesar (rot13) Region" message-caesar-region (mark t)]
    ["Elide Region" message-elide-region (mark t)]
    ["Delete Outside Region" message-delete-not-region (mark t)]
+   ["Kill To Signature" message-kill-to-signature t]
    ["Newline and Reformat" message-newline-and-reformat t]
    ["Rename buffer" message-rename-buffer t]
    ["Spellcheck" ispell-message t]
@@ -1316,7 +1316,10 @@ C-c C-r  message-caesar-buffer-body (rot13 the message body)."
        (mail-abbrevs-setup)
       (funcall (intern "mail-aliases-setup"))))
   (message-set-auto-save-file-name)
-  (run-hooks 'text-mode-hook 'message-mode-hook))
+  (run-hooks 'text-mode-hook 'message-mode-hook)
+  (unless (string-match "XEmacs" emacs-version)
+    (set (make-local-variable 'font-lock-defaults)
+        '(message-font-lock-keywords t))))
 
 \f
 
@@ -1445,6 +1448,16 @@ With the prefix argument FORCE, insert the header anyway."
   (message-goto-signature)
   (forward-line -2))
 
+(defun message-kill-to-signature ()
+  "Deletes all text up to the signature."
+  (interactive)
+  (let ((point (point)))
+    (message-goto-signature)
+    (forward-line -2)
+    (kill-region point (point))
+    (unless (bolp)
+      (insert "\n"))))
+
 (defun message-newline-and-reformat ()
   "Insert four newlines, and then reformat if inside quoted text."
   (interactive)
@@ -1598,7 +1611,9 @@ name, rather than giving an automatic name."
                       (read-string "New buffer name: " name-default)
                     name-default))
             (default-directory
-              (file-name-as-directory message-autosave-directory)))
+              (if message-autosave-directory
+                  (file-name-as-directory message-autosave-directory)
+                default-directory)))
        (rename-buffer name t)))))
 
 (defun message-fill-yanked-message (&optional justifyp)
@@ -1680,6 +1695,26 @@ prefix, and don't delete any headers."
       (unless modified
        (setq message-checksum (cons (message-checksum) (buffer-size)))))))
 
+(defun message-cite-original-without-signature ()
+  "Cite function in the standard Message manner."
+  (let ((start (point))
+       (end (mark t))
+       (functions
+        (when message-indent-citation-function
+          (if (listp message-indent-citation-function)
+              message-indent-citation-function
+            (list message-indent-citation-function)))))
+    (goto-char end)
+    (when (re-search-backward "^-- $" start t)
+      (delete-region (point) end))
+    (goto-char start)
+    (while functions
+      (funcall (pop functions)))
+    (when message-citation-line-function
+      (unless (bolp)
+       (insert "\n"))
+      (funcall message-citation-line-function))))
+
 (defun message-cite-original ()
   "Cite function in the standard Message manner."
   (let ((start (point))
@@ -1774,6 +1809,7 @@ The text will also be indented the normal way."
 (defun message-dont-send ()
   "Don't send the message you have been editing."
   (interactive)
+  (save-buffer)
   (let ((actions message-postpone-actions))
     (message-bury (current-buffer))
     (message-do-actions actions)))
@@ -1806,15 +1842,9 @@ Otherwise any failure is reported in a message back to
 the user from the mailer."
   (interactive "P")
   ;; Disabled test.
-  (when (if (and buffer-file-name
-                nil)
-           (y-or-n-p (format "Send buffer contents as %s message? "
-                             (if (message-mail-p)
-                                 (if (message-news-p) "mail and news" "mail")
-                               "news")))
-         (or (buffer-modified-p)
-             (message-check-element 'unchanged)
-             (y-or-n-p "No changes in the buffer; really send? ")))
+  (when (or (buffer-modified-p)
+           (message-check-element 'unchanged)
+           (y-or-n-p "No changes in the buffer; really send? "))
     ;; Make it possible to undo the coming changes.
     (undo-boundary)
     (let ((inhibit-read-only t))
@@ -1822,29 +1852,20 @@ the user from the mailer."
     (message-fix-before-sending)
     (run-hooks 'message-send-hook)
     (message "Sending...")
-    (let ((message-encoding-buffer
-          (message-generate-new-buffer-clone-locals " message encoding"))
-         (message-edit-buffer (current-buffer))
-         (message-mime-mode mime-edit-mode-flag)
-         (alist message-send-method-alist)
+    (let ((alist message-send-method-alist)
          (success t)
          elem sent)
-      (save-excursion
-       (set-buffer message-encoding-buffer)
-       (erase-buffer)
-       (insert-buffer message-edit-buffer)
-       (funcall message-encode-function)
-       (while (and success
-                   (setq elem (pop alist)))
-         (when (and (or (not (funcall (cadr elem)))
-                        (and (or (not (memq (car elem)
-                                            message-sent-message-via))
-                                 (y-or-n-p
-                                  (format
-                                   "Already sent message via %s; resend? "
-                                   (car elem))))
-                             (setq success (funcall (caddr elem) arg)))))
-           (setq sent t))))
+      (while (and success
+                 (setq elem (pop alist)))
+       (when (and (or (not (funcall (cadr elem)))
+                      (and (or (not (memq (car elem)
+                                          message-sent-message-via))
+                               (y-or-n-p
+                                (format
+                                 "Already sent message via %s; resend? "
+                                 (car elem))))
+                           (setq success (funcall (caddr elem) arg)))))
+         (setq sent t)))
       (when (and success sent)
        (message-do-fcc)
        ;;(when (fboundp 'mail-hist-put-headers-into-history)
@@ -1867,7 +1888,7 @@ the user from the mailer."
 
 (defun message-send-via-news (arg)
   "Send the current message via news."
-  (message-send-news arg))
+  (funcall message-send-news-function arg))
 
 (defun message-fix-before-sending ()
   "Do various things to make the message nice before sending it."
@@ -1901,7 +1922,8 @@ the user from the mailer."
   (require 'mail-utils)
   (let ((tembuf (message-generate-new-buffer-clone-locals " message temp"))
        (case-fold-search nil)
-       (news (message-news-p)))
+       (news (message-news-p))
+       (mailbuf (current-buffer)))
     (save-restriction
       (message-narrow-to-headers)
       ;; Insert some headers.
@@ -1914,7 +1936,11 @@ the user from the mailer."
        (save-excursion
          (set-buffer tembuf)
          (erase-buffer)
-         (insert-buffer message-encoding-buffer)
+         ;; Avoid copying text props.
+         (insert (format
+                  "%s" (save-excursion
+                         (set-buffer mailbuf)
+                         (buffer-string))))
          ;; Remove some headers.
          (save-restriction
            (message-narrow-to-headers)
@@ -1928,15 +1954,9 @@ the user from the mailer."
                     (or (message-fetch-field "cc")
                         (message-fetch-field "to")))
            (message-insert-courtesy-copy))
-         (mime-edit-maybe-split-and-send
-          (function
-           (lambda ()
-             (interactive)
-             (funcall message-send-mail-function)
-             )))
          (funcall message-send-mail-function))
       (kill-buffer tembuf))
-    (set-buffer message-edit-buffer)
+    (set-buffer mailbuf)
     (push 'mail message-sent-message-via)))
 
 (defun message-send-mail-with-sendmail ()
@@ -1966,7 +1986,8 @@ the user from the mailer."
        (save-excursion
          (set-buffer errbuf)
          (erase-buffer))))
-    (let ((default-directory "/"))
+    (let ((default-directory "/")
+         (coding-system-for-write 'binary))
       (apply 'call-process-region
             (append (list (point-min) (point-max)
                           (if (boundp 'sendmail-program)
@@ -2014,27 +2035,28 @@ to find out how to use this."
   (run-hooks 'message-send-mail-hook)
   ;; send the message
   (case
-      (apply
-       'call-process-region 1 (point-max) message-qmail-inject-program
-       nil nil nil
-       ;; qmail-inject's default behaviour is to look for addresses on the
-       ;; command line; if there're none, it scans the headers.
-       ;; yes, it does The Right Thing w.r.t. Resent-To and it's kin.
-       ;;
-       ;; in general, ALL of qmail-inject's defaults are perfect for simply
-       ;; reading a formatted (i. e., at least a To: or Resent-To header)
-       ;; message from stdin.
-       ;;
-       ;; qmail also has the advantage of not having been raped by
-       ;; various vendors, so we don't have to allow for that, either --
-       ;; compare this with message-send-mail-with-sendmail and weep
-       ;; for sendmail's lost innocence.
-       ;;
-       ;; all this is way cool coz it lets us keep the arguments entirely
-       ;; free for -inject-arguments -- a big win for the user and for us
-       ;; since we don't have to play that double-guessing game and the user
-       ;; gets full control (no gestapo'ish -f's, for instance).  --sj
-       message-qmail-inject-args)
+      (let ((coding-system-for-write 'binary))
+       (apply
+        'call-process-region 1 (point-max) message-qmail-inject-program
+        nil nil nil
+        ;; qmail-inject's default behaviour is to look for addresses on the
+        ;; command line; if there're none, it scans the headers.
+        ;; yes, it does The Right Thing w.r.t. Resent-To and it's kin.
+        ;;
+        ;; in general, ALL of qmail-inject's defaults are perfect for simply
+        ;; reading a formatted (i. e., at least a To: or Resent-To header)
+        ;; message from stdin.
+        ;;
+        ;; qmail also has the advantage of not having been raped by
+        ;; various vendors, so we don't have to allow for that, either --
+        ;; compare this with message-send-mail-with-sendmail and weep
+        ;; for sendmail's lost innocence.
+        ;;
+        ;; all this is way cool coz it lets us keep the arguments entirely
+        ;; free for -inject-arguments -- a big win for the user and for us
+        ;; since we don't have to play that double-guessing game and the user
+        ;; gets full control (no gestapo'ish -f's, for instance).  --sj
+        message-qmail-inject-args))
     ;; qmail-inject doesn't say anything on it's stdout/stderr,
     ;; we have to look at the retval instead
     (0 nil)
@@ -2067,6 +2089,7 @@ to find out how to use this."
        (method (if (message-functionp message-post-method)
                    (funcall message-post-method arg)
                  message-post-method))
+       (messbuf (current-buffer))
        (message-syntax-checks
         (if arg
             (cons '(existing-newsgroups . disabled)
@@ -2089,7 +2112,11 @@ to find out how to use this."
            (set-buffer tembuf)
            (buffer-disable-undo (current-buffer))
            (erase-buffer)
-           (insert-buffer message-encoding-buffer)
+           ;; Avoid copying text props.
+           (insert (format
+                    "%s" (save-excursion
+                           (set-buffer messbuf)
+                           (buffer-string))))
            ;; Remove some headers.
            (save-restriction
              (message-narrow-to-headers)
@@ -2099,48 +2126,30 @@ to find out how to use this."
            ;; require one newline at the end.
            (or (= (preceding-char) ?\n)
                (insert ?\n))
-           (mime-edit-maybe-split-and-send
-            (function
-             (lambda ()
-               (interactive)
-               (save-restriction
-                 (std11-narrow-to-header mail-header-separator)
-                 (goto-char (point-min))
-                 (when (re-search-forward "^Message-Id:" nil t)
-                   (delete-region (match-end 0)(std11-field-end))
-                   (insert (concat " " (message-make-message-id)))
-                   ))
-               (funcall message-send-news-function method)
-               )))
-           (setq result (funcall message-send-news-function method)))
+           (let ((case-fold-search t))
+             ;; Remove the delimiter.
+             (goto-char (point-min))
+             (re-search-forward
+              (concat "^" (regexp-quote mail-header-separator) "\n"))
+             (replace-match "\n")
+             (backward-char 1))
+           (run-hooks 'message-send-news-hook)
+           ;;(require (car method))
+           ;;(funcall (intern (format "%s-open-server" (car method)))
+           ;;(cadr method) (cddr method))
+           ;;(setq result
+           ;;    (funcall (intern (format "%s-request-post" (car method)))
+           ;;             (cadr method)))
+           (gnus-open-server method)
+           (setq result (gnus-request-post method)))
        (kill-buffer tembuf))
-      (set-buffer message-edit-buffer)
+      (set-buffer messbuf)
       (if result
          (push 'news message-sent-message-via)
        (message "Couldn't send message via news: %s"
                 (nnheader-get-report (car method)))
        nil))))
 
-;; 1997-09-29 by MORIOKA Tomohiko
-(defun message-send-news-with-gnus (method)
-  (let ((case-fold-search t))
-    ;; Remove the delimiter.
-    (goto-char (point-min))
-    (re-search-forward
-     (concat "^" (regexp-quote mail-header-separator) "\n"))
-    (replace-match "\n")
-    (backward-char 1)
-    (run-hooks 'message-send-news-hook)
-    ;;(require (car method))
-    ;;(funcall (intern (format "%s-open-server" (car method)))
-    ;;(cadr method) (cddr method))
-    ;;(setq result
-    ;;   (funcall (intern (format "%s-request-post" (car method)))
-    ;;            (cadr method)))
-    (gnus-open-server method)
-    (gnus-request-post method)
-    ))
-
 ;;;
 ;;; Header generation & syntax checking.
 ;;;
@@ -2174,9 +2183,7 @@ to find out how to use this."
           (message-narrow-to-headers)
           (message-check-news-header-syntax)))
        ;; Check the body.
-       (save-excursion
-        (set-buffer message-edit-buffer)
-        (message-check-news-body-syntax))))))
+       (message-check-news-body-syntax)))))
 
 (defun message-check-news-header-syntax ()
   (and
@@ -2433,20 +2440,18 @@ to find out how to use this."
 (defun message-do-fcc ()
   "Process Fcc headers in the current buffer."
   (let ((case-fold-search t)
-       (coding-system-for-write 'raw-text)
+       (buf (current-buffer))
        list file)
     (save-excursion
       (set-buffer (get-buffer-create " *message temp*"))
       (buffer-disable-undo (current-buffer))
       (erase-buffer)
-      (insert-buffer-substring message-encoding-buffer)
+      (insert-buffer-substring buf)
       (save-restriction
        (message-narrow-to-headers)
        (while (setq file (message-fetch-field "fcc"))
          (push file list)
          (message-remove-header "fcc" nil t)))
-      (run-hooks 'message-header-hook)
-      (run-hooks 'message-before-do-fcc-hook)
       (goto-char (point-min))
       (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
       (replace-match "" t t)
@@ -2941,7 +2946,7 @@ Headers already prepared in the buffer are not modified."
 
 (defun message-fill-header (header value)
   (let ((begin (point))
-       (fill-column 78)
+       (fill-column 990)
        (fill-prefix "\t"))
     (insert (capitalize (symbol-name header))
            ": "
@@ -3383,7 +3388,7 @@ responses here are directed to other newsgroups."))
                distribution (message-fetch-field "distribution")))
        ;; Make sure that this article was written by the user.
        (unless (string-equal
-                (downcase (cadr (std11-extract-address-components from)))
+                (downcase (cadr (mail-extract-address-components from)))
                 (downcase (message-make-address)))
          (error "This article is not yours"))
        ;; Make control message.
@@ -3401,10 +3406,8 @@ responses here are directed to other newsgroups."))
                message-cancel-message)
        (message "Canceling your article...")
        (if (let ((message-syntax-checks
-                  'dont-check-for-anything-just-trust-me)
-                 (message-encoding-buffer (current-buffer))
-                 (message-edit-buffer (current-buffer)))
-             (message-send-news))
+                  'dont-check-for-anything-just-trust-me))
+             (funcall message-send-news-function))
            (message "Canceling your article...done"))
        (kill-buffer buf)))))
 
@@ -3703,7 +3706,7 @@ Do a `tab-to-tab-stop' if not in those headers."
 
 (defvar gnus-active-hashtb)
 (defun message-expand-group ()
-  (let* ((b (save-excursion
+  "Expand the group name under point."  (let* ((b (save-excursion
              (save-restriction
                (narrow-to-region
                 (save-excursion
@@ -3797,47 +3800,6 @@ regexp varstr."
                (cdr local)))))
      locals)))
 
-
-;;; @ for MIME Edit mode
-;;;
-
-(defun message-maybe-setup-default-charset ()
-  (let ((charset
-        (and (boundp 'gnus-summary-buffer)
-              (buffer-live-p gnus-summary-buffer)
-             (save-excursion
-               (set-buffer gnus-summary-buffer)
-               default-mime-charset))))
-    (if charset
-       (progn
-         (make-local-variable 'default-mime-charset)
-         (setq default-mime-charset charset)
-         ))))
-
-(defun message-maybe-encode ()
-  (when message-mime-mode
-    (run-hooks 'mime-edit-translate-hook)
-    (if (catch 'mime-edit-error
-         (save-excursion
-           (mime-edit-translate-body)
-           ))
-       (error "Translation error!")
-      )
-    (end-of-invisible)
-    (run-hooks 'mime-edit-exit-hook)
-    ))
-
-(defun message-mime-insert-article (&optional message)
-  (interactive)
-  (let ((message-cite-function 'mime-edit-inserted-message-filter)
-        (message-reply-buffer gnus-original-article-buffer)
-       )
-    (message-yank-original nil)
-    ))
-
-(set-alist 'mime-edit-message-inserter-alist
-          'message-mode (function message-mime-insert-article))
-
 ;;; Miscellaneous functions
 
 ;; stolen (and renamed) from nnheader.el