*** empty log message ***
[gnus] / lisp / message.el
index 847e9fd..1b39948 100644 (file)
@@ -40,7 +40,6 @@
     (require 'mail-abbrevs)
   (require 'mailabbrev))
 
-;;;###autoload
 (defvar message-directory "~/Mail/"
   "*Directory from which all other mail file variables are derived.")
 
@@ -113,7 +112,7 @@ RFC822 required that From, Date, To, Subject and Message-ID be
 included.  Organization, Lines and X-Mailer are optional.")
 
 ;;;###autoload
-(defvar message-deletable-headers '(Message-ID Date)
+(defvar message-deletable-headers '(Message-ID Date Lines)
   "*Headers to be deleted if they already exist and were generated by message previously.")
 
 ;;;###autoload
@@ -152,7 +151,6 @@ should return the new buffer name.")
   "*Non-nil means that the message buffer will be killed after sending a message.")
 
 (defvar gnus-local-organization)
-;;;###autoload
 (defvar message-user-organization 
   (or (and (boundp 'gnus-local-organization)
           gnus-local-organization)
@@ -165,9 +163,8 @@ If t, use `message-user-organization-file'.")
 (defvar message-user-organization-file "/usr/lib/news/organization"
   "*Local news organization file.")
 
-;;;###autoload
-(defvar message-autosave-directory
-  (concat (file-name-as-directory message-directory) "drafts/")
+(defvar message-autosave-directory "~/"
+  ; (concat (file-name-as-directory message-directory) "drafts/")
   "*Directory where message autosaves buffers.
 If nil, message won't autosave.")
 
@@ -196,6 +193,9 @@ If nil, message won't autosave.")
 (defvar message-ignored-cited-headers "."
   "Delete these headers from the messages you yank.")
 
+(defvar message-cancel-message "I am canceling my own article."
+  "Message to be inserted in the cancel message.")
+
 ;; Useful to set in site-init.el
 ;;;###autoload
 (defvar message-send-mail-function 'message-send-mail-with-sendmail
@@ -203,8 +203,8 @@ If nil, message won't autosave.")
 The headers should be delimited by a line whose contents match the
 variable `mail-header-separator'.
 
-Legal values include `message-send-mail-with-mh' and
-`message-send-mail-with-sendmail', which is the default.")
+Legal values include `message-send-mail-with-sendmail' (the default),
+`message-send-mail-with-mh' and `message-send-mail-with-qmail'.")
 
 ;;;###autoload
 (defvar message-send-news-function 'message-send-news
@@ -238,6 +238,18 @@ using the \"poster\" value.  If it is the symbol `ask', query the user
 whether to ignore the \"poster\" value.  If it is the symbol `use',
 always use the value.")
 
+;; qmail-related stuff
+(defvar message-qmail-inject-program "/var/qmail/bin/qmail-inject"
+  "Location of the qmail-inject program.")
+
+(defvar message-qmail-inject-args nil
+  "Arguments passed to qmail-inject programs.
+This should be a list of strings, one string for each argument.
+
+For e.g., if you wish to set the envelope sender address so that bounces
+go to the right place or to deal with listserv's usage of that address, you
+might set this variable to '(\"-f\" \"you@some.where\").")
+
 (defvar gnus-post-method)
 (defvar gnus-select-method)
 ;;;###autoload
@@ -373,12 +385,19 @@ these lines.")
 The value should be an expression to test whether the problem will
 actually occur.")
 
+;;; Internal variables.
+;;; Well, not really internal.
+
 (defvar message-mode-syntax-table 
   (let ((table (copy-syntax-table text-mode-syntax-table)))
     (modify-syntax-entry ?% ". " table)
     table)
   "Syntax table used while in Message mode.")
 
+(defvar message-mode-abbrev-table text-mode-abbrev-table
+  "Abbrev table used in Message mode buffers.
+Defaults to `text-mode-abbrev-table'.")
+
 (defvar message-font-lock-keywords
   (let* ((cite-prefix "A-Za-z") (cite-suffix (concat cite-prefix "0-9_.@-")))
     (list '("^To:" . font-lock-function-name-face)
@@ -414,6 +433,9 @@ The cdr of ech entry is a function for applying the face to a region.")
 
 (defvar message-buffer-list nil)
 
+;; Byte-compiler warning
+(defvar gnus-active-hashtb)
+
 ;;; Regexp matching the delimiter of messages in UNIX mail format
 ;;; (UNIX From lines), minus the initial ^.  
 (defvar message-unix-mail-delimiter
@@ -508,6 +530,10 @@ The cdr of ech entry is a function for applying the face to a region.")
        (point)
       (goto-char p))))
 
+(defmacro message-y-or-n-p (question show &rest text)
+  "Ask QUESTION, displaying the rest of the arguments in a temp. buffer if SHOW"
+  `(message-talkative-question 'y-or-n-p ,question ,show ,@text))
+
 ;; Delete the current line (and the next N lines.);
 (defmacro message-delete-line (&optional n)
   `(delete-region (progn (beginning-of-line) (point))
@@ -516,17 +542,34 @@ The cdr of ech entry is a function for applying the face to a region.")
 (defun message-tokenize-header (header &optional separator)
   "Split HEADER into a list of header elements.
 \",\" is used as the separator."
-  (let* ((beg 0)
-        (separator (or separator ","))
-        (regexp
-         (format "[ \t]*\\([^%s]+\\)?\\([%s]+\\|\\'\\)" separator separator))
-        elems)
-    (while (and (string-match regexp header beg)
-               (< beg (length header)))
-      (when (match-beginning 1)
-       (push (match-string 1 header) elems))
-      (setq beg (match-end 0)))
-    (nreverse elems)))
+  (let ((regexp (format "[%s]+" (or separator ",")))
+       (beg 1)
+       (first t)
+       quoted elems paren)
+    (save-excursion
+      (message-set-work-buffer)
+      (insert header)
+      (goto-char (point-min))
+      (while (not (eobp))
+       (if first
+           (setq first nil)
+         (forward-char 1))
+       (cond ((and (> (point) beg)
+                   (or (eobp)
+                       (and (looking-at regexp)
+                            (not quoted)
+                            (not paren))))
+              (push (buffer-substring beg (point)) elems)
+              (setq beg (match-end 0)))
+             ((= (following-char) ?\")
+              (setq quoted (not quoted)))
+             ((and (= (following-char) ?\()
+                   (not quoted))
+              (setq paren t))
+             ((and (= (following-char) ?\))
+                   (not quoted))
+              (setq paren nil))))
+      (nreverse elems))))
 
 (defun message-fetch-field (header)
   "The same as `mail-fetch-field', only remove all newlines."
@@ -652,7 +695,7 @@ Return the number of headers removed."
        (forward-char -1)))
    (lambda ()
      (or (get-text-property (point) 'message-rank)
-        0))))
+        10000))))
 
 (defun message-sort-headers ()
   "Sort the headers of the current message according to `message-header-format-alist'."
@@ -783,7 +826,7 @@ C-c C-r  message-ceasar-buffer-body (rot13 the message body)."
   (make-local-variable 'message-postpone-actions)
   (set-syntax-table message-mode-syntax-table)
   (use-local-map message-mode-map)
-  (setq local-abbrev-table text-mode-abbrev-table)
+  (setq local-abbrev-table message-mode-abbrev-table)
   (setq major-mode 'message-mode)
   (setq mode-name "Message")
   (setq buffer-offer-save t)
@@ -803,9 +846,11 @@ C-c C-r  message-ceasar-buffer-body (rot13 the message body)."
   (make-local-variable 'paragraph-start)
   (setq paragraph-start (concat (regexp-quote mail-header-separator)
                                "$\\|[ \t]*[-_][-_][-_]+$\\|"
+                               "-- $\\|"
                                paragraph-start))
   (setq paragraph-separate (concat (regexp-quote mail-header-separator)
                                   "$\\|[ \t]*[-_][-_][-_]+$\\|"
+                                  "-- $\\|"
                                   paragraph-separate))
   (make-local-variable 'message-reply-headers)
   (setq message-reply-headers nil)
@@ -816,8 +861,8 @@ C-c C-r  message-ceasar-buffer-body (rot13 the message body)."
   (setq message-sent-message-via nil)
   (make-local-variable 'message-checksum)
   (setq message-checksum nil)
-  (when (fboundp 'mail-hist-define-keys)
-    (mail-hist-define-keys))
+  ;;(when (fboundp 'mail-hist-define-keys)
+  ;;  (mail-hist-define-keys))
   (when (string-match "XEmacs\\|Lucid" emacs-version)
     (message-setup-toolbar))
   (easy-menu-add message-mode-menu message-mode-map)
@@ -909,7 +954,9 @@ C-c C-r  message-ceasar-buffer-body (rot13 the message body)."
 (defun message-insert-to ()
   "Insert a To header that points to the author of the article being replied to."
   (interactive)
-  (when (message-position-on-field "To")
+  (when (and (message-position-on-field "To")
+            (mail-fetch-field "to")
+            (not (string-match "\\` *\\'" (mail-fetch-field "to"))))
     (insert ", "))
   (insert (or (message-fetch-reply-field "reply-to")
              (message-fetch-reply-field "from") "")))
@@ -917,7 +964,9 @@ C-c C-r  message-ceasar-buffer-body (rot13 the message body)."
 (defun message-insert-newsgroups ()
   "Insert the Newsgroups header from the article being replied to."
   (interactive)
-  (when (message-position-on-field "Newsgroups")
+  (when (and (message-position-on-field "Newsgroups")
+            (mail-fetch-field "newsgroups")
+            (not (string-match "\\` *\\'" (mail-fetch-field "newsgroups"))))
     (insert ","))
   (insert (or (message-fetch-reply-field "newsgroups") "")))
 
@@ -927,9 +976,15 @@ C-c C-r  message-ceasar-buffer-body (rot13 the message body)."
 
 (defun message-insert-signature (&optional force)
   "Insert a signature.  See documentation for the `message-signature' variable."
-  (interactive (list t))
+  (interactive (list 0))
   (let* ((signature 
          (cond ((and (null message-signature)
+                     (eq force 0))
+                (save-excursion
+                  (goto-char (point-max))
+                  (not (re-search-backward
+                        message-signature-separator nil t))))
+               ((and (null message-signature)
                      force)
                 t)
                ((message-functionp message-signature)
@@ -945,12 +1000,10 @@ C-c C-r  message-ceasar-buffer-body (rot13 the message body)."
                      (file-exists-p message-signature-file))
                 signature))))
     (when signature
-      ;; Remove blank lines at the end of the message.
       (goto-char (point-max))
-      (skip-chars-backward " \t\n")
-      (forward-line 1)
-      (delete-region (point) (point-max))
       ;; Insert the signature.
+      (unless (bolp)
+       (insert "\n"))
       (insert "\n-- \n")
       (if (eq signature t)
          (insert-file-contents message-signature-file)
@@ -1030,8 +1083,10 @@ name, rather than giving an automatic name."
             (name-default (concat "*message* " mail-trimmed-to))
             (name (if enter-string
                       (read-string "New buffer name: " name-default)
-                    name-default)))
-       (rename-buffer name t)))))
+                    name-default))
+            (default-directory
+              (file-name-as-directory message-autosave-directory)))
+         (rename-buffer name t)))))
 
 (defun message-fill-yanked-message (&optional justifyp)
   "Fill the paragraphs of a message yanked into this one.
@@ -1059,7 +1114,19 @@ However, if `message-yank-prefix' is non-nil, insert that prefix on each line."
         (if (search-forward "\n\n" nil t)
             (1- (point))
           (point)))
-       (message-remove-header message-ignored-cited-headers t)))
+       (message-remove-header message-ignored-cited-headers t)
+       (goto-char (point-max))))
+    ;; Delete blank lines at the start of the buffer.
+    (while (and (point-min)
+               (eolp))
+      (message-delete-line))
+    ;; Delete blank lines at the end of the buffer.
+    (goto-char (point-max))
+    (unless (eolp)
+      (insert "\n"))
+    (while (and (zerop (forward-line -1))
+               (looking-at "$"))
+      (message-delete-line))
     ;; Do the indentation.
     (if (null message-yank-prefix)
        (indent-rigidly start (mark t) message-indentation-spaces)
@@ -1076,6 +1143,8 @@ Puts point before the text and mark after.
 Normally indents each nonblank line ARG spaces (default 3).  However,
 if `message-yank-prefix' is non-nil, insert that prefix on each line.
 
+This function uses `message-cite-function' to do the actual citing.
+
 Just \\[universal-argument] as argument means don't indent, insert no
 prefix, and don't delete any headers."
   (interactive "P")
@@ -1085,13 +1154,14 @@ prefix, and don't delete any headers."
       (delete-windows-on message-reply-buffer t)
       (insert-buffer message-reply-buffer)
       (funcall message-cite-function)
-      (exchange-point-and-mark)
+      (message-exchange-point-and-mark)
       (unless (bolp)
        (insert ?\n))
       (unless modified
-       (setq message-checksum (message-checksum))))))
+       (setq message-checksum (cons (message-checksum) (buffer-size)))))))
 
-(defun message-cite-original ()    
+(defun message-cite-original ()
+  "Cite function in the standard Message manner."
   (let ((start (point))
        (functions 
         (when message-indent-citation-function
@@ -1236,8 +1306,8 @@ the user from the mailer."
                             "Already sent message via mail; resend? "))
                        (message-send-mail arg))))
       (message-do-fcc)
-      (when (fboundp 'mail-hist-put-headers-into-history)
-       (mail-hist-put-headers-into-history))
+      ;;(when (fboundp 'mail-hist-put-headers-into-history)
+      ;; (mail-hist-put-headers-into-history))
       (run-hooks 'message-sent-hook)
       (message "Sending...done")
       ;; If buffer has no file, mark it as unmodified and delete autosave.
@@ -1297,7 +1367,11 @@ the user from the mailer."
        (save-excursion
          (set-buffer tembuf)
          (erase-buffer)
-         (insert-buffer-substring mailbuf)
+         ;; Avoid copying text props.
+         (insert (format 
+                  "%s" (save-excursion
+                         (set-buffer mailbuf)
+                         (buffer-string))))
          ;; Remove some headers.
          (save-restriction
            (message-narrow-to-headers)
@@ -1375,6 +1449,47 @@ the user from the mailer."
       (when (bufferp errbuf)
        (kill-buffer errbuf)))))
 
+(defun message-send-mail-with-qmail ()
+  "Pass the prepared message buffer to qmail-inject.
+Refer to the documentation for the variable `message-send-mail-function'
+to find out how to use this."
+  ;; replace the header delimiter with a blank line
+  (goto-char (point-min))
+  (re-search-forward
+   (concat "^" (regexp-quote mail-header-separator) "\n"))
+  (replace-match "\n")
+  ;; send the message
+  (case
+      (apply
+       'call-process-region 1 (point-max) message-qmail-inject-program
+       nil nil nil
+       ;; qmail-inject's default behaviour is to look for addresses on the
+       ;; command line; if there're none, it scans the headers.
+       ;; yes, it does The Right Thing w.r.t. Resent-To and it's kin.
+       ;;
+       ;; in general, ALL of qmail-inject's defaults are perfect for simply
+       ;; reading a formatted (i.e., at least a To: or Resent-To header)
+       ;; message from stdin.
+       ;;
+       ;; qmail also has the advantage of not having being raped by
+       ;; various vendors, so we don't have to allow for that, either --
+       ;; compare this with message-send-mail-with-sendmail and weep 
+       ;; for sendmail's lost innocence.
+       ;;
+       ;; all this is way cool coz it lets us keep the arguments entirely
+       ;; free for -inject-arguments -- a big win for the user and for us
+       ;; since we don't have to play that double-guessing game and the user
+       ;; gets full control (no gestapo'ish -f's, for instance). --sj
+       message-qmail-inject-args)
+    ;; qmail-inject doesn't say anything on it's stdout/stderr,
+    ;; we have to look at the retval instead
+    (0 nil)
+    (1   (error "qmail-inject reported permanent failure."))
+    (111 (error "qmail-inject reported transient failure."))
+    ;; should never happen
+    (t   (error "qmail-inject reported unknown failure."))))
+
+
 (defun message-send-mail-with-mh ()
   "Send the prepared message buffer with mh."
   (let ((mh-previous-window-config nil)
@@ -1382,10 +1497,17 @@ the user from the mailer."
               (concat (file-name-as-directory message-autosave-directory)
                       "msg."))))
     (setq buffer-file-name name)
-    (mh-send-letter)
-    (condition-case ()
-       (delete-file name)
-      (error nil))))
+    ;; MH wants to generate these headers itself.
+    (let ((headers message-deletable-headers))
+      (while headers
+       (goto-char (point-min)) 
+       ;;(message "Deleting header %s" (car headers)) (sit-for 5)
+       (and (re-search-forward 
+             (concat "^" (symbol-name (car headers)) ": *") nil t)
+            (message-delete-line))
+       (pop headers)))
+    ;; Pass it on to mh.
+    (mh-send-letter)))
 
 (defun message-send-news (&optional arg)
   (let ((tembuf (generate-new-buffer " *message temp*"))
@@ -1394,6 +1516,11 @@ the user from the mailer."
                    (funcall message-post-method arg)
                  message-post-method))
        (messbuf (current-buffer))
+       (message-syntax-checks
+        (if arg
+            (cons '(existing-newsgroups . disabled)
+                  message-syntax-checks)
+          message-syntax-checks))
        result)
     (save-restriction
       (message-narrow-to-headers)
@@ -1401,13 +1528,18 @@ the user from the mailer."
       (message-generate-headers message-required-news-headers)
       ;; Let the user do all of the above.
       (run-hooks 'message-header-hook))
+    (message-cleanup-headers)
     (when (message-check-news-syntax)
       (unwind-protect
          (save-excursion
            (set-buffer tembuf)
            (buffer-disable-undo (current-buffer))
            (erase-buffer) 
-           (insert-buffer-substring messbuf)
+           ;; Avoid copying text props.
+         (insert (format 
+                  "%s" (save-excursion
+                         (set-buffer messbuf)
+                         (buffer-string))))
            ;; Remove some headers.
            (save-restriction
              (message-narrow-to-headers)
@@ -1506,8 +1638,9 @@ the user from the mailer."
        ;; Check "Shoot me".
        (or (message-check-element 'shoot)
            (save-excursion
-             (if (search-forward
-                  ".i-have-a-misconfigured-system-so-shoot-me" nil t)
+             (if (re-search-forward
+                  "Message-ID.*.i-have-a-misconfigured-system-so-shoot-me"
+                  nil t)
                  (y-or-n-p
                   "You appear to have a misconfigured system.  Really post? ")
                t)))
@@ -1582,7 +1715,7 @@ the user from the mailer."
               (if (or
                    (not 
                     (string-match
-                     "\\`\\([-+_&.a-zA-Z0-9]+\\)?\\(,[-.a-zA-Z0-9]+\\)*\\'"
+                     "\\`\\([-+_&.a-zA-Z0-9]+\\)?\\(,[-+_&.a-zA-Z0-9]+\\)*\\'"
                      header))
                    (memq 
                     nil (mapcar 
@@ -1599,7 +1732,6 @@ the user from the mailer."
                      (car headers) header)))))
        ;; Check the From header.
        (or 
-        (message-check-element 'from)
         (save-excursion
           (let* ((case-fold-search t)
                  (from (message-fetch-field "from")))
@@ -1644,8 +1776,8 @@ the user from the mailer."
          (concat "^" (regexp-quote mail-header-separator) "$"))
         (forward-line 1)
         (let ((b (point)))
-          (or (re-search-forward message-signature-separator nil t)
-              (goto-char (point-max)))
+          (goto-char (point-max))
+          (re-search-backward message-signature-separator nil t)
           (beginning-of-line)
           (or (re-search-backward "[^ \n\t]" b t)
               (y-or-n-p "Empty article.  Really post? ")))))
@@ -1666,7 +1798,8 @@ the user from the mailer."
    ;; Check whether any new text has been added.
    (or (message-check-element 'new-text)
        (not message-checksum)
-       (not (eq (message-checksum) message-checksum))
+       (not (and (eq (message-checksum) (car message-checksum))
+                (eq (buffer-size) (cdr message-checksum))))
        (y-or-n-p
        "It looks like no new text has been added.  Really post? "))
    ;; Check the length of the signature.
@@ -1674,14 +1807,14 @@ the user from the mailer."
     (message-check-element 'signature)
     (progn
       (goto-char (point-max))
-      (if (or (not (re-search-backward "^-- $" nil t))
+      (if (or (not (re-search-backward message-signature-separator nil t))
              (search-forward message-forward-end-separator nil t))
          t
        (if (> (count-lines (point) (point-max)) 5)
            (y-or-n-p
             (format
              "Your .sig is %d lines; it should be max 4.  Really post? "
-             (count-lines (point) (point-max))))
+             (1- (count-lines (point) (point-max)))))
          t))))))
 
 (defun message-check-element (type)
@@ -1700,7 +1833,8 @@ the user from the mailer."
       (re-search-forward
        (concat "^" (regexp-quote mail-header-separator) "$"))
       (while (not (eobp))
-       (setq sum (logxor sum (following-char)))
+       (when (not (looking-at "[ \t\n]"))
+         (setq sum (logxor (ash sum 1) (following-char))))
        (forward-char 1)))
     sum))
 
@@ -1728,7 +1862,8 @@ the user from the mailer."
        (if (string-match "^[ \t]*|[ \t]*\\(.*\\)[ \t]*$" file)
            ;; Pipe the article to the program in question.
            (call-process-region (point-min) (point-max) shell-file-name
-                                nil nil nil "-c" (match-string 1 file))
+                                nil nil nil shell-command-switch
+                                (match-string 1 file))
          ;; Save the article.
          (setq file (expand-file-name file))
          (unless (file-exists-p (file-name-directory file))
@@ -2237,7 +2372,7 @@ Headers already prepared in the buffer are not modified."
                         (or (car (mail-extract-address-components to))
                             to) "")
               "")
-            (if group (concat " on " group) "")
+            (if (and group (not (string= group ""))) (concat " on " group) "")
             "*")))
    ;; Use standard name.
    (t
@@ -2263,8 +2398,8 @@ Headers already prepared in the buffer are not modified."
   ;; We might have sent this buffer already.  Delete it from the
   ;; list of buffers.
   (setq message-buffer-list (delq (current-buffer) message-buffer-list))
-  (when (and message-max-buffers
-            (>= (length message-buffer-list) message-max-buffers))
+  (while (and message-max-buffers
+             (>= (length message-buffer-list) message-max-buffers))
     ;; Kill the oldest buffer -- unless it has been changed.
     (let ((buffer (pop message-buffer-list)))
       (when (and (buffer-name buffer)
@@ -2302,7 +2437,7 @@ Headers already prepared in the buffer are not modified."
        (pop h))
      alist)
    headers)
-  (forward-line -1)
+  (delete-region (point) (progn (forward-line -1) (point)))
   (when message-default-headers
     (insert message-default-headers))
   (put-text-property
@@ -2385,13 +2520,10 @@ Headers already prepared in the buffer are not modified."
   (let ((cur (current-buffer))
        from subject date reply-to to cc
        references message-id follow-to 
+       (inhibit-point-motion-hooks t)
        mct never-mct gnus-warning)
     (save-restriction
-      (narrow-to-region
-       (goto-char (point-min))
-       (if (search-forward "\n\n" nil t)
-          (1- (point))
-        (point-max)))
+      (message-narrow-to-head)
       ;; Allow customizations to have their say.
       (if (not wide)
          ;; This is a regular reply.
@@ -2439,10 +2571,9 @@ Headers already prepared in the buffer are not modified."
              (message-set-work-buffer)
              (unless never-mct
                (insert (or reply-to from "")))
-             (insert 
-              (if (bolp) "" ", ") (or to "")
-              (if mct (concat (if (bolp) "" ", ") mct) "")
-              (if cc (concat (if (bolp) "" ", ") cc) ""))
+             (insert (if (bolp) "" ", ") (or to ""))
+             (insert (if mct (concat (if (bolp) "" ", ") mct) ""))
+             (insert (if cc (concat (if (bolp) "" ", ") cc) ""))
              ;; Remove addresses that match `rmail-dont-reply-to-names'. 
              (insert (prog1 (rmail-dont-reply-to (buffer-string))
                        (erase-buffer)))
@@ -2451,7 +2582,7 @@ Headers already prepared in the buffer are not modified."
                    (mapcar
                     (lambda (addr)
                       (cons (mail-strip-quoted-names addr) addr))
-                    (nreverse (mail-parse-comma-list))))
+                    (message-tokenize-header (buffer-string))))
              (let ((s ccalist))
                (while s
                  (setq ccalist (delq (assoc (car (pop s)) s) ccalist)))))
@@ -2462,7 +2593,9 @@ Headers already prepared in the buffer are not modified."
                    follow-to)))))
       (widen))
 
-    (message-pop-to-buffer (message-buffer-name "reply" from))
+    (message-pop-to-buffer (message-buffer-name
+                           (if wide "wide reply" "reply") from
+                           (if wide to-address nil)))
 
     (setq message-reply-headers
          (vector 0 subject from date message-id references 0 0 ""))
@@ -2487,6 +2620,7 @@ Headers already prepared in the buffer are not modified."
   (let ((cur (current-buffer))
        from subject date reply-to mct
        references message-id follow-to 
+       (inhibit-point-motion-hooks t)
        followup-to distribution newsgroups gnus-warning)
     (save-restriction
       (narrow-to-region
@@ -2612,7 +2746,7 @@ responses here are directed to other newsgroups."))
                    (concat "Distribution: " distribution "\n")
                  "")
                mail-header-separator "\n"
-               "This is a cancel message from " from ".\n")
+               message-cancel-message)
        (message "Canceling your article...")
        (let ((message-syntax-checks 'dont-check-for-anything-just-trust-me))
          (funcall message-send-news-function))
@@ -2680,7 +2814,8 @@ header line with the old Message-ID."
 Optional NEWS will use news to forward instead of mail."
   (interactive "P")
   (let ((cur (current-buffer))
-       (subject (message-make-forward-subject)))
+       (subject (message-make-forward-subject))
+       art-beg)
     (if news (message-news nil subject) (message-mail nil subject))
     ;; Put point where we want it before inserting the forwarded
     ;; message. 
@@ -2694,13 +2829,13 @@ Optional NEWS will use news to forward instead of mail."
     (narrow-to-region (point) (point))
     ;; Insert the separators and the forwarded buffer.
     (insert message-forward-start-separator)
+    (setq art-beg (point))
     (insert-buffer-substring cur)
     (goto-char (point-max))
     (insert message-forward-end-separator)
     (set-text-properties (point-min) (point-max) nil)
     ;; Remove all unwanted headers.
-    (goto-char (point-min))
-    (forward-line 1)
+    (goto-char art-beg)
     (narrow-to-region (point) (if (search-forward "\n\n" nil t)
                                  (1- (point))
                                (point)))
@@ -2782,7 +2917,7 @@ you."
     ;; We remove everything before the bounced mail.
     (delete-region 
      (point-min)
-     (if (re-search-forward "[^ \t]*:" nil t)
+     (if (re-search-forward "^[^ \n\t]+:" nil t)
         (match-beginning 0)
        (point)))
     (save-restriction
@@ -2880,6 +3015,8 @@ which specify the range to operate on."
        (if (eq (following-char) (char-after (- (point) 2)))
           (delete-char -2))))))
 
+(defalias 'message-exchange-point-and-mark 'exchange-point-and-mark)
+
 ;; Support for toolbar
 (when (string-match "XEmacs\\|Lucid" emacs-version)
   (require 'messagexmas))
@@ -2934,10 +3071,6 @@ Do a `tab-to-tab-stop' if not in those headers."
 
 ;;; Help stuff.
 
-(defmacro message-y-or-n-p (question show &rest text)
-  "Ask QUESTION, displaying the rest of the arguments in a temporary buffer."
-  `(message-talkative-question 'y-or-n-p ,question ,show ,@text))
-
 (defun message-talkative-question (ask question show &rest text)
   "Call FUNCTION with argument QUESTION, displaying the rest of the arguments in a temporary buffer if SHOW.  
 The following arguments may contain lists of values."