This commit was generated by cvs2svn to compensate for changes in r2665,
[elisp/gnus.git-] / lisp / gnus-msg.el
index ba08218..116ad34 100644 (file)
@@ -1,9 +1,10 @@
-;;; gnus-msg.el --- mail and post interface for Open gnus
-;; Copyright (C) 1995,96,97 Free Software Foundation, Inc.
+;;; gnus-msg.el --- mail and post interface for Semi-gnus
+;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;;         Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;;     Shuhei KOBAYASHI <shuhei-k@jaist.ac.jp>
 ;; Keywords: mail, news, MIME
 
 ;; This file is part of GNU Emacs.
 (require 'message)
 (require 'gnus-art)
 
-;; Added by Sudish Joseph <joseph@cis.ohio-state.edu>.
-(defvar gnus-post-method nil
+(defcustom gnus-post-method nil
   "*Preferred method for posting USENET news.
-If this variable is nil, Gnus will use the current method to decide
-which method to use when posting.  If it is non-nil, it will override
-the current method.  This method will not be used in mail groups and
-the like, only in \"real\" newsgroups.
 
-The value must be a valid method as discussed in the documentation of
-`gnus-select-method'.  It can also be a list of methods.  If that is
-the case, the user will be queried for what select method to use when
-posting.")
+If this variable is `current', Gnus will use the \"current\" select
+method when posting.  If it is nil (which is the default), Gnus will
+use the native posting method of the server.
+
+This method will not be used in mail groups and the like, only in
+\"real\" newsgroups.
+
+If not nil nor `native', the value must be a valid method as discussed
+in the documentation of `gnus-select-method'. It can also be a list of
+methods. If that is the case, the user will be queried for what select
+method to use when posting."
+  :group 'gnus-group-foreign
+  :type `(choice (const nil)
+                 (const current)
+                (const native)
+                (sexp :tag "Methods" ,gnus-select-method)))
 
 (defvar gnus-outgoing-message-group nil
   "*All outgoing messages will be put in this group.
@@ -67,13 +75,6 @@ the group.")
 (defvar gnus-add-to-list nil
   "*If non-nil, add a `to-list' parameter automatically.")
 
-(defvar gnus-sent-message-ids-file
-  (nnheader-concat gnus-directory "Sent-Message-IDs")
-  "File where Gnus saves a cache of sent message ids.")
-
-(defvar gnus-sent-message-ids-length 1000
-  "The number of sent Message-IDs to save.")
-
 (defvar gnus-crosspost-complaint
   "Hi,
 
@@ -95,15 +96,38 @@ the second with the current group name.")
 (defvar gnus-message-setup-hook nil
   "Hook run after setting up a message buffer.")
 
+(defvar gnus-bug-create-help-buffer t
+  "*Should we create the *Gnus Help Bug* buffer?")
+
+(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.")
+
 ;;; Internal variables.
 
+(defvar gnus-inhibit-posting-styles nil
+  "Inhibit the use of posting styles.")
+
 (defvar gnus-message-buffer "*Mail Gnus*")
 (defvar gnus-article-copy nil)
 (defvar gnus-last-posting-server nil)
 (defvar gnus-message-group-art nil)
 
 (defconst gnus-bug-message
-  "Sending a bug report to the Gnus Towers.
+  (format "Sending a bug report to the Gnus Towers.
+========================================
+
+This gnus is the %s%s.
+If you think the bug is a Semi-gnus bug, send a bug report to Semi-gnus
+Developers. (the addresses below are mailing list addresses)
+
 ========================================
 
 The buffer below is a mail buffer.  When you press `C-c C-c', it will
@@ -120,7 +144,12 @@ and include the backtrace in your bug report.
 Please describe the bug in annoying, painstaking detail.
 
 Thank you for your help in stamping out bugs.
-")
+"
+
+         gnus-product-name
+         (if (string= gnus-product-name "Semi-gnus")
+             ""
+           ", a modified version of Semi-gnus")))
 
 (eval-and-compile
   (autoload 'gnus-uu-post-news "gnus-uu" nil t)
@@ -151,8 +180,8 @@ Thank you for your help in stamping out bugs.
   "\M-c" gnus-summary-mail-crosspost-complaint
   "om" gnus-summary-mail-forward
   "op" gnus-summary-post-forward
-  "Om" gnus-uu-digest-mail-forward
-  "Op" gnus-uu-digest-post-forward)
+  "Om" gnus-summary-mail-digest
+  "Op" gnus-summary-post-digest)
 
 (gnus-define-keys (gnus-send-bounce-map "D" gnus-summary-send-map)
   "b" gnus-summary-resend-bounced-mail
@@ -165,23 +194,32 @@ Thank you for your help in stamping out bugs.
 (defmacro gnus-setup-message (config &rest forms)
   (let ((winconf (make-symbol "gnus-setup-message-winconf"))
        (buffer (make-symbol "gnus-setup-message-buffer"))
-       (article (make-symbol "gnus-setup-message-article")))
+       (article (make-symbol "gnus-setup-message-article"))
+       (group (make-symbol "gnus-setup-message-group")))
     `(let ((,winconf (current-window-configuration))
           (,buffer (buffer-name (current-buffer)))
           (,article (and gnus-article-reply (gnus-summary-article-number)))
+          (,group gnus-newsgroup-name)
           (message-header-setup-hook
-           (copy-sequence message-header-setup-hook)))
+           (copy-sequence message-header-setup-hook))
+          (message-mode-hook (copy-sequence message-mode-hook))
+          (message-startup-parameter-alist
+           '((reply-buffer . gnus-copy-article-buffer)
+             (original-buffer . gnus-original-article-buffer)
+             (user-agent . Gnus))))
        (add-hook 'message-header-setup-hook 'gnus-inews-insert-gcc)
        (add-hook 'message-header-setup-hook 'gnus-inews-insert-archive-gcc)
+       (add-hook 'message-mode-hook 'gnus-configure-posting-styles)
        (unwind-protect
           (progn
             ,@forms)
         (gnus-inews-add-send-actions ,winconf ,buffer ,article)
         (setq gnus-message-buffer (current-buffer))
         (set (make-local-variable 'gnus-message-group-art)
-             (cons ,gnus-newsgroup-name ,article))
+             (cons ,group ,article))
         (make-local-variable 'gnus-newsgroup-name)
-        (run-hooks 'gnus-message-setup-hook))
+        (gnus-run-hooks 'gnus-message-setup-hook))
+       (gnus-add-buffer)
        (gnus-configure-windows ,config t)
        (set-buffer-modified-p nil))))
 
@@ -191,13 +229,14 @@ Thank you for your help in stamping out bugs.
   (setq message-post-method
        `(lambda (arg)
           (gnus-post-method arg ,gnus-newsgroup-name)))
-  (setq message-newsreader (setq message-mailer (gnus-extended-version)))
-  (message-add-action
-   `(set-window-configuration ,winconf) 'exit 'postpone 'kill)
+  (setq message-user-agent (gnus-extended-version))
+  (when (not message-use-multi-frames)
+    (message-add-action
+     `(set-window-configuration ,winconf) 'exit 'postpone 'kill))
   (message-add-action
-   `(when (buffer-name (get-buffer ,buffer))
+   `(when (gnus-buffer-exists-p ,buffer)
       (save-excursion
-       (set-buffer (get-buffer ,buffer))
+       (set-buffer ,buffer)
        ,(when article
           `(gnus-summary-mark-article-as-replied ,article))))
    'send))
@@ -218,8 +257,7 @@ Thank you for your help in stamping out bugs.
 If ARG, post to the group under point.
 If ARG is 1, prompt for a group name."
   (interactive "P")
-  ;; Bind this variable here to make message mode hooks
-  ;; work ok.
+  ;; Bind this variable here to make message mode hooks work ok.
   (let ((gnus-newsgroup-name
         (if arg
             (if (= 1 (prefix-numeric-value arg))
@@ -313,16 +351,17 @@ post using the current select method."
 This is done simply by taking the old article and adding a Supersedes
 header line with the old Message-ID."
   (interactive)
-  (let ((article (gnus-summary-article-number)))
+  (let ((article (gnus-summary-article-number))
+       gnus-message-setup-hook)
     (gnus-setup-message 'reply-yank
       (gnus-summary-select-article t)
       (set-buffer gnus-original-article-buffer)
       (message-supersede)
       (push
        `((lambda ()
-          (when (buffer-name (get-buffer ,gnus-summary-buffer))
+          (when (gnus-buffer-exists-p ,gnus-summary-buffer)
             (save-excursion
-              (set-buffer (get-buffer ,gnus-summary-buffer))
+              (set-buffer ,gnus-summary-buffer)
               (gnus-cache-possibly-remove-article ,article nil nil nil t)
               (gnus-summary-mark-as-read ,article gnus-canceled-mark)))))
        message-send-actions))))
@@ -334,14 +373,12 @@ header line with the old Message-ID."
   ;; this copy is in the buffer gnus-article-copy.
   ;; if ARTICLE-BUFFER is nil, gnus-article-buffer is used
   ;; this buffer should be passed to all mail/news reply/post routines.
-  (setq gnus-article-copy (get-buffer-create " *gnus article copy*"))
+  (setq gnus-article-copy (gnus-get-buffer-create " *gnus article copy*"))
   (buffer-disable-undo gnus-article-copy)
-  (or (memq gnus-article-copy gnus-buffer-list)
-      (push gnus-article-copy gnus-buffer-list))
   (let ((article-buffer (or article-buffer gnus-article-buffer))
-       end beg contents)
+       end beg)
     (if (not (and (get-buffer article-buffer)
-                 (buffer-name (get-buffer article-buffer))))
+                 (gnus-buffer-exists-p article-buffer)))
        (error "Can't find any article buffer")
       (save-excursion
        (set-buffer article-buffer)
@@ -410,6 +447,7 @@ header line with the old Message-ID."
            (if post
                (message-news (or to-group group))
              (set-buffer gnus-article-copy)
+             (gnus-msg-treat-broken-reply-to)
              (message-followup (if (or newsgroup-p force-news) nil to-group)))
          ;; The is mail.
          (if post
@@ -423,12 +461,19 @@ header line with the old Message-ID."
                  (push (list 'gnus-inews-add-to-address pgroup)
                        message-send-actions)))
            (set-buffer gnus-article-copy)
-           (message-wide-reply to-address
-                               (gnus-group-find-parameter
-                                gnus-newsgroup-name 'broken-reply-to))))
+           (gnus-msg-treat-broken-reply-to)
+           (message-wide-reply to-address)))
        (when yank
          (gnus-inews-yank-articles yank))))))
 
+(defun gnus-msg-treat-broken-reply-to ()
+  "Remove the Reply-to header iff broken-reply-to."
+  (when (gnus-group-find-parameter
+        gnus-newsgroup-name 'broken-reply-to)
+    (save-restriction
+      (message-narrow-to-head)
+      (message-remove-header "reply-to"))))
+
 (defun gnus-post-method (arg group &optional silent)
   "Return the posting method based on GROUP and ARG.
 If SILENT, don't prompt the user."
@@ -437,22 +482,28 @@ If SILENT, don't prompt the user."
      ;; If the group-method is nil (which shouldn't happen) we use
      ;; the default method.
      ((null group-method)
-      (or gnus-post-method gnus-select-method message-post-method))
-     ;; We want this group's method.
+      (or (and (null (eq gnus-post-method 'active)) gnus-post-method)
+              gnus-select-method message-post-method))
+     ;; We want the inverse of the default
      ((and arg (not (eq arg 0)))
-      group-method)
+      (if (eq gnus-post-method 'active)
+         gnus-select-method
+       group-method))
      ;; We query the user for a post method.
      ((or arg
          (and gnus-post-method
+              (not (eq gnus-post-method 'current))
               (listp (car gnus-post-method))))
       (let* ((methods
              ;; Collect all methods we know about.
              (append
-              (when gnus-post-method
+              (when (and gnus-post-method
+                         (not (eq gnus-post-method 'current)))
                 (if (listp (car gnus-post-method))
                     gnus-post-method
                   (list gnus-post-method)))
               gnus-secondary-select-methods
+              (mapcar 'cdr gnus-server-alist)
               (list gnus-select-method)
               (list group-method)))
             method-alist post-methods method)
@@ -481,80 +532,67 @@ If SILENT, don't prompt the user."
                   (cons (or gnus-last-posting-server "") 0))))
          method-alist))))
      ;; Override normal method.
-     (gnus-post-method
+     ((and (eq gnus-post-method 'current)
+          (not (eq (car group-method) 'nndraft))
+          (not arg))
+      group-method) 
+     ((and gnus-post-method
+          (not (eq gnus-post-method 'current)))
       gnus-post-method)
      ;; Use the normal select method.
      (t gnus-select-method))))
 
-;;;
-;;; Check whether the message has been sent already.
-;;;
-
-(defvar gnus-inews-sent-ids nil)
-
-(defun gnus-inews-reject-message ()
-  "Check whether this message has already been sent."
-  (when gnus-sent-message-ids-file
-    (let ((message-id (save-restriction (message-narrow-to-headers)
-                                       (mail-fetch-field "message-id")))
-         end)
-      (when message-id
-       (unless gnus-inews-sent-ids
-         (ignore-errors
-           (load t t t)))
-       (if (member message-id gnus-inews-sent-ids)
-           ;; Reject this message.
-           (not (gnus-yes-or-no-p
-                 (format "Message %s already sent.  Send anyway? "
-                         message-id)))
-         (push message-id gnus-inews-sent-ids)
-         ;; Chop off the last Message-IDs.
-         (when (setq end (nthcdr gnus-sent-message-ids-length
-                                 gnus-inews-sent-ids))
-           (setcdr end nil))
-         (nnheader-temp-write gnus-sent-message-ids-file
-           (gnus-prin1 `(setq gnus-inews-sent-ids ',gnus-inews-sent-ids)))
-         nil)))))
-
 \f
 
 ;; Dummy to avoid byte-compile warning.
 (defvar nnspool-rejected-article-hook)
 (defvar xemacs-codename)
 
-;;; Since the X-Newsreader/X-Mailer are ``vanity'' headers, they might
-;;; as well include the Emacs version as well.
-;;; The following function works with later GNU Emacs, and XEmacs.
 (defun gnus-extended-version ()
-  "Stringified Gnus version"
+  "Stringified gnus version."
   (interactive)
-  gnus-version)
-
-;; Written by "Mr. Per Persson" <pp@gnu.ai.mit.edu>.
-(defun gnus-inews-insert-mime-headers ()
-  (goto-char (point-min))
-  (let ((mail-header-separator
-        (progn
-          (goto-char (point-min))
-          (if (and (search-forward (concat "\n" mail-header-separator "\n")
-                                   nil t)
-                   (not (search-backward "\n\n" nil t)))
-              mail-header-separator
-            ""))))
-    (or (mail-position-on-field "Mime-Version")
-       (insert "1.0")
-       (cond ((save-restriction
-                (widen)
-                (goto-char (point-min))
-                (re-search-forward "[\200-\377]" nil t))
-              (or (mail-position-on-field "Content-Type")
-                  (insert "text/plain; charset=ISO-8859-1"))
-              (or (mail-position-on-field "Content-Transfer-Encoding")
-                  (insert "8bit")))
-             (t (or (mail-position-on-field "Content-Type")
-                    (insert "text/plain; charset=US-ASCII"))
-                (or (mail-position-on-field "Content-Transfer-Encoding")
-                    (insert "7bit")))))))
+  (concat gnus-product-name "/" gnus-version-number))
+
+(defun gnus-message-make-user-agent (&optional include-mime-info max-column)
+  "Return user-agent info.
+INCLUDE-MIME-INFO the optional first argument if it is non-nil and the variable
+  `mime-edit-user-agent-value' exists, the return value will include it.
+MAX-COLUMN the optional second argument if it is specified, the return value
+  will be folded up in the proper way."
+  (let ((user-agent (if (and include-mime-info
+                            (boundp 'mime-edit-user-agent-value))
+                       (concat (gnus-extended-version)
+                               " "
+                               mime-edit-user-agent-value)
+                     (gnus-extended-version))))
+    (if max-column
+       (let (boundary)
+         (unless (natnump max-column) (setq max-column 76))
+         (with-temp-buffer
+           (insert "            " user-agent)
+           (goto-char 13)
+           (while (re-search-forward "[\n\t ]+" nil t)
+             (replace-match " "))
+           (goto-char 13)
+           (while (re-search-forward "[^ ()/]+\\(/[^ ()/]+\\)? ?" nil t)
+             (while (eq ?\( (char-after (point)))
+               (forward-list)
+               (skip-chars-forward " "))
+             (skip-chars-backward " ")
+             (if (> (current-column) max-column)
+                 (progn
+                   (if (or (not boundary) (eq ?\n (char-after boundary)))
+                       (progn
+                         (setq boundary (point))
+                         (unless (eobp)
+                           (delete-char 1)
+                           (insert "\n ")))
+                     (goto-char boundary)
+                     (delete-char 1)
+                     (insert "\n ")))
+               (setq boundary (point))))
+           (buffer-substring 13 (point-max))))
+      user-agent)))
 
 \f
 ;;;
@@ -577,8 +615,8 @@ automatically."
     (gnus-setup-message (if yank 'reply-yank 'reply)
       (gnus-summary-select-article)
       (set-buffer (gnus-copy-article-buffer))
-      (message-reply nil wide (gnus-group-find-parameter
-                              gnus-newsgroup-name 'broken-reply-to))
+      (gnus-msg-treat-broken-reply-to)
+      (message-reply nil wide)
       (when yank
        (gnus-inews-yank-articles yank)))))
 
@@ -609,11 +647,48 @@ If FULL-HEADERS (the prefix), include full headers when forwarding."
   (interactive "P")
   (gnus-setup-message 'forward
     (gnus-summary-select-article)
-    (set-buffer gnus-original-article-buffer)
+    (let ((charset default-mime-charset))
+      (set-buffer gnus-original-article-buffer)
+      (make-local-variable 'default-mime-charset)
+      (setq default-mime-charset charset)
+      )
     (let ((message-included-forward-headers
           (if full-headers "" message-included-forward-headers)))
       (message-forward post))))
 
+(defun gnus-summary-post-forward (&optional full-headers)
+  "Forward the current article to a newsgroup.
+If FULL-HEADERS (the prefix), include full headers when forwarding."
+  (interactive "P")
+  (gnus-summary-mail-forward full-headers t))
+
+;;; XXX: generate Subject and ``Topics''?
+(defun gnus-summary-mail-digest (&optional n post)
+  "Digests and forwards all articles in this series."
+  (interactive "P")
+  (let ((subject "Digested Articles")
+       (articles (gnus-summary-work-articles n))
+       article)
+    (gnus-setup-message 'forward
+      (gnus-summary-select-article)
+      (if post (message-news nil subject) (message-mail nil subject))
+      (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))
+       (insert (mime-make-tag "message" "rfc822") "\n")
+       (insert-buffer-substring gnus-original-article-buffer))
+      (push-mark)
+      (message-goto-body)
+      (mime-edit-enclose-digest-region (point)(mark t)))))
+
+(defun gnus-summary-post-digest (&optional n)
+  "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")
@@ -625,12 +700,6 @@ If FULL-HEADERS (the prefix), include full headers when forwarding."
        (set-buffer gnus-original-article-buffer)
        (message-resend address)))))
 
-(defun gnus-summary-post-forward (&optional full-headers)
-  "Forward the current article to a newsgroup.
-If FULL-HEADERS (the prefix), include full headers when forwarding."
-  (interactive "P")
-  (gnus-summary-mail-forward full-headers t))
-
 (defvar gnus-nastygram-message
   "The following article was inappropriately posted to %s.\n\n"
   "Format string to insert in nastygrams.
@@ -783,18 +852,21 @@ If YANK is non-nil, include the original article."
     (error "Gnus has been shut down"))
   (gnus-setup-message 'bug
     (delete-other-windows)
-    (switch-to-buffer (get-buffer-create "*Gnus Help Bug*"))
-    (erase-buffer)
-    (insert gnus-bug-message)
-    (goto-char (point-min))
+    (when gnus-bug-create-help-buffer
+      (switch-to-buffer "*Gnus Help Bug*")
+      (erase-buffer)
+      (insert gnus-bug-message)
+      (goto-char (point-min)))
     (message-pop-to-buffer "*Gnus Bug*")
-    (message-setup `((To . ,gnus-maintainer) (Subject . "")))
-    (push `(gnus-bug-kill-buffer) message-send-actions)
+    (message-setup
+     `((To . ,gnus-maintainer) (Cc . ,semi-gnus-developers) (Subject . "")))
+    (when gnus-bug-create-help-buffer
+      (push `(gnus-bug-kill-buffer) message-send-actions))
     (goto-char (point-min))
     (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
     (forward-line 1)
-    (insert (gnus-version) "\n")
-    (insert (emacs-version) "\n")
+    (insert (gnus-version) "\n"
+           (emacs-version) "\n")
     (when (and (boundp 'nntp-server-type)
               (stringp nntp-server-type))
       (insert nntp-server-type))
@@ -822,7 +894,7 @@ The source file has to be in the Emacs load path."
     (sit-for 0)
     ;; Go through all the files looking for non-default values for variables.
     (save-excursion
-      (set-buffer (get-buffer-create " *gnus bug info*"))
+      (set-buffer (gnus-get-buffer-create " *gnus bug info*"))
       (buffer-disable-undo (current-buffer))
       (while files
        (erase-buffer)
@@ -882,14 +954,15 @@ this is a reply."
   (interactive "P")
   (gnus-summary-select-article t)
   (set-buffer gnus-original-article-buffer)
-  (gnus-setup-message 'compose-bounce
-    (let* ((references (mail-fetch-field "references"))
-          (parent (and references (gnus-parent-id references))))
-      (message-bounce)
-      ;; If there are references, we fetch the article we answered to.
-      (and fetch parent
-          (gnus-summary-refer-article parent)
-          (gnus-summary-show-all-headers)))))
+  (let (gnus-message-setup-hook)
+    (gnus-setup-message 'compose-bounce
+      (let* ((references (mail-fetch-field "references"))
+            (parent (and references (gnus-parent-id references))))
+       (message-bounce)
+       ;; If there are references, we fetch the article we answered to.
+       (and fetch parent
+            (gnus-summary-refer-article parent)
+            (gnus-summary-show-all-headers))))))
 
 ;;; Gcc handling.
 
@@ -930,7 +1003,7 @@ this is a reply."
              (save-excursion
                (nnheader-set-temp-buffer " *acc*")
                (insert-buffer-substring message-encoding-buffer)
-               (run-hooks 'gnus-before-do-gcc-hook)
+               (gnus-run-hooks 'gnus-before-do-gcc-hook)
                (goto-char (point-min))
                (when (re-search-forward
                       (concat "^" (regexp-quote mail-header-separator) "$")
@@ -1033,10 +1106,88 @@ this is a reply."
                (insert " ")))
            (insert "\n")))))))
 
-(gnus-add-shutdown 'gnus-inews-close 'gnus)
-
-(defun gnus-inews-close ()
-  (setq gnus-inews-sent-ids nil))
+;;; 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)
+      ;; Go through all styles and look for matches.
+      (while styles
+       (setq style (pop styles)
+             match (pop style))
+       (when (cond ((stringp match)
+                    ;; Regexp string match on the group name.
+                    (string-match match gnus-newsgroup-name))
+                   ((or (symbolp match)
+                        (gnus-functionp match))
+                    (cond ((gnus-functionp match)
+                           ;; Function to be called.
+                           (funcall match))
+                          ((boundp match)
+                           ;; Variable to be checked.
+                           (symbol-value match))))
+                   ((listp match)
+                    ;; 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
+                   (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.
+               (when value-value
+                 (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)))))
 
 ;;; Allow redefinition of functions.