tm 7.43.1.
[elisp/tm.git] / tm-vm.el
index 223abcf..96c6df9 100644 (file)
--- a/tm-vm.el
+++ b/tm-vm.el
@@ -1,34 +1,56 @@
 ;;;
 ;;; tm-vm.el --- tm-MUA for VM
 ;;;
-;;; Copyright (C) 1995 Free Software Foundation, Inc.
+;;; Copyright (C) 1994 MASUTANI Yasuhiro
+;;; Copyright (C) 1995 WAKAMIYA Kenji
+;;; Copyright (C) 1995,1996 KOBAYASHI Shuhei
 ;;; 
-;;; Author:   MASUTANI Yasuhiro <masutani@me.es.osaka-u.ac.jp>
-;;;           Kenji Wakamiya <wkenji@flab.fujitsu.co.jp>
-;;;           MORIOKA Tomohiko <morioka@jaist.ac.jp>
-;;;           Shuhei KOBAYASHI <shuhei@cmpt01.phys.tohoku.ac.jp>
-;;;           Oscar Figueiredo <figueire@lspsun2.epfl.ch>
-;;; modified by SHIONO Jun'ichi <jun@p5.nm.fujitsu.co.jp>,
-;;;         and Steinar Bang <steinarb@falch.no>,
-;;;
-;;; Keywords: news, MIME, multimedia, multilingual, encoded-word
+;;; Author: MASUTANI Yasuhiro <masutani@me.es.osaka-u.ac.jp>
+;;;         Kenji Wakamiya <wkenji@flab.fujitsu.co.jp>
+;;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;;;         Shuhei KOBAYASHI <shuhei@cmpt01.phys.tohoku.ac.jp>
+;;;         Oscar Figueiredo <figueire@lspsun2.epfl.ch>
+;;; modified by SHIONO Jun'ichi <jun@case.nm.fujitsu.co.jp>
+;;;         and ISHIHARA Akito <aki@bpel.tutics.tut.ac.jp>
+;;; Maintainer: Shuhei KOBAYASHI <shuhei@cmpt01.phys.tohoku.ac.jp>
+;;; Created: 1994/10/29
+;;; Version: $Revision: 7.42 $
+;;; Keywords: mail, MIME, multimedia, multilingual, encoded-word
 ;;;
 ;;; This file is part of tm (Tools for MIME).
 ;;;
