Mercurial > emacs
comparison lisp/mh-e/mh-mime.el @ 50702:7dd3d5eae9c7
Upgraded to MH-E version 7.3.
See etc/MH-E-NEWS and lisp/mh-e/ChangeLog for details.
author | Bill Wohler <wohler@newt.com> |
---|---|
date | Fri, 25 Apr 2003 05:52:00 +0000 |
parents | b35587af8747 |
children | 695cf19ef79e |
comparison
equal
deleted
inserted
replaced
50701:cb5f0a5d5b36 | 50702:7dd3d5eae9c7 |
---|---|
1 ;;; mh-mime.el --- MH-E support for composing MIME messages | 1 ;;; mh-mime.el --- MH-E support for composing MIME messages |
2 | 2 |
3 ;; Copyright (C) 1993, 1995, 2001, 2002 Free Software Foundation, Inc. | 3 ;; Copyright (C) 1993, 1995, 2001, 02, 2003 Free Software Foundation, Inc. |
4 | 4 |
5 ;; Author: Bill Wohler <wohler@newt.com> | 5 ;; Author: Bill Wohler <wohler@newt.com> |
6 ;; Maintainer: Bill Wohler <wohler@newt.com> | 6 ;; Maintainer: Bill Wohler <wohler@newt.com> |
7 ;; Keywords: mail | 7 ;; Keywords: mail |
8 ;; See: mh-e.el | 8 ;; See: mh-e.el |
29 ;; Internal support for MH-E package. | 29 ;; Internal support for MH-E package. |
30 ;; Support for generating an mhn composition file. | 30 ;; Support for generating an mhn composition file. |
31 ;; MIME is supported only by MH 6.8 or later. | 31 ;; MIME is supported only by MH 6.8 or later. |
32 | 32 |
33 ;;; Change Log: | 33 ;;; Change Log: |
34 | |
35 ;; $Id: mh-mime.el,v 1.100 2003/01/25 19:18:51 satyaki Exp $ | |
36 | 34 |
37 ;;; Code: | 35 ;;; Code: |
38 | 36 |
39 (require 'cl) | 37 (require 'cl) |
40 (require 'mh-comp) | 38 (require 'mh-comp) |
56 (autoload 'mml-minibuffer-read-file "mml") | 54 (autoload 'mml-minibuffer-read-file "mml") |
57 (autoload 'mml-minibuffer-read-description "mml") | 55 (autoload 'mml-minibuffer-read-description "mml") |
58 (autoload 'mml-insert-empty-tag "mml") | 56 (autoload 'mml-insert-empty-tag "mml") |
59 (autoload 'mml-to-mime "mml") | 57 (autoload 'mml-to-mime "mml") |
60 (autoload 'mml-attach-file "mml") | 58 (autoload 'mml-attach-file "mml") |
59 (autoload 'rfc2047-decode-region "rfc2047") | |
61 | 60 |
62 ;;;###mh-autoload | 61 ;;;###mh-autoload |
63 (defun mh-compose-insertion (&optional inline) | 62 (defun mh-compose-insertion (&optional inline) |
64 "Add a directive to insert a MIME part from a file, using mhn or gnus. | 63 "Add a directive to insert a MIME part from a file, using mhn or gnus. |
65 If the variable `mh-compose-insertion' is set to 'mhn, then that will be used. | 64 If the variable `mh-compose-insertion' is set to 'mhn, then that will be used. |
233 "Insert a mhn directive to insert a file. | 232 "Insert a mhn directive to insert a file. |
234 | 233 |
235 The file specified by FILENAME is encoded as TYPE. An optional DESCRIPTION is | 234 The file specified by FILENAME is encoded as TYPE. An optional DESCRIPTION is |
236 used as the Content-Description field, optional set of ATTRIBUTES and an | 235 used as the Content-Description field, optional set of ATTRIBUTES and an |
237 optional COMMENT can also be included." | 236 optional COMMENT can also be included." |
238 (setq mh-mhn-compose-insert-flag t) | |
239 (beginning-of-line) | 237 (beginning-of-line) |
240 (insert "#" type) | 238 (insert "#" type) |
241 (and attributes | 239 (and attributes |
242 (insert "; " attributes)) | 240 (insert "; " attributes)) |
243 (and comment | 241 (and comment |
304 file and TYPE which is the MIME Content-Type. Optional arguments include | 302 file and TYPE which is the MIME Content-Type. Optional arguments include |
305 DESCRIPTION, a line of text for the Content-description header, ATTRIBUTES, | 303 DESCRIPTION, a line of text for the Content-description header, ATTRIBUTES, |
306 EXTRA-PARAMS, and COMMENT. | 304 EXTRA-PARAMS, and COMMENT. |
307 | 305 |
308 See also \\[mh-edit-mhn]." | 306 See also \\[mh-edit-mhn]." |
309 (setq mh-mhn-compose-insert-flag t) | |
310 (beginning-of-line) | 307 (beginning-of-line) |
311 (insert "#@" type) | 308 (insert "#@" type) |
312 (and attributes | 309 (and attributes |
313 (insert "; " attributes)) | 310 (insert "; " attributes)) |
314 (and comment | 311 (and comment |
339 (mh-prompt-for-folder "Message from" mh-sent-from-folder nil) | 336 (mh-prompt-for-folder "Message from" mh-sent-from-folder nil) |
340 (read-string (format "Messages%s: " | 337 (read-string (format "Messages%s: " |
341 (if mh-sent-from-msg | 338 (if mh-sent-from-msg |
342 (format " [%d]" mh-sent-from-msg) | 339 (format " [%d]" mh-sent-from-msg) |
343 ""))))) | 340 ""))))) |
344 (setq mh-mhn-compose-insert-flag t) | |
345 (beginning-of-line) | 341 (beginning-of-line) |
346 (insert "#forw [") | 342 (insert "#forw [") |
347 (and description | 343 (and description |
348 (not (string= description "")) | 344 (not (string= description "")) |
349 (insert description)) | 345 (insert description)) |
366 | 362 |
367 Process the current draft with the mhn program, which, using directives | 363 Process the current draft with the mhn program, which, using directives |
368 already inserted in the draft, fills in all the MIME components and header | 364 already inserted in the draft, fills in all the MIME components and header |
369 fields. | 365 fields. |
370 | 366 |
371 This step should be done last just before sending the message. | 367 This step is performed automatically when sending the message, but this |
368 function may be called manually before sending the draft as well. | |
372 | 369 |
373 The `\\[mh-revert-mhn-edit]' command undoes this command. The arguments in the | 370 The `\\[mh-revert-mhn-edit]' command undoes this command. The arguments in the |
374 list `mh-mhn-args' are passed to mhn if this function is passed an optional | 371 list `mh-mhn-args' are passed to mhn if this function is passed an optional |
375 prefix argument EXTRA-ARGS. | 372 prefix argument EXTRA-ARGS. |
376 | 373 |
377 For assistance with creating mhn directives to insert various types of | 374 For assistance with creating mhn directives to insert various types of |
378 components in a message, see \\[mh-mhn-compose-insertion] (generic insertion | 375 components in a message, see \\[mh-mhn-compose-insertion] (generic insertion |
379 from a file), \\[mh-mhn-compose-anon-ftp] (external reference to file via | 376 from a file), \\[mh-mhn-compose-anon-ftp] (external reference to file via |
380 anonymous ftp), \\[mh-mhn-compose-external-compressed-tar] \ \(reference to | 377 anonymous ftp), \\[mh-mhn-compose-external-compressed-tar] \ \(reference to |
381 compressed tar file via anonymous ftp), and \\[mh-mhn-compose-forw] (forward | 378 compressed tar file via anonymous ftp), and \\[mh-mhn-compose-forw] (forward |
382 message). If these helper functions are used, `mh-edit-mhn' is run | 379 message). |
383 automatically when the draft is sent. | |
384 | 380 |
385 The value of `mh-edit-mhn-hook' is a list of functions to be called, with no | 381 The value of `mh-edit-mhn-hook' is a list of functions to be called, with no |
386 arguments, after performing the conversion. | 382 arguments, after performing the conversion. |
387 | 383 |
388 The mhn program is part of MH version 6.8 or later." | 384 The mhn program is part of MH version 6.8 or later." |
394 (mh-exec-cmd-error nil | 390 (mh-exec-cmd-error nil |
395 "mhbuild" (if extra-args mh-mhn-args) buffer-file-name)) | 391 "mhbuild" (if extra-args mh-mhn-args) buffer-file-name)) |
396 (t | 392 (t |
397 (mh-exec-cmd-error (format "mhdraft=%s" buffer-file-name) | 393 (mh-exec-cmd-error (format "mhdraft=%s" buffer-file-name) |
398 "mhn" (if extra-args mh-mhn-args) buffer-file-name))) | 394 "mhn" (if extra-args mh-mhn-args) buffer-file-name))) |
399 (setq mh-mhn-compose-insert-flag nil) | |
400 (revert-buffer t t) | 395 (revert-buffer t t) |
401 (message "mhn editing...done") | 396 (message "mhn editing...done") |
402 (run-hooks 'mh-edit-mhn-hook)) | 397 (run-hooks 'mh-edit-mhn-hook)) |
403 | 398 |
404 ;;;###mh-autoload | 399 ;;;###mh-autoload |
427 (let ((buffer-read-only nil)) | 422 (let ((buffer-read-only nil)) |
428 (erase-buffer) | 423 (erase-buffer) |
429 (insert-file-contents backup-file)) | 424 (insert-file-contents backup-file)) |
430 (after-find-file nil))) | 425 (after-find-file nil))) |
431 | 426 |
427 ;;;###mh-autoload | |
428 (defun mh-mhn-directive-present-p () | |
429 "Check if the current buffer has text which might be a MHN directive." | |
430 (save-excursion | |
431 (block 'search-for-mhn-directive | |
432 (goto-char (point-min)) | |
433 (while (re-search-forward "^#" nil t) | |
434 (let ((s (buffer-substring-no-properties (point) (line-end-position)))) | |
435 (cond ((equal s "")) | |
436 ((string-match "^forw[ \t\n]+" s) | |
437 (return-from 'search-for-mhn-directive t)) | |
438 (t (let ((first-token (car (split-string s "[ \t;@]")))) | |
439 (when (string-match mh-media-type-regexp first-token) | |
440 (return-from 'search-for-mhn-directive t))))))) | |
441 nil))) | |
442 | |
432 | 443 |
433 | 444 |
434 ;;; MIME composition functions | 445 ;;; MIME composition functions |
435 | 446 |
436 ;;;###mh-autoload | 447 ;;;###mh-autoload |
437 (defun mh-mml-to-mime () | 448 (defun mh-mml-to-mime () |
438 "Compose MIME message from mml directives." | 449 "Compose MIME message from mml directives. |
450 This step is performed automatically when sending the message, but this | |
451 function may be called manually before sending the draft as well." | |
439 (interactive) | 452 (interactive) |
440 (when mh-gnus-pgp-support-flag ;; This is only needed for PGP | 453 (when mh-gnus-pgp-support-flag ;; This is only needed for PGP |
441 (message-options-set-recipient)) | 454 (message-options-set-recipient)) |
442 (mml-to-mime) | 455 (mml-to-mime)) |
443 (setq mh-mml-compose-insert-flag nil)) | |
444 | 456 |
445 ;;;###mh-autoload | 457 ;;;###mh-autoload |
446 (defun mh-mml-forward-message (description folder message) | 458 (defun mh-mml-forward-message (description folder message) |
447 "Forward a message as attachment. | 459 "Forward a message as attachment. |
448 The function will prompt the user for a DESCRIPTION, a FOLDER and MESSAGE | 460 The function will prompt the user for a DESCRIPTION, a FOLDER and MESSAGE |
458 mh-user-path (substring folder 1) msg) | 470 mh-user-path (substring folder 1) msg) |
459 "message/rfc822") | 471 "message/rfc822") |
460 (mml-attach-file (format "%s%s/%d" | 472 (mml-attach-file (format "%s%s/%d" |
461 mh-user-path (substring folder 1) msg) | 473 mh-user-path (substring folder 1) msg) |
462 "message/rfc822" | 474 "message/rfc822" |
463 description)) | 475 description))) |
464 (setq mh-mml-compose-insert-flag t)) | |
465 (t (error "The message number, %s is not a integer!" msg))))) | 476 (t (error "The message number, %s is not a integer!" msg))))) |
466 | 477 |
467 ;;;###mh-autoload | 478 ;;;###mh-autoload |
468 (defun mh-mml-attach-file (&optional disposition) | 479 (defun mh-mml-attach-file (&optional disposition) |
469 "Attach a file to the outgoing MIME message. | 480 "Attach a file to the outgoing MIME message. |
486 (completing-read "Disposition: [attachment] " | 497 (completing-read "Disposition: [attachment] " |
487 '(("attachment")("inline")) | 498 '(("attachment")("inline")) |
488 nil t nil nil | 499 nil t nil nil |
489 "attachment")))) | 500 "attachment")))) |
490 (mml-insert-empty-tag 'part 'type type 'filename file | 501 (mml-insert-empty-tag 'part 'type type 'filename file |
491 'disposition dispos 'description description) | 502 'disposition dispos 'description description))) |
492 (setq mh-mml-compose-insert-flag t))) | |
493 | 503 |
494 ;;;###mh-autoload | 504 ;;;###mh-autoload |
495 (defun mh-mml-secure-message-sign-pgpmime () | 505 (defun mh-mml-secure-message-sign-pgpmime () |
496 "Add directive to encrypt/sign the entire message." | 506 "Add directive to encrypt/sign the entire message." |
497 (interactive) | 507 (interactive) |
498 (if (not mh-gnus-pgp-support-flag) | 508 (if (not mh-gnus-pgp-support-flag) |
499 (error "Sorry. Your version of gnus does not support PGP/GPG") | 509 (error "Sorry. Your version of gnus does not support PGP/GPG") |
500 (mml-secure-message-sign-pgpmime) | 510 (mml-secure-message-sign-pgpmime))) |
501 (setq mh-mml-compose-insert-flag t))) | |
502 | 511 |
503 ;;;###mh-autoload | 512 ;;;###mh-autoload |
504 (defun mh-mml-secure-message-encrypt-pgpmime (&optional dontsign) | 513 (defun mh-mml-secure-message-encrypt-pgpmime (&optional dontsign) |
505 "Add directive to encrypt and sign the entire message. | 514 "Add directive to encrypt and sign the entire message. |
506 If called with a prefix argument DONTSIGN, only encrypt (do NOT sign)." | 515 If called with a prefix argument DONTSIGN, only encrypt (do NOT sign)." |
507 (interactive "P") | 516 (interactive "P") |
508 (if (not mh-gnus-pgp-support-flag) | 517 (if (not mh-gnus-pgp-support-flag) |
509 (error "Sorry. Your version of gnus does not support PGP/GPG") | 518 (error "Sorry. Your version of gnus does not support PGP/GPG") |
510 (mml-secure-message-encrypt-pgpmime dontsign) | 519 (mml-secure-message-encrypt-pgpmime dontsign))) |
511 (setq mh-mml-compose-insert-flag t))) | 520 |
521 ;;;###mh-autoload | |
522 (defun mh-mml-directive-present-p () | |
523 "Check if the current buffer has text which may be an MML directive." | |
524 (save-excursion | |
525 (goto-char (point-min)) | |
526 (re-search-forward | |
527 "\\(<#part\\(.\\|\n\\)*>[ \n\t]*<#/part>\\|^<#secure.+>$\\)" | |
528 nil t))) | |
512 | 529 |
513 | 530 |
514 | 531 |
515 ;;; MIME decoding | 532 ;;; MIME decoding |
516 | 533 |
544 (car handle)))) | 561 (car handle)))) |
545 | 562 |
546 ;; Copy of original macro is in mm-decode.el | 563 ;; Copy of original macro is in mm-decode.el |
547 (mh-defun-compat mm-handle-multipart-ctl-parameter (handle parameter) | 564 (mh-defun-compat mm-handle-multipart-ctl-parameter (handle parameter) |
548 (get-text-property 0 parameter (car handle))) | 565 (get-text-property 0 parameter (car handle))) |
566 | |
567 (mh-do-in-xemacs (defvar default-enable-multibyte-characters)) | |
549 | 568 |
550 ;; Copy of original function in mm-decode.el | 569 ;; Copy of original function in mm-decode.el |
551 (mh-defun-compat mm-readable-p (handle) | 570 (mh-defun-compat mm-readable-p (handle) |
552 "Say whether the content of HANDLE is readable." | 571 "Say whether the content of HANDLE is readable." |
553 (and (< (with-current-buffer (mm-handle-buffer handle) | 572 (and (< (with-current-buffer (mm-handle-buffer handle) |
608 ;;;###mh-autoload | 627 ;;;###mh-autoload |
609 (defun mh-mime-cleanup () | 628 (defun mh-mime-cleanup () |
610 "Free the decoded MIME parts." | 629 "Free the decoded MIME parts." |
611 (let ((mime-data (gethash (current-buffer) mh-globals-hash))) | 630 (let ((mime-data (gethash (current-buffer) mh-globals-hash))) |
612 ;; This is for Emacs, what about XEmacs? | 631 ;; This is for Emacs, what about XEmacs? |
613 (cond ((fboundp 'remove-images) | 632 (mh-funcall-if-exists remove-images (point-min) (point-max)) |
614 (remove-images (point-min) (point-max)))) | |
615 (when mime-data | 633 (when mime-data |
616 (mm-destroy-parts (mh-mime-handles mime-data)) | 634 (mm-destroy-parts (mh-mime-handles mime-data)) |
617 (remhash (current-buffer) mh-globals-hash)))) | 635 (remhash (current-buffer) mh-globals-hash)))) |
618 | 636 |
619 ;;;###mh-autoload | 637 ;;;###mh-autoload |
660 (defun mh-display-smileys () | 678 (defun mh-display-smileys () |
661 "Function to display smileys." | 679 "Function to display smileys." |
662 (when (and mh-graphical-smileys-flag | 680 (when (and mh-graphical-smileys-flag |
663 (fboundp 'smiley-region) | 681 (fboundp 'smiley-region) |
664 (boundp 'font-lock-maximum-size) | 682 (boundp 'font-lock-maximum-size) |
683 font-lock-maximum-size | |
665 (>= (/ font-lock-maximum-size 8) (buffer-size))) | 684 (>= (/ font-lock-maximum-size 8) (buffer-size))) |
666 (smiley-region (point-min) (point-max)))) | 685 (smiley-region (point-min) (point-max)))) |
667 | 686 |
668 ;;;###mh-autoload | 687 ;;;###mh-autoload |
669 (defun mh-display-emphasis () | 688 (defun mh-display-emphasis () |
670 "Function to display graphical emphasis." | 689 "Function to display graphical emphasis." |
671 (when (and mh-graphical-emphasis-flag | 690 (when (and mh-graphical-emphasis-flag |
672 (boundp 'font-lock-maximum-size) | 691 (if font-lock-maximum-size |
673 (>= (/ font-lock-maximum-size 8) (buffer-size))) | 692 (>= (/ font-lock-maximum-size 8) (buffer-size)))) |
674 (flet ((article-goto-body ())) ; shadow this function to do nothing | 693 (flet ((article-goto-body ())) ; shadow this function to do nothing |
675 (save-excursion | 694 (save-excursion |
676 (goto-char (point-min)) | 695 (goto-char (point-min)) |
677 (article-emphasize))))) | 696 (article-emphasize))))) |
678 | 697 |
683 (defvar mh-mime-button-map | 702 (defvar mh-mime-button-map |
684 (let ((map (make-sparse-keymap))) | 703 (let ((map (make-sparse-keymap))) |
685 (unless (>= (string-to-number emacs-version) 21) | 704 (unless (>= (string-to-number emacs-version) 21) |
686 ;; XEmacs doesn't care. | 705 ;; XEmacs doesn't care. |
687 (set-keymap-parent map mh-show-mode-map)) | 706 (set-keymap-parent map mh-show-mode-map)) |
688 (define-key map [mouse-2] 'mh-push-button) | 707 (mh-do-in-gnu-emacs |
708 (define-key map [mouse-2] 'mh-push-button)) | |
709 (mh-do-in-xemacs | |
710 (define-key map '(button2) 'mh-push-button)) | |
689 (dolist (c mh-mime-button-commands) | 711 (dolist (c mh-mime-button-commands) |
690 (define-key map (cadr c) (car c))) | 712 (define-key map (cadr c) (car c))) |
691 map)) | 713 map)) |
692 (defvar mh-mime-button-line-format-alist | 714 (defvar mh-mime-button-line-format-alist |
693 '((?T long-type ?s) | 715 '((?T long-type ?s) |
706 (defvar mh-mime-security-button-map | 728 (defvar mh-mime-security-button-map |
707 (let ((map (make-sparse-keymap))) | 729 (let ((map (make-sparse-keymap))) |
708 (unless (>= (string-to-number emacs-version) 21) | 730 (unless (>= (string-to-number emacs-version) 21) |
709 (set-keymap-parent map mh-show-mode-map)) | 731 (set-keymap-parent map mh-show-mode-map)) |
710 (define-key map "\r" 'mh-press-button) | 732 (define-key map "\r" 'mh-press-button) |
711 (define-key map [mouse-2] 'mh-push-button) | 733 (mh-do-in-gnu-emacs |
734 (define-key map [mouse-2] 'mh-push-button)) | |
735 (mh-do-in-xemacs | |
736 (define-key map '(button2) 'mh-push-button)) | |
712 map)) | 737 map)) |
713 | 738 |
714 (defvar mh-mime-save-parts-directory nil | 739 (defvar mh-mime-save-parts-directory nil |
715 "Default to use for `mh-mime-save-parts-default-directory'. | 740 "Default to use for `mh-mime-save-parts-default-directory'. |
716 Set from last use.") | 741 Set from last use.") |
753 (if (not (file-directory-p directory)) | 778 (if (not (file-directory-p directory)) |
754 (message "No directory specified.") | 779 (message "No directory specified.") |
755 (if (equal nil mh-mime-save-parts-default-directory) | 780 (if (equal nil mh-mime-save-parts-default-directory) |
756 (setq mh-mime-save-parts-directory directory)) | 781 (setq mh-mime-save-parts-directory directory)) |
757 (save-excursion | 782 (save-excursion |
758 (set-buffer (get-buffer-create " *mh-store*")) | 783 (set-buffer (get-buffer-create mh-log-buffer)) |
759 (cd directory) | 784 (cd directory) |
760 (setq mh-mime-save-parts-directory directory) | 785 (setq mh-mime-save-parts-directory directory) |
761 (erase-buffer) | 786 (let ((initial-size (mh-truncate-log-buffer))) |
762 (apply 'call-process | 787 (apply 'call-process |
763 (expand-file-name command mh-progs) nil t nil | 788 (expand-file-name command mh-progs) nil t nil |
764 (mh-list-to-string (list folder msg "-auto"))) | 789 (mh-list-to-string (list folder msg "-auto"))) |
765 (if (> (buffer-size) 0) | 790 (if (> (buffer-size) initial-size) |
766 (save-window-excursion | 791 (save-window-excursion |
767 (switch-to-buffer-other-window " *mh-store*") | 792 (switch-to-buffer-other-window mh-log-buffer) |
768 (sit-for 3))))))) | 793 (sit-for 3)))))))) |
769 | 794 |
770 ;; Avoid errors if gnus-sum isn't loaded yet... | 795 ;; Avoid errors if gnus-sum isn't loaded yet... |
771 (defvar gnus-newsgroup-charset nil) | 796 (defvar gnus-newsgroup-charset nil) |
772 (defvar gnus-newsgroup-name nil) | 797 (defvar gnus-newsgroup-name nil) |
798 | |
799 (defun mh-decode-message-body () | |
800 "Decode message based on charset. | |
801 If message has been encoded for transfer take that into account." | |
802 (let* ((ct (ignore-errors (mail-header-parse-content-type | |
803 (message-fetch-field "Content-Type" t)))) | |
804 (charset (mail-content-type-get ct 'charset)) | |
805 (cte (message-fetch-field "Content-Transfer-Encoding"))) | |
806 (when (stringp cte) (setq cte (mail-header-strip cte))) | |
807 (when (or (not ct) (equal (car ct) "text/plain")) | |
808 (save-restriction | |
809 (narrow-to-region (min (1+ (mh-mail-header-end)) (point-max)) | |
810 (point-max)) | |
811 (mm-decode-body charset | |
812 (and cte (intern (downcase | |
813 (gnus-strip-whitespace cte)))) | |
814 (car ct)))))) | |
815 | |
816 ;;;###mh-autoload | |
817 (defun mh-decode-message-header () | |
818 "Decode RFC2047 encoded message header fields." | |
819 (when mh-decode-mime-flag | |
820 (let ((buffer-read-only nil)) | |
821 (rfc2047-decode-region (point-min) (mh-mail-header-end))))) | |
773 | 822 |
774 ;;;###mh-autoload | 823 ;;;###mh-autoload |
775 (defun mh-mime-display (&optional pre-dissected-handles) | 824 (defun mh-mime-display (&optional pre-dissected-handles) |
776 "Display (and possibly decode) MIME handles. | 825 "Display (and possibly decode) MIME handles. |
777 Optional argument, PRE-DISSECTED-HANDLES is a list of MIME handles. If | 826 Optional argument, PRE-DISSECTED-HANDLES is a list of MIME handles. If |
778 present they are displayed otherwise the buffer is parsed and then | 827 present they are displayed otherwise the buffer is parsed and then |
779 displayed." | 828 displayed." |
780 (let ((handles ()) | 829 (let ((handles ()) |
781 (folder mh-show-folder-buffer)) | 830 (folder mh-show-folder-buffer) |
831 (raw-message-data (buffer-string))) | |
782 (flet ((mm-handle-set-external-undisplayer | 832 (flet ((mm-handle-set-external-undisplayer |
783 (handle function) | 833 (handle function) |
784 (mh-handle-set-external-undisplayer folder handle function))) | 834 (mh-handle-set-external-undisplayer folder handle function))) |
785 ;; If needed dissect the current buffer | 835 (goto-char (point-min)) |
786 (if pre-dissected-handles | 836 (unless (search-forward "\n\n" nil t) |
787 (setq handles pre-dissected-handles) | 837 (goto-char (point-max)) |
788 (setq handles (or (mm-dissect-buffer nil) (mm-uu-dissect))) | 838 (insert "\n\n")) |
789 (setf (mh-mime-handles (mh-buffer-data)) | 839 |
790 (mm-merge-handles handles (mh-mime-handles (mh-buffer-data)))) | 840 (condition-case err |
791 | 841 (progn |
792 ;; Use charset to decode body... | 842 ;; If needed dissect the current buffer |
793 (unless handles | 843 (if pre-dissected-handles |
794 (let* ((ct (ignore-errors | 844 (setq handles pre-dissected-handles) |
795 (mail-header-parse-content-type | 845 (setq handles (or (mm-dissect-buffer nil) (mm-uu-dissect))) |
796 (message-fetch-field "Content-Type" t)))) | 846 (setf (mh-mime-handles (mh-buffer-data)) |
797 (charset (mail-content-type-get ct 'charset))) | 847 (mm-merge-handles handles |
798 (when (stringp charset) | 848 (mh-mime-handles (mh-buffer-data)))) |
799 (mm-decode-body charset))))) | 849 (unless handles (mh-decode-message-body))) |
800 | 850 |
801 (when (and handles (or (not (stringp (car handles))) (cdr handles))) | 851 (when (and handles |
802 ;; Goto start of message body | 852 (or (not (stringp (car handles))) (cdr handles))) |
803 (goto-char (point-min)) | 853 ;; Goto start of message body |
804 (or (search-forward "\n\n" nil t) (goto-char (point-max))) | 854 (goto-char (point-min)) |
805 | 855 (or (search-forward "\n\n" nil t) (goto-char (point-max))) |
806 ;; Delete the body | 856 |
807 (delete-region (point) (point-max)) | 857 ;; Delete the body |
808 | 858 (delete-region (point) (point-max)) |
809 ;; Display the MIME handles | 859 |
810 (mh-mime-display-part handles))))) | 860 ;; Display the MIME handles |
861 (mh-mime-display-part handles))) | |
862 (error | |
863 (message "Please report this error. The error message is:\n %s" | |
864 (error-message-string err)) | |
865 (delete-region (point-min) (point-max)) | |
866 (insert raw-message-data)))))) | |
811 | 867 |
812 (defun mh-mime-display-part (handle) | 868 (defun mh-mime-display-part (handle) |
813 "Decides the viewer to call based on the type of HANDLE." | 869 "Decides the viewer to call based on the type of HANDLE." |
814 (cond ((null handle) nil) | 870 (cond ((null handle) nil) |
815 ((not (stringp (car handle))) | 871 ((not (stringp (car handle))) |
866 ; this only tells us if the image is | 922 ; this only tells us if the image is |
867 ; something that emacs can display | 923 ; something that emacs can display |
868 (let* ((image (mm-get-image handle))) | 924 (let* ((image (mm-get-image handle))) |
869 (cond ((fboundp 'glyph-width) | 925 (cond ((fboundp 'glyph-width) |
870 ;; XEmacs -- totally untested, copied from gnus | 926 ;; XEmacs -- totally untested, copied from gnus |
871 (and (< (glyph-width image) | 927 (and (mh-funcall-if-exists glyphp image) |
928 (< (glyph-width image) | |
872 (or mh-max-inline-image-width | 929 (or mh-max-inline-image-width |
873 (window-pixel-width))) | 930 (window-pixel-width))) |
874 (< (glyph-height image) | 931 (< (glyph-height image) |
875 (or mh-max-inline-image-height | 932 (or mh-max-inline-image-height |
876 (window-pixel-height))))) | 933 (window-pixel-height))))) |
877 ((fboundp 'image-size) | 934 ((fboundp 'image-size) |
878 ;; Emacs21 -- copied from gnus | 935 ;; Emacs21 -- copied from gnus |
879 (let ((size (image-size image))) | 936 (let ((size (mh-funcall-if-exists image-size image))) |
880 (and (< (cdr size) | 937 (and size |
938 (< (cdr size) | |
881 (or mh-max-inline-image-height | 939 (or mh-max-inline-image-height |
882 (1- (window-height)))) | 940 (1- (window-height)))) |
883 (< (car size) | 941 (< (car size) |
884 (or mh-max-inline-image-width (window-width)))))) | 942 (or mh-max-inline-image-width (window-width)))))) |
885 (t | 943 (t |
887 nil)))))) | 945 nil)))))) |
888 | 946 |
889 (defun mh-inline-vcard-p (handle) | 947 (defun mh-inline-vcard-p (handle) |
890 "Decide if HANDLE is a vcard that must be displayed inline." | 948 "Decide if HANDLE is a vcard that must be displayed inline." |
891 (let ((type (mm-handle-type handle))) | 949 (let ((type (mm-handle-type handle))) |
892 (and (consp type) | 950 (and (or (featurep 'vcard) (fboundp 'vcard-pretty-print)) |
951 (consp type) | |
893 (equal (car type) "text/x-vcard") | 952 (equal (car type) "text/x-vcard") |
894 (save-excursion | 953 (save-excursion |
895 (save-restriction | 954 (save-restriction |
896 (widen) | 955 (widen) |
897 (goto-char (point-min)) | 956 (goto-char (point-min)) |
930 (insert "\n") | 989 (insert "\n") |
931 (mh-insert-mime-button handle (mh-mime-part-index handle) nil) | 990 (mh-insert-mime-button handle (mh-mime-part-index handle) nil) |
932 (forward-line -1) | 991 (forward-line -1) |
933 (mh-mm-display-part handle))) | 992 (mh-mm-display-part handle))) |
934 (goto-char (point-max))))) | 993 (goto-char (point-max))))) |
994 | |
995 (mh-do-in-xemacs | |
996 (defvar dots) | |
997 (defvar type)) | |
935 | 998 |
936 (defun mh-insert-mime-button (handle index displayed) | 999 (defun mh-insert-mime-button (handle index displayed) |
937 "Insert MIME button for HANDLE. | 1000 "Insert MIME button for HANDLE. |
938 INDEX is the part number that will be DISPLAYED. It is also used by commands | 1001 INDEX is the part number that will be DISPLAYED. It is also used by commands |
939 like \"K v\" which operate on individual MIME parts." | 1002 like \"K v\" which operate on individual MIME parts." |
997 (if (mm-handle-displayed-p handle) | 1060 (if (mm-handle-displayed-p handle) |
998 ;; This will remove the part. | 1061 ;; This will remove the part. |
999 (progn | 1062 (progn |
1000 ;; Delete the button and displayed part (if any) | 1063 ;; Delete the button and displayed part (if any) |
1001 (let ((region (get-text-property point 'mh-region))) | 1064 (let ((region (get-text-property point 'mh-region))) |
1002 (when region | 1065 (when (and region (fboundp 'remove-images)) |
1003 (when (fboundp 'remove-images) | 1066 (mh-funcall-if-exists |
1004 (remove-images (car region) (cdr region)))) | 1067 remove-images (car region) (cdr region))) |
1005 (mm-display-part handle) | 1068 (mm-display-part handle) |
1006 (when region | 1069 (when region |
1007 (delete-region (car region) (cdr region)))) | 1070 (delete-region (car region) (cdr region)))) |
1008 ;; Delete button (if it still remains). This happens for | 1071 ;; Delete button (if it still remains). This happens for |
1009 ;; externally displayed parts where the previous step does | 1072 ;; externally displayed parts where the previous step does |
1065 "Click MIME button for EVENT. | 1128 "Click MIME button for EVENT. |
1066 If the MIME part is visible then it is removed. Otherwise the part is | 1129 If the MIME part is visible then it is removed. Otherwise the part is |
1067 displayed. This function is called when the mouse is used to click the MIME | 1130 displayed. This function is called when the mouse is used to click the MIME |
1068 button." | 1131 button." |
1069 (interactive "e") | 1132 (interactive "e") |
1070 (set-buffer (window-buffer (posn-window (event-start event)))) | 1133 (save-excursion |
1071 (select-window (posn-window (event-start event))) | 1134 (let* ((event-window |
1072 (let* ((pos (posn-point (event-start event))) | 1135 (or (mh-funcall-if-exists posn-window (event-start event));GNU Emacs |
1073 (folder mh-show-folder-buffer) | 1136 (mh-funcall-if-exists event-window event))) ;XEmacs |
1074 (mm-inline-media-tests mh-mm-inline-media-tests) | 1137 (event-position |
1075 (data (get-text-property pos 'mh-data)) | 1138 (or (mh-funcall-if-exists posn-point (event-start event)) ;GNU Emacs |
1076 (function (get-text-property pos 'mh-callback)) | 1139 (mh-funcall-if-exists event-closest-point event))) ;XEmacs |
1077 (buffer-read-only nil)) | 1140 (original-window (selected-window)) |
1078 (flet ((mm-handle-set-external-undisplayer | 1141 (original-position (progn |
1079 (handle function) | 1142 (set-buffer (window-buffer event-window)) |
1080 (mh-handle-set-external-undisplayer folder handle function))) | 1143 (set-marker (make-marker) (point)))) |
1081 (goto-char pos) | 1144 (folder mh-show-folder-buffer) |
1082 (unwind-protect (and function (funcall function data)) | 1145 (mm-inline-media-tests mh-mm-inline-media-tests) |
1083 (set-buffer-modified-p nil))))) | 1146 (data (get-text-property event-position 'mh-data)) |
1147 (function (get-text-property event-position 'mh-callback)) | |
1148 (buffer-read-only nil)) | |
1149 (unwind-protect | |
1150 (progn | |
1151 (select-window event-window) | |
1152 (flet ((mm-handle-set-external-undisplayer (handle func) | |
1153 (mh-handle-set-external-undisplayer folder handle func))) | |
1154 (goto-char event-position) | |
1155 (and function (funcall function data)))) | |
1156 (set-buffer-modified-p nil) | |
1157 (goto-char original-position) | |
1158 (set-marker original-position nil) | |
1159 (select-window original-window))))) | |
1084 | 1160 |
1085 ;;;###mh-autoload | 1161 ;;;###mh-autoload |
1086 (defun mh-mime-save-part () | 1162 (defun mh-mime-save-part () |
1087 "Save MIME part at point." | 1163 "Save MIME part at point." |
1088 (interactive) | 1164 (interactive) |
1240 (mm-merge-handles | 1316 (mm-merge-handles |
1241 handles (mh-mime-handles (mh-buffer-data)))) | 1317 handles (mh-mime-handles (mh-buffer-data)))) |
1242 handles)))) | 1318 handles)))) |
1243 | 1319 |
1244 (goto-char (point-min)) | 1320 (goto-char (point-min)) |
1321 (mh-show-xface) | |
1245 (cond (clean-message-header | 1322 (cond (clean-message-header |
1246 (mh-clean-msg-header (point-min) | 1323 (mh-clean-msg-header (point-min) |
1247 invisible-headers | 1324 invisible-headers |
1248 visible-headers) | 1325 visible-headers) |
1249 (goto-char (point-min))) | 1326 (goto-char (point-min))) |
1250 (t | 1327 (t |
1251 (mh-start-of-uncleaned-message))) | 1328 (mh-start-of-uncleaned-message))) |
1252 (mh-show-xface) | 1329 (mh-decode-message-header) |
1253 (mh-show-addr) | 1330 (mh-show-addr) |
1254 ;; The other highlighting types don't need anything special | 1331 ;; The other highlighting types don't need anything special |
1255 (when (eq mh-highlight-citation-p 'gnus) | 1332 (when (eq mh-highlight-citation-p 'gnus) |
1256 (mh-gnus-article-highlight-citation)) | 1333 (mh-gnus-article-highlight-citation)) |
1257 (goto-char (point-min)) | 1334 (goto-char (point-min)) |