(eval-when-compile
(require 'cl)
- (defvar tool-bar-map))
+ (defvar tool-bar-map)
+ (defvar w3m-minor-mode-map))
(require 'gnus)
;; Avoid the "Recursive load suspected" error in Emacs 21.1.
regexp. If it matches, the text in question is not a signature.
This can also be a list of the above values."
- :type '(choice (integer :value 200)
+ :type '(choice (const nil)
+ (integer :value 200)
(number :value 4.0)
(function :value fun)
(regexp :value ".*"))
This is meant for people who want to do something automatic based
on parts -- for instance, adding Vcard info to a database."
:group 'gnus-article-mime
- :type 'function)
+ :type '(choice (const nil)
+ function))
(defcustom gnus-mime-multipart-functions nil
"An alist of MIME types to functions to display them."
(defcustom gnus-mime-action-alist
'(("save to file" . gnus-mime-save-part)
("save and strip" . gnus-mime-save-part-and-strip)
+ ("replace with file" . gnus-mime-replace-part)
("delete part" . gnus-mime-delete-part)
("display as text" . gnus-mime-inline-part)
("view the part" . gnus-mime-view-part)
(gnus-mime-view-part-as-charset "C" "View As charset...")
(gnus-mime-save-part "o" "Save...")
(gnus-mime-save-part-and-strip "\C-o" "Save and Strip")
+ (gnus-mime-replace-part "r" "Replace part")
(gnus-mime-delete-part "d" "Delete part")
(gnus-mime-copy-part "c" "View As Text, In Other Buffer")
(gnus-mime-inline-part "i" "View As Text, In This Buffer")
- (gnus-mime-view-part-internally "E" "View Internally")
+ (gnus-mime-view-part-internally "E" "View Internally") ;; Why `E'?
(gnus-mime-view-part-externally "e" "View Externally")
(gnus-mime-print-part "p" "Print")
(gnus-mime-pipe-part "|" "Pipe To Command...")
"Jump to MIME part N."
(interactive "P")
(pop-to-buffer gnus-article-buffer)
+ ;; FIXME: why is it necessary?
+ (sit-for 0)
(let ((parts (length gnus-article-mime-handle-alist)))
(or n (setq n
(string-to-number
n parts)
parts)))
(gnus-message 9 "Jumping to part %s." n)
- (gnus-article-goto-part n)))
+ (cond ((>= gnus-auto-select-part 1)
+ (while (and (<= n parts)
+ (not (gnus-article-goto-part n)))
+ (setq n (1+ n))))
+ ((< gnus-auto-select-part 0)
+ (while (and (>= n 1)
+ (not (gnus-article-goto-part n)))
+ (setq n (1- n))))
+ (t
+ (gnus-article-goto-part n)))))
(eval-when-compile
(defsubst gnus-article-edit-part (handles &optional current-id)
(gnus-article-jump-to-part
(+ current-id gnus-auto-select-part)))))
-(defun gnus-mime-save-part-and-strip ()
- "Save the MIME part under point then replace it with an external body."
+(defun gnus-mime-replace-part (file)
+ "Replace MIME part under point with an external body."
+ ;; Useful if file has already been saved to disk
+ (interactive
+ (list
+ (mm-with-multibyte
+ (read-file-name "Replace MIME part with file: "
+ (or mm-default-directory default-directory)
+ nil nil))))
+ (gnus-mime-save-part-and-strip file))
+
+(defun gnus-mime-save-part-and-strip (&optional file)
+ "Save the MIME part under point then replace it with an external body.
+If FILE is given, use it for the external part."
(interactive)
(gnus-article-check-buffer)
(when (gnus-group-read-only-p)
The current article has a complicated MIME structure, giving up..."))
(let* ((data (get-text-property (point) 'gnus-data))
(id (get-text-property (point) 'gnus-part))
- file param
+ param
(handles gnus-article-mime-handles))
- (setq file (and data (mm-save-part data "Delete MIME part and save to: ")))
+ (unless file
+ (setq file
+ (and data (mm-save-part data "Delete MIME part and save to: "))))
(when file
(with-current-buffer (mm-handle-buffer data)
(erase-buffer)
;; (set-buffer gnus-summary-buffer)
(gnus-article-edit-part handles id))))
+;; A function like `gnus-summary-save-parts' (`X m', `<MIME> <Extract all
+;; parts...>') but with stripping would be nice.
+
(defun gnus-mime-delete-part ()
"Delete the MIME part under point.
Replace it with some information about the removed part."
(if action-pair
(funcall (cdr action-pair)))))
-(defun gnus-article-part-wrapper (n function &optional no-handle)
- (with-current-buffer gnus-article-buffer
- (when (> n (length gnus-article-mime-handle-alist))
- (error "No such part"))
- (gnus-article-goto-part n)
- (if no-handle
- (funcall function)
- (let ((handle (cdr (assq n gnus-article-mime-handle-alist))))
- (funcall function handle)))))
+(defun gnus-article-part-wrapper (n function &optional no-handle interactive)
+ "Call FUNCTION on MIME part N.
+Unless NO-HANDLE, call FUNCTION with N-th MIME handle as it's only argument.
+If INTERACTIVE, call FUNCTION interactivly."
+ (let (window frame)
+ ;; Check whether the article is displayed.
+ (unless (and (gnus-buffer-live-p gnus-article-buffer)
+ (setq window (get-buffer-window gnus-article-buffer t))
+ (frame-visible-p (setq frame (window-frame window))))
+ (error "No article is displayed"))
+ (with-current-buffer gnus-article-buffer
+ ;; Check whether the article displays the right contents.
+ (unless (with-current-buffer gnus-summary-buffer
+ (eq gnus-current-article (gnus-summary-article-number)))
+ (error "You should select the right article first"))
+ ;; Check whether the specified part exists.
+ (when (> n (length gnus-article-mime-handle-alist))
+ (error "No such part")))
+ (unless
+ (progn
+ ;; To select the window is needed so that the cursor
+ ;; might be visible on the MIME button.
+ (select-window (prog1
+ window
+ (setq window (selected-window))
+ ;; Article may be displayed in the other frame.
+ (gnus-select-frame-set-input-focus
+ (prog1
+ frame
+ (setq frame (selected-frame))))))
+ (when (gnus-article-goto-part n)
+ ;; We point the cursor and the arrow at the MIME button
+ ;; when the `function' prompt the user for something.
+ (let ((cursor-in-non-selected-windows t)
+ (overlay-arrow-string "=>")
+ (overlay-arrow-position (point-marker)))
+ (unwind-protect
+ (cond
+ ((and no-handle interactive)
+ (call-interactively function))
+ (no-handle
+ (funcall function))
+ (interactive
+ (call-interactively
+ function
+ (cdr (assq n gnus-article-mime-handle-alist))))
+ (t
+ (funcall function
+ (cdr (assq n gnus-article-mime-handle-alist)))))
+ (set-marker overlay-arrow-position nil)
+ (unless gnus-auto-select-part
+ (gnus-select-frame-set-input-focus frame)
+ (select-window window))))
+ t))
+ (if gnus-inhibit-mime-unbuttonizing
+ ;; This is the default though the program shouldn't reach here.
+ (error "No such part")
+ ;; The part which doesn't have the MIME button is selected.
+ ;; So, we display all the buttons and redo it.
+ (let ((gnus-inhibit-mime-unbuttonizing t))
+ (gnus-summary-show-article)
+ (gnus-article-part-wrapper n function no-handle))))))
(defun gnus-article-pipe-part (n)
"Pipe MIME part N, which is the numerical prefix."
(interactive "p")
(gnus-article-part-wrapper n 'gnus-mime-save-part-and-strip t))
+(defun gnus-article-replace-part (n)
+ "Replace MIME part N with an external body.
+N is the numerical prefix."
+ (interactive "p")
+ (gnus-article-part-wrapper n 'gnus-mime-replace-part t t))
+
(defun gnus-article-delete-part (n)
"Delete MIME part N and add some information about the removed part.
N is the numerical prefix."
(defun gnus-mime-display-part (handle)
(cond
+ ;; Maybe a broken MIME message.
+ ((null handle))
;; Single part.
((not (stringp (car handle)))
(gnus-mime-display-single handle))
(forward-line -1)
(setq beg (point)))
(gnus-article-insert-newline)
- (mm-display-inline handle)
+ (mm-insert-inline handle
+ (let ((charset
+ (mail-content-type-get
+ (mm-handle-type handle) 'charset)))
+ (if (eq charset 'gnus-decoded)
+ (mm-get-part handle)
+ (mm-decode-string (mm-get-part handle)
+ charset))))
(goto-char (point-max))))
;; Do highlighting.
(save-excursion
(narrow-to-region (point) (point))
(unless (gnus-unbuttonized-mime-type-p (car handle))
(gnus-insert-mime-security-button handle))
- (gnus-mime-display-mixed (cdr handle))
+ (gnus-mime-display-part (cadr handle))
(unless (bolp)
(insert "\n"))
(unless (gnus-unbuttonized-mime-type-p (car handle))