Mercurial > hg > xemacs-beta
diff lisp/tm/tm-vm.el @ 16:0293115a14e9 r19-15b91
Import from CVS: tag r19-15b91
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:49:20 +0200 |
parents | 4b173ad71786 |
children | 859a2309aef8 |
line wrap: on
line diff
--- a/lisp/tm/tm-vm.el Mon Aug 13 08:48:43 2007 +0200 +++ b/lisp/tm/tm-vm.el Mon Aug 13 08:49:20 2007 +0200 @@ -9,7 +9,7 @@ ;; Oscar Figueiredo <Oscar.Figueiredo@di.epfl.ch> ;; Maintainer: Oscar Figueiredo <Oscar.Figueiredo@di.epfl.ch> ;; Created: 1994/10/29 -;; Version: $Revision: 1.2 $ +;; Version: $Revision: 1.3 $ ;; Keywords: mail, MIME, multimedia, multilingual, encoded-word ;; This file is part of tm (Tools for MIME). @@ -42,24 +42,202 @@ (require 'vm-window)) (require 'tm-view) +(require 'vm-menu) + + +;;; @ Variables + +;;; @@ User customization variables + +(defvar tm-vm/use-vm-bindings t + "*If t, use VM compatible keybindings in MIME Preview buffers. +Otherwise TM generic bindings for content extraction/playing are +made available.") + +(defvar tm-vm/attach-to-popup-menus t + "*If t append MIME specific commands to VM's popup menus.") + +(defvar tm-vm/use-original-url-button nil + "*If it is t, use original URL button instead of tm's.") + +(defvar tm-vm/automatic-mime-preview t + "*If non-nil, automatically process and show MIME messages.") + +(defvar tm-vm/strict-mime t + "*If nil, do MIME processing even if there is no MIME-Version field.") + +(defvar tm-vm/use-ps-print (not (featurep 'mule)) + "*Use Postscript printing (ps-print) to print MIME messages.") + +(defvar tm-vm-load-hook nil + "*List of functions called after tm-vm is loaded.") + +(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 tm-vm/select-message-hook instead. +When the hooks are run current buffer is either VM folder buffer with +the current message delimited by (point-min) and (point-max) or the MIME +Preview buffer.") + +(defvar tm-vm/forward-message-hook vm-forward-message-hook + "*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'.") + + +;;; @@ System/Information variables (defconst tm-vm/RCS-ID - "$Id: tm-vm.el,v 1.2 1996/12/22 00:29:43 steve Exp $") + "$Id: tm-vm.el,v 1.3 1997/02/02 05:06:20 steve Exp $") (defconst tm-vm/version (get-version-string tm-vm/RCS-ID)) +(defvar tm-vm/vm-emulation-map + (let ((map (make-sparse-keymap))) + (define-key map "h" 'vm-summarize) + ;(define-key map "\M-n" 'vm-next-unread-message) + ;(define-key map "\M-p" 'vm-previous-unread-message) + (define-key map "n" 'vm-next-message) + (define-key map "p" 'vm-previous-message) + (define-key map "N" 'vm-next-message-no-skip) + (define-key map "P" 'vm-previous-message-no-skip) + ;(define-key map "\C-\M-n" 'vm-move-message-forward) + ;(define-key map "\C-\M-p" 'vm-move-message-backward) + ;(define-key map "\t" 'vm-goto-message-last-seen) + ;(define-key map "\r" 'vm-goto-message) + ;(define-key map "^" 'vm-goto-parent-message) + (define-key map "t" 'vm-expose-hidden-headers) + (define-key map " " 'vm-scroll-forward) + (define-key map "b" 'vm-scroll-backward) + (define-key map "\C-?" 'vm-scroll-backward) + ;(define-key map "d" 'vm-delete-message) + ;(define-key map "\C-d" 'vm-delete-message-backward) + ;(define-key map "u" 'vm-undelete-message) + ;(define-key map "U" 'vm-unread-message) + ;(define-key map "e" 'vm-edit-message) + ;(define-key map "a" 'vm-set-message-attributes) + ;(define-key map "j" 'vm-discard-cached-data) + ;(define-key map "k" 'vm-kill-subject) + (define-key map "f" 'vm-followup) + (define-key map "F" 'vm-followup-include-text) + (define-key map "r" 'vm-reply) + (define-key map "R" 'vm-reply-include-text) + (define-key map "\M-r" 'vm-resend-bounced-message) + (define-key map "B" 'vm-resend-message) + (define-key map "z" 'vm-forward-message) + ;(define-key map "c" 'vm-continue-composing-message) + (define-key map "@" 'vm-send-digest) + ;(define-key map "*" 'vm-burst-digest) + (define-key map "m" 'vm-mail) + (define-key map "g" 'vm-get-new-mail) + ;(define-key map "G" 'vm-sort-messages) + (define-key map "v" 'vm-visit-folder) + ;(define-key map "s" 'vm-save-message) + ;(define-key map "w" 'vm-save-message-sans-headers) + ;(define-key map "A" 'vm-auto-archive-messages) + ;(define-key map "S" 'vm-save-folder) + ;(define-key map "|" 'vm-pipe-message-to-command) + ;(define-key map "#" 'vm-expunge-folder) + (define-key map "q" 'vm-quit) + (define-key map "x" 'vm-quit-no-change) + (define-key map "i" 'vm-iconify-frame) + (define-key map "?" 'vm-help) + (define-key map "\C-_" 'vm-undo) + (define-key map "\C-xu" 'vm-undo) + (define-key map "!" 'shell-command) + (define-key map "<" 'vm-beginning-of-message) + (define-key map ">" 'vm-end-of-message) + ;(define-key map "\M-s" 'vm-isearch-forward) + (define-key map "=" 'vm-summarize) + ;(define-key map "L" 'vm-load-init-file) + ;(define-key map "l" (make-sparse-keymap)) + ;(define-key map "la" 'vm-add-message-labels) + ;(define-key map "ld" 'vm-delete-message-labels) + ;(define-key map "V" (make-sparse-keymap)) + ;(define-key map "VV" 'vm-visit-virtual-folder) + ;(define-key map "VC" 'vm-create-virtual-folder) + ;(define-key map "VA" 'vm-apply-virtual-folder) + ;(define-key map "VM" 'vm-toggle-virtual-mirror) + ;(define-key map "V?" 'vm-virtual-help) + ;(define-key map "M" (make-sparse-keymap)) + ;(define-key map "MN" 'vm-next-command-uses-marks) + ;(define-key map "Mn" 'vm-next-command-uses-marks) + ;(define-key map "MM" 'vm-mark-message) + ;(define-key map "MU" 'vm-unmark-message) + ;(define-key map "Mm" 'vm-mark-all-messages) + ;(define-key map "Mu" 'vm-clear-all-marks) + ;(define-key map "MC" 'vm-mark-matching-messages) + ;(define-key map "Mc" 'vm-unmark-matching-messages) + ;(define-key map "MT" 'vm-mark-thread-subtree) + ;(define-key map "Mt" 'vm-unmark-thread-subtree) + ;(define-key map "MS" 'vm-mark-messages-same-subject) + ;(define-key map "Ms" 'vm-unmark-messages-same-subject) + ;(define-key map "MA" 'vm-mark-messages-same-author) + ;(define-key map "Ma" 'vm-unmark-messages-same-author) + ;(define-key map "M?" 'vm-mark-help) + ;(define-key map "W" (make-sparse-keymap)) + ;(define-key map "WW" 'vm-apply-window-configuration) + ;(define-key map "WS" 'vm-save-window-configuration) + ;(define-key map "WD" 'vm-delete-window-configuration) + ;(define-key map "W?" 'vm-window-help) + ;(define-key map "\C-t" 'vm-toggle-threads-display) + ;(define-key map "\C-x\C-s" 'vm-save-buffer) + ;(define-key map "\C-x\C-w" 'vm-write-file) + ;(define-key map "\C-x\C-q" 'vm-toggle-read-only) + ;(define-key map "%" 'vm-change-folder-type) + ;(define-key map "\M-C" 'vm-show-copying-restrictions) + ;(define-key map "\M-W" 'vm-show-no-warranty) + ;; suppress-keymap provides these, but now that we don't use + ;; suppress-keymap anymore... + (define-key map "0" 'digit-argument) + (define-key map "1" 'digit-argument) + (define-key map "2" 'digit-argument) + (define-key map "3" 'digit-argument) + (define-key map "4" 'digit-argument) + (define-key map "5" 'digit-argument) + (define-key map "6" 'digit-argument) + (define-key map "7" 'digit-argument) + (define-key map "8" 'digit-argument) + (define-key map "9" 'digit-argument) + (define-key map "-" 'negative-argument) + (if mouse-button-2 + (define-key map mouse-button-2 (function tm:button-dispatcher))) + (if (vm-menu-fsfemacs-menus-p) + (progn + (vm-menu-initialize-vm-mode-menu-map) + (define-key map [menu-bar] + (lookup-key vm-mode-menu-map [rootmenu vm])))) + map) + "VM emulation keymap for MIME-Preview buffers.") + +(defvar tm-vm/popup-menu + (let (fsfmenu + (dummy (make-sparse-keymap)) + (menu (append vm-menu-dispose-menu + (list "----" + (cons mime-viewer/menu-title + (mapcar (function + (lambda (item) + (vector (nth 1 item)(nth 2 item) t))) + mime-viewer/menu-list)))))) + (if running-xemacs + menu + (vm-easy-menu-define fsfmenu (list dummy) nil menu) + fsfmenu)) + "VM's popup menu + MIME specific commands") + (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/use-original-url-button nil - "*If it is t, use original URL button instead of tm's.") -(defvar tm-vm-load-hook nil - "*List of functions called after tm-vm is loaded.") - - -;;; @ for MIME encoded-words -;;; +;;; @ MIME encoded-words (defvar tm-vm/use-tm-patch nil "Does not decode encoded-words in summary buffer if it is t. @@ -156,30 +334,9 @@ (vm-preview-current-message) (setq vbufs (cdr vbufs)))))) - -;;; @ automatic MIME preview -;;; - -(defvar tm-vm/automatic-mime-preview t - "*If non-nil, automatically process and show MIME messages.") - -(defvar tm-vm/strict-mime t - "*If nil, do MIME processing even if there is no 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) - -(setq mime-viewer/content-header-filter-alist - (append '((vm-mode . tm-vm/header-filter) - (vm-virtual-mode . tm-vm/header-filter)) - mime-viewer/content-header-filter-alist)) - (defun tm-vm/header-filter () - "Filter headers in current buffer (assumed to be a message-like buffer) -according to vm-visible-headers and vm-invisible-header-regexp" + "Filter headers in current buffer according to vm-visible-headers and vm-invisible-header-regexp. +Current buffer is assumed to have a message-like structure." (goto-char (point-min)) (let ((visible-headers vm-visible-headers)) (if (or vm-use-lucid-highlighting @@ -190,6 +347,19 @@ vm-invisible-header-regexp) (mime/decode-message-header))) +(setq mime-viewer/content-header-filter-alist + (append '((vm-mode . tm-vm/header-filter) + (vm-virtual-mode . tm-vm/header-filter)) + mime-viewer/content-header-filter-alist)) + + + +;;; @ MIME Viewer + +;;; @@ MIME-Preview buffer management + +(defvar tm-vm/system-state nil) + (defun tm-vm/system-state () (save-excursion (if mime::preview/article-buffer @@ -197,51 +367,136 @@ (vm-select-folder-buffer)) tm-vm/system-state)) +(defun tm-vm/build-preview-buffer () + "Build the MIME Preview buffer for the current VM message. +Current buffer should be VM's folder buffer." + + (set (make-local-variable 'tm-vm/system-state) 'mime-viewing) + (setq vm-system-state 'reading) + + ;; Update message flags and store them in folder buffer before + ;; entering MIME viewer + (tm-vm/update-message-status) + + ;; We need to save window configuration because we may be working + ;; in summary window + (save-window-excursion + (save-restriction + (save-excursion + (widen) + (goto-char (vm-start-of (car vm-message-pointer))) + (forward-line) + (narrow-to-region (point) + (vm-end-of (car vm-message-pointer))) + + (let ((ml vm-message-list)) + (mime/viewer-mode nil nil nil nil nil nil) + (setq vm-mail-buffer mime::preview/article-buffer) + (setq vm-message-list ml)) + ;; Install VM toolbar for MIME-Preview buffer if not installed + (tm-vm/check-for-toolbar) + (if tm-vm/use-vm-bindings + (progn + (define-key tm-vm/vm-emulation-map "\C-c" (current-local-map)) + (use-local-map tm-vm/vm-emulation-map) + (vm-menu-install-menubar) + (if (and vm-use-menus + (vm-menu-support-possible-p)) + (setq mode-popup-menu tm-vm/popup-menu)))) + + ;; Highlight message (and display XFace if supported) + (if (or vm-highlighted-header-regexp + (and (vm-xemacs-p) vm-use-lucid-highlighting)) + (vm-highlight-headers)) + ;; Energize URLs and buttons + (if (and tm-vm/use-original-url-button + vm-use-menus (vm-menu-support-possible-p)) + (progn + (vm-energize-urls) + (vm-energize-headers))))))) + (defun tm-vm/sync-preview-buffer () - "Ensure that the MIME preview buffer, if it exists actually corresponds to -the current message. If no MIME Preview buffer is needed, delete it. If no + "Ensure that the MIME preview buffer, if it exists, actually corresponds to the current message. +If no MIME Preview buffer is needed then kill it. If no MIME Preview buffer exists nothing is done." ;; Current buffer should be message buffer when calling this function (let* ((mbuf (current-buffer)) (pbuf (and mime::article/preview-buffer - (get-buffer mime::article/preview-buffer))) - (win (or (and pbuf (vm-get-buffer-window pbuf)) - (vm-get-buffer-window mbuf))) - (frame (selected-frame))) + (get-buffer mime::article/preview-buffer)))) (if pbuf - ;; Go to the frame where pbuf or mbuf is (frame-per-composition t) - (save-excursion - (if win - (vm-select-frame (vm-window-frame win))) - ;; Rebuild MIME Preview buffer to ensure it corresponds to - ;; current message - (save-window-excursion - (save-selected-window - (save-excursion - (set-buffer mbuf) - (setq mime::article/preview-buffer nil) - (if pbuf (kill-buffer pbuf))) - (tm-vm/view-message))) + ;; A MIME Preview buffer exists then it may need to be synch'ed + (save-excursion + (set-buffer mbuf) + (if (and tm-vm/strict-mime + (not (vm-get-header-contents (car vm-message-pointer) + "MIME-Version:"))) + (progn + (setq mime::article/preview-buffer nil + tm-vm/system-state nil) + (if pbuf (kill-buffer pbuf))) + (tm-vm/build-preview-buffer))) ;; Return to previous frame - (vm-select-frame frame))))) + ))) + +(defun tm-vm/toggle-preview-mode () + "Toggle automatic MIME preview on or off. +In automatic MIME Preview mode each newly selected article is MIME processed if +it has MIME content without need for an explicit request from the user. This +behaviour is controlled by the variable tm-vm/automatic-mime-preview." + + (interactive) + (if tm-vm/automatic-mime-preview + (progn + (tm-vm/quit-view-message) + (setq tm-vm/automatic-mime-preview nil) + (message "Automatic MIME Preview is now disabled.")) + ;; Enable Automatic MIME Preview + (tm-vm/view-message) + (setq tm-vm/automatic-mime-preview t) + (message "Automatic MIME Preview is now enabled.") + )) + +;;; @@ Display functions + +(defun tm-vm/update-message-status () + "Update current message display and summary. +Remove 'unread' and 'new' flags. The MIME Preview buffer is not displayed, +tm-vm/display-preview-buffer should be called for that. This function is +display-configuration safe." + (if mime::preview/article-buffer + (set-buffer mime::preview/article-buffer) + (vm-select-folder-buffer)) + (if (or (and mime::article/preview-buffer + (get-buffer mime::article/preview-buffer) + (vm-get-visible-buffer-window mime::article/preview-buffer)) + (vm-get-visible-buffer-window (current-buffer))) + (progn + (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/display-preview-buffer () + "Replace the VM message buffer with the MIME-Preview buffer if the VM message buffer is currently displayed or undisplay it if tm-vm/system-state is nil." (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 + ;; display preview buffer if preview-buffer exists (cond ((and mwin pwin) (vm-undisplay-buffer mbuf) - (tm-vm/show-current-message)) + (tm-vm/update-message-status)) ((and mwin (not pwin)) (set-window-buffer mwin pbuf) - (tm-vm/show-current-message)) + (tm-vm/update-message-status)) (pwin - (tm-vm/show-current-message)) + (tm-vm/update-message-status)) (t ;; don't display if neither mwin nor pwin was displayed before. )) @@ -257,477 +512,94 @@ (t ;; don't display if neither mwin nor pwin was displayed before. ))) - (set-buffer mbuf))) + (set-buffer mbuf))) (defun tm-vm/preview-current-message () - "Preview current message if it has MIME contents and -tm-vm/automatic-mime-preview is non nil. Installed on -vm-visit-folder-hook and vm-select-message-hook." + "Either preview message (view first lines only) or MIME-Preview it. +The message is previewed if message previewing is enabled see vm-preview-lines. +If not, MIME-Preview current message (ie. parse MIME +contents and display appropriately) if it has MIME contents and +tm-vm/automatic-mime-preview is non nil. Installed on vm-visit-folder-hook and +vm-select-message-hook." ;; 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 (and vm-message-pointer + tm-vm/automatic-mime-preview + (or (null vm-preview-lines) + (not (eq vm-system-state 'previewing)) + (and (not vm-preview-read-messages) + (not (vm-new-flag (car vm-message-pointer))) + (not (vm-unread-flag (car vm-message-pointer)))))) (if (or (not tm-vm/strict-mime) (vm-get-header-contents (car vm-message-pointer) "MIME-Version:")) ;; do MIME processing. - (progn - ;; Consider message as shown => update its flags and store them - ;; in folder buffer before entering MIME viewer - (tm-vm/show-current-message) - (set (make-local-variable 'tm-vm/system-state) 'previewing) - (save-window-excursion - (vm-widen-page) - (goto-char (point-max)) - (widen) - (narrow-to-region (point) - (save-excursion - (goto-char - (vm-start-of (car vm-message-pointer)) - ) - (forward-line) - (point) - )) - - (mime/viewer-mode nil nil nil nil nil vm-mode-map) - ;; Highlight message (and display XFace if supported) - (if (or vm-highlighted-header-regexp - (and (vm-xemacs-p) vm-use-lucid-highlighting)) - (vm-highlight-headers)) - ;; Energize URLs and buttons - (if (and tm-vm/use-original-url-button - vm-use-menus (vm-menu-support-possible-p)) - (progn - (vm-energize-urls) - (vm-energize-headers))) - (goto-char (point-min)) - (narrow-to-region (point) (search-forward "\n\n" nil t)) - )) + (progn + (tm-vm/build-preview-buffer) + (save-excursion + (set-buffer mime::article/preview-buffer) + (run-hooks 'tm-vm/select-message-hook))) ;; don't do MIME processing. decode header only. (let (buffer-read-only) - (mime/decode-message-header)) + (mime/decode-message-header) + (run-hooks 'tm-vm/select-message-hook)) ) ;; don't preview; do nothing. - ) - (tm-vm/display-preview-buffer) - (run-hooks 'tm-vm/select-message-hook)) + (run-hooks 'tm-vm/select-message-hook)) + (tm-vm/display-preview-buffer)) + +(defun tm-vm/view-message () + "Decode and view the current VM message as a MIME encoded message. +A MIME Preview buffer using mime/viewer-mode is created. +See mime/viewer-mode for more information" + (interactive) + (vm-follow-summary-cursor) + (vm-select-folder-buffer) + (vm-check-for-killed-summary) + (vm-error-if-folder-empty) + (vm-display (current-buffer) t '(tm-vm/view-message + tm-vm/toggle-preview-mode) + '(tm-vm/view-message reading-message)) + (let ((tm-vm/automatic-mime-preview t)) + (tm-vm/preview-current-message)) +) -(defun tm-vm/show-current-message () - "Update current message display and summary. Remove 'unread' and 'new' flags. " - (if mime::preview/article-buffer - (set-buffer mime::preview/article-buffer) - (vm-select-folder-buffer)) - (if (and mime::article/preview-buffer - (get-buffer mime::article/preview-buffer)) - (save-excursion - (set-buffer mime::article/preview-buffer) - (goto-char (point-min)) - (widen))) - (if (or (and mime::article/preview-buffer - (get-buffer mime::article/preview-buffer) - (vm-get-visible-buffer-window mime::article/preview-buffer)) - (vm-get-visible-buffer-window (current-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 () - "Toggle automatic MIME preview on or off. In automatic MIME Preview mode -each newly selected article is MIME processed if it has MIME content without -need for an explicit request from the user. This behaviour is controlled by the -variable tm-vm/automatic-mime-preview." - (interactive) - (if tm-vm/automatic-mime-preview - (progn - (tm-vm/quit-view-message) - (setq tm-vm/automatic-mime-preview nil) - (message "Automatic MIME Preview is now disabled.")) - ;; Enable Automatic MIME Preview - (tm-vm/view-message) - (setq tm-vm/automatic-mime-preview t) - (message "Automatic MIME Preview is now enabled.") - )) +(defun tm-vm/quit-view-message () + "Quit MIME-Viewer and go back to normal VM. +MIME Preview buffer is killed. This function is called by `mime-viewer/quit' +command via `mime-viewer/quitting-method-alist'." + (if (get-buffer mime/output-buffer-name) + (vm-undisplay-buffer mime/output-buffer-name)) + (vm-select-folder-buffer) + (let* ((mbuf (current-buffer)) + (pbuf (and mime::article/preview-buffer + (get-buffer mime::article/preview-buffer))) + (pwin (and pbuf (vm-get-visible-buffer-window pbuf)))) + (if pbuf (kill-buffer pbuf)) + (and pwin + (select-window pwin) + (switch-to-buffer mbuf))) + (setq tm-vm/system-state nil) + (vm-display (current-buffer) t (list this-command) + (list 'reading-message))) (add-hook 'vm-select-message-hook 'tm-vm/preview-current-message) (add-hook 'vm-visit-folder-hook 'tm-vm/preview-current-message) - -;;; tm-vm move commands -;;; - -(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)) - (progn - (vm-scroll-forward arg) - (tm-vm/display-preview-buffer)) - (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/display-preview-buffer) - (setq mwin (vm-get-buffer-window mbuf) - pwin (and pbuf (vm-get-buffer-window pbuf))) - (cond - ((or mp-changed 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 - (tm-vm/save-window-excursion - (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)) - )))) - ))) - -;;; 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/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 - (tm-vm/save-window-excursion - (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)) - )))) - ))) - -;;; based on vm-beginning-of-message [vm-page.el] -(defun tm-vm/beginning-of-message () - "Moves to the beginning of the current message." - (interactive) - (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))) -;;; based on vm-quit [vm-folder.el] -(defun tm-vm/quit () - "Quit VM saving the folder buffer and killing the MIME Preview buffer if any" - (interactive) - (save-excursion - (vm-select-folder-buffer) - (if (and mime::article/preview-buffer - (get-buffer mime::article/preview-buffer)) - (kill-buffer mime::article/preview-buffer))) - (vm-quit)) - -(defun tm-vm/quit-no-change () - "Quit VM without saving the folder buffer but killing the MIME Preview buffer -if any" - (interactive) - (save-excursion - (vm-select-folder-buffer) - (if (and mime::article/preview-buffer - (get-buffer mime::article/preview-buffer)) - (kill-buffer mime::article/preview-buffer))) - (vm-quit-no-change)) - -;;; 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) - -;;; @@ vm-yank-message -;;; -;; 1996/3/28 by Oscar Figueiredo <figueire@lspsun16.epfl.ch> - -(require 'vm-reply) - -(defvar tm-vm/yank:message-to-restore nil - "For internal use by tm-vm only.") - -(defun vm-yank-message (&optional message) - "Yank message number N into the current buffer at point. -When called interactively N is always read from the minibuffer. When -called non-interactively the first argument is expected to be a -message struct. - -This function originally provided by vm-reply has been patched for TM -in order to provide better citation of MIME messages : if a MIME -Preview buffer exists for the message then its contents are inserted -instead of the raw message. - -This command is meant to be used in VM created Mail mode buffers; the -yanked message comes from the mail buffer containing the message you -are replying to, forwarding, or invoked VM's mail command from. - -All message headers are yanked along with the text. Point is -left before the inserted text, the mark after. Any hook -functions bound to mail-citation-hook are run, after inserting -the text and setting point and mark. For backward compatibility, -if mail-citation-hook is set to nil, `mail-yank-hooks' is run -instead. - -If mail-citation-hook and mail-yank-hooks are both nil, this -default action is taken: the yanked headers are trimmed as -specified by vm-included-text-headers and -vm-included-text-discard-header-regexp, and the value of -vm-included-text-prefix is prepended to every yanked line." - (interactive - (list - ;; What we really want for the first argument is a message struct, - ;; but if called interactively, we let the user type in a message - ;; number instead. - (let (mp default - (result 0) - prompt - (last-command last-command) - (this-command this-command)) - (if (bufferp vm-mail-buffer) - (save-excursion - (vm-select-folder-buffer) - (setq default (and vm-message-pointer - (vm-number-of (car vm-message-pointer))) - prompt (if default - (format "Yank message number: (default %s) " - default) - "Yank message number: ")) - (while (zerop result) - (setq result (read-string prompt)) - (and (string= result "") default (setq result default)) - (setq result (string-to-int result))) - (if (null (setq mp (nthcdr (1- result) vm-message-list))) - (error "No such message.")) - (setq tm-vm/yank:message-to-restore (string-to-int default)) - (save-selected-window - (vm-goto-message result)) - (car mp)) - nil)))) - (if (null message) - (if mail-reply-buffer - (tm-vm/yank-content) - (error "This is not a VM Mail mode buffer.")) - (if (null (buffer-name vm-mail-buffer)) - (error "The folder buffer containing message %d has been killed." - (vm-number-of message))) - (vm-display nil nil '(vm-yank-message) - '(vm-yank-message composing-message)) - (let ((b (current-buffer)) (start (point)) end) - (save-restriction - (widen) - (save-excursion - (set-buffer (vm-buffer-of message)) - (let* ((mbuf (current-buffer)) - pbuf) - (tm-vm/sync-preview-buffer) - (setq pbuf (and mime::article/preview-buffer - (get-buffer mime::article/preview-buffer))) - (if (and pbuf - (not (eq this-command 'tm-vm/forward-message))) - (if running-xemacs - (let ((tmp (generate-new-buffer "tm-vm/tmp"))) - (set-buffer pbuf) - (append-to-buffer tmp (point-min) (point-max)) - (set-buffer tmp) - (map-extents - '(lambda (ext maparg) - (set-extent-property ext 'begin-glyph nil))) - (append-to-buffer b (point-min) (point-max)) - (setq end (vm-marker - (+ start (length (buffer-string))) b)) - (kill-buffer tmp)) - (set-buffer pbuf) - (append-to-buffer b (point-min) (point-max)) - (setq end (vm-marker - (+ start (length (buffer-string))) b))) - (save-restriction - (setq message (vm-real-message-of message)) - (set-buffer (vm-buffer-of message)) - (widen) - (append-to-buffer - b (vm-headers-of message) (vm-text-end-of message)) - (setq end - (vm-marker (+ start (- (vm-text-end-of message) - (vm-headers-of message))) b)))))) - (push-mark end) - (cond (mail-citation-hook (run-hooks 'mail-citation-hook)) - (mail-yank-hooks (run-hooks 'mail-yank-hooks)) - (t (vm-mail-yank-default message))) - )) - (if tm-vm/yank:message-to-restore - (save-selected-window - (vm-goto-message tm-vm/yank:message-to-restore) - (setq tm-vm/yank:message-to-restore nil))) - )) -;;; @ for tm-view -;;; + +;;; @@ for tm-view ;;; based on vm-do-reply [vm-reply.el] (defun tm-vm/do-reply (buf to-all include-text) (save-excursion (set-buffer buf) (let ((dir default-directory) - to cc subject mp in-reply-to references newsgroups) + to cc subject in-reply-to references newsgroups) (cond ((setq to (let ((reply-to (std11-field-body "Reply-To"))) (if (vm-ignored-reply-to reply-to) @@ -829,42 +701,6 @@ (function tm-vm/following-method)) -(defun tm-vm/quit-view-message () - "Quit MIME-Viewer and go back to normal VM. MIME Preview buffer -is killed. This function is called by `mime-viewer/quit' command -via `mime-viewer/quitting-method-alist'." - (if (get-buffer mime/output-buffer-name) - (vm-undisplay-buffer mime/output-buffer-name)) - (vm-select-folder-buffer) - (let* ((mbuf (current-buffer)) - (pbuf (and mime::article/preview-buffer - (get-buffer mime::article/preview-buffer))) - (pwin (and pbuf (vm-get-visible-buffer-window pbuf)))) - (kill-buffer pbuf) - (and pwin - (select-window pwin) - (switch-to-buffer mbuf))) - (setq tm-vm/system-state nil) - (vm-display (current-buffer) t (list this-command) - (list 'reading-message)) - ) - -(defun tm-vm/view-message () - "Decode and view a MIME encoded message under VM. -A MIME Preview buffer using mime/viewer-mode is created. -See mime/viewer-mode for more information" - (interactive) - (vm-follow-summary-cursor) - (vm-select-folder-buffer) - (vm-check-for-killed-summary) - (vm-error-if-folder-empty) - (vm-display (current-buffer) t '(tm-vm/view-message - tm-vm/toggle-preview-mode) - '(tm-vm/view-message reading-message)) - (let ((tm-vm/automatic-mime-preview t)) - (tm-vm/preview-current-message)) -) - (set-alist 'mime-viewer/quitting-method-alist 'vm-mode 'tm-vm/quit-view-message) @@ -873,8 +709,386 @@ 'vm-virtual-mode 'tm-vm/quit-view-message) +;;; @@ Motion commands -;;; @ for tm-partial +(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))))) + +(defmacro tm-vm/save-frame-excursion (&rest forms) + (list 'let '((tm-vm/selected-frame (vm-selected-frame))) + (list 'unwind-protect + (cons 'progn forms) + '(if (frame-live-p tm-vm/selected-frame) + (vm-select-frame tm-vm/selected-frame))))) + +(defadvice vm-scroll-forward (around tm-aware activate) + "Made TM-aware (handles the MIME-Preview buffer)." + (if (and + (not (save-excursion + (if mime::preview/article-buffer + (set-buffer mime::preview/article-buffer)) + (vm-select-folder-buffer) + (eq vm-system-state 'previewing))) + (not (tm-vm/system-state))) + (progn + ad-do-it + (tm-vm/display-preview-buffer)) + (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))) + ) + (vm-check-for-killed-summary) + (vm-error-if-folder-empty) + (cond + ; A new message was selected + ; => leave it to tm-vm/preview-current-message + (mp-changed + nil) + ((eq vm-system-state 'previewing) + (vm-display (current-buffer) t (list this-command) '(reading-message)) + (vm-show-current-message) + (tm-vm/preview-current-message)) + ; Preview buffer was killed + ((null pbuf) + (tm-vm/preview-current-message)) + ; Preview buffer was undisplayed + ((null pwin) + (if (null mwin) + (vm-display mbuf t '(vm-scroll-forward vm-scroll-backward) + (list this-command 'reading-message))) + (tm-vm/display-preview-buffer)) + ; Preview buffer is displayed => scroll + (t + (tm-vm/save-window-excursion + (select-window pwin) + (set-buffer pbuf) + (if (pos-visible-in-window-p (point-max) pwin) + (vm-next-message) + ;; not at the end of message. scroll preview buffer only. + (scroll-up) + (tm-vm/howl-if-eom)) + )))) + ) +) + +(defadvice vm-scroll-backward (around tm-aware activate) + "Made TM-aware (handles the MIME-Preview buffer)." + (if (and + (not (save-excursion + (if mime::preview/article-buffer + (set-buffer mime::preview/article-buffer)) + (vm-select-folder-buffer) + (eq vm-system-state 'previewing))) + (not (tm-vm/system-state))) + ad-do-it + (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))) + ) + (vm-check-for-killed-summary) + (vm-error-if-folder-empty) + (cond + ; A new message was selected + ; => leave it to tm-vm/preview-current-message + (mp-changed + nil) + ((eq vm-system-state 'previewing) + (tm-vm/update-message-status) + (setq vm-system-state 'reading) + (tm-vm/preview-current-message)) + ; Preview buffer was killed + ((null pbuf) + (tm-vm/preview-current-message)) + ; Preview buffer was undisplayed + ((null pwin) + (if (null mwin) + (vm-display mbuf t '(vm-scroll-forward vm-scroll-backward) + (list this-command 'reading-message))) + (tm-vm/display-preview-buffer)) + ; Preview buffer is displayed => scroll + (t + (tm-vm/save-window-excursion + (select-window pwin) + (if (pos-visible-in-window-p (point-min) pwin) + nil + ;; not at the end of message. scroll preview buffer only. + (scroll-down)) + )))) + )) + +(defadvice vm-beginning-of-message (around tm-aware activate) + "Made TM-aware, works properly in MIME-Preview buffers." + (if (not (tm-vm/system-state)) + ad-do-it + (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)) + )))) + +(defadvice vm-end-of-message (around tm-aware activate) + "Made TM-aware, works properly in MIME-Preview buffers." + (interactive) + (if (not (tm-vm/system-state)) + ad-do-it + (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)) + (tm-vm/save-frame-excursion + (vm-select-frame (vm-window-frame pwin)) + (save-selected-window + (select-window pwin) + (save-excursion + (let ((scroll-in-place-replace-original nil)) + (scroll-up))))) + nil) + (error t)))) + (vm-emit-eom-blurb) + ))) + +(defadvice vm-emit-eom-blurb (around tm-aware activate) + "Made TM-aware, works properly in MIME-Preview buffers." + (save-excursion + (if mime::preview/article-buffer + (set-buffer mime::preview/article-buffer)) + ad-do-it)) + +(defadvice vm-next-message (around tm-aware activate) + "Made TM-aware, works properly in MIME-Preview buffers." + (if mime::preview/article-buffer + (set-buffer mime::preview/article-buffer)) + (tm-vm/save-window-excursion + ad-do-it)) + +(defadvice vm-previous-message (around tm-aware activate) + "Made TM-aware, works properly in MIME-Preview buffers." + (if mime::preview/article-buffer + (set-buffer mime::preview/article-buffer)) + (tm-vm/save-window-excursion + ad-do-it)) + +(defadvice vm-next-message-no-skip (around tm-aware activate) + "Made TM-aware, works properly in MIME-Preview buffers." + (if mime::preview/article-buffer + (set-buffer mime::preview/article-buffer)) + (tm-vm/save-window-excursion + ad-do-it)) + +(defadvice vm-previous-message-no-skip (around tm-aware activate) + "TM wrapper for vm-previous-message-no-skip (which see)." + (if mime::preview/article-buffer + (set-buffer mime::preview/article-buffer)) + (tm-vm/save-window-excursion + ad-do-it)) + +(defadvice vm-next-unread-message (around tm-aware activate) + "Made TM-aware, works properly in MIME-Preview buffers." + (if mime::preview/article-buffer + (set-buffer mime::preview/article-buffer)) + (tm-vm/save-window-excursion + ad-do-it)) + +(defadvice vm-previous-unread-message (around tm-aware activate) + "Made TM-aware, works properly in MIME-Preview buffers." + (if mime::preview/article-buffer + (set-buffer mime::preview/article-buffer)) + (tm-vm/save-window-excursion + ad-do-it)) + + +(set-alist 'mime-viewer/over-to-previous-method-alist + 'vm-mode 'vm-previous-message) +(set-alist 'mime-viewer/over-to-next-method-alist + 'vm-mode 'vm-next-message) +(set-alist 'mime-viewer/over-to-previous-method-alist + 'vm-virtual-mode 'vm-previous-message) +(set-alist 'mime-viewer/over-to-next-method-alist + 'vm-virtual-mode 'vm-next-message) + + + + + + +;;; @ MIME Editor + +;;; @@ vm-yank-message + +(require 'vm-reply) + +(defvar tm-vm/yank:message-to-restore nil + "For internal use by tm-vm only.") + +(defun vm-yank-message (&optional message) + "Yank message number N into the current buffer at point. +When called interactively N is always read from the minibuffer. When +called non-interactively the first argument is expected to be a +message struct. + +This function originally provided by vm-reply has been patched for TM +in order to provide better citation of MIME messages : if a MIME +Preview buffer exists for the message then its contents are inserted +instead of the raw message. + +This command is meant to be used in VM created Mail mode buffers; the +yanked message comes from the mail buffer containing the message you +are replying to, forwarding, or invoked VM's mail command from. + +All message headers are yanked along with the text. Point is +left before the inserted text, the mark after. Any hook +functions bound to mail-citation-hook are run, after inserting +the text and setting point and mark. For backward compatibility, +if mail-citation-hook is set to nil, `mail-yank-hooks' is run +instead. + +If mail-citation-hook and mail-yank-hooks are both nil, this +default action is taken: the yanked headers are trimmed as +specified by vm-included-text-headers and +vm-included-text-discard-header-regexp, and the value of +vm-included-text-prefix is prepended to every yanked line." + (interactive + (list + ;; What we really want for the first argument is a message struct, + ;; but if called interactively, we let the user type in a message + ;; number instead. + (let (mp default + (result 0) + prompt + (last-command last-command) + (this-command this-command)) + (if (bufferp vm-mail-buffer) + (save-excursion + (vm-select-folder-buffer) + (setq default (and vm-message-pointer + (vm-number-of (car vm-message-pointer))) + prompt (if default + (format "Yank message number: (default %s) " + default) + "Yank message number: ")) + (while (zerop result) + (setq result (read-string prompt)) + (and (string= result "") default (setq result default)) + (setq result (string-to-int result))) + (if (null (setq mp (nthcdr (1- result) vm-message-list))) + (error "No such message.")) + (setq tm-vm/yank:message-to-restore (string-to-int default)) + (save-selected-window + (vm-goto-message result)) + (car mp)) + nil)))) + (if (null message) + (if mail-reply-buffer + (tm-vm/yank-content) + (error "This is not a VM Mail mode buffer.")) + (if (null (buffer-name vm-mail-buffer)) + (error "The folder buffer containing message %d has been killed." + (vm-number-of message))) + (vm-display nil nil '(vm-yank-message) + '(vm-yank-message composing-message)) + (let ((b (current-buffer)) (start (point)) end) + (save-restriction + (widen) + (save-excursion + (set-buffer (vm-buffer-of message)) + (let (pbuf) + (tm-vm/sync-preview-buffer) + (setq pbuf (and mime::article/preview-buffer + (get-buffer mime::article/preview-buffer))) + (if (and pbuf + (not (eq this-command 'vm-forward-message))) + ;; Yank contents of MIME Preview buffer + (if running-xemacs + (let ((tmp (generate-new-buffer "tm-vm/tmp"))) + (set-buffer pbuf) + (append-to-buffer tmp (point-min) (point-max)) + (set-buffer tmp) + (map-extents + '(lambda (ext maparg) + (set-extent-property ext 'begin-glyph nil))) + (append-to-buffer b (point-min) (point-max)) + (setq end (vm-marker + (+ start (length (buffer-string))) b)) + (kill-buffer tmp)) + (set-buffer pbuf) + (append-to-buffer b (point-min) (point-max)) + (setq end (vm-marker + (+ start (length (buffer-string))) b))) + ;; Yank contents of raw VM message + (save-restriction + (setq message (vm-real-message-of message)) + (set-buffer (vm-buffer-of message)) + (widen) + (append-to-buffer + b (vm-headers-of message) (vm-text-end-of message)) + (setq end + (vm-marker (+ start (- (vm-text-end-of message) + (vm-headers-of message))) b)))))) + (push-mark end) + (cond (mail-citation-hook (run-hooks 'mail-citation-hook)) + (mail-yank-hooks (run-hooks 'mail-yank-hooks)) + (t (vm-mail-yank-default message))) + )) + (if tm-vm/yank:message-to-restore + (save-selected-window + (vm-goto-message tm-vm/yank:message-to-restore) + (setq tm-vm/yank:message-to-restore nil))) + )) + +;;; @@ for tm-partial ;;; (call-after-loaded @@ -896,23 +1110,18 @@ ))) -;;; @ for tm-edit -;;; - -;;; @@ for multipart/digest +;;; @@ for tm-edit ;;; -(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'.") +(call-after-loaded + 'mime-setup + (function + (lambda () + (setq vm-forwarding-digest-type "rfc1521") + (setq vm-digest-send-type "rfc1521") + ))) -(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'.") +;;; @@@ multipart/digest (defun tm-vm/enclose-messages (mlist &optional preamble) "Enclose the messages in MLIST as multipart/digest. @@ -951,14 +1160,10 @@ (mime-editor/enclose-digest-region (point-min) (point-max))) )))) -(defun tm-vm/forward-message () - "Forward the current message to one or more recipients. -You will be placed in a Mail mode buffer as you would with a -reply, but you must fill in the To: header and perhaps the -Subject: header manually." - (interactive) +(defadvice vm-forward-message (around tm-aware activate) + "Extended to support rfc1521 multipart digests and to work properly in MIME-Preview buffers." (if (not (equal vm-forwarding-digest-type "rfc1521")) - (vm-forward-message) + ad-do-it (if mime::preview/article-buffer (set-buffer mime::preview/article-buffer)) (vm-follow-summary-cursor) @@ -1010,8 +1215,7 @@ (let ((dir default-directory) (vm-forward-list (if (eq last-command 'vm-next-command-uses-marks) (vm-select-marked-or-prefixed-messages 0) - vm-message-list)) - start) + vm-message-list))) (save-restriction (widen) (vm-mail-internal (format "digest from %s" (buffer-name))) @@ -1028,16 +1232,10 @@ (run-hooks 'tm-vm/send-digest-hook) (run-hooks 'vm-mail-mode-hook))) -(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) - -;;; @@ setting -;;; - -(defvar tm-vm/use-xemacs-popup-menu t) +;;; @@@ Menus ;;; modified by Steven L. Baur <steve@miranova.com> ;;; 1995/12/6 (c.f. [tm-en:209]) @@ -1050,7 +1248,8 @@ (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 @@ -1066,21 +1265,78 @@ (funcall send-mail-function) ))) (if (and (string-match "XEmacs\\|Lucid" emacs-version) - tm-vm/use-xemacs-popup-menu) + tm-vm/attach-to-popup-menus) (add-hook 'vm-mail-mode-hook 'mime-editor/attach-to-vm-mode-menu) ) ))) -(call-after-loaded - 'mime-setup - (function - (lambda () - (setq vm-forwarding-digest-type "rfc1521") - (setq vm-digest-send-type "rfc1521") - ))) + + +;;; @ VM Integration + +(add-hook 'vm-quit-hook 'tm-vm/quit-view-message) + +;;; @@ Wrappers for miscellaneous VM functions + +(defadvice vm-summarize (around tm-aware activate) + "Made TM aware. Callable from the MIME Preview buffer." + (if mime::preview/article-buffer + (set-buffer mime::preview/article-buffer)) + ad-do-it + (save-excursion + (set-buffer vm-summary-buffer) + (tm-vm/check-for-toolbar)) + (tm-vm/preview-current-message)) + +(defadvice vm-expose-hidden-headers (around tm-aware activate) + "Made TM aware. Callable from the MIME Preview buffer." + (if mime::preview/article-buffer + (set-buffer mime::preview/article-buffer)) + (let ((visible-headers vm-visible-headers)) + (tm-vm/quit-view-message) + ad-do-it + (let ((vm-visible-headers visible-headers)) + (if (= (point-min) (vm-start-of (car vm-message-pointer))) + (setq vm-visible-headers '(".*"))) + (tm-vm/preview-current-message)))) + +(if (vm-mouse-fsfemacs-mouse-p) + (progn + (define-key tm-vm/vm-emulation-map [mouse-3] 'ignore) + (define-key tm-vm/vm-emulation-map [down-mouse-3] 'vm-mouse-button-3) + (defadvice vm-mouse-button-3 (after tm-aware activate) + "Made TM aware. Works in MIME-Preview buffers." + (if (and + vm-use-menus + (eq major-mode 'mime/viewer-mode)) + (vm-menu-popup-mode-menu event)))) +) -;;; @ for BBDB +;;; @@ VM Toolbar Integration + +(require 'vm-toolbar) + +;;; based on vm-toolbar-any-messages-p [vm-toolbar.el] +(defun tm-vm/check-for-toolbar () + "Install VM toolbar if necessary." + (if (and running-xemacs + vm-toolbar-specifier) + (progn + (if (null (specifier-instance vm-toolbar-specifier)) + (vm-toolbar-install-toolbar)) + (vm-toolbar-update-toolbar)))) + +(defun vm-toolbar-any-messages-p () + (save-excursion + (if mime::preview/article-buffer + (set-buffer mime::preview/article-buffer)) + (vm-check-for-killed-folder) + (vm-select-folder-buffer) + vm-message-list)) + + +;;; @ BBDB Integration ;;; (call-after-loaded @@ -1090,26 +1346,24 @@ (require 'bbdb-vm) (require 'tm-bbdb) (defun tm-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)) - (let ((tm-bbdb/auto-create-p bbdb/mail-auto-create-p)) - (tm-bbdb/update-record offer-to-create)) - (or (bbdb/vm-update-record offer-to-create) - (delete-windows-on (get-buffer "*BBDB*"))) - )) + (save-excursion + (vm-select-folder-buffer) + (if (and (tm-vm/system-state) + mime::article/preview-buffer + (get-buffer mime::article/preview-buffer)) + (let ((tm-bbdb/auto-create-p bbdb/mail-auto-create-p)) + (tm-bbdb/update-record offer-to-create)) + (or (bbdb/vm-update-record offer-to-create) + (delete-windows-on (get-buffer "*BBDB*"))) + ))) (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 'tm-bbdb/vm-update-record) ))) -;;; @ for ps-print (Suggestted by Anders Stenman <stenman@isy.liu.se>) +;;; @ ps-print (Suggested by Anders Stenman <stenman@isy.liu.se>) ;;; -(defvar tm-vm/use-ps-print (not (featurep 'mule)) - "*Use Postscript printing (ps-print) to print MIME messages.") - (if tm-vm/use-ps-print (progn (autoload 'ps-print-buffer-with-faces "ps-print" "Postscript Print" t) @@ -1133,11 +1387,10 @@ Value of tm-vm/strict-mime is also taken into consideration." (interactive) (vm-follow-summary-cursor) - (let* ((mbuf (or (vm-select-folder-buffer) (current-buffer))) - pbuf) - (tm-vm/sync-preview-buffer) - (setq pbuf (and mime::article/preview-buffer - (get-buffer mime::article/preview-buffer))) + (vm-select-folder-buffer) + (tm-vm/sync-preview-buffer) + (let ((pbuf (and mime::article/preview-buffer + (get-buffer mime::article/preview-buffer)))) (if pbuf (save-excursion (set-buffer pbuf) @@ -1146,40 +1399,9 @@ (vm-print-message)))) -;;; @ Substitute VM bindings and menus -;;; - -(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-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-forward-message - 'tm-vm/forward-message vm-mode-map) -(substitute-key-definition 'vm-quit - 'tm-vm/quit vm-mode-map) -(substitute-key-definition 'vm-quit-no-change - 'tm-vm/quit-no-change vm-mode-map) - -;; The following function should be modified and called on vm-menu-setup-hook -;; but VM 5.96 does not run that hook on XEmacs -(require 'vm-menu) -(if running-xemacs - (condition-case nil - (aset (car (find-menu-item vm-menu-dispose-menu '("Forward"))) - 1 - 'tm-vm/forward-message) - (t nil))) - ;;; @ end -;;; (provide 'tm-vm) - (run-hooks 'tm-vm-load-hook) ;;; tm-vm.el ends here. -