Move image files to etc/gnus.
[gnus] / lisp / message.el
index abb9bdf..170e7b7 100644 (file)
@@ -303,6 +303,7 @@ The provided functions are:
 
 (defcustom message-forward-show-mml t
   "*If non-nil, forward messages are shown as mml.  Otherwise, forward messages are unchanged."
+  :version "21.1"
   :group 'message-forwarding
   :type 'boolean)
 
@@ -935,6 +936,26 @@ The first matched address (not primary one) is used in the From field."
   :type '(choice (const :tag "Always use primary" nil)
                 regexp))
 
+(defcustom message-mail-user-agent nil
+  "Like `mail-user-agent'.
+Except if it is `nil', use Gnus native MUA; if it is t, use
+`mail-user-agent'."
+  :type '(radio (const :tag "Gnus native"
+                      :format "%t\n"
+                      nil)
+               (const :tag "`mail-user-agent'"
+                      :format "%t\n"
+                      t)
+               (function-item :tag "Default Emacs mail"
+                              :format "%t\n"
+                              sendmail-user-agent)
+               (function-item :tag "Emacs interface to MH"
+                              :format "%t\n"
+                              mh-e-user-agent)
+               (function :tag "Other"))
+  :version "21.1"
+  :group 'message)
+
 ;;; Internal variables.
 
 (defvar message-sending-message "Sending...")
@@ -1263,10 +1284,8 @@ Return the number of headers removed."
      (point-max)))
   (goto-char (point-min)))
 
-(defun message-narrow-to-head ()
-  "Narrow the buffer to the head of the message.
-Point is left at the beginning of the narrowed-to region."
-  (widen)
+(defun message-narrow-to-head-1 ()
+  "Like `message-narrow-to-head'. Don't widen."
   (narrow-to-region
    (goto-char (point-min))
    (if (search-forward "\n\n" nil 1)
@@ -1274,6 +1293,12 @@ Point is left at the beginning of the narrowed-to region."
      (point-max)))
   (goto-char (point-min)))
 
+(defun message-narrow-to-head ()
+  "Narrow the buffer to the head of the message.
+Point is left at the beginning of the narrowed-to region."
+  (widen)
+  (message-narrow-to-head-1))
+
 (defun message-narrow-to-headers-or-head ()
   "Narrow the buffer to the head of the message."
   (widen)
@@ -1458,10 +1483,11 @@ Point is left at the beginning of the narrowed-to region."
    ["Body" message-goto-body t]
    ["Signature" message-goto-signature t]))
 
