Mercurial > hg > xemacs-beta
diff lisp/vm/vm-folder.el @ 20:859a2309aef8 r19-15b93
Import from CVS: tag r19-15b93
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:50:05 +0200 |
parents | 49a24b4fd526 |
children | 4103f0995bd7 |
line wrap: on
line diff
--- a/lisp/vm/vm-folder.el Mon Aug 13 08:49:44 2007 +0200 +++ b/lisp/vm/vm-folder.el Mon Aug 13 08:50:05 2007 +0200 @@ -1,5 +1,5 @@ ;;; VM folder related functions -;;; Copyright (C) 1989, 1990, 1991, 1993, 1994, 1995, 1996 Kyle E. Jones +;;; Copyright (C) 1989-1997 Kyle E. Jones ;;; ;;; This program is free software; you can redistribute it and/or modify ;;; it under the terms of the GNU General Public License as published by @@ -59,17 +59,18 @@ vm-numbering-redo-start-point or is equal to t, then vm-numbering-redo-start-point is set to match it." (intern (buffer-name) vm-buffers-needing-display-update) - (if (and (consp start-point) (consp vm-numbering-redo-start-point) - (not (eq vm-numbering-redo-start-point t))) - (let ((mp vm-message-list)) - (while (and mp (not (or (eq mp start-point) - (eq mp 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) - (setq vm-numbering-redo-start-point start-point))) - (setq vm-numbering-redo-start-point start-point))) + (if (eq vm-numbering-redo-start-point t) + 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)))) + (setq mp (cdr mp))) + (if (null mp) + (error "Something is wrong in vm-set-numbering-redo-start-point")) + (if (eq mp start-point) + (setq vm-numbering-redo-start-point start-point))) + (setq vm-numbering-redo-start-point start-point)))) (defun vm-set-numbering-redo-end-point (end-point) "Set vm-numbering-redo-end-point to END-POINT if appropriate. @@ -122,20 +123,21 @@ START-POINT should be a cons in vm-message-list or just t. (t means start from the beginning of vm-message-list.) If START-POINT is closer to the head of vm-message-list than -vm-numbering-redo-start-point or is equal to t, then -vm-numbering-redo-start-point is set to match it." +vm-summary-redo-start-point or is equal to t, then +vm-summary-redo-start-point is set to match it." (intern (buffer-name) vm-buffers-needing-display-update) - (if (and (consp start-point) (consp vm-summary-redo-start-point) - (not (eq vm-summary-redo-start-point t))) - (let ((mp vm-message-list)) - (while (and mp (not (or (eq mp start-point) - (eq mp vm-summary-redo-start-point)))) - (setq mp (cdr mp))) - (if (null mp) - (error "Something is wrong in vm-set-summary-redo-start-point")) - (if (eq mp start-point) - (setq vm-summary-redo-start-point start-point))) - (setq vm-summary-redo-start-point start-point))) + (if (eq vm-summary-redo-start-point t) + nil + (if (and (consp start-point) (consp vm-summary-redo-start-point)) + (let ((mp vm-message-list)) + (while (and mp (not (or (eq mp start-point) + (eq mp vm-summary-redo-start-point)))) + (setq mp (cdr mp))) + (if (null mp) + (error "Something is wrong in vm-set-summary-redo-start-point")) + (if (eq mp start-point) + (setq vm-summary-redo-start-point start-point))) + (setq vm-summary-redo-start-point start-point)))) (defun vm-mark-for-summary-update (m &optional dont-kill-cache) "Mark message M for a summary update. @@ -235,22 +237,34 @@ "Do a modeline update for the current folder buffer. This means setting up all the various vm-ml attribute variables in the folder buffer and copying necessary variables to the -folder buffer's summary buffer, and then forcing Emacs to update -all modelines. +folder buffer's summary and presentation buffers, and then +forcing Emacs to update all modelines. -Also if a virtual folder being updated has no messages, -erase-buffer is called on its buffer." +If a virtual folder being updated has no messages, then +erase-buffer is called on its buffer. + +If any type of folder is empty, erase-buffer is called +on its presentation buffer, if any." ;; XXX This last bit should probably should be moved to ;; XXX vm-expunge-folder. (if (null vm-message-pointer) - ;; erase the leftover message if the folder is really empty. - (if (eq major-mode 'vm-virtual-mode) - (let ((buffer-read-only nil) - (omodified (buffer-modified-p))) - (unwind-protect - (erase-buffer) - (set-buffer-modified-p omodified)))) + (progn + ;; erase the leftover message if the folder is really empty. + (if (eq major-mode 'vm-virtual-mode) + (let ((buffer-read-only nil) + (omodified (buffer-modified-p))) + (unwind-protect + (erase-buffer) + (set-buffer-modified-p omodified)))) + (if vm-presentation-buffer + (let ((omodified (buffer-modified-p))) + (unwind-protect + (save-excursion + (set-buffer vm-presentation-buffer) + (let ((buffer-read-only nil)) + (erase-buffer))) + (set-buffer-modified-p omodified))))) ;; try to avoid calling vm-su-labels if possible so as to ;; avoid loading vm-summary.el. (if (vm-labels-of (car vm-message-pointer)) @@ -295,6 +309,30 @@ 'vm-message-list) (set-buffer vm-summary-buffer) (set-buffer-modified-p modified)))) + (if vm-presentation-buffer + (let ((modified (buffer-modified-p))) + (save-excursion + (vm-copy-local-variables vm-presentation-buffer + 'vm-ml-message-new + 'vm-ml-message-unread + 'vm-ml-message-read + 'vm-ml-message-edited + 'vm-ml-message-replied + 'vm-ml-message-forwarded + 'vm-ml-message-filed + 'vm-ml-message-written + 'vm-ml-message-deleted + 'vm-ml-message-marked + 'vm-ml-message-number + 'vm-ml-highest-message-number + 'vm-folder-read-only + 'vm-folder-type + 'vm-virtual-folder-definition + 'vm-virtual-mirror + 'vm-ml-labels + 'vm-message-list) + (set-buffer vm-presentation-buffer) + (set-buffer-modified-p modified)))) (vm-force-mode-line-update)) (defun vm-update-summary-and-mode-line () @@ -440,7 +478,7 @@ This function works by examining the beginning of a folder. If optional arg FILE is present the type of FILE is returned instead. If optional second and third arg START and END are provided, -vm-get-folder-type will examine the the text between those buffer +vm-get-folder-type will examine the text between those buffer positions. START and END default to 1 and (buffer-size) + 1. Returns @@ -939,15 +977,17 @@ ;; ;; header-alist will contain an assoc list version of ;; keep-list. For messages associated with a folder - ;; buffer: when a matching header is found, the header - ;; is stuffed into its corresponding assoc cell and the - ;; header text is deleted from the buffer. After all - ;; the visible headers have been collected, they are - ;; inserted into the buffer in a clump at the end of - ;; the header section. Unmatched headers are skipped over. + ;; buffer: when a matching header is found, the + ;; header's start and end positions are added to its + ;; corresponding assoc cell. The positions of unwanted + ;; headers are remember also so that they can be copied + ;; to the top of the message, to be out of sight after + ;; narrowing. Once the positions have all been + ;; recorded a new copy of the headers is inserted in + ;; the proper order and the old headers are deleted. ;; - ;; For free standing messages, unmatched headers are - ;; stripped from the message. + ;; For free standing messages, unwanted headers are + ;; stripped from the message, unremembered. (vm-save-restriction (let ((header-alist (vm-build-header-order-alist keep-list)) (buffer-read-only nil) @@ -961,6 +1001,10 @@ ;; in a mail context reordering headers is harmless. (buffer-file-name nil) (case-fold-search t) + (unwanted-list nil) + unwanted-tail + new-header-start + old-header-start (old-buffer-modified-p (buffer-modified-p))) (unwind-protect (progn @@ -987,6 +1031,7 @@ (vm-headers-of message) (vm-text-of message)) (goto-char (point-min)))) + (setq old-header-start (point)) (while (and (not (= (following-char) ?\n)) (vm-match-header)) (setq end-of-header (vm-matched-header-end) @@ -998,50 +1043,69 @@ ;; discard-regexp is matched (if (or (and (null list) (null discard-regexp)) (and discard-regexp (looking-at discard-regexp))) - ;; skip the unwanted header if doing + ;; delete the unwanted header if not doing ;; work for a folder buffer, otherwise - ;; discard the header. - (if message - (goto-char end-of-header) - (delete-region (point) end-of-header)) + ;; remember the start and end of the + ;; unwanted header so we can copy it + ;; later. + (if (not message) + (delete-region (point) end-of-header) + (if (null unwanted-list) + (setq unwanted-list + (cons (point) (cons end-of-header nil)) + unwanted-tail unwanted-list) + (if (= (point) (car (cdr unwanted-tail))) + (setcar (cdr unwanted-tail) + end-of-header) + (setcdr (cdr unwanted-tail) + (cons (point) + (cons end-of-header nil))) + (setq unwanted-tail (cdr (cdr unwanted-tail))))) + (goto-char end-of-header)) ;; got a match - ;; stuff the header into the cdr of the - ;; returned alist element + ;; stuff the start and end of the header + ;; into the cdr of the returned alist + ;; element. (if list - (if (cdr list) - (setcdr list - (concat - (cdr list) - (buffer-substring (point) - end-of-header))) - (setcdr list (buffer-substring (point) - end-of-header))) + ;; reverse point and end-of-header. + ;; list will be nreversed later. + (setcdr list (cons end-of-header + (cons (point) + (cdr list)))) + ;; reverse point and end-of-header. + ;; list will be nreversed later. (setq extras - (cons (buffer-substring (point) end-of-header) - extras))) - (delete-region (point) end-of-header))) + (cons end-of-header + (cons (point) extras)))) + (goto-char end-of-header))) + (setq new-header-start (point)) + (while unwanted-list + (insert-buffer-substring (current-buffer) + (car unwanted-list) + (car (cdr unwanted-list))) + (setq unwanted-list (cdr (cdr unwanted-list)))) ;; remember the offset of where the visible ;; header start so we can initialize the ;; vm-vheaders-of field later. (if message - (setq vheader-offset (1- (point)))) - ;; now dump out the headers we saved. - ;; the keep-list headers go first. - (setq list header-alist) - (while list - (if (cdr (car list)) - (progn - (insert (cdr (car list))) - (setcdr (car list) nil))) - (setq list (cdr list))) + (setq vheader-offset (- (point) new-header-start))) + (while header-alist + (setq list (nreverse (cdr (car header-alist)))) + (while list + (insert-buffer-substring (current-buffer) + (car list) + (car (cdr list))) + (setq list (cdr (cdr list)))) + (setq header-alist (cdr header-alist))) ;; now the headers that were not explicitly ;; undesirable, if any. - (if extras - (progn - (setq extras (nreverse extras)) - (while extras - (insert (car extras)) - (setq extras (cdr extras))))) + (setq extras (nreverse extras)) + (while extras + (insert-buffer-substring (current-buffer) + (car extras) + (car (cdr extras))) + (setq extras (cdr (cdr extras)))) + (delete-region old-header-start new-header-start) ;; update the folder buffer if we're supposed to. ;; lock out interrupts. (if message @@ -1473,8 +1537,6 @@ attributes cache (case-fold-search t) (buffer-read-only nil) - ;; don't truncate the printing of large Lisp objects - (print-length nil) opoint ;; This prevents file locking from occuring. Disabling ;; locking can speed things noticeably if the lock @@ -1533,6 +1595,28 @@ (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) + ;; stuff the attributes of messages that need it. + ;; build a list of messages that need their attributes stuffed + (setq mp vm-message-list) + (while mp + (if (vm-modflag-of (car mp)) + (setq newlist (cons (car mp) newlist))) + (setq mp (cdr mp))) + ;; 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. + (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 mp (cdr mp))) + (if mp nil t))) + ;; we can be a bit lazy in this function since it's only called ;; from within vm-stuff-attributes. we don't worry about ;; restoring the modified flag, setting buffer-read-only, or @@ -1655,8 +1739,6 @@ ;; oh well, no way around this. (insert vm-labels-header " " (let ((print-escape-newlines t) - ;; don't truncate the printing of large Lisp objects - (print-length nil) (list nil)) (mapatoms (function (lambda (sym) @@ -1717,8 +1799,6 @@ (widen) (let ((old-buffer-modified-p (buffer-modified-p)) (case-fold-search t) - ;; don't truncate the printing of large Lisp objects - (print-length nil) ;; This prevents file locking from occuring. Disabling ;; locking can speed things noticeably if the lock ;; directory is on a slow device. We don't need locking @@ -1765,8 +1845,6 @@ (case-fold-search t) (print-escape-newlines t) lim - ;; don't truncate the printing of large Lisp objects - (print-length nil) (buffer-read-only nil) ;; This prevents file locking from occuring. Disabling ;; locking can speed things noticeably if the lock @@ -1810,8 +1888,6 @@ (widen) (let ((old-buffer-modified-p (buffer-modified-p)) (case-fold-search t) - ;; don't truncate the printing of large Lisp objects - (print-length nil) ;; This prevents file locking from occuring. Disabling ;; locking can speed things noticeably if the lock ;; directory is on a slow device. We don't need locking @@ -1937,8 +2013,11 @@ (if (not (memq major-mode '(vm-mode vm-virtual-mode))) (error "%s must be invoked from a VM buffer." this-command)) (vm-check-for-killed-summary) + (vm-check-for-killed-presentation) - (run-hooks 'vm-quit-hook) + (save-excursion (run-hooks 'vm-quit-hook)) + + (vm-garbage-collect-message) (vm-display nil nil '(vm-quit-just-bury) '(vm-quit-just-bury quitting)) @@ -1946,6 +2025,10 @@ (vm-display vm-summary-buffer nil nil nil)) (if vm-summary-buffer (vm-bury-buffer vm-summary-buffer)) + (if vm-presentation-buffer-handle + (vm-display vm-presentation-buffer-handle nil nil nil)) + (if vm-presentation-buffer-handle + (vm-bury-buffer vm-presentation-buffer-handle)) (vm-display (current-buffer) nil nil nil) (vm-bury-buffer (current-buffer))) @@ -1957,15 +2040,22 @@ (if (not (memq major-mode '(vm-mode vm-virtual-mode))) (error "%s must be invoked from a VM buffer." this-command)) (vm-check-for-killed-summary) + (vm-check-for-killed-presentation) - (run-hooks 'vm-quit-hook) + (save-excursion (run-hooks 'vm-quit-hook)) + + (vm-garbage-collect-message) (vm-display nil nil '(vm-quit-just-iconify) '(vm-quit-just-iconify quitting)) - (vm-bury-buffer (current-buffer)) - (if vm-summary-buffer - (vm-bury-buffer vm-summary-buffer)) - (vm-iconify-frame)) + (let ((summary-buffer vm-summary-buffer) + (pres-buffer vm-presentation-buffer-handle)) + (vm-bury-buffer (current-buffer)) + (if summary-buffer + (vm-bury-buffer summary-buffer)) + (if pres-buffer + (vm-bury-buffer pres-buffer)) + (vm-iconify-frame))) (defun vm-quit-no-change () "Quit visiting the current folder without saving changes made to the folder." @@ -1979,11 +2069,13 @@ (if (not (memq major-mode '(vm-mode vm-virtual-mode))) (error "%s must be invoked from a VM buffer." this-command)) (vm-check-for-killed-summary) + (vm-check-for-killed-presentation) (vm-display nil nil '(vm-quit vm-quit-no-change) (list this-command 'quitting)) (let ((virtual (eq major-mode 'vm-virtual-mode))) (cond ((and (not virtual) no-change (buffer-modified-p) + (or buffer-file-name buffer-offer-save) (not (zerop vm-messages-not-on-disk)) ;; Folder may have been saved with C-x C-s and attributes may have ;; been changed after that; in that case vm-messages-not-on-disk @@ -2000,14 +2092,20 @@ (if (= 1 vm-messages-not-on-disk) "" "s"))))) (error "Aborted")) ((and (not virtual) - no-change (buffer-modified-p) vm-confirm-quit + no-change + (or buffer-file-name buffer-offer-save) + (buffer-modified-p) + vm-confirm-quit (not (y-or-n-p "There are unsaved changes, quit anyway? "))) (error "Aborted")) ((and (eq vm-confirm-quit t) (not (y-or-n-p "Do you really want to quit? "))) (error "Aborted"))) - (run-hooks 'vm-quit-hook) + (save-excursion (run-hooks 'vm-quit-hook)) + + (vm-garbage-collect-message) + (vm-garbage-collect-folder) (vm-virtual-quit) (if (and (not no-change) (not virtual)) @@ -2016,45 +2114,71 @@ (vm-unsaved-message "Quitting...") (or vm-folder-read-only (eq major-mode 'vm-virtual-mode) (vm-change-all-new-to-unread)))) - (if (and (buffer-modified-p) (not no-change) (not virtual)) + (if (and (buffer-modified-p) + (or buffer-file-name buffer-offer-save) + (not no-change) + (not virtual)) (vm-save-folder)) (vm-unsaved-message "") (let ((summary-buffer vm-summary-buffer) + (pres-buffer vm-presentation-buffer-handle) (mail-buffer (current-buffer))) (if summary-buffer (progn - (vm-display vm-summary-buffer nil nil nil) + (vm-display summary-buffer nil nil nil) (kill-buffer summary-buffer))) + (if pres-buffer + (progn + (vm-display pres-buffer nil nil nil) + (kill-buffer pres-buffer))) (set-buffer mail-buffer) (vm-display mail-buffer nil nil nil) ;; vm-display is not supposed to change the current buffer. - ;; still better to be safe here. + ;; still it's better to be safe here. (set-buffer mail-buffer) (set-buffer-modified-p nil) (kill-buffer (current-buffer))) (vm-update-summary-and-mode-line))) (defun vm-start-itimers-if-needed () - (if (or (natnump vm-flush-interval) - (natnump vm-auto-get-new-mail)) - (progn - (if (null - (condition-case data - (progn (require 'itimer) t) - (error nil))) - (setq vm-flush-interval t - vm-auto-get-new-mail t) - (and (natnump vm-flush-interval) (not (get-itimer "vm-flush")) - (start-itimer "vm-flush" 'vm-flush-itimer-function - vm-flush-interval nil)) - (and (natnump vm-auto-get-new-mail) (not (get-itimer "vm-get-mail")) - (start-itimer "vm-get-mail" 'vm-get-mail-itimer-function - vm-auto-get-new-mail nil)))))) + (cond ((and (not (natnump vm-flush-interval)) + (not (natnump vm-auto-get-new-mail)))) + ((condition-case data + (progn (require 'itimer) t) + (error nil)) + (and (natnump vm-flush-interval) (not (get-itimer "vm-flush")) + (start-itimer "vm-flush" 'vm-flush-itimer-function + vm-flush-interval nil)) + (and (natnump vm-auto-get-new-mail) (not (get-itimer "vm-get-mail")) + (start-itimer "vm-get-mail" 'vm-get-mail-itimer-function + vm-auto-get-new-mail nil))) + ((condition-case data + (progn (require 'timer) t) + (error nil)) + (let (timer) + (and (natnump vm-flush-interval) + (setq timer (run-at-time vm-flush-interval vm-flush-interval + 'vm-flush-itimer-function nil)) + (timer-set-function timer 'vm-flush-itimer-function + (list timer))) + (and (natnump vm-auto-get-new-mail) + (setq timer (run-at-time vm-auto-get-new-mail + vm-auto-get-new-mail + 'vm-get-mail-itimer-function nil)) + (timer-set-function timer 'vm-get-mail-itimer-function + (list timer))))) + (t + (setq vm-flush-interval t + vm-auto-get-new-mail t)))) ;; support for numeric vm-auto-get-new-mail -(defun vm-get-mail-itimer-function () +;; if timer argument is present, this means we're using the Emacs +;; 'timer package rather than the 'itimer package. +(defun vm-get-mail-itimer-function (&optional timer) (if (integerp vm-auto-get-new-mail) - (set-itimer-restart current-itimer vm-auto-get-new-mail)) + (if timer + (timer-set-time timer (current-time) vm-auto-get-new-mail) + (set-itimer-restart current-itimer vm-auto-get-new-mail))) (let ((b-list (buffer-list))) (while (and (not (input-pending-p)) b-list) (save-excursion @@ -2079,13 +2203,19 @@ (setq b-list (cdr b-list))))) ;; support for numeric vm-flush-interval -(defun vm-flush-itimer-function () +;; if timer argument is present, this means we're using the Emacs +;; 'timer package rather than the 'itimer package. +(defun vm-flush-itimer-function (&optional timer) (if (integerp vm-flush-interval) - (set-itimer-restart current-itimer vm-flush-interval)) + (if timer + (timer-set-time timer (current-time) vm-flush-interval) + (set-itimer-restart current-itimer vm-flush-interval))) ;; if no vm-mode buffers are found, we might as well shut down the ;; flush itimer. (if (not (vm-flush-cached-data)) - (set-itimer-restart current-itimer nil))) + (if timer + (cancel-timer timer) + (set-itimer-restart current-itimer nil)))) ;; flush cached data in all vm-mode buffers. ;; returns non-nil if any vm-mode buffers were found. @@ -2099,16 +2229,12 @@ (setq found-one t) (if (not (eq vm-modification-counter vm-flushed-modification-counter)) - (let ((mp vm-message-list)) + (progn (vm-stuff-summary) (vm-stuff-labels) (and vm-message-order-changed (vm-stuff-message-order)) - (while (and mp (not (input-pending-p))) - (if (vm-modflag-of (car mp)) - (vm-stuff-attributes (car mp))) - (setq mp (cdr mp))) - (and (null mp) + (and (vm-stuff-folder-attributes t) (setq vm-flushed-modification-counter vm-modification-counter)))))) (setq buf-list (cdr buf-list))) @@ -2124,23 +2250,19 @@ ;; the stuff routines clean up after themselves, but should remain ;; as a safeguard against the time when other stuff is added here. (vm-save-restriction - (let ((mp vm-message-list) - (buffer-read-only)) - (while mp - (if (vm-modflag-of (car mp)) - (vm-stuff-attributes (car mp))) - (setq mp (cdr mp))) - (if vm-message-list - (progn - ;; get summary cache up-to-date - (vm-update-summary-and-mode-line) - (vm-stuff-bookmark) - (vm-stuff-header-variables) - (vm-stuff-labels) - (vm-stuff-summary) - (and vm-message-order-changed - (vm-stuff-message-order)))) - nil )))) + (let ((buffer-read-only)) + (vm-stuff-folder-attributes nil) + (if vm-message-list + (progn + ;; get summary cache up-to-date + (vm-update-summary-and-mode-line) + (vm-stuff-bookmark) + (vm-stuff-header-variables) + (vm-stuff-labels) + (vm-stuff-summary) + (and vm-message-order-changed + (vm-stuff-message-order)))) + nil )))) (defun vm-save-buffer (prefix) (interactive "P") @@ -2177,14 +2299,10 @@ (if (eq major-mode 'vm-virtual-mode) (vm-virtual-save-folder prefix) (if (buffer-modified-p) - (let (mp) + (let (mp (newlist nil)) ;; stuff the attributes of messages that need it. (vm-unsaved-message "Stuffing attributes...") - (setq mp vm-message-list) - (while mp - (if (vm-modflag-of (car mp)) - (vm-stuff-attributes (car mp))) - (setq mp (cdr mp))) + (vm-stuff-folder-attributes nil) ;; stuff bookmark and header variable values (if vm-message-list (progn @@ -2435,8 +2553,31 @@ ;; a timer process might try to start retrieving mail ;; before we finish. block these attempts. (vm-block-new-mail t) + (fallback-triples nil) crash in maildrop popdrop (got-mail nil)) + (cond ((and buffer-file-name + (consp vm-spool-file-suffixes) + (stringp vm-crash-box-suffix)) + (setq fallback-triples + (mapcar (function + (lambda (suffix) + (list buffer-file-name + (concat buffer-file-name suffix) + (concat buffer-file-name + vm-crash-box-suffix)))) + vm-spool-file-suffixes)))) + (cond ((and buffer-file-name + vm-make-spool-file-name vm-make-crash-box-name) + (setq fallback-triples + (ncons fallback-triples + (list (list buffer-file-name + (save-excursion + (funcall vm-make-spool-file-name + buffer-file-name)) + (save-excursion + (funcall vm-make-crash-box-name + buffer-file-name)))))))) (cond ((null (vm-spool-files)) (setq triples (list (list vm-primary-inbox @@ -2449,6 +2590,7 @@ (vm-spool-files)))) ((consp (car (vm-spool-files))) (setq triples (vm-spool-files)))) + (setq triples (append triples fallback-triples)) (while triples (setq in (expand-file-name (nth 0 (car triples)) vm-folder-directory) maildrop (nth 1 (car triples)) @@ -2573,7 +2715,10 @@ (message "No messages gathered.")))))) ;; returns non-nil if there were any new messages -(defun vm-assimilate-new-messages (&optional dont-read-attributes gobble-order) +(defun vm-assimilate-new-messages (&optional + dont-read-attributes + gobble-order + labels) (let ((tail-cons (vm-last vm-message-list)) b-list new-messages) (save-excursion @@ -2606,6 +2751,12 @@ ;; vm-assimilate-new-messages returns this value so it must ;; not be mangled. (setq new-messages (copy-sequence new-messages)) + ;; add the labels + (if (and labels vm-burst-digest-messages-inherit-labels) + (let ((mp new-messages)) + (while mp + (vm-set-labels-of (car mp) (copy-sequence labels)) + (setq mp (cdr mp))))) (if vm-summary-show-threads (progn ;; get numbering and summary of new messages done now @@ -2688,7 +2839,7 @@ (defun vm-display-startup-message () (if (sit-for 5) (let ((lines vm-startup-message-lines)) - (message "VM %s, Copyright (C) 1996 Kyle E. Jones; type ? for help" + (message "VM %s, Copyright (C) 1997 Kyle E. Jones; type ? for help" vm-version) (setq vm-startup-message-displayed t) (while (and (sit-for 4) lines) @@ -2702,7 +2853,7 @@ (progn (and vm-init-file (load vm-init-file (not interactive) (not interactive) t)) - (and vm-options-file (load vm-options-file t t t)))) + (and vm-preferences-file (load vm-preferences-file t t t)))) (setq vm-init-file-loaded t) (vm-display nil nil '(vm-load-init-file) '(vm-load-init-file))) @@ -2744,10 +2895,16 @@ 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 + mode-popup-menu (and vm-use-menus vm-popup-menu-on-mouse-3 (vm-menu-support-possible-p) (vm-menu-mode-menu)) buffer-read-only t + ;; If the user quits a vm-mode buffer, the default action is + ;; to kill the buffer. Make a note that we should offer to + ;; save this buffer even if it has no file associated with it. + ;; We have no idea of the value of the data in the buffer + ;; before it was put into vm-mode. + buffer-offer-save t require-final-newline nil vm-thread-obarray nil vm-thread-subject-obarray nil @@ -2767,6 +2924,15 @@ (use-local-map vm-mode-map) (and (vm-menu-support-possible-p) (vm-menu-install-menus)) + (add-hook 'kill-buffer-hook 'vm-garbage-collect-folder) + (add-hook 'kill-buffer-hook 'vm-garbage-collect-message) + ;; avoid the XEmacs file dialog box. + (defvar should-use-dialog-box) + (make-local-variable 'should-use-dialog-box) + (setq should-use-dialog-box nil) + ;; mail folders are precious. protect them by default. + (make-local-variable 'file-precious-flag) + (setq file-precious-flag t) (run-hooks 'vm-mode-hook) ;; compatibility (run-hooks 'vm-mode-hooks)) @@ -2881,6 +3047,24 @@ (narrow-to-region (point-min) (vm-text-end-of (car vm-message-pointer)))) (vm-display nil nil '(vm-change-folder-type) '(vm-change-folder-type))) +(defun vm-garbage-collect-folder () + (save-excursion + (while vm-folder-garbage-alist + (condition-case nil + (funcall (cdr (car vm-folder-garbage-alist)) + (car (car vm-folder-garbage-alist))) + (error nil)) + (setq vm-folder-garbage-alist (cdr vm-folder-garbage-alist))))) + +(defun vm-garbage-collect-message () + (save-excursion + (while vm-message-garbage-alist + (condition-case nil + (funcall (cdr (car vm-message-garbage-alist)) + (car (car vm-message-garbage-alist))) + (error nil)) + (setq vm-message-garbage-alist (cdr vm-message-garbage-alist))))) + (if (not (memq 'vm-write-file-hook write-file-hooks)) (setq write-file-hooks (cons 'vm-write-file-hook write-file-hooks)))