tm 7.67.
[elisp/tm.git] / tm-view.el
index 4e88e2b..30b5bd1 100644 (file)
@@ -8,7 +8,7 @@
 ;;; modified by Steven L. Baur <steve@miranova.com>
 ;;; Maintainer: MORIOKA Tomohiko <morioka@jaist.ac.jp>
 ;;; Created: 1994/7/13 (1994/8/31 obsolete tm-body.el)
-;;; Version: $Revision: 7.50 $
+;;; Version: $Revision: 7.65 $
 ;;; Keywords: mail, news, MIME, multimedia
 ;;;
 ;;; This file is part of tm (Tools for MIME).
 (require 'tm-ew-d)
 (require 'tm-def)
 (require 'tm-parse)
+(require 'tm-text)
 
 
 ;;; @ version
 ;;;
 
 (defconst mime-viewer/RCS-ID
-  "$Id: tm-view.el,v 7.50 1996/04/21 17:33:21 morioka Exp $")
+  "$Id: tm-view.el,v 7.65 1996/05/23 16:45:10 shuhei-k Exp $")
 
 (defconst mime-viewer/version (get-version-string mime-viewer/RCS-ID))
 (defconst mime/viewer-version mime-viewer/version)
     "application/octet-stream"
     "application/x-selection" "application/x-comment"))
 
-(defvar mime-viewer/content-subject-omitting-Content-Type-list
+(defvar mime-viewer/content-button-ignored-ctype-list
   '("application/x-selection"))
 
-(defvar mime-viewer/content-subject-showing-Content-Type-list
+(defvar mime-viewer/content-button-visible-ctype-list
   '("application/pgp"))
 
 (defvar mime-viewer/uuencode-encoding-name-list '("x-uue" "x-uuencode"))
@@ -135,7 +136,7 @@ Each elements are regexp of field-name. [tm-view.el]")
          ":"))
 
 (defvar mime-viewer/visible-field-list
-  '("Dnas.*")
+  '("Dnas.*" "Message-Id")
   "All fields that match this list will be displayed in MIME preview buffer.
 Each elements are regexp of field-name. [tm-view.el]")
 
@@ -192,54 +193,69 @@ Each elements are regexp of field-name. [tm-view.el]")
     ))
 
 
-;;; @@ content subject
+;;; @@ content button
 ;;;
 
-(defun mime-viewer/insert-content-subject
-  (rcnum cinfo ctype params subj)
+(defun mime-preview/insert-content-button
+  (rcnum cinfo ctype params subj encoding)
   (save-restriction
     (narrow-to-region (point)(point))
-    (insert
-     (let ((access-type (assoc "access-type" params))
-          (num (or (assoc-value "x-part-number" params)
-                   (if (consp rcnum)
-                       (mapconcat (function
-                                   (lambda (num)
-                                     (format "%s" (1+ num))
-                                     ))
-                                  (reverse rcnum) ".")
-                     "0"))
-               ))
-       (if access-type
-          (let ((server (assoc "server" params)))
-            (setq access-type (cdr access-type))
-            (if server
-                (format "[%s %s ([%s] %s)]\n" num subj
-                        access-type (cdr server))
-              (let ((site (assoc-value "site" params))
-                    (dir (assoc-value "directory" params))
-                    )
-                (format "[%s %s ([%s] %s:%s)]\n" num subj
-                        access-type site dir)
-                )))
-        (format "[%s %s (%s)]\n" num subj ctype)
-        )))
+    (let ((access-type (assoc "access-type" params))
+         (charset (assoc "charset" params))
+         (num (or (assoc-value "x-part-number" params)
+                  (if (consp rcnum)
+                      (mapconcat (function
+                                  (lambda (num)
+                                    (format "%s" (1+ num))
+                                    ))
+                                 (reverse rcnum) ".")
+                    "0"))
+              ))
+      (cond (access-type
+            (let ((server (assoc "server" params)))
+              (setq access-type (cdr access-type))
+              (if server
+                  (insert (format "[%s %s ([%s] %s)]\n" num subj
+                                  access-type (cdr server)))
+                (let ((site (assoc-value "site" params))
+                      (dir (assoc-value "directory" params))
+                      )
+                  (insert (format "[%s %s ([%s] %s:%s)]\n" num subj
+                                  access-type site dir))
+                  )))
+            )
+           (t
+            (insert (concat "[" num " " subj))
+            (let ((rest
+                   (if (setq charset (cdr charset))
+                       (if encoding
+                           (format " <%s; %s (%s)>]\n"
+                                   ctype charset encoding)
+                         (format " <%s; %s>]\n" ctype charset)
+                         )
+                     (format " <%s>]\n" ctype)
+                     )))
+              (if (>= (+ (current-column)(length rest))(window-width))
+                  (setq rest (concat "\n\t" rest))
+                )
+              (insert rest)
+              ))))
     (tm:add-button (point-min)(1- (point-max))
                   (function mime-viewer/play-content))
     ))
 
-(defun mime-viewer/default-content-subject-function
-  (rcnum cinfo ctype params subj)
+(defun mime-preview/default-content-button-function
+  (rcnum cinfo ctype params subj encoding)
   (if (and (consp rcnum)
           (not (member
                 ctype
-                mime-viewer/content-subject-omitting-Content-Type-list)))
-      (mime-viewer/insert-content-subject
-       rcnum cinfo ctype params subj)
+                mime-viewer/content-button-ignored-ctype-list)))
+      (mime-preview/insert-content-button
+       rcnum cinfo ctype params subj encoding)
     ))
 
-(defvar mime-viewer/content-subject-function
-  (function mime-viewer/default-content-subject-function))
+(defvar mime-preview/content-button-function
+  (function mime-preview/default-content-button-function))
 
 
 ;;; @@ content header filter
@@ -277,18 +293,16 @@ Each elements are regexp of field-name. [tm-view.el]")
 ;;;
 
 (defvar mime-viewer/content-filter-alist
-  '(("text/plain"      . mime-viewer/filter-text/plain)
-    ("application/pgp" . mime-viewer/filter-text/plain)
-    (nil . mime-viewer/filter-text/plain)))
-
-(defun mime-viewer/default-content-filter (rcnum cinfo ctype params subj)
-  )
+  '(("text/enriched" . mime-preview/filter-for-text/enriched)
+    ("text/richtext" . mime-preview/filter-for-text/richtext)
+    (t . mime-preview/filter-for-text/plain)
+    ))
 
 
 ;;; @@ content separator
 ;;;
 