+(defvar message-tool-bar-map nil)
+
 (eval-when-compile
   (defvar facemenu-add-face-function)
-  (defvar facemenu-remove-face-function)
-  (defvar message-tool-bar-map))
+  (defvar facemenu-remove-face-function))
 
 ;;;###autoload
 (defun message-mode ()
@@ -1525,6 +1551,8 @@ M-RET    message-newline-and-reformat (break the line and reformat)."
   (set (make-local-variable 'message-checksum) nil)
   (set (make-local-variable 'message-mime-part) 0)
   (message-setup-fill-variables)
+  ;; Allow using comment commands to add/remove quoting.
+  (set (make-local-variable 'comment-start) message-yank-prefix)
   ;;(when (fboundp 'mail-hist-define-keys)
   ;;  (mail-hist-define-keys))
   (if (featurep 'xemacs)
@@ -1532,7 +1560,7 @@ M-RET    message-newline-and-reformat (break the line and reformat)."
     (set (make-local-variable 'font-lock-defaults)
         '(message-font-lock-keywords t))
     (if (boundp 'tool-bar-map)
-       (set (make-local-variable 'tool-bar-map) message-tool-bar-map)))
+       (set (make-local-variable 'tool-bar-map) (message-tool-bar-map))))
   (easy-menu-add message-mode-menu message-mode-map)
   (easy-menu-add message-mode-field-menu message-mode-map)
   ;; Allow mail alias things.
@@ -3655,8 +3683,42 @@ than 988 characters long, and if they are not, trim them until they are."
     (setq message-buffer-list
          (nconc message-buffer-list (list (current-buffer))))))
 
+(defun message-mail-user-agent ()
+  (let ((mua (cond
+             ((not message-mail-user-agent) nil)
+             ((eq message-mail-user-agent t) mail-user-agent)
+             (t message-mail-user-agent))))
+    (if (memq mua '(message-user-agent gnus-user-agent))
+       nil
+      mua)))
+
+(defun message-setup (headers &optional replybuffer actions switch-function)
+  (let ((mua (message-mail-user-agent))
+       subject to field yank-action)
+    (if (not (and message-this-is-mail mua))
+       (message-setup-1 headers replybuffer actions)
+      (if replybuffer
+         (setq yank-action (list 'insert-buffer replybuffer)))
+      (setq headers (copy-sequence headers))
+      (setq field (assq 'Subject headers))
+      (when field
+       (setq subject (cdr field))
+       (setq headers (delq field headers)))
+      (setq field (assq 'To headers))
+      (when field
+       (setq to (cdr field))
+       (setq headers (delq field headers)))
+      (let ((mail-user-agent mua))
+       (compose-mail to subject 
+                     (mapcar (lambda (item)
+                               (cons
+                                (format "%s" (car item))
+                                (cdr item)))
+                             headers)
+                     nil switch-function yank-action actions))))) 
+
 ;;;(defvar mc-modes-alist)
-(defun message-setup (headers &optional replybuffer actions)
+(defun message-setup-1 (headers &optional replybuffer actions)
 ;;;   (when (and (boundp 'mc-modes-alist)
 ;;;         (not (assq 'message-mode mc-modes-alist)))
 ;;;     (push '(message-mode (encrypt . mc-encrypt-message)
@@ -3770,7 +3832,8 @@ than 988 characters long, and if they are not, trim them until they are."
 OTHER-HEADERS is an alist of header/value pairs."
   (interactive)
   (let ((message-this-is-mail t))
-    (message-pop-to-buffer (message-buffer-name "mail" to))
+    (unless (message-mail-user-agent)
+      (message-pop-to-buffer (message-buffer-name "mail" to)))
     (message-setup
      (nconc
       `((To . ,(or to "")) (Subject . ,(or subject "")))
@@ -3883,7 +3946,7 @@ responses here are directed to other addresses.")))
        (message-this-is-mail t)
        gnus-warning)
     (save-restriction
-      (message-narrow-to-head)
+      (message-narrow-to-head-1)
       ;; Allow customizations to have their say.
       (if (not wide)
          ;; This is a regular reply.
@@ -3910,10 +3973,11 @@ responses here are directed to other addresses.")))
     (unless follow-to
       (setq follow-to (message-get-reply-headers wide to-address))))
 
-    (message-pop-to-buffer
-     (message-buffer-name
-      (if wide "wide reply" "reply") from
-      (if wide to-address nil)))
+    (unless (message-mail-user-agent)
+      (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 ""))
@@ -4058,7 +4122,7 @@ If ARG, allow editing of the cancellation message."
       (save-excursion
        ;; Get header info from original article.
        (save-restriction
-         (message-narrow-to-head)
+         (message-narrow-to-head-1)
          (setq from (message-fetch-field "from")
                sender (message-fetch-field "sender")
                newsgroups (message-fetch-field "newsgroups")
@@ -4120,7 +4184,7 @@ header line with the old Message-ID."
     (message-pop-to-buffer (message-buffer-name "supersede"))
     (insert-buffer-substring cur)
     (mime-to-mml)
-    (message-narrow-to-head)
+    (message-narrow-to-head-1)
     ;; Remove unwanted headers.
     (when message-ignored-supersedes-headers
       (message-remove-header message-ignored-supersedes-headers t))
@@ -4208,13 +4272,15 @@ the message."
   "Return a Subject header suitable for the message in the current buffer."
   (save-excursion
     (save-restriction
-      (current-buffer)
-      (message-narrow-to-head)
+      (message-narrow-to-head-1)
       (let ((funcs message-make-forward-subject-function)
-           (subject (if message-wash-forwarded-subjects
-                        (message-wash-subject
-                         (or (message-fetch-field "Subject") ""))
-                      (or (message-fetch-field "Subject") ""))))
+           (subject (message-fetch-field "Subject")))
+       (setq subject
+             (if subject
+                 (mail-decode-encoded-word-string subject)
+               ""))
+       (if message-wash-forwarded-subjects
+           (setq subject (message-wash-subject subject)))
        ;; Make sure funcs is a list.
        (and funcs
             (not (listp funcs))
@@ -4234,8 +4300,7 @@ Optional NEWS will use news to forward instead of mail.
 Optional DIGEST will use digest to forward."
   (interactive "P")
   (let* ((cur (current-buffer))
-        (subject (mail-decode-encoded-word-string
-                  (message-make-forward-subject)))
+        (subject (message-make-forward-subject))
         art-beg)
     (if news
        (message-news nil subject)
@@ -4258,12 +4323,31 @@ Optional DIGEST will use digest to forward."
              (insert-buffer-substring cur)
            (mml-insert-buffer cur))
        (if message-forward-show-mml
-           (save-restriction
-             (narrow-to-region (point) (point))
-             (insert-buffer-substring cur)
-             (mime-to-mml)
-             (goto-char (point-max)))
-         (mml-insert-buffer cur)))
+           (let ((target (current-buffer)) tmp)
+             (with-temp-buffer
+               (mm-disable-multibyte) ;; Must copy buffer in unibyte mode
+               (setq tmp (current-buffer))
+               (set-buffer cur)
+               (mm-with-unibyte-current-buffer
+                 (set-buffer tmp)
+                 (insert-buffer-substring cur)
+                 (set-buffer cur))
+               (set-buffer tmp)
+               (mm-enable-multibyte)
+               (mime-to-mml)
+               (goto-char (point-min))
+               (when (looking-at "From ")
+                 (replace-match "X-From-Line: "))
+               (set-buffer target)
+               (insert-buffer-substring tmp)
+               (set-buffer tmp)))
+         (save-restriction
+           (narrow-to-region (point) (point))
+           (mml-insert-buffer cur)
+           (goto-char (point-min))
+           (when (looking-at "From ")
+             (replace-match "X-From-Line: "))
+           (goto-char (point-max)))))
       (setq e (point))
       (if message-forward-as-mime
          (if digest
@@ -4299,9 +4383,11 @@ Optional DIGEST will use digest to forward."
     (let ((cur (current-buffer))
          beg)
       ;; We first set up a normal mail buffer.
-      (set-buffer (get-buffer-create " *message resend*"))
-      (erase-buffer)
-      (message-setup `((To . ,address)))
+      (unless (message-mail-user-agent)
+       (set-buffer (get-buffer-create " *message resend*"))
+       (erase-buffer))
+      (let ((message-this-is-mail t))
+       (message-setup `((To . ,address))))
       ;; Insert our usual headers.
       (message-generate-headers '(From Date To))
       (message-narrow-to-headers)
@@ -4369,7 +4455,7 @@ you."
     (mm-enable-multibyte)
     (mime-to-mml)
     (save-restriction
-      (message-narrow-to-head)
+      (message-narrow-to-head-1)
       (message-remove-header message-ignored-bounced-headers t)
       (goto-char (point-max))
       (insert mail-header-separator))
@@ -4383,27 +4469,31 @@ you."
 (defun message-mail-other-window (&optional to subject)
   "Like `message-mail' command, but display mail buffer in another window."
   (interactive)
-  (let ((pop-up-windows t)
-       (special-display-buffer-names nil)
-       (special-display-regexps nil)
-       (same-window-buffer-names nil)
-       (same-window-regexps nil))
-    (message-pop-to-buffer (message-buffer-name "mail" to)))
+  (unless (message-mail-user-agent)
+    (let ((pop-up-windows t)
+         (special-display-buffer-names nil)
+         (special-display-regexps nil)
+         (same-window-buffer-names nil)
+         (same-window-regexps nil))
+      (message-pop-to-buffer (message-buffer-name "mail" to))))
   (let ((message-this-is-mail t))
-    (message-setup `((To . ,(or to "")) (Subject . ,(or subject ""))))))
+    (message-setup `((To . ,(or to "")) (Subject . ,(or subject "")))
+                  nil nil 'switch-to-buffer-other-window)))
 
 ;;;###autoload
 (defun message-mail-other-frame (&optional to subject)
   "Like `message-mail' command, but display mail buffer in another frame."
   (interactive)
-  (let ((pop-up-frames t)
-       (special-display-buffer-names nil)
-       (special-display-regexps nil)
-       (same-window-buffer-names nil)
-       (same-window-regexps nil))
-    (message-pop-to-buffer (message-buffer-name "mail" to)))
+  (unless (message-mail-user-agent)
+    (let ((pop-up-frames t)
+         (special-display-buffer-names nil)
+         (special-display-regexps nil)
+         (same-window-buffer-names nil)
+         (same-window-regexps nil))
+      (message-pop-to-buffer (message-buffer-name "mail" to))))
   (let ((message-this-is-mail t))
-    (message-setup `((To . ,(or to "")) (Subject . ,(or subject ""))))))
+    (message-setup `((To . ,(or to "")) (Subject . ,(or subject "")))
+                  nil nil 'switch-to-buffer-other-frame)))
 
 ;;;###autoload
 (defun message-news-other-window (&optional newsgroups subject)
@@ -4470,33 +4560,36 @@ which specify the range to operate on."
 (defalias 'message-exchange-point-and-mark 'exchange-point-and-mark)
 
 ;; Support for toolbar
+(if (featurep 'xemacs)
+    (require 'messagexmas))
+
 (eval-when-compile 
   (defvar tool-bar-map)
   (defvar tool-bar-mode))
-(if (featurep 'xemacs)
-    (require 'messagexmas)
-  (when (and (>= (string-to-int emacs-version) 21)
-            ;; I hate warnings --zsh.
-            (fboundp 'tool-bar-add-item-from-menu)
-            tool-bar-mode)
-    (defvar message-tool-bar-map
-      (let ((tool-bar-map (copy-keymap tool-bar-map)))
-       ;; Zap some items which aren't so relevant and take up space.
-       (dolist (key '(print-buffer kill-buffer save-buffer write-file
-                                   dired open-file))
-         (define-key tool-bar-map (vector key) nil))
-       
-       (tool-bar-add-item-from-menu
-        'message-send-and-exit "mail_send" message-mode-map)
-       (tool-bar-add-item-from-menu
-        'message-kill-buffer "close" message-mode-map)
-       (tool-bar-add-item-from-menu
-        'message-dont-send "cancel" message-mode-map)
-       (tool-bar-add-item-from-menu
-        'mml-attach-file "attach" message-mode-map)
-       (tool-bar-add-item-from-menu
-        'ispell-message "spell" message-mode-map)
-       tool-bar-map))))
+
+(defun message-tool-bar-map ()
+  (or message-tool-bar-map
+      (setq message-tool-bar-map
+           (and (fboundp 'tool-bar-add-item-from-menu)
+                tool-bar-mode
+                (let ((tool-bar-map (copy-keymap tool-bar-map))
+                      (load-path (mm-image-load-path)))
+                  ;; Zap some items which aren't so relevant and take
+                  ;; up space.
+                  (dolist (key '(print-buffer kill-buffer save-buffer 
+                                              write-file dired open-file))
+                    (define-key tool-bar-map (vector key) nil))
+                  (tool-bar-add-item-from-menu
+                   'message-send-and-exit "mail_send" message-mode-map)
+                  (tool-bar-add-item-from-menu
+                   'message-kill-buffer "close" message-mode-map)
+                  (tool-bar-add-item-from-menu
+                   'message-dont-send "cancel" message-mode-map)
+                  (tool-bar-add-item-from-menu
+                   'mml-attach-file "attach" message-mode-map)
+                  (tool-bar-add-item-from-menu
+                   'ispell-message "spell" message-mode-map)
+                  tool-bar-map)))))
 
 ;;; Group name completion.