+;; There is a bug in Gnus inline image display due to which an extra line
+;; gets inserted every time it is viewed. To work around that problem we are
+;; using an extra property 'mh-region to remember the region that is added
+;; when the button is clicked. The region is then deleted to make sure that
+;; no extra lines get inserted.
+(defun mh-mm-display-part (handle)
+ "Toggle display of button for MIME part, HANDLE."
+ (beginning-of-line)
+ (let ((id (get-text-property (point) 'mh-part))
+ (point (point))
+ (window (selected-window))
+ (mail-parse-charset 'nil)
+ (mail-parse-ignored-charsets nil)
+ region buffer-read-only)
+ (save-excursion
+ (unwind-protect
+ (let ((win (get-buffer-window (current-buffer) t)))
+ (when win
+ (select-window win))
+ (goto-char point)
+
+ (if (mm-handle-displayed-p handle)
+ ;; This will remove the part.
+ (progn
+ ;; Delete the button and displayed part (if any)
+ (let ((region (get-text-property point 'mh-region)))
+ (when region
+ (mh-funcall-if-exists
+ remove-images (car region) (cdr region)))
+ (mm-display-part handle)
+ (when region
+ (delete-region (car region) (cdr region))))
+ ;; Delete button (if it still remains). This happens for
+ ;; externally displayed parts where the previous step does
+ ;; nothing.
+ (unless (eolp)
+ (delete-region (point) (progn (forward-line) (point)))))
+ (save-restriction
+ (delete-region (point) (progn (forward-line 1) (point)))
+ (narrow-to-region (point) (point))
+ ;; Maybe we need another unwind-protect here.
+ (when (equal (mm-handle-media-supertype handle) "image")
+ (insert "\n"))
+ (when (and (not (eq (ignore-errors (mm-display-part handle))
+ 'inline))
+ (equal (mm-handle-media-supertype handle)
+ "image"))
+ (goto-char (point-min))
+ (delete-char 1))
+ (when (equal (mm-handle-media-supertype handle) "text")
+ (when (eq mh-highlight-citation-style 'gnus)
+ (mh-gnus-article-highlight-citation))
+ (mh-display-smileys)
+ (mh-display-emphasis)
+ (mh-signature-highlight handle))
+ (setq region (cons (progn (goto-char (point-min))
+ (point-marker))
+ (progn (goto-char (point-max))
+ (point-marker)))))))
+ (when (window-live-p window)
+ (select-window window))
+ (goto-char point)
+ (beginning-of-line)
+ (mh-insert-mime-button handle id (mm-handle-displayed-p handle))
+ (goto-char point)
+ (when region
+ (add-text-properties (mh-line-beginning-position)
+ (mh-line-end-position)
+ `(mh-region ,region)))))))
+
+(defun mh-mime-part-index (handle)
+ "Generate the button number for MIME part, HANDLE.
+Notice that a hash table is used to display the same number when
+buttons need to be displayed multiple times (for instance when
+nested messages are opened)."
+ (or (gethash handle (mh-mime-part-index-hash (mh-buffer-data)))
+ (setf (gethash handle (mh-mime-part-index-hash (mh-buffer-data)))
+ (incf (mh-mime-parts-count (mh-buffer-data))))))
+
+(defun mh-small-image-p (handle)
+ "Decide whether HANDLE is a \"small\" image that can be displayed inline.
+This is only useful if a Content-Disposition header is not present."
+ (let ((media-test (caddr (assoc (car (mm-handle-type handle))
+ mh-mm-inline-media-tests)))
+ (mm-inline-large-images t))
+ (and media-test
+ (equal (mm-handle-media-supertype handle) "image")
+ (funcall media-test handle) ; Since mm-inline-large-images is T,
+ ; this only tells us if the image is
+ ; something that emacs can display
+ (let* ((image (mm-get-image handle)))
+ (or (mh-do-in-xemacs
+ (and (mh-funcall-if-exists glyphp image)
+ (< (glyph-width image)
+ (or mh-max-inline-image-width (window-pixel-width)))
+ (< (glyph-height image)
+ (or mh-max-inline-image-height
+ (window-pixel-height)))))
+ (mh-do-in-gnu-emacs
+ (let ((size (mh-funcall-if-exists image-size image)))
+ (and size
+ (< (cdr size) (or mh-max-inline-image-height
+ (1- (window-height))))
+ (< (car size) (or mh-max-inline-image-width
+ (window-width)))))))))))
+
+(defun mh-inline-vcard-p (handle)
+ "Decide if HANDLE is a vcard that must be displayed inline."
+ (let ((type (mm-handle-type handle)))
+ (and (or (featurep 'vcard) (fboundp 'vcard-pretty-print))
+ (consp type)
+ (equal (car type) "text/x-vcard")
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (not (mh-signature-separator-p)))))))
+
+(defun mh-signature-highlight (&optional handle)
+ "Highlight message signature in HANDLE.
+The optional argument, HANDLE is a MIME handle if the function is
+being used to highlight the signature in a MIME part."
+ (let ((regexp
+ (cond ((not handle) "^-- $")
+ ((not (and (equal (mm-handle-media-supertype handle) "text")
+ (equal (mm-handle-media-subtype handle) "html")))
+ "^-- $")
+ ((eq (mh-mm-text-html-renderer) 'lynx) "^ --$")
+ (t "^--$"))))
+ (save-excursion
+ (goto-char (point-max))
+ (when (re-search-backward regexp nil t)
+ (mh-do-in-gnu-emacs
+ (let ((ov (make-overlay (point) (point-max))))
+ (overlay-put ov 'face 'mh-show-signature)
+ (overlay-put ov 'evaporate t)))
+ (mh-do-in-xemacs
+ (set-extent-property (make-extent (point) (point-max))
+ 'face 'mh-show-signature))))))