--- /dev/null
+Return-Path: <markwalters1009@gmail.com>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by olra.theworths.org (Postfix) with ESMTP id 0B1CB431FD8\r
+ for <notmuch@notmuchmail.org>; Wed, 5 Jun 2013 09:24:13 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0.224\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0.224 tagged_above=-999 required=5\r
+ tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,\r
+ FREEMAIL_ENVFROM_END_DIGIT=1, FREEMAIL_FROM=0.001,\r
+ HS_INDEX_PARAM=0.023, RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+ by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id xujJgItUg2nQ for <notmuch@notmuchmail.org>;\r
+ Wed, 5 Jun 2013 09:24:00 -0700 (PDT)\r
+Received: from mail-wi0-f175.google.com (mail-wi0-f175.google.com\r
+ [209.85.212.175]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
+ (No client certificate requested)\r
+ by olra.theworths.org (Postfix) with ESMTPS id 51A04431FB6\r
+ for <notmuch@notmuchmail.org>; Wed, 5 Jun 2013 09:23:57 -0700 (PDT)\r
+Received: by mail-wi0-f175.google.com with SMTP id hn14so4994170wib.8\r
+ for <notmuch@notmuchmail.org>; Wed, 05 Jun 2013 09:23:56 -0700 (PDT)\r
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;\r
+ h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references;\r
+ bh=hKWwxBUR1hAlUagUlVrOWYvy1g8/CJe4Q7fzDgvJOS0=;\r
+ b=bekF8Pc2Ud/R5lvIhohatvlrgLbwS7yzmMjDt51rUaAsvtu2ZNmqcqvak45dESdJji\r
+ VcRQ3TNKGy9FltXkOjN4ebvG+7vl9Fvs6zyQmzIFVuo2UykuXtF4vhlqTEM0HvXQEDvG\r
+ dVfqezByfjdApWAwfL8z0gol5esui1m1+26J338hecmrtQb8eNXdKvyixVNHtqYFgcPO\r
+ 15lTtB6QZCmbbCeCNXSyDLKPr1eS0B8hStohYyvWLN4+n4bn+YAu65bFjAPU0+RY55ir\r
+ jaWb79/KN/6/LGWuujBQ1zZ6HD9dFZzhO4tkrIHxxtJBFP/Y14nwBiwfk5G7br/xC4fr\r
+ u1qA==\r
+X-Received: by 10.180.184.101 with SMTP id et5mr7366942wic.45.1370449436197;\r
+ Wed, 05 Jun 2013 09:23:56 -0700 (PDT)\r
+Received: from localhost (93-97-24-31.zone5.bethere.co.uk. [93.97.24.31])\r
+ by mx.google.com with ESMTPSA id\r
+ fu14sm11487953wic.0.2013.06.05.09.23.54 for <multiple recipients>\r
+ (version=TLSv1.2 cipher=RC4-SHA bits=128/128);\r
+ Wed, 05 Jun 2013 09:23:55 -0700 (PDT)\r
+From: Mark Walters <markwalters1009@gmail.com>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH 2/2] insert forest moved\r
+Date: Wed, 5 Jun 2013 17:23:46 +0100\r
+Message-Id: <1370449426-2325-3-git-send-email-markwalters1009@gmail.com>\r
+X-Mailer: git-send-email 1.7.9.1\r
+In-Reply-To: <1370449426-2325-1-git-send-email-markwalters1009@gmail.com>\r
+References: <1370449426-2325-1-git-send-email-markwalters1009@gmail.com>\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Wed, 05 Jun 2013 16:24:13 -0000\r
+\r
+---\r
+ emacs/notmuch-show-display.el | 704 ++++++++++++++++++++++++++++++++++++++++-\r
+ emacs/notmuch-show.el | 692 ----------------------------------------\r
+ 2 files changed, 703 insertions(+), 693 deletions(-)\r
+\r
+diff --git a/emacs/notmuch-show-display.el b/emacs/notmuch-show-display.el\r
+index 50d83ad..82678c2 100644\r
+--- a/emacs/notmuch-show-display.el\r
++++ b/emacs/notmuch-show-display.el\r
+@@ -21,5 +21,707 @@\r
+ ;; Authors: Carl Worth <cworth@cworth.org>\r
+ ;; David Edmondson <dme@dme.org>\r
+ \r
++(require 'mm-view)\r
++(require 'message)\r
++(require 'mm-decode)\r
++(require 'mailcap)\r
+ \r
+-(provide 'notmuch-show-display)\r
+\ No newline at end of file\r
++(require 'notmuch-lib)\r
++(require 'notmuch-tag)\r
++(require 'notmuch-wash)\r
++(require 'notmuch-crypto)\r
++\r
++(declare-function notmuch-show-get-header "notmuch-show" (header &optional props))\r
++(declare-function notmuch-show-set-message-properties "notmuch-show" (props))\r
++(declare-function notmuch-show-set-prop "notmuch-show" (prop val &optional props))\r
++\r
++(defcustom notmuch-message-headers '("Subject" "To" "Cc" "Date")\r
++ "Headers that should be shown in a message, in this order.\r
++\r
++For an open message, all of these headers will be made visible\r
++according to `notmuch-message-headers-visible' or can be toggled\r
++with `notmuch-show-toggle-visibility-headers'. For a closed message,\r
++only the first header in the list will be visible."\r
++ :type '(repeat string)\r
++ :group 'notmuch-show)\r
++\r
++(defcustom notmuch-message-headers-visible t\r
++ "Should the headers be visible by default?\r
++\r
++If this value is non-nil, then all of the headers defined in\r
++`notmuch-message-headers' will be visible by default in the display\r
++of each message. Otherwise, these headers will be hidden and\r
++`notmuch-show-toggle-visibility-headers' can be used to make them\r
++visible for any given message."\r
++ :type 'boolean\r
++ :group 'notmuch-show)\r
++\r
++(defcustom notmuch-show-relative-dates t\r
++ "Display relative dates in the message summary line."\r
++ :type 'boolean\r
++ :group 'notmuch-show)\r
++\r
++(defvar notmuch-show-markup-headers-hook '(notmuch-show-colour-headers)\r
++ "A list of functions called to decorate the headers listed in\r
++`notmuch-message-headers'.")\r
++\r
++(defcustom notmuch-show-insert-text/plain-hook '(notmuch-wash-wrap-long-lines\r
++ notmuch-wash-tidy-citations\r
++ notmuch-wash-elide-blank-lines\r
++ notmuch-wash-excerpt-citations)\r
++ "Functions used to improve the display of text/plain parts."\r
++ :type 'hook\r
++ :options '(notmuch-wash-convert-inline-patch-to-part\r
++ notmuch-wash-wrap-long-lines\r
++ notmuch-wash-tidy-citations\r
++ notmuch-wash-elide-blank-lines\r
++ notmuch-wash-excerpt-citations)\r
++ :group 'notmuch-show\r
++ :group 'notmuch-hooks)\r
++\r
++;; Mostly useful for debugging.\r
++(defcustom notmuch-show-all-multipart/alternative-parts nil\r
++ "Should all parts of multipart/alternative parts be shown?"\r
++ :type 'boolean\r
++ :group 'notmuch-show)\r
++\r
++(defcustom notmuch-show-indent-messages-width 1\r
++ "Width of message indentation in threads.\r
++\r
++Messages are shown indented according to their depth in a thread.\r
++This variable determines the width of this indentation measured\r
++in number of blanks. Defaults to `1', choose `0' to disable\r
++indentation."\r
++ :type 'integer\r
++ :group 'notmuch-show)\r
++\r
++(defcustom notmuch-show-indent-multipart nil\r
++ "Should the sub-parts of a multipart/* part be indented?"\r
++ ;; dme: Not sure which is a good default.\r
++ :type 'boolean\r
++ :group 'notmuch-show)\r
++\r
++(defvar notmuch-show-process-crypto nil)\r
++(make-variable-buffer-local 'notmuch-show-process-crypto)\r
++(put 'notmuch-show-process-crypto 'permanent-local t)\r
++\r
++(defvar notmuch-show-indent-content t)\r
++(make-variable-buffer-local 'notmuch-show-indent-content)\r
++(put 'notmuch-show-indent-content 'permanent-local t)\r
++\r
++(defun notmuch-show-fontify-header ()\r
++ (let ((face (cond\r
++ ((looking-at "[Tt]o:")\r
++ 'message-header-to)\r
++ ((looking-at "[Bb]?[Cc][Cc]:")\r
++ 'message-header-cc)\r
++ ((looking-at "[Ss]ubject:")\r
++ 'message-header-subject)\r
++ ((looking-at "[Ff]rom:")\r
++ 'message-header-from)\r
++ (t\r
++ 'message-header-other))))\r
++\r
++ (overlay-put (make-overlay (point) (re-search-forward ":"))\r
++ 'face 'message-header-name)\r
++ (overlay-put (make-overlay (point) (re-search-forward ".*$"))\r
++ 'face face)))\r
++\r
++(defun notmuch-show-colour-headers ()\r
++ "Apply some colouring to the current headers."\r
++ (goto-char (point-min))\r
++ (while (looking-at "^[A-Za-z][-A-Za-z0-9]*:")\r
++ (notmuch-show-fontify-header)\r
++ (forward-line)))\r
++\r
++(defun notmuch-show-spaces-n (n)\r
++ "Return a string comprised of `n' spaces."\r
++ (make-string n ? ))\r
++\r
++(defun notmuch-clean-address (address)\r
++ "Try to clean a single email ADDRESS for display. Return a cons\r
++cell of (AUTHOR_EMAIL AUTHOR_NAME). Return (ADDRESS nil) if\r
++parsing fails."\r
++ (condition-case nil\r
++ (let (p-name p-address)\r
++ ;; It would be convenient to use `mail-header-parse-address',\r
++ ;; but that expects un-decoded mailbox parts, whereas our\r
++ ;; mailbox parts are already decoded (and hence may contain\r
++ ;; UTF-8). Given that notmuch should handle most of the awkward\r
++ ;; cases, some simple string deconstruction should be sufficient\r
++ ;; here.\r
++ (cond\r
++ ;; "User <user@dom.ain>" style.\r
++ ((string-match "\\(.*\\) <\\(.*\\)>" address)\r
++ (setq p-name (match-string 1 address)\r
++ p-address (match-string 2 address)))\r
++\r
++ ;; "<user@dom.ain>" style.\r
++ ((string-match "<\\(.*\\)>" address)\r
++ (setq p-address (match-string 1 address)))\r
++\r
++ ;; Everything else.\r
++ (t\r
++ (setq p-address address)))\r
++\r
++ (when p-name\r
++ ;; Remove elements of the mailbox part that are not relevant for\r
++ ;; display, even if they are required during transport:\r
++ ;;\r
++ ;; Backslashes.\r
++ (setq p-name (replace-regexp-in-string "\\\\" "" p-name))\r
++\r
++ ;; Outer single and double quotes, which might be nested.\r
++ (loop\r
++ with start-of-loop\r
++ do (setq start-of-loop p-name)\r
++\r
++ when (string-match "^\"\\(.*\\)\"$" p-name)\r
++ do (setq p-name (match-string 1 p-name))\r
++\r
++ when (string-match "^'\\(.*\\)'$" p-name)\r
++ do (setq p-name (match-string 1 p-name))\r
++\r
++ until (string= start-of-loop p-name)))\r
++\r
++ ;; If the address is 'foo@bar.com <foo@bar.com>' then show just\r
++ ;; 'foo@bar.com'.\r
++ (when (string= p-name p-address)\r
++ (setq p-name nil))\r
++\r
++ (cons p-address p-name))\r
++ (error (cons address nil))))\r
++\r
++(defun notmuch-show-clean-address (address)\r
++ "Try to clean a single email ADDRESS for display. Return\r
++unchanged ADDRESS if parsing fails."\r
++ (let* ((clean-address (notmuch-clean-address address))\r
++ (p-address (car clean-address))\r
++ (p-name (cdr clean-address)))\r
++ ;; If no name, return just the address.\r
++ (if (not p-name)\r
++ p-address\r
++ ;; Otherwise format the name and address together.\r
++ (concat p-name " <" p-address ">"))))\r
++\r
++(defun notmuch-show-insert-headerline (headers date tags depth)\r
++ "Insert a notmuch style headerline based on HEADERS for a\r
++message at DEPTH in the current thread."\r
++ (let ((start (point)))\r
++ (insert (notmuch-show-spaces-n (* notmuch-show-indent-messages-width depth))\r
++ (notmuch-show-clean-address (plist-get headers :From))\r
++ " ("\r
++ date\r
++ ") ("\r
++ (notmuch-tag-format-tags tags)\r
++ ")\n")\r
++ (overlay-put (make-overlay start (point)) 'face 'notmuch-message-summary-face)))\r
++\r
++(defun notmuch-show-insert-header (header header-value)\r
++ "Insert a single header."\r
++ (insert header ": " header-value "\n"))\r
++\r
++(defun notmuch-show-insert-headers (headers)\r
++ "Insert the headers of the current message."\r
++ (let ((start (point)))\r
++ (mapc (lambda (header)\r
++ (let* ((header-symbol (intern (concat ":" header)))\r
++ (header-value (plist-get headers header-symbol)))\r
++ (if (and header-value\r
++ (not (string-equal "" header-value)))\r
++ (notmuch-show-insert-header header header-value))))\r
++ notmuch-message-headers)\r
++ (save-excursion\r
++ (save-restriction\r
++ (narrow-to-region start (point-max))\r
++ (run-hooks 'notmuch-show-markup-headers-hook)))))\r
++\r
++(defun notmuch-show-insert-part-header (nth content-type declared-type &optional name comment)\r
++ (let ((button)\r
++ (base-label (concat (when name (concat name ": "))\r
++ declared-type\r
++ (unless (string-equal declared-type content-type)\r
++ (concat " (as " content-type ")"))\r
++ comment)))\r
++\r
++ (setq button\r
++ (insert-button\r
++ (concat "[ " base-label " ]")\r
++ :base-label base-label\r
++ :type 'notmuch-show-part-button-type\r
++ :notmuch-part nth\r
++ :notmuch-filename name\r
++ :notmuch-content-type content-type))\r
++ (insert "\n")\r
++ ;; return button\r
++ button))\r
++\r
++;; This is taken from notmuch-wash: maybe it should be unified?\r
++(defun notmuch-show-toggle-part-invisibility (&optional button)\r
++ (interactive)\r
++ (let* ((button (or button (button-at (point))))\r
++ (overlay (button-get button 'overlay)))\r
++ (when overlay\r
++ (let* ((show (overlay-get overlay 'invisible))\r
++ (new-start (button-start button))\r
++ (button-label (button-get button :base-label))\r
++ (old-point (point))\r
++ (inhibit-read-only t))\r
++ (overlay-put overlay 'invisible (not show))\r
++ (goto-char new-start)\r
++ (insert "[ " button-label (if show " ]" " (hidden) ]"))\r
++ (let ((old-end (button-end button)))\r
++ (move-overlay button new-start (point))\r
++ (delete-region (point) old-end))\r
++ (goto-char (min old-point (1- (button-end button))))))))\r
++\r
++(defun notmuch-show-multipart/*-to-list (part)\r
++ (mapcar (lambda (inner-part) (plist-get inner-part :content-type))\r
++ (plist-get part :content)))\r
++\r
++(defun notmuch-show-insert-part-multipart/alternative (msg part content-type nth depth declared-type)\r
++ (notmuch-show-insert-part-header nth declared-type content-type nil)\r
++ (let ((chosen-type (car (notmuch-multipart/alternative-choose (notmuch-show-multipart/*-to-list part))))\r
++ (inner-parts (plist-get part :content))\r
++ (start (point)))\r
++ ;; This inserts all parts of the chosen type rather than just one,\r
++ ;; but it's not clear that this is the wrong thing to do - which\r
++ ;; should be chosen if there are more than one that match?\r
++ (mapc (lambda (inner-part)\r
++ (let* ((inner-type (plist-get inner-part :content-type))\r
++ (hide (not (or notmuch-show-all-multipart/alternative-parts\r
++ (string= chosen-type inner-type)))))\r
++ (notmuch-show-insert-bodypart msg inner-part depth hide)))\r
++ inner-parts)\r
++\r
++ (when notmuch-show-indent-multipart\r
++ (indent-rigidly start (point) 1)))\r
++ t)\r
++\r
++(defun notmuch-show-setup-w3m ()\r
++ "Instruct w3m how to retrieve content from a \"related\" part of a message."\r
++ (interactive)\r
++ (if (boundp 'w3m-cid-retrieve-function-alist)\r
++ (unless (assq 'notmuch-show-mode w3m-cid-retrieve-function-alist)\r
++ (push (cons 'notmuch-show-mode 'notmuch-show-w3m-cid-retrieve)\r
++ w3m-cid-retrieve-function-alist)))\r
++ (setq mm-inline-text-html-with-images t))\r
++\r
++(defvar w3m-current-buffer) ;; From `w3m.el'.\r
++(defvar notmuch-show-w3m-cid-store nil)\r
++(make-variable-buffer-local 'notmuch-show-w3m-cid-store)\r
++\r
++(defun notmuch-show-w3m-cid-store-internal (content-id\r
++ message-id\r
++ part-number\r
++ content-type\r
++ content)\r
++ (push (list content-id\r
++ message-id\r
++ part-number\r
++ content-type\r
++ content)\r
++ notmuch-show-w3m-cid-store))\r
++\r
++(defun notmuch-show-w3m-cid-store (msg part)\r
++ (let ((content-id (plist-get part :content-id)))\r
++ (when content-id\r
++ (notmuch-show-w3m-cid-store-internal (concat "cid:" content-id)\r
++ (plist-get msg :id)\r
++ (plist-get part :id)\r
++ (plist-get part :content-type)\r
++ nil))))\r
++\r
++(defun notmuch-show-w3m-cid-retrieve (url &rest args)\r
++ (let ((matching-part (with-current-buffer w3m-current-buffer\r
++ (assoc url notmuch-show-w3m-cid-store))))\r
++ (if matching-part\r
++ (let ((message-id (nth 1 matching-part))\r
++ (part-number (nth 2 matching-part))\r
++ (content-type (nth 3 matching-part))\r
++ (content (nth 4 matching-part)))\r
++ ;; If we don't already have the content, get it and cache\r
++ ;; it, as some messages reference the same cid: part many\r
++ ;; times (hundreds!), which results in many calls to\r
++ ;; `notmuch part'.\r
++ (unless content\r
++ (setq content (notmuch-get-bodypart-internal (notmuch-id-to-query message-id)\r
++ part-number notmuch-show-process-crypto))\r
++ (with-current-buffer w3m-current-buffer\r
++ (notmuch-show-w3m-cid-store-internal url\r
++ message-id\r
++ part-number\r
++ content-type\r
++ content)))\r
++ (insert content)\r
++ content-type)\r
++ nil)))\r
++\r
++(defun notmuch-show-insert-part-multipart/related (msg part content-type nth depth declared-type)\r
++ (notmuch-show-insert-part-header nth declared-type content-type nil)\r
++ (let ((inner-parts (plist-get part :content))\r
++ (start (point)))\r
++\r
++ ;; We assume that the first part is text/html and the remainder\r
++ ;; things that it references.\r
++\r
++ ;; Stash the non-primary parts.\r
++ (mapc (lambda (part)\r
++ (notmuch-show-w3m-cid-store msg part))\r
++ (cdr inner-parts))\r
++\r
++ ;; Render the primary part.\r
++ (notmuch-show-insert-bodypart msg (car inner-parts) depth)\r
++\r
++ (when notmuch-show-indent-multipart\r
++ (indent-rigidly start (point) 1)))\r
++ t)\r
++\r
++(defun notmuch-show-insert-part-multipart/signed (msg part content-type nth depth declared-type)\r
++ (let ((button (notmuch-show-insert-part-header nth declared-type content-type nil)))\r
++ (button-put button 'face 'notmuch-crypto-part-header)\r
++ ;; add signature status button if sigstatus provided\r
++ (if (plist-member part :sigstatus)\r
++ (let* ((from (notmuch-show-get-header :From msg))\r
++ (sigstatus (car (plist-get part :sigstatus))))\r
++ (notmuch-crypto-insert-sigstatus-button sigstatus from))\r
++ ;; if we're not adding sigstatus, tell the user how they can get it\r
++ (button-put button 'help-echo "Set notmuch-crypto-process-mime to process cryptographic MIME parts.")))\r
++\r
++ (let ((inner-parts (plist-get part :content))\r
++ (start (point)))\r
++ ;; Show all of the parts.\r
++ (mapc (lambda (inner-part)\r
++ (notmuch-show-insert-bodypart msg inner-part depth))\r
++ inner-parts)\r
++\r
++ (when notmuch-show-indent-multipart\r
++ (indent-rigidly start (point) 1)))\r
++ t)\r
++\r
++(defun notmuch-show-insert-part-multipart/encrypted (msg part content-type nth depth declared-type)\r
++ (let ((button (notmuch-show-insert-part-header nth declared-type content-type nil)))\r
++ (button-put button 'face 'notmuch-crypto-part-header)\r
++ ;; add encryption status button if encstatus specified\r
++ (if (plist-member part :encstatus)\r
++ (let ((encstatus (car (plist-get part :encstatus))))\r
++ (notmuch-crypto-insert-encstatus-button encstatus)\r
++ ;; add signature status button if sigstatus specified\r
++ (if (plist-member part :sigstatus)\r
++ (let* ((from (notmuch-show-get-header :From msg))\r
++ (sigstatus (car (plist-get part :sigstatus))))\r
++ (notmuch-crypto-insert-sigstatus-button sigstatus from))))\r
++ ;; if we're not adding encstatus, tell the user how they can get it\r
++ (button-put button 'help-echo "Set notmuch-crypto-process-mime to process cryptographic MIME parts.")))\r
++\r
++ (let ((inner-parts (plist-get part :content))\r
++ (start (point)))\r
++ ;; Show all of the parts.\r
++ (mapc (lambda (inner-part)\r
++ (notmuch-show-insert-bodypart msg inner-part depth))\r
++ inner-parts)\r
++\r
++ (when notmuch-show-indent-multipart\r
++ (indent-rigidly start (point) 1)))\r
++ t)\r
++\r
++(defun notmuch-show-insert-part-multipart/* (msg part content-type nth depth declared-type)\r
++ (notmuch-show-insert-part-header nth declared-type content-type nil)\r
++ (let ((inner-parts (plist-get part :content))\r
++ (start (point)))\r
++ ;; Show all of the parts.\r
++ (mapc (lambda (inner-part)\r
++ (notmuch-show-insert-bodypart msg inner-part depth))\r
++ inner-parts)\r
++\r
++ (when notmuch-show-indent-multipart\r
++ (indent-rigidly start (point) 1)))\r
++ t)\r
++\r
++(defun notmuch-show-insert-part-message/rfc822 (msg part content-type nth depth declared-type)\r
++ (notmuch-show-insert-part-header nth declared-type content-type nil)\r
++ (let* ((message (car (plist-get part :content)))\r
++ (body (car (plist-get message :body)))\r
++ (start (point)))\r
++\r
++ ;; Override `notmuch-message-headers' to force `From' to be\r
++ ;; displayed.\r
++ (let ((notmuch-message-headers '("From" "Subject" "To" "Cc" "Date")))\r
++ (notmuch-show-insert-headers (plist-get message :headers)))\r
++\r
++ ;; Blank line after headers to be compatible with the normal\r
++ ;; message display.\r
++ (insert "\n")\r
++\r
++ ;; Show the body\r
++ (notmuch-show-insert-bodypart msg body depth)\r
++\r
++ (when notmuch-show-indent-multipart\r
++ (indent-rigidly start (point) 1)))\r
++ t)\r
++\r
++(defun notmuch-show-insert-part-text/plain (msg part content-type nth depth declared-type)\r
++ (let ((start (point)))\r
++ ;; If this text/plain part is not the first part in the message,\r
++ ;; insert a header to make this clear.\r
++ (if (> nth 1)\r
++ (notmuch-show-insert-part-header nth declared-type content-type (plist-get part :filename)))\r
++ (insert (notmuch-get-bodypart-content msg part nth notmuch-show-process-crypto))\r
++ (save-excursion\r
++ (save-restriction\r
++ (narrow-to-region start (point-max))\r
++ (run-hook-with-args 'notmuch-show-insert-text/plain-hook msg depth))))\r
++ t)\r
++\r
++(defun notmuch-show-insert-part-text/calendar (msg part content-type nth depth declared-type)\r
++ (notmuch-show-insert-part-header nth declared-type content-type (plist-get part :filename))\r
++ (insert (with-temp-buffer\r
++ (insert (notmuch-get-bodypart-content msg part nth notmuch-show-process-crypto))\r
++ ;; notmuch-get-bodypart-content provides "raw", non-converted\r
++ ;; data. Replace CRLF with LF before icalendar can use it.\r
++ (goto-char (point-min))\r
++ (while (re-search-forward "\r\n" nil t)\r
++ (replace-match "\n" nil nil))\r
++ (let ((file (make-temp-file "notmuch-ical"))\r
++ result)\r
++ (unwind-protect\r
++ (progn\r
++ (unless (icalendar-import-buffer file t)\r
++ (error "Icalendar import error. See *icalendar-errors* for more information"))\r
++ (set-buffer (get-file-buffer file))\r
++ (setq result (buffer-substring (point-min) (point-max)))\r
++ (set-buffer-modified-p nil)\r
++ (kill-buffer (current-buffer)))\r
++ (delete-file file))\r
++ result)))\r
++ t)\r
++\r
++;; For backwards compatibility.\r
++(defun notmuch-show-insert-part-text/x-vcalendar (msg part content-type nth depth declared-type)\r
++ (notmuch-show-insert-part-text/calendar msg part content-type nth depth declared-type))\r
++\r
++(defun notmuch-show-get-mime-type-of-application/octet-stream (part)\r
++ ;; If we can deduce a MIME type from the filename of the attachment,\r
++ ;; we return that.\r
++ (if (plist-get part :filename)\r
++ (let ((extension (file-name-extension (plist-get part :filename)))\r
++ mime-type)\r
++ (if extension\r
++ (progn\r
++ (mailcap-parse-mimetypes)\r
++ (setq mime-type (mailcap-extension-to-mime extension))\r
++ (if (and mime-type\r
++ (not (string-equal mime-type "application/octet-stream")))\r
++ mime-type\r
++ nil))\r
++ nil))))\r
++\r
++;; Handler for wash generated inline patch fake parts.\r
++(defun notmuch-show-insert-part-inline-patch-fake-part (msg part content-type nth depth declared-type)\r
++ (notmuch-show-insert-part-*/* msg part content-type nth depth declared-type))\r
++\r
++(defun notmuch-show-insert-part-text/html (msg part content-type nth depth declared-type)\r
++ ;; text/html handler to work around bugs in renderers and our\r
++ ;; invisibile parts code. In particular w3m sets up a keymap which\r
++ ;; "leaks" outside the invisible region and causes strange effects\r
++ ;; in notmuch. We set mm-inline-text-html-with-w3m-keymap to nil to\r
++ ;; tell w3m not to set a keymap (so the normal notmuch-show-mode-map\r
++ ;; remains).\r
++ (let ((mm-inline-text-html-with-w3m-keymap nil))\r
++ (notmuch-show-insert-part-*/* msg part content-type nth depth declared-type)))\r
++\r
++(defun notmuch-show-insert-part-*/* (msg part content-type nth depth declared-type)\r
++ ;; This handler _must_ succeed - it is the handler of last resort.\r
++ (notmuch-show-insert-part-header nth content-type declared-type (plist-get part :filename))\r
++ (notmuch-mm-display-part-inline msg part nth content-type notmuch-show-process-crypto)\r
++ t)\r
++\r
++;; Functions for determining how to handle MIME parts.\r
++\r
++(defun notmuch-show-handlers-for (content-type)\r
++ "Return a list of content handlers for a part of type CONTENT-TYPE."\r
++ (let (result)\r
++ (mapc (lambda (func)\r
++ (if (functionp func)\r
++ (push func result)))\r
++ ;; Reverse order of prefrence.\r
++ (list (intern (concat "notmuch-show-insert-part-*/*"))\r
++ (intern (concat\r
++ "notmuch-show-insert-part-"\r
++ (car (notmuch-split-content-type content-type))\r
++ "/*"))\r
++ (intern (concat "notmuch-show-insert-part-" content-type))))\r
++ result))\r
++\r
++;; \f\r
+\r
++\r
++(defun notmuch-show-insert-bodypart-internal (msg part content-type nth depth declared-type)\r
++ (let ((handlers (notmuch-show-handlers-for content-type)))\r
++ ;; Run the content handlers until one of them returns a non-nil\r
++ ;; value.\r
++ (while (and handlers\r
++ (not (condition-case err\r
++ (funcall (car handlers) msg part content-type nth depth declared-type)\r
++ (error (progn\r
++ (insert "!!! Bodypart insert error: ")\r
++ (insert (error-message-string err))\r
++ (insert " !!!\n") nil)))))\r
++ (setq handlers (cdr handlers))))\r
++ t)\r
++\r
++(defun notmuch-show-create-part-overlays (msg beg end hide)\r
++ "Add an overlay to the part between BEG and END"\r
++ (let* ((button (button-at beg))\r
++ (part-beg (and button (1+ (button-end button)))))\r
++\r
++ ;; If the part contains no text we do not make it toggleable. We\r
++ ;; also need to check that the button is a genuine part button not\r
++ ;; a notmuch-wash button.\r
++ (when (and button (/= part-beg end) (button-get button :base-label))\r
++ (button-put button 'overlay (make-overlay part-beg end))\r
++ ;; We toggle the button for hidden parts as that gets the\r
++ ;; button label right.\r
++ (save-excursion\r
++ (when hide\r
++ (notmuch-show-toggle-part-invisibility button))))))\r
++\r
++(defun notmuch-show-insert-bodypart (msg part depth &optional hide)\r
++ "Insert the body part PART at depth DEPTH in the current thread.\r
++\r
++If HIDE is non-nil then initially hide this part."\r
++ (let* ((content-type (downcase (plist-get part :content-type)))\r
++ (mime-type (or (and (string= content-type "application/octet-stream")\r
++ (notmuch-show-get-mime-type-of-application/octet-stream part))\r
++ (and (string= content-type "inline patch")\r
++ "text/x-diff")\r
++ content-type))\r
++ (nth (plist-get part :id))\r
++ (beg (point)))\r
++\r
++ (notmuch-show-insert-bodypart-internal msg part mime-type nth depth content-type)\r
++ ;; Some of the body part handlers leave point somewhere up in the\r
++ ;; part, so we make sure that we're down at the end.\r
++ (goto-char (point-max))\r
++ ;; Ensure that the part ends with a carriage return.\r
++ (unless (bolp)\r
++ (insert "\n"))\r
++ (notmuch-show-create-part-overlays msg beg (point) hide)))\r
++\r
++(defun notmuch-show-insert-body (msg body depth)\r
++ "Insert the body BODY at depth DEPTH in the current thread."\r
++ (mapc (lambda (part) (notmuch-show-insert-bodypart msg part depth)) body))\r
++\r
++(defun notmuch-show-strip-re (string)\r
++ (replace-regexp-in-string "^\\([Rr]e: *\\)+" "" string))\r
++\r
++(defvar notmuch-show-previous-subject "")\r
++(make-variable-buffer-local 'notmuch-show-previous-subject)\r
++\r
++(defun notmuch-show-insert-msg (msg depth)\r
++ "Insert the message MSG at depth DEPTH in the current thread."\r
++ (let* ((headers (plist-get msg :headers))\r
++ ;; Indentation causes the buffer offset of the start/end\r
++ ;; points to move, so we must use markers.\r
++ message-start message-end\r
++ content-start content-end\r
++ headers-start headers-end\r
++ (bare-subject (notmuch-show-strip-re (plist-get headers :Subject))))\r
++\r
++ (setq message-start (point-marker))\r
++\r
++ (notmuch-show-insert-headerline headers\r
++ (or (if notmuch-show-relative-dates\r
++ (plist-get msg :date_relative)\r
++ nil)\r
++ (plist-get headers :Date))\r
++ (plist-get msg :tags) depth)\r
++\r
++ (setq content-start (point-marker))\r
++\r
++ ;; Set `headers-start' to point after the 'Subject:' header to be\r
++ ;; compatible with the existing implementation. This just sets it\r
++ ;; to after the first header.\r
++ (notmuch-show-insert-headers headers)\r
++ (save-excursion\r
++ (goto-char content-start)\r
++ ;; If the subject of this message is the same as that of the\r
++ ;; previous message, don't display it when this message is\r
++ ;; collapsed.\r
++ (when (not (string= notmuch-show-previous-subject\r
++ bare-subject))\r
++ (forward-line 1))\r
++ (setq headers-start (point-marker)))\r
++ (setq headers-end (point-marker))\r
++\r
++ (setq notmuch-show-previous-subject bare-subject)\r
++\r
++ ;; A blank line between the headers and the body.\r
++ (insert "\n")\r
++ (notmuch-show-insert-body msg (plist-get msg :body)\r
++ (if notmuch-show-indent-content depth 0))\r
++ ;; Ensure that the body ends with a newline.\r
++ (unless (bolp)\r
++ (insert "\n"))\r
++ (setq content-end (point-marker))\r
++\r
++ ;; Indent according to the depth in the thread.\r
++ (if notmuch-show-indent-content\r
++ (indent-rigidly content-start content-end (* notmuch-show-indent-messages-width depth)))\r
++\r
++ (setq message-end (point-max-marker))\r
++\r
++ ;; Save the extents of this message over the whole text of the\r
++ ;; message.\r
++ (put-text-property message-start message-end :notmuch-message-extent (cons message-start message-end))\r
++\r
++ ;; Create overlays used to control visibility\r
++ (plist-put msg :headers-overlay (make-overlay headers-start headers-end))\r
++ (plist-put msg :message-overlay (make-overlay headers-start content-end))\r
++\r
++ (plist-put msg :depth depth)\r
++\r
++ ;; Save the properties for this message. Currently this saves the\r
++ ;; entire message (augmented it with other stuff), which seems\r
++ ;; like overkill. We might save a reduced subset (for example, not\r
++ ;; the content).\r
++ (notmuch-show-set-message-properties msg)\r
++\r
++ ;; Set header visibility.\r
++ (notmuch-show-headers-visible msg notmuch-message-headers-visible)\r
++\r
++ ;; Message visibility depends on whether it matched the search\r
++ ;; criteria.\r
++ (notmuch-show-message-visible msg (and (plist-get msg :match)\r
++ (not (plist-get msg :excluded))))))\r
++\r
++(defun notmuch-show-insert-tree (tree depth)\r
++ "Insert the message tree TREE at depth DEPTH in the current thread."\r
++ (let ((msg (car tree))\r
++ (replies (cadr tree)))\r
++ ;; We test whether there is a message or just some replies.\r
++ (when msg\r
++ (notmuch-show-insert-msg msg depth))\r
++ (notmuch-show-insert-thread replies (1+ depth))))\r
++\r
++(defun notmuch-show-insert-thread (thread depth)\r
++ "Insert the thread THREAD at depth DEPTH in the current forest."\r
++ (mapc (lambda (tree) (notmuch-show-insert-tree tree depth)) thread))\r
++\r
++(defun notmuch-show-insert-forest (forest)\r
++ "Insert the forest of threads FOREST."\r
++ (mapc (lambda (thread) (notmuch-show-insert-thread thread 0)) forest))\r
++\r
++;; Functions relating to the visibility of messages and their\r
++;; components.\r
++\r
++(defun notmuch-show-message-visible (props visible-p)\r
++ (overlay-put (plist-get props :message-overlay) 'invisible (not visible-p))\r
++ (notmuch-show-set-prop :message-visible visible-p props))\r
++\r
++(defun notmuch-show-headers-visible (props visible-p)\r
++ (overlay-put (plist-get props :headers-overlay) 'invisible (not visible-p))\r
++ (notmuch-show-set-prop :headers-visible visible-p props))\r
++\r
++;;\r
++\r
++(provide 'notmuch-show-display)\r
+diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el\r
+index 37ba911..9e3401d 100644\r
+--- a/emacs/notmuch-show.el\r
++++ b/emacs/notmuch-show.el\r
+@@ -22,17 +22,12 @@\r
+ ;; David Edmondson <dme@dme.org>\r
+ \r
+ (eval-when-compile (require 'cl))\r
+-(require 'mm-view)\r
+-(require 'message)\r
+-(require 'mm-decode)\r
+-(require 'mailcap)\r
+ (require 'icalendar)\r
+ (require 'goto-addr)\r
+ \r
+ (require 'notmuch-lib)\r
+ (require 'notmuch-tag)\r
+ (require 'notmuch-query)\r
+-(require 'notmuch-wash)\r
+ (require 'notmuch-mua)\r
+ (require 'notmuch-crypto)\r
+ (require 'notmuch-print)\r
+@@ -43,36 +38,6 @@\r
+ (declare-function notmuch-search-previous-thread "notmuch" nil)\r
+ (declare-function notmuch-search-show-thread "notmuch" nil)\r
+ \r
+-(defcustom notmuch-message-headers '("Subject" "To" "Cc" "Date")\r
+- "Headers that should be shown in a message, in this order.\r
+-\r
+-For an open message, all of these headers will be made visible\r
+-according to `notmuch-message-headers-visible' or can be toggled\r
+-with `notmuch-show-toggle-visibility-headers'. For a closed message,\r
+-only the first header in the list will be visible."\r
+- :type '(repeat string)\r
+- :group 'notmuch-show)\r
+-\r
+-(defcustom notmuch-message-headers-visible t\r
+- "Should the headers be visible by default?\r
+-\r
+-If this value is non-nil, then all of the headers defined in\r
+-`notmuch-message-headers' will be visible by default in the display\r
+-of each message. Otherwise, these headers will be hidden and\r
+-`notmuch-show-toggle-visibility-headers' can be used to make them\r
+-visible for any given message."\r
+- :type 'boolean\r
+- :group 'notmuch-show)\r
+-\r
+-(defcustom notmuch-show-relative-dates t\r
+- "Display relative dates in the message summary line."\r
+- :type 'boolean\r
+- :group 'notmuch-show)\r
+-\r
+-(defvar notmuch-show-markup-headers-hook '(notmuch-show-colour-headers)\r
+- "A list of functions called to decorate the headers listed in\r
+-`notmuch-message-headers'.")\r
+-\r
+ (defcustom notmuch-show-hook '(notmuch-show-turn-on-visual-line-mode)\r
+ "Functions called after populating a `notmuch-show' buffer."\r
+ :type 'hook\r
+@@ -80,42 +45,6 @@ visible for any given message."\r
+ :group 'notmuch-show\r
+ :group 'notmuch-hooks)\r
+ \r
+-(defcustom notmuch-show-insert-text/plain-hook '(notmuch-wash-wrap-long-lines\r
+- notmuch-wash-tidy-citations\r
+- notmuch-wash-elide-blank-lines\r
+- notmuch-wash-excerpt-citations)\r
+- "Functions used to improve the display of text/plain parts."\r
+- :type 'hook\r
+- :options '(notmuch-wash-convert-inline-patch-to-part\r
+- notmuch-wash-wrap-long-lines\r
+- notmuch-wash-tidy-citations\r
+- notmuch-wash-elide-blank-lines\r
+- notmuch-wash-excerpt-citations)\r
+- :group 'notmuch-show\r
+- :group 'notmuch-hooks)\r
+-\r
+-;; Mostly useful for debugging.\r
+-(defcustom notmuch-show-all-multipart/alternative-parts nil\r
+- "Should all parts of multipart/alternative parts be shown?"\r
+- :type 'boolean\r
+- :group 'notmuch-show)\r
+-\r
+-(defcustom notmuch-show-indent-messages-width 1\r
+- "Width of message indentation in threads.\r
+-\r
+-Messages are shown indented according to their depth in a thread.\r
+-This variable determines the width of this indentation measured\r
+-in number of blanks. Defaults to `1', choose `0' to disable\r
+-indentation."\r
+- :type 'integer\r
+- :group 'notmuch-show)\r
+-\r
+-(defcustom notmuch-show-indent-multipart nil\r
+- "Should the sub-parts of a multipart/* part be indented?"\r
+- ;; dme: Not sure which is a good default.\r
+- :type 'boolean\r
+- :group 'notmuch-show)\r
+-\r
+ (defcustom notmuch-show-part-button-default-action 'notmuch-show-save-part\r
+ "Default part header button action (on ENTER or mouse click)."\r
+ :group 'notmuch-show\r
+@@ -143,18 +72,10 @@ indentation."\r
+ (make-variable-buffer-local 'notmuch-show-query-context)\r
+ (put 'notmuch-show-query-context 'permanent-local t)\r
+ \r
+-(defvar notmuch-show-process-crypto nil)\r
+-(make-variable-buffer-local 'notmuch-show-process-crypto)\r
+-(put 'notmuch-show-process-crypto 'permanent-local t)\r
+-\r
+ (defvar notmuch-show-elide-non-matching-messages nil)\r
+ (make-variable-buffer-local 'notmuch-show-elide-non-matching-messages)\r
+ (put 'notmuch-show-elide-non-matching-messages 'permanent-local t)\r
+ \r
+-(defvar notmuch-show-indent-content t)\r
+-(make-variable-buffer-local 'notmuch-show-indent-content)\r
+-(put 'notmuch-show-indent-content 'permanent-local t)\r
+-\r
+ (defcustom notmuch-show-stash-mlarchive-link-alist\r
+ '(("Gmane" . "http://mid.gmane.org/")\r
+ ("MARC" . "http://marc.info/?i=")\r
+@@ -328,35 +249,6 @@ operation on the contents of the current buffer."\r
+ (interactive)\r
+ (notmuch-show-with-message-as-text 'notmuch-print-message))\r
+ \r
+-(defun notmuch-show-fontify-header ()\r
+- (let ((face (cond\r
+- ((looking-at "[Tt]o:")\r
+- 'message-header-to)\r
+- ((looking-at "[Bb]?[Cc][Cc]:")\r
+- 'message-header-cc)\r
+- ((looking-at "[Ss]ubject:")\r
+- 'message-header-subject)\r
+- ((looking-at "[Ff]rom:")\r
+- 'message-header-from)\r
+- (t\r
+- 'message-header-other))))\r
+-\r
+- (overlay-put (make-overlay (point) (re-search-forward ":"))\r
+- 'face 'message-header-name)\r
+- (overlay-put (make-overlay (point) (re-search-forward ".*$"))\r
+- 'face face)))\r
+-\r
+-(defun notmuch-show-colour-headers ()\r
+- "Apply some colouring to the current headers."\r
+- (goto-char (point-min))\r
+- (while (looking-at "^[A-Za-z][-A-Za-z0-9]*:")\r
+- (notmuch-show-fontify-header)\r
+- (forward-line)))\r
+-\r
+-(defun notmuch-show-spaces-n (n)\r
+- "Return a string comprised of `n' spaces."\r
+- (make-string n ? ))\r
+-\r
+ (defun notmuch-show-update-tags (tags)\r
+ "Update the displayed tags of the current message."\r
+ (save-excursion\r
+@@ -367,104 +259,6 @@ operation on the contents of the current buffer."\r
+ (notmuch-tag-format-tags tags)\r
+ ")"))))))\r
+ \r
+-(defun notmuch-clean-address (address)\r
+- "Try to clean a single email ADDRESS for display. Return a cons\r
+-cell of (AUTHOR_EMAIL AUTHOR_NAME). Return (ADDRESS nil) if\r
+-parsing fails."\r
+- (condition-case nil\r
+- (let (p-name p-address)\r
+- ;; It would be convenient to use `mail-header-parse-address',\r
+- ;; but that expects un-decoded mailbox parts, whereas our\r
+- ;; mailbox parts are already decoded (and hence may contain\r
+- ;; UTF-8). Given that notmuch should handle most of the awkward\r
+- ;; cases, some simple string deconstruction should be sufficient\r
+- ;; here.\r
+- (cond\r
+- ;; "User <user@dom.ain>" style.\r
+- ((string-match "\\(.*\\) <\\(.*\\)>" address)\r
+- (setq p-name (match-string 1 address)\r
+- p-address (match-string 2 address)))\r
+-\r
+- ;; "<user@dom.ain>" style.\r
+- ((string-match "<\\(.*\\)>" address)\r
+- (setq p-address (match-string 1 address)))\r
+-\r
+- ;; Everything else.\r
+- (t\r
+- (setq p-address address)))\r
+-\r
+- (when p-name\r
+- ;; Remove elements of the mailbox part that are not relevant for\r
+- ;; display, even if they are required during transport:\r
+- ;;\r
+- ;; Backslashes.\r
+- (setq p-name (replace-regexp-in-string "\\\\" "" p-name))\r
+-\r
+- ;; Outer single and double quotes, which might be nested.\r
+- (loop\r
+- with start-of-loop\r
+- do (setq start-of-loop p-name)\r
+-\r
+- when (string-match "^\"\\(.*\\)\"$" p-name)\r
+- do (setq p-name (match-string 1 p-name))\r
+-\r
+- when (string-match "^'\\(.*\\)'$" p-name)\r
+- do (setq p-name (match-string 1 p-name))\r
+-\r
+- until (string= start-of-loop p-name)))\r
+-\r
+- ;; If the address is 'foo@bar.com <foo@bar.com>' then show just\r
+- ;; 'foo@bar.com'.\r
+- (when (string= p-name p-address)\r
+- (setq p-name nil))\r
+-\r
+- (cons p-address p-name))\r
+- (error (cons address nil))))\r
+-\r
+-(defun notmuch-show-clean-address (address)\r
+- "Try to clean a single email ADDRESS for display. Return\r
+-unchanged ADDRESS if parsing fails."\r
+- (let* ((clean-address (notmuch-clean-address address))\r
+- (p-address (car clean-address))\r
+- (p-name (cdr clean-address)))\r
+- ;; If no name, return just the address.\r
+- (if (not p-name)\r
+- p-address\r
+- ;; Otherwise format the name and address together.\r
+- (concat p-name " <" p-address ">"))))\r
+-\r
+-(defun notmuch-show-insert-headerline (headers date tags depth)\r
+- "Insert a notmuch style headerline based on HEADERS for a\r
+-message at DEPTH in the current thread."\r
+- (let ((start (point)))\r
+- (insert (notmuch-show-spaces-n (* notmuch-show-indent-messages-width depth))\r
+- (notmuch-show-clean-address (plist-get headers :From))\r
+- " ("\r
+- date\r
+- ") ("\r
+- (notmuch-tag-format-tags tags)\r
+- ")\n")\r
+- (overlay-put (make-overlay start (point)) 'face 'notmuch-message-summary-face)))\r
+-\r
+-(defun notmuch-show-insert-header (header header-value)\r
+- "Insert a single header."\r
+- (insert header ": " header-value "\n"))\r
+-\r
+-(defun notmuch-show-insert-headers (headers)\r
+- "Insert the headers of the current message."\r
+- (let ((start (point)))\r
+- (mapc (lambda (header)\r
+- (let* ((header-symbol (intern (concat ":" header)))\r
+- (header-value (plist-get headers header-symbol)))\r
+- (if (and header-value\r
+- (not (string-equal "" header-value)))\r
+- (notmuch-show-insert-header header header-value))))\r
+- notmuch-message-headers)\r
+- (save-excursion\r
+- (save-restriction\r
+- (narrow-to-region start (point-max))\r
+- (run-hooks 'notmuch-show-markup-headers-hook)))))\r
+-\r
+ (define-button-type 'notmuch-show-part-button-type\r
+ 'action 'notmuch-show-part-button-default\r
+ 'keymap 'notmuch-show-part-button-map\r
+@@ -483,26 +277,6 @@ message at DEPTH in the current thread."\r
+ "Submap for button commands")\r
+ (fset 'notmuch-show-part-button-map notmuch-show-part-button-map)\r
+ \r
+-(defun notmuch-show-insert-part-header (nth content-type declared-type &optional name comment)\r
+- (let ((button)\r
+- (base-label (concat (when name (concat name ": "))\r
+- declared-type\r
+- (unless (string-equal declared-type content-type)\r
+- (concat " (as " content-type ")"))\r
+- comment)))\r
+-\r
+- (setq button\r
+- (insert-button\r
+- (concat "[ " base-label " ]")\r
+- :base-label base-label\r
+- :type 'notmuch-show-part-button-type\r
+- :notmuch-part nth\r
+- :notmuch-filename name\r
+- :notmuch-content-type content-type))\r
+- (insert "\n")\r
+- ;; return button\r
+- button))\r
+-\r
+ ;; Functions handling particular MIME parts.\r
+ \r
+ (defmacro notmuch-with-temp-part-buffer (message-id nth &rest body)\r
+@@ -550,447 +324,9 @@ message at DEPTH in the current thread."\r
+ (let ((handle (mm-make-handle (current-buffer) (list content-type))))\r
+ (mm-pipe-part handle))))\r
+ \r
+-;; This is taken from notmuch-wash: maybe it should be unified?\r
+-(defun notmuch-show-toggle-part-invisibility (&optional button)\r
+- (interactive)\r
+- (let* ((button (or button (button-at (point))))\r
+- (overlay (button-get button 'overlay)))\r
+- (when overlay\r
+- (let* ((show (overlay-get overlay 'invisible))\r
+- (new-start (button-start button))\r
+- (button-label (button-get button :base-label))\r
+- (old-point (point))\r
+- (inhibit-read-only t))\r
+- (overlay-put overlay 'invisible (not show))\r
+- (goto-char new-start)\r
+- (insert "[ " button-label (if show " ]" " (hidden) ]"))\r
+- (let ((old-end (button-end button)))\r
+- (move-overlay button new-start (point))\r
+- (delete-region (point) old-end))\r
+- (goto-char (min old-point (1- (button-end button))))))))\r
+-\r
+-(defun notmuch-show-multipart/*-to-list (part)\r
+- (mapcar (lambda (inner-part) (plist-get inner-part :content-type))\r
+- (plist-get part :content)))\r
+-\r
+-(defun notmuch-show-insert-part-multipart/alternative (msg part content-type nth depth declared-type)\r
+- (notmuch-show-insert-part-header nth declared-type content-type nil)\r
+- (let ((chosen-type (car (notmuch-multipart/alternative-choose (notmuch-show-multipart/*-to-list part))))\r
+- (inner-parts (plist-get part :content))\r
+- (start (point)))\r
+- ;; This inserts all parts of the chosen type rather than just one,\r
+- ;; but it's not clear that this is the wrong thing to do - which\r
+- ;; should be chosen if there are more than one that match?\r
+- (mapc (lambda (inner-part)\r
+- (let* ((inner-type (plist-get inner-part :content-type))\r
+- (hide (not (or notmuch-show-all-multipart/alternative-parts\r
+- (string= chosen-type inner-type)))))\r
+- (notmuch-show-insert-bodypart msg inner-part depth hide)))\r
+- inner-parts)\r
+-\r
+- (when notmuch-show-indent-multipart\r
+- (indent-rigidly start (point) 1)))\r
+- t)\r
+-\r
+-(defun notmuch-show-setup-w3m ()\r
+- "Instruct w3m how to retrieve content from a \"related\" part of a message."\r
+- (interactive)\r
+- (if (boundp 'w3m-cid-retrieve-function-alist)\r
+- (unless (assq 'notmuch-show-mode w3m-cid-retrieve-function-alist)\r
+- (push (cons 'notmuch-show-mode 'notmuch-show-w3m-cid-retrieve)\r
+- w3m-cid-retrieve-function-alist)))\r
+- (setq mm-inline-text-html-with-images t))\r
+-\r
+-(defvar w3m-current-buffer) ;; From `w3m.el'.\r
+-(defvar notmuch-show-w3m-cid-store nil)\r
+-(make-variable-buffer-local 'notmuch-show-w3m-cid-store)\r
+-\r
+-(defun notmuch-show-w3m-cid-store-internal (content-id\r
+- message-id\r
+- part-number\r
+- content-type\r
+- content)\r
+- (push (list content-id\r
+- message-id\r
+- part-number\r
+- content-type\r
+- content)\r
+- notmuch-show-w3m-cid-store))\r
+-\r
+-(defun notmuch-show-w3m-cid-store (msg part)\r
+- (let ((content-id (plist-get part :content-id)))\r
+- (when content-id\r
+- (notmuch-show-w3m-cid-store-internal (concat "cid:" content-id)\r
+- (plist-get msg :id)\r
+- (plist-get part :id)\r
+- (plist-get part :content-type)\r
+- nil))))\r
+-\r
+-(defun notmuch-show-w3m-cid-retrieve (url &rest args)\r
+- (let ((matching-part (with-current-buffer w3m-current-buffer\r
+- (assoc url notmuch-show-w3m-cid-store))))\r
+- (if matching-part\r
+- (let ((message-id (nth 1 matching-part))\r
+- (part-number (nth 2 matching-part))\r
+- (content-type (nth 3 matching-part))\r
+- (content (nth 4 matching-part)))\r
+- ;; If we don't already have the content, get it and cache\r
+- ;; it, as some messages reference the same cid: part many\r
+- ;; times (hundreds!), which results in many calls to\r
+- ;; `notmuch part'.\r
+- (unless content\r
+- (setq content (notmuch-get-bodypart-internal (notmuch-id-to-query message-id)\r
+- part-number notmuch-show-process-crypto))\r
+- (with-current-buffer w3m-current-buffer\r
+- (notmuch-show-w3m-cid-store-internal url\r
+- message-id\r
+- part-number\r
+- content-type\r
+- content)))\r
+- (insert content)\r
+- content-type)\r
+- nil)))\r
+-\r
+-(defun notmuch-show-insert-part-multipart/related (msg part content-type nth depth declared-type)\r
+- (notmuch-show-insert-part-header nth declared-type content-type nil)\r
+- (let ((inner-parts (plist-get part :content))\r
+- (start (point)))\r
+-\r
+- ;; We assume that the first part is text/html and the remainder\r
+- ;; things that it references.\r
+-\r
+- ;; Stash the non-primary parts.\r
+- (mapc (lambda (part)\r
+- (notmuch-show-w3m-cid-store msg part))\r
+- (cdr inner-parts))\r
+-\r
+- ;; Render the primary part.\r
+- (notmuch-show-insert-bodypart msg (car inner-parts) depth)\r
+-\r
+- (when notmuch-show-indent-multipart\r
+- (indent-rigidly start (point) 1)))\r
+- t)\r
+-\r
+-(defun notmuch-show-insert-part-multipart/signed (msg part content-type nth depth declared-type)\r
+- (let ((button (notmuch-show-insert-part-header nth declared-type content-type nil)))\r
+- (button-put button 'face 'notmuch-crypto-part-header)\r
+- ;; add signature status button if sigstatus provided\r
+- (if (plist-member part :sigstatus)\r
+- (let* ((from (notmuch-show-get-header :From msg))\r
+- (sigstatus (car (plist-get part :sigstatus))))\r
+- (notmuch-crypto-insert-sigstatus-button sigstatus from))\r
+- ;; if we're not adding sigstatus, tell the user how they can get it\r
+- (button-put button 'help-echo "Set notmuch-crypto-process-mime to process cryptographic MIME parts.")))\r
+-\r
+- (let ((inner-parts (plist-get part :content))\r
+- (start (point)))\r
+- ;; Show all of the parts.\r
+- (mapc (lambda (inner-part)\r
+- (notmuch-show-insert-bodypart msg inner-part depth))\r
+- inner-parts)\r
+-\r
+- (when notmuch-show-indent-multipart\r
+- (indent-rigidly start (point) 1)))\r
+- t)\r
+-\r
+-(defun notmuch-show-insert-part-multipart/encrypted (msg part content-type nth depth declared-type)\r
+- (let ((button (notmuch-show-insert-part-header nth declared-type content-type nil)))\r
+- (button-put button 'face 'notmuch-crypto-part-header)\r
+- ;; add encryption status button if encstatus specified\r
+- (if (plist-member part :encstatus)\r
+- (let ((encstatus (car (plist-get part :encstatus))))\r
+- (notmuch-crypto-insert-encstatus-button encstatus)\r
+- ;; add signature status button if sigstatus specified\r
+- (if (plist-member part :sigstatus)\r
+- (let* ((from (notmuch-show-get-header :From msg))\r
+- (sigstatus (car (plist-get part :sigstatus))))\r
+- (notmuch-crypto-insert-sigstatus-button sigstatus from))))\r
+- ;; if we're not adding encstatus, tell the user how they can get it\r
+- (button-put button 'help-echo "Set notmuch-crypto-process-mime to process cryptographic MIME parts.")))\r
+-\r
+- (let ((inner-parts (plist-get part :content))\r
+- (start (point)))\r
+- ;; Show all of the parts.\r
+- (mapc (lambda (inner-part)\r
+- (notmuch-show-insert-bodypart msg inner-part depth))\r
+- inner-parts)\r
+-\r
+- (when notmuch-show-indent-multipart\r
+- (indent-rigidly start (point) 1)))\r
+- t)\r
+-\r
+-(defun notmuch-show-insert-part-multipart/* (msg part content-type nth depth declared-type)\r
+- (notmuch-show-insert-part-header nth declared-type content-type nil)\r
+- (let ((inner-parts (plist-get part :content))\r
+- (start (point)))\r
+- ;; Show all of the parts.\r
+- (mapc (lambda (inner-part)\r
+- (notmuch-show-insert-bodypart msg inner-part depth))\r
+- inner-parts)\r
+-\r
+- (when notmuch-show-indent-multipart\r
+- (indent-rigidly start (point) 1)))\r
+- t)\r
+-\r
+-(defun notmuch-show-insert-part-message/rfc822 (msg part content-type nth depth declared-type)\r
+- (notmuch-show-insert-part-header nth declared-type content-type nil)\r
+- (let* ((message (car (plist-get part :content)))\r
+- (body (car (plist-get message :body)))\r
+- (start (point)))\r
+-\r
+- ;; Override `notmuch-message-headers' to force `From' to be\r
+- ;; displayed.\r
+- (let ((notmuch-message-headers '("From" "Subject" "To" "Cc" "Date")))\r
+- (notmuch-show-insert-headers (plist-get message :headers)))\r
+-\r
+- ;; Blank line after headers to be compatible with the normal\r
+- ;; message display.\r
+- (insert "\n")\r
+-\r
+- ;; Show the body\r
+- (notmuch-show-insert-bodypart msg body depth)\r
+-\r
+- (when notmuch-show-indent-multipart\r
+- (indent-rigidly start (point) 1)))\r
+- t)\r
+-\r
+-(defun notmuch-show-insert-part-text/plain (msg part content-type nth depth declared-type)\r
+- (let ((start (point)))\r
+- ;; If this text/plain part is not the first part in the message,\r
+- ;; insert a header to make this clear.\r
+- (if (> nth 1)\r
+- (notmuch-show-insert-part-header nth declared-type content-type (plist-get part :filename)))\r
+- (insert (notmuch-get-bodypart-content msg part nth notmuch-show-process-crypto))\r
+- (save-excursion\r
+- (save-restriction\r
+- (narrow-to-region start (point-max))\r
+- (run-hook-with-args 'notmuch-show-insert-text/plain-hook msg depth))))\r
+- t)\r
+-\r
+-(defun notmuch-show-insert-part-text/calendar (msg part content-type nth depth declared-type)\r
+- (notmuch-show-insert-part-header nth declared-type content-type (plist-get part :filename))\r
+- (insert (with-temp-buffer\r
+- (insert (notmuch-get-bodypart-content msg part nth notmuch-show-process-crypto))\r
+- ;; notmuch-get-bodypart-content provides "raw", non-converted\r
+- ;; data. Replace CRLF with LF before icalendar can use it.\r
+- (goto-char (point-min))\r
+- (while (re-search-forward "\r\n" nil t)\r
+- (replace-match "\n" nil nil))\r
+- (let ((file (make-temp-file "notmuch-ical"))\r
+- result)\r
+- (unwind-protect\r
+- (progn\r
+- (unless (icalendar-import-buffer file t)\r
+- (error "Icalendar import error. See *icalendar-errors* for more information"))\r
+- (set-buffer (get-file-buffer file))\r
+- (setq result (buffer-substring (point-min) (point-max)))\r
+- (set-buffer-modified-p nil)\r
+- (kill-buffer (current-buffer)))\r
+- (delete-file file))\r
+- result)))\r
+- t)\r
+-\r
+-;; For backwards compatibility.\r
+-(defun notmuch-show-insert-part-text/x-vcalendar (msg part content-type nth depth declared-type)\r
+- (notmuch-show-insert-part-text/calendar msg part content-type nth depth declared-type))\r
+-\r
+-(defun notmuch-show-get-mime-type-of-application/octet-stream (part)\r
+- ;; If we can deduce a MIME type from the filename of the attachment,\r
+- ;; we return that.\r
+- (if (plist-get part :filename)\r
+- (let ((extension (file-name-extension (plist-get part :filename)))\r
+- mime-type)\r
+- (if extension\r
+- (progn\r
+- (mailcap-parse-mimetypes)\r
+- (setq mime-type (mailcap-extension-to-mime extension))\r
+- (if (and mime-type\r
+- (not (string-equal mime-type "application/octet-stream")))\r
+- mime-type\r
+- nil))\r
+- nil))))\r
+-\r
+-;; Handler for wash generated inline patch fake parts.\r
+-(defun notmuch-show-insert-part-inline-patch-fake-part (msg part content-type nth depth declared-type)\r
+- (notmuch-show-insert-part-*/* msg part content-type nth depth declared-type))\r
+-\r
+-(defun notmuch-show-insert-part-text/html (msg part content-type nth depth declared-type)\r
+- ;; text/html handler to work around bugs in renderers and our\r
+- ;; invisibile parts code. In particular w3m sets up a keymap which\r
+- ;; "leaks" outside the invisible region and causes strange effects\r
+- ;; in notmuch. We set mm-inline-text-html-with-w3m-keymap to nil to\r
+- ;; tell w3m not to set a keymap (so the normal notmuch-show-mode-map\r
+- ;; remains).\r
+- (let ((mm-inline-text-html-with-w3m-keymap nil))\r
+- (notmuch-show-insert-part-*/* msg part content-type nth depth declared-type)))\r
+-\r
+-(defun notmuch-show-insert-part-*/* (msg part content-type nth depth declared-type)\r
+- ;; This handler _must_ succeed - it is the handler of last resort.\r
+- (notmuch-show-insert-part-header nth content-type declared-type (plist-get part :filename))\r
+- (notmuch-mm-display-part-inline msg part nth content-type notmuch-show-process-crypto)\r
+- t)\r
+-\r
+-;; Functions for determining how to handle MIME parts.\r
+-\r
+-(defun notmuch-show-handlers-for (content-type)\r
+- "Return a list of content handlers for a part of type CONTENT-TYPE."\r
+- (let (result)\r
+- (mapc (lambda (func)\r
+- (if (functionp func)\r
+- (push func result)))\r
+- ;; Reverse order of prefrence.\r
+- (list (intern (concat "notmuch-show-insert-part-*/*"))\r
+- (intern (concat\r
+- "notmuch-show-insert-part-"\r
+- (car (notmuch-split-content-type content-type))\r
+- "/*"))\r
+- (intern (concat "notmuch-show-insert-part-" content-type))))\r
+- result))\r
+-\r
+-;; \f\r
+\r
+-\r
+-(defun notmuch-show-insert-bodypart-internal (msg part content-type nth depth declared-type)\r
+- (let ((handlers (notmuch-show-handlers-for content-type)))\r
+- ;; Run the content handlers until one of them returns a non-nil\r
+- ;; value.\r
+- (while (and handlers\r
+- (not (condition-case err\r
+- (funcall (car handlers) msg part content-type nth depth declared-type)\r
+- (error (progn\r
+- (insert "!!! Bodypart insert error: ")\r
+- (insert (error-message-string err))\r
+- (insert " !!!\n") nil)))))\r
+- (setq handlers (cdr handlers))))\r
+- t)\r
+-\r
+-(defun notmuch-show-create-part-overlays (msg beg end hide)\r
+- "Add an overlay to the part between BEG and END"\r
+- (let* ((button (button-at beg))\r
+- (part-beg (and button (1+ (button-end button)))))\r
+-\r
+- ;; If the part contains no text we do not make it toggleable. We\r
+- ;; also need to check that the button is a genuine part button not\r
+- ;; a notmuch-wash button.\r
+- (when (and button (/= part-beg end) (button-get button :base-label))\r
+- (button-put button 'overlay (make-overlay part-beg end))\r
+- ;; We toggle the button for hidden parts as that gets the\r
+- ;; button label right.\r
+- (save-excursion\r
+- (when hide\r
+- (notmuch-show-toggle-part-invisibility button))))))\r
+-\r
+-(defun notmuch-show-insert-bodypart (msg part depth &optional hide)\r
+- "Insert the body part PART at depth DEPTH in the current thread.\r
+-\r
+-If HIDE is non-nil then initially hide this part."\r
+- (let* ((content-type (downcase (plist-get part :content-type)))\r
+- (mime-type (or (and (string= content-type "application/octet-stream")\r
+- (notmuch-show-get-mime-type-of-application/octet-stream part))\r
+- (and (string= content-type "inline patch")\r
+- "text/x-diff")\r
+- content-type))\r
+- (nth (plist-get part :id))\r
+- (beg (point)))\r
+-\r
+- (notmuch-show-insert-bodypart-internal msg part mime-type nth depth content-type)\r
+- ;; Some of the body part handlers leave point somewhere up in the\r
+- ;; part, so we make sure that we're down at the end.\r
+- (goto-char (point-max))\r
+- ;; Ensure that the part ends with a carriage return.\r
+- (unless (bolp)\r
+- (insert "\n"))\r
+- (notmuch-show-create-part-overlays msg beg (point) hide)))\r
+-\r
+-(defun notmuch-show-insert-body (msg body depth)\r
+- "Insert the body BODY at depth DEPTH in the current thread."\r
+- (mapc (lambda (part) (notmuch-show-insert-bodypart msg part depth)) body))\r
+-\r
+ (defun notmuch-show-make-symbol (type)\r
+ (make-symbol (concat "notmuch-show-" type)))\r
+ \r
+-(defun notmuch-show-strip-re (string)\r
+- (replace-regexp-in-string "^\\([Rr]e: *\\)+" "" string))\r
+-\r
+-(defvar notmuch-show-previous-subject "")\r
+-(make-variable-buffer-local 'notmuch-show-previous-subject)\r
+-\r
+-(defun notmuch-show-insert-msg (msg depth)\r
+- "Insert the message MSG at depth DEPTH in the current thread."\r
+- (let* ((headers (plist-get msg :headers))\r
+- ;; Indentation causes the buffer offset of the start/end\r
+- ;; points to move, so we must use markers.\r
+- message-start message-end\r
+- content-start content-end\r
+- headers-start headers-end\r
+- (bare-subject (notmuch-show-strip-re (plist-get headers :Subject))))\r
+-\r
+- (setq message-start (point-marker))\r
+-\r
+- (notmuch-show-insert-headerline headers\r
+- (or (if notmuch-show-relative-dates\r
+- (plist-get msg :date_relative)\r
+- nil)\r
+- (plist-get headers :Date))\r
+- (plist-get msg :tags) depth)\r
+-\r
+- (setq content-start (point-marker))\r
+-\r
+- ;; Set `headers-start' to point after the 'Subject:' header to be\r
+- ;; compatible with the existing implementation. This just sets it\r
+- ;; to after the first header.\r
+- (notmuch-show-insert-headers headers)\r
+- (save-excursion\r
+- (goto-char content-start)\r
+- ;; If the subject of this message is the same as that of the\r
+- ;; previous message, don't display it when this message is\r
+- ;; collapsed.\r
+- (when (not (string= notmuch-show-previous-subject\r
+- bare-subject))\r
+- (forward-line 1))\r
+- (setq headers-start (point-marker)))\r
+- (setq headers-end (point-marker))\r
+-\r
+- (setq notmuch-show-previous-subject bare-subject)\r
+-\r
+- ;; A blank line between the headers and the body.\r
+- (insert "\n")\r
+- (notmuch-show-insert-body msg (plist-get msg :body)\r
+- (if notmuch-show-indent-content depth 0))\r
+- ;; Ensure that the body ends with a newline.\r
+- (unless (bolp)\r
+- (insert "\n"))\r
+- (setq content-end (point-marker))\r
+-\r
+- ;; Indent according to the depth in the thread.\r
+- (if notmuch-show-indent-content\r
+- (indent-rigidly content-start content-end (* notmuch-show-indent-messages-width depth)))\r
+-\r
+- (setq message-end (point-max-marker))\r
+-\r
+- ;; Save the extents of this message over the whole text of the\r
+- ;; message.\r
+- (put-text-property message-start message-end :notmuch-message-extent (cons message-start message-end))\r
+-\r
+- ;; Create overlays used to control visibility\r
+- (plist-put msg :headers-overlay (make-overlay headers-start headers-end))\r
+- (plist-put msg :message-overlay (make-overlay headers-start content-end))\r
+-\r
+- (plist-put msg :depth depth)\r
+-\r
+- ;; Save the properties for this message. Currently this saves the\r
+- ;; entire message (augmented it with other stuff), which seems\r
+- ;; like overkill. We might save a reduced subset (for example, not\r
+- ;; the content).\r
+- (notmuch-show-set-message-properties msg)\r
+-\r
+- ;; Set header visibility.\r
+- (notmuch-show-headers-visible msg notmuch-message-headers-visible)\r
+-\r
+- ;; Message visibility depends on whether it matched the search\r
+- ;; criteria.\r
+- (notmuch-show-message-visible msg (and (plist-get msg :match)\r
+- (not (plist-get msg :excluded))))))\r
+-\r
+ (defun notmuch-show-toggle-process-crypto ()\r
+ "Toggle the processing of cryptographic MIME parts."\r
+ (interactive)\r
+@@ -1018,23 +354,6 @@ If HIDE is non-nil then initially hide this part."\r
+ "Content is not indented."))\r
+ (notmuch-show-refresh-view))\r
+ \r
+-(defun notmuch-show-insert-tree (tree depth)\r
+- "Insert the message tree TREE at depth DEPTH in the current thread."\r
+- (let ((msg (car tree))\r
+- (replies (cadr tree)))\r
+- ;; We test whether there is a message or just some replies.\r
+- (when msg\r
+- (notmuch-show-insert-msg msg depth))\r
+- (notmuch-show-insert-thread replies (1+ depth))))\r
+-\r
+-(defun notmuch-show-insert-thread (thread depth)\r
+- "Insert the thread THREAD at depth DEPTH in the current forest."\r
+- (mapc (lambda (tree) (notmuch-show-insert-tree tree depth)) thread))\r
+-\r
+-(defun notmuch-show-insert-forest (forest)\r
+- "Insert the forest of threads FOREST."\r
+- (mapc (lambda (thread) (notmuch-show-insert-thread thread 0)) forest))\r
+-\r
+ (defvar notmuch-id-regexp\r
+ (concat\r
+ ;; Match the id: prefix only if it begins a word (to disallow, for\r
+@@ -1373,17 +692,6 @@ effects."\r
+ (loop do (funcall function)\r
+ while (notmuch-show-goto-message-next))))\r
+ \r
+-;; Functions relating to the visibility of messages and their\r
+-;; components.\r
+-\r
+-(defun notmuch-show-message-visible (props visible-p)\r
+- (overlay-put (plist-get props :message-overlay) 'invisible (not visible-p))\r
+- (notmuch-show-set-prop :message-visible visible-p props))\r
+-\r
+-(defun notmuch-show-headers-visible (props visible-p)\r
+- (overlay-put (plist-get props :headers-overlay) 'invisible (not visible-p))\r
+- (notmuch-show-set-prop :headers-visible visible-p props))\r
+-\r
+ ;; Functions for setting and getting attributes of the current\r
+ ;; message.\r
+ \r
+-- \r
+1.7.9.1\r
+\r