*** empty log message ***
[gnus] / lisp / gnus-msg.el
index 7961c3b..7d72d54 100644 (file)
@@ -1,5 +1,5 @@
 ;;; gnus-msg.el --- mail and post interface for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
+;; Copyright (C) 1995,96,97 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 
 ;;; Code:
 
-(require 'gnus-load)
+(require 'gnus)
 (require 'gnus-ems)
 (require 'message)
 (require 'gnus-art)
-(require 'gnus)
 
 ;; Added by Sudish Joseph <joseph@cis.ohio-state.edu>.
 (defvar gnus-post-method nil
@@ -48,7 +47,7 @@ posting.")
 (defvar 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
+\"nnml:archive\", you set this variable to that value.  This variable
 can also be a list of group names. 
 
 If you want to have greater control over what group to put each
@@ -81,11 +80,15 @@ of this message.  Please trim your Newsgroups header to exclude this
 group before posting in the future.
 
 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 nil
+  "Hook run after setting up a message buffer.")
+
 ;;; Internal variables.
 
 (defvar gnus-message-buffer "*Mail Gnus*")
@@ -132,6 +135,10 @@ Thank you for your help in stamping out bugs.
   "s" gnus-summary-supersede-article
   "r" gnus-summary-reply
   "R" gnus-summary-reply-with-original
+  "w" gnus-summary-wide-reply
+  "W" gnus-summary-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
@@ -153,16 +160,18 @@ Thank you for your help in stamping out bugs.
        (buffer (make-symbol "buffer"))
        (article (make-symbol "article")))
     `(let ((,winconf (current-window-configuration))
-          (,buffer (current-buffer))
+          (,buffer (buffer-name (current-buffer)))
           (,article (and gnus-article-reply (gnus-summary-article-number)))
           (message-header-setup-hook
            (copy-sequence message-header-setup-hook)))
        (add-hook 'message-header-setup-hook 'gnus-inews-insert-gcc)
        (add-hook 'message-header-setup-hook 'gnus-inews-insert-archive-gcc)
-       ,@forms
-       (gnus-inews-add-send-actions ,winconf ,buffer ,article)
-       (setq gnus-message-buffer (current-buffer))
-       (make-local-variable 'gnus-newsgroup-name)
+       (unwind-protect
+          ,@forms
+        (gnus-inews-add-send-actions ,winconf ,buffer ,article)
+        (setq gnus-message-buffer (current-buffer))
+        (make-local-variable 'gnus-newsgroup-name)
+        (run-hooks 'gnus-message-setup-hook))
        (gnus-configure-windows ,config t))))
     
 (defun gnus-inews-add-send-actions (winconf buffer article)
@@ -175,15 +184,14 @@ Thank you for your help in stamping out bugs.
   (message-add-action
    `(set-window-configuration ,winconf) 'exit 'postpone 'kill)
   (message-add-action
-   `(when (buffer-name ,buffer)
+   `(when (buffer-name (get-buffer ,buffer))
       (save-excursion
-       (set-buffer ,buffer)
+       (set-buffer (get-buffer ,buffer))
        ,(when article
           `(gnus-summary-mark-article-as-replied ,article))))
    'send))
 
 (put 'gnus-setup-message 'lisp-indent-function 1)
-(put 'gnus-setup-message 'lisp-indent-hook 1)
 (put 'gnus-setup-message 'edebug-form-spec '(form body))
 
 ;;; Post news commands of Gnus group mode and summary mode
@@ -239,8 +247,21 @@ If prefix argument YANK is non-nil, original article is yanked automatically."
   (interactive "P")
   (gnus-summary-followup (gnus-summary-work-articles n) force-news))
 
+(defun gnus-summary-followup-to-mail (&optional arg)
+  "Followup to the current mail message via news."
+  (interactive 
+   (list (and current-prefix-arg 
+             (gnus-summary-work-articles 1))))
+  (gnus-summary-followup arg t))
+
+(defun gnus-summary-followup-to-mail-with-original (&optional arg)
+  "Followup to the current mail message via news."
+  (interactive "P")
+  (gnus-summary-followup (gnus-summary-work-articles arg) t))
+
 (defun gnus-inews-yank-articles (articles)
   (let (beg article)
+    (message-goto-body)
     (while (setq article (pop articles))
       (save-window-excursion
        (set-buffer gnus-summary-buffer)
@@ -251,8 +272,8 @@ If prefix argument YANK is non-nil, original article is yanked automatically."
            (message-reply-headers gnus-current-headers))
        (message-yank-original)
        (setq beg (or beg (mark t))))
-      (when articles (insert "\n")))
-    
+      (when articles
+       (insert "\n")))
     (push-mark)
     (goto-char beg)))
 
@@ -288,6 +309,13 @@ header line with the old Message-ID."
       (push
        `((lambda ()
           (gnus-cache-possibly-remove-article ,article nil nil nil t)))
+       message-send-actions)
+      (push
+       `((lambda ()
+          (when (buffer-name (get-buffer ,gnus-summary-buffer))
+            (save-excursion
+              (set-buffer (get-buffer ,gnus-summary-buffer))
+              (gnus-summary-mark-as-read ,article gnus-canceled-mark)))))
        message-send-actions))))
 
 \f
@@ -300,29 +328,41 @@ header line with the old Message-ID."
   (setq gnus-article-copy (get-buffer-create " *gnus article copy*"))
   (buffer-disable-undo gnus-article-copy)
   (or (memq gnus-article-copy gnus-buffer-list)
-      (setq gnus-buffer-list (cons 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)
-    (when (and (get-buffer article-buffer)
-              (buffer-name (get-buffer article-buffer)))
+    (if (not (and (get-buffer article-buffer)
+                 (buffer-name (get-buffer article-buffer))))
+       (error "Can't find any article buffer")
       (save-excursion
        (set-buffer article-buffer)
        (save-restriction
+         ;; Copy over the (displayed) article buffer, delete
+         ;; hidden text and remove text properties.
          (widen)
-         (article-delete-text-of-type 'annotation)
-         (setq contents (format "%s" (buffer-string)))
+         (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)))
+         ;; Find the original headers.
          (set-buffer gnus-original-article-buffer)
          (goto-char (point-min))
          (while (looking-at message-unix-mail-delimiter)
            (forward-line 1))
          (setq beg (point))
          (setq end (or (search-forward "\n\n" nil t) (point)))
+         ;; Delete the headers from the displayed articles.
          (set-buffer gnus-article-copy)
-         (erase-buffer)
-         (insert contents)
          (delete-region (goto-char (point-min))
                         (or (search-forward "\n\n" nil t) (point)))
-         (insert-buffer-substring gnus-original-article-buffer beg end)))
+         ;; Insert the original article headers.
+         (insert-buffer-substring gnus-original-article-buffer beg end)
+         (gnus-article-decode-rfc1522)))
       gnus-article-copy)))
 
 (defun gnus-post-news (post &optional group header article-buffer yank subject
@@ -335,16 +375,19 @@ header line with the old Message-ID."
                              (t 'message))
       (let* ((group (or group gnus-newsgroup-name))
             (pgroup group)
-            to-address to-group mailing-list to-list)
+            to-address to-group mailing-list to-list 
+            newsgroup-p)
        (when group
          (setq to-address (gnus-group-find-parameter group 'to-address)
                to-group (gnus-group-find-parameter group 'to-group)
                to-list (gnus-group-find-parameter group 'to-list)
+               newsgroup-p (gnus-group-find-parameter group 'newsgroup)
                mailing-list (when gnus-mailing-list-groups
                               (string-match gnus-mailing-list-groups group))
                group (gnus-group-real-name group)))
        (if (or (and to-group
                     (gnus-news-group-p to-group))
+               newsgroup-p
                force-news
                (and (gnus-news-group-p 
                      (or pgroup gnus-newsgroup-name)
@@ -357,7 +400,7 @@ header line with the old Message-ID."
            (if post
                (message-news (or to-group group))
              (set-buffer gnus-article-copy)
-             (message-followup to-group))
+             (message-followup (if (or newsgroup-p force-news) nil to-group)))
          ;; The is mail.
          (if post
              (progn
@@ -423,14 +466,8 @@ If SILENT, don't prompt the user."
                   (cons (or gnus-last-posting-server "") 0))))
          method-alist))))
      ;; Override normal method.
-     ((and gnus-post-method
-          (or (gnus-method-option-p group-method 'post)
-              (gnus-method-option-p group-method 'post-mail)))
+     (gnus-post-method
       gnus-post-method)
-     ;; Perhaps this is a mail group?
-     ((and (not (gnus-member-of-valid 'post group))
-          (not (gnus-method-option-p group-method 'post-mail)))
-      group-method)
      ;; Use the normal select method.
      (t gnus-select-method))))
 
@@ -458,9 +495,8 @@ If SILENT, don't prompt the user."
          end)
       (when message-id
        (unless gnus-inews-sent-ids
-         (condition-case ()
-             (load  t t t)
-           (error nil)))
+         (ignore-errors
+           (load t t t)))
        (if (member message-id gnus-inews-sent-ids)
            ;; Reject this message.
            (not (gnus-yes-or-no-p 
@@ -534,13 +570,13 @@ If SILENT, don't prompt the user."
 
 ;;; Mail reply commands of Gnus summary mode
 
-(defun gnus-summary-reply (&optional yank)
-  "Reply mail to news author.
-If prefix argument YANK is non-nil, original article is yanked automatically."
+(defun gnus-summary-reply (&optional yank wide)
+  "Start composing a 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))))
-  ;; Bug fix by jbw@bigbird.bu.edu (Joe Wells)
   ;; Stripping headers should be specified with mail-yank-ignored-headers.
   (gnus-set-global-variables)
   (when yank 
@@ -549,54 +585,78 @@ If prefix argument YANK is non-nil, original article is yanked automatically."
     (gnus-setup-message (if yank 'reply-yank 'reply)
       (gnus-summary-select-article)
       (set-buffer (gnus-copy-article-buffer))
-      (message-reply nil nil (gnus-group-find-parameter
-                             gnus-newsgroup-name 'broken-reply-to))
+      (message-reply nil wide (gnus-group-find-parameter
+                              gnus-newsgroup-name 'broken-reply-to))
       (when yank
        (gnus-inews-yank-articles yank)))))
 
-(defun gnus-summary-reply-with-original (n)
-  "Reply mail to news author with original article."
+(defun gnus-summary-reply-with-original (n &optional wide)
+  "Start composing a reply mail to the current message.
+The original article will be yanked."
   (interactive "P")
   (gnus-summary-reply (gnus-summary-work-articles n)))
 
-(defun gnus-summary-mail-forward (&optional post)
-  "Forward the current message to another user."
+(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 
+automatically."
+  (interactive 
+   (list (and current-prefix-arg 
+             (gnus-summary-work-articles 1))))
+  (gnus-summary-reply yank t))
+
+(defun gnus-summary-wide-reply-with-original (n)
+  "Start composing a wide reply mail to the current message.
+The original article will be yanked."
+  (interactive "P")
+  (gnus-summary-reply-with-original n t))
+
+(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."
   (interactive "P")
   (gnus-set-global-variables)
   (gnus-setup-message 'forward
     (gnus-summary-select-article)
     (set-buffer gnus-original-article-buffer)
-    (message-forward post)))
+    (let ((message-included-forward-headers
+          (if full-headers "" message-included-forward-headers)))
+      (message-forward post))))
 
-(defun gnus-summary-resend-message (address)
+(defun gnus-summary-resend-message (address n)
   "Resend the current article to ADDRESS."
-  (interactive "sResend message to: ")
-  (gnus-summary-select-article)
-  (save-excursion
-    (set-buffer gnus-original-article-buffer)
-    (message-resend address)))
+  (interactive "sResend message(s) to: \nP")
+  (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)))))
 
-(defun gnus-summary-post-forward ()
-  "Forward the current article to a newsgroup."
-  (interactive)
-  (gnus-summary-mail-forward t))
+(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"
+  "The following article was inappropriately posted to %s.\n\n"
   "Format string to insert in nastygrams.
 The current group name will be inserted at \"%s\".")
 
 (defun gnus-summary-mail-nastygram (n)
   "Send a nastygram to the author of the current article."
   (interactive "P")
-  (if (or gnus-expert-user
-         (gnus-y-or-n-p 
-          "Really send a nastygram to the author of the current article? "))
-      (let ((group gnus-newsgroup-name))
-       (gnus-summary-reply-with-original n)
-       (set-buffer gnus-message-buffer)
-       (insert (format gnus-nastygram-message group))
-       (message-send-and-exit))))
+  (when (or gnus-expert-user
+           (gnus-y-or-n-p 
+            "Really send a nastygram to the author of the current article? "))
+    (let ((group gnus-newsgroup-name))
+      (gnus-summary-reply-with-original n)
+      (set-buffer gnus-message-buffer)
+      (message-goto-body)
+      (insert (format gnus-nastygram-message group))
+      (message-send-and-exit))))
 
 (defun gnus-summary-mail-crosspost-complaint (n)
   "Send a complaint about crossposting to the current article(s)."
@@ -623,7 +683,11 @@ The current group name will be inserted at \"%s\".")
          (set-buffer gnus-summary-buffer)
          (gnus-summary-reply-with-original 1)
          (set-buffer gnus-message-buffer)
+         (message-goto-body)
          (insert (format gnus-crosspost-complaint newsgroups group))
+         (message-goto-subject)
+         (re-search-forward " *$")
+         (replace-match " (crosspost notification)" t t)
          (when (gnus-y-or-n-p "Send this complaint? ")
            (message-send-and-exit)))))))
 
@@ -649,24 +713,17 @@ The current group name will be inserted at \"%s\".")
                    (logand (progn
                              (while (search-forward "\"" nil t)
                                (incf i))
-                             (if (zerop i) 2 i)) 2)))))
+                             (if (zerop i) 2 i))
+                           2)))))
        (skip-chars-forward ",")
        (skip-chars-forward "^,"))
       (skip-chars-backward " ")
-      (setq accumulated
-           (cons (buffer-substring beg (point))
-                 accumulated))
+      (push (buffer-substring beg (point))
+           accumulated)
       (skip-chars-forward "^,")
       (skip-chars-forward ", "))
     accumulated))
 
-(defun gnus-mail-yank-original ()
-  (interactive)
-  (save-excursion
-    (mail-yank-original nil))
-  (or mail-yank-hooks mail-citation-hook
-      (run-hooks 'news-reply-header-hook)))
-
 (defun gnus-inews-add-to-address (group)
   (let ((to-address (mail-fetch-field "to")))
     (when (and to-address
@@ -685,8 +742,8 @@ The current group name will be inserted at \"%s\".")
     (or (and group (not (gnus-group-read-only-p group)))
        (setq group (read-string "Put in group: " nil
                                 (gnus-writable-groups))))
-    (and (gnus-gethash group gnus-newsrc-hashtb)
-        (error "No such group: %s" group))
+    (when (gnus-gethash group gnus-newsrc-hashtb)
+      (error "No such group: %s" group))
 
     (save-excursion
       (save-restriction
@@ -702,15 +759,14 @@ The current group name will be inserted at \"%s\".")
 
     (gnus-inews-do-gcc)
 
-    (if (get-buffer gnus-group-buffer)
-       (progn
-         (if (gnus-buffer-exists-p (car-safe reply))
-             (progn
-               (set-buffer (car reply))
-               (and (cdr reply)
-                    (gnus-summary-mark-article-as-replied 
-                     (cdr reply)))))
-         (and winconf (set-window-configuration winconf))))))
+    (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)))))
 
 (defun gnus-article-mail (yank)
   "Send a reply to the address near point.
@@ -725,6 +781,7 @@ If YANK is non-nil, include the original article."
       (when yank
        (gnus-inews-yank-articles (list (cdr gnus-article-current)))))))
 
+(defvar nntp-server-type)
 (defun gnus-bug ()
   "Send a bug report to the Gnus maintainers."
   (interactive)
@@ -743,7 +800,10 @@ If YANK is non-nil, include the original article."
     (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
     (forward-line 1)
     (insert (gnus-version) "\n")
-    (insert (emacs-version))
+    (insert (emacs-version) "\n")
+    (when (and (boundp 'nntp-server-type)
+              (stringp nntp-server-type))
+      (insert nntp-server-type))
     (insert "\n\n\n\n\n")
     (gnus-debug)
     (goto-char (point-min))
@@ -751,15 +811,15 @@ If YANK is non-nil, include the original article."
     (message "")))
 
 (defun gnus-bug-kill-buffer ()
-  (and (get-buffer "*Gnus Help Bug*")
-       (kill-buffer "*Gnus Help Bug*")))
+  (when (get-buffer "*Gnus Help Bug*")
+    (kill-buffer "*Gnus Help Bug*")))
 
 (defun gnus-debug ()
-  "Attemps to go through the Gnus source file and report what variables have been changed.
+  "Attempts to go through the Gnus source file and report what variables have been changed.
 The source file has to be in the Emacs load path."
   (interactive)
-  (let ((files '("gnus-load.el" "gnus-sum.el" "gnus-group.el"
-                "gnus-art.el" "gnus-start.el"
+  (let ((files '("gnus.el" "gnus-sum.el" "gnus-group.el"
+                "gnus-art.el" "gnus-start.el" "gnus-async.el"
                 "gnus-msg.el" "gnus-score.el" "gnus-win.el"
                 "nnmail.el" "message.el"))
        file expr olist sym)
@@ -771,23 +831,23 @@ The source file has to be in the Emacs load path."
       (buffer-disable-undo (current-buffer))
       (while files
        (erase-buffer)
-       (when (file-exists-p (setq file (locate-library (pop files))))
+       (when (and (setq file (locate-library (pop files)))
+                  (file-exists-p file))
          (insert-file-contents file)
          (goto-char (point-min))
          (if (not (re-search-forward "^;;* *Internal variables" nil t))
              (gnus-message 4 "Malformed sources in file %s" file)
            (narrow-to-region (point-min) (point))
            (goto-char (point-min))
-           (while (setq expr (condition-case () 
-                                 (read (current-buffer)) (error nil)))
-             (condition-case ()
-                 (and (eq (car expr) 'defvar)
-                      (stringp (nth 3 expr))
-                      (or (not (boundp (nth 1 expr)))
-                          (not (equal (eval (nth 2 expr))
-                                      (symbol-value (nth 1 expr)))))
-                      (push (nth 1 expr) olist))
-               (error nil))))))
+           (while (setq expr (ignore-errors (read (current-buffer))))
+             (ignore-errors
+               (and (or (eq (car expr) 'defvar)
+                        (eq (car expr) 'defcustom))
+                    (stringp (nth 3 expr))
+                    (or (not (boundp (nth 1 expr)))
+                        (not (equal (eval (nth 2 expr))
+                                    (symbol-value (nth 1 expr)))))
+                    (push (nth 1 expr) olist)))))))
       (kill-buffer (current-buffer)))
     (when (setq olist (nreverse olist))
       (insert "------------------ Environment follows ------------------\n\n"))
@@ -808,7 +868,7 @@ The source file has to be in the Emacs load path."
       (setq olist (cdr olist)))
     (insert "\n\n")
     ;; Remove any null chars - they seem to cause trouble for some
-    ;; mailers. (Byte-compiled output from the stuff above.) 
+    ;; mailers.  (Byte-compiled output from the stuff above.)
     (goto-char (point-min))
     (while (re-search-forward "[\000\200]" nil t)
       (replace-match "" t t))))
@@ -969,7 +1029,8 @@ this is a reply."
                          name
                        (gnus-group-prefixed-name 
                         name gnus-message-archive-method)))
-             (if groups (insert " ")))
+             (when groups
+               (insert " ")))
            (insert "\n")))))))
 
 (defun gnus-summary-send-draft ()