-(defun mime-viewer/default-content-separator (rcnum cinfo ctype params subj)
+(defun mime-preview/default-content-separator (rcnum cinfo ctype params subj)
   (if (and (not (mime-viewer/header-visible-p rcnum cinfo ctype))
           (not (mime-viewer/body-visible-p rcnum cinfo ctype))
           )
@@ -407,41 +421,36 @@ The compressed face will be piped to this command.")
     ret))
 
 (defun mime-viewer/make-preview-buffer (&optional obuf)
-  (let ((cinfo mime::article/content-info)
-       (the-buf (current-buffer))
-       (mode major-mode)
-       pcl dest)
+  (let* ((cinfo mime::article/content-info)
+        (pcl (mime/flatten-content-info cinfo))
+        (dest (make-list (length pcl) nil))
+        (the-buf (current-buffer))
+        (mode major-mode)
+        )
     (or obuf
-       (setq obuf (concat "*Preview-" (buffer-name the-buf) "*"))
-       )
-    (setq pcl (mime/flatten-content-info cinfo))
-    (let ((bf (get-buffer obuf)))
-      (if bf
-         (progn
-           (set-buffer obuf)
-           (setq buffer-read-only nil)
-           (erase-buffer)
-           )
-       (setq bf (get-buffer-create obuf))
-       (set-buffer obuf)
-       ))
+       (setq obuf (concat "*Preview-" (buffer-name the-buf) "*")))
+    (set-buffer (get-buffer-create obuf))
+    (setq buffer-read-only nil)
+    (widen)
+    (erase-buffer)
     (setq mime::preview/article-buffer the-buf)
     (setq mime::preview/original-major-mode mode)
     (setq major-mode 'mime/viewer-mode)
     (setq mode-name "MIME-View")
-    (while pcl
-      (setq dest
-           (cons (mime-viewer/display-content (car pcl) cinfo the-buf obuf)
-                 dest)
-           pcl (cdr pcl))
-      )
+    (let ((drest dest))
+      (while pcl
+       (setcar drest
+               (mime-preview/display-content (car pcl) cinfo the-buf obuf))
+       (setq pcl (cdr pcl)
+             drest (cdr drest))
+       ))
     (set-buffer-modified-p nil)
     (setq buffer-read-only t)
     (set-buffer the-buf)
-    (list obuf (nreverse dest))
+    (list obuf dest)
     ))
 
-(defun mime-viewer/display-content (content cinfo ibuf obuf)
+(defun mime-preview/display-content (content cinfo ibuf obuf)
   (let* ((beg (mime::content-info/point-min content))
         (end (mime::content-info/point-max content))
         (ctype (mime::content-info/type content))
@@ -466,37 +475,34 @@ The compressed face will be piped to this command.")
     (set-buffer obuf)
     (setq nb (point))
     (narrow-to-region nb nb)
-    (funcall mime-viewer/content-subject-function
-            rcnum cinfo ctype params subj)
-    (set-buffer ibuf)
+    (funcall mime-preview/content-button-function
+            rcnum cinfo ctype params subj encoding)
     (if (mime-viewer/header-visible-p rcnum cinfo ctype)
-       (mime-viewer/display-header beg he obuf)
+       (mime-preview/display-header beg he)
       )
     (if (and (null rcnum)
             (member
-             ctype mime-viewer/content-subject-showing-Content-Type-list))
+             ctype mime-viewer/content-button-visible-ctype-list))
        (save-excursion
-         (set-buffer obuf)
          (goto-char (point-max))
-         (mime-viewer/insert-content-subject rcnum cinfo ctype params subj)
+         (mime-preview/insert-content-button
+          rcnum cinfo ctype params subj encoding)
          ))
     (cond ((mime-viewer/body-visible-p rcnum cinfo ctype)
-          (mime-viewer/display-body he end obuf
-                                    rcnum cinfo ctype params subj encoding)
+          (mime-preview/display-body he end
+                                     rcnum cinfo ctype params subj encoding)
           )
          ((equal ctype "message/partial")
-          (mime-viewer/display-message/partial obuf)
+          (mime-preview/display-message/partial)
           )
          ((and (null rcnum)
                (null (mime::content-info/children cinfo))
                )
-          (set-buffer obuf)
           (goto-char (point-max))
-          (mime-viewer/insert-content-subject rcnum cinfo ctype params subj)
-          )
-         (t (set-buffer obuf))
-         )
-    (mime-viewer/default-content-separator rcnum cinfo ctype params subj)
+          (mime-preview/insert-content-button
+           rcnum cinfo ctype params subj encoding)
+          ))
+    (mime-preview/default-content-separator rcnum cinfo ctype params subj)
     (prog1
        (progn
          (setq ne (point-max))
@@ -506,40 +512,32 @@ The compressed face will be piped to this command.")
       (goto-char ne)
       )))
 
-(defun mime-viewer/display-header (beg end obuf)
-  (let ((str (buffer-substring beg end))
-       (f (assq major-mode mime-viewer/content-header-filter-alist))
-       )
-    (save-excursion
-      (set-buffer obuf)
-      (save-restriction
-       (narrow-to-region (point)(point))
-       (insert str)
-       (if (and f (setq f (cdr f)))
-           (funcall f)
-         (mime-viewer/default-content-header-filter)
-         )
-       (run-hooks 'mime-viewer/content-header-filter-hook)
-       ))))
+(defun mime-preview/display-header (beg end)
+  (save-restriction
+    (narrow-to-region (point)(point))
+    (insert-buffer-substring mime::preview/article-buffer beg end)
+    (let ((f (cdr (assq mime::preview/original-major-mode
+                       mime-viewer/content-header-filter-alist))))
+      (if (functionp f)
+         (funcall f)
+       (mime-viewer/default-content-header-filter)
+       ))
+    (run-hooks 'mime-viewer/content-header-filter-hook)
+    ))
 
-(defun mime-viewer/display-body (beg end obuf
-                                    rcnum cinfo ctype params subj encoding)
-  (let ((str (buffer-substring beg end))
-       be)
-    (set-buffer obuf)
-    (save-restriction
-      (setq be (point-max))
-      (narrow-to-region be be)
-      (insert str)
-      (let ((f (assoc-value ctype mime-viewer/content-filter-alist)))
-       (if (and f (fboundp f))
-           (funcall f ctype params encoding)
-         (mime-viewer/default-content-filter rcnum cinfo ctype params subj)
-         ))
+(defun mime-preview/display-body (beg end
+                                     rcnum cinfo ctype params subj encoding)
+  (save-restriction
+    (narrow-to-region (point-max)(point-max))
+    (insert-buffer-substring mime::preview/article-buffer beg end)
+    (let ((f (cdr (or (assoc ctype mime-viewer/content-filter-alist)
+                     (assq t mime-viewer/content-filter-alist)))))
+      (and (functionp f)
+          (funcall f ctype params encoding)
+          )
       )))
 
-(defun mime-viewer/display-message/partial (obuf)
-  (set-buffer obuf)
+(defun mime-preview/display-message/partial ()
   (save-restriction
     (goto-char (point-max))
     (if (not (search-backward "\n\n" nil t))
@@ -665,59 +663,6 @@ The compressed face will be piped to this command.")
     ))
 
 
-;;; @ content filter
-;;;
-
-(defvar mime-viewer/code-converter-alist
-  '((mime/show-message-mode      . mime/code-convert-region-to-emacs)
-    (mime/temporary-message-mode . mime/code-convert-region-to-emacs)
-    ))
-
-(defun mime-viewer/default-code-convert-region
-  (beg end charset &optional encoding)
-  (if (member encoding '("quoted-printable" "base64"))
-      (mime/code-convert-region-to-emacs beg (point-max) charset)
-    ))
-
-(defun mime-preview/decode-text-region (beg end charset encoding)
-  (mime/decode-region encoding beg end)
-  (let* ((mode mime::preview/original-major-mode)
-        (m (or (save-excursion
-                 (set-buffer mime::preview/article-buffer)
-                 mime::article/code-converter)
-               (cdr (assq mode mime-viewer/code-converter-alist))
-               ))
-        )
-    (if (and m (fboundp m))
-       (funcall m beg (point-max) charset encoding)
-      (mime-viewer/default-code-convert-region
-       beg (point-max) charset encoding)
-      )))
-
-(defun mime-viewer/filter-text/plain (ctype params encoding)
-  (let ((charset (cdr (assoc "charset" params)))
-       (beg (point-min)) (end (point-max))
-       )
-    (mime-preview/decode-text-region beg end charset encoding)
-    )
-  (goto-char (point-max))
-  (if (not (eq (char-after (1- (point))) ?\n))
-      (insert "\n")
-    )
-  (if browse-url-browser-function
-      (progn
-       (goto-char (point-min))
-       (while (re-search-forward tm:URL-regexp nil t)
-         (let ((beg (match-beginning 0))
-               (end (match-end 0)))
-           (tm:add-button beg end
-                          (function tm:browse-url)
-                          (list (buffer-substring beg end))))
-         )))
-  (run-hooks 'mime-viewer/plain-text-preview-hook)
-  )
-
-
 ;;; @ MIME viewer mode
 ;;;
 
@@ -776,6 +721,8 @@ The compressed face will be piped to this command.")
         "<"        (function beginning-of-buffer))
       (define-key mime/viewer-mode-map
         ">"        (function end-of-buffer))
+      (define-key mime/viewer-mode-map
+        "?"        (function describe-mode))
       (if mouse-button-2
          (define-key mime/viewer-mode-map
            mouse-button-2 (function tm:button-dispatcher))
@@ -832,7 +779,8 @@ M-RET               Move to previous line
 v              Decode current content as `play mode'
 e              Decode current content as `extract mode'
 C-c C-p                Decode current content as `print mode'
-f              Display X-Face
+a              Followup to current content.
+x              Display X-Face
 q              Quit
 button-2       Move to point under the mouse cursor
                and decode current content as `play mode'
@@ -959,77 +907,55 @@ listed in key order:
               (new-name (format "%s-%s" (buffer-name) (reverse rcnum)))
               new-buf
               (the-buf (current-buffer))
-              from to cc reply-to subj mid f)
-         (save-excursion
-           (set-buffer mime::preview/article-buffer)
-           (setq from (rfc822/get-field-body "From")
-                 to (rfc822/get-field-body "To")
-                 cc (rfc822/get-field-body "cc")
-                 reply-to (rfc822/get-field-body "Reply-To")
-                 subj (rfc822/get-field-body "Subject")
-                 mid (rfc822/get-field-body "Message-Id")
-                 ))
+              (a-buf mime::preview/article-buffer)
+              (hb (mime::content-info/point-min cinfo))
+              (he (mime::content-info/point-max cinfo))
+              fields from to cc reply-to subj mid f)
          (save-excursion
            (set-buffer (setq new-buf (get-buffer-create new-name)))
            (erase-buffer)
            (insert-buffer-substring the-buf p-beg p-end)
            (goto-char (point-min))
            (if (mime-viewer/header-visible-p rcnum root-cinfo)
-               (setq mid nil)
-             (insert "\n")
+               (delete-region (goto-char (point-min))
+                              (if (re-search-forward "^$" nil t)
+                                  (match-end 0)
+                                (point-min)))
              )
            (goto-char (point-min))
-           (if (setq f (rfc822/get-field-body "From"))
-               (setq from f)
-             (and from
-                  (insert (format "From: %s\n"
-                                  (mime-eword/decode-string from)))
-                  ))
-           (if (setq f (rfc822/get-field-body "To"))
-               (setq to f)
-             (and to
-                  (insert (format "To: %s\n"
-                                  (mime-eword/decode-string to)))
-                  ))
-           (if (setq f (rfc822/get-field-body "cc"))
-               (setq cc f)
-             (and cc
-                  (insert (format "cc: %s\n"
-                                  (mime-eword/decode-string cc)))
-                  ))
-           (if (setq f (rfc822/get-field-body "Reply-To"))
-               (setq reply-to f)
-             (and reply-to
-                  (insert (format "Reply-To: %s\n"
-                                  (mime-eword/decode-string reply-to)))
-                  ))
-           (if (setq f (or (rfc822/get-field-body "Subject")
-                           (rfc822/get-field-body "Content-Description")))
-               (setq subj f)
-             (and subj
-                  (insert (format "Subject: %s\n"
-                                  (mime-eword/decode-string subj)))
-                  ))
-           (if (setq f (rfc822/get-field-body "Message-Id"))
-               (setq mid f)
-             (and mid
-                  (insert (format "Message-Id: %s\n"
-                                  (mime-eword/decode-string mid)))
-                  ))
-           (goto-char (point-max))
-           (funcall (cdr (assq mode mime-viewer/following-method-alist))
-                    (or reply-to
-                        (if (string-equal
-                             (nth 1 (rfc822/extract-address-components from))
-                             user-mail-address)
-                            to
-                          from))
-                    cc (and subj
-                            (if (string-match "^Re:" subj)
-                                subj
-                              (concat "Re: " subj))
-                            ))
-           )))))
+           (insert "\n")
+           (goto-char (point-min))
+           (let ((rcnum (mime::content-info/rcnum cinfo)) ci str)
+             (while (progn
+                      (setq str
+                            (save-excursion
+                              (set-buffer a-buf)
+                              (setq ci (mime-article/rcnum-to-cinfo rcnum))
+                              (save-restriction
+                                (narrow-to-region
+                                 (mime::content-info/point-min ci)
+                                 (mime::content-info/point-max ci)
+                                 )
+                                (rfc822/get-header-string-except
+                                 (concat "^"
+                                         (apply (function regexp-or) fields)
+                                         ":") ""))))
+                      (if (string-equal (mime::content-info/type ci)
+                                        "message/rfc822")
+                          nil
+                        (if str
+                            (insert str)
+                          )
+                        rcnum))
+               (setq fields (rfc822/get-field-names)
+                     rcnum (cdr rcnum))
+               )
+             )
+           (mime/decode-message-header)
+           )
+         (funcall (cdr (assq mode mime-viewer/following-method-alist))
+                  new-buf)
+         ))))
 
 (defun mime-viewer/display-x-face ()
   (interactive)