Commits

youngs  committed 22db3da

2002-06-07 Steve Youngs <youngs@xemacs.org>

* Sync with VM-7.07

* Makefile (PRELOADS): Don't preload vm-misc.el.
(MANUAL): Remove.
(EXTRA_OBJS): Include vm.el and vm.elc.
(EXTRA_SOURCES): Ditto.
(vm.elc): Create a byte-compiled file.

  • Participants
  • Parent commits 4007973

Comments (0)

Files changed (16)

+2002-06-07  Steve Youngs  <youngs@xemacs.org>
+
+	* Sync with VM-7.07
+
+	* Makefile (PRELOADS): Don't preload vm-misc.el.
+	(MANUAL): Remove.
+	(EXTRA_OBJS): Include vm.el and vm.elc.
+	(EXTRA_SOURCES): Ditto.
+	(vm.elc): Create a byte-compiled file.
+
 2002-05-09  Steve Youngs  <youngs@xemacs.org>
 
 	* Makefile (VERSION): XEmacs package 7.04 released.
 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-VERSION = 7.04
-AUTHOR_VERSION = 7.04
+VERSION = 7.06
+AUTHOR_VERSION = 7.07
 MAINTAINER = Kyle Jones <kyle_jones@wonderworks.com>
 PACKAGE = vm
 PKG_TYPE = regular
 	vm-user.elc vm-vars.elc vm-virtual.elc vm-window.elc \
 	vm-crypto.elc
 
-EXTRA_SOURCES = vm.elc vm-autoload.el vm-autoload.elc Makefile-kj \
+EXTRA_SOURCES = vm.el vm.elc vm-autoload.el vm-autoload.elc Makefile-kj \
 	README.bytecompile
 
 PRELOADS =-l vm-byteopts.el -l vm-version.el -l vm-message.el \
-	-l vm-macro.el -l vm-misc.el -l vm-vars.el
+	-l vm-macro.el -l vm-vars.el
 
 INFO_FILES = $(PACKAGE).info*
 HTML_FILES = $(PACKAGE)*.html
 HTML_DEP = $(PACKAGE).html
 TEXI_FILES = $(PACKAGE).texinfo
