Update.
[elisp/semi.git] / mime-view.el
index 740e63c..2a30e18 100644 (file)
@@ -139,37 +139,87 @@ mother-buffer."
 ;;; @ entity information
 ;;;
 
-(defun mime-entity-situation (entity)
+(defun mime-entity-situation (entity &optional situation)
   "Return situation of ENTITY."
-  (append (or (mime-entity-content-type entity)
-             (make-mime-content-type 'text 'plain))
-         (let ((d (mime-entity-content-disposition entity)))
-           (cons (cons 'disposition-type
-                       (mime-content-disposition-type d))
-                 (mapcar (function
-                          (lambda (param)
-                            (let ((name (car param)))
-                              (cons (cond ((string= name "filename")
-                                           'filename)
-                                          ((string= name "creation-date")
-                                           'creation-date)
-                                          ((string= name "modification-date")
-                                           'modification-date)
-                                          ((string= name "read-date")
-                                           'read-date)
-                                          ((string= name "size")
-                                           'size)
-                                          (t (cons 'disposition (car param))))
-                                    (cdr param)))))
-                         (mime-content-disposition-parameters d))
-                 ))
-         (list (cons 'encoding (mime-entity-encoding entity))
-               (cons 'major-mode
-                     (save-excursion
-                       (set-buffer (mime-entity-buffer entity))
-                       major-mode)))
-         ))
+  (let (rest param name)
+    ;; Content-Type
+    (unless (assq 'type situation)
+      (setq rest (or (mime-entity-content-type entity)
+                    (make-mime-content-type 'text 'plain))
+           situation (cons (car rest) situation)
+           rest (cdr rest))
+      )
+    (unless (assq 'subtype situation)
+      (or rest
+         (setq rest (or (cdr (mime-entity-content-type entity))
+                        '((subtype . plain)))))
+      (setq situation (cons (car rest) situation)
+           rest (cdr rest))
+      )
+    (while rest
+      (setq param (car rest))
+      (or (assoc (car param) situation)
+         (setq situation (cons param situation)))
+      (setq rest (cdr rest)))
+    
+    ;; Content-Disposition
+    (setq rest nil)
+    (unless (assq 'disposition-type situation)
+      (setq rest (mime-entity-content-disposition entity))
+      (if rest
+         (setq situation (cons (cons 'disposition-type
+                                     (mime-content-disposition-type rest))
+                               situation)
+               rest (mime-content-disposition-parameters rest))
+       ))
+    (while rest
+      (setq param (car rest)
+           name (car param))
+      (if (cond ((string= name "filename")
+                (if (assq 'filename situation)
+                    nil
+                  (setq name 'filename)))
+               ((string= name "creation-date")
+                (if (assq 'creation-date situation)
+                    nil
+                  (setq name 'creation-date)))
+               ((string= name "modification-date")
+                (if (assq 'modification-date situation)
+                    nil
+                  (setq name 'modification-date)))
+               ((string= name "read-date")
+                (if (assq 'read-date situation)
+                    nil
+                  (setq name 'read-date)))
+               ((string= name "size")
+                (if (assq 'size situation)
+                    nil
+                  (setq name 'size)))
+               (t (setq name (cons 'disposition name))
+                  (if (assoc name situation)
+                      nil
+                    name)))
+         (setq situation
+               (cons (cons name (cdr param))
+                     situation)))
+      (setq rest (cdr rest)))
+    
+    ;; Content-Transfer-Encoding
+    (or (assq 'encoding situation)
+       (setq situation
+             (cons (cons 'encoding (or (mime-entity-encoding entity)
+                                       "7bit"))
+                   situation)))
 
+    ;; major-mode
+    (or (assq 'major-mode situation)
+       (setq situation
+             (cons (cons 'major-mode
+                         (with-current-buffer (mime-entity-buffer entity)
+                           major-mode))
+                   situation)))
+    
+    situation))
 
 (defun mime-view-entity-title (entity)
   (or (mime-read-field 'Content-Description entity)
@@ -318,6 +368,8 @@ Each elements are regexp of field-name.")
 ;;; @@@ predicate function
 ;;;
 
+(in-calist-package 'mime-view)
+
 (defun mime-calist::field-match-method-as-default-rule (calist
                                                        field-type field-value)
   (let ((s-field (assq field-type calist)))
@@ -685,9 +737,10 @@ MEDIA-TYPE must be (TYPE . SUBTYPE), TYPE or t.  t means default."
       (setq preview-buffer (current-buffer)))
   (let* ((raw-buffer (mime-entity-buffer entity))
         (start (mime-entity-point-min entity))
-        e nb ne)
+        e nb ne nhb nbb)
     (set-buffer raw-buffer)
     (goto-char start)
+    (in-calist-package 'mime-view)
     (or situation
        (setq situation
              (or (ctree-match-calist mime-preview-condition
@@ -712,15 +765,18 @@ MEDIA-TYPE must be (TYPE . SUBTYPE), TYPE or t.  t means default."
              (mime-view-insert-entity-button entity)
            ))
       (when header-is-visible
+       (setq nhb (point))
        (if header-presentation-method
            (funcall header-presentation-method entity situation)
          (mime-insert-header entity
                              mime-view-ignored-field-list
                              mime-view-visible-field-list))
+       (run-hooks 'mime-display-header-hook)
+       (put-text-property nhb (point-max) 'mime-view-entity-header entity)
        (goto-char (point-max))
        (insert "\n")
-       (run-hooks 'mime-display-header-hook)
        )
+      (setq nbb (point))
       (cond (children)
             ((functionp body-presentation-method)
             (funcall body-presentation-method entity situation)
@@ -739,6 +795,7 @@ MEDIA-TYPE must be (TYPE . SUBTYPE), TYPE or t.  t means default."
       (setq ne (point-max))
       (widen)
       (put-text-property nb ne 'mime-view-entity entity)
+      (put-text-property nbb ne 'mime-view-entity-body entity)
       (goto-char ne)
       (if children
          (if (functionp body-presentation-method)
@@ -883,8 +940,20 @@ MEDIA-TYPE must be (TYPE . SUBTYPE), TYPE or t.  t means default."
 
 (defvar mime-view-redisplay nil)
 
+;;;###autoload
 (defun mime-display-message (message &optional preview-buffer
                                     mother default-keymap-or-function)
+  "View MESSAGE in MIME-View mode.
+
+Optional argument PREVIEW-BUFFER specifies the buffer of the
+presentation.  It must be either nil or a name of preview buffer.
+
+Optional argument MOTHER specifies mother-buffer of the preview-buffer.
+
+Optional argument DEFAULT-KEYMAP-OR-FUNCTION is nil, keymap or
+function.  If it is a keymap, keymap of MIME-View mode will be added
+to it.  If it is a function, it will be bound as default binding of
+keymap of MIME-View mode."
   (mime-maybe-hide-echo-buffer)
   (let ((win-conf (current-window-configuration))
        (raw-buffer (mime-entity-buffer message)))
@@ -930,6 +999,7 @@ MEDIA-TYPE must be (TYPE . SUBTYPE), TYPE or t.  t means default."
                  )))))
       )))
 
+;;;###autoload
 (defun mime-view-buffer (&optional raw-buffer preview-buffer mother
                                   default-keymap-or-function
                                   representation-type)
@@ -1050,6 +1120,7 @@ It calls following-method selected from variable
     (let* ((p-beg
            (previous-single-property-change (point) 'mime-view-entity))
           p-end
+          ph-end
           (entity-node-id (mime-entity-node-id entity))
           (len (length entity-node-id))
           )
@@ -1093,6 +1164,12 @@ It calls following-method selected from variable
                 (setq p-end (point-max))
                 ))
             ))
+      (setq ph-end
+           (previous-single-property-change p-end 'mime-view-entity-header))
+      (if (or (null ph-end)
+             (< ph-end p-beg))
+         (setq ph-end p-beg)
+       )
       (let* ((mode (mime-preview-original-major-mode 'recursive))
             (new-name
              (format "%s-%s" (buffer-name) (reverse entity-node-id)))
@@ -1103,7 +1180,10 @@ It calls following-method selected from variable
        (save-excursion
          (set-buffer (setq new-buf (get-buffer-create new-name)))
          (erase-buffer)
-         (insert-buffer-substring the-buf p-beg p-end)
+         (insert-buffer-substring the-buf ph-end p-end)
+         (when (= ph-end p-beg)
+           (goto-char (point-min))
+           (insert ?\n))
          (goto-char (point-min))
           (let ((entity-node-id (mime-entity-node-id entity)) ci str)
            (while (progn
@@ -1122,9 +1202,8 @@ It calls following-method selected from variable
                           (concat "^"
                                   (apply (function regexp-or) fields)
                                   ":") ""))))
-                    (if (and
-                         (eq (mime-entity-media-type ci) 'message)
-                         (eq (mime-entity-media-subtype ci) 'rfc822))
+                    (if (and (eq (mime-entity-media-type ci) 'message)
+                             (eq (mime-entity-media-subtype ci) 'rfc822))
                         nil
                       (if str
                           (insert str)