Commits

Anonymous committed 4007973

2002-05-09 Ben Wing <ben@xemacs.org>

* arc-mode.el (archive-*-write-file-member):
* arc-mode.el (archive-lzh-summarize):
* arc-mode.el (archive-zip-summarize):
Use #o... not ?\... to get octal integers. ?\ in XEmacs
gives chars and you will get syntax errors or worse.

2002-05-09 Ben Wing <ben@xemacs.org>

* pending-del.el: Add {backward{or-forward}-}kill-word to
delete-like behaviors along with delete-char etc., so that
CTRL-DEL (now bound to kill-word) gets its old behavior of delete
selection when there's a selection. (And this behavior in general
with delete-word commands functioning as delete-selection is more
standard and makes more sense than what we'd otherwise have.)

2002-05-09 Rendhalver [Peter Brown] <rendhalver@xemacs.org>

* apache-mode.el: separated apache directives into sections
for easier updating
* apache-mode.el (apache-font-lock-keywords):

2002-05-09 Steve Youngs <youngs@xemacs.org>

* Sync with VM-7.04

Comments (0)

Files changed (16)

 
 	* Makefile (VERSION): XEmacs package 7.04 released.
 
+	* Sync with VM-7.04
+
 	* Makefile (PRELOADS): Remove ./'s
 
 2002-03-25  Steve Youngs  <youngs@xemacs.org>
 # Boston, MA 02111-1307, USA.
 
 VERSION = 7.04
-AUTHOR_VERSION = 7.03
+AUTHOR_VERSION = 7.04
 MAINTAINER = Kyle Jones <kyle_jones@wonderworks.com>
 PACKAGE = vm
 PKG_TYPE = regular
 	       (or (not use-marks)
 		   (vm-mark-of (car mp)))))
 	;; remove the message from the thread tree.
