Sync up with Pterodactyl Gnus v0.91, etc. See ChangeLog for more details.
[elisp/gnus.git-] / lisp / gnus-msg.el
index e8788c8..a124cef 100644 (file)
@@ -6,6 +6,7 @@
 ;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
 ;;     Shuhei KOBAYASHI <shuhei-k@jaist.ac.jp>
 ;;     Katsumi Yamaoka  <yamaoka@jpl.org>
+;;     Kiyokazu SUTO    <suto@merry.xmath.ous.ac.jp>
 ;; Keywords: mail, news, MIME
 
 ;; This file is part of GNU Emacs.
@@ -103,20 +104,11 @@ the second with the current group name.")
 (defvar gnus-posting-styles nil
   "*Alist of styles to use when posting.")
 
-(defvar gnus-posting-style-alist
-  '((organization . message-user-organization)
-    (signature . message-signature)
-    (signature-file . message-signature-file)
-    (address . user-mail-address)
-    (name . user-full-name))
-  "*Mapping from style parameters to variables.")
-
 (defcustom gnus-group-posting-charset-alist
   '(("^no\\." iso-8859-1)
-    (".*" iso-8859-1)
-    (message-this-is-news iso-8859-1)
     (message-this-is-mail nil)
-    )
+    (".*" iso-8859-1)
+    (message-this-is-news iso-8859-1))
   "Alist of regexps (to match group names) and default charsets to be unencoded when posting."
   :type '(repeat (list (regexp :tag "Group")
                       (symbol :tag "Charset")))
@@ -145,9 +137,10 @@ Developers. (the addresses below are mailing list addresses)
 The buffer below is a mail buffer.  When you press `C-c C-c', it will
 be sent to the Gnus Bug Exterminators.
 
-At the bottom of the buffer you'll see lots of variable settings.
-Please do not delete those.  They will tell the Bug People what your
-environment is, so that it will be easier to locate the bugs.
+The thing near the bottom of the buffer is how the environment
+settings will be included in the mail.  Please do not delete that.
+They will tell the Bug People what your environment is, so that it
+will be easier to locate the bugs.
 
 If you have found a bug that makes Emacs go \"beep\", set
 debug-on-error to t (`M-x set-variable RET debug-on-error RET t RET')