-;;; Plese insert (require 'tm-vm) in your ~/.vm or ~/.emacs file.
+;;; Plese insert `(require 'tm-vm)' in your ~/.vm file.
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU General Public License as
+;;; published by the Free Software Foundation; either version 2, or
+;;; (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with This program.  If not, write to the Free Software
+;;; Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 ;;;
+;;; Code:
 
 (require 'tm-view)
 (require 'vm)
 
 (defconst tm-vm/RCS-ID
-  "$Id: tm-vm.el,v 7.10 1995/11/16 17:07:02 morioka Exp $")
+  "$Id: tm-vm.el,v 7.42 1996/02/09 00:31:21 morioka Exp $")
 (defconst tm-vm/version (get-version-string tm-vm/RCS-ID))
 
 (define-key vm-mode-map "Z" 'tm-vm/view-message)
 (define-key vm-mode-map "T" 'tm-vm/decode-message-header)
 (define-key vm-mode-map "\et" 'tm-vm/toggle-preview-mode)
 
+(defvar tm-vm-load-hook nil
+  "*List of functions called after tm-vm is loaded.")
+
 
 ;;; @ for MIME encoded-words
 ;;;
@@ -41,9 +63,6 @@ If you use tiny-mime patch for VM (by RIKITAKE Kenji
 (or tm-vm/use-tm-patch
     (progn
 ;;;
-;; by Steinar Bang <steinarb@falch.no>
-(setq vm-summary-format "%n %*%a %-17.17F %-3.3m %2d %4l/%-5c, %I\"%UA\"\n")
-
 (defvar tm-vm/chop-full-name-function 'tm-vm/default-chop-full-name)
 (setq vm-chop-full-name-function tm-vm/chop-full-name-function)
 
@@ -56,9 +75,26 @@ If you use tiny-mime patch for VM (by RIKITAKE Kenji
              (cdr ret))
       ret)))
 
-;; by Steinar Bang <steinarb@falch.no>
-(defun vm-summary-function-A (m)
-  (mime-eword/decode-string (vm-su-subject m))
+(require 'vm-summary)
+(or (fboundp 'tm:vm-su-subject)
+    (fset 'tm:vm-su-subject (symbol-function 'vm-su-subject))
+    )
+(defun vm-su-subject (m)
+  (mime-eword/decode-string (tm:vm-su-subject m))
+  )
+
+(or (fboundp 'tm:vm-su-full-name)
+    (fset 'tm:vm-su-full-name (symbol-function 'vm-su-full-name))
+    )
+(defun vm-su-full-name (m)
+  (mime-eword/decode-string (tm:vm-su-full-name m))
+  )
+
+(or (fboundp 'tm:vm-su-to-names)
+    (fset 'tm:vm-su-to-names (symbol-function 'vm-su-to-names))
+    )
+(defun vm-su-to-names (m)
+  (mime-eword/decode-string (tm:vm-su-to-names m))
   )
 ;;;
 ))
@@ -114,201 +150,393 @@ all marked messages are affected, other messages are ignored."
        (vm-preview-current-message)
        (setq vbufs (cdr vbufs))))))
 
-
+\f
 ;;; @ automatic MIME preview
 ;;;
 
 (defvar tm-vm/automatic-mime-preview t
-  "If non-nil, show MIME processed article.")
+  "*If non-nil, show MIME processed article.")
+
+(defvar tm-vm/strict-mime t
+  "*If nil, do MIME processing even if there is not MIME-Version field.")
+
+(defvar tm-vm/select-message-hook nil
+  "*List of functions called every time a message is selected.
+tm-vm uses `vm-select-message-hook', use this hook instead.")
+
+(defvar tm-vm/system-state nil)
+(defun tm-vm/system-state ()
+  (save-excursion
+    (if mime::preview/article-buffer
+        (set-buffer mime::preview/article-buffer)
+      (vm-select-folder-buffer))
+    tm-vm/system-state))
+
+(defun tm-vm/display-preview-buffer ()
+  (let* ((mbuf (current-buffer))
+         (mwin (vm-get-visible-buffer-window mbuf))
+         (pbuf (and mime::article/preview-buffer
+                    (get-buffer mime::article/preview-buffer)))
+         (pwin (and pbuf (vm-get-visible-buffer-window pbuf)))) 
+    (if (and pbuf (tm-vm/system-state))
+        ;; display preview buffer
+        (cond
+         ((and mwin pwin)
+          (vm-undisplay-buffer mbuf)
+          (tm-vm/show-current-message))
+         ((and mwin (not pwin))
+          (set-window-buffer mwin pbuf)
+          (tm-vm/show-current-message))
+         (pwin
+          (tm-vm/show-current-message))
+         (t
+          ;; don't display if neither mwin nor pwin was displayed before.
+          ))
+      ;; display folder buffer
+      (cond
+       ((and mwin pwin)
+        (vm-undisplay-buffer pbuf))
+       ((and (not mwin) pwin)
+        (set-window-buffer pwin mbuf))
+       (mwin
+        ;; folder buffer is already displayed.
+        )
+       (t
+        ;; don't display if neither mwin nor pwin was displayed before.
+        )))
+    (set-buffer mbuf)))
 
 (defun tm-vm/preview-current-message ()
-  ;;; suggested by Simon Rowe <smr@robots.oxford.ac.uk>
-  ;;;  (c.f. [tm-eng:163])
-  ;; Selecting a new mail message, but we're already displaying a mime
-  ;; on in the window, make sure that the mail buffer is displayed.
-  (if (get-buffer-window "*MIME-out*")
-      (delete-window (get-buffer-window (get-buffer "*MIME-out*")))
+  ;; assumed current buffer is folder buffer.
+  (setq tm-vm/system-state nil)
+  (if (get-buffer mime/output-buffer-name)
+      (vm-undisplay-buffer mime/output-buffer-name))
+  (if (and vm-message-pointer tm-vm/automatic-mime-preview)
+      (if (or (not tm-vm/strict-mime)
+              (vm-get-header-contents (car vm-message-pointer)
+                                      "MIME-Version:"))
+          ;; do MIME processiong.
+          (progn
+            (set (make-local-variable 'tm-vm/system-state) 'previewing)
+            (save-window-excursion
+              (mime/viewer-mode)
+              (goto-char (point-min))
+              (narrow-to-region (point)
+                                (search-forward "\n\n" nil t))
+              ))
+        ;; don't do MIME processing. decode header only.
+        (let (buffer-read-only)
+          (mime/decode-message-header))
+        )
+    ;; don't preview; do nothing.
     )
-  (display-buffer (current-buffer))
-  (if (and tm-vm/automatic-mime-preview
-          (let* ((mp (car vm-message-pointer))
-                 (ct  (vm-get-header-contents mp "Content-Type:"))
-                 (cte (vm-get-header-contents
-                       mp "Content-Transfer-Encoding:"))
-                 )
-            ;; Check if this message actually is a mime, or just a text
-            ;; one sent by someone using PINE or similar.
-            (and ct
-                 (not (and (string= (car (mime/parse-Content-Type ct))
-                                    "text/plain")
-                           (member cte '("7bit" "8bit" "binary"))
-                           ))))
-          )
-      (let ((win (selected-window)))
-       (vm-display (current-buffer) t
-                   '(tm-vm/preview-current-message
-                     vm-preview-current-message)
-                   '(tm-vm/preview-current-message reading-message))
-       (mime/viewer-mode)
-       (select-window win)
-       )))
+  (tm-vm/display-preview-buffer)
+  (run-hooks 'tm-vm/select-message-hook))
+
+(defun tm-vm/show-current-message ()
+  (if mime::preview/article-buffer
+      (set-buffer mime::preview/article-buffer)
+    (vm-select-folder-buffer))
+  ;; Now current buffer is folder buffer.
+  (if (or t ; mime/viewer-mode doesn't support narrowing yet.
+          (null vm-preview-lines)
+          (and (not vm-preview-read-messages)
+               (not (vm-new-flag
+                     (car vm-message-pointer)))
+               (not (vm-unread-flag
+                     (car vm-message-pointer)))))
+      (save-excursion
+        (set-buffer mime::article/preview-buffer)
+        (save-excursion
+          (save-excursion
+            (goto-char (point-min))
+            (widen))
+          ;; narrow to page; mime/viewer-mode doesn't support narrowing yet.
+          )))
+  (if (vm-get-visible-buffer-window mime::article/preview-buffer)
+      (progn
+        (setq tm-vm/system-state 'reading)
+        (if (vm-new-flag (car vm-message-pointer))
+            (vm-set-new-flag (car vm-message-pointer) nil))
+        (if (vm-unread-flag (car vm-message-pointer))
+            (vm-set-unread-flag (car vm-message-pointer) nil))
+        (vm-update-summary-and-mode-line)
+        (tm-vm/howl-if-eom))
+    (vm-update-summary-and-mode-line)))
+
+(defun tm-vm/toggle-preview-mode ()
+  (interactive)
+  (vm-select-folder-buffer)
+  (vm-display (current-buffer) t (list this-command)
+              (list this-command 'reading-message))
+  (if tm-vm/automatic-mime-preview
+      (setq tm-vm/automatic-mime-preview nil
+            tm-vm/system-state nil)
+    (setq tm-vm/automatic-mime-preview t
+          tm-vm/system-state nil)
+    (save-restriction
+       (vm-widen-page)
+       (let* ((mp (car vm-message-pointer))
+              (exposed (= (point-min) (vm-start-of mp))))
+         (if (or (not tm-vm/strict-mime)
+                 (vm-get-header-contents mp "MIME-Version:"))
+             ;; do MIME processiong.
+             (progn
+               (set (make-local-variable 'tm-vm/system-state) 'previewing)
+               (save-window-excursion
+                 (mime/viewer-mode)
+                 (goto-char (point-min))
+                 (narrow-to-region (point)
+                                   (search-forward "\n\n" nil t))
+                 ))
+           ;; don't do MIME processing. decode header only.
+           (let (buffer-read-only)
+             (mime/decode-message-header))
+           )
+         ;; don't preview; do nothing.
+         ))
+    (tm-vm/display-preview-buffer)
+    ))
 
 (add-hook 'vm-select-message-hook 'tm-vm/preview-current-message)
-(add-hook 'vm-visit-folder-hook 'tm-vm/preview-current-message)
+(add-hook 'vm-visit-folder-hook   'tm-vm/preview-current-message)
+\f
+;;; tm-vm move commands
+;;;
 
-;; fixed by Oscar Figueiredo <figueire@lspsun2.epfl.ch>
-;;     1995/11/14 (c.f. [tm-eng:162])
-(defun tm-vm/scroll-forward ()
-  (interactive)
-  (if (not tm-vm/automatic-mime-preview)
-      (vm-scroll-forward)
-    (let* ((summary-buffer (or vm-summary-buffer
-                              (and (eq major-mode 'vm-summary-mode)
-                                   (current-buffer))))
-          (summary-win (get-buffer-window summary-buffer))
-          (mail-buffer (save-excursion
-                         (set-buffer summary-buffer)
-                         vm-mail-buffer))
-          (mail-win (get-buffer-window mail-buffer))
-          (preview-win (get-buffer-window
-                        (save-excursion
-                          (set-buffer mail-buffer)
-                          mime::article/preview-buffer))))                     
-      (if preview-win
-         (progn
-           (select-window preview-win)
-           (if (pos-visible-in-window-p (point-max) preview-win)
-               (progn
-                 (switch-to-buffer mail-buffer)
-                 (goto-char (point-max))
-                 (select-window summary-win))
-             (scroll-up)       
-             (switch-to-buffer mail-buffer)
-             (select-window summary-win))))
-      (vm-scroll-forward)
-      (save-excursion
-       (set-buffer summary-buffer)
-       (setq mail-win (get-buffer-window vm-mail-buffer)))
-      (if mail-win
-         (progn
-           (select-window mail-win)
-           (switch-to-buffer mime::article/preview-buffer)
-           (select-window summary-win)))
+(defmacro tm-vm/save-window-excursion (&rest forms)
+  (list 'let '((tm-vm/selected-window (selected-window)))
+        (list 'unwind-protect
+              (cons 'progn forms)
+              '(if (window-live-p tm-vm/selected-window)
+                   (select-window tm-vm/selected-window)))))
+
+;;; based on vm-scroll-forward [vm-page.el]
+(defun tm-vm/scroll-forward (&optional arg)
+  (interactive "P")
+  (let ((this-command 'vm-scroll-forward))
+    (if (not (tm-vm/system-state))
+        (vm-scroll-forward arg)
+      (let* ((mp-changed (vm-follow-summary-cursor))
+             (mbuf (or (vm-select-folder-buffer) (current-buffer)))
+             (mwin (vm-get-buffer-window mbuf))
+             (pbuf (and mime::article/preview-buffer
+                        (get-buffer mime::article/preview-buffer)))
+             (pwin (and pbuf (vm-get-buffer-window pbuf)))
+             (was-invisible (and (null mwin) (null pwin)))
+             )
+        ;; now current buffer is folder buffer.
+        (tm-vm/save-window-excursion
+         (if (or mp-changed was-invisible)
+             (vm-display mbuf t '(vm-scroll-forward vm-scroll-backward)
+                         (list this-command 'reading-message)))
+         (tm-vm/display-preview-buffer)
+         (setq mwin (vm-get-buffer-window mbuf)
+               pwin (and pbuf (vm-get-buffer-window pbuf)))
+         (cond
+          (was-invisible
+           nil
+           )
+          ((null pbuf)
+           ;; preview buffer is killed.
+           (tm-vm/preview-current-message)
+           (vm-update-summary-and-mode-line))
+          ((eq (tm-vm/system-state) 'previewing)
+           (tm-vm/show-current-message))
+          (t
+           (select-window pwin)
+           (set-buffer pbuf)
+           (if (pos-visible-in-window-p (point-max) pwin)
+               (tm-vm/next-message)
+             ;; not end of message. scroll preview buffer only.
+             (scroll-up)
+             (tm-vm/howl-if-eom)
+             (set-buffer mbuf))
+           ))))
       )))
 
-(defun tm-vm/scroll-backward ()
-  (interactive)
-  (if (not tm-vm/automatic-mime-preview)
-      (vm-scroll-backward nil)
-    (let* ((summary-buffer (or vm-summary-buffer
-                              (and (eq major-mode 'vm-summary-mode)
-                                   (current-buffer))))
-          (summary-win (get-buffer-window summary-buffer))
-          (mail-buffer (save-excursion
-                         (set-buffer summary-buffer)
-                         vm-mail-buffer))
-          (mail-win (get-buffer-window mail-buffer))
-          (preview-win (get-buffer-window
-                        (save-excursion
-                          (set-buffer mail-buffer)
-                          mime::article/preview-buffer))))                     
-      (if preview-win
-         (progn
-           (select-window preview-win)
-           (if (pos-visible-in-window-p (point-min) preview-win)
-               (progn
-                 (switch-to-buffer mail-buffer)
-                 (goto-char (point-min))
-                 (select-window summary-win))
-             (scroll-down)             
-             (switch-to-buffer mail-buffer)
-             (select-window summary-win))))
-      (vm-scroll-backward nil)
-      (save-excursion
-       (set-buffer summary-buffer)
-       (setq mail-win (get-buffer-window vm-mail-buffer)))
-      (if mail-win
-         (progn
-           (select-window mail-win)
-           (switch-to-buffer mime::article/preview-buffer)
-           (select-window summary-win)))
+;;; based on vm-scroll-backward [vm-page.el]
+(defun tm-vm/scroll-backward (&optional arg)
+  (interactive "P")
+  (let ((this-command 'vm-scroll-backward))
+    (if (not (tm-vm/system-state))
+        (vm-scroll-backward arg)
+      (let* ((mp-changed (vm-follow-summary-cursor))
+             (mbuf (or (vm-select-folder-buffer) (current-buffer)))
+             (mwin (vm-get-buffer-window mbuf))
+             (pbuf (and mime::article/preview-buffer
+                        (get-buffer mime::article/preview-buffer)))
+             (pwin (and pbuf (vm-get-buffer-window pbuf)))
+             (was-invisible (and (null mwin) (null pwin)))
+             )
+        ;; now current buffer is folder buffer.
+        (if (or mp-changed was-invisible)
+            (vm-display mbuf t '(vm-scroll-forward vm-scroll-backward)
+                        (list this-command 'reading-message)))
+        (tm-vm/save-window-excursion
+         (tm-vm/display-preview-buffer)
+         (setq mwin (vm-get-buffer-window mbuf)
+               pwin (and pbuf (vm-get-buffer-window pbuf)))
+         (cond
+          (was-invisible
+           nil
+           )
+          ((null pbuf)
+           ;; preview buffer is killed.
+           (tm-vm/preview-current-message)
+           (vm-update-summary-and-mode-line))
+          ((eq (tm-vm/system-state) 'previewing)
+           (tm-vm/show-current-message))
+          (t
+           (select-window pwin)
+           (set-buffer pbuf)
+           (if (pos-visible-in-window-p (point-min) pwin)
+               nil
+             ;; scroll preview buffer only.
+             (scroll-down)
+             (set-buffer mbuf))
+           ))))
       )))
 
-;; 1995/11/16 by Oscar Figueiredo <figueire@lspsun2.epfl.ch>
-(defun tm-vm/expunge-folder ()
+;;; based on vm-beginning-of-message [vm-page.el]
+(defun tm-vm/beginning-of-message ()
+  "Moves to the beginning of the current message."
   (interactive)
-  (let* ((summary-buf (or (and (eq major-mode 'vm-summary-mode)
-                              (current-buffer))
-                         vm-summary-buffer))
-        (preview-buf (save-excursion
-                       (set-buffer (save-excursion
-                                     (set-buffer summary-buf)
-                                     vm-mail-buffer))
-                       mime::article/preview-buffer))
-        (preview-win (and preview-buf
-                          (get-buffer-window preview-buf)))
-        (win (selected-window)))
-    
-    (vm-expunge-folder)
-    (if preview-win
-       (save-excursion
-         (set-buffer summary-buf)
-         (set-buffer vm-mail-buffer)
-         (if (eq (point-min) (point-max))
-             (kill-buffer preview-buf))))
-    ))
+  (if (not (tm-vm/system-state))
+      (progn
+       (setq this-command 'vm-beginning-of-message)
+       (vm-beginning-of-message))
+    (vm-follow-summary-cursor)
+    (vm-select-folder-buffer)
+    (vm-check-for-killed-summary)
+    (vm-error-if-folder-empty)
+    (let ((mbuf (current-buffer))
+          (pbuf (and mime::article/preview-buffer
+                     (get-buffer mime::article/preview-buffer))))
+      (if (null pbuf)
+          (progn
+            (tm-vm/preview-current-message)
+            (setq pbuf (get-buffer mime::article/preview-buffer))
+            ))
+      (vm-display mbuf t '(vm-beginning-of-message)
+                  '(vm-beginning-of-message reading-message))
+      (tm-vm/display-preview-buffer)
+      (set-buffer pbuf)
+      (tm-vm/save-window-excursion
+       (select-window (vm-get-buffer-window pbuf))
+       (push-mark)
+       (goto-char (point-min))
+       ))))
+
+;;; based on vm-end-of-message [vm-page.el]
+(defun tm-vm/end-of-message ()
+  "Moves to the end of the current message."
+  (interactive)
+  (if (not (tm-vm/system-state))
+      (progn
+       (setq this-command 'vm-end-of-message)
+       (vm-end-of-message))
+    (vm-follow-summary-cursor)
+    (vm-select-folder-buffer)
+    (vm-check-for-killed-summary)
+    (vm-error-if-folder-empty)
+    (let ((mbuf (current-buffer))
+          (pbuf (and mime::article/preview-buffer
+                     (get-buffer mime::article/preview-buffer))))
+      (if (null pbuf)
+          (progn
+            (tm-vm/preview-current-message)
+            (setq pbuf (get-buffer mime::article/preview-buffer))
+            ))
+      (vm-display mbuf t '(vm-end-of-message)
+                  '(vm-end-of-message reading-message))
+      (tm-vm/display-preview-buffer)
+      (set-buffer pbuf)
+      (tm-vm/save-window-excursion
+       (select-window (vm-get-buffer-window pbuf))
+       (push-mark)
+       (goto-char (point-max))
+       ))))
+
+;;; based on vm-howl-if-eom [vm-page.el]
+(defun tm-vm/howl-if-eom ()
+  (let* ((pbuf (or mime::article/preview-buffer (current-buffer)))
+         (pwin (and (vm-get-visible-buffer-window pbuf))))
+    (and pwin
+        (save-excursion
+          (save-window-excursion
+            (condition-case ()
+                (let ((next-screen-context-lines 0))
+                  (select-window pwin)
+                  (save-excursion
+                    (save-window-excursion
+                      (let ((scroll-in-place-replace-original nil))
+                        (scroll-up))))
+                  nil)
+              (error t))))
+         (tm-vm/emit-eom-blurb)
+         )))
+
+;;; based on vm-emit-eom-blurb [vm-page.el]
+(defun tm-vm/emit-eom-blurb ()
+  (save-excursion
+    (if mime::preview/article-buffer
+        (set-buffer mime::preview/article-buffer))
+    (vm-emit-eom-blurb)))
 
-;; fixed by Oscar Figueiredo <figueire@lspsun2.epfl.ch>
-;;     1995/11/14 (c.f. [tm-eng:162])
+;;; based on vm-quit [vm-folder.el]
 (defun tm-vm/quit ()
   (interactive)
   (save-excursion
-    (set-buffer vm-mail-buffer)
+    (vm-select-folder-buffer)
     (if (and mime::article/preview-buffer
             (get-buffer mime::article/preview-buffer))
        (kill-buffer mime::article/preview-buffer)))
-  (vm-quit)
-  )
+  (vm-quit))
 
 (substitute-key-definition 'vm-scroll-forward
                           'tm-vm/scroll-forward vm-mode-map)
 (substitute-key-definition 'vm-scroll-backward
                           'tm-vm/scroll-backward vm-mode-map)
-(substitute-key-definition 'vm-expunge-folder
-                          'tm-vm/expunge-folder vm-mode-map)
+(substitute-key-definition 'vm-beginning-of-message
+                           'tm-vm/beginning-of-message vm-mode-map)
+(substitute-key-definition 'vm-end-of-message
+                           'tm-vm/end-of-message vm-mode-map)
 (substitute-key-definition 'vm-quit
                           'tm-vm/quit vm-mode-map)
-;; end
-
-
-(defun tm-vm/toggle-preview-mode ()
-  (interactive)
-  (if tm-vm/automatic-mime-preview
-      (progn
-       (setq tm-vm/automatic-mime-preview nil)
-       (vm-select-folder-buffer)
-       (vm-display (current-buffer) t
-                   '(tm-vm/toggle-preview-mode)
-                   '(tm-vm/toggle-preview-mode reading-message))
-       )
-    (setq tm-vm/automatic-mime-preview t)
-    (let ((win (selected-window)))
-      (vm-select-folder-buffer)
-      (save-window-excursion
-       (let* ((mp (car vm-message-pointer))
-              (ct  (vm-get-header-contents mp "Content-Type:"))
-              (cte (vm-get-header-contents mp "Content-Transfer-Encoding:"))
-              )
-         (mime/viewer-mode nil (mime/parse-Content-Type (or ct "")) cte)
-         ))
-      (vm-display mime::article/preview-buffer t
-                 '(tm-vm/toggle-preview-mode)
-                 '(tm-vm/toggle-preview-mode reading-message))
-      (select-window win)
-      )
-    ))
-
 
+;;; based on vm-next-message [vm-motion.el]                        
+(defun tm-vm/next-message ()
+  (set-buffer mime::preview/article-buffer)
+  (let ((this-command 'vm-next-message)
+        (owin (selected-window))
+        (vm-preview-lines nil)
+        )
+    (vm-next-message 1 nil t)
+    (if (window-live-p owin)
+        (select-window owin))))
+
+;;; based on vm-previous-message [vm-motion.el]
+(defun tm-vm/previous-message ()
+  (set-buffer mime::preview/article-buffer)
+  (let ((this-command 'vm-previous-message)
+        (owin (selected-window))
+        (vm-preview-lines nil)
+        )
+    (vm-previous-message 1 nil t)
+    (if (window-live-p owin)
+        (select-window owin))))
+
+(set-alist 'mime-viewer/over-to-previous-method-alist
+          'vm-mode 'tm-vm/previous-message)
+(set-alist 'mime-viewer/over-to-next-method-alist
+          'vm-mode 'tm-vm/next-message)
+(set-alist 'mime-viewer/over-to-previous-method-alist
+          'vm-virtual-mode 'tm-vm/previous-message)
+(set-alist 'mime-viewer/over-to-next-method-alist
+          'vm-virtual-mode 'tm-vm/next-message)
+
+\f
 ;;; @ for tm-view
 ;;;
 
@@ -316,12 +544,20 @@ all marked messages are affected, other messages are ignored."
   "Quit MIME-viewer and go back to VM.
 This function is called by `mime-viewer/quit' command via
 `mime-viewer/quitting-method-alist'."
-  (mime-viewer/kill-buffer)
   (if (get-buffer mime/output-buffer-name)
-      (bury-buffer mime/output-buffer-name))
-  (vm-select-folder-buffer)
-  (vm-display (current-buffer) t '(mime-viewer/quit mime-viewer/up-content)
-             '(mime-viewer/quit reading-message)))
+      (vm-undisplay-buffer mime/output-buffer-name))
+  (if (and tm-vm/automatic-mime-preview
+           (save-excursion
+             (set-buffer mime::preview/article-buffer)
+             vm-summary-buffer))
+      (switch-to-buffer mime::preview/article-buffer)
+    (mime-viewer/kill-buffer)
+    (vm-select-folder-buffer)
+    (setq tm-vm/system-state nil))
+  (vm-display (current-buffer) t (list this-command)
+              (list this-command 'reading-message))
+  (tm-vm/display-preview-buffer)
+  )
 
 (defun tm-vm/view-message ()
   "Decode and view MIME encoded message, under VM."
@@ -382,23 +618,21 @@ This function is called by `mime-viewer/quit' command via
 ;;; @ for tm-edit
 ;;;
 
-;; 1995/11/9 by Shuhei KOBAYASHI <shuhei@cmpt01.phys.tohoku.ac.jp>
-;;     (c.f. [tm ML:1075])
-(defun tm-vm/insert-message (&optional message)
-  (interactive)
-  (let* (mail-yank-hooks
-        (mail-citation-hook '(mime-editor/inserted-message-filter))
-        (mail-reply-buffer vm-mail-buffer)
-        )
-    (if (null message)
-        (call-interactively 'vm-yank-message)
-      (vm-yank-message message))
-    ))
-
-
 ;;; @@ for multipart/digest
 ;;;
 
+(defvar tm-vm/forward-message-hook nil
+  "*List of functions called after a Mail mode buffer has been
+created to forward a message in message/rfc822 type format.
+If `vm-forwarding-digest-type' is \"rfc1521\", tm-vm runs this
+hook instead of `vm-forward-message-hook'.")
+
+(defvar tm-vm/send-digest-hook nil
+  "*List of functions called after a Mail mode buffer has been
+created to send a digest in multipart/digest type format.
+If `vm-digest-send-type' is \"rfc1521\", tm-vm runs this hook
+instead of `vm-send-digest-hook'.")
+
 (defun tm-vm/enclose-messages (mlist)
   "Enclose the messages in MLIST as multipart/digest.
 The resulting digest is inserted at point in the current buffer.
@@ -413,7 +647,7 @@ These are the messages that will be enclosed."
          (while mlist
            (setq m (vm-real-message-of (car mlist)))
             (mime-editor/insert-tag "message" "rfc822")
-            (tm-vm/insert-message m)
+            (tm-mail/insert-message m)
             (goto-char (point-max))
            (setq mlist (cdr mlist)))
           (if digest
@@ -457,7 +691,7 @@ Subject: header manually."
            (concat "^" (regexp-quote mail-header-separator) "\n") nil 0)
           (tm-vm/enclose-messages vm-forward-list)
           (mail-position-on-field "To"))
-        ;; (run-hooks 'tm-vm/forward-message-hook) ; Is it necessary?
+        (run-hooks 'tm-vm/forward-message-hook)
         (run-hooks 'vm-mail-mode-hook)))))
 
 (defun tm-vm/send-digest (&optional prefix)
@@ -511,38 +745,89 @@ only marked messages will be put into the digest."
              (setq mp (cdr mp)))))
         (mail-position-on-field "To")
         (message "Building %s digest... done" vm-digest-send-type)))
-    ;; (run-hooks 'tm-vm/send-digest-hook) ; Is it necessary?
+    (run-hooks 'tm-vm/send-digest-hook)
     (run-hooks 'vm-mail-mode-hook)))
 
-
-;;; @@ setting
-;;;
-
 (substitute-key-definition 'vm-forward-message
                           'tm-vm/forward-message vm-mode-map)
 (substitute-key-definition 'vm-send-digest
                           'tm-vm/send-digest vm-mode-map)
 
+;;; @@ for message/rfc822
+;;;
+\f
+
+;;; @@ setting
+;;;
+
+(defvar tm-vm/use-xemacs-popup-menu t)
+
+;;; modified by Steven L. Baur <steve@miranova.com>
+;;;    1995/12/6 (c.f. [tm-en:209])
+(defun mime-editor/attach-to-vm-mode-menu ()
+  "Arrange to attach MIME editor's popup menu to VM's"
+  (if (boundp 'vm-menu-mail-menu)
+      (progn
+       (setq vm-menu-mail-menu
+             (append vm-menu-mail-menu
+                     (list "----"
+                           mime-editor/popup-menu-for-xemacs)))
+       (remove-hook 'vm-mail-mode-hook 'mime-editor/attach-to-vm-mode-menu)
+       )))
+
 (call-after-loaded
  'tm-edit
  (function
   (lambda ()
+    (autoload 'tm-mail/insert-message "tm-mail")
     (set-alist 'mime-editor/message-inserter-alist
-              'mail-mode (function tm-vm/insert-message))
+              'mail-mode (function tm-mail/insert-message))
+    (if (and (string-match "XEmacs\\|Lucid" emacs-version)
+            tm-vm/use-xemacs-popup-menu)
+       (add-hook 'vm-mail-mode-hook 'mime-editor/attach-to-vm-mode-menu)
+      )
     )))
 
 (call-after-loaded
  'mime-setup
  (function
   (lambda ()
-    (remove-hook 'mail-mode-hook 'mime/editor-mode)
-    (add-hook 'vm-mail-mode-hook 'mime/editor-mode)
     (setq vm-forwarding-digest-type "rfc1521")
     (setq vm-digest-send-type "rfc1521")
     )))
 
 
+;;; @ for BBDB
+;;;
+
+(call-after-loaded
+ 'bbdb
+ (function
+  (lambda ()
+    (require 'bbdb-vm)
+    (require 'tm-bbdb)
+    (or (fboundp 'tm:bbdb/vm-update-record)
+        (fset 'tm:bbdb/vm-update-record
+              (symbol-function 'bbdb/vm-update-record)))
+    (defun bbdb/vm-update-record (&optional offer-to-create)
+      (vm-select-folder-buffer)
+      (if (and (tm-vm/system-state)
+               mime::article/preview-buffer
+               (get-buffer mime::article/preview-buffer))
+          (tm-bbdb/update-record offer-to-create)
+        (tm:bbdb/vm-update-record offer-to-create)
+        ))
+    (remove-hook 'vm-select-message-hook 'bbdb/vm-update-record)
+    (remove-hook 'vm-show-message-hook 'bbdb/vm-update-record)
+    (add-hook 'tm-vm/select-message-hook 'bbdb/vm-update-record)
+    )))
+
+
 ;;; @ end
 ;;;
 
 (provide 'tm-vm)
+
+(run-hooks 'tm-vm-load-hook)
+
+;;; tm-vm.el ends here.