# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: kdo@cosmos.phy.tufts.edu-20131227194350-\ # g3o5h6bnyg8yntf2 # target_branch: bzr://bzr.savannah.gnu.org/emacs/trunk/ # testament_sha1: dc810978fb73db2f3fdc77450d771642e5e60cfb # timestamp: 2013-12-27 14:44:04 -0500 # source_branch: rmail # base_revision_id: eggert@cs.ucla.edu-20131227191410-z9ibc5kpdv0wj3ub # # Begin patch === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2013-12-27 15:43:54 +0000 +++ lisp/ChangeLog 2013-12-27 19:28:08 +0000 @@ -1,3 +1,19 @@ +2013-12-27 Ken Olum + + * mail/rmail.el (rmail-mime-process): Handle text/html + separately from other text/ types. Suppress tagline for + multipart body. + (rmail-mime-parse): Don't change visibility of tagline here. + (rmail-mime-set-bulk-data, rmail-mime-insert-bulk): + Handle text/html specially. + (rmail-mime-render-html-function): New variable. + (rmail-mime-insert-html, rmail-mime-render-html-shr) + (rmail-mime-render-html-lynx): New functions. + (rmail-mime-fix-inserted-faces): New function. + (rmail-mime-searching): New variable. + (rmail-search-mime-message): Bind rmail-mime-searching to + suppress rendering while searching. + 2013-12-27 Lars Ingebrigtsen * net/shr.el (shr-insert): Don't infloop if the width is zero. === modified file 'lisp/mail/rmail.el' --- lisp/mail/rmail.el 2013-10-30 16:29:36 +0000 +++ lisp/mail/rmail.el 2013-12-27 19:28:08 +0000 @@ -4668,7 +4668,7 @@ ;;;*** -;;;### (autoloads nil "rmailmm" "rmailmm.el" "8c14f4cf6e7dacb0c94fd300d814caf7") +;;;### (autoloads nil "rmailmm" "rmailmm.el" "9ac7864956507a43015757329f12895a") ;;; Generated autoloads from rmailmm.el (autoload 'rmail-mime "rmailmm" "\ === modified file 'lisp/mail/rmailmm.el' --- lisp/mail/rmailmm.el 2013-09-18 03:47:11 +0000 +++ lisp/mail/rmailmm.el 2013-12-27 19:28:08 +0000 @@ -131,6 +131,17 @@ :version "23.2" :group 'rmail-mime) +(defcustom rmail-mime-render-html-function + (cond ((fboundp 'libxml-parse-html-region) 'rmail-mime-render-html-shr) + ((executable-find "lynx") 'rmail-mime-render-html-lynx) + (t nil)) + "Function to convert HTML to text. Called with buffer containing HTML +extracted from message in a temporary buffer. Converts to text in current +buffer. If NIL, display HTML source." + :group 'rmail + :version "24.4" + :type '(choice function (const nil))) + ;;; End of user options. ;;; Global variables that always have let-binding when referred. @@ -150,6 +161,10 @@ The value is usually nil, and bound to non-nil while inserting MIME entities.") +(defvar rmail-mime-searching nil + "Bound to T inside `rmail-search-mime-message' to suppress expensive +operations such as HTML decoding") + ;;; MIME-entity object (defun rmail-mime-entity (type disposition transfer-encoding @@ -636,6 +651,57 @@ (insert-image (create-image data (cdr bulk-data) t)) (insert "\n"))) +(defun rmail-mime-insert-html (entity) + "Decode, render, and insert html from MIME-entity ENTITY." + (let ((body (rmail-mime-entity-body entity)) + (transfer-encoding (rmail-mime-entity-transfer-encoding entity)) + (buffer (current-buffer))) + (with-temp-buffer + (set-buffer-multibyte nil) + (setq buffer-undo-list t) + (insert-buffer-substring rmail-mime-mbox-buffer + (aref body 0) (aref body 1)) + (cond ((string= transfer-encoding "base64") + (ignore-errors (base64-decode-region (point-min) (point-max)))) + ((string= transfer-encoding "quoted-printable") + (quoted-printable-decode-region (point-min) (point-max)))) + ;; Convert html in temporary buffer to text and insert in original buffer + (let ((source-buffer (current-buffer))) + (with-current-buffer buffer + (let ((start (point))) + (if rmail-mime-render-html-function + (funcall rmail-mime-render-html-function source-buffer) + (insert-buffer-substring source-buffer)) + (rmail-mime-fix-inserted-faces start))))))) + +(defun rmail-mime-render-html-shr (source-buffer) + (let ((dom (with-current-buffer source-buffer + (libxml-parse-html-region (point-min) (point-max)))) + ;; Image retrieval happens asynchronously, but meanwhile + ;; `rmail-swap-buffers' may have been run, leaving + ;; `shr-image-fetched' trying to insert the image in the wrong buffer. + (shr-inhibit-images t)) + (shr-insert-document dom))) + +(defun rmail-mime-render-html-lynx (source-buffer) + (let ((destination-buffer (current-buffer))) + (with-current-buffer source-buffer + (call-process-region (point-min) (point-max) + "lynx" nil destination-buffer nil + "-stdin" "-dump" "-force_html" + "-dont_wrap_pre" "-width=70")))) + +;; Put font-lock-face properties matching face properties on text +;; inserted, e.g., by shr, in text from START to point. +(defun rmail-mime-fix-inserted-faces (start) + (while (< start (point)) + (let ((face (get-text-property start 'face)) + (next (next-single-property-change + start 'face (current-buffer) (point)))) + (if face ; anything to do? + (put-text-property start next 'font-lock-face face)) + (setq start next)))) + (defun rmail-mime-toggle-button (button) "Hide or show the body of the MIME-entity associated with BUTTON." (save-excursion @@ -680,6 +746,8 @@ (setq size (/ (* size 7) 3))))))) (cond + ((string-match "text/html" content-type) + (setq type 'html)) ((string-match "text/" content-type) (setq type 'text)) ((string-match "image/\\(.*\\)" content-type) @@ -789,6 +857,12 @@ (if (rmail-mime-display-body new) (cond ((eq (cdr bulk-data) 'text) (rmail-mime-insert-decoded-text entity)) + ((eq (cdr bulk-data) 'html) + ;; Render HTML if display single message, but if searching + ;; don't render but just search HTML itself. + (if rmail-mime-searching + (rmail-mime-insert-decoded-text entity) + (rmail-mime-insert-html entity))) ((cdr bulk-data) (rmail-mime-insert-image entity)) (t @@ -1119,6 +1193,8 @@ (cond ((string-match "multipart/.*" (car content-type)) (save-restriction (narrow-to-region (1- end) (point-max)) + (if (zerop (length parse-tag)) ; top level of message + (aset new 1 (aset tagline 2 nil))) ; don't show tagline (setq children (rmail-mime-process-multipart content-type content-disposition @@ -1139,6 +1215,12 @@ (aset (rmail-mime-entity-tagline msg) 2 nil) (setq children (list msg) handler 'rmail-mime-insert-multipart)))) + ((and is-inline (string-match "text/html" (car content-type))) + ;; Display tagline, so part can be detached + (aset new 1 (aset tagline 2 t)) + (aset new 2 (aset body 2 t)) ; display body also. + (setq handler 'rmail-mime-insert-bulk)) + ;; Inline non-HTML text ((and is-inline (string-match "text/" (car content-type))) ;; Don't need a tagline. (aset new 1 (aset tagline 2 nil)) @@ -1191,10 +1273,6 @@ (new (aref (rmail-mime-entity-display entity) 1))) ;; Show header. (aset new 0 (aset (rmail-mime-entity-header entity) 2 t)) - ;; Show tagline if and only if body is not shown. - (if (aref new 2) - (aset new 1 (aset (rmail-mime-entity-tagline entity) 2 nil)) - (aset new 1 (aset (rmail-mime-entity-tagline entity) 2 t))) entity))) (error (format "%s" err))))) @@ -1395,7 +1473,8 @@ "Function to set in `rmail-search-mime-message-function' (which see)." (save-restriction (narrow-to-region (rmail-msgbeg msg) (rmail-msgend msg)) - (let* ((rmail-mime-mbox-buffer (current-buffer)) + (let* ((rmail-mime-searching t) ; mark inside search + (rmail-mime-mbox-buffer (current-buffer)) (rmail-mime-view-buffer rmail-view-buffer) (header-end (save-excursion (re-search-forward "^$" nil 'move) (point))) # Begin bundle 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