Sync with `t-gnus-6_14'.
[elisp/gnus.git-] / lisp / mm-decode.el
index 07ca6b6..85f3a5a 100644 (file)
 (require 'mail-parse)
 (require 'gnus-mailcap)
 (require 'mm-bodies)
+(eval-when-compile (require 'cl))
 
 (eval-and-compile
   (autoload 'mm-inline-partial "mm-partial"))
 
-(defvar mm-xemacs-p (string-match "XEmacs" (emacs-version)))
-
 (defgroup mime-display ()
   "Display of MIME in mail and news articles."
   :link '(custom-manual "(emacs-mime)Customization")
   :group 'mail
-  :group 'news)
+  :group 'news
+  :group 'multimedia)
 
 ;;; Convenience macros.
 
 Viewing agents are supposed to view the last possible part of a message,
 as that is supposed to be the richest.  However, users may prefer other
 types instead, and this list says what types are most unwanted.  If,
-for instance, text/html parts are very unwanted, and text/richtech are
+for instance, text/html parts are very unwanted, and text/richtext are
 somewhat unwanted, then the value of this variable should be set
 to:
 
@@ -211,6 +211,11 @@ to:
 (defvar mm-last-shell-command "")
 (defvar mm-content-id-alist nil)
 
+;; According to RFC2046, in particular, in a digest, the default
+;; Content-Type value for a body part is changed from "text/plain" to
+;; "message/rfc822".
+(defvar mm-dissect-default-type "text/plain")
+
 ;;; The functions.
 
 (defun mm-dissect-buffer (&optional no-strict-mime)
@@ -232,7 +237,7 @@ to:
       (if (or (not ctl)
              (not (string-match "/" (car ctl))))
          (mm-dissect-singlepart
-          '("text/plain") 
+          (list mm-dissect-default-type)
           (and cte (intern (downcase (mail-header-remove-whitespace
                                       (mail-header-remove-comments
                                        cte)))))
@@ -246,7 +251,10 @@ to:
         result
         (cond
          ((equal type "multipart")
-          (cons (car ctl) (mm-dissect-multipart ctl)))
+          (let ((mm-dissect-default-type (if (equal subtype "digest")
+                                             "message/rfc822"
+                                           "text/plain")))
+            (cons (car ctl) (mm-dissect-multipart ctl))))
          (t
           (mm-dissect-singlepart
            ctl
@@ -288,7 +296,8 @@ to:
                (if (re-search-backward close-delimiter nil t)
                    (match-beginning 0)
                  (point-max)))))
-    (while (search-forward boundary end t)
+    (setq boundary (concat (regexp-quote boundary) "[ \t]*$"))
+    (while (re-search-forward boundary end t)
       (goto-char (match-beginning 0))
       (when start
        (save-excursion
@@ -360,6 +369,7 @@ external if displayed external."
            (buffer-disable-undo)
            (mm-set-buffer-file-coding-system mm-binary-coding-system)
            (insert-buffer-substring cur)
+           (goto-char (point-min))
            (message "Viewing with %s" method)
            (let ((mm (current-buffer))
                  (non-viewer (assq 'non-viewer
@@ -397,7 +407,7 @@ external if displayed external."
                 (unwind-protect
                     (start-process "*display*" nil
                                    "xterm"
-                                   "-e" shell-file-name 
+                                   "-e" shell-file-name
                                    shell-command-switch
                                    (mm-mailcap-command
                                     method file (mm-handle-type handle)))
@@ -412,7 +422,7 @@ external if displayed external."
                    (unwind-protect
                        (progn
                          (call-process shell-file-name nil
-                                       (setq buffer 
+                                       (setq buffer
                                              (generate-new-buffer "*mm*"))
                                        nil
                                        shell-command-switch
@@ -469,7 +479,7 @@ external if displayed external."
     (mapconcat 'identity (nreverse out) "")))
     
 (defun mm-remove-parts (handles)
-  "Remove the displayed MIME parts represented by HANDLE."
+  "Remove the displayed MIME parts represented by HANDLES."
   (if (and (listp handles)
           (bufferp (car handles)))
       (mm-remove-part handles)
@@ -486,7 +496,7 @@ external if displayed external."
          (mm-remove-part handle)))))))
 
 (defun mm-destroy-parts (handles)
-  "Remove the displayed MIME parts represented by HANDLE."
+  "Remove the displayed MIME parts represented by HANDLES."
   (if (and (listp handles)
           (bufferp (car handles)))
       (mm-destroy-part handles)
@@ -633,7 +643,7 @@ external if displayed external."
     (save-excursion
       (if (member (mm-handle-media-supertype handle) '("text" "message"))
          (with-temp-buffer
-           (insert-buffer-substring (mm-handle-buffer handle))
+           (insert-buffer-substring (mm-handle-buffer handle))
            (mm-decode-content-transfer-encoding
             (mm-handle-encoding handle)
             (mm-handle-media-type handle))
@@ -700,6 +710,8 @@ external if displayed external."
         (method (completing-read "Viewer: " methods)))
     (when (string= method "")
       (error "No method given"))
+    (if (string-match "^[^% \t]+$" method) 
+       (setq method (concat method " %s")))
     (mm-display-external (copy-sequence handle) method)))
 
 (defun mm-preferred-alternative (handles &optional preferred)
@@ -725,9 +737,8 @@ external if displayed external."
     result))
 
 (defun mm-preferred-alternative-precedence (handles)
-  "Return the precedence based on HANDLES and mm-discouraged-alternatives."
-  (let ((seq (nreverse (mapcar (lambda (h)
-                                (mm-handle-media-type h))
+  "Return the precedence based on HANDLES and `mm-discouraged-alternatives'."
+  (let ((seq (nreverse (mapcar #'mm-handle-media-type
                               handles))))
     (dolist (disc (reverse mm-discouraged-alternatives))
       (dolist (elem (copy-sequence seq))
@@ -739,37 +750,7 @@ external if displayed external."
   "Return the handle(s) referred to by ID."
   (cdr (assoc id mm-content-id-alist)))
 
-(defun mm-get-image-emacs (handle)
-  "Return an image instance based on HANDLE."
-  (let ((type (mm-handle-media-subtype handle))
-       spec)
-    ;; Allow some common translations.
-    (setq type
-         (cond
-          ((equal type "x-pixmap")
-           "xpm")
-          ((equal type "x-xbitmap")
-           "xbm")
-          (t type)))
-    (or (mm-handle-cache handle)
-       (mm-with-unibyte-buffer
-         (mm-insert-part handle)
-         (prog1
-             (setq spec
-                   (ignore-errors
-                     (cond
-                      ((equal type "xbm")
-                       ;; xbm images require special handling, since
-                       ;; the only way to create glyphs from these
-                       ;; (without a ton of work) is to write them
-                       ;; out to a file, and then create a file
-                       ;; specifier.
-                       (error "Don't know what to do for XBMs right now."))
-                      (t
-                       (list 'image :type (intern type) :data (buffer-string))))))
-           (mm-handle-set-cache handle spec))))))
-
-(defun mm-get-image-xemacs (handle)
+(defun mm-get-image (handle)
   "Return an image instance based on HANDLE."
   (let ((type (mm-handle-media-subtype handle))
        spec)
@@ -787,32 +768,31 @@ external if displayed external."
          (prog1
              (setq spec
                    (ignore-errors
-                     (cond
-                      ((equal type "xbm")
-                       ;; xbm images require special handling, since
-                       ;; the only way to create glyphs from these
-                       ;; (without a ton of work) is to write them
-                       ;; out to a file, and then create a file
-                       ;; specifier.
-                       (let ((file (make-temp-name
-                                    (expand-file-name "emm.xbm"
-                                                      mm-tmp-directory))))
-                         (unwind-protect
-                             (progn
-                               (write-region (point-min) (point-max) file)
-                               (make-glyph (list (cons 'x file))))
-                           (ignore-errors
-                             (delete-file file)))))
-                      (t
-                       (make-glyph
-                        (vector (intern type) :data (buffer-string)))))))
+                    ;; Avoid testing `make-glyph' since W3 may define
+                    ;; a bogus version of it.
+                     (if (fboundp 'create-image)
+                         (create-image (buffer-string) (intern type) 'data-p)
+                       (cond
+                        ((equal type "xbm")
+                         ;; xbm images require special handling, since
+                         ;; the only way to create glyphs from these
+                         ;; (without a ton of work) is to write them
+                         ;; out to a file, and then create a file
+                         ;; specifier.
+                         (let ((file (make-temp-name
+                                      (expand-file-name "emm.xbm"
+                                                        mm-tmp-directory))))
+                           (unwind-protect
+                               (progn
+                                 (write-region (point-min) (point-max) file)
+                                 (make-glyph (list (cons 'x file))))
+                             (ignore-errors
+                              (delete-file file)))))
+                        (t
+                         (make-glyph
+                          (vector (intern type) :data (buffer-string))))))))
            (mm-handle-set-cache handle spec))))))
 
-(defun mm-get-image (handle)
-  (if mm-xemacs-p
-      (mm-get-image-xemacs handle)
-    (mm-get-image-emacs handle)))
-
 (defun mm-image-fit-p (handle)
   "Say whether the image in HANDLE will fit the current window."
   (let ((image (mm-get-image handle)))
@@ -822,10 +802,12 @@ external if displayed external."
        (or mm-inline-large-images
            (and (< (glyph-width image) (window-pixel-width))
                 (< (glyph-height image) (window-pixel-height))))
-      ;; Let's just inline everything under Emacs 21, since the image
-      ;; specification there doesn't actually get the width/height
-      ;; until you render the image.
-      t)))
+      (let* ((size (image-size image))
+            (w (car size))
+            (h (cdr size)))
+       (or mm-inline-large-images
+           (and (< h (1- (window-height))) ; Don't include mode line.
+                (< w (window-width))))))))
 
 (defun mm-valid-image-format-p (format)
   "Say whether FORMAT can be displayed natively by Emacs."
@@ -835,7 +817,8 @@ external if displayed external."
     (valid-image-instantiator-format-p format))
    ;; Handle Emacs 21
    ((fboundp 'image-type-available-p)
-    (image-type-available-p format))
+    (and (display-graphic-p)
+        (image-type-available-p format)))
    ;; Nobody else can do images yet.
    (t
     nil)))
@@ -848,4 +831,4 @@ external if displayed external."
 
 (provide 'mm-decode)
 
-;; mm-decode.el ends here
+;;; mm-decode.el ends here