Synch to No Gnus 200601241028.
[elisp/gnus.git-] / lisp / mml.el
index cc16def..13df698 100644 (file)
@@ -1,6 +1,7 @@
 ;;; mml.el --- A package for parsing and validating MML documents
-;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-;;        Free Software Foundation, Inc.
+
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; This file is part of GNU Emacs.
   (autoload 'gnus-make-local-hook "gnus-util")
   (autoload 'message-fetch-field "message")
   (autoload 'message-mark-active-p "message")
+  (autoload 'message-info "message")
   (autoload 'fill-flowed-encode "flow-fill")
   (autoload 'message-posting-charset "message"))
 
 (eval-when-compile
   (autoload 'dnd-get-local-file-name "dnd"))
 
+(defvar gnus-article-mime-handles)
+(defvar gnus-mouse-2)
+(defvar gnus-newsrc-hashtb)
+(defvar message-default-charset)
+(defvar message-deletable-headers)
+(defvar message-options)
+(defvar message-posting-charset)
+(defvar message-required-mail-headers)
+(defvar message-required-news-headers)
+
 (defcustom mml-content-type-parameters
   '(name access-type expiration size permission format)
   "*A list of acceptable parameters in MML tag.
@@ -413,8 +425,10 @@ If MML is non-nil, return the buffer up till the correspondent mml tag."
        (let* ((raw (cdr (assq 'raw cont)))
               (filename (cdr (assq 'filename cont)))
               (type (or (cdr (assq 'type cont))
-                        (and filename (mm-default-file-encoding filename))
-                        "application/octet-stream"))
+                        (if filename
+                            (or (mm-default-file-encoding filename)
+                                "application/octet-stream")
+                          "text/plain")))
               (charset (cdr (assq 'charset cont)))
               (coding (mm-charset-to-coding-system charset))
               encoding flowed coded)
@@ -544,8 +558,10 @@ If MML is non-nil, return the buffer up till the correspondent mml tag."
          (insert "\n\n")
          (insert "Content-Type: "
                  (or (cdr (assq 'type cont))
-                     (and name (mm-default-file-encoding name))
-                     "application/octet-stream")
+                     (if name
+                         (or (mm-default-file-encoding name)
+                             "application/octet-stream")
+                       "text/plain"))
                  "\n")
          (insert "Content-ID: " (message-make-message-id) "\n")
          (insert "Content-Transfer-Encoding: "
@@ -855,6 +871,11 @@ If HANDLES is non-nil, use it instead reparsing the buffer."
        (encryptpart (make-sparse-keymap))
        (map (make-sparse-keymap))
        (main (make-sparse-keymap)))
+    (define-key map "\C-s" 'mml-secure-message-sign)
+    (define-key map "\C-c" 'mml-secure-message-encrypt)
+    (define-key map "\C-e" 'mml-secure-message-sign-encrypt)
+    (define-key map "\C-p\C-s" 'mml-secure-sign)
+    (define-key map "\C-p\C-c" 'mml-secure-encrypt)
     (define-key sign "p" 'mml-secure-message-sign-pgpmime)
     (define-key sign "o" 'mml-secure-message-sign-pgp)
     (define-key sign "s" 'mml-secure-message-sign-smime)
@@ -892,31 +913,63 @@ If HANDLES is non-nil, use it instead reparsing the buffer."
     ["Attach File..." mml-attach-file
      ,@(if (featurep 'xemacs) '(t)
         '(:help "Attach a file at point"))]
-    ["Attach Buffer..." mml-attach-buffer t]
-    ["Attach External..." mml-attach-external t]
-    ["Insert Part..." mml-insert-part t]
-    ["Insert Multipart..." mml-insert-multipart t]
-    ["PGP/MIME Sign" mml-secure-message-sign-pgpmime t]
-    ["PGP/MIME Encrypt" mml-secure-message-encrypt-pgpmime t]
-    ["PGP Sign" mml-secure-message-sign-pgp t]
-    ["PGP Encrypt" mml-secure-message-encrypt-pgp t]
-    ["S/MIME Sign" mml-secure-message-sign-smime t]
-    ["S/MIME Encrypt" mml-secure-message-encrypt-smime t]
-    ("Secure MIME part"
-     ["PGP/MIME Sign Part" mml-secure-sign-pgpmime t]
-     ["PGP/MIME Encrypt Part" mml-secure-encrypt-pgpmime t]
-     ["PGP Sign Part" mml-secure-sign-pgp t]
-     ["PGP Encrypt Part" mml-secure-encrypt-pgp t]
-     ["S/MIME Sign Part" mml-secure-sign-smime t]
-     ["S/MIME Encrypt Part" mml-secure-encrypt-smime t])
-    ["Encrypt/Sign off" mml-unsecure-message t]
+    ["Attach Buffer..." mml-attach-buffer
+     ,@(if (featurep 'xemacs) '(t)
+        '(:help "Attach a buffer to the outgoing MIME message"))]
+    ["Attach External..." mml-attach-external
+     ,@(if (featurep 'xemacs) '(t)
+        '(:help "Attach reference to file"))]
+    ;;
+    ("Change Security Method"
+     ["PGP/MIME"
+      (lambda () (interactive) (setq mml-secure-method "pgpmime"))
+      ,@(if (featurep 'xemacs) nil
+         '(:help "Set Security Method to PGP/MIME"))
+      :style radio
+      :selected (equal mml-secure-method "pgpmime") ]
+     ["S/MIME"
+      (lambda () (interactive) (setq mml-secure-method "smime"))
+      ,@(if (featurep 'xemacs) nil
+         '(:help "Set Security Method to S/MIME"))
+      :style radio
+      :selected (equal mml-secure-method "smime") ]
+     ["Inline PGP"
+      (lambda () (interactive) (setq mml-secure-method "pgp"))
+      ,@(if (featurep 'xemacs) nil
+         '(:help "Set Security Method to inline PGP"))
+      :style radio
+      :selected (equal mml-secure-method "pgp") ] )
+    ;;
+    ["Sign Message" mml-secure-message-sign t]
+    ["Encrypt Message" mml-secure-message-encrypt t]
+    ["Sign and Encrypt Message" mml-secure-message-sign-encrypt t]
+    ["Encrypt/Sign off" mml-unsecure-message
+     ,@(if (featurep 'xemacs) '(t)
+        '(:help "Don't Encrypt/Sign Message"))]
+    ;; Maybe we could remove these, because people who write MML most probably
+    ;; don't use the menu:
+    ["Insert Part..." mml-insert-part
+     :active (message-in-body-p)]
+    ["Insert Multipart..." mml-insert-multipart
+     :active (message-in-body-p)]
+    ;;
+    ;; Do we have separate encrypt and encrypt/sign commands for parts?
+    ["Sign Part" mml-secure-sign t]
+    ["Encrypt Part" mml-secure-encrypt t]
     ;;["Narrow" mml-narrow-to-part t]
-    ["Quote MML" mml-quote-region
+    ["Quote MML in region" mml-quote-region
      :active (message-mark-active-p)
      ,@(if (featurep 'xemacs) nil
         '(:help "Quote MML tags in region"))]
     ["Validate MML" mml-validate t]
-    ["Preview" mml-preview t]))
+    ["Preview" mml-preview t]
+    "----"
+    ["Emacs MIME manual" (lambda () (interactive) (message-info 4))
+     ,@(if (featurep 'xemacs) '(t)
+        '(:help "Display the Emacs MIME manual"))]
+    ["PGG manual" (lambda () (interactive) (message-info 16))
+     ,@(if (featurep 'xemacs) '(t)
+        '(:help "Display the PGG manual"))]))
 
 (defvar mml-mode nil
   "Minor mode for editing MML.")
@@ -935,9 +988,8 @@ See Info node `(emacs-mime)Composing'.
     (easy-menu-add mml-menu mml-mode-map)
     (when (boundp 'dnd-protocol-alist)
       (set (make-local-variable 'dnd-protocol-alist)
-          '(("^file:///" . mml-dnd-attach-file)
-            ("^file://"  . dnd-open-file)
-            ("^file:"    . mml-dnd-attach-file))))
+          (append mml-dnd-protocol-alist
+                  (symbol-value 'dnd-protocol-alist))))
     (run-hooks 'mml-mode-hook)))
 
 ;;;
@@ -1035,33 +1087,83 @@ See Info node `(emacs-mime)Composing'.
 
 ;;; Attachment functions.
 
+(defcustom mml-dnd-protocol-alist
+  '(("^file:///" . mml-dnd-attach-file)
+    ("^file://"  . dnd-open-file)
+    ("^file:"    . mml-dnd-attach-file))
+  "The functions to call when a drop in `mml-mode' is made.
+See `dnd-protocol-alist' for more information.  When nil, behave
+as in other buffers."
+  :type '(choice (repeat (cons (regexp) (function)))
+                (const :tag "Behave as in other buffers" nil))
+  :version "23.0" ;; No Gnus
+  :group 'message)
+
+(defcustom mml-dnd-attach-options nil
+  "Which options should be queried when attaching a file via drag and drop.
+
+If it is a list, valid members are `type', `description' and
+`disposition'.  `disposition' implies `type'.  If it is nil,
+don't ask for options.  If it is t, ask the user whether or not
+to specify options."
+  :type '(choice
+         (const :tag "Non" nil)
+         (const :tag "Query" t)
+         (list :value (type description disposition)
+          (set :inline t
+               (const type)
+               (const description)
+               (const disposition))))
+  :version "23.0" ;; No Gnus
+  :group 'message)
+
 (defun mml-attach-file (file &optional type description disposition)
   "Attach a file to the outgoing MIME message.
 The file is not inserted or encoded until you send the message with
 `\\[message-send-and-exit]' or `\\[message-send]'.
 
-FILE is the name of the file to attach.  TYPE is its content-type, a
-string of the form \"type/subtype\".  DESCRIPTION is a one-line
-description of the attachment."
+FILE is the name of the file to attach.  TYPE is its
+content-type, a string of the form \"type/subtype\".  DESCRIPTION
+is a one-line description of the attachment.  The DISPOSITION
+specifies how the attachment is intended to be displayed.  It can
+be either \"inline\" (displayed automatically within the message
+body) or \"attachment\" (separate from the body)."
   (interactive
    (let* ((file (mml-minibuffer-read-file "Attach file: "))
          (type (mml-minibuffer-read-type file))
          (description (mml-minibuffer-read-description))
          (disposition (mml-minibuffer-read-disposition type)))
      (list file type description disposition)))
-  (mml-insert-empty-tag 'part
-                       'type type
-                       'filename file
-                       'disposition (or disposition "attachment")
-                       'description description))
+  (save-excursion
+    (unless (message-in-body-p) (goto-char (point-max)))
+    (mml-insert-empty-tag 'part
+                         'type type
+                         'filename file
+                         'disposition (or disposition "attachment")
+                         'description description)))
 
 (defun mml-dnd-attach-file (uri action)
-  "Attach a drag and drop file."
+  "Attach a drag and drop file.
+
+Ask for type, description or disposition according to
+`mml-dnd-attach-options'."
   (let ((file (dnd-get-local-file-name uri t)))
     (when (and file (file-regular-p file))
-      (let* ((type (mml-minibuffer-read-type file))
-           (description (mml-minibuffer-read-description))
-           (disposition (mml-minibuffer-read-disposition type)))
+      (let ((mml-dnd-attach-options mml-dnd-attach-options)
+           type description disposition)
+       (setq mml-dnd-attach-options
+             (when (and (eq mml-dnd-attach-options t)
+                        (not
+                         (y-or-n-p
+                          "Use default type, disposition and description? ")))
+               '(type description disposition)))
+       (when (or (memq 'type mml-dnd-attach-options)
+                 (memq 'disposition mml-dnd-attach-options))
+         (setq type (mml-minibuffer-read-type file)))
+       (when (memq 'description mml-dnd-attach-options)
+         (setq description (mml-minibuffer-read-description)))
+       (when (memq 'disposition mml-dnd-attach-options)
+         (setq disposition (mml-minibuffer-read-disposition type)))
        (mml-attach-file file type description disposition)))))
 
 (defun mml-attach-buffer (buffer &optional type description)
@@ -1072,8 +1174,11 @@ See `mml-attach-file' for details of operation."
          (type (mml-minibuffer-read-type buffer "text/plain"))
          (description (mml-minibuffer-read-description)))
      (list buffer type description)))
-  (mml-insert-empty-tag 'part 'type type 'buffer buffer
-                       'disposition "attachment" 'description description))
+  (save-excursion
+    (unless (message-in-body-p) (goto-char (point-max)))
+    (mml-insert-empty-tag 'part 'type type 'buffer buffer
+                         'disposition "attachment"
+                         'description description)))
 
 (defun mml-attach-external (file &optional type description)
   "Attach an external file into the buffer.
@@ -1084,8 +1189,10 @@ TYPE is the MIME type to use."
          (type (mml-minibuffer-read-type file))
          (description (mml-minibuffer-read-description)))
      (list file type description)))
-  (mml-insert-empty-tag 'external 'type type 'name file
-                       'disposition "attachment" 'description description))
+  (save-excursion
+    (unless (message-in-body-p) (goto-char (point-max)))
+    (mml-insert-empty-tag 'external 'type type 'name file
+                         'disposition "attachment" 'description description)))
 
 (defun mml-insert-multipart (&optional type)
   (interactive (list (completing-read "Multipart type (default mixed): "
@@ -1117,7 +1224,12 @@ Should be adopted if code in `message-send-mail' is changed."
 
 (defun mml-preview (&optional raw)
   "Display current buffer with Gnus, in a new buffer.
-If RAW, don't highlight the article."
+If RAW, display a raw encoded MIME message.
+
+The window layout for the preview buffer is controled by the variables
+`special-display-buffer-names', `special-display-regexps', or
+`gnus-buffer-configuration' (the first match made will be used),
+or the `pop-to-buffer' function."
   (interactive "P")
   (setq mml-preview-buffer (generate-new-buffer
                            (concat (if raw "*Raw MIME preview of "
@@ -1186,7 +1298,8 @@ If RAW, don't highlight the article."
                       (interactive "@e")
                       (widget-button-press (widget-event-point event) event)))
       (goto-char (point-min))))
-  (if (and (boundp 'gnus-buffer-configuration)
+  (if (and (not (mm-special-display-p (buffer-name mml-preview-buffer)))
+          (boundp 'gnus-buffer-configuration)
           (assq 'mml-preview gnus-buffer-configuration))
       (let ((gnus-message-buffer (current-buffer)))
        (gnus-configure-windows 'mml-preview))