-MANUAL = $(PACKAGE)
 DATA_FILES = $(shell echo etc/*.x??)
 DATA_DEST = $(PACKAGE)
 
-EXTRA_OBJS = vm-autoload.el* vm.elc
+EXTRA_OBJS = vm-autoload.el* vm.el*
 
 include ../../XEmacs.rules
 
 all:: $(ELCS) vm-autoload.elc vm.elc auto-autoloads.elc $(PACKAGE).info
 
-vm.elc: $(ELCS)
+vm.elc:	vm-autoload.elc $(ELCS)
 	@echo "building vm.elc (with all modules set to autoload)..."
-	@echo "(require 'vm-version)" > vm.elc
-	@echo "(require 'vm-startup)" >> vm.elc
-	@echo "(require 'vm-vars)" >> vm.elc
-	@echo "(require 'vm-autoload)" >> vm.elc
+	@echo "(defun vm-its-such-a-cruel-world ()" > vm.el
+	@echo "   (require 'vm-version)" >> vm.el
+	@echo "   (require 'vm-startup)" >> vm.el
+	@echo "   (require 'vm-vars)" >> vm.el
+	@echo "   (require 'vm-autoload))" >> vm.el
+	@echo "(vm-its-such-a-cruel-world)" >> vm.el
+	@echo "(fmakunbound 'vm-its-such-a-cruel-world)" >> vm.el
+	@$(BOOT_XEMACS) -f batch-byte-compile vm.el
 
 vm-autoload.el: $(ELCS:.elc=.el)
 	@echo scanning sources to build autoload definitions...
 # installed when we do this.  After all, we're compiling and installing
 # the packages right now and need to be able to bootstrap.
 vm.info: vm.texinfo
-	$(XEMACS) -vanilla -batch -insert vm.texinfo $(FORMAT_INFO_USING_XEMACS_ARGS)
+	$(XEMACS) -vanilla -batch -insert vm.texinfo \
+		$(FORMAT_INFO_USING_XEMACS_ARGS)
 
 srckit: srckit-std
 
 # code needs the Emacs/XEmacs MULE/no-MULE feature stuff.
 OBJECTS = \
     vm-version.elc \
+    vm-crypto.elc \
     vm-delete.elc vm-digest.elc vm-easymenu.elc vm-edit.elc vm-folder.elc \
     vm-imap.elc vm-license.elc vm-macro.elc vm-mark.elc vm-menu.elc \
     vm-message.elc \
-    vm-mime.elc vm-minibuf.elc vm-misc.elc vm-mouse.elc \
-    vm-motion.elc vm-page.elc vm-pop.elc vm-reply.elc \
+    vm-mime.elc vm-minibuf.elc vm-misc.elc vm-motion.elc \
+    vm-mouse.elc vm-page.elc vm-pop.elc vm-reply.elc \
     vm-save.elc \
     vm-search.elc vm-sort.elc vm-summary.elc vm-startup.elc vm-thread.elc \
     vm-toolbar.elc vm-undo.elc \
 
 SOURCES = \
     vm-version.el \
+    vm-crypto.el \
     vm-delete.el vm-digest.el vm-easymenu.el vm-edit.el vm-folder.el \
     vm-imap.el vm-license.el vm-macro.el vm-mark.el vm-menu.el vm-message.el \
-    vm-mime.el vm-minibuf.el vm-misc.el vm-mouse.el \
-    vm-motion.el vm-page.el vm-pop.el vm-reply.el vm-save.el \
+    vm-mime.el vm-minibuf.el vm-misc.el vm-motion.el \
+    vm-mouse.el vm-page.el vm-pop.el vm-reply.el vm-save.el \
     vm-search.el vm-sort.el vm-startup.el vm-summary.el vm-thread.el \
     vm-toolbar.el vm-undo.el \
     vm-user.el vm-vars.el vm-virtual.el vm-window.el
 	@echo "   (require 'vm-vars)" >> vm.el
 	@echo "   (require 'vm-autoload))" >> vm.el
 	@echo "(vm-its-such-a-cruel-world)" >> vm.el
+	@echo "(fmakunbound 'vm-its-such-a-cruel-world)" >> vm.el
 	@$(EMACS) $(BATCHFLAGS) $(PRELOADS) -f batch-byte-compile vm.el
 
 all:	vm.info vm utils
 	test -d $(LISPDIR) || mkdir -p $(LISPDIR)
 	cp *.elc $(LISPDIR)
 
+install-el:
+	test -d $(LISPDIR) || mkdir -p $(LISPDIR)
+	cp *.el $(LISPDIR)
+
 install-pixmaps:
 	test -d $(PIXMAPDIR) || mkdir -p $(PIXMAPDIR)
 	cp pixmaps/*.x[pb]m $(PIXMAPDIR)
 	@echo "making vm.info..."
 	@$(EMACS) $(BATCHFLAGS) -insert vm.texinfo -l texinfmt -f texinfo-format-buffer -f save-buffer
 
+# We use tr -d because Emacs under Cygwin apparently outputs CRLF
+# under Windows.  We remove the CRs.
 vm-autoload.elc:	$(SOURCES)
 	@echo scanning sources to build autoload definitions...
 	@echo "(provide 'vm-autoload)" > vm-autoload.el
-	@$(EMACS) $(BATCHFLAGS) -l ./make-autoloads -f print-autoloads $(SOURCES) >> vm-autoload.el
+	@$(EMACS) $(BATCHFLAGS) -l ./make-autoloads -f print-autoloads $(SOURCES) | tr -d '\r' >> vm-autoload.el
 	@echo compiling vm-autoload.el...
 	@$(EMACS) $(BATCHFLAGS) -l $(BYTEOPTS) -f batch-byte-compile vm-autoload.el
 
+vm-crypto.elc:	vm-crypto.el $(CORE)
+	@echo compiling vm-crypto.el...
+	@$(EMACS) $(BATCHFLAGS) $(PRELOADS) -f batch-byte-compile vm-crypto.el
+
 vm-delete.elc:	vm-delete.el $(CORE)
 	@echo compiling vm-delete.el...
 	@$(EMACS) $(BATCHFLAGS) $(PRELOADS) -f batch-byte-compile vm-delete.el

File vm-folder.el

       nil
     (if (and (consp start-point) (consp vm-numbering-redo-start-point))
 	(let ((mp vm-message-list))
-	  (while (and mp (not (or (eq mp start-point)
-				  (eq mp vm-numbering-redo-start-point))))
+	  (while (and mp
+		      (not
+		       (or (eq (car mp) (car start-point))
+			   (eq (car mp) (car vm-numbering-redo-start-point)))))
 	    (setq mp (cdr mp)))
 	  (if (null mp)
 	      (error "Something is wrong in vm-set-numbering-redo-start-point"))
-	  (if (eq mp start-point)
+	  (if (eq (car mp) (car start-point))
 	      (setq vm-numbering-redo-start-point start-point)))
       (setq vm-numbering-redo-start-point start-point))))
 
 	     (vm-set-modflag-of m nil))
 	 (set-buffer-modified-p old-buffer-modified-p))))))
 
-(defun vm-stuff-folder-attributes (&optional abort-if-input-pending)
-  (let ((newlist nil) mp)
+(defun vm-stuff-folder-attributes (&optional abort-if-input-pending quiet)
+  (let ((newlist nil) mp len (n 0))
     ;; stuff the attributes of messages that need it.
     ;; build a list of messages that need their attributes stuffed
     (setq mp vm-message-list)
       (if (vm-modflag-of (car mp))
 	  (setq newlist (cons (car mp) newlist)))
       (setq mp (cdr mp)))
+    (if (and newlist (not quiet))
+	(progn
+	  (setq len (length newlist))
+	  (message "%d message%s to stuff" len (if (= 1 len) "" "s"))))
     ;; now sort the list by physical order so that we
     ;; reduce the amount of gap motion induced by modifying
     ;; the buffer.  what we want to avoid is updating
     ;; message 3, then 234, then 10, then 500, thus causing
     ;; large chunks of memory to be copied repeatedly as
     ;; the gap moves to accomodate the insertions.
+    (if (not quiet)
+	(message "Ordering updates..."))
     (let ((vm-key-functions '(vm-sort-compare-physical-order-r)))
       (setq mp (sort newlist 'vm-sort-compare-xxxxxx)))
     (while (and mp (or (not abort-if-input-pending) (not (input-pending-p))))
       (vm-stuff-attributes (car mp))
+      (setq n (1+ n))
+      (if (not quiet)
+	  (message "Stuffing %d%% complete..." (* (/ (+ n 0.0) len) 100)))
       (setq mp (cdr mp)))
     (if mp nil t)))
 
 		 (message "Write of %s signaled: %s" index-file data)
 		 (sleep-for 2)
 		 (throw 'done nil))))
-	    (vm-error-free-call 'set-file-modes index-file 384) ;; 384 == 0600
+	    (vm-error-free-call 'set-file-modes index-file (vm-octal 600))
 	    (message "Writing index file... done")
 	    t ))
       (and work-buffer (kill-buffer work-buffer)))))
 		       (vm-stuff-labels)
 		       (and vm-message-order-changed
 			    (vm-stuff-message-order))
-		       (and (vm-stuff-folder-attributes t)
+		       (and (vm-stuff-folder-attributes t t)
 			    (setq vm-flushed-modification-counter
 				  vm-modification-counter)))))))
 	(setq buf-list (cdr buf-list)))
     ;; as a safeguard against the time when other stuff is added here.
     (vm-save-restriction
      (let ((buffer-read-only))
+       (message "Stuffing attributes...")
        (vm-stuff-folder-attributes nil)
+       (message "Stuffing attributes... done")
        (if vm-message-list
 	   (progn
 	     (if (and vm-folders-summary-database buffer-file-name)
   (interactive)
   (vm-select-folder-buffer)
   (vm-error-if-virtual-folder)
-  (let ((old-buffer-name (buffer-name)))
-    (save-excursion
-      (call-interactively 'write-file))
+  (let ((old-buffer-name (buffer-name))
+	(oldmodebits (and (fboundp 'default-file-modes)
+			  (default-file-modes))))
+    (unwind-protect
+	(save-excursion
+	  (and oldmodebits (set-default-file-modes
+			    vm-default-folder-permission-bits))
+	  (call-interactively 'write-file))
+      (and oldmodebits (set-default-file-modes oldmodebits)))
     (if (and vm-folders-summary-database buffer-file-name)
 	(progn
 	  (vm-compute-totals)
 	  ;; stuff the attributes of messages that need it.
 	  (message "Stuffing attributes...")
 	  (vm-stuff-folder-attributes nil)
+	  (message "Stuffing attributes... done")
 	  ;; stuff bookmark and header variable values
 	  (if vm-message-list
 	      (progn
 		(and vm-message-order-changed
 		     (vm-stuff-message-order))))
 	  (message "Saving...")
-	  (let ((vm-inhibit-write-file-hook t))
-	    (save-buffer prefix))
+	  (let ((vm-inhibit-write-file-hook t)
+		(oldmodebits (and (fboundp 'default-file-modes)
+				  (default-file-modes))))
+	    (unwind-protect
+		(progn
+		  (and oldmodebits (set-default-file-modes
+				    vm-default-folder-permission-bits))
+		  (save-buffer prefix))
+	      (and oldmodebits (set-default-file-modes oldmodebits))))
 	  (vm-set-buffer-modified-p nil)
 	  ;; clear the modified flag in virtual folders if all the
 	  ;; real buffers associated with them are unmodified.
 	     ;; done here too.
 	     (if gobble-order
 		 (vm-gobble-message-order))
-	     (if (vectorp vm-thread-obarray)
+	     (if (or (vectorp vm-thread-obarray)
+		     vm-summary-show-threads)
 		 (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)
 	    (setq mp (cdr mp)))))
     (if (and new-messages vm-summary-show-threads)
 	(progn
-	  ;; get numbering and summary of new messages done now
+	  ;; 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)
    mode-line-format vm-mode-line-format
    mode-name "VM"
    ;; must come after the setting of major-mode
-   mode-popup-menu (and vm-use-menus vm-popup-menu-on-mouse-3
+   mode-popup-menu (and vm-use-menus
 			(vm-menu-support-possible-p)
 			(vm-menu-mode-menu))
    buffer-read-only t
 		   major-mode 'vm-presentation-mode
 		   vm-message-pointer (list nil)
 		   vm-mail-buffer mail-buffer
-		   mode-popup-menu (and vm-use-menus vm-popup-menu-on-mouse-3
+		   mode-popup-menu (and vm-use-menus
 					(vm-menu-support-possible-p)
 					(vm-menu-mode-menu))
 		   ;; Default to binary file type for DOS/NT.
 	    (setq i-list (cdr i-list))))
 	matched ))))
 
-(defun vm-mime-should-display-internal (layout dont-honor-content-disposition)
-  (if (and vm-honor-mime-content-disposition
-	   (not dont-honor-content-disposition)
-	   (vm-mm-layout-disposition layout))
-      (let ((case-fold-search t))
-	(string-match "^inline$" (car (vm-mm-layout-disposition layout))))
-    (let ((i-list vm-mime-internal-content-types)
-	  (type (car (vm-mm-layout-type layout)))
-	  (matched nil))
-      (if (if (eq i-list t)
-	      t
-	    (while (and i-list (not matched))
-	      (if (vm-mime-types-match (car i-list) type)
-		  (setq matched t)
-		(setq i-list (cdr i-list))))
-	    matched )
-	  (progn
-	    (setq i-list vm-mime-internal-content-type-exceptions
-		  matched nil)
-	    (while (and i-list (not matched))
-	      (if (vm-mime-types-match (car i-list) type)
-		  (setq matched t)
-		(setq i-list (cdr i-list))))
-	    (not matched))
-	nil ))))
+(defun vm-mime-should-display-internal (layout)
+  (let ((i-list vm-mime-internal-content-types)
+	(type (car (vm-mm-layout-type layout)))
+	(matched nil))
+    (if (if (eq i-list t)
+	    t
+	  (while (and i-list (not matched))
+	    (if (vm-mime-types-match (car i-list) type)
+		(setq matched t)
+	      (setq i-list (cdr i-list))))
+	  matched )
+	(progn
+	  (setq i-list vm-mime-internal-content-type-exceptions
+		matched nil)
+	  (while (and i-list (not matched))
+	    (if (vm-mime-types-match (car i-list) type)
+		(setq matched t)
+	      (setq i-list (cdr i-list))))
+	  (not matched))
+      nil )))
 
 (defun vm-mime-find-external-viewer (type)
   (catch 'done
 						type-no-subtype))
 				       layout)
 			    (void-function nil)))))
-		((and (vm-mime-should-display-internal layout dont-honor-c-d)
+		((and (vm-mime-should-display-internal layout)
 		      (or (condition-case nil
 			      (funcall (intern
 					(concat "vm-mime-display-internal-"
 	     (while (and part-list (not done))
 	       (setq type (car (vm-mm-layout-type (car part-list))))
 	       (cond ((and (vm-mime-can-display-internal (car part-list) t)
-			   (vm-mime-should-display-internal (car part-list)
-							    nil))
+			   (vm-mime-should-display-internal (car part-list)))
 		      (setq best (car part-list)
 			    done t))
 		     ((and (null second-best)
 	       (while (and part-list (not done))
 		 (setq type (car (vm-mm-layout-type (car part-list))))
 		 (cond ((and (vm-mime-can-display-internal (car part-list) t)
-			     (vm-mime-should-display-internal (car part-list)
-							      nil))
+			     (vm-mime-should-display-internal (car part-list)))
 			(if (vm-mime-types-match (car favs) type)
 			    (setq best (car part-list)
 				  done t)
 	(vm-set-edited-flag-of m t)
 	(vm-set-byte-count-of m nil)
 	(vm-set-line-count-of m nil)
+	(vm-set-modflag-of m t)
 	;; For the dreaded From_-with-Content-Length folders recompute
 	;; the message length and make a new Content-Length header.
 	(if (eq (vm-message-type-of m) 'From_-with-Content-Length)
 	(goto-char (point-max))
 	(let ((buffer-read-only nil))
 	  (insert string)))
-    (let ((temp-buffer nil)
-	  (coding-system-for-write (vm-line-ending-coding-system)))
+    (let ((temp-buffer nil))
       (unwind-protect
 	  (save-excursion
 	    (setq temp-buffer (generate-new-buffer "*vm-work*"))
 	    ;; correct for VM's uses of this function---
 	    ;; writing out message separators
 	    (setq buffer-file-type nil)
-	    ;; Tell MULE to pick the correct newline conversion.
-	    (if (fboundp 'set-buffer-file-coding-system)
-		(set-buffer-file-coding-system 
-		 (vm-line-ending-coding-system) nil))
 	    (write-region (point-min) (point-max) where t 'quiet))
 	(and temp-buffer (kill-buffer temp-buffer))))))
 
       (t
        (fset 'vm-coding-system-name 'symbol-name)))
 
+(defun vm-get-file-line-ending-coding-system (file)
+  (if (not (or vm-fsfemacs-mule-p vm-xemacs-mule-p vm-xemacs-file-coding-p))
+      nil
+    (let ((coding-system-for-read  (vm-binary-coding-system))
+	  (work-buffer nil))
+      (unwind-protect
+	  (save-excursion
+	    (setq work-buffer (vm-make-work-buffer))
+	    (set-buffer work-buffer)
+	    (condition-case nil
+		(insert-file-contents file nil 0 4096)
+	      (error nil))
+	    (goto-char (point-min))
+	    (cond ((re-search-forward "[^\r]\n" nil t)
+		   (if vm-fsfemacs-mule-p 'raw-text-unix 'no-conversion-unix))
+		  ((re-search-forward "\r[^\n]" nil t)
+		   (if vm-fsfemacs-mule-p 'raw-text-mac 'no-conversion-mac))
+		  ((search-forward "\r\n" nil t)
+		   (if vm-fsfemacs-mule-p 'raw-text-dos 'no-conversion-dos))
+		  (t (vm-line-ending-coding-system))))
+	(and work-buffer (kill-buffer work-buffer))))))
+
 (defun vm-collapse-whitespace ()
   (goto-char (point-min))
   (while (re-search-forward "[ \t\n]+" nil 0)
   (vm-with-string-as-temp-buffer string 'vm-url-decode-buffer))
 
 (defun vm-url-decode-buffer ()
-  (let ((case-fold-search nil)
+  (let ((case-fold-search t)
 	(hex-digit-alist '((?0 .  0)  (?1 .  1)  (?2 .  2)  (?3 .  3)
 			   (?4 .  4)  (?5 .  5)  (?6 .  6)  (?7 .  7)
 			   (?8 .  8)  (?9 .  9)  (?A . 10)  (?B . 11)
     (if (memq major-mode '(vm-mode vm-virtual-mode))
 	(setq folder-buffer (current-buffer)))
     (set-buffer (generate-new-buffer (or buffer-name "mail to ?")))
+    ;; FSF Emacs: try to prevent write-region (called to handle FCC) from
+    ;; asking the user to choose a safe coding system.
+    (if (and vm-fsfemacs-mule-p (fboundp 'set-buffer-file-coding-system))
+	(set-buffer-file-coding-system 'raw-text))
     ;; avoid trying to write auto-save files in potentially
     ;; unwritable directories.
     (setq default-directory (or vm-folder-directory (expand-file-name "~/")))
 	       (nconc vm-mail-mode-map mail-mode-map)
 	       (setq vm-mail-mode-map-parented t))))
     (setq vm-mail-buffer folder-buffer
-	  mode-popup-menu (and vm-use-menus vm-popup-menu-on-mouse-3
+	  mode-popup-menu (and vm-use-menus
 			       (vm-menu-support-possible-p)
 			       (vm-menu-mode-menu)))
     (and vm-use-menus (vm-menu-support-possible-p)
 	  (goto-char (point-min))
 	  (insert (vm-leading-message-separator 'mmdf))
 	  (goto-char (point-max))
+	  (if (not (eq (preceding-char) ?\n))
+	      (insert ?\n))
 	  (insert (vm-trailing-message-separator 'mmdf))
 	  (set-buffer-modified-p nil)
 	  ;; point of no return, don't kill it if the user quits
     (if (and (not vm-visit-when-saving) (vm-get-file-buffer folder))
 	(error "Folder %s is being visited, cannot save." folder))
     (let ((mlist (vm-select-marked-or-prefixed-messages count))
+	  (coding-system-for-write
+	   (vm-get-file-line-ending-coding-system folder))
+	  (oldmodebits (and (fboundp 'default-file-modes)
+			    (default-file-modes)))
 	  (m nil) (count 0) folder-buffer target-type)
       (cond ((and mlist (eq vm-visit-when-saving t))
 	     (setq folder-buffer (or (vm-get-file-buffer folder)
 				       (vm-message-type-of (car mlist)))))
 	    (if (eq target-type 'unknown)
 		(error "Folder %s's type is unrecognized" folder))))
-      ;; if target folder is empty or nonexistent we need to
-      ;; write out the folder header first.
-      (if mlist
-	  (let ((attrs (file-attributes folder)))
-	    (if (or (null attrs) (= 0 (nth 7 attrs)))
-		(if (null folder-buffer)
-		    (vm-write-string folder (vm-folder-header target-type))
-		  (vm-write-string folder-buffer
-				   (vm-folder-header target-type))))))
-      (save-excursion
-	(while mlist
-	  (setq m (vm-real-message-of (car mlist)))
-	  (set-buffer (vm-buffer-of m))
-	  (vm-save-restriction
-	   (widen)
-	   ;; have to stuff the attributes in all cases because
-	   ;; the deleted attribute may have been stuffed
-	   ;; previously and we don't want to save that attribute.
-	   ;; also we don't want to save out the cached summary entry.
-	   (vm-stuff-attributes m t)
-	   (if (null folder-buffer)
-	       (if (or (null vm-check-folder-types)
-		       (eq target-type (vm-message-type-of m)))
-		   (write-region (vm-start-of m)
-				 (vm-end-of m)
-				 folder t 'quiet)
-		 (if (null vm-convert-folder-types)
-		     (if (not (vm-virtual-message-p (car mlist)))
-			 (error "Folder type mismatch: %s, %s"
-				(vm-message-type-of m) target-type)
-		       (error "Message %s type mismatches folder %s"
-			      (vm-number-of (car mlist))
-			      folder
-			      (vm-message-type-of m)
-			      target-type))
-		   (vm-write-string
-		    folder
-		    (vm-leading-message-separator target-type m t))
-		   (if (eq target-type 'From_-with-Content-Length)
+      (unwind-protect
+	  (save-excursion
+	    (and oldmodebits (set-default-file-modes
+			      vm-default-folder-permission-bits))
+	    ;; if target folder is empty or nonexistent we need to
+	    ;; write out the folder header first.
+	    (if mlist
+		(let ((attrs (file-attributes folder)))
+		  (if (or (null attrs) (= 0 (nth 7 attrs)))
+		      (if (null folder-buffer)
+			  (vm-write-string folder
+					   (vm-folder-header target-type))
+			(vm-write-string folder-buffer
+					 (vm-folder-header target-type))))))
+	    (while mlist
+	      (setq m (vm-real-message-of (car mlist)))
+	      (set-buffer (vm-buffer-of m))
+	      (vm-save-restriction
+	       (widen)
+	       ;; have to stuff the attributes in all cases because
+	       ;; the deleted attribute may have been stuffed
+	       ;; previously and we don't want to save that attribute.
+	       ;; also we don't want to save out the cached summary entry.
+	       (vm-stuff-attributes m t)
+	       (if (null folder-buffer)
+		   (if (or (null vm-check-folder-types)
+			   (eq target-type (vm-message-type-of m)))
+		       (write-region (vm-start-of m)
+				     (vm-end-of m)
+				     folder t 'quiet)
+		     (if (null vm-convert-folder-types)
+			 (if (not (vm-virtual-message-p (car mlist)))
+			     (error "Folder type mismatch: %s, %s"
+				    (vm-message-type-of m) target-type)
+			   (error "Message %s type mismatches folder %s"
+				  (vm-number-of (car mlist))
+				  folder
+				  (vm-message-type-of m)
+				  target-type))
 		       (vm-write-string
 			folder
-			(concat vm-content-length-header " "
-				(vm-su-byte-count m) "\n")))
-		   (write-region (vm-headers-of m)
-				 (vm-text-end-of m)
-				 folder t 'quiet)
-		   (vm-write-string
-		    folder
-		    (vm-trailing-message-separator target-type))))
-	     (save-excursion
-	       (set-buffer folder-buffer)
-	       ;; if the buffer is a live VM folder
-	       ;; honor vm-folder-read-only.
-	       (if vm-folder-read-only
-		   (signal 'folder-read-only (list (current-buffer))))
-	       (let ((buffer-read-only nil))
-		 (vm-save-restriction
-		  (widen)
-		  (save-excursion
-		    (goto-char (point-max))
-		    (if (or (null vm-check-folder-types)
-			    (eq target-type (vm-message-type-of m)))
-			(insert-buffer-substring
-			 (vm-buffer-of m)
-			 (vm-start-of m) (vm-end-of m))
-		      (if (null vm-convert-folder-types)
-			  (if (not (vm-virtual-message-p (car mlist)))
-			      (error "Folder type mismatch: %s, %s"
-				     (vm-message-type-of m) target-type)
-			    (error "Message %s type mismatches folder %s"
-				   (vm-number-of (car mlist))
-				   folder
-				   (vm-message-type-of m)
-				   target-type))
-			(vm-write-string
-			 (current-buffer)
-			 (vm-leading-message-separator target-type m t))
-			(if (eq target-type 'From_-with-Content-Length)
+			(vm-leading-message-separator target-type m t))
+		       (if (eq target-type 'From_-with-Content-Length)
+			   (vm-write-string
+			    folder
+			    (concat vm-content-length-header " "
+				    (vm-su-byte-count m) "\n")))
+		       (write-region (vm-headers-of m)
+				     (vm-text-end-of m)
+				     folder t 'quiet)
+		       (vm-write-string
+			folder
+			(vm-trailing-message-separator target-type))))
+		 (save-excursion
+		   (set-buffer folder-buffer)
+		   ;; if the buffer is a live VM folder
+		   ;; honor vm-folder-read-only.
+		   (if vm-folder-read-only
+		       (signal 'folder-read-only (list (current-buffer))))
+		   (let ((buffer-read-only nil))
+		     (vm-save-restriction
+		      (widen)
+		      (save-excursion
+			(goto-char (point-max))
+			(if (or (null vm-check-folder-types)
+				(eq target-type (vm-message-type-of m)))
+			    (insert-buffer-substring
+			     (vm-buffer-of m)
+			     (vm-start-of m) (vm-end-of m))
+			  (if (null vm-convert-folder-types)
+			      (if (not (vm-virtual-message-p (car mlist)))
+				  (error "Folder type mismatch: %s, %s"
+					 (vm-message-type-of m) target-type)
+				(error "Message %s type mismatches folder %s"
+				       (vm-number-of (car mlist))
+				       folder
+				       (vm-message-type-of m)
+				       target-type))
 			    (vm-write-string
 			     (current-buffer)
-			     (concat vm-content-length-header " "
-				     (vm-su-byte-count m) "\n")))
-			(insert-buffer-substring (vm-buffer-of m)
-						 (vm-headers-of m)
-						 (vm-text-end-of m))
-			(vm-write-string
-			 (current-buffer)
-			 (vm-trailing-message-separator target-type)))))
-		  ;; vars should exist and be local
-		  ;; but they may have strange values,
-		  ;; so check the major-mode.
-		  (cond ((eq major-mode 'vm-mode)
-			 (vm-increment vm-messages-not-on-disk)
-			 (vm-clear-modification-flag-undos)))))))
-	   (if (null (vm-filed-flag m))
-	       (vm-set-filed-flag m t))
-	   (vm-increment count)
-	   (vm-modify-folder-totals folder 'saved 1 m)
-	   (vm-update-summary-and-mode-line)
-	   (setq mlist (cdr mlist)))))
+			     (vm-leading-message-separator target-type m t))
+			    (if (eq target-type 'From_-with-Content-Length)
+				(vm-write-string
+				 (current-buffer)
+				 (concat vm-content-length-header " "
+					 (vm-su-byte-count m) "\n")))
+			    (insert-buffer-substring (vm-buffer-of m)
+						     (vm-headers-of m)
+						     (vm-text-end-of m))
+			    (vm-write-string
+			     (current-buffer)
+			     (vm-trailing-message-separator target-type)))))
+		      ;; vars should exist and be local
+		      ;; but they may have strange values,
+		      ;; so check the major-mode.
+		      (cond ((eq major-mode 'vm-mode)
+			     (vm-increment vm-messages-not-on-disk)
+			     (vm-clear-modification-flag-undos)))))))
+	       (if (null (vm-filed-flag m))
+		   (vm-set-filed-flag m t))
+	       (vm-increment count)
+	       (vm-modify-folder-totals folder 'saved 1 m)
+	       (vm-update-summary-and-mode-line)
+	       (setq mlist (cdr mlist)))))
+	(and oldmodebits (set-default-file-modes oldmodebits)))
       (if m
 	  (if folder-buffer
 	      (progn
   (if (and (not vm-visit-when-saving) (vm-get-file-buffer file))
       (error "File %s is being visited, cannot save." file))
   (let ((mlist (vm-select-marked-or-prefixed-messages count))
+	(oldmodebits (and (fboundp 'default-file-modes)
+			  (default-file-modes)))
+	(coding-system-for-write
+	 (vm-get-file-line-ending-coding-system file))
 	(m nil) file-buffer)
     (cond ((and mlist (eq vm-visit-when-saving t))
 	   (setq file-buffer (or (vm-get-file-buffer file)
     (if (and (not (memq (vm-get-folder-type file) '(nil unknown)))
 	     (not (y-or-n-p "This file looks like a mail folder, append to it anyway? ")))
 	(error "Aborted"))
-    (save-excursion
-      (while mlist
-	(setq m (vm-real-message-of (car mlist)))
-	(set-buffer (vm-buffer-of m))
-	(vm-save-restriction
-	 (widen)
-	 (if (null file-buffer)
-	     (write-region (vm-text-of m)
-			   (vm-text-end-of m)
-			   file t 'quiet)
-	   (let ((start (vm-text-of m))
-		 (end (vm-text-end-of m)))
-	     (save-excursion
-	       (set-buffer file-buffer)
-	       (save-excursion
-		 (let (buffer-read-only)
-		   (vm-save-restriction
-		    (widen)
-		    (save-excursion
-		      (goto-char (point-max))
-		      (insert-buffer-substring
-		       (vm-buffer-of m)
-		       start end))))))))
-	(if (null (vm-written-flag m))
-	    (vm-set-written-flag m t))
-	(vm-update-summary-and-mode-line)
-	(setq mlist (cdr mlist)))))
+    (unwind-protect
+	(save-excursion
+	  (and oldmodebits (set-default-file-modes
+			    vm-default-folder-permission-bits))
+	  (while mlist
+	    (setq m (vm-real-message-of (car mlist)))
+	    (set-buffer (vm-buffer-of m))
+	    (vm-save-restriction
+	     (widen)
+	     (if (null file-buffer)
+		 (write-region (vm-text-of m)
+			       (vm-text-end-of m)
+			       file t 'quiet)
+	       (let ((start (vm-text-of m))
+		     (end (vm-text-end-of m)))
+		 (save-excursion
+		   (set-buffer file-buffer)
+		   (save-excursion
+		     (let (buffer-read-only)
+		       (vm-save-restriction
+			(widen)
+			(save-excursion
+			  (goto-char (point-max))
+			  (insert-buffer-substring
+			   (vm-buffer-of m)
+			   start end))))))))
+	     (if (null (vm-written-flag m))
+		 (vm-set-written-flag m t))
+	     (vm-update-summary-and-mode-line)
+	     (setq mlist (cdr mlist)))))
+      (and oldmodebits (set-default-file-modes oldmodebits)))
     (if m
 	(if file-buffer
 	    (message "Message%s written to buffer %s" (if (/= 1 count) "s" "")
   ;; ditto
   (if (and (interactive-p) (or vm-move-messages-physically lets-get-physical))
       (vm-error-if-folder-read-only))
+
   (vm-display nil nil '(vm-sort-messages) '(vm-sort-messages))
   (let (key-list key-funcs key ml-keys
 	physical-order-list old-message-list new-message-list mp-old mp-new
 
 (defun vm-sort-compare-thread (m1 m2)
   (let ((list1 (vm-th-thread-list m1))
-	(list2 (vm-th-thread-list m2)))
+	(list2 (vm-th-thread-list m2))
+	p1 p2 d1 d2)
     (catch 'done
       (if (not (eq (car list1) (car list2)))
-	  (let ((date1 (get (car list1) 'oldest-date))
-		(date2 (get (car list2) 'oldest-date)))
+	  (let ((date1 (get (car list1) 'youngest-date))
+		(date2 (get (car list2) 'youngest-date)))
 	    (cond ((string-lessp date1 date2) t)
 		  ((string-equal date1 date2)
 		   (string-lessp (car list1) (car list2)))
 		  (t nil)))
+	(setq list1 (cdr list1) list2 (cdr list2))
 	(while (and list1 list2)
-	  (cond ((string-lessp (car list1) (car list2)) (throw 'done t))
-		((not (string-equal (car list1) (car list2)))
-		 (throw 'done nil)))
+	  (setq p1 (car list1) p2 (car list2))
+	  (cond ((not (string-equal p1 p2))
+		 (setq d1 (or (get p1 'date) "0") d2 (or (get p2 'date) "0"))
+		 (cond ((string-lessp d1 d2)
+			(throw 'done t))
+		       ((string-lessp d2 d1)
+			(throw 'done nil))
+		       ((string-lessp p1 p2)
+			(throw 'done t))
+		       (t
+			(throw 'done t)))))
 	  (setq list1 (cdr list1)
 		list2 (cdr list2)))
 	(cond ((and list1 (not list2)) nil)

File vm-startup.el

 (defun vm-mode (&optional read-only)
   "Major mode for reading mail.
 
-This is VM 7.04.
+This is VM 7.07.
 
 Commands:
    h - summarize folder contents
    vm-crash-box
    vm-crash-box-suffix
    vm-default-From_-folder-type
+   vm-default-folder-permission-bits
    vm-default-folder-type
    vm-delete-after-archiving
    vm-delete-after-bursting
    vm-mime-display-function
    vm-mime-external-content-types-alist
    vm-mime-ignore-mime-version
+   vm-mime-ignore-composite-type-opaque-transfer-encoding
    vm-mime-internal-content-type-exceptions
    vm-mime-internal-content-types
    vm-mime-max-message-size
 	  (setq major-mode 'vm-virtual-mode)
 	  (run-hooks 'vm-virtual-mode-hook)
 	  ;; must come after the setting of major-mode
-	  (setq mode-popup-menu (and vm-use-menus vm-popup-menu-on-mouse-3
+	  (setq mode-popup-menu (and vm-use-menus
 				     (vm-menu-support-possible-p)
 				     (vm-menu-mode-menu)))
 	  (setq blurb (vm-emit-totals-blurb))
       'vm-crash-box
       'vm-crash-box-suffix
       'vm-default-From_-folder-type
+      'vm-default-folder-permission-bits
       'vm-default-folder-type
       'vm-delete-after-archiving
       'vm-delete-after-bursting
       'vm-mime-display-function
       'vm-mime-external-content-types-alist
       'vm-mime-ignore-mime-version
+      'vm-mime-ignore-composite-type-opaque-transfer-encoding
       'vm-mime-internal-content-type-exceptions
       'vm-mime-internal-content-types
       'vm-mime-max-message-size

File vm-summary.el

 	major-mode 'vm-summary-mode
 	mode-line-format vm-mode-line-format
 	;; must come after the setting of major-mode
-	mode-popup-menu (and vm-use-menus vm-popup-menu-on-mouse-3
+	mode-popup-menu (and vm-use-menus
 			     (vm-menu-support-possible-p)
 			     (vm-menu-mode-menu))
 	buffer-read-only t
       (vm-mark-for-summary-update (car mp))
       (vm-set-modflag-of (car mp) t)
       (setq mp (cdr mp)))
+    (message "Stuffing attributes...")
     (vm-stuff-folder-attributes nil)
+    (message "Stuffing attributes... done")
     (set-buffer-modified-p t)
     (vm-update-summary-and-mode-line))
   (message "Fixing your summary... done"))
 	major-mode 'vm-folders-summary-mode
 	mode-line-format '("     %b")
 	;; must come after the setting of major-mode
-	mode-popup-menu (and vm-use-menus vm-popup-menu-on-mouse-3
+	mode-popup-menu (and vm-use-menus
 			     (vm-menu-support-possible-p)
 			     (vm-menu-mode-menu))
 	buffer-read-only t

File vm-thread.el

   (interactive)
   (vm-select-folder-buffer)
   (vm-check-for-killed-summary)
+  ;; 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-set-summary-redo-start-point t)
   (setq vm-summary-show-threads (not vm-summary-show-threads))
   (if vm-summary-show-threads
 	    id-sym (intern id vm-thread-obarray)
 	    date (vm-so-sortable-datestring m))
       (put id-sym 'messages (cons m (get id-sym 'messages)))
+      (put id-sym 'date date)
       (if (and (null (cdr (get id-sym 'messages)))
 	       schedule-reindents)
 	  (vm-thread-mark-for-summary-update (get id-sym 'children)))
 	      ;; information vector.
 	      (if (not (boundp subject-sym))
 		  (set subject-sym
-		       (vector id-sym (vm-so-sortable-datestring m)
+		       (vector id-sym date
 			       nil (list m)))
 		;; this subject seen before 
 		(aset (symbol-value subject-sym) 3
   (let ((done nil)
 	(m message)
 	(loop-recovery-point nil)
-	thread-list id-sym subject-sym loop-sym root-date)
+	(date (vm-so-sortable-datestring message))
+	thread-list id-sym subject-sym loop-sym root-date youngest-date)
     (save-excursion
       (set-buffer (vm-buffer-of m))
       (fillarray vm-thread-loop-obarray 0)
 	;; save the date of the oldest message in this thread
 	(setq root-date (get id-sym 'oldest-date))
 	(if (or (null root-date)
-		(string< (vm-so-sortable-datestring message) root-date))
-	    (put id-sym 'oldest-date (vm-so-sortable-datestring message)))
+		(string< date root-date))
+	    (put id-sym 'oldest-date date))
+	;; save the date of the youngest message in this thread
+	(setq youngest-date (get id-sym 'youngest-date))
+	(if (or (null root-date)
+		(string< youngest-date date))
+	    (put id-sym 'youngest-date date))
 	(if (and (boundp id-sym) (symbol-value id-sym))
 	    (progn
 	      (setq id-sym (symbol-value id-sym)
 	  m id-sym subject-sym vect p-sym)
       (while mp
 	(setq m (car mp))
-	(let ((inhibit-quit t))
-	  (vm-set-thread-list-of m nil)
-	  (vm-set-thread-indentation-of m nil)
-	  (set-buffer (vm-buffer-of m))
-	  (setq id-sym (intern (vm-su-message-id m) vm-thread-obarray)
-		subject-sym (intern (vm-so-sortable-subject m)
-				    vm-thread-subject-obarray))
-	  (if (boundp id-sym)
-	      (progn
-		(put id-sym 'messages (delq m (get id-sym 'messages)))
-		(vm-thread-mark-for-summary-update (get id-sym 'children))
-		(setq p-sym (symbol-value id-sym))
-		(and p-sym (put p-sym 'children
-				(delq m (get p-sym 'children))))
-		(if message-changing
-		    (set id-sym nil))))
-	  (if (and (boundp subject-sym) (setq vect (symbol-value subject-sym)))
-	      (if (not (eq id-sym (aref vect 0)))
-		  (aset vect 2 (delq m (aref vect 2)))
-		(if message-changing
-		    (if (null (cdr (aref vect 3)))
-			(makunbound subject-sym)
-		      (let ((p (aref vect 3))
-			    oldest-msg oldest-date children)
-			(setq oldest-msg (car p)
-			      oldest-date (vm-so-sortable-datestring (car p))
-			      p (cdr p))
-			(while p
-			  (if (and (string-lessp (vm-so-sortable-datestring (car p))
-						 oldest-date)
-				   (not (eq m (car p))))
-			      (setq oldest-msg (car p)
-				    oldest-date (vm-so-sortable-datestring (car p))))
-			  (setq p (cdr p)))
-			(aset vect 0 (intern (vm-su-message-id oldest-msg)
-					     vm-thread-obarray))
-			(aset vect 1 oldest-date)
-			(setq children (delq oldest-msg (aref vect 2)))
-			(aset vect 2 children)
-			(aset vect 3 (delq m (aref vect 3)))
-			;; I'm not sure there aren't situations
-			;; where this might loop forever.
-			(let ((inhibit-quit nil))
-			  (vm-thread-mark-for-summary-update children))))))))
+	(set-buffer (vm-buffer-of m))
+	(if (not (vectorp vm-thread-obarray))
+	    nil
+	  (let ((inhibit-quit t))
+	    (vm-set-thread-list-of m nil)
+	    (vm-set-thread-indentation-of m nil)
+	    (setq id-sym (intern (vm-su-message-id m) vm-thread-obarray)
+		  subject-sym (intern (vm-so-sortable-subject m)
+				      vm-thread-subject-obarray))
+	    (if (boundp id-sym)
+		(progn
+		  (put id-sym 'messages (delq m (get id-sym 'messages)))
+		  (vm-thread-mark-for-summary-update (get id-sym 'children))
+		  (setq p-sym (symbol-value id-sym))
+		  (and p-sym (put p-sym 'children
+				  (delq m (get p-sym 'children))))
+		  (if message-changing
+		      (set id-sym nil))))
+	    (if (and (boundp subject-sym) (setq vect (symbol-value subject-sym)))
+		(if (not (eq id-sym (aref vect 0)))
+		    (aset vect 2 (delq m (aref vect 2)))
+		  (if message-changing
+		      (if (null (cdr (aref vect 3)))
+			  (makunbound subject-sym)
+			(let ((p (aref vect 3))
+			      oldest-msg oldest-date children)
+			  (setq oldest-msg (car p)
+				oldest-date (vm-so-sortable-datestring (car p))
+				p (cdr p))
+			  (while p
+			    (if (and (string-lessp (vm-so-sortable-datestring (car p))
+						   oldest-date)
+				     (not (eq m (car p))))
+				(setq oldest-msg (car p)
+				      oldest-date (vm-so-sortable-datestring (car p))))
+			    (setq p (cdr p)))
+			  (aset vect 0 (intern (vm-su-message-id oldest-msg)
+					       vm-thread-obarray))
+			  (aset vect 1 oldest-date)
+			  (setq children (delq oldest-msg (aref vect 2)))
+			  (aset vect 2 children)
+			  (aset vect 3 (delq m (aref vect 3)))
+			  ;; I'm not sure there aren't situations
+			  ;; where this might loop forever.
+			  (let ((inhibit-quit nil))
+			    (vm-thread-mark-for-summary-update children)))))))))
 	  (setq mp (cdr mp))))))
 
 (defun vm-th-references (m)
 The value of `vm-spool-files-suffixes' will not be used unless
 `vm-crash-box-suffix' is also defined, since a crash box is
 required for all mail retrieval from spool files."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-crash-box-suffix nil
   "*String suffix used to create possible crash box file names for folders.
 for this variable to have effect."
   :type 'boolean)
 
-(defcustom vm-auto-displayed-mime-content-types '("text" "multipart")
+(defcustom vm-auto-displayed-mime-content-types '("text" "image" "multipart")
   "*List of MIME content types that should be displayed immediately
 after decoding.  Other types will be displayed as a button that
 you must activate to display the object.
 Any type that cannot be displayed internally or externally will
 be displayed as a button that allows you to save the body of the MIME
 object to a file."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-auto-displayed-mime-content-type-exceptions nil
   "*List of MIME content types that should not be displayed immediately
 
 If a top-level type is listed without a subtype, all subtypes of
 that type are assumed to be included."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-mime-internal-content-types t
   "*List of MIME content types that should be displayed internally
 
 Note that all multipart types are always handled internally.
 There is no need to list them here."
-  :type '(choice (const t) (const nil) (list string)))
+  :type '(choice (const t) (const nil) (repeat string)))
 
 (defcustom vm-mime-internal-content-type-exceptions nil
   "*List of MIME content types that should not be displayed internally.
 
 If a top-level type is listed without a subtype, all subtypes of
 that type are assumed to be included."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-mime-external-content-types-alist nil
   "*Alist of MIME content types and the external programs used to display them.
 
 If a top-level type is listed without a subtype, all subtypes of
 that type are assumed to be included."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-mime-delete-viewer-processes t
   "*Non-nil value causes VM to kill external MIME viewer processes
 
 To tell VM how to display other character sets, see
 `vm-mime-charset-font-alist'."
-  :type '(choice (const t) (list string)))
+  :type '(choice (const t) (repeat string)))
 
 (defcustom vm-mime-default-face-charset-exceptions nil
   "*List of character sets that cannot be displayed using the default face.
 This variable acts as an exception list for `vm-mime-default-face-charsets'.
 Character sets listed here will not be considered displayable using the
 default face even if they are also listed in `vm-mime-default-face-charsets'."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-mime-charset-font-alist nil
   "*Assoc list of character sets and fonts that can be used to display them.
 (defcustom vm-mime-base64-decoder-switches nil
   "*List of command line flags passed to the command named by
 `vm-mime-base64-decoder-program'."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-mime-base64-encoder-program nil
   "*Non-nil value should be a string that names a MIME base64 encoder.
 (defcustom vm-mime-base64-encoder-switches nil
   "*List of command line flags passed to the command named by
 `vm-mime-base64-encoder-program'."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-mime-qp-decoder-program nil
   "*Non-nil value should be a string that names a MIME quoted-printable
 (defcustom vm-mime-qp-decoder-switches nil
   "*List of command line flags passed to the command named by
 `vm-mime-qp-decoder-program'."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-mime-qp-encoder-program nil
   "*Non-nil value should be a string that names a MIME quoted-printable
 (defcustom vm-mime-qp-encoder-switches nil
   "*List of command line flags passed to the command named by
 `vm-mime-qp-encoder-program'."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-mime-uuencode-decoder-program "uudecode"
   "*Non-nil value should be a string that names UUENCODE decoder.
 (defcustom vm-mime-uuencode-decoder-switches nil
   "*List of command line flags passed to the command named by
 `vm-mime-uuencode-decoder-program'."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-auto-next-message t
   "*Non-nil value causes VM to use `vm-next-message' to advance to the next
 it yourself.
 
 Case is ignored when matching the addresses."
-  :type '(list regexp))
+  :type '(repeat regexp))
 
 (defcustom vm-reply-ignored-reply-tos nil
   "*Non-nil value should be a list of regular expressions that match
 This variable exists solely to provide an escape chute from
 mailing lists that add a Reply-To: mailing list header, thereby
 leaving no way to reply to just the author of a message."
-  :type '(list regexp))
+  :type '(repeat regexp))
 
 (defcustom vm-in-reply-to-format "%i"
   "*String which specifies the format of the contents of the In-Reply-To
 order in that case, with headers not matching any in the
 `vm-included-text-headers' list appearing last in the header
 section of the included text."
-  :type '(list regexp))
+  :type '(repeat regexp))
 
 (defcustom vm-included-text-discard-header-regexp nil
   "*Non-nil value should be a regular expression header that tells
 in that case, with headers not matching any in the
 `vm-forwarded-headers' list appearing last in the header section of
 the forwarded message."
-  :type '(list regexp))
+  :type '(repeat regexp))
 
 (defcustom vm-unforwarded-header-regexp "only-drop-this-header"
   "*Non-nil value should be a regular expression header that tells
 appearance in that case, with headers not matching any in the
 `vm-rfc934-digest-headers' list appearing last in the headers
 of the digestified messages."
-  :type '(list regexp))
+  :type '(repeat regexp))
 
 (defcustom vm-rfc934-digest-discard-header-regexp nil
   "*Non-nil value should be a regular expression header that tells
 appearance in that case, with headers not matching any in the
 `vm-rfc1153-digest-headers' list appearing last in the headers of
 the digestified messages."
-  :type '(list regexp))
+  :type '(repeat regexp))
 
 (defcustom vm-rfc1153-digest-discard-header-regexp "\\(X400-\\)?Received:"
   "*Non-nil value should be a regular expression header that tells
 appearance in that case, with headers not matching any in the
 `vm-mime-digest-headers' list appearing last in the headers
 of the digestified messages."
-  :type '(list regexp))
+  :type '(repeat regexp))
 
 (defcustom vm-mime-digest-discard-header-regexp nil
   "*Non-nil value should be a regular expression header that tells
 appearance in that case, with headers not matching any in the
 `vm-resend-bounced-headers' list appearing last in the headers of
 the message."
-  :type '(list regexp))
+  :type '(repeat regexp))
 
 (defcustom vm-resend-bounced-discard-header-regexp nil
   "*Non-nil value should be a regular expression that tells
 appearance in that case, with headers not matching any in the
 `vm-resend-headers' list appearing last in the headers of
 the message."
-  :type '(list regexp))
+  :type '(repeat regexp))
 
 (defcustom vm-resend-discard-header-regexp "\\(\\(X400-\\)?Received:\\|Resent-\\)"
   "*Non-nil value should be a regular expression that tells
       (list (or vm-folder-directory (file-name-directory vm-primary-inbox)))
   "*List of directories containing folders to be listed in the folders summary.
 List the directories in the order you wish them to appear in the summary."
-  :type '(list directory))
+  :type '(repeat directory))
 
 (defcustom vm-mutable-windows pop-up-windows
   "*This variable's value controls VM's window usage.
 
 PARAMLIST is a list of pairs as described in the documentation for
 the function `make-frame'."
-  :type '(repeat (list (choice completion)
-		       (choice composition)
-		       (choice edit)
-		       (choice folder)
-		       (choice folders-summary)
-		       (choice primary-folder)
-		       (choice summary))
-		 (repeat (cons symbol sexp))))
+  :type '(repeat (cons (choice (const completion)
+			       (const composition)
+			       (const edit)
+			       (const folder)
+			       (const folders-summary)
+			       (const primary-folder)
+			       (const summary))
+		       (repeat (cons symbol sexp)))))
 
 (defcustom vm-search-other-frames t
   "*Non-nil means VM should search frames other than the selected frame
 Emacs 21 and beyond.
 
 See also `vm-toolbar-orientation' to control where the toolbar is placed."
-  :type '(list (choice autofile)
-	       (choice compose)
-	       (choice delete/undelete)
-	       (choice file)
-	       (choice getmail)
-	       (choice help)
-	       (choice mime)
-	       (choice next)
-	       (choice previous)
-	       (choice print)
-	       (choice quit)
-	       (choice reply)
-	       (choice visit)
-	       (choice nil)))
+  :type '(repeat (choice integer
+			 (const autofile)
+			 (const compose)
+			 (const delete/undelete)
+			 (const file)
+			 (const getmail)
+			 (const help)
+			 (const mime)
+			 (const next)
+			 (const previous)
+			 (const print)
+			 (const quit)
+			 (const reply)
+			 (const visit)
+			 (const nil))))
 
 (defcustom vm-toolbar-orientation 'left
   "*Value is a symbol that specifies where the VM toolbar is located.
 
 This variable only has meaning under XEmacs 19.12 and beyond.
 Under FSF Emacs 21 the toolbar is always at the top of the frame."
-  :type '(list (choice left)
-	       (choice right)
-	       (choice top)
-	       (choice bottom)))
+  :type '(choice (const left)
+		 (const right)
+		 (const top)
+		 (const bottom)))
 
 (defcustom vm-toolbar-pixmap-directory vm-image-directory
   "*Value specifies the directory VM should find its toolbar pixmaps."
 This variable only has meaning in Emacs environments where menus
 are provided, which usually means Emacs has to be running under a
 window system."
-  :type '(list (choice dispose)
-	       (choice emacs)
-	       (choice folder)
-	       (choice help)
-	       (choice label)
-	       (choice mark)
-	       (choice motion)
-	       (choice send)
-	       (choice sort)
-	       (choice undo)
-	       (choice virtual)
-	       (choice nil)))
+  :type '(choice (const 1)
+		 (repeat (choice (const dispose)
+				 (const emacs)
+				 (const folder)
+				 (const help)
+				 (const label)
+				 (const mark)
+				 (const motion)
+				 (const send)
+				 (const sort)
+				 (const undo)
+				 (const virtual)
+				 (const nil)))))
 
 (defcustom vm-popup-menu-on-mouse-3 t
   "*Non-nil value means VM should provide context-sensitive menus on mouse-3.
 
 If `vm-url-retrieval-methods' value is nil, VM will not try to
 use any URL retrieval methods."
-  :type '(list symbol))
+  :type '(set (const lynx)
+	      (const wget)
+	      (const w3m)
+	      (const url-w3)))
 
 (defcustom vm-url-browser
   (cond ((fboundp 'w3-fetch-other-frame)
 an URL using an existing Mosaic or Netscape process, if possible.
 
 A nil value means VM should not enable URL passing to browsers."
-  :type 'function)
+  :type '(choice (const nil)
+		 function
+		 string))
 
 (defcustom vm-highlight-url-face 'bold-italic
   "*Non-nil value should be a face to use display URLs found in messages.
   "*List of command line flags passed to the command named by
 `vm-print-command'.  VM uses `vm-print-command' to print
 messages."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-berkeley-mail-compatibility
   (memq system-type '(berkeley-unix netbsd))
 (defcustom vm-movemail-program-switches nil
   "*List of command line flags to pass to the movemail program
 named by `vm-movemail-program'."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-netscape-program "netscape"
   "*Name of program to use to run Netscape.
 
 (defcustom vm-netscape-program-switches nil
   "*List of command line switches to pass to Netscape."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-mosaic-program "Mosaic"
   "*Name of program to use to run Mosaic.
 
 (defcustom vm-mosaic-program-switches nil
   "*List of command line switches to pass to Mosaic."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-mmosaic-program "mMosaic"
   "*Name of program to use to run mMosaic.
 
 (defcustom vm-mmosaic-program-switches nil
   "*List of command line switches to pass to mMosaic."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-wget-program "wget"
   "*Name of program to use to run wget.
 
 (defcustom vm-ssh-program-switches nil
   "*List of command line switches to pass to SSH."
-  :type '(list string))
+  :type '(repeat string))
 
 (defcustom vm-ssh-remote-command "echo ready; sleep 15"
   "*Shell command to run to hold open the SSH connection.
 mail is not sent."
   :type 'boolean)
 
-(defconst vm-maintainer-address "bug-vm@uunet.uu.net"
+(defun vm-octal (n)
+  (let ((val 0) digit (expo 1))
+    (while (> n 0)
+      (setq digit (% n 10))
+      (if (>= digit 8)
+	  (error "invalid octal digit: %d" digit))
+      (setq val (+ val (* digit expo))
+	    n (/ n 10)
+	    expo (* expo 8)))
+    val ))
+
+(defcustom vm-default-folder-permission-bits (vm-octal 600)
+  "*Default UNIX permission bits for newly created folders."
+  :type 'integer)
+
+(defconst vm-maintainer-address "bug-vm@wonderworks.com"
   "Where to send VM bug reports.")
 
 (defvar vm-mode-map

File vm-version.el

 
 (provide 'vm-version)
 
-(defconst vm-version "7.04"
+(defconst vm-version "7.07"
   "Version number of VM.")
 
 (defun vm-version ()

File vm-virtual.el

 	  (setcdr (car clauses)
 		  (list (list 'and '(marked)
 			      (nconc (list 'or) (cdr (car clauses)))))))
-      (message "%S" (car clauses))
       (setq clauses (cdr clauses)))
     (setcar vfolder (format "%s/%s" (buffer-name) (car vfolder)))
     (setq vm-virtual-folder-alist (list vfolder))
 \input texinfo  @comment -*-Text-*-
 @setfilename vm.info
 @settitle VM User's Manual
-@c @direntry
-@c * VM::			A mail reader.
-@c @end direntry
+@direntry
+* VM::			A mail reader.
+@end direntry
 @iftex
 @finalout
 @end iftex
 @code{vm-ssh-program} must name it in order for IMAP over SSH to
 work.  When VM makes the SSH connection it must run a command on
 the remote host so that the SSH session is maintained long
-enough for the POP connection to be established.  By default that command
+enough for the IMAP connection to be established.  By default that command
 is @samp{"echo ready; sleep 10"}, but you can specify another
 command by setting @code{vm-ssh-remote-command}.  Whatever
 command you use must produce some output and hold the connection