Mercurial > emacs
diff 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 |
line wrap: on
line diff
--- a/lisp/mh-e/mh-mime.el Fri Apr 25 04:32:25 2003 +0000 +++ b/lisp/mh-e/mh-mime.el Fri Apr 25 05:52:00 2003 +0000 @@ -1,6 +1,6 @@ ;;; mh-mime.el --- MH-E support for composing MIME messages -;; Copyright (C) 1993, 1995, 2001, 2002 Free Software Foundation, Inc. +;; Copyright (C) 1993, 1995, 2001, 02, 2003 Free Software Foundation, Inc. ;; Author: Bill Wohler <wohler@newt.com> ;; Maintainer: Bill Wohler <wohler@newt.com> @@ -32,8 +32,6 @@ ;;; Change Log: -;; $Id: mh-mime.el,v 1.100 2003/01/25 19:18:51 satyaki Exp $ - ;;; Code: (require 'cl) @@ -58,6 +56,7 @@ (autoload 'mml-insert-empty-tag "mml") (autoload 'mml-to-mime "mml") (autoload 'mml-attach-file "mml") +(autoload 'rfc2047-decode-region "rfc2047") ;;;###mh-autoload (defun mh-compose-insertion (&optional inline) @@ -235,7 +234,6 @@ The file specified by FILENAME is encoded as TYPE. An optional DESCRIPTION is used as the Content-Description field, optional set of ATTRIBUTES and an optional COMMENT can also be included." - (setq mh-mhn-compose-insert-flag t) (beginning-of-line) (insert "#" type) (and attributes @@ -306,7 +304,6 @@ EXTRA-PARAMS, and COMMENT. See also \\[mh-edit-mhn]." - (setq mh-mhn-compose-insert-flag t) (beginning-of-line) (insert "#@" type) (and attributes @@ -341,7 +338,6 @@ (if mh-sent-from-msg (format " [%d]" mh-sent-from-msg) ""))))) - (setq mh-mhn-compose-insert-flag t) (beginning-of-line) (insert "#forw [") (and description @@ -368,7 +364,8 @@ already inserted in the draft, fills in all the MIME components and header fields. -This step should be done last just before sending the message. +This step is performed automatically when sending the message, but this +function may be called manually before sending the draft as well. The `\\[mh-revert-mhn-edit]' command undoes this command. The arguments in the list `mh-mhn-args' are passed to mhn if this function is passed an optional @@ -379,8 +376,7 @@ from a file), \\[mh-mhn-compose-anon-ftp] (external reference to file via anonymous ftp), \\[mh-mhn-compose-external-compressed-tar] \ \(reference to compressed tar file via anonymous ftp), and \\[mh-mhn-compose-forw] (forward -message). If these helper functions are used, `mh-edit-mhn' is run -automatically when the draft is sent. +message). The value of `mh-edit-mhn-hook' is a list of functions to be called, with no arguments, after performing the conversion. @@ -396,7 +392,6 @@ (t (mh-exec-cmd-error (format "mhdraft=%s" buffer-file-name) "mhn" (if extra-args mh-mhn-args) buffer-file-name))) - (setq mh-mhn-compose-insert-flag nil) (revert-buffer t t) (message "mhn editing...done") (run-hooks 'mh-edit-mhn-hook)) @@ -429,18 +424,35 @@ (insert-file-contents backup-file)) (after-find-file nil))) +;;;###mh-autoload +(defun mh-mhn-directive-present-p () + "Check if the current buffer has text which might be a MHN directive." + (save-excursion + (block 'search-for-mhn-directive + (goto-char (point-min)) + (while (re-search-forward "^#" nil t) + (let ((s (buffer-substring-no-properties (point) (line-end-position)))) + (cond ((equal s "")) + ((string-match "^forw[ \t\n]+" s) + (return-from 'search-for-mhn-directive t)) + (t (let ((first-token (car (split-string s "[ \t;@]")))) + (when (string-match mh-media-type-regexp first-token) + (return-from 'search-for-mhn-directive t))))))) + nil))) + ;;; MIME composition functions ;;;###mh-autoload (defun mh-mml-to-mime () - "Compose MIME message from mml directives." + "Compose MIME message from mml directives. +This step is performed automatically when sending the message, but this +function may be called manually before sending the draft as well." (interactive) (when mh-gnus-pgp-support-flag ;; This is only needed for PGP (message-options-set-recipient)) - (mml-to-mime) - (setq mh-mml-compose-insert-flag nil)) + (mml-to-mime)) ;;;###mh-autoload (defun mh-mml-forward-message (description folder message) @@ -460,8 +472,7 @@ (mml-attach-file (format "%s%s/%d" mh-user-path (substring folder 1) msg) "message/rfc822" - description)) - (setq mh-mml-compose-insert-flag t)) + description))) (t (error "The message number, %s is not a integer!" msg))))) ;;;###mh-autoload @@ -488,8 +499,7 @@ nil t nil nil "attachment")))) (mml-insert-empty-tag 'part 'type type 'filename file - 'disposition dispos 'description description) - (setq mh-mml-compose-insert-flag t))) + 'disposition dispos 'description description))) ;;;###mh-autoload (defun mh-mml-secure-message-sign-pgpmime () @@ -497,8 +507,7 @@ (interactive) (if (not mh-gnus-pgp-support-flag) (error "Sorry. Your version of gnus does not support PGP/GPG") - (mml-secure-message-sign-pgpmime) - (setq mh-mml-compose-insert-flag t))) + (mml-secure-message-sign-pgpmime))) ;;;###mh-autoload (defun mh-mml-secure-message-encrypt-pgpmime (&optional dontsign) @@ -507,8 +516,16 @@ (interactive "P") (if (not mh-gnus-pgp-support-flag) (error "Sorry. Your version of gnus does not support PGP/GPG") - (mml-secure-message-encrypt-pgpmime dontsign) - (setq mh-mml-compose-insert-flag t))) + (mml-secure-message-encrypt-pgpmime dontsign))) + +;;;###mh-autoload +(defun mh-mml-directive-present-p () + "Check if the current buffer has text which may be an MML directive." + (save-excursion + (goto-char (point-min)) + (re-search-forward + "\\(<#part\\(.\\|\n\\)*>[ \n\t]*<#/part>\\|^<#secure.+>$\\)" + nil t))) @@ -547,6 +564,8 @@ (mh-defun-compat mm-handle-multipart-ctl-parameter (handle parameter) (get-text-property 0 parameter (car handle))) +(mh-do-in-xemacs (defvar default-enable-multibyte-characters)) + ;; Copy of original function in mm-decode.el (mh-defun-compat mm-readable-p (handle) "Say whether the content of HANDLE is readable." @@ -610,8 +629,7 @@ "Free the decoded MIME parts." (let ((mime-data (gethash (current-buffer) mh-globals-hash))) ;; This is for Emacs, what about XEmacs? - (cond ((fboundp 'remove-images) - (remove-images (point-min) (point-max)))) + (mh-funcall-if-exists remove-images (point-min) (point-max)) (when mime-data (mm-destroy-parts (mh-mime-handles mime-data)) (remhash (current-buffer) mh-globals-hash)))) @@ -662,6 +680,7 @@ (when (and mh-graphical-smileys-flag (fboundp 'smiley-region) (boundp 'font-lock-maximum-size) + font-lock-maximum-size (>= (/ font-lock-maximum-size 8) (buffer-size))) (smiley-region (point-min) (point-max)))) @@ -669,8 +688,8 @@ (defun mh-display-emphasis () "Function to display graphical emphasis." (when (and mh-graphical-emphasis-flag - (boundp 'font-lock-maximum-size) - (>= (/ font-lock-maximum-size 8) (buffer-size))) + (if font-lock-maximum-size + (>= (/ font-lock-maximum-size 8) (buffer-size)))) (flet ((article-goto-body ())) ; shadow this function to do nothing (save-excursion (goto-char (point-min)) @@ -685,7 +704,10 @@ (unless (>= (string-to-number emacs-version) 21) ;; XEmacs doesn't care. (set-keymap-parent map mh-show-mode-map)) - (define-key map [mouse-2] 'mh-push-button) + (mh-do-in-gnu-emacs + (define-key map [mouse-2] 'mh-push-button)) + (mh-do-in-xemacs + (define-key map '(button2) 'mh-push-button)) (dolist (c mh-mime-button-commands) (define-key map (cadr c) (car c))) map)) @@ -708,7 +730,10 @@ (unless (>= (string-to-number emacs-version) 21) (set-keymap-parent map mh-show-mode-map)) (define-key map "\r" 'mh-press-button) - (define-key map [mouse-2] 'mh-push-button) + (mh-do-in-gnu-emacs + (define-key map [mouse-2] 'mh-push-button)) + (mh-do-in-xemacs + (define-key map '(button2) 'mh-push-button)) map)) (defvar mh-mime-save-parts-directory nil @@ -755,22 +780,46 @@ (if (equal nil mh-mime-save-parts-default-directory) (setq mh-mime-save-parts-directory directory)) (save-excursion - (set-buffer (get-buffer-create " *mh-store*")) + (set-buffer (get-buffer-create mh-log-buffer)) (cd directory) (setq mh-mime-save-parts-directory directory) - (erase-buffer) - (apply 'call-process - (expand-file-name command mh-progs) nil t nil - (mh-list-to-string (list folder msg "-auto"))) - (if (> (buffer-size) 0) - (save-window-excursion - (switch-to-buffer-other-window " *mh-store*") - (sit-for 3))))))) + (let ((initial-size (mh-truncate-log-buffer))) + (apply 'call-process + (expand-file-name command mh-progs) nil t nil + (mh-list-to-string (list folder msg "-auto"))) + (if (> (buffer-size) initial-size) + (save-window-excursion + (switch-to-buffer-other-window mh-log-buffer) + (sit-for 3)))))))) ;; Avoid errors if gnus-sum isn't loaded yet... (defvar gnus-newsgroup-charset nil) (defvar gnus-newsgroup-name nil) +(defun mh-decode-message-body () + "Decode message based on charset. +If message has been encoded for transfer take that into account." + (let* ((ct (ignore-errors (mail-header-parse-content-type + (message-fetch-field "Content-Type" t)))) + (charset (mail-content-type-get ct 'charset)) + (cte (message-fetch-field "Content-Transfer-Encoding"))) + (when (stringp cte) (setq cte (mail-header-strip cte))) + (when (or (not ct) (equal (car ct) "text/plain")) + (save-restriction + (narrow-to-region (min (1+ (mh-mail-header-end)) (point-max)) + (point-max)) + (mm-decode-body charset + (and cte (intern (downcase + (gnus-strip-whitespace cte)))) + (car ct)))))) + +;;;###mh-autoload +(defun mh-decode-message-header () + "Decode RFC2047 encoded message header fields." + (when mh-decode-mime-flag + (let ((buffer-read-only nil)) + (rfc2047-decode-region (point-min) (mh-mail-header-end))))) + ;;;###mh-autoload (defun mh-mime-display (&optional pre-dissected-handles) "Display (and possibly decode) MIME handles. @@ -778,36 +827,43 @@ present they are displayed otherwise the buffer is parsed and then displayed." (let ((handles ()) - (folder mh-show-folder-buffer)) + (folder mh-show-folder-buffer) + (raw-message-data (buffer-string))) (flet ((mm-handle-set-external-undisplayer (handle function) (mh-handle-set-external-undisplayer folder handle function))) - ;; If needed dissect the current buffer - (if pre-dissected-handles - (setq handles pre-dissected-handles) - (setq handles (or (mm-dissect-buffer nil) (mm-uu-dissect))) - (setf (mh-mime-handles (mh-buffer-data)) - (mm-merge-handles handles (mh-mime-handles (mh-buffer-data)))) + (goto-char (point-min)) + (unless (search-forward "\n\n" nil t) + (goto-char (point-max)) + (insert "\n\n")) + + (condition-case err + (progn + ;; If needed dissect the current buffer + (if pre-dissected-handles + (setq handles pre-dissected-handles) + (setq handles (or (mm-dissect-buffer nil) (mm-uu-dissect))) + (setf (mh-mime-handles (mh-buffer-data)) + (mm-merge-handles handles + (mh-mime-handles (mh-buffer-data)))) + (unless handles (mh-decode-message-body))) - ;; Use charset to decode body... - (unless handles - (let* ((ct (ignore-errors - (mail-header-parse-content-type - (message-fetch-field "Content-Type" t)))) - (charset (mail-content-type-get ct 'charset))) - (when (stringp charset) - (mm-decode-body charset))))) + (when (and handles + (or (not (stringp (car handles))) (cdr handles))) + ;; Goto start of message body + (goto-char (point-min)) + (or (search-forward "\n\n" nil t) (goto-char (point-max))) - (when (and handles (or (not (stringp (car handles))) (cdr handles))) - ;; Goto start of message body - (goto-char (point-min)) - (or (search-forward "\n\n" nil t) (goto-char (point-max))) + ;; Delete the body + (delete-region (point) (point-max)) - ;; Delete the body - (delete-region (point) (point-max)) - - ;; Display the MIME handles - (mh-mime-display-part handles))))) + ;; Display the MIME handles + (mh-mime-display-part handles))) + (error + (message "Please report this error. The error message is:\n %s" + (error-message-string err)) + (delete-region (point-min) (point-max)) + (insert raw-message-data)))))) (defun mh-mime-display-part (handle) "Decides the viewer to call based on the type of HANDLE." @@ -868,7 +924,8 @@ (let* ((image (mm-get-image handle))) (cond ((fboundp 'glyph-width) ;; XEmacs -- totally untested, copied from gnus - (and (< (glyph-width image) + (and (mh-funcall-if-exists glyphp image) + (< (glyph-width image) (or mh-max-inline-image-width (window-pixel-width))) (< (glyph-height image) @@ -876,8 +933,9 @@ (window-pixel-height))))) ((fboundp 'image-size) ;; Emacs21 -- copied from gnus - (let ((size (image-size image))) - (and (< (cdr size) + (let ((size (mh-funcall-if-exists image-size image))) + (and size + (< (cdr size) (or mh-max-inline-image-height (1- (window-height)))) (< (car size) @@ -889,7 +947,8 @@ (defun mh-inline-vcard-p (handle) "Decide if HANDLE is a vcard that must be displayed inline." (let ((type (mm-handle-type handle))) - (and (consp type) + (and (or (featurep 'vcard) (fboundp 'vcard-pretty-print)) + (consp type) (equal (car type) "text/x-vcard") (save-excursion (save-restriction @@ -933,6 +992,10 @@ (mh-mm-display-part handle))) (goto-char (point-max))))) +(mh-do-in-xemacs + (defvar dots) + (defvar type)) + (defun mh-insert-mime-button (handle index displayed) "Insert MIME button for HANDLE. INDEX is the part number that will be DISPLAYED. It is also used by commands @@ -999,9 +1062,9 @@ (progn ;; Delete the button and displayed part (if any) (let ((region (get-text-property point 'mh-region))) - (when region - (when (fboundp 'remove-images) - (remove-images (car region) (cdr region)))) + (when (and region (fboundp 'remove-images)) + (mh-funcall-if-exists + remove-images (car region) (cdr region))) (mm-display-part handle) (when region (delete-region (car region) (cdr region)))) @@ -1067,20 +1130,33 @@ displayed. This function is called when the mouse is used to click the MIME button." (interactive "e") - (set-buffer (window-buffer (posn-window (event-start event)))) - (select-window (posn-window (event-start event))) - (let* ((pos (posn-point (event-start event))) - (folder mh-show-folder-buffer) - (mm-inline-media-tests mh-mm-inline-media-tests) - (data (get-text-property pos 'mh-data)) - (function (get-text-property pos 'mh-callback)) - (buffer-read-only nil)) - (flet ((mm-handle-set-external-undisplayer - (handle function) - (mh-handle-set-external-undisplayer folder handle function))) - (goto-char pos) - (unwind-protect (and function (funcall function data)) - (set-buffer-modified-p nil))))) + (save-excursion + (let* ((event-window + (or (mh-funcall-if-exists posn-window (event-start event));GNU Emacs + (mh-funcall-if-exists event-window event))) ;XEmacs + (event-position + (or (mh-funcall-if-exists posn-point (event-start event)) ;GNU Emacs + (mh-funcall-if-exists event-closest-point event))) ;XEmacs + (original-window (selected-window)) + (original-position (progn + (set-buffer (window-buffer event-window)) + (set-marker (make-marker) (point)))) + (folder mh-show-folder-buffer) + (mm-inline-media-tests mh-mm-inline-media-tests) + (data (get-text-property event-position 'mh-data)) + (function (get-text-property event-position 'mh-callback)) + (buffer-read-only nil)) + (unwind-protect + (progn + (select-window event-window) + (flet ((mm-handle-set-external-undisplayer (handle func) + (mh-handle-set-external-undisplayer folder handle func))) + (goto-char event-position) + (and function (funcall function data)))) + (set-buffer-modified-p nil) + (goto-char original-position) + (set-marker original-position nil) + (select-window original-window))))) ;;;###mh-autoload (defun mh-mime-save-part () @@ -1242,6 +1318,7 @@ handles)))) (goto-char (point-min)) + (mh-show-xface) (cond (clean-message-header (mh-clean-msg-header (point-min) invisible-headers @@ -1249,7 +1326,7 @@ (goto-char (point-min))) (t (mh-start-of-uncleaned-message))) - (mh-show-xface) + (mh-decode-message-header) (mh-show-addr) ;; The other highlighting types don't need anything special (when (eq mh-highlight-citation-p 'gnus)