Synch with Oort Gnus.
[elisp/gnus.git-] / lisp / gnus-msg.el
index 719e7a4..cb5581f 100644 (file)
@@ -1,5 +1,5 @@
 ;;; gnus-msg.el --- mail and post interface for Semi-gnus
-;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001
 ;;        Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
@@ -42,8 +42,8 @@
 (defcustom gnus-post-method 'current
   "*Preferred method for posting USENET news.
 
-If this variable is `current', Gnus will use the \"current\" select
-method when posting.  If it is nil (which is the default), Gnus will
+If this variable is `current' (which is the default), Gnus will use
+the \"current\" select method when posting.  If it is nil, Gnus will
 use the native select method when posting.
 
 This method will not be used in mail groups and the like, only in
@@ -55,11 +55,11 @@ 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 current)
                 (const native)
                 (sexp :tag "Methods" ,gnus-select-method)))
 
-(defvar gnus-outgoing-message-group nil
+(defcustom gnus-outgoing-message-group nil
   "*All outgoing messages will be put in this group.
 If you want to store all your outgoing mail and articles in the group
 \"nnml:archive\", you set this variable to that value.  This variable
@@ -68,18 +68,25 @@ can also be a list of group names.
 If you want to have greater control over what group to put each
 message in, you can set this variable to a function that checks the
 current newsgroup name and then returns a suitable group name (or list
-of names).")
+of names)."
+  :group 'gnus-message
+  :type '(choice (string :tag "Group")
+                 (function)))
 
-(defvar gnus-mailing-list-groups nil
+(defcustom gnus-mailing-list-groups nil
   "*Regexp matching groups that are really mailing lists.
 This is useful when you're reading a mailing list that has been
 gatewayed to a newsgroup, and you want to followup to an article in
-the group.")
+the group."
+  :group 'gnus-message
+  :type 'regexp)
 
-(defvar gnus-add-to-list nil
-  "*If non-nil, add a `to-list' parameter automatically.")
+(defcustom gnus-add-to-list nil
+  "*If non-nil, add a `to-list' parameter automatically."
+  :group 'gnus-message
+  :type 'boolean)
 
-(defvar gnus-crosspost-complaint
+(defcustom gnus-crosspost-complaint
   "Hi,
 
 You posted the article below with the following Newsgroups header:
@@ -95,19 +102,44 @@ Thank you.
 "
   "Format string to be inserted when complaining about crossposts.
 The first %s will be replaced by the Newsgroups header;
-the second with the current group name.")
-
-(defvar gnus-message-setup-hook '(gnus-maybe-setup-default-charset)
-  "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-inews-mark-gcc-as-read nil
-  "If non-nil, automatically mark Gcc articles as read.")
+the second with the current group name."
+  :group 'gnus-message
+  :type 'string)
+
+(defcustom gnus-message-setup-hook '(gnus-maybe-setup-default-charset)
+  "Hook run after setting up a message buffer."
+  :group 'gnus-message
+  :type 'hook)
+
+(defcustom gnus-bug-create-help-buffer t
+  "*Should we create the *Gnus Help Bug* buffer?"
+  :group 'gnus-message
+  :type 'boolean)
+
+(defcustom gnus-posting-styles nil
+  "*Alist of styles to use when posting."
+  :group 'gnus-message
+  :type '(repeat (cons (choice (regexp)
+                              (function)
+                              (variable)
+                              (sexp))
+                      (repeat (list
+                               (choice (const signature)
+                                       (const signature-file)
+                                       (const organization)
+                                       (const address)
+                                       (const name)
+                                       (const body)
+                                       (string :tag "Header"))
+                               (choice (string)
+                                       (function)
+                                       (variable)
+                                       (sexp)))))))
+
+(defcustom gnus-inews-mark-gcc-as-read nil
+  "If non-nil, automatically mark Gcc articles as read."
+  :group 'gnus-message
+  :type 'boolean)
 
 (defcustom gnus-group-posting-charset-alist
   '(("^\\(no\\|fr\\)\\.[^,]*\\(,[ \t\n]*\\(no\\|fr\\)\\.[^,]*\\)*$" iso-8859-1 (iso-8859-1))
@@ -127,18 +159,20 @@ nil (always encode using quoted-printable) or t (always use 8bit).
 Note that any value other than nil for HEADER infringes some RFCs, so
 use this option with care."
   :type '(repeat (list :tag "Permitted unencoded charsets"
-                 (choice :tag "Where"
-                  (regexp :tag "Group")
-                  (const :tag "Mail message" :value message-this-is-mail)
-                  (const :tag "News article" :value message-this-is-news))
-                 (choice :tag "Header"
-                  (const :tag "None" nil)
-                  (symbol :tag "Charset"))
-                 (choice :tag "Body"
-                         (const :tag "Any" :value t)
-                         (const :tag "None" :value nil)
-                         (repeat :tag "Charsets"
-                                 (symbol :tag "Charset")))))
+                      (choice :tag "Where"
+                              (regexp :tag "Group")
+                              (const :tag "Mail message"
+                                     :value message-this-is-mail)
+                              (const :tag "News article"
+                                     :value message-this-is-news))
+                      (choice :tag "Header"
+                              (const :tag "None" nil)
+                              (symbol :tag "Charset"))
+                      (choice :tag "Body"
+                              (const :tag "Any" :value t)
+                              (const :tag "None" :value nil)
+                              (repeat :tag "Charsets"
+                                      (symbol :tag "Charset")))))
   :group 'gnus-charset)
 
 ;;; Internal variables.
@@ -152,6 +186,8 @@ use this option with care."
 (defvar gnus-last-posting-server nil)
 (defvar gnus-message-group-art nil)
 
+(defvar gnus-msg-force-broken-reply-to nil)
+
 (defconst gnus-bug-message
   (format "Sending a bug report to the Gnus Towers.
 ========================================
@@ -206,15 +242,19 @@ Thank you for your help in stamping out bugs.
   "R" gnus-summary-reply-with-original
   "w" gnus-summary-wide-reply
   "W" gnus-summary-wide-reply-with-original
+  "v" gnus-summary-very-wide-reply
+  "V" gnus-summary-very-wide-reply-with-original
   "n" gnus-summary-followup-to-mail
   "N" gnus-summary-followup-to-mail-with-original
   "m" gnus-summary-mail-other-window
   "u" gnus-uu-post-news
   "\M-c" gnus-summary-mail-crosspost-complaint
+  "Br" gnus-summary-reply-broken-reply-to
+  "BR" gnus-summary-reply-broken-reply-to-with-original
   "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-digest-mail-forward
+  "Op" gnus-summary-digest-post-forward)
 
 (gnus-define-keys (gnus-send-bounce-map "D" gnus-summary-send-map)
   "b" gnus-summary-resend-bounced-mail
@@ -231,7 +271,7 @@ Thank you for your help in stamping out bugs.
        (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)))
+          (,article gnus-article-reply)
           (,group gnus-newsgroup-name)
           (message-header-setup-hook
            (copy-sequence message-header-setup-hook))
@@ -246,7 +286,8 @@ Thank you for your help in stamping out bugs.
        (unwind-protect
           (progn
             ,@forms)
-        (gnus-inews-add-send-actions ,winconf ,buffer ,article)
+        (gnus-inews-add-send-actions ,winconf ,buffer ,article ,config)
+        (gnus-inews-insert-draft-meta-information ,group ,article)
         (setq gnus-message-buffer (current-buffer))
         (set (make-local-variable 'gnus-message-group-art)
              (cons ,group ,article))
@@ -256,21 +297,56 @@ Thank you for your help in stamping out bugs.
        (gnus-configure-windows ,config t)
        (set-buffer-modified-p nil))))
 
+(defun gnus-inews-insert-draft-meta-information (group article)
+  (save-excursion
+    (when (and group
+              (not (string= group ""))
+              (not (message-fetch-field gnus-draft-meta-information-header)))
+      (goto-char (point-min))
+      (insert gnus-draft-meta-information-header ": (\"" group "\" "
+             (if article (number-to-string
+                          (if (listp article)
+                              (car article)
+                            article)) "\"\"")
+             ")\n"))))
+
 ;;;###autoload
-(defun gnus-msg-mail (&rest args)
+(defun gnus-msg-mail (&optional to subject other-headers continue
+                               switch-action yank-action send-actions)
   "Start editing a mail message to be sent.
 Like `message-mail', but with Gnus paraphernalia, particularly the
 Gcc: header for archiving purposes."
   (interactive)
-  (gnus-setup-message 'message
-    (apply 'message-mail args))
+  (let ((buf (current-buffer))
+       mail-buf)
+    (gnus-setup-message 'message
+      (message-mail to subject other-headers continue
+                   nil yank-action send-actions))
+    (when switch-action
+      (setq mail-buf (current-buffer))
+      (switch-to-buffer buf)
+      (apply switch-action mail-buf nil)))
   ;; COMPOSEFUNC should return t if succeed.  Undocumented ???
   t)
 
 ;;;###autoload
+(defun gnus-button-mailto (address)
+  "Mail to ADDRESS."
+  (set-buffer (gnus-copy-article-buffer))
+  (gnus-setup-message 'message
+    (message-reply address)))
+
+;;;###autoload
+(defun gnus-button-reply (&optional to-address wide)
+  "Like `message-reply'."
+  (interactive)
+  (gnus-setup-message 'message
+    (message-reply to-address wide)))
+
+;;;###autoload
 (define-mail-user-agent 'gnus-user-agent
-      'gnus-msg-mail 'message-send-and-exit
-      'message-kill-buffer 'message-send-hook)
+  'gnus-msg-mail 'message-send-and-exit
+  'message-kill-buffer 'message-send-hook)
 
 (defun gnus-setup-posting-charset (group)
   (let ((alist gnus-group-posting-charset-alist)
@@ -287,7 +363,7 @@ Gcc: header for archiving purposes."
                         (symbol-value (car elem))))
            (throw 'found (cons (cadr elem) (caddr elem)))))))))
 
-(defun gnus-inews-add-send-actions (winconf buffer article)
+(defun gnus-inews-add-send-actions (winconf buffer article &optional config)
   (make-local-hook 'message-sent-hook)
   (add-hook 'message-sent-hook (if gnus-agent 'gnus-agent-possibly-do-gcc
                                 'gnus-inews-do-gcc) nil t)
@@ -306,7 +382,9 @@ Gcc: header for archiving purposes."
       (save-excursion
        (set-buffer ,buffer)
        ,(when article
-          `(gnus-summary-mark-article-as-replied ,article))))
+          (if (eq config 'forward)
+              `(gnus-summary-mark-article-as-forwarded ',article)
+            `(gnus-summary-mark-article-as-replied ',article)))))
    'send))
 
 (put 'gnus-setup-message 'lisp-indent-function 1)
@@ -393,29 +471,32 @@ 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* ((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)
+  (let ((more-than-one (cdr articles))
+       (cur (current-buffer))
+       refs beg article window)
     (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))
 
       ;; 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))))
+                   (mail-header-message-id gnus-current-headers)))
+       (when message-use-multi-frames
+         (when (setq window (get-buffer-window cur t))
+           (select-frame (window-frame window)))))
 
       (gnus-copy-article-buffer)
       (let ((message-reply-buffer gnus-article-copy)
-           (message-reply-headers gnus-current-headers))
+           (message-reply-headers
+            (with-current-buffer gnus-article-copy
+              ;; The headers are decoded.
+              (nnheader-parse-head t))))
        (message-yank-original)
        (setq beg (or beg (mark t))))
       (when articles
@@ -522,7 +603,12 @@ header line with the old Message-ID."
              (gnus-remove-text-with-property 'x-face-mule-bitmap-image)
              (insert
               (prog1
-                  (buffer-substring-no-properties (point-min) (point-max))
+                  (static-if (featurep 'xemacs)
+                      ;; Revome smiley extents for (possibly) XEmacs 21.1.
+                      (format "%s"
+                              (buffer-substring-no-properties (point-min)
+                                                              (point-max)))
+                    (buffer-substring-no-properties (point-min) (point-max)))
                 (erase-buffer))))
            ;; Find the original headers.
            (set-buffer gnus-original-article-buffer)
@@ -530,11 +616,11 @@ header line with the old Message-ID."
            (while (looking-at message-unix-mail-delimiter)
              (forward-line 1))
            (setq beg (point))
-           (setq end (or (search-forward "\n\n" nil t) (point)))
+           (setq end (or (message-goto-body) beg))
            ;; Delete the headers from the displayed articles.
            (set-buffer gnus-article-copy)
            (delete-region (goto-char (point-min))
-                          (or (search-forward "\n\n" nil t) (point-max)))
+                          (or (message-goto-body) (point-max)))
            ;; Insert the original article headers.
            (insert-buffer-substring gnus-original-article-buffer beg end)
            (article-decode-encoded-words))))
@@ -544,7 +630,7 @@ header line with the old Message-ID."
                            force-news)
   (when article-buffer
     (gnus-copy-article-buffer))
-  (let ((gnus-article-reply article-buffer)
+  (let ((gnus-article-reply (and article-buffer (gnus-summary-article-number)))
        (add-to-list gnus-add-to-list))
     (gnus-setup-message (cond (yank 'reply-yank)
                              (article-buffer 'reply)
@@ -555,9 +641,9 @@ header line with the old Message-ID."
             to-address to-group mailing-list to-list
             newsgroup-p)
        (when group
-         (setq to-address (gnus-group-find-parameter group 'to-address)
+         (setq to-address (gnus-parameter-to-address group)
                to-group (gnus-group-find-parameter group 'to-group)
-               to-list (gnus-group-find-parameter group 'to-list)
+               to-list (gnus-parameter-to-list group)
                newsgroup-p (gnus-group-find-parameter group 'newsgroup)
                mailing-list (when gnus-mailing-list-groups
                               (string-match gnus-mailing-list-groups group))
@@ -579,7 +665,13 @@ header line with the old Message-ID."
                (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)))
+             (message-followup (if (or newsgroup-p force-news)
+                                   (if (save-restriction
+                                         (article-narrow-to-head)
+                                         (message-fetch-field "newsgroups"))
+                                       nil
+                                     "")
+                                 to-group)))
          ;; The is mail.
          (if post
              (progn
@@ -597,10 +689,11 @@ header line with the old Message-ID."
        (when yank
          (gnus-inews-yank-articles yank))))))
 
-(defun gnus-msg-treat-broken-reply-to ()
+(defun gnus-msg-treat-broken-reply-to (&optional force)
   "Remove the Reply-to header iff broken-reply-to."
-  (when (gnus-group-find-parameter
-        gnus-newsgroup-name 'broken-reply-to)
+  (when (or force
+           (gnus-group-find-parameter
+            gnus-newsgroup-name 'broken-reply-to))
     (save-restriction
       (message-narrow-to-head)
       (message-remove-header "reply-to"))))
@@ -728,21 +821,39 @@ MAX-COLUMN the optional second argument if it is specified, the return value
 
 ;;; Mail reply commands of Gnus summary mode
 
-(defun gnus-summary-reply (&optional yank wide)
-  "Start composing a reply mail to the current message.
+(defun gnus-summary-reply (&optional yank wide very-wide)
+  "Start composing a mail reply to the current message.
 If prefix argument YANK is non-nil, the original article is yanked
-automatically."
+automatically.
+If WIDE, make a wide reply.
+If VERY-WIDE, make a very wide reply."
   (interactive
    (list (and current-prefix-arg
              (gnus-summary-work-articles 1))))
   ;; Stripping headers should be specified with mail-yank-ignored-headers.
   (when yank
     (gnus-summary-goto-subject (car yank)))
-  (let ((gnus-article-reply t))
+  (let ((gnus-article-reply (or yank (gnus-summary-article-number)))
+       (headers ""))
     (gnus-setup-message (if yank 'reply-yank 'reply)
-      (gnus-summary-select-article)
+      (if (not very-wide)
+         (gnus-summary-select-article)
+       (dolist (article very-wide)
+         (gnus-summary-select-article nil nil nil article)
+         (save-excursion
+           (set-buffer (gnus-copy-article-buffer))
+           (gnus-msg-treat-broken-reply-to)
+           (save-restriction
+             (message-narrow-to-head)
+             (setq headers (concat headers (buffer-string)))))))
       (set-buffer (gnus-copy-article-buffer))
-      (gnus-msg-treat-broken-reply-to)
+      (gnus-msg-treat-broken-reply-to gnus-msg-force-broken-reply-to)
+      (save-restriction
+       (message-narrow-to-head)
+       (when very-wide
+         (erase-buffer)
+         (insert headers))
+       (goto-char (point-max)))
       (message-reply nil wide)
       (when yank
        (gnus-inews-yank-articles yank)))))
@@ -753,6 +864,24 @@ The original article will be yanked."
   (interactive "P")
   (gnus-summary-reply (gnus-summary-work-articles n) wide))
 
+(defun gnus-summary-reply-broken-reply-to (&optional yank wide very-wide)
+  "Like `gnus-summary-reply' except removing reply-to field.
+If prefix argument YANK is non-nil, the original article is yanked
+automatically.
+If WIDE, make a wide reply.
+If VERY-WIDE, make a very wide reply."
+  (interactive
+   (list (and current-prefix-arg
+             (gnus-summary-work-articles 1))))
+  (let ((gnus-msg-force-broken-reply-to t))
+    (gnus-summary-reply yank wide very-wide)))
+
+(defun gnus-summary-reply-broken-reply-to-with-original (n &optional wide)
+  "Like `gnus-summary-reply-with-original' except removing reply-to field.
+The original article will be yanked."
+  (interactive "P")
+  (gnus-summary-reply-broken-reply-to (gnus-summary-work-articles n) wide))
+
 (defun gnus-summary-wide-reply (&optional yank)
   "Start composing a wide reply mail to the current message.
 If prefix argument YANK is non-nil, the original article is yanked
@@ -768,6 +897,22 @@ The original article will be yanked."
   (interactive "P")
   (gnus-summary-reply-with-original n t))
 
+(defun gnus-summary-very-wide-reply (&optional yank)
+  "Start composing a very wide reply mail to the current message.
+If prefix argument YANK is non-nil, the original article is yanked
+automatically."
+  (interactive
+   (list (and current-prefix-arg
+             (gnus-summary-work-articles 1))))
+  (gnus-summary-reply yank t (gnus-summary-work-articles yank)))
+
+(defun gnus-summary-very-wide-reply-with-original (n)
+  "Start composing a very wide reply mail to the current message.
+The original article will be yanked."
+  (interactive "P")
+  (gnus-summary-reply
+   (gnus-summary-work-articles n) t (gnus-summary-work-articles n)))
+
 (defun gnus-summary-mail-forward (&optional full-headers post)
   "Forward the current message to another user.
 If FULL-HEADERS (the prefix), include full headers when forwarding."
@@ -782,47 +927,77 @@ If FULL-HEADERS (the prefix), include full headers when forwarding."
           (if full-headers "" message-included-forward-headers)))
       (message-forward post))))
 
-;;;;; 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 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)
-;;      (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-digest-mail-forward (&optional n post)
+  "Digests and forwards all articles in this series.
+If N is a positive number, forward the N next articles.
+If N is a negative number, forward the N previous articles.
+If N is nil and any articles have been marked with the process mark,
+forward those articles instead.
+Optional POST will use news to forward instead of mail."
+  (interactive "P")
+  (let ((articles (gnus-summary-work-articles n))
+       (topics "Topics:\n")
+       subject article frame)
+    (when (car articles)
+      (gnus-setup-message 'forward
+       (gnus-summary-select-article)
+       (if (cdr articles)
+           (setq articles (sort articles '<)
+                 subject "Digested Articles")
+         (with-current-buffer gnus-original-article-buffer
+           (setq subject (message-make-forward-subject))))
+       (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)
+           (setq topics (concat topics "    "
+                                (mail-header-subject gnus-current-headers)
+                                "\n"))
+           (gnus-summary-remove-process-mark article))
+         (when frame
+           (select-frame frame))
+         (insert (mime-make-tag "message" "rfc822") "\n")
+         (narrow-to-region (point) (point))
+         (insert-buffer-substring gnus-original-article-buffer)
+         (save-restriction
+           (article-narrow-to-head)
+           (message-remove-header message-included-forward-headers t nil t))
+         (goto-char (point-max))
+         (widen))
+       (push-mark)
+       (message-goto-body)
+       (insert topics)
+       (message-goto-body)
+       (mime-edit-enclose-digest-region (point)(mark t))))))
+
+(defun gnus-summary-digest-post-forward (&optional n)
+  "Digest and forwards all articles in this series to a newsgroup.
+If N is a positive number, forward the N next articles.
+If N is a negative number, forward the N previous articles.
+If N is nil and any articles have been marked with the process mark,
+forward those articles instead."
+  (interactive "P")
+  (gnus-summary-digest-mail-forward n t))
 
 (defun gnus-summary-resend-message (address n)
   "Resend the current article to ADDRESS."
-  (interactive "sResend message(s) to: \nP")
+  (interactive
+   (list (message-read-from-minibuffer "Resend message(s) to: ")
+        current-prefix-arg))
   (let ((articles (gnus-summary-work-articles n))
        article)
     (while (setq article (pop articles))
       (gnus-summary-select-article nil nil nil article)
       (save-excursion
        (set-buffer gnus-original-article-buffer)
-       (message-resend address)))))
+       (message-resend address))
+      (gnus-summary-mark-article-as-forwarded article))))
 
 (defun gnus-summary-post-forward (&optional full-headers)
   "Forward the current article to a newsgroup.
@@ -932,35 +1107,32 @@ The current group name will be inserted at \"%s\".")
   (let ((reply gnus-article-reply)
        (winconf gnus-prev-winconf)
        (group gnus-newsgroup-name))
+    (unless (and group
+                (not (gnus-group-read-only-p group)))
+      (setq group (read-string "Put in group: " nil (gnus-writable-groups))))
 
-    (or (and group (not (gnus-group-read-only-p group)))
-       (setq group (read-string "Put in group: " nil
-                                (gnus-writable-groups))))
     (when (gnus-gethash group gnus-newsrc-hashtb)
       (error "No such group: %s" group))
-
     (save-excursion
       (save-restriction
        (widen)
        (message-narrow-to-headers)
-       (let (gnus-deletable-headers)
-         (if (message-news-p)
-             (message-generate-headers message-required-news-headers)
-           (message-generate-headers message-required-mail-headers)))
+       (let ((gnus-deletable-headers nil))
+         (message-generate-headers
+          (if (message-news-p)
+              message-required-news-headers
+            message-required-mail-headers)))
        (goto-char (point-max))
        (insert "Gcc: " group "\n")
        (widen)))
-
     (gnus-inews-do-gcc)
-
-    (when (get-buffer gnus-group-buffer)
-      (when (gnus-buffer-exists-p (car-safe reply))
-       (set-buffer (car reply))
-       (and (cdr reply)
-            (gnus-summary-mark-article-as-replied
-             (cdr reply))))
-      (when winconf
-       (set-window-configuration winconf)))))
+    (when (and (get-buffer gnus-group-buffer)
+              (gnus-buffer-exists-p (car-safe reply))
+              (cdr reply))
+      (set-buffer (car reply))
+      (gnus-summary-mark-article-as-replied (cdr reply)))
+    (when winconf
+      (set-window-configuration winconf))))
 
 (defun gnus-article-mail (yank)
   "Send a reply to the address near point.
@@ -983,13 +1155,15 @@ If YANK is non-nil, include the original article."
     (error "Gnus has been shut down"))
   (gnus-setup-message (if (message-mail-user-agent) 'message 'bug)
     (unless (message-mail-user-agent)
+      (message-pop-to-buffer "*Gnus Bug*")
       (delete-other-windows)
       (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*"))
+       (goto-char (point-min))
+       (sit-for 0)
+       (set-buffer "*Gnus Bug*")))
     (let ((message-this-is-mail t))
       (message-setup `((To . ,gnus-maintainer) (Subject . ""))))
     (when gnus-bug-create-help-buffer
@@ -1065,9 +1239,9 @@ The source file has to be in the Emacs load path."
        (point (point))
        file expr olist sym)
     (gnus-message 4 "Please wait while we snoop your variables...")
-    (sit-for 0)
     ;; Go through all the files looking for non-default values for variables.
     (save-excursion
+      (sit-for 0)
       (set-buffer (gnus-get-buffer-create " *gnus bug info*"))
       (while files
        (erase-buffer)
@@ -1160,68 +1334,41 @@ this is a reply."
 ;; Do Gcc handling, which copied the message over to some group.
 (defun gnus-inews-do-gcc (&optional gcc)
   (interactive)
-  (when (gnus-alive-p)
-    (save-excursion
-      (save-restriction
-       (message-narrow-to-headers)
-       (let ((gcc (or gcc (mail-fetch-field "gcc" nil t)))
-             (coding-system-for-write 'raw-text)
-             (output-coding-system 'raw-text)
-             groups group method group-art)
-         (when gcc
-           (message-remove-header "gcc")
-           (widen)
-           (setq groups (message-unquote-tokens
-                          (message-tokenize-header gcc " ,")))
-           ;; Copy the article over to some group(s).
-           (while (setq group (pop groups))
-             (gnus-check-server
-              (setq method (gnus-inews-group-method group)))
-             (unless (gnus-request-group group t method)
-               (gnus-request-create-group group method))
-             (save-excursion
-               (nnheader-set-temp-buffer " *acc*")
-               (insert-buffer-substring message-encoding-buffer)
-               (gnus-run-hooks 'gnus-before-do-gcc-hook)
-               (goto-char (point-min))
-               (when (re-search-forward
-                      (concat "^" (regexp-quote mail-header-separator) "$")
-                      nil t)
-                 (replace-match "" t t ))
-               (unless (setq group-art 
-                             (gnus-request-accept-article group method t t))
-                 (gnus-message 1 "Couldn't store article in group %s: %s"
-                               group (gnus-status-message method))
-                 (sit-for 2))
-               (when (and group-art gnus-inews-mark-gcc-as-read)
-                 (let ((active (gnus-active group)))
-                   (if active
-                       (if (< (cdr active) (cdr group-art))
-                           (gnus-set-active group (cons (car active) 
-                                                        (cdr group-art))))
-                     (gnus-activate-group group)))
-                 (let ((buffer (concat "*Summary " group "*"))
-                       (mark gnus-read-mark)
-                       (article (cdr group-art)))
-                   (unless 
-                       (and 
-                        (get-buffer buffer)
-                        (with-current-buffer buffer
-                          (when gnus-newsgroup-prepared
-                            (when (and gnus-newsgroup-auto-expire
-                                       (memq mark gnus-auto-expirable-marks))
-                              (setq mark gnus-expirable-mark))
-                            (setq mark (gnus-request-update-mark 
-                                        group article mark))
-                            (gnus-mark-article-as-read article mark)
-                            (setq gnus-newsgroup-active (gnus-active group))
-                            t)))
-                     (gnus-group-make-articles-read group 
-                                                    (list article))
-                     (when (gnus-group-auto-expirable-p group)
-                       (gnus-add-marked-articles
-                        group 'expire (list article))))))
-               (kill-buffer (current-buffer))))))))))
+  (save-excursion
+    (save-restriction
+      (message-narrow-to-headers)
+      (let ((gcc (or gcc (mail-fetch-field "gcc" nil t)))
+           (coding-system-for-write 'raw-text)
+           (output-coding-system 'raw-text)
+           groups group method group-art)
+       (when gcc
+         (message-remove-header "gcc")
+         (widen)
+         (setq groups (message-unquote-tokens
+                       (message-tokenize-header gcc " ,")))
+         ;; Copy the article over to some group(s).
+         (while (setq group (pop groups))
+           (gnus-check-server
+            (setq method (gnus-inews-group-method group)))
+           (unless (gnus-request-group group nil method)
+             (gnus-request-create-group group method))
+           (save-excursion
+             (nnheader-set-temp-buffer " *acc*")
+             (insert-buffer-substring message-encoding-buffer)
+             (gnus-run-hooks 'gnus-before-do-gcc-hook)
+             (goto-char (point-min))
+             (when (re-search-forward
+                    (concat "^" (regexp-quote mail-header-separator) "$")
+                    nil t)
+               (replace-match "" t t ))
+             (unless (setq group-art
+                           (gnus-request-accept-article group method t t))
+               (gnus-message 1 "Couldn't store article in group %s: %s"
+                             group (gnus-status-message method))
+               (sit-for 2))
+             (when (and group-art gnus-inews-mark-gcc-as-read)
+               (gnus-group-mark-article-read group (cdr group-art)))
+             (kill-buffer (current-buffer)))))))))
 
 (defun gnus-inews-insert-gcc ()
   "Insert Gcc headers based on `gnus-outgoing-message-group'."
@@ -1340,9 +1487,11 @@ this is a reply."
                ;; Regexp string match on the group name.
                (string-match match group))
               ((eq match 'header)
-               (let ((header (message-fetch-field (pop style))))
-                 (and header
-                      (string-match (pop style) header))))
+               (and (gnus-buffer-live-p gnus-article-copy)
+                    (with-current-buffer gnus-article-copy
+                      (let ((header (message-fetch-field (pop style))))
+                        (and header
+                             (string-match (pop style) header))))))
               ((or (symbolp match)
                    (gnus-functionp match))
                (cond
@@ -1433,8 +1582,8 @@ this is a reply."
       (when (or name address)
        (add-hook 'message-setup-hook
                  `(lambda ()
-                    (set (make-local-variable 'user-mail-address)
-                         ,(or (cdr address) user-mail-address))
+                    (set (make-local-variable 'user-mail-address)
+                         ,(or (cdr address) user-mail-address))
                     (let ((user-full-name ,(or (cdr name) (user-full-name)))
                           (user-mail-address
                            ,(or (cdr address) user-mail-address)))
@@ -1450,7 +1599,7 @@ this is a reply."
 (defun gnus-maybe-setup-default-charset ()
   (let ((charset
         (and (boundp 'gnus-summary-buffer)
-              (buffer-live-p gnus-summary-buffer)
+             (buffer-live-p gnus-summary-buffer)
              (save-excursion
                (set-buffer gnus-summary-buffer)
                default-mime-charset))))