-	(if vm-thread-obarray
+	(if (vectorp vm-thread-obarray)
 	    (vm-unthread-message (vm-real-message-of (car mp))))
 	;; expunge from the virtual side first, removing all
 	;; references to this message before actually removing
     (while mlist
       (setq m (vm-real-message-of (car mlist)))
       (vm-garbage-collect-message)
-      (if vm-thread-obarray
+      (if (vectorp vm-thread-obarray)
 	  (vm-unthread-message m t))
       (fillarray (vm-cache-of m) nil)
       (vm-set-vheaders-of m nil)
       (vm-set-mime-encoded-header-flag-of m nil)
       (if (and vm-presentation-buffer (eq (car vm-message-pointer) m))
 	  (save-excursion (vm-preview-current-message)))
-      (if vm-thread-obarray
+      (if (vectorp vm-thread-obarray)
 	  (vm-build-threads (list m)))
       (if vm-summary-show-threads
 	  (intern (buffer-name) buffers-needing-thread-sort))
 	    (if (and vm-presentation-buffer
 		     (eq (car vm-message-pointer) (car v-list)))
 		(save-excursion (vm-preview-current-message)))
-	    (if vm-thread-obarray
+	    (if (vectorp vm-thread-obarray)
 		(vm-build-threads (list (car v-list))))
 	    (if vm-summary-show-threads
 		(intern (buffer-name) buffers-needing-thread-sort))
 
 		(vm-startup-apply-bookmark bookmark)
 		(and order (vm-startup-apply-message-order order))
+		(if vm-summary-show-threads
+		    (progn
+		      ;; get numbering of new messages done now
+		      ;; so that the sort code only has to worry about the
+		      ;; changes it needs to make.
+		      (vm-update-summary-and-mode-line)
+		      (vm-sort-messages "thread")))
 		(vm-startup-apply-summary summary)
 		(vm-startup-apply-labels labels)
 		(vm-startup-apply-header-variables vis invis)
 	     ;; done here too.
 	     (if gobble-order
 		 (vm-gobble-message-order))
-	     (if vm-thread-obarray
+	     (if (vectorp vm-thread-obarray)
 		 (vm-build-threads (cdr tail-cons))))))
       (setq new-messages (if tail-cons (cdr tail-cons) vm-message-list))
       (vm-set-numbering-redo-start-point new-messages)
 		  (if (or (null tail-cons) (cdr tail-cons))
 		      (progn
 			(setq vm-ml-sort-keys nil)
-			(if vm-thread-obarray
+			(if (vectorp vm-thread-obarray)
 			    (vm-build-threads (cdr tail-cons)))
 			(vm-set-summary-redo-start-point
 			 (or (cdr tail-cons) vm-message-list))
    ;; don't let CR's in folders be mashed into LF's because of a
    ;; stupid user setting.
    selective-display nil
-   vm-thread-obarray nil
-   vm-thread-subject-obarray nil
+   vm-thread-obarray 'bonk
+   vm-thread-subject-obarray 'bonk
    vm-label-obarray (make-vector 29 0)
    vm-last-message-pointer nil
    vm-modification-counter 0
 		 (skip-chars-forward "^\042")
 		 (setq curpoint (point))
 		 (if (looking-at "\042")
-		     (setq done t)
+		     (progn
+		       (setq done t)
+		       (forward-char 1))
 		   (accept-process-output process)
 		   (goto-char curpoint))
-	       (setq token (list 'string start (1- curpoint))))))
+	       (setq token (list 'string start curpoint)))))
 	    ;; should be (looking-at "[\000-\040\177-\377]")
 	    ;; but Microsoft Exchange emits 8-bit chars.
 	    ((looking-at "[\000-\040\177]")
        (error "%s cannot be applied to virtual folders." this-command)))
 
 (defsubst vm-build-threads-if-unbuilt ()
-  (if (null vm-thread-obarray)
+  (if (not (vectorp vm-thread-obarray))
       (vm-build-threads nil)))
 
 (defsubst vm-binary-coding-system ()
 			 "---")
 		 (list "VM"))))
     `(,@title
-      vm-menu-folder-menu
-      vm-menu-motion-menu
-      vm-menu-send-menu
-      vm-menu-mark-menu
-      vm-menu-label-menu
-      vm-menu-sort-menu
-      vm-menu-virtual-menu
-;;    vm-menu-undo-menu
-      vm-menu-dispose-menu
+      ,vm-menu-folder-menu
+      ,vm-menu-motion-menu
+      ,vm-menu-send-menu
+      ,vm-menu-mark-menu
+      ,vm-menu-label-menu
+      ,vm-menu-sort-menu
+      ,vm-menu-virtual-menu
+;;    ,vm-menu-undo-menu
+      ,vm-menu-dispose-menu
       "---"
       "---"
-      vm-menu-help-menu)))
+      ,vm-menu-help-menu)))
 
 (defvar vm-mode-menu-map nil)
 
 				  (car type)))
 		  ((and (string-match "^multipart/\\|^message/" (car type))
 			(null (string-match "^\\(7bit\\|8bit\\|binary\\)$"
-					    encoding)))
+					    encoding))
+			(if vm-mime-ignore-composite-type-opaque-transfer-encoding
+			    (progn
+			      ;; Some mailers declare an opaque
+			      ;; encoding on a composite type even
+			      ;; though it's only a subobject that
+			      ;; uses that encoding.  Deal with it
+			      ;; by assuming a proper transfer encoding.
+			      (setq encoding "binary")
+			      ;; return nil so and-clause will fail
+			      nil )
+			  t ))
 		   (vm-mime-error "Opaque transfer encoding used with multipart or message type: %s, %s" (car type) encoding))
 		  ((and (string-match "^message/partial$" (car type))
 			(null (string-match "^7bit$" encoding)))
   (vm-mime-display-internal-text/plain layout))
 
 (defun vm-mime-display-internal-text/html (layout)
-  (if (fboundp 'w3-region)
+  (if (and (fboundp 'w3-region)
+	   vm-mime-use-w3-for-text/html)
       (condition-case error-data
 	  (let ((buffer-read-only nil)
 		(start (point))
     nil ))
 
 (defun vm-mime-display-button-xxxx (layout disposable)
-  (if (or (vm-mime-can-display-internal layout)
-	  (vm-mime-find-external-viewer (car (vm-mm-layout-type layout)))
-	  (vm-mime-can-convert (car (vm-mm-layout-type layout))))
-      (progn
-	(vm-mime-insert-button
-	 (vm-mime-sprintf (vm-mime-find-format-for-layout layout) layout)
-	 (function
-	  (lambda (layout)
-	    (save-excursion
-	      (let ((vm-auto-displayed-mime-content-types t)
-		    (vm-auto-displayed-mime-content-type-exceptions nil))
-		(vm-decode-mime-layout layout t)))))
-	 layout disposable)
-	t )
-    ;; don't display a button if we have no way of displaying the
-    ;; object.
-    nil ))
+  (vm-mime-insert-button
+   (vm-mime-sprintf (vm-mime-find-format-for-layout layout) layout)
+   (function
+    (lambda (layout)
+      (save-excursion
+	(let ((vm-auto-displayed-mime-content-types t)
+	      (vm-auto-displayed-mime-content-type-exceptions nil))
+	  (vm-decode-mime-layout layout t)))))
+   layout disposable)
+  t )
+
+(defun vm-find-layout-extent-at-point ()
+  (cond (vm-fsfemacs-p
+	 (let (o-list o retval (found nil))
+	   (setq o-list (overlays-at (point)))
+	   (while (and o-list (not found))
+	     (cond ((overlay-get (car o-list) 'vm-mime-layout)
+		    (setq found t)
+		    (setq retval (car o-list))))
+	     (setq o-list (cdr o-list)))
+	   retval ))
+	(vm-xemacs-p
+	 (extent-at (point) nil 'vm-mime-layout))))
 
 (defun vm-mime-run-display-function-at-point (&optional function dispose)
   (interactive)
   ;; drag window point along, to a place arbitrarily far from
   ;; where it was when the user triggered the button.
   (save-excursion
-    (cond (vm-fsfemacs-p
-	   (let (o-list o retval (found nil))
-	     (setq o-list (overlays-at (point)))
-	     (while (and o-list (not found))
-	       (cond ((overlay-get (car o-list) 'vm-mime-layout)
-		      (setq found t)
-		      ;; return value is used by caller.
-		      (setq retval 
-			    (funcall (or function (overlay-get (car o-list)
-							       'vm-mime-function))
-				     (car o-list)))))
-	       (setq o-list (cdr o-list)))
-	     retval ))
-	  (vm-xemacs-p
-	   (let ((e (extent-at (point) nil 'vm-mime-layout)))
-	     ;; return value is used by caller.
+    (let ((e (vm-find-layout-extent-at-point))
+	  retval )
+      (cond ((null e) nil)
+	    (vm-fsfemacs-p
+	     (funcall (or function (overlay-get e 'vm-mime-function))
+		      e))
+	    (vm-xemacs-p
 	     (funcall (or function (extent-property e 'vm-mime-function))
 		      e))))))
 
   t )
 
 (defun vm-mime-pipe-body-to-queried-command (layout &optional discard-output)
-  (let ((command (read-string "Pipe to command: ")))
+  (let ((command (read-string "Pipe object to command: ")))
     (vm-mime-pipe-body-to-command command layout discard-output)))
 
 (defun vm-mime-pipe-body-to-queried-command-discard-output (layout)
   (cond ((and vm-xemacs-mule-p (memq (device-type) '(x mswindows)))
 	 (or (vm-string-assoc name vm-mime-mule-charset-to-coding-alist)
 	     (vm-mime-default-face-charset-p name)))
-	((and vm-fsfemacs-mule-p (memq window-system '(x win32 w32)))
+	((and vm-fsfemacs-mule-p (memq window-system '(x mac win32 w32)))
 	 (or (vm-string-assoc name vm-mime-mule-charset-to-coding-alist)
 	     (vm-mime-default-face-charset-p name)))
 	((vm-multiple-fonts-possible-p)
 		      (list 'if (list 'eq (current-buffer) '(current-buffer))
 			    (list 'kill-buffer buf)))))))
 
+(defun vm-mime-attach-object-from-message (composition)
+  "Attach a object from the current message to a VM composition buffer.
+
+The object is not inserted into the buffer and MIME encoded until
+you execute `vm-mail-send' or `vm-mail-send-and-exit'.  A visible tag
+indicating the existence of the object is placed in the
+composition buffer.  You can move the object around or remove
+it entirely with normal text editing commands.  If you remove the
+object tag, the object will not be sent.
+
+First argument COMPOSITION is the buffer into which the object
+will be inserted.  When this function is called interactively
+COMPOSITION's name will be read from the minibuffer."
+  (interactive
+   ;; protect value of last-command and this-command
+   (let ((last-command last-command)
+	 (this-command this-command))
+     (list
+      (read-buffer "Attach object to buffer: "
+		   (vm-find-composition-buffer) t))))
+  (if (null vm-send-using-mime)
+      (error "MIME attachments disabled, set vm-send-using-mime non-nil to enable."))
+  (vm-check-for-killed-summary)
+  (vm-error-if-folder-empty)
+
+  (let (e layout (work-buffer nil) buf)
+    (setq e (vm-find-layout-extent-at-point)
+	  layout (and e (vm-extent-property e 'vm-mime-layout)))
+    (unwind-protect
+	(if (null layout)
+	    (error "No MIME object found at point.")
+	  (save-excursion
+	    (setq work-buffer (vm-make-work-buffer))
+	    (set-buffer work-buffer)
+	    (vm-mime-insert-mime-headers layout)
+	    (insert "\n")
+	    (vm-mime-insert-mime-body layout)
+	    (set-buffer composition)
+	    (vm-mime-attach-object work-buffer
+				   (car (vm-mm-layout-type layout))
+				   (cdr (vm-mm-layout-type layout))
+				   (vm-mm-layout-description layout)
+				   t)
+	    (setq buf work-buffer
+		  work-buffer nil)
+	    (add-hook 'kill-buffer-hook
+		      (list 'lambda ()
+			    (list 'if (list 'eq (current-buffer)
+					    '(current-buffer))
+				  (list 'kill-buffer buf))))))
+      (and work-buffer (kill-buffer work-buffer)))))
+
 (defun vm-mime-attach-object (object type params description mimed
 			      &optional no-suggested-filename)
   (if (not (eq major-mode 'mail-mode))
 
 (defun vm-display-xface-fsfemacs ()
   (catch 'done
-    (let ((case-fold-search t) i g h)
-      (if (next-single-property-change (point-min) 'vm-xface)
-	  nil
-	(goto-char (point-min))
-	(if (re-search-forward "^X-Face:" nil t)
-	    (progn
-	      (goto-char (match-beginning 0))
-	      (vm-match-header)
-	      (setq h (vm-matched-header-contents))
-	      (setq g (intern h vm-xface-cache))
-	      (if (boundp g)
-		  (setq g (symbol-value g))
-		(setq i (vm-convert-xface-to-fsfemacs-image-instantiator h))
-		(cond (i
-		       (set g i)
-		       (setq g (symbol-value g)))
-		      (t (throw 'done nil))))
-	      (let ((pos (vm-vheaders-of (car vm-message-pointer)))
-		    o )
-		;; An image must replace the normal display of at
-		;; least one character.  Since we want to put the
-		;; image at the beginning of the visible headers
-		;; section, it will obscure the first character of
-		;; that section.  To display that character we add
-		;; an after-string that contains the character.
-		;; Kludge city, but it works.
-		(setq o (make-overlay (+ 0 pos) (+ 1 pos)))
-		(overlay-put o 'after-string
-			     (char-to-string (char-after pos)))
-		(overlay-put o 'display g))))))))
+    (let ((case-fold-search t) i g h ooo)
+      (setq ooo (overlays-in (point-min) (point-max)))
+      (while ooo
+	(if (overlay-get (car ooo) 'vm-xface)
+	    (delete-overlay (car ooo)))
+	(setq ooo (cdr ooo)))
+      (goto-char (point-min))
+      (if (re-search-forward "^X-Face:" nil t)
+	  (progn
+	    (goto-char (match-beginning 0))
+	    (vm-match-header)
+	    (setq h (vm-matched-header-contents))
+	    (setq g (intern h vm-xface-cache))
+	    (if (boundp g)
+		(setq g (symbol-value g))
+	      (setq i (vm-convert-xface-to-fsfemacs-image-instantiator h))
+	      (cond (i
+		     (set g i)
+		     (setq g (symbol-value g)))
+		    (t (throw 'done nil))))
+	    (let ((pos (vm-vheaders-of (car vm-message-pointer)))
+		  o )
+	      ;; An image must replace the normal display of at
+	      ;; least one character.  Since we want to put the
+	      ;; image at the beginning of the visible headers
+	      ;; section, it will obscure the first character of
+	      ;; that section.  To display that character we add
+	      ;; an after-string that contains the character.
+	      ;; Kludge city, but it works.
+	      (setq o (make-overlay (+ 0 pos) (+ 1 pos)))
+	      (overlay-put o 'vm-xface t)
+	      (overlay-put o 'evaporate t)
+	      (overlay-put o 'after-string
+			   (char-to-string (char-after pos)))
+	      (overlay-put o 'display g)))))))
 
 (defun vm-convert-xface-to-fsfemacs-image-instantiator (data)
   (let ((work-buffer nil)
 (defvar vm-dont-ask-coding-system-question nil)
 
 (cond ((and vm-fsfemacs-mule-p
+	    (fboundp 'select-message-coding-system)
 	    (not (fboundp 'vm-old-select-message-coding-system)))
        (fset 'vm-old-select-message-coding-system
 	     (symbol-function 'select-message-coding-system))
 		(list this-command 'composing-message))
     (if (null to)
 	(mail-position-on-field "To"))
-    (add-hook 'post-command-hook 'vm-update-composition-buffer-name t)
+    (if (boundp 'post-command-idle-hook)
+	(add-hook 'post-command-idle-hook
+		   'vm-update-composition-buffer-name t)
+      (add-hook 'post-command-hook 'vm-update-composition-buffer-name t))
     (run-hooks 'mail-setup-hook)))
 
 (defun vm-reply-other-frame (count)
 (defun vm-mode (&optional read-only)
   "Major mode for reading mail.
 
-This is VM 7.03.
+This is VM 7.04.
 
 Commands:
    h - summarize folder contents
    vm-frame-per-summary
    vm-highlighted-header-face
    vm-highlighted-header-regexp
+   vm-honor-mime-content-disposition
    vm-honor-page-delimiters
+   vm-icontopbm-program
    vm-image-directory
    vm-imagemagick-convert-program
    vm-imagemagick-identify-program
    vm-thread-using-subject
    vm-toolbar-pixmap-directory
    vm-trust-From_-with-Content-Length
+   vm-uncompface-program
    vm-undisplay-buffer-hook
    vm-unforwarded-header-regexp
    vm-url-browser
       'vm-frame-per-summary
       'vm-highlight-url-face
       'vm-highlighted-header-regexp
+      'vm-honor-mime-content-disposition
       'vm-honor-page-delimiters
+      'vm-icontopbm-program
       'vm-image-directory
       'vm-imagemagick-convert-program
       'vm-imagemagick-identify-program
       'vm-thread-using-subject
       'vm-toolbar-pixmap-directory
       'vm-trust-From_-with-Content-Length
+      'vm-uncompface-program
       'vm-undisplay-buffer-hook
       'vm-unforwarded-header-regexp
       'vm-url-browser
 		     ;; names may not be valid.
 		     (set-face-foreground 'gui-button-face "white")
 		     (set-face-background 'gui-button-face "red")))))
+	;; gui-button-face might not exist under XEmacs either.
+	;; This can happen if XEmacs is built without window
+	;; system support.  In any case, create it anyway.
+	(if (and vm-xemacs-p (not (find-face 'gui-button-face)))
+	    (progn
+	      (make-face 'gui-button-face)
+	      (set-face-foreground 'gui-button-face "black" nil '(win))
+	      (set-face-background 'gui-button-face "gray75" nil '(win))
+	      (set-face-foreground 'gui-button-face "white" nil '(tty))
+	      (set-face-background 'gui-button-face "red" nil '(tty))))
 	(and (vm-mouse-support-possible-p)
 	     (vm-mouse-install-mouse))
 	(and (vm-menu-support-possible-p)
     (vm-sort-messages "physical-order")))
 
 (defun vm-build-threads (message-list)
-  (if (null vm-thread-obarray)
+  (if (not (vectorp vm-thread-obarray))
       (setq vm-thread-obarray (make-vector 641 0)
 	    vm-thread-subject-obarray (make-vector 641 0)))
   (let ((mp (or message-list vm-message-list))
   :type 'boolean)
 
 (defcustom vm-mime-require-mime-version-header t
-  "Non-nil means a message must contain MIME-Version to be considered MIME.
+  "*Non-nil means a message must contain MIME-Version to be considered MIME.
 The MIME standard requires that MIME messages contain a MIME-Version,
 but some mailers ignore the standard and do not send the header.  Set
 this variable to nil if you want VM to be lax and parse such messages
 as MIME anyway."
   :type 'boolean)
 
+(defcustom vm-mime-ignore-composite-type-opaque-transfer-encoding t
+  "*Non-nil means VM should ignore type declaration of base64 and
+quoted-printable for objecto ftype message/* or multipart/*.  The
+MIME spec requries that these ype use either 7bit, 8bit, or binary
+transfer encodings but some mailers declare quoted-printable and
+base64 even when they are not used.  Set this variable if you want
+VM to ignore this problem and try to display the object anyway."
+  :type 'boolean)
+
 (defcustom vm-send-using-mime t
   "*Non-nil value means VM should support sending messages using MIME.
 MIME (Multipurpose Internet Mail Extensions) is a set of
 current buffer will be the folder containing the message and the
 start and end of the message will be bracketed by (point-min) and
 (point-max)."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-select-unread-message-hook nil
   "*List of hook functions called every time a message with the 'unread'
 current buffer will be the folder containing the message and the
 start and end of the message will be bracketed by (point-min) and
 (point-max)."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-select-message-hook nil
   "*List of hook functions called every time a message
 current buffer will be the folder containing the message and the
 start and end of the message will be bracketed by (point-min) and
 (point-max)."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-arrived-message-hook nil
   "*List of hook functions called once for each message gathered from
 hooks are run, the current buffer will be the folder containing
 the message and the start and end of the message will be
 bracketed by (point-min) and (point-max)."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-spooled-mail-waiting-hook nil
   "*List of functions called when VM first notices mail is spooled
 for a folder.  The folder buffer will be current when the hooks are
 run."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-arrived-messages-hook nil
   "*List of hook functions called after VM has gathered a group of
 the message list but may not yet appear in the summary.
 Also, the current buffer will be the folder containing
 the messages."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-reply-hook nil
   "*List of hook functions to be run after a Mail mode
 composition buffer has been created for a reply.  VM runs this
 hook and then runs `vm-mail-mode-hook' before leaving the user in
 the Mail mode buffer."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-forward-message-hook nil
   "*List of hook functions to be run after a Mail mode
 composition buffer has been created to forward a message.  VM
 runs this hook and then runs `vm-mail-mode-hook' before leaving the
 user in the Mail mode buffer."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-resend-bounced-message-hook nil
   "*List of hook functions to be run after a Mail mode
 composition buffer has been created to resend a bounced message.
 VM runs this hook and then runs `vm-mail-mode-hook' before leaving
 the user in the Mail mode buffer."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-resend-message-hook nil
   "*List of hook functions to be run after a Mail mode
 composition buffer has been created to resend a message.
 VM runs this hook and then runs `vm-mail-mode-hook' before leaving
 the user in the Mail mode buffer."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-send-digest-hook nil
   "*List of hook functions to be run after a Mail mode
 composition buffer has been created to send a digest.
 VM runs this hook and then runs `vm-mail-mode-hook' before leaving
 the user in the Mail mode buffer."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-mail-hook nil
   "*List of hook functions to be run after a Mail mode
 message, i.e. a message that is not a reply, forward, digest,
 etc.  VM runs this hook and then runs `vm-mail-mode-hook' before
 leaving the user in the Mail mode buffer."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-summary-update-hook nil
   "*List of hook functions called just after VM updates an existing
 entry a folder summary."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-summary-redo-hook nil
   "*List of hook functions called just after VM adds or deletes
 entries from a folder summary."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-visit-folder-hook nil
   "*List of hook functions called just after VM visits a folder.
 It doesn't matter if the folder buffer already exists, this hook
 is run each time `vm' or `vm-visit-folder' is called interactively.
 It is NOT run after `vm-mode' is called."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-retrieved-spooled-mail-hook nil
   "*List of hook functions called just after VM has retrieved
 but not the message list or summary.  When the hooks are run, the
 current buffer will be the folder where the messages were
 incorporated."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-edit-message-hook nil
   "*List of hook functions to be run just before a message is edited.
 This is the last thing `vm-edit-message' does before leaving the user
 in the edit buffer."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-mail-mode-hook nil
   "*List of hook functions to be run after a Mail mode
 composition buffer has been created.  This is the last thing VM
 does before leaving the user in the Mail mode buffer."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-mode-hook nil
   "*List of hook functions to run when a buffer enters `vm-mode'.
 These hook functions should generally be used to set key bindings
 and local variables."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-mode-hooks nil
   "*Old name for `vm-mode-hook'.
 Supported for backward compatibility.
 You should use the new name."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-summary-mode-hook nil
   "*List of hook functions to run when a VM summary buffer is created.
 The current buffer will be that buffer when the hooks are run."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-summary-mode-hooks nil
   "*Old name for `vm-summary-mode-hook'.
 Supported for backward compatibility.
 You should use the new name."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-folders-summary-mode-hook nil
   "*List of hook functions to run when a VM folders summary buffer is created.
 The current buffer will be that buffer when the hooks are run."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-virtual-mode-hook nil
   "*List of hook functions to run when a VM virtual folder buffer is created.
 The current buffer will be that buffer when the hooks are run."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-presentation-mode-hook nil
   "*List of hook functions to run when a VM presentation buffer is created.
 The current buffer will be the new presentation buffer when the hooks are run.
 Presentation buffers are used to display messages when some type of decoding
 must be done to the message to make it presentable.  E.g. MIME decoding."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-quit-hook nil
   "*List of hook functions to run when you quit VM.
 This applies to any VM quit command."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-summary-pointer-update-hook nil
   "*List of hook functions to run when the VM summary pointer is updated.
 When the hooks are run, the current buffer will be the summary buffer."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-display-buffer-hook nil
   "*List of hook functions that are run every time VM wants to
 
 If you use display hooks, you should not use VM's builtin window
 configuration system as the result is likely to be confusing."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-undisplay-buffer-hook nil
   "*List of hook functions that are run every time VM wants to
 If you use undisplay hooks, you should not use VM's builtin
 window configuration system as the result is likely to be
 confusing."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-iconify-frame-hook nil
   "*List of hook functions that are run whenever VM iconifies a frame."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-menu-setup-hook nil
   "*List of hook functions that are run just after all menus are initialized."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-mime-display-function nil
   "*If non-nil, this should name a function to be called inside 
 are connected to an authenticated IMAP session, and to return
 this process.  If the hook cannot accomplish this, it should
 return nil.  If all the hooks return nil, VM will signal an error."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom vm-mail-send-hook nil
   "*List of hook functions to call just before sending a message.
 The hooks are run after confirming that you want to send the
 message (see `vm-confirm-mail-send') but before MIME encoding and
 FCC processing."
-  :type '(list function))
+  :type 'hook)
 
 (defvar mail-yank-hooks nil
   "Hooks called after a message is yanked into a mail composition buffer.
 
 If this hook is entirely empty (nil), a default action is taken
 instead of no action."
-  :type '(list function))
+  :type 'hook)
 
 (defcustom mail-default-headers nil
   "*A string containing header lines, to be inserted in outgoing messages.
 
 (defvar vm-mime-reader-map
   (let ((map (make-sparse-keymap)))
+    (define-key map "$a" 'vm-mime-attach-object-from-message)
     (define-key map "$s" 'vm-mime-reader-map-save-message)
     (define-key map "$w" 'vm-mime-reader-map-save-file)
     (define-key map "$|" 'vm-mime-reader-map-pipe-to-command)
 (make-variable-buffer-local 'vm-summary-redo-start-point)
 (defvar vm-need-summary-pointer-update nil)
 (make-variable-buffer-local 'vm-need-summary-pointer-update)
-(defvar vm-thread-obarray nil)
+(defvar vm-thread-obarray 'bonk)
 (make-variable-buffer-local 'vm-thread-obarray)
-(defvar vm-thread-subject-obarray nil)
+(defvar vm-thread-subject-obarray 'bonk)
 (make-variable-buffer-local 'vm-thread-subject-obarray)
 (defvar vm-label-obarray nil)
 (make-variable-buffer-local 'vm-label-obarray)
 
 (provide 'vm-version)
 
-(defconst vm-version "7.03"
+(defconst vm-version "7.04"
   "Version number of VM.")
 
 (defun vm-version ()
   (cond (vm-xemacs-p
 	 (memq 'win (device-matching-specifier-tag-list)))
 	(vm-fsfemacs-p
-	 (memq window-system '(x w32 win32)))))
+	 (memq window-system '(x mac w32 win32)))))
 
 (defun vm-menu-support-possible-p ()
   (cond (vm-xemacs-p
   (cond (vm-xemacs-p
 	 (memq (device-type) '(x mswindows)))
 	(vm-fsfemacs-p
-	 (memq window-system '(x w32 win32)))))
+	 (memq window-system '(x mac w32 win32)))))
 
 (defun vm-images-possible-here-p ()
   (or (and vm-xemacs-p (memq (device-type) '(x mswindows)))
 flushbottom for left and right toolbars.
 @end table
 
-If a positive integer appears in the the @code{vm-use-toolbar} list, it
+If an positive integer appears in the the @code{vm-use-toolbar} list, it
 specifies the number of pixels of blank space to display between
 the button that comes before and the button that comes after the
 integer.