(eword-lexical-analyze): `last' of Emacs 20.0.97 allows two arguments.
[elisp/semi.git] / mime-view.el
index d8d7b2b..bbd01a3 100644 (file)
@@ -6,7 +6,7 @@
 ;; Created: 1994/7/13
 ;;     Renamed: 1994/8/31 from tm-body.el
 ;;     Renamed: 1997/02/19 from tm-view.el
-;; Version: $Revision: 0.67 $
+;; Version: $Revision: 0.97 $
 ;; Keywords: MIME, multimedia, mail, news
 
 ;; This file is part of SEMI (SEMI is Emacs MIME Interfaces).
 ;;;
 
 (defconst mime-view-RCS-ID
-  "$Id: mime-view.el,v 0.67 1997-03-18 08:08:44 morioka Exp $")
+  "$Id: mime-view.el,v 0.97 1997-07-14 15:15:17 morioka Exp $")
 
-(defconst mime-view-version (get-version-string mime-view-RCS-ID))
+(defconst mime-view-version
+  `,(get-version-string mime-view-RCS-ID))
+
+(defconst mime-view-version-name
+  `,(concat "SEMI MIME-View " mime-view-version
+           " (" semi-version-name ")"))
 
 
 ;;; @ variables
 ;;;
 
-(defvar mime/content-decoding-condition
+(defvar mime-acting-condition
   '(((type . "text/plain")
      (method "tm-plain" nil 'file 'type 'encoding 'mode 'name)
      (mode "play" "print")
      (mode . "play")
      )
     ((type . "text/x-rot13-47")
-     (method . mime-article/decode-caesar)
+     (method . mime-display-caesar)
+     (mode . "play")
+     )
+    ((type . "text/x-rot13-47-48")
+     (method . mime-display-caesar)
      (mode . "play")
      )
     ((type . "audio/basic")
      (method "tm-image" nil 'file 'type 'encoding 'mode 'name)
      (mode "play" "print")
      )
+    ((type . "image/png")
+     (method "tm-image" nil 'file 'type 'encoding 'mode 'name)
+     (mode "play" "print")
+     )
     ((type . "image/tiff")
      (method "tm-image" nil 'file 'type 'encoding 'mode 'name)
      (mode "play" "print")
     ;;         'file '"access-type" '"name" '"site" '"directory"))
     ((type . "message/external-body")
      ("access-type" . "anon-ftp")
-     (method . mime-article/decode-message/external-ftp)
+     (method . mime-display-message/external-ftp)
      )
     ((type . "message/rfc822")
-     (method . mime-article/view-message/rfc822)
+     (method . mime-display-message/rfc822)
      (mode . "play")
      )
     ((type . "message/partial")
-     (method . mime-article/decode-message/partial)
+     (method . mime-display-message/partial)
      (mode . "play")
      )
     
@@ -222,50 +235,47 @@ Each elements are regexp of field-name.")
 
 (defun mime-view-insert-entity-button (rcnum cinfo ctype params subj encoding)
   "Insert entity-button."
-  (save-restriction
-    (narrow-to-region (point)(point))
-    (let ((access-type (assoc "access-type" params))
-         (num (or (cdr (assoc "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 (cdr (assoc "site" params)))
-                      (dir (cdr (assoc "directory" params)))
-                      )
-                  (insert (format "[%s %s ([%s] %s:%s)]\n" num subj
-                                  access-type site dir))
-                  )))
-            )
-           (t
-            (let ((charset (cdr (assoc "charset" params))))
-              (insert (concat "[" num " " subj))
+  (mime-insert-button
+   (let ((access-type (assoc "access-type" params))
+        (num (or (cdr (assoc "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
+                 (format "%s %s ([%s] %s)"
+                         num subj access-type (cdr server))
+               (let ((site (cdr (assoc "site" params)))
+                     (dir (cdr (assoc "directory" params)))
+                     )
+                 (format "%s %s ([%s] %s:%s)"
+                         num subj access-type site dir)
+                 )))
+           )
+          (t
+           (let ((charset (cdr (assoc "charset" params))))
+             (concat
+              num " " subj
               (let ((rest
                      (concat " <" ctype
                              (if charset
                                  (concat "; " charset)
                                (if encoding (concat " (" encoding ")"))
                                )
-                             ">]\n")))
+                             ">")))
                 (if (>= (+ (current-column)(length rest))(window-width))
-                    (insert "\n\t")
-                  )
-                (insert rest)
-                ))))
-      )
-    (mime-add-button (point-min)(1- (point-max))
-                    (function mime-view-play-current-entity))
-    ))
+                    "\n\t")
+                rest)))
+           )))
+   (function mime-view-play-current-entity))
+  )
 
 (defun mime-view-entity-button-function
   (rcnum cinfo ctype params subj encoding)
@@ -296,9 +306,10 @@ Please redefine this function if you want to change default setting."
                        (string-match regexp name)
                        )) mime-view-visible-field-list)
          (delete-region beg
-                        (if (re-search-forward "^\\([^ \t]\\|$\\)" nil t)
-                            (match-beginning 0)
-                          (point-max)))
+                        (save-excursion
+                          (if (re-search-forward "^\\([^ \t]\\|$\\)" nil t)
+                              (match-beginning 0)
+                            (point-max))))
          ))))
 
 (defun mime-view-default-content-header-filter ()
@@ -313,10 +324,14 @@ Please redefine this function if you want to change default setting."
 ;;;
 
 (defvar mime-view-content-filter-alist
-  '(("text/enriched" . mime-preview/filter-for-text/enriched)
-    ("text/richtext" . mime-preview/filter-for-text/richtext)
-    (t . mime-preview/filter-for-text/plain)
-    ))
+  '(("text/enriched" . mime-view-filter-for-text/enriched)
+    ("text/richtext" . mime-view-filter-for-text/richtext)
+    (t . mime-view-filter-for-text/plain)
+    )
+  "Alist of media-types vs. corresponding MIME-View filter functions.
+Each element looks like (TYPE/SUBTYPE . FUNCTION) or (t . FUNCTION).
+TYPE/SUBTYPE is a string of media-type and FUNCTION is a filter
+function.  t means default media-type.")
 
 
 ;;; @@ entity separator
@@ -339,22 +354,48 @@ Please redefine this function if you want to change default setting."
 ;;; @@@ in raw buffer
 ;;;
 
+(defvar mime::article/content-info
+  "Information about structure of message.
+Please use reference function `mime::content-info/SLOT-NAME' to
+reference slot of content-info.  Their argument is only content-info.
+
+Following is a list of slots of the structure:
+
+rcnum          reversed content-number (list)
+point-min      beginning point of region in raw-buffer
+point-max      end point of region in raw-buffer
+type           media-type/subtype (string or nil)
+parameters     parameter of Content-Type field (association list)
+encoding       Content-Transfer-Encoding (string or nil)
+children       entities included in this entity (list of content-infos)
+
+If a entity includes other entities in its body, such as multipart or
+message/rfc822, content-infos of other entities are included in
+`children', so content-info become a tree.")
 (make-variable-buffer-local 'mime::article/content-info)
 
-(defvar mime::article/preview-buffer nil)
-(make-variable-buffer-local 'mime::article/preview-buffer)
+(defvar mime-view-buffer nil
+  "MIME View buffer corresponding with the (raw) buffer.")
+(make-variable-buffer-local 'mime-view-buffer)
 
 
 ;;; @@@ in view buffer
 ;;;
 
-(make-variable-buffer-local 'mime::preview/mother-buffer)
-(make-variable-buffer-local 'mime::preview/content-list)
+(defvar mime-mother-buffer nil
+  "Mother buffer corresponding with the (MIME-View) buffer.
+If current MIME-View buffer is generated by other buffer, such as
+message/partial, it is called `mother-buffer'.")
+(make-variable-buffer-local 'mime-mother-buffer)
+
+(defvar mime-raw-buffer nil
+  "Raw buffer corresponding with the (MIME-View) buffer.")
+(make-variable-buffer-local 'mime-raw-buffer)
 
-(defvar mime::preview/article-buffer nil)
-(make-variable-buffer-local 'mime::preview/article-buffer)
+(defvar mime-view-original-major-mode nil
+  "Major-mode in mime-raw-buffer.")
+(make-variable-buffer-local 'mime-view-original-major-mode)
 
-(make-variable-buffer-local 'mime::preview/original-major-mode)
 (make-variable-buffer-local 'mime::preview/original-window-configuration)
 
 
@@ -376,7 +417,8 @@ Please redefine this function if you want to change default setting."
 ;;; @@ following method
 ;;;
 
-(defvar mime-view-following-method-alist nil)
+(defvar mime-view-following-method-alist nil
+  "Alist of major-mode vs. following-method of mime-view.")
 
 (defvar mime-view-following-required-fields-list
   '("From"))
@@ -414,32 +456,10 @@ The compressed face will be piped to this command.")
          ))))
 
 
-;;; @@ utility
-;;;
-
-(defun mime-preview/get-original-major-mode ()
-  (if mime::preview/mother-buffer
-      (save-excursion
-       (set-buffer mime::preview/mother-buffer)
-       (mime-preview/get-original-major-mode)
-       )
-    mime::preview/original-major-mode))
-
-
-;;; @ data structures
-;;;
-
-;;; @@ preview-content-info
-;;;
-
-(define-structure mime::preview-content-info
-  point-min point-max buffer content-info)
-
-
 ;;; @ buffer setup
 ;;;
 
-(defun mime-view-setup-buffer (&optional ctl encoding ibuf obuf)
+(defun mime-view-setup-buffers (&optional ctl encoding ibuf obuf)
   (if ibuf
       (progn
        (get-buffer ibuf)
@@ -448,39 +468,33 @@ The compressed face will be piped to this command.")
   (or mime-view-redisplay
       (setq mime::article/content-info (mime-parse-message ctl encoding))
       )
-  (let ((ret (mime-view-make-preview-buffer obuf)))
-    (setq mime::article/preview-buffer (car ret))
-    ret))
-
-(defun mime-view-make-preview-buffer (&optional obuf)
   (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) "*")))
     (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-view-mode)
-    (setq mode-name "MIME-View")
-    (let ((drest dest))
+    (let ((inhibit-read-only t))
+      ;;(setq buffer-read-only nil)
+      (widen)
+      (erase-buffer)
+      (setq mime-raw-buffer the-buf)
+      (setq mime-view-original-major-mode mode)
+      (setq major-mode 'mime-view-mode)
+      (setq mode-name "MIME-View")
       (while pcl
-       (setcar drest
-               (mime-view-display-entity (car pcl) cinfo the-buf obuf))
-       (setq pcl (cdr pcl)
-             drest (cdr drest))
-       ))
-    (set-buffer-modified-p nil)
+       (mime-view-display-entity (car pcl) cinfo the-buf obuf)
+       (setq pcl (cdr pcl))
+       )
+      (set-buffer-modified-p nil)
+      )
     (setq buffer-read-only t)
     (set-buffer the-buf)
-    (list obuf dest)
-    ))
+    )
+  (setq mime-view-buffer obuf)
+  )
 
 (defun mime-view-display-entity (content cinfo ibuf obuf)
   "Display entity from content-info CONTENT."
@@ -525,7 +539,7 @@ The compressed face will be piped to this command.")
                                      rcnum cinfo ctype params subj encoding)
           )
          ((equal ctype "message/partial")
-          (mime-preview/display-message/partial)
+          (mime-view-insert-message/partial-button)
           )
          ((and (null rcnum)
                (null (mime::content-info/children cinfo))
@@ -535,22 +549,18 @@ The compressed face will be piped to this command.")
            rcnum cinfo ctype params subj encoding)
           ))
     (mime-view-entity-separator-function rcnum cinfo ctype params subj)
