*** empty log message ***
[gnus] / lisp / message.el
index 2c39d48..a60aa16 100644 (file)
@@ -458,7 +458,13 @@ variable isn't used."
   :type 'sexp)
 
 (defcustom message-generate-headers-first nil
-  "*If non-nil, generate all required headers before composing."
+  "*If non-nil, generate all required headers before composing.
+The variables `message-required-news-headers' and
+`message-required-mail-headers' specify which headers to generate.
+
+Note that the variable `message-deletable-headers' specifies headers which
+are to be deleted and then re-generated before sending, so this variable
+will not have a visible effect for those headers."
   :group 'message-headers
   :type 'boolean)
 
@@ -554,8 +560,10 @@ If a form, the result from the form will be used instead."
 
 ;;;###autoload
 (defcustom message-signature-file "~/.signature"
-  "*File containing the text inserted at end of message buffer."
-  :type 'file
+  "*Name of file containing the text inserted at end of message buffer.
+Ignored if the named file doesn't exist.
+If nil, don't insert a signature."
+  :type '(choice file (const :tags "None" nil))
   :group 'message-insertion)
 
 (defcustom message-distribution-function nil
@@ -1085,8 +1093,9 @@ Except if it is nil, use Gnus native MUA; if it is t, use
   (autoload 'gnus-open-server "gnus-int")
   (autoload 'gnus-request-post "gnus-int")
   (autoload 'gnus-alive-p "gnus-util")
+  (autoload 'gnus-server-string "gnus")
   (autoload 'gnus-group-name-charset "gnus-group")
-  (autoload 'rmail-output "rmail"))
+  (autoload 'rmail-output "rmailout"))
 
 \f
 
@@ -1444,7 +1453,7 @@ Point is left at the beginning of the narrowed-to 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 "\M-q" 'message-fill-paragraph)
+  ;;(define-key message-mode-map "\M-q" 'message-fill-paragraph)
 
   (define-key message-mode-map "\C-c\C-a" 'mml-attach-file)
 
@@ -1592,6 +1601,8 @@ M-RET    `message-newline-and-reformat' (break the line and reformat)."
 
 (defun message-setup-fill-variables ()
   "Setup message fill variables."
+  (set (make-local-variable 'fill-paragraph-function) 
+       'message-fill-paragraph)
   (make-local-variable 'paragraph-separate)
   (make-local-variable 'paragraph-start)
   (make-local-variable 'adaptive-fill-regexp)
@@ -1791,9 +1802,10 @@ With the prefix argument FORCE, insert the header anyway."
     (unless (bolp)
       (insert "\n"))))
 
-(defun message-newline-and-reformat (&optional not-break)
-  "Insert four newlines, and then reformat if inside quoted text."
-  (interactive)
+(defun message-newline-and-reformat (&optional arg not-break)
+  "Insert four newlines, and then reformat if inside quoted text.
+Prefix arg means justify as well."
+  (interactive (list (if current-prefix-arg 'full)))
   (let (quoted point beg end leading-space bolp)
     (setq point (point))
     (beginning-of-line)
@@ -1869,14 +1881,15 @@ With the prefix argument FORCE, insert the header anyway."
                 (regexp-quote (concat quoted leading-space)))
                 (adaptive-fill-first-line-regexp
                  adaptive-fill-regexp ))
-           (fill-paragraph nil))
-       (fill-paragraph nil))
+           (fill-paragraph arg))
+       (fill-paragraph arg))
       (if point (goto-char point)))))
 
-(defun message-fill-paragraph ()
+(defun message-fill-paragraph (&optional arg)
   "Like `fill-paragraph'."
-  (interactive)
-  (message-newline-and-reformat t))
+  (interactive (list (if current-prefix-arg 'full)))
+  (message-newline-and-reformat arg t)
+  t)
 
 (defun message-insert-signature (&optional force)
   "Insert a signature.  See documentation for variable `message-signature'."
@@ -2367,7 +2380,7 @@ It should typically alter the sending method in some way or other."
     (pop actions)))
 
 (defun message-send-mail-partially ()
-  "Sendmail as message/partial."
+  "Send mail as message/partial."
   ;; replace the header delimiter with a blank line
   (goto-char (point-min))
   (re-search-forward
@@ -2495,8 +2508,9 @@ It should typically alter the sending method in some way or other."
            (message-insert-courtesy-copy))
          (if (or (not message-send-mail-partially-limit)
                  (< (point-max) message-send-mail-partially-limit)
-                 (not (y-or-n-p "The message size is too large, should it be sent partially? ")))
+                 (not (y-or-n-p "Message exceeds message-send-mail-partially-limit, send in parts? ")))
              (mm-with-unibyte-current-buffer
+               (message "Sending via mail...")
                (funcall message-send-mail-function))
            (message-send-mail-partially)))
       (kill-buffer tembuf))
@@ -2660,8 +2674,8 @@ to find out how to use this."
        (message-generate-headers message-required-news-headers)
        ;; Let the user do all of the above.
        (run-hooks 'message-header-hook))
-      (if group-name-charset
-         (setq message-syntax-checks
+      (when group-name-charset
+       (setq message-syntax-checks
              (cons '(valid-newsgroups . disabled)
                    message-syntax-checks)))
       (message-cleanup-headers)
@@ -2700,6 +2714,7 @@ to find out how to use this."
                (backward-char 1))
              (run-hooks 'message-send-news-hook)
              (gnus-open-server method)
+             (message "Sending news with %s..." (gnus-server-string method))
              (setq result (let ((mail-header-separator ""))
                             (gnus-request-post method))))
          (kill-buffer tembuf))
@@ -2843,87 +2858,100 @@ to find out how to use this."
            (hashtb (and (boundp 'gnus-active-hashtb)
                         gnus-active-hashtb))
            errors)
-       (if (or (not hashtb)
-              (not (boundp 'gnus-read-active-file))
-              (not gnus-read-active-file)
-              (eq gnus-read-active-file 'some))
-          t
-        (while groups
-          (when (and (not (boundp (intern (car groups) hashtb)))
-                     (not (equal (car groups) "poster")))
-            (push (car groups) errors))
-          (pop groups))
-        (if (not errors)
-            t
-          (y-or-n-p
-           (format
-            "Really post to %s unknown group%s: %s? "
-            (if (= (length errors) 1) "this" "these")
-            (if (= (length errors) 1) "" "s")
-            (mapconcat 'identity errors ", ")))))))
-   ;; Check the Newsgroups & Followup-To headers for syntax errors.
-   (message-check 'valid-newsgroups
-     (let ((case-fold-search t)
-          (headers '("Newsgroups" "Followup-To"))
-          header error)
-       (while (and headers (not error))
-        (when (setq header (mail-fetch-field (car headers)))
-          (if (or
-               (not
-                (string-match
-                 "\\`\\([-+_&.a-zA-Z0-9]+\\)?\\(,[-+_&.a-zA-Z0-9]+\\)*\\'"
-                 header))
-               (memq
-                nil (mapcar
-                     (lambda (g)
-                       (not (string-match "\\.\\'\\|\\.\\." g)))
-                     (message-tokenize-header header ","))))
-              (setq error t)))
-        (unless error
-          (pop headers)))
-       (if (not error)
-          t
+       (while groups
+        (when (and (not (boundp (intern (car groups) hashtb)))
+                   (not (equal (car groups) "poster")))
+          (push (car groups) errors))
+        (pop groups))
+       (cond
+       ;; Gnus is not running.
+       ((or (not hashtb)
+            (not (boundp 'gnus-read-active-file)))
+        t)
+       ;; We don't have all the group names.
+       ((and (or (not gnus-read-active-file)
+                 (eq gnus-read-active-file 'some))
+             errors)
         (y-or-n-p
-         (format "The %s header looks odd: \"%s\".  Really post? "
-                 (car headers) header)))))
-   (message-check 'repeated-newsgroups
-     (let ((case-fold-search t)
-          (headers '("Newsgroups" "Followup-To"))
-          header error groups group)
-       (while (and headers
-                  (not error))
-        (when (setq header (mail-fetch-field (pop headers)))
-          (setq groups (message-tokenize-header header ","))
-          (while (setq group (pop groups))
-            (when (member group groups)
-              (setq error group
-                    groups nil)))))
-       (if (not error)
-          t
+         (format
+          "Really post to %s possibly unknown group%s: %s? "
+          (if (= (length errors) 1) "this" "these")
+          (if (= (length errors) 1) "" "s")
+          (mapconcat 'identity errors ", "))))
+       ;; There were no errors.
+       ((not errors)
+        t)
+       ;; There are unknown groups.
+       (t
         (y-or-n-p
-         (format "Group %s is repeated in headers.  Really post? " error)))))
-   ;; Check the From header.
-   (message-check 'from
-     (let* ((case-fold-search t)
-           (from (message-fetch-field "from"))
-           ad)
-       (cond
-       ((not from)
-        (message "There is no From line.  Posting is denied.")
-        nil)
-       ((or (not (string-match
-                  "@[^\\.]*\\."
-                  (setq ad (nth 1 (mail-extract-address-components
-                                   from))))) ;larsi@ifi
-            (string-match "\\.\\." ad) ;larsi@ifi..uio
-            (string-match "@\\." ad)   ;larsi@.ifi.uio
-            (string-match "\\.$" ad)   ;larsi@ifi.uio.
-            (not (string-match "^[^@]+@[^@]+$" ad)) ;larsi.ifi.uio
-            (string-match "(.*).*(.*)" from)) ;(lars) (lars)
-        (message
-         "Denied posting -- the From looks strange: \"%s\"." from)
-        nil)
-       (t t))))))
+         (format
+          "Really post to %s unknown group%s: %s? "
+          (if (= (length errors) 1) "this" "these")
+          (if (= (length errors) 1) "" "s")
+          (mapconcat 'identity errors ", ")))))))
+     ;; Check the Newsgroups & Followup-To headers for syntax errors.
+     (message-check 'valid-newsgroups
+       (let ((case-fold-search t)
+            (headers '("Newsgroups" "Followup-To"))
+            header error)
+        (while (and headers (not error))
+          (when (setq header (mail-fetch-field (car headers)))
+            (if (or
+                 (not
+                  (string-match
+                   "\\`\\([-+_&.a-zA-Z0-9]+\\)?\\(,[-+_&.a-zA-Z0-9]+\\)*\\'"
+                   header))
+                 (memq
+                  nil (mapcar
+                       (lambda (g)
+                         (not (string-match "\\.\\'\\|\\.\\." g)))
+                       (message-tokenize-header header ","))))
+                (setq error t)))
+          (unless error
+            (pop headers)))
+        (if (not error)
+            t
+          (y-or-n-p
+           (format "The %s header looks odd: \"%s\".  Really post? "
+                   (car headers) header)))))
+     (message-check 'repeated-newsgroups
+       (let ((case-fold-search t)
+            (headers '("Newsgroups" "Followup-To"))
+            header error groups group)
+        (while (and headers
+                    (not error))
+          (when (setq header (mail-fetch-field (pop headers)))
+            (setq groups (message-tokenize-header header ","))
+            (while (setq group (pop groups))
+              (when (member group groups)
+                (setq error group
+                      groups nil)))))
+        (if (not error)
+            t
+          (y-or-n-p
+           (format "Group %s is repeated in headers.  Really post? " error)))))
+     ;; Check the From header.
+     (message-check 'from
+       (let* ((case-fold-search t)
+             (from (message-fetch-field "from"))
+             ad)
+        (cond
+         ((not from)
+          (message "There is no From line.  Posting is denied.")
+          nil)
+         ((or (not (string-match
+                    "@[^\\.]*\\."
+                    (setq ad (nth 1 (mail-extract-address-components
+                                     from))))) ;larsi@ifi
+              (string-match "\\.\\." ad) ;larsi@ifi..uio
+              (string-match "@\\." ad) ;larsi@.ifi.uio
+              (string-match "\\.$" ad) ;larsi@ifi.uio.
+              (not (string-match "^[^@]+@[^@]+$" ad)) ;larsi.ifi.uio
+              (string-match "(.*).*(.*)" from)) ;(lars) (lars)
+          (message
+           "Denied posting -- the From looks strange: \"%s\"." from)
+          nil)
+         (t t))))))
 
 (defun message-check-news-body-syntax ()
   (and
@@ -2932,10 +2960,13 @@ to find out how to use this."
      (goto-char (point-min))
      (re-search-forward
       (concat "^" (regexp-quote mail-header-separator) "$"))
+     (forward-line 1)
      (while (and
-            (progn
-              (end-of-line)
-              (< (current-column) 80))
+            (or (looking-at 
+                 "<#\\(/\\)?\\(multipart\\|part\\|external\\|mml\\)")
+                (let ((p (point)))
+                  (end-of-line)
+                  (< (- (point) p) 80)))
             (zerop (forward-line 1))))
      (or (bolp)
         (eobp)
@@ -3713,9 +3744,25 @@ than 988 characters long, and if they are not, trim them until they are."
   ;; Rename the buffer.
   (if message-send-rename-function
       (funcall message-send-rename-function)
-    (when (string-match "\\`\\*\\(unsent \\)?" (buffer-name))
-      (rename-buffer
-       (concat "*sent " (substring (buffer-name) (match-end 0))) t)))
+    (when (string-match "\\`\\*\\(sent \\|unsent \\)?\\(.+\\)\\*[^\\*]*" 
+                       (buffer-name))
+      (let ((name (match-string 2 (buffer-name)))
+           to group)
+       (if (not (or (string-equal name "mail")
+                    (string-equal name "news")))
+           (setq name (concat "*sent " name "*"))
+         (setq to (message-fetch-field "to"))
+         (setq group (message-fetch-field "newsgroups"))
+         (setq name
+               (cond 
+                (to (concat "*sent mail to "
+                            (or (car (mail-extract-address-components to))
+                                to) "*"))
+                ((and group (not (string= group "")))
+                 (concat "*sent news on " group "*"))
+                (t "*sent mail*"))))
+       (unless (string-equal name (buffer-name))
+         (rename-buffer name t)))))
   ;; Push the current buffer onto the list.
   (when message-max-buffers
     (setq message-buffer-list
@@ -3827,8 +3874,11 @@ than 988 characters long, and if they are not, trim them until they are."
     (if (gnus-alive-p)
        (setq message-draft-article
              (nndraft-request-associate-buffer "drafts"))
-      (setq buffer-file-name (expand-file-name "*message*"
-                                              message-auto-save-directory))
+      (setq buffer-file-name (expand-file-name
+                             (if (eq system-type 'windows-nt)
+                                 "message"
+                               "*message*")
+                             message-auto-save-directory))
       (setq buffer-auto-save-file-name (make-auto-save-file-name)))
     (clear-visited-file-modtime)
     (setq buffer-file-coding-system message-draft-coding-system)))
@@ -3902,7 +3952,8 @@ OTHER-HEADERS is an alist of header/value pairs."
          mct (message-fetch-field "mail-copies-to")
          reply-to (message-fetch-field "reply-to")
          mrt (message-fetch-field "mail-reply-to")
-         mft (message-fetch-field "mail-followup-to"))
+         mft (and message-use-followup-to
+                   (message-fetch-field "mail-followup-to")))
 
     ;; Handle special values of Mail-Copies-To.
     (when mct
@@ -3914,13 +3965,14 @@ OTHER-HEADERS is an alist of header/value pairs."
                 (equal (downcase mct) "poster"))
             (setq mct (or mrt reply-to from)))))
 
-    (if (or (not wide)
-           to-address)
+    (if (and (not mft)
+             (or (not wide)
+                 to-address))
        (progn
          (setq follow-to (list (cons 'To (or to-address mrt reply-to from))))
-         (when (and (and wide (or mft mct))
-                    (not (member (cons 'To (or mft mct)) follow-to)))
-           (push (cons 'Cc (or mft mct)) follow-to)))
+         (when (and (and wide mct)
+                    (not (member (cons 'To mct) follow-to)))
+           (push (cons 'Cc mct) follow-to)))
       (let (ccalist)
        (save-excursion
          (message-set-work-buffer)
@@ -4164,28 +4216,28 @@ If ARG, allow editing of the cancellation message."
   (interactive "P")
   (unless (message-news-p)
     (error "This is not a news article; canceling is impossible"))
-  (when (yes-or-no-p "Do you really want to cancel this article? ")
-    (let (from newsgroups message-id distribution buf sender)
-      (save-excursion
-       ;; Get header info from original article.
-       (save-restriction
-         (message-narrow-to-head-1)
-         (setq from (message-fetch-field "from")
-               sender (message-fetch-field "sender")
-               newsgroups (message-fetch-field "newsgroups")
-               message-id (message-fetch-field "message-id" t)
-               distribution (message-fetch-field "distribution")))
-       ;; Make sure that this article was written by the user.
-       (unless (or (message-gnksa-enable-p 'cancel-messages)
-                   (and sender
-                        (string-equal
-                         (downcase sender)
-                         (downcase (message-make-sender))))
-                   (string-equal
-                    (downcase (cadr (mail-extract-address-components from)))
-                    (downcase (cadr (mail-extract-address-components
-                                     (message-make-from))))))
-         (error "This article is not yours"))
+  (let (from newsgroups message-id distribution buf sender)
+    (save-excursion
+      ;; Get header info from original article.
+      (save-restriction
+       (message-narrow-to-head-1)
+       (setq from (message-fetch-field "from")
+             sender (message-fetch-field "sender")
+             newsgroups (message-fetch-field "newsgroups")
+             message-id (message-fetch-field "message-id" t)
+             distribution (message-fetch-field "distribution")))
+      ;; Make sure that this article was written by the user.
+      (unless (or (message-gnksa-enable-p 'cancel-messages)
+                 (and sender
+                      (string-equal
+                       (downcase sender)
+                       (downcase (message-make-sender))))
+                 (string-equal
+                  (downcase (cadr (mail-extract-address-components from)))
+                  (downcase (cadr (mail-extract-address-components
+                                   (message-make-from))))))
+       (error "This article is not yours"))
+      (when (yes-or-no-p "Do you really want to cancel this article? ")
        ;; Make control message.
        (if arg
            (message-news)
@@ -4301,15 +4353,22 @@ Previous forwarders, replyers, etc. may add it."
 
 ;;; Forwarding messages.
 
+(defvar message-forward-decoded-p nil
+  "Non-nil means the original message is decoded.")
+
 (defun message-forward-subject-author-subject (subject)
   "Generate a SUBJECT for a forwarded message.
 The form is: [Source] Subject, where if the original message was mail,
 Source is the sender, and if the original message was news, Source is
 the list of newsgroups is was posted to."
   (concat "["
-         (or (message-fetch-field
-              (if (message-news-p) "newsgroups" "from"))
-             "(nowhere)")
+          (let ((prefix 
+                 (or (message-fetch-field
+                      (if (message-news-p) "newsgroups" "from"))
+                     "(nowhere)")))
+            (if message-forward-decoded-p
+                prefix
+              (mail-decode-encoded-word-string prefix)))
          "] " subject))
 
 (defun message-forward-subject-fwd (subject)
@@ -4318,7 +4377,7 @@ The form is: Fwd: Subject, where Subject is the original subject of
 the message."
   (concat "Fwd: " subject))
 
-(defun message-make-forward-subject (&optional decoded)
+(defun message-make-forward-subject ()
   "Return a Subject header suitable for the message in the current buffer."
   (save-excursion
     (save-restriction
@@ -4327,7 +4386,7 @@ the message."
            (subject (message-fetch-field "Subject")))
        (setq subject
              (if subject
-                 (if decoded 
+                 (if message-forward-decoded-p
                      subject
                    (mail-decode-encoded-word-string subject))
                ""))
@@ -4345,15 +4404,22 @@ the message."
          (setq funcs (cdr funcs)))
        subject))))
 
+(eval-when-compile
+  (defvar gnus-article-decoded-p))
+
 ;;;###autoload
 (defun message-forward (&optional news digest)
   "Forward the current message via mail.
 Optional NEWS will use news to forward instead of mail.
 Optional DIGEST will use digest to forward."
   (interactive "P")
-  (let ((cur (current-buffer))
-       (subject (message-make-forward-subject digest))
-       art-beg)
+  (let* ((cur (current-buffer))
+        (message-forward-decoded-p 
+         (if (local-variable-p 'gnus-article-decoded-p (current-buffer))
+             gnus-article-decoded-p  ;; In an article buffer.
+           message-forward-decoded-p))
+        (subject (message-make-forward-subject))
+        art-beg)
     (if news
        (message-news nil subject)
       (message-mail nil subject))
@@ -4374,7 +4440,8 @@ Optional DIGEST will use digest to forward."
          (if message-forward-as-mime
              (insert-buffer-substring cur)
            (mml-insert-buffer cur))
-       (if message-forward-show-mml
+       (if (and message-forward-show-mml
+                (not message-forward-decoded-p))
            (insert
             (with-temp-buffer
               (mm-disable-multibyte-mule4) ;; Must copy buffer in unibyte mode
@@ -4852,8 +4919,11 @@ regexp varstr."
                         (mail-strip-quoted-names
                          (message-fetch-field "from")))
     (message-options-set 'message-recipients
-                         (mail-strip-quoted-names
-                          (message-fetch-field "to")))))
+                        (mail-strip-quoted-names
+                         (concat
+                          (or (message-fetch-field "to") "") ", "
+                          (or (message-fetch-field "cc") "") ", "
+                          (or (message-fetch-field "bcc") ""))))))
 
 (when (featurep 'xemacs)
   (require 'messagexmas)