@@ -238,16 +231,18 @@ Thank you for your help in stamping out bugs.
 
 (defun gnus-setup-posting-charset (group)
   (let ((alist gnus-group-posting-charset-alist)
+       (group (or group ""))
        elem)
-    (catch 'found
-      (while (setq elem (pop alist))
-       (when (or (and (stringp (car elem))
-                      (string-match (car elem) group))
-                 (and (gnus-functionp (car elem))
-                      (funcall (car elem) group))
-                 (and (symbolp (car elem))
-                      (symbol-value (car elem))))
-         (throw 'found (cadr elem)))))))
+    (when group
+      (catch 'found
+       (while (setq elem (pop alist))
+         (when (or (and (stringp (car elem))
+                        (string-match (car elem) group))
+                   (and (gnus-functionp (car elem))
+                        (funcall (car elem) group))
+                   (and (symbolp (car elem))
+                        (symbol-value (car elem))))
+           (throw 'found (cadr elem))))))))
 
 (defun gnus-inews-add-send-actions (winconf buffer article)
   (make-local-hook 'message-sent-hook)
@@ -351,10 +346,10 @@ If prefix argument YANK is non-nil, original article is yanked automatically."
   (gnus-summary-followup (gnus-summary-work-articles arg) t))
 
 (defun gnus-inews-yank-articles (articles)
-  (let ((frame (when (and message-use-multi-frames
-                         (> (length articles) 1))
-                (window-frame (get-buffer-window (current-buffer)))))
-       beg article)
+  (let* ((more-than-one (cdr articles))
+        (frame (when (and message-use-multi-frames more-than-one)
+                 (window-frame (get-buffer-window (current-buffer)))))
+        refs beg article)
     (message-goto-body)
     (while (setq article (pop articles))
       (save-window-excursion
@@ -363,6 +358,14 @@ If prefix argument YANK is non-nil, original article is yanked automatically."
        (gnus-summary-remove-process-mark article))
       (when frame
        (select-frame frame))
+
+      ;; Gathering references.
+      (when more-than-one
+       (setq refs (message-list-references
+                   refs
+                   (mail-header-references gnus-current-headers)
+                   (mail-header-message-id gnus-current-headers))))
+
       (gnus-copy-article-buffer)
       (let ((message-reply-buffer gnus-article-copy)
            (message-reply-headers gnus-current-headers))
@@ -371,6 +374,25 @@ If prefix argument YANK is non-nil, original article is yanked automatically."
       (when articles
        (insert "\n")))
     (push-mark)
+
+    ;; Replace with the gathered references.
+    (when refs
+      (push-mark beg)
+      (save-restriction
+       (message-narrow-to-headers)
+       (let ((case-fold-search t))
+         (if (re-search-forward "^References:\\([\t ]+.+\n\\)+" nil t)
+             (replace-match "")
+           (goto-char (point-max))))
+       (mail-header-format
+        (list (or (assq 'References message-header-format-alist)
+                  '(References . message-shorten-references)))
+        (list (cons 'References
+                    (mapconcat 'identity (nreverse refs) " "))))
+       (backward-delete-char 1))
+      (setq beg (mark t))
+      (pop-mark))
+
     (goto-char beg)))
 
 (defun gnus-summary-cancel-article (&optional n symp)
@@ -434,15 +456,18 @@ header line with the old Message-ID."
          ;; Copy over the (displayed) article buffer, delete
          ;; hidden text and remove text properties.
          (widen)
-         (copy-to-buffer gnus-article-copy (point-min) (point-max))
-         (set-buffer gnus-article-copy)
-         (gnus-article-delete-text-of-type 'annotation)
-         (gnus-remove-text-with-property 'gnus-prev)
-         (gnus-remove-text-with-property 'gnus-next)
-         (insert
-          (prog1
-              (format "%s" (buffer-string))
-            (erase-buffer)))
+         (let ((inhibit-read-only t))
+           (copy-to-buffer gnus-article-copy (point-min) (point-max))
+           (set-buffer gnus-article-copy)
+           (gnus-article-delete-text-of-type 'annotation)
+           (gnus-remove-text-with-property 'gnus-prev)
+           (gnus-remove-text-with-property 'gnus-next)
+           (gnus-remove-text-with-property 'x-face-mule-bitmap-image)
+           (insert
+            (prog1
+                (format "%s" (buffer-string))
+              (erase-buffer)))
+           )
          ;; Find the original headers.
          (set-buffer gnus-original-article-buffer)
          (goto-char (point-min))
@@ -596,8 +621,13 @@ If SILENT, don't prompt the user."
 
 (defun gnus-extended-version ()
   "Stringified gnus version."
-  (concat gnus-product-name "/" gnus-version-number " (based on "
-         gnus-original-product-name " v" gnus-original-version-number ")"))
+  (concat gnus-product-name "/" gnus-version-number
+         " (based on "
+         gnus-original-product-name " v" gnus-original-version-number ")"
+         (if (zerop (string-to-number gnus-revision-number))
+             ""
+           (concat " (revision " gnus-revision-number ")"))
+         ))
 
 (defun gnus-message-make-user-agent (&optional include-mime-info max-column)
   "Return user-agent info.
@@ -708,16 +738,20 @@ If FULL-HEADERS (the prefix), include full headers when forwarding."
   (interactive "P")
   (let ((subject "Digested Articles")
        (articles (gnus-summary-work-articles n))
-       article)
+       article frame)
     (gnus-setup-message 'forward
       (gnus-summary-select-article)
       (if post (message-news nil subject) (message-mail nil subject))
+      (when (and message-use-multi-frames (cdr articles))
+       (setq frame (window-frame (get-buffer-window (current-buffer)))))
       (message-goto-body)
       (while (setq article (pop articles))
        (save-window-excursion
          (set-buffer gnus-summary-buffer)
          (gnus-summary-select-article nil nil nil article)
          (gnus-summary-remove-process-mark article))
+       (when frame
+         (select-frame frame))
        (insert (mime-make-tag "message" "rfc822") "\n")
        (insert-buffer-substring gnus-original-article-buffer))
       (push-mark)
@@ -728,7 +762,7 @@ If FULL-HEADERS (the prefix), include full headers when forwarding."
   "Digest and forwards all articles in this series to a newsgroup."
   (interactive "P")
   (gnus-summary-mail-digest n t))
+
 (defun gnus-summary-resend-message (address n)
   "Resend the current article to ADDRESS."
   (interactive "sResend message(s) to: \nP")
@@ -918,7 +952,10 @@ If YANK is non-nil, include the original article."
               (stringp nntp-server-type))
       (insert nntp-server-type))
     (insert "\n\n\n\n\n")
-    (gnus-debug)
+    (save-excursion
+      (set-buffer (gnus-get-buffer-create " *gnus environment info*"))
+      (gnus-debug))
+    (insert "<#part type=application/x-emacs-lisp buffer=\" *gnus environment info*\" disposition=inline description=\"User settings\"><#/part>")
     (goto-char (point-min))
     (search-forward "Subject: " nil t)
     (message "")))
@@ -1154,31 +1191,27 @@ this is a reply."
 
 ;;; Posting styles.
 
-(defvar gnus-message-style-insertions nil)
-
 (defun gnus-configure-posting-styles ()
   "Configure posting styles according to `gnus-posting-styles'."
   (unless gnus-inhibit-posting-styles
-    (let ((styles gnus-posting-styles)
-         (gnus-newsgroup-name (or gnus-newsgroup-name ""))
-         style match variable attribute value value-value)
-      (make-local-variable 'gnus-message-style-insertions)
+    (let ((group (or gnus-newsgroup-name ""))
+         (styles gnus-posting-styles)
+         style match variable attribute value v styles results
+         filep name address element)
       ;; If the group has a posting-style parameter, add it at the end with a
       ;; regexp matching everything, to be sure it takes precedence over all
       ;; the others.
-      (unless (zerop (length gnus-newsgroup-name))
-       (let ((tmp-style (gnus-group-find-parameter
-                         gnus-newsgroup-name 'posting-style t)))
+      (when gnus-newsgroup-name
+       (let ((tmp-style (gnus-group-find-parameter group 'posting-style t)))
          (when tmp-style
            (setq styles (append styles (list (cons ".*" tmp-style)))))))
       ;; Go through all styles and look for matches.
-      (while styles
-       (setq style (pop styles)
-             match (pop style))
+      (dolist (style styles)
+       (setq match (pop style))
        (when (cond
               ((stringp match)
                ;; Regexp string match on the group name.
-               (string-match match gnus-newsgroup-name))
+               (string-match match group))
               ((or (symbolp match)
                    (gnus-functionp match))
                (cond
@@ -1192,58 +1225,84 @@ this is a reply."
                ;; This is a form to be evaled.
                (eval match)))
          ;; We have a match, so we set the variables.
-         (while style
-           (setq attribute (pop style)
-                 value (cadr attribute)
-                 variable nil)
-           ;; We find the variable that is to be modified.
-           (if (and (not (stringp (car attribute)))
-                    (not (eq 'body (car attribute)))
-                    (not (setq variable
-                               (cdr (assq (car attribute)
-                                          gnus-posting-style-alist)))))
-               (message "Couldn't find attribute %s" (car attribute))
-             ;; We get the value.
-             (setq value-value
+         (dolist (attribute style)
+           (setq element (pop attribute)
+                 variable nil
+                 filep nil)
+           (setq value
+                 (cond
+                  ((eq (car attribute) :file)
+                   (setq filep t)
+                   (cadr attribute))
+                  ((eq (car attribute) :value)
+                   (cadr attribute))
+                  (t
+                   (car attribute))))
+           ;; We get the value.
+           (setq v
+                 (cond
+                  ((stringp value)
+                   value)
+                  ((or (symbolp value)
+                       (gnus-functionp value))
+                   (cond ((gnus-functionp value)
+                          (funcall value))
+                         ((boundp value)
+                          (symbol-value value))))
+                  ((listp value)
+                   (eval value))))
+           ;; Translate obsolescent value.
+           (when (eq element 'signature-file)
+             (setq element 'signature
+                   filep t))
+           ;; Get the contents of file elems.
+           (when filep
+             (setq v (with-temp-buffer
+                       (insert-file-contents v)
+                       (buffer-string))))
+           (setq results (delq (assoc element results) results))
+           (push (cons element v) results))))
+      ;; Now we have all the styles, so we insert them.
+      (setq name (assq 'name results)
+           address (assq 'address results))
+      (setq results (delq name (delq address results)))
+      (make-local-variable 'message-setup-hook)
+      (dolist (result results)
+       (when (cdr result)
+         (add-hook 'message-setup-hook
                    (cond
-                    ((stringp value)
-                     value)
-                    ((or (symbolp value)
-                         (gnus-functionp value))
-                     (cond ((gnus-functionp value)
-                            (funcall value))
-                           ((boundp value)
-                            (symbol-value value))))
-                    ((listp value)
-                     (eval value))))
-             (if variable
-                 ;; This is an ordinary variable.
-                 (set (make-local-variable variable) value-value)
-               ;; This is either a body or a header to be inserted in the
-               ;; message.
-               (let ((attr (car attribute)))
-                 (make-local-variable 'message-setup-hook)
-                 (if (eq 'body attr)
-                     (add-hook 'message-setup-hook
-                               `(lambda ()
-                                  (save-excursion
-                                    (message-goto-body)
-                                    (insert ,value-value))))
-                   (add-hook 'message-setup-hook
-                             'gnus-message-insert-stylings)
-                   (push (cons (if (stringp attr) attr
-                                 (symbol-name attr))
-                               value-value)
-                         gnus-message-style-insertions)))))))))))
-
-(defun gnus-message-insert-stylings ()
-  (let (val)
-    (save-excursion
-      (message-goto-eoh)
-      (while (setq val (pop gnus-message-style-insertions))
-       (when (cdr val)
-         (insert (car val) ": " (cdr val) "\n"))
-       (gnus-pull (car val) gnus-message-style-insertions t)))))
+                    ((eq 'body (car result))
+                     `(lambda ()
+                        (save-excursion
+                          (message-goto-body)
+                          (insert ,(cdr result)))))
+                    ((eq 'signature (car result))
+                     (set (make-local-variable 'message-signature) nil)
+                     (set (make-local-variable 'message-signature-file) nil)
+                     `(lambda ()
+                        (save-excursion
+                          (let ((message-signature ,(cdr result)))
+                            (message-insert-signature)))))
+                    (t
+                     (let ((header
+                            (if (symbolp (car result))
+                                (capitalize (symbol-name (car result)))
+                              (car result))))
+                       `(lambda ()
+                          (save-excursion
+                            (message-remove-header ,header)
+                            (message-goto-eoh)
+                            (insert ,header ": " ,(cdr result) "\n")))))))))
+      (when (or name address)
+       (add-hook 'message-setup-hook
+                 `(lambda ()
+                    (let ((user-full-name ,(or (cdr name) user-full-name))
+                          (user-mail-address
+                           ,(or (cdr address) user-mail-address)))
+                      (save-excursion
+                        (message-remove-header "From")
+                        (message-goto-eoh)
+                        (insert "From: " (message-make-from) "\n")))))))))
 
 
 ;;; @ for MIME Edit mode