-    (prog1
-       (progn
-         (setq ne (point-max))
-         (widen)
-         (put-text-property nb ne 'mime-view-raw-buffer ibuf)
-         (put-text-property nb ne 'mime-view-cinfo content)
-         (mime::preview-content-info/create nb (1- ne) ibuf content)
-         )
-      (goto-char ne)
-      )))
+    (setq ne (point-max))
+    (widen)
+    (put-text-property nb ne 'mime-view-raw-buffer ibuf)
+    (put-text-property nb ne 'mime-view-cinfo content)
+    (goto-char ne)
+    ))
 
 (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
+    (insert-buffer-substring mime-raw-buffer beg end)
+    (let ((f (cdr (assq mime-view-original-major-mode
                        mime-view-content-header-filter-alist))))
       (if (functionp f)
          (funcall f)
@@ -563,7 +573,7 @@ The compressed face will be piped to this command.")
                                      rcnum cinfo ctype params subj encoding)
   (save-restriction
     (narrow-to-region (point-max)(point-max))
-    (insert-buffer-substring mime::preview/article-buffer beg end)
+    (insert-buffer-substring mime-raw-buffer beg end)
     (let ((f (cdr (or (assoc ctype mime-view-content-filter-alist)
                      (assq t mime-view-content-filter-alist)))))
       (and (functionp f)
@@ -571,18 +581,18 @@ The compressed face will be piped to this command.")
           )
       )))
 
-(defun mime-preview/display-message/partial ()
+(defun mime-view-insert-message/partial-button ()
   (save-restriction
     (goto-char (point-max))
     (if (not (search-backward "\n\n" nil t))
        (insert "\n")
       )
-    (let ((be (point-max)))
-      (narrow-to-region be be)
-      (insert mime-view-announcement-for-message/partial)
-      (mime-add-button (point-min)(point-max)
-                      (function mime-view-play-current-entity))
-      )))
+    (goto-char (point-max))
+    (narrow-to-region (point-max)(point-max))
+    (insert mime-view-announcement-for-message/partial)
+    (mime-add-button (point-min)(point-max)
+                    (function mime-view-play-current-entity))
+    ))
 
 (defun mime-article/get-uu-filename (param &optional encoding)
   (if (member (or encoding
@@ -746,23 +756,33 @@ The compressed face will be piped to this command.")
     (define-key mime-view-mode-map
       "\C-c\C-p" (function mime-view-print-current-entity))
     (define-key mime-view-mode-map
-      "a"        (function mime-view-follow-content))
+      "a"        (function mime-view-follow-current-entity))
     (define-key mime-view-mode-map
       "q"        (function mime-view-quit))
     (define-key mime-view-mode-map
       "h"        (function mime-view-show-summary))
     (define-key mime-view-mode-map
       "\C-c\C-x" (function mime-view-kill-buffer))
+    ;; (define-key mime-view-mode-map
+    ;;   "<"        (function beginning-of-buffer))
+    ;; (define-key mime-view-mode-map
+    ;;   ">"        (function end-of-buffer))
     (define-key mime-view-mode-map
-      "<"        (function beginning-of-buffer))
+      "?"        (function describe-mode))
     (define-key mime-view-mode-map
-      ">"        (function end-of-buffer))
+      [tab] (function mime-view-move-to-next))
     (define-key mime-view-mode-map
-      "?"        (function describe-mode))
+      [delete] (function mime-view-scroll-down-entity))
+    (define-key mime-view-mode-map
+      [backspace] (function mime-view-scroll-down-entity))
     (if (functionp default)
-       (setq mime-view-mode-map
-             (append mime-view-mode-map (list (cons t default)))
-             ))
+       (cond (running-xemacs
+              (set-keymap-default-binding mime-view-mode-map default)
+              )
+             (t
+              (setq mime-view-mode-map
+                    (append mime-view-mode-map (list (cons t default))))
+              )))
     (if mouse-button-2
        (define-key mime-view-mode-map
          mouse-button-2 (function mime-button-dispatcher))
@@ -789,6 +809,13 @@ The compressed face will be piped to this command.")
     (run-hooks 'mime-view-define-keymap-hook)
     ))
 
+(defsubst mime-hide-echo-buffer ()
+  "Hide mime-echo buffer."
+  (let ((win (get-buffer-window mime-echo-buffer-name)))
+    (if win
+       (delete-window win)
+      )))
+
 (defun mime-view-mode (&optional mother ctl encoding ibuf obuf
                                 default-keymap-or-function)
   "Major mode for viewing MIME message.
@@ -815,45 +842,44 @@ button-2  Move to point under the mouse cursor
                and decode current content as `play mode'
 "
   (interactive)
-  (let ((buf (get-buffer mime/output-buffer-name)))
+  (let ((buf (get-buffer mime-echo-buffer-name)))
     (if buf
        (save-excursion
          (set-buffer buf)
          (erase-buffer)
+         (mime-hide-echo-buffer)
          )))
-  (let ((ret (mime-view-setup-buffer ctl encoding ibuf obuf))
+  (let ((ret (mime-view-setup-buffers ctl encoding ibuf obuf))
        (win-conf (current-window-configuration))
        )
     (prog1
-       (switch-to-buffer (car ret))
+       (switch-to-buffer ret)
       (setq mime::preview/original-window-configuration win-conf)
       (if mother
          (progn
-           (setq mime::preview/mother-buffer mother)
+           (setq mime-mother-buffer mother)
            ))
       (mime-view-define-keymap default-keymap-or-function)
-      (setq mime::preview/content-list (nth 1 ret))
-      (goto-char
-       (let ((ce (mime::preview-content-info/point-max
-                 (car mime::preview/content-list)
-                 ))
-            e)
-        (goto-char (point-min))
-        (search-forward "\n\n" nil t)
-        (setq e (match-end 0))
-        (if (<= e ce)
-            e
-          ce)))
+      (let ((point (next-single-property-change (point-min) 'mime-view-cinfo)))
+       (if point
+           (goto-char point)
+         (goto-char (point-min))
+         (search-forward "\n\n" nil t)
+         ))
       (run-hooks 'mime-view-mode-hook)
       )))
 
+
+;;; @@ playing
+;;;
+
 (autoload 'mime-view-play-current-entity "mime-play" "Play current entity." t)
 
 (defun mime-view-extract-current-entity ()
   "Extract current entity into file (maybe).
 It decodes current entity to call internal or external method as
 \"extract\" mode.  The method is selected from variable
-`mime/content-decoding-condition'."
+`mime-acting-condition'."
   (interactive)
   (mime-view-play-current-entity "extract")
   )
@@ -862,131 +888,171 @@ It decodes current entity to call internal or external method as
   "Print current entity (maybe).
 It decodes current entity to call internal or external method as
 \"print\" mode.  The method is selected from variable
-`mime/content-decoding-condition'."
+`mime-acting-condition'."
   (interactive)
   (mime-view-play-current-entity "print")
   )
 
-(defun mime-view-follow-content ()
+
+;;; @@ following
+;;;
+
+(defun mime-view-get-original-major-mode ()
+  "Return major-mode of original buffer.
+If a current buffer has mime-mother-buffer, return original major-mode
+of the mother-buffer."
+  (if mime-mother-buffer
+      (save-excursion
+       (set-buffer mime-mother-buffer)
+       (mime-view-get-original-major-mode)
+       )
+    mime-view-original-major-mode))
+
+(defun mime-view-follow-current-entity ()
+  "Write follow message to current entity.
+It calls following-method selected from variable
+`mime-view-following-method-alist'."
   (interactive)
-  (let ((root-cinfo
-        (mime::preview-content-info/content-info
-         (car mime::preview/content-list)))
-       pc p-beg p-end cinfo rcnum)
-    (let ((rest mime::preview/content-list)
-         b e cell len rc)
-      (if (catch 'tag
-           (while (setq cell (car rest))
-             (setq b (mime::preview-content-info/point-min cell)
-                   e (mime::preview-content-info/point-max cell))
-             (setq rest (cdr rest))
-             (if (and (<= b (point))(<= (point) e))
-                 (throw 'tag cell)
-               )
-             ))
-         (progn
-           (setq pc cell
-                 cinfo (mime::preview-content-info/content-info pc)
-                 rcnum (mime::content-info/rcnum cinfo))
-           (setq len (length rcnum))
-           (setq p-beg (mime::preview-content-info/point-min pc)
-                 p-end (mime::preview-content-info/point-max pc))
-           (while (and (setq cell (car rest))
-                       (progn
-                         (setq rc
-                               (mime::content-info/rcnum
-                                (mime::preview-content-info/content-info
-                                 cell)))
-                         (equal rcnum
-                                (nthcdr (- (length rc) len) rc))
-                         ))
-             (setq p-end (mime::preview-content-info/point-max cell))
-             (setq rest (cdr rest))
-             ))))
-    (if pc
-       (let* ((mode (mime-preview/get-original-major-mode))
-              (new-name (format "%s-%s" (buffer-name) (reverse rcnum)))
-              new-buf
-              (the-buf (current-buffer))
-              (a-buf mime::preview/article-buffer)
-              fields)
-         (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-view-header-visible-p rcnum root-cinfo)
-               (delete-region (goto-char (point-min))
-                              (if (re-search-forward "^$" nil t)
-                                  (match-end 0)
-                                (point-min)))
-             )
-           (goto-char (point-min))
-           (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)
-                                 )
-                                (std11-header-string-except
-                                 (concat "^"
-                                         (apply (function regexp-or) fields)
-                                         ":") ""))))
-                      (if (string= (mime::content-info/type ci)
-                                   "message/rfc822")
-                          nil
-                        (if str
-                            (insert str)
-                          )
-                        rcnum))
-               (setq fields (std11-collect-field-names)
-                     rcnum (cdr rcnum))
-               )
+  (let ((root-cinfo (get-text-property (point-min) 'mime-view-cinfo))
+       cinfo)
+    (while (null (setq cinfo (get-text-property (point) 'mime-view-cinfo)))
+      (backward-char)
+      )
+    (let* ((p-beg (previous-single-property-change (point) 'mime-view-cinfo))
+          p-end
+          (rcnum (mime::content-info/rcnum cinfo))
+          (len (length rcnum))
+          )
+      (cond ((null p-beg)
+            (setq p-beg
+                  (if (eq (next-single-property-change (point-min)
+                                                       'mime-view-cinfo)
+                          (point))
+                      (point)
+                    (point-min)))
+            )
+           ((eq (next-single-property-change p-beg 'mime-view-cinfo)
+                (point))
+            (setq p-beg (point))
+            ))
+      (setq p-end (next-single-property-change p-beg 'mime-view-cinfo))
+      (cond ((null p-end)
+            (setq p-end (point-max))
+            )
+           ((null rcnum)
+            (setq p-end (point-max))
+            )
+           (t
+            (save-excursion
+              (goto-char p-end)
+              (catch 'tag
+                (let (e)
+                  (while (setq e
+                               (next-single-property-change
+                                (point) 'mime-view-cinfo))
+                    (goto-char e)
+                    (let ((rc (mime::content-info/rcnum
+                               (get-text-property (point)
+                                                  'mime-view-cinfo))))
+                      (or (equal rcnum (nthcdr (- (length rc) len) rc))
+                          (throw 'tag nil)
+                          ))
+                    (setq p-end e)
+                    ))
+                (setq p-end (point-max))
+                ))
+            ))
+      (let* ((mode (mime-view-get-original-major-mode))
+            (new-name (format "%s-%s" (buffer-name) (reverse rcnum)))
+            new-buf
+            (the-buf (current-buffer))
+            (a-buf mime-raw-buffer)
+            fields)
+       (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-view-header-visible-p rcnum root-cinfo)
+             (delete-region (goto-char (point-min))
+                            (if (re-search-forward "^$" nil t)
+                                (match-end 0)
+                              (point-min)))
+           )
+         (goto-char (point-min))
+         (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)
+                               )
+                              (std11-header-string-except
+                               (concat "^"
+                                       (apply (function regexp-or) fields)
+                                       ":") ""))))
+                    (if (string= (mime::content-info/type ci)
+                                 "message/rfc822")
+                        nil
+                      (if str
+                          (insert str)
+                        )
+                      rcnum))
+             (setq fields (std11-collect-field-names)
+                   rcnum (cdr rcnum))
              )
-           (let ((rest mime-view-following-required-fields-list))
-             (while rest
-               (let ((field-name (car rest)))
-                 (or (std11-field-body field-name)
-                     (insert
-                      (format
-                       (concat field-name
-                               ": "
-                               (save-excursion
-                                 (set-buffer the-buf)
-                                 (set-buffer mime::preview/mother-buffer)
-                                 (set-buffer mime::preview/article-buffer)
-                                 (std11-field-body field-name)
-                                 )
-                               "\n")))
-                     ))
-               (setq rest (cdr rest))
-               ))
-           (eword-decode-header)
            )
-         (let ((f (cdr (assq mode mime-view-following-method-alist))))
-           (if (functionp f)
-               (funcall f new-buf)
-             (message
-              (format
-               "Sorry, following method for %s is not implemented yet."
-               mode))
+         (let ((rest mime-view-following-required-fields-list))
+           (while rest
+             (let ((field-name (car rest)))
+               (or (std11-field-body field-name)
+                   (insert
+                    (format
+                     (concat field-name
+                             ": "
+                             (save-excursion
+                               (set-buffer the-buf)
+                               (set-buffer mime-mother-buffer)
+                               (set-buffer mime-raw-buffer)
+                               (std11-field-body field-name)
+                               )
+                             "\n")))
+                   ))
+             (setq rest (cdr rest))
              ))
-         ))))
+         (eword-decode-header)
+         )
+       (let ((f (cdr (assq mode mime-view-following-method-alist))))
+         (if (functionp f)
+             (funcall f new-buf)
+           (message
+            (format
+             "Sorry, following method for %s is not implemented yet."
+             mode))
+           ))
+       ))))
+
+
+;;; @@ X-Face
+;;;
 
 (defun mime-view-display-x-face ()
   (interactive)
   (save-window-excursion
-    (set-buffer mime::preview/article-buffer)
+    (set-buffer mime-raw-buffer)
     (mime-view-x-face-function)
     ))
 
+
+;;; @@ moving
+;;;
+
 (defun mime-view-move-to-upper ()
   "Move to upper entity.
 If there is no upper entity, call function `mime-view-quit'."
@@ -1021,7 +1087,7 @@ variable `mime-view-over-to-previous-method-alist'."
   (let ((point (previous-single-property-change (point) 'mime-view-cinfo)))
     (if point
        (goto-char point)
-      (let ((f (assq mime::preview/original-major-mode
+      (let ((f (assq mime-view-original-major-mode
                     mime-view-over-to-previous-method-alist)))
        (if f
            (funcall (cdr f))
@@ -1036,7 +1102,7 @@ variable `mime-view-over-to-next-method-alist'."
   (let ((point (next-single-property-change (point) 'mime-view-cinfo)))
     (if point
        (goto-char point)
-      (let ((f (assq mime::preview/original-major-mode
+      (let ((f (assq mime-view-original-major-mode
                     mime-view-over-to-next-method-alist)))
        (if f
            (funcall (cdr f))
@@ -1052,7 +1118,7 @@ If reached to (point-max), it calls function registered in variable
       (setq h (1- (window-height)))
       )
   (if (= (point) (point-max))
-      (let ((f (assq mime::preview/original-major-mode
+      (let ((f (assq mime-view-original-major-mode
                      mime-view-over-to-next-method-alist)))
         (if f
             (funcall (cdr f))
@@ -1075,7 +1141,7 @@ If reached to (point-min), it calls function registered in variable
       (setq h (1- (window-height)))
       )
   (if (= (point) (point-min))
-      (let ((f (assq mime::preview/original-major-mode
+      (let ((f (assq mime-view-original-major-mode
                      mime-view-over-to-previous-method-alist)))
         (if f
             (funcall (cdr f))
@@ -1108,12 +1174,16 @@ If reached to (point-min), it calls function registered in variable
   (mime-view-scroll-down-entity 1)
   )
 
+
+;;; @@ quitting
+;;;
+
 (defun mime-view-quit ()
   "Quit from MIME-View buffer.
 It calls function registered in variable
 `mime-view-quitting-method-alist'."
   (interactive)
-  (let ((r (assq mime::preview/original-major-mode
+  (let ((r (assq mime-view-original-major-mode
                 mime-view-quitting-method-alist)))
     (if r
        (funcall (cdr r))
@@ -1124,7 +1194,7 @@ It calls function registered in variable
 It calls function registered in variable
 `mime-view-show-summary-method'."
   (interactive)
-  (let ((r (assq mime::preview/original-major-mode
+  (let ((r (assq mime-view-original-major-mode
                 mime-view-show-summary-method)))
     (if r
        (funcall (cdr r))