comparison lisp/vm/vm-folder.el @ 70:131b0175ea99 r20-0b30

Import from CVS: tag r20-0b30
author cvs
date Mon, 13 Aug 2007 09:02:59 +0200
parents 05472e90ae02
children c0c698873ce1
comparison
equal deleted inserted replaced
69:804d1389bcd6 70:131b0175ea99
1 ;;; VM folder related functions 1 ;;; VM folder related functions
2 ;;; Copyright (C) 1989-1997 Kyle E. Jones 2 ;;; Copyright (C) 1989, 1990, 1991, 1993, 1994, 1995, 1996 Kyle E. Jones
3 ;;; 3 ;;;
4 ;;; This program is free software; you can redistribute it and/or modify 4 ;;; This program is free software; you can redistribute it and/or modify
5 ;;; it under the terms of the GNU General Public License as published by 5 ;;; it under the terms of the GNU General Public License as published by
6 ;;; the Free Software Foundation; either version 1, or (at your option) 6 ;;; the Free Software Foundation; either version 1, or (at your option)
7 ;;; any later version. 7 ;;; any later version.
57 (t means start from the beginning of vm-message-list.) 57 (t means start from the beginning of vm-message-list.)
58 If START-POINT is closer to the head of vm-message-list than 58 If START-POINT is closer to the head of vm-message-list than
59 vm-numbering-redo-start-point or is equal to t, then 59 vm-numbering-redo-start-point or is equal to t, then
60 vm-numbering-redo-start-point is set to match it." 60 vm-numbering-redo-start-point is set to match it."
61 (intern (buffer-name) vm-buffers-needing-display-update) 61 (intern (buffer-name) vm-buffers-needing-display-update)
62 (if (eq vm-numbering-redo-start-point t) 62 (if (and (consp start-point) (consp vm-numbering-redo-start-point)
63 nil 63 (not (eq vm-numbering-redo-start-point t)))
64 (if (and (consp start-point) (consp vm-numbering-redo-start-point)) 64 (let ((mp vm-message-list))
65 (let ((mp vm-message-list)) 65 (while (and mp (not (or (eq mp start-point)
66 (while (and mp (not (or (eq mp start-point) 66 (eq mp vm-numbering-redo-start-point))))
67 (eq mp vm-numbering-redo-start-point)))) 67 (setq mp (cdr mp)))
68 (setq mp (cdr mp))) 68 (if (null mp)
69 (if (null mp) 69 (error "Something is wrong in vm-set-numbering-redo-start-point"))
70 (error "Something is wrong in vm-set-numbering-redo-start-point")) 70 (if (eq mp start-point)
71 (if (eq mp start-point) 71 (setq vm-numbering-redo-start-point start-point)))
72 (setq vm-numbering-redo-start-point start-point))) 72 (setq vm-numbering-redo-start-point start-point)))
73 (setq vm-numbering-redo-start-point start-point))))
74 73
75 (defun vm-set-numbering-redo-end-point (end-point) 74 (defun vm-set-numbering-redo-end-point (end-point)
76 "Set vm-numbering-redo-end-point to END-POINT if appropriate. 75 "Set vm-numbering-redo-end-point to END-POINT if appropriate.
77 Also mark the current buffer as needing a display update. 76 Also mark the current buffer as needing a display update.
78 77
121 Also mark the current buffer as needing a display update. 120 Also mark the current buffer as needing a display update.
122 121
123 START-POINT should be a cons in vm-message-list or just t. 122 START-POINT should be a cons in vm-message-list or just t.
124 (t means start from the beginning of vm-message-list.) 123 (t means start from the beginning of vm-message-list.)
125 If START-POINT is closer to the head of vm-message-list than 124 If START-POINT is closer to the head of vm-message-list than
126 vm-summary-redo-start-point or is equal to t, then 125 vm-numbering-redo-start-point or is equal to t, then
127 vm-summary-redo-start-point is set to match it." 126 vm-numbering-redo-start-point is set to match it."
128 (intern (buffer-name) vm-buffers-needing-display-update) 127 (intern (buffer-name) vm-buffers-needing-display-update)
129 (if (eq vm-summary-redo-start-point t) 128 (if (and (consp start-point) (consp vm-summary-redo-start-point)
130 nil 129 (not (eq vm-summary-redo-start-point t)))
131 (if (and (consp start-point) (consp vm-summary-redo-start-point)) 130 (let ((mp vm-message-list))
132 (let ((mp vm-message-list)) 131 (while (and mp (not (or (eq mp start-point)
133 (while (and mp (not (or (eq mp start-point) 132 (eq mp vm-summary-redo-start-point))))
134 (eq mp vm-summary-redo-start-point)))) 133 (setq mp (cdr mp)))
135 (setq mp (cdr mp))) 134 (if (null mp)
136 (if (null mp) 135 (error "Something is wrong in vm-set-summary-redo-start-point"))
137 (error "Something is wrong in vm-set-summary-redo-start-point")) 136 (if (eq mp start-point)
138 (if (eq mp start-point) 137 (setq vm-summary-redo-start-point start-point)))
139 (setq vm-summary-redo-start-point start-point))) 138 (setq vm-summary-redo-start-point start-point)))
140 (setq vm-summary-redo-start-point start-point))))
141 139
142 (defun vm-mark-for-summary-update (m &optional dont-kill-cache) 140 (defun vm-mark-for-summary-update (m &optional dont-kill-cache)
143 "Mark message M for a summary update. 141 "Mark message M for a summary update.
144 Also mark M's buffer as needing a display update. Any virtual 142 Also mark M's buffer as needing a display update. Any virtual
145 messages of M and their buffers are similarly marked for update. 143 messages of M and their buffers are similarly marked for update.
235 233
236 (defun vm-do-needed-mode-line-update () 234 (defun vm-do-needed-mode-line-update ()
237 "Do a modeline update for the current folder buffer. 235 "Do a modeline update for the current folder buffer.
238 This means setting up all the various vm-ml attribute variables 236 This means setting up all the various vm-ml attribute variables
239 in the folder buffer and copying necessary variables to the 237 in the folder buffer and copying necessary variables to the
240 folder buffer's summary and presentation buffers, and then 238 folder buffer's summary buffer, and then forcing Emacs to update
241 forcing Emacs to update all modelines. 239 all modelines.
242 240
243 If a virtual folder being updated has no messages, then 241 Also if a virtual folder being updated has no messages,
244 erase-buffer is called on its buffer. 242 erase-buffer is called on its buffer."
245
246 If any type of folder is empty, erase-buffer is called
247 on its presentation buffer, if any."
248 ;; XXX This last bit should probably should be moved to 243 ;; XXX This last bit should probably should be moved to
249 ;; XXX vm-expunge-folder. 244 ;; XXX vm-expunge-folder.
250 245
251 (if (null vm-message-pointer) 246 (if (null vm-message-pointer)
252 (progn 247 ;; erase the leftover message if the folder is really empty.
253 ;; erase the leftover message if the folder is really empty. 248 (if (eq major-mode 'vm-virtual-mode)
254 (if (eq major-mode 'vm-virtual-mode) 249 (let ((buffer-read-only nil)
255 (let ((buffer-read-only nil) 250 (omodified (buffer-modified-p)))
256 (omodified (buffer-modified-p))) 251 (unwind-protect
257 (unwind-protect 252 (erase-buffer)
258 (erase-buffer) 253 (set-buffer-modified-p omodified))))
259 (set-buffer-modified-p omodified))))
260 (if vm-presentation-buffer
261 (let ((omodified (buffer-modified-p)))
262 (unwind-protect
263 (save-excursion
264 (set-buffer vm-presentation-buffer)
265 (let ((buffer-read-only nil))
266 (erase-buffer)))
267 (set-buffer-modified-p omodified)))))
268 ;; try to avoid calling vm-su-labels if possible so as to 254 ;; try to avoid calling vm-su-labels if possible so as to
269 ;; avoid loading vm-summary.el. 255 ;; avoid loading vm-summary.el.
270 (if (vm-labels-of (car vm-message-pointer)) 256 (if (vm-labels-of (car vm-message-pointer))
271 (setq vm-ml-labels (vm-su-labels (car vm-message-pointer))) 257 (setq vm-ml-labels (vm-su-labels (car vm-message-pointer)))
272 (setq vm-ml-labels nil)) 258 (setq vm-ml-labels nil))
304 'vm-folder-type 290 'vm-folder-type
305 'vm-virtual-folder-definition 291 'vm-virtual-folder-definition
306 'vm-virtual-mirror 292 'vm-virtual-mirror
307 'vm-ml-sort-keys 293 'vm-ml-sort-keys
308 'vm-ml-labels 294 'vm-ml-labels
309 'vm-spooled-mail-waiting
310 'vm-message-list) 295 'vm-message-list)
311 (set-buffer vm-summary-buffer) 296 (set-buffer vm-summary-buffer)
312 (set-buffer-modified-p modified))))
313 (if vm-presentation-buffer
314 (let ((modified (buffer-modified-p)))
315 (save-excursion
316 (vm-copy-local-variables vm-presentation-buffer
317 'vm-ml-message-new
318 'vm-ml-message-unread
319 'vm-ml-message-read
320 'vm-ml-message-edited
321 'vm-ml-message-replied
322 'vm-ml-message-forwarded
323 'vm-ml-message-filed
324 'vm-ml-message-written
325 'vm-ml-message-deleted
326 'vm-ml-message-marked
327 'vm-ml-message-number
328 'vm-ml-highest-message-number
329 'vm-folder-read-only
330 'vm-folder-type
331 'vm-virtual-folder-definition
332 'vm-virtual-mirror
333 'vm-ml-labels
334 'vm-spooled-mail-waiting
335 'vm-message-list)
336 (set-buffer vm-presentation-buffer)
337 (set-buffer-modified-p modified)))) 297 (set-buffer-modified-p modified))))
338 (vm-force-mode-line-update)) 298 (vm-force-mode-line-update))
339 299
340 (defun vm-update-summary-and-mode-line () 300 (defun vm-update-summary-and-mode-line ()
341 "Update summary and mode line for all VM folder and summary buffers. 301 "Update summary and mode line for all VM folder and summary buffers.
506 (set-buffer b) 466 (set-buffer b)
507 (setq temp-buffer (generate-new-buffer "*vm-work*")) 467 (setq temp-buffer (generate-new-buffer "*vm-work*"))
508 (set-buffer temp-buffer) 468 (set-buffer temp-buffer)
509 (if (file-readable-p file) 469 (if (file-readable-p file)
510 (condition-case nil 470 (condition-case nil
511 (let ((coding-system-for-read 'binary)) 471 (insert-file-contents file nil 0 4096)
512 (insert-file-contents file nil 0 4096))
513 (wrong-number-of-arguments 472 (wrong-number-of-arguments
514 (call-process "sed" file temp-buffer nil 473 (call-process "sed" file temp-buffer nil
515 "-n" "1,/^$/p"))))))) 474 "-n" "1,/^$/p")))))))
516 (save-excursion 475 (save-excursion
517 (save-restriction 476 (save-restriction
917 tail-cons vm-message-list) 876 tail-cons vm-message-list)
918 (setcdr tail-cons (list message)) 877 (setcdr tail-cons (list message))
919 (setq tail-cons (cdr tail-cons))) 878 (setq tail-cons (cdr tail-cons)))
920 (vm-increment n) 879 (vm-increment n)
921 (if (zerop (% n modulus)) 880 (if (zerop (% n modulus))
922 (message "Parsing messages... %d" n))) 881 (vm-unsaved-message "Parsing messages... %d" n)))
923 (if (>= n modulus) 882 (if (>= n modulus)
924 (message "Parsing messages... done")) 883 (vm-unsaved-message "Parsing messages... done"))
925 (if (and (not (= last-end (point-max))) 884 (if (and (not (= last-end (point-max)))
926 (not (eq vm-folder-type 'unknown))) 885 (not (eq vm-folder-type 'unknown)))
927 (progn 886 (progn
928 (message "Warning: garbage found at end of folder, %s" 887 (message "Warning: garbage found at end of folder, %s"
929 (or buffer-file-name (buffer-name))) 888 (or buffer-file-name (buffer-name)))
978 (vm-set-vheaders-of message (vm-marker (match-beginning 0)))) 937 (vm-set-vheaders-of message (vm-marker (match-beginning 0))))
979 ;; oh well, we gotta do it the hard way. 938 ;; oh well, we gotta do it the hard way.
980 ;; 939 ;;
981 ;; header-alist will contain an assoc list version of 940 ;; header-alist will contain an assoc list version of
982 ;; keep-list. For messages associated with a folder 941 ;; keep-list. For messages associated with a folder
983 ;; buffer: when a matching header is found, the 942 ;; buffer: when a matching header is found, the header
984 ;; header's start and end positions are added to its 943 ;; is stuffed into its corresponding assoc cell and the
985 ;; corresponding assoc cell. The positions of unwanted 944 ;; header text is deleted from the buffer. After all
986 ;; headers are remember also so that they can be copied 945 ;; the visible headers have been collected, they are
987 ;; to the top of the message, to be out of sight after 946 ;; inserted into the buffer in a clump at the end of
988 ;; narrowing. Once the positions have all been 947 ;; the header section. Unmatched headers are skipped over.
989 ;; recorded a new copy of the headers is inserted in
990 ;; the proper order and the old headers are deleted.
991 ;; 948 ;;
992 ;; For free standing messages, unwanted headers are 949 ;; For free standing messages, unmatched headers are
993 ;; stripped from the message, unremembered. 950 ;; stripped from the message.
994 (vm-save-restriction 951 (vm-save-restriction
995 (let ((header-alist (vm-build-header-order-alist keep-list)) 952 (let ((header-alist (vm-build-header-order-alist keep-list))
996 (buffer-read-only nil) 953 (buffer-read-only nil)
997 (work-buffer nil) 954 (work-buffer nil)
998 (extras nil) 955 (extras nil)
1002 ;; locking can speed things noticeably if the lock directory 959 ;; locking can speed things noticeably if the lock directory
1003 ;; is on a slow device. We don't need locking here because 960 ;; is on a slow device. We don't need locking here because
1004 ;; in a mail context reordering headers is harmless. 961 ;; in a mail context reordering headers is harmless.
1005 (buffer-file-name nil) 962 (buffer-file-name nil)
1006 (case-fold-search t) 963 (case-fold-search t)
1007 (unwanted-list nil)
1008 unwanted-tail
1009 new-header-start
1010 old-header-start
1011 (old-buffer-modified-p (buffer-modified-p))) 964 (old-buffer-modified-p (buffer-modified-p)))
1012 (unwind-protect 965 (unwind-protect
1013 (progn 966 (progn
1014 (if message 967 (if message
1015 (progn 968 (progn
1032 (insert-buffer-substring 985 (insert-buffer-substring
1033 folder-buffer 986 folder-buffer
1034 (vm-headers-of message) 987 (vm-headers-of message)
1035 (vm-text-of message)) 988 (vm-text-of message))
1036 (goto-char (point-min)))) 989 (goto-char (point-min))))
1037 (setq old-header-start (point)) 990 (while (and (not (= (following-char) ?\n))
1038 ;; as we loop through the headers, skip >From 991 (vm-match-header))
1039 ;; lines. these can occur anywhere in the
1040 ;; header section if the message has been
1041 ;; manhandled by some dumb delivery agents
1042 ;; (SCO and Solaris are the usual suspects.)
1043 ;; it's a tough ol' world.
1044 (while (progn (while (looking-at ">From ")
1045 (forward-line))
1046 (and (not (= (following-char) ?\n))
1047 (vm-match-header)))
1048 (setq end-of-header (vm-matched-header-end) 992 (setq end-of-header (vm-matched-header-end)
1049 list (vm-match-ordered-header header-alist)) 993 list (vm-match-ordered-header header-alist))
1050 ;; don't display/keep this header if 994 ;; don't display/keep this header if
1051 ;; keep-list not matched 995 ;; keep-list not matched
1052 ;; and discard-regexp is nil 996 ;; and discard-regexp is nil
1053 ;; or 997 ;; or
1054 ;; discard-regexp is matched 998 ;; discard-regexp is matched
1055 (if (or (and (null list) (null discard-regexp)) 999 (if (or (and (null list) (null discard-regexp))
1056 (and discard-regexp (looking-at discard-regexp))) 1000 (and discard-regexp (looking-at discard-regexp)))
1057 ;; delete the unwanted header if not doing 1001 ;; skip the unwanted header if doing
1058 ;; work for a folder buffer, otherwise 1002 ;; work for a folder buffer, otherwise
1059 ;; remember the start and end of the 1003 ;; discard the header.
1060 ;; unwanted header so we can copy it 1004 (if message
1061 ;; later. 1005 (goto-char end-of-header)
1062 (if (not message) 1006 (delete-region (point) end-of-header))
1063 (delete-region (point) end-of-header)
1064 (if (null unwanted-list)
1065 (setq unwanted-list
1066 (cons (point) (cons end-of-header nil))
1067 unwanted-tail unwanted-list)
1068 (if (= (point) (car (cdr unwanted-tail)))
1069 (setcar (cdr unwanted-tail)
1070 end-of-header)
1071 (setcdr (cdr unwanted-tail)
1072 (cons (point)
1073 (cons end-of-header nil)))
1074 (setq unwanted-tail (cdr (cdr unwanted-tail)))))
1075 (goto-char end-of-header))
1076 ;; got a match 1007 ;; got a match
1077 ;; stuff the start and end of the header 1008 ;; stuff the header into the cdr of the
1078 ;; into the cdr of the returned alist 1009 ;; returned alist element
1079 ;; element.
1080 (if list 1010 (if list
1081 ;; reverse point and end-of-header. 1011 (if (cdr list)
1082 ;; list will be nreversed later. 1012 (setcdr list
1083 (setcdr list (cons end-of-header 1013 (concat
1084 (cons (point) 1014 (cdr list)
1085 (cdr list)))) 1015 (buffer-substring (point)
1086 ;; reverse point and end-of-header. 1016 end-of-header)))
1087 ;; list will be nreversed later. 1017 (setcdr list (buffer-substring (point)
1018 end-of-header)))
1088 (setq extras 1019 (setq extras
1089 (cons end-of-header 1020 (cons (buffer-substring (point) end-of-header)
1090 (cons (point) extras)))) 1021 extras)))
1091 (goto-char end-of-header))) 1022 (delete-region (point) end-of-header)))
1092 (setq new-header-start (point))
1093 (while unwanted-list
1094 (insert-buffer-substring (current-buffer)
1095 (car unwanted-list)
1096 (car (cdr unwanted-list)))
1097 (setq unwanted-list (cdr (cdr unwanted-list))))
1098 ;; remember the offset of where the visible 1023 ;; remember the offset of where the visible
1099 ;; header start so we can initialize the 1024 ;; header start so we can initialize the
1100 ;; vm-vheaders-of field later. 1025 ;; vm-vheaders-of field later.
1101 (if message 1026 (if message
1102 (setq vheader-offset (- (point) new-header-start))) 1027 (setq vheader-offset (1- (point))))
1103 (while header-alist 1028 ;; now dump out the headers we saved.
1104 (setq list (nreverse (cdr (car header-alist)))) 1029 ;; the keep-list headers go first.
1105 (while list 1030 (setq list header-alist)
1106 (insert-buffer-substring (current-buffer) 1031 (while list
1107 (car list) 1032 (if (cdr (car list))
1108 (car (cdr list))) 1033 (progn
1109 (setq list (cdr (cdr list)))) 1034 (insert (cdr (car list)))
1110 (setq header-alist (cdr header-alist))) 1035 (setcdr (car list) nil)))
1036 (setq list (cdr list)))
1111 ;; now the headers that were not explicitly 1037 ;; now the headers that were not explicitly
1112 ;; undesirable, if any. 1038 ;; undesirable, if any.
1113 (setq extras (nreverse extras)) 1039 (if extras
1114 (while extras 1040 (progn
1115 (insert-buffer-substring (current-buffer) 1041 (setq extras (nreverse extras))
1116 (car extras) 1042 (while extras
1117 (car (cdr extras))) 1043 (insert (car extras))
1118 (setq extras (cdr (cdr extras)))) 1044 (setq extras (cdr extras)))))
1119 (delete-region old-header-start new-header-start)
1120 ;; update the folder buffer if we're supposed to. 1045 ;; update the folder buffer if we're supposed to.
1121 ;; lock out interrupts. 1046 ;; lock out interrupts.
1122 (if message 1047 (if message
1123 (let ((inhibit-quit t)) 1048 (let ((inhibit-quit t))
1124 (set-buffer (vm-buffer-of message)) 1049 (set-buffer (vm-buffer-of message))
1164 (vm-unread-count 0) 1089 (vm-unread-count 0)
1165 (vm-deleted-count 0) 1090 (vm-deleted-count 0)
1166 (vm-total-count 0) 1091 (vm-total-count 0)
1167 (modulus (+ (% (vm-abs (random)) 11) 25)) 1092 (modulus (+ (% (vm-abs (random)) 11) 25))
1168 (case-fold-search t) 1093 (case-fold-search t)
1169 oldpoint data) 1094 data)
1170 (while mp 1095 (while mp
1171 (vm-increment vm-total-count) 1096 (vm-increment vm-total-count)
1172 (if (vm-attributes-of (car mp)) 1097 (if (vm-attributes-of (car mp))
1173 () 1098 ()
1174 (goto-char (vm-headers-of (car mp))) 1099 (goto-char (vm-headers-of (car mp)))
1180 (cond 1105 (cond
1181 ((re-search-forward vm-attributes-header-regexp 1106 ((re-search-forward vm-attributes-header-regexp
1182 (vm-text-of (car mp)) t) 1107 (vm-text-of (car mp)) t)
1183 (goto-char (match-beginning 2)) 1108 (goto-char (match-beginning 2))
1184 (condition-case () 1109 (condition-case ()
1185 (progn 1110 (setq data (read (current-buffer)))
1186 (setq oldpoint (point) 1111 (error (setq data
1187 data (read (current-buffer))) 1112 (list
1188 (if (and (or (not (listp data)) (not (= 3 (length data)))) 1113 (make-vector vm-attributes-vector-length nil)
1189 (not (vectorp data))) 1114 (make-vector vm-cache-vector-length nil)
1190 (progn 1115 nil))
1191 (error "Bad x-vm-v5-data at %d in buffer %s" 1116 ;; In lieu of a valid attributes header
1192 oldpoint (buffer-name)))) 1117 ;; assume the message is new. avoid
1193 data ) 1118 ;; vm-set-new-flag because it asks for a
1194 (error 1119 ;; summary update.
1195 (message "Bad x-vm-v5-data header at %d in buffer %s, ignoring" 1120 (vm-set-new-flag-in-vector (car data) t)))
1196 oldpoint (buffer-name))
1197 (setq data
1198 (list
1199 (make-vector vm-attributes-vector-length nil)
1200 (make-vector vm-cache-vector-length nil)
1201 nil))
1202 ;; In lieu of a valid attributes header
1203 ;; assume the message is new. avoid
1204 ;; vm-set-new-flag because it asks for a
1205 ;; summary update.
1206 (vm-set-new-flag-in-vector (car data) t)))
1207 ;; support version 4 format 1121 ;; support version 4 format
1208 (cond ((vectorp data) 1122 (cond ((vectorp data)
1209 (setq data (vm-convert-v4-attributes data)) 1123 (setq data (vm-convert-v4-attributes data))
1210 ;; tink the message modflag so that if the 1124 ;; tink the message modflag so that if the
1211 ;; user saves we get rid of the old v4 1125 ;; user saves we get rid of the old v4
1272 ((vm-new-flag (car mp)) 1186 ((vm-new-flag (car mp))
1273 (vm-increment vm-new-count)) 1187 (vm-increment vm-new-count))
1274 ((vm-unread-flag (car mp)) 1188 ((vm-unread-flag (car mp))
1275 (vm-increment vm-unread-count))) 1189 (vm-increment vm-unread-count)))
1276 (if (zerop (% vm-total-count modulus)) 1190 (if (zerop (% vm-total-count modulus))
1277 (message "Reading attributes... %d" vm-total-count)) 1191 (vm-unsaved-message "Reading attributes... %d" vm-total-count))
1278 (setq mp (cdr mp))) 1192 (setq mp (cdr mp)))
1279 (if (>= vm-total-count modulus) 1193 (if (>= vm-total-count modulus)
1280 (message "Reading attributes... done")) 1194 (vm-unsaved-message "Reading attributes... done"))
1281 (if (null message-list) 1195 (if (null message-list)
1282 (setq vm-totals (list vm-modification-counter 1196 (setq vm-totals (list vm-modification-counter
1283 vm-total-count 1197 vm-total-count
1284 vm-new-count 1198 vm-new-count
1285 vm-unread-count 1199 vm-unread-count
1415 (setq lim (point)) 1329 (setq lim (point))
1416 (goto-char (point-min)) 1330 (goto-char (point-min))
1417 (vm-skip-past-folder-header) 1331 (vm-skip-past-folder-header)
1418 (vm-skip-past-leading-message-separator) 1332 (vm-skip-past-leading-message-separator)
1419 (if (re-search-forward vm-labels-header-regexp lim t) 1333 (if (re-search-forward vm-labels-header-regexp lim t)
1420 (let ((oldpoint (point)) 1334 (let (list)
1421 list) 1335 (setq list (read (current-buffer)))
1422 (condition-case ()
1423 (progn
1424 (setq list (read (current-buffer)))
1425 (if (not (listp list))
1426 (error "Bad global label list at %d in buffer %s"
1427 oldpoint (buffer-name)))
1428 list )
1429 (error
1430 (message "Bad global label list at %d in buffer %s, ignoring"
1431 oldpoint (buffer-name))
1432 (setq list nil) ))
1433 (mapcar (function 1336 (mapcar (function
1434 (lambda (s) 1337 (lambda (s)
1435 (intern s vm-label-obarray))) 1338 (intern s vm-label-obarray)))
1436 list)))))) 1339 list))))))
1437 t )) 1340 t ))
1438 1341
1439 ;; Go to the message specified in a bookmark and eat the bookmark. 1342 ;; Go to the message specified in a bookmark and eat the bookmark.
1440 ;; Returns non-nil if successful, nil otherwise. 1343 ;; Returns non-nil if successful, nil otherwise.
1441 (defun vm-gobble-bookmark () 1344 (defun vm-gobble-bookmark ()
1442 (let ((case-fold-search t) 1345 (let ((case-fold-search t)
1443 (n nil) 1346 n lim)
1444 lim oldpoint)
1445 (save-excursion 1347 (save-excursion
1446 (vm-save-restriction 1348 (vm-save-restriction
1447 (widen) 1349 (widen)
1448 (goto-char (point-min)) 1350 (goto-char (point-min))
1449 (vm-skip-past-folder-header) 1351 (vm-skip-past-folder-header)
1452 (setq lim (point)) 1354 (setq lim (point))
1453 (goto-char (point-min)) 1355 (goto-char (point-min))
1454 (vm-skip-past-folder-header) 1356 (vm-skip-past-folder-header)
1455 (vm-skip-past-leading-message-separator) 1357 (vm-skip-past-leading-message-separator)
1456 (if (re-search-forward vm-bookmark-header-regexp lim t) 1358 (if (re-search-forward vm-bookmark-header-regexp lim t)
1457 (condition-case () 1359 (setq n (read (current-buffer))))))
1458 (progn
1459 (setq oldpoint (point)
1460 n (read (current-buffer)))
1461 (if (not (natnump n))
1462 (error "Bad bookmark at %d in buffer %s"
1463 oldpoint (buffer-name)))
1464 n )
1465 (error
1466 (message "Bad bookmark at %d in buffer %s, ignoring"
1467 oldpoint (buffer-name))
1468 (setq n 1))))))
1469 (if n 1360 (if n
1470 (vm-record-and-change-message-pointer 1361 (vm-record-and-change-message-pointer
1471 vm-message-pointer 1362 vm-message-pointer
1472 (nthcdr (1- n) vm-message-list))) 1363 (nthcdr (1- n) vm-message-list)))
1473 t )) 1364 t ))
1497 ;; folder was saved, then we have to discard any cached 1388 ;; folder was saved, then we have to discard any cached
1498 ;; vheader info so the user will see the right headers. 1389 ;; vheader info so the user will see the right headers.
1499 (and got (or (not (equal vis vm-visible-headers)) 1390 (and got (or (not (equal vis vm-visible-headers))
1500 (not (equal invis vm-invisible-header-regexp))) 1391 (not (equal invis vm-invisible-header-regexp)))
1501 (let ((mp vm-message-list)) 1392 (let ((mp vm-message-list))
1502 (message "Discarding visible header info...") 1393 (vm-unsaved-message "Discarding visible header info...")
1503 (while mp 1394 (while mp
1504 (vm-set-vheaders-regexp-of (car mp) nil) 1395 (vm-set-vheaders-regexp-of (car mp) nil)
1505 (vm-set-vheaders-of (car mp) nil) 1396 (vm-set-vheaders-of (car mp) nil)
1506 (setq mp (cdr mp))))))))))) 1397 (setq mp (cdr mp)))))))))))
1507 1398
1522 (setq lim (point)) 1413 (setq lim (point))
1523 (goto-char (point-min)) 1414 (goto-char (point-min))
1524 (vm-skip-past-folder-header) 1415 (vm-skip-past-folder-header)
1525 (vm-skip-past-leading-message-separator) 1416 (vm-skip-past-leading-message-separator)
1526 (if (re-search-forward vm-message-order-header-regexp lim t) 1417 (if (re-search-forward vm-message-order-header-regexp lim t)
1527 (let ((oldpoint (point))) 1418 (progn
1528 (message "Reordering messages...") 1419 (vm-unsaved-message "Reordering messages...")
1529 (condition-case nil 1420 (setq order (read (current-buffer))
1530 (progn 1421 list-length (length vm-message-list)
1531 (setq order (read (current-buffer)))
1532 (if (not (listp order))
1533 (error "Bad order header at %d in buffer %s"
1534 oldpoint (buffer-name)))
1535 order )
1536 (error
1537 (message "Bad order header at %d in buffer %s, ignoring"
1538 oldpoint (buffer-name))
1539 (setq order nil)))
1540 (setq list-length (length vm-message-list)
1541 v (make-vector (max list-length (length order)) nil)) 1422 v (make-vector (max list-length (length order)) nil))
1542 (while (and order mp) 1423 (while (and order mp)
1543 (condition-case nil 1424 (aset v (1- (car order)) (car mp))
1544 (aset v (1- (car order)) (car mp))
1545 (args-out-of-range nil))
1546 (setq order (cdr order) mp (cdr mp))) 1425 (setq order (cdr order) mp (cdr mp)))
1547 ;; lock out interrupts while the message list is in 1426 ;; lock out interrupts while the message list is in
1548 ;; an inconsistent state. 1427 ;; an inconsistent state.
1549 (let ((inhibit-quit t)) 1428 (let ((inhibit-quit t))
1550 (setq vm-message-list (delq nil (append v mp)) 1429 (setq vm-message-list (delq nil (append v mp))
1552 vm-message-order-header-present t 1431 vm-message-order-header-present t
1553 vm-message-pointer (memq (car vm-message-pointer) 1432 vm-message-pointer (memq (car vm-message-pointer)
1554 vm-message-list)) 1433 vm-message-list))
1555 (vm-set-numbering-redo-start-point t) 1434 (vm-set-numbering-redo-start-point t)
1556 (vm-reverse-link-messages)) 1435 (vm-reverse-link-messages))
1557 (message "Reordering messages... done"))))))) 1436 (vm-unsaved-message "Reordering messages... done")))))))
1558 1437
1559 ;; Read the header that gives the folder's cached summary format 1438 ;; Read the header that gives the folder's cached summary format
1560 ;; If the current summary format is different, then the cached 1439 ;; If the current summary format is different, then the cached
1561 ;; summary lines are discarded. 1440 ;; summary lines are discarded.
1562 (defun vm-gobble-summary () 1441 (defun vm-gobble-summary ()
1573 (setq lim (point)) 1452 (setq lim (point))
1574 (goto-char (point-min)) 1453 (goto-char (point-min))
1575 (vm-skip-past-folder-header) 1454 (vm-skip-past-folder-header)
1576 (vm-skip-past-leading-message-separator) 1455 (vm-skip-past-leading-message-separator)
1577 (if (re-search-forward vm-summary-header-regexp lim t) 1456 (if (re-search-forward vm-summary-header-regexp lim t)
1578 (let ((oldpoint (point))) 1457 (progn
1579 (condition-case () 1458 (setq summary (read (current-buffer)))
1580 (setq summary (read (current-buffer)))
1581 (error
1582 (message "Bad summary header at %d in buffer %s, ignoring"
1583 oldpoint (buffer-name))
1584 (setq summary "")))
1585 (if (not (equal summary vm-summary-format)) 1459 (if (not (equal summary vm-summary-format))
1586 (while mp 1460 (while mp
1587 (vm-set-summary-of (car mp) nil) 1461 (vm-set-summary-of (car mp) nil)
1588 ;; force restuffing of cache to clear old 1462 ;; force restuffing of cache to clear old
1589 ;; summary entry cache. 1463 ;; summary entry cache.
1655 "O\n") 1529 "O\n")
1656 (set-marker (vm-headers-of m) opoint))))) 1530 (set-marker (vm-headers-of m) opoint)))))
1657 (vm-set-modflag-of m nil)) 1531 (vm-set-modflag-of m nil))
1658 (set-buffer-modified-p old-buffer-modified-p)))))) 1532 (set-buffer-modified-p old-buffer-modified-p))))))
1659 1533
1660 (defun vm-stuff-folder-attributes (&optional abort-if-input-pending)
1661 (let ((newlist nil) mp)
1662 ;; stuff the attributes of messages that need it.
1663 ;; build a list of messages that need their attributes stuffed
1664 (setq mp vm-message-list)
1665 (while mp
1666 (if (vm-modflag-of (car mp))
1667 (setq newlist (cons (car mp) newlist)))
1668 (setq mp (cdr mp)))
1669 ;; now sort the list by physical order so that we
1670 ;; reduce the amount of gap motion induced by modifying
1671 ;; the buffer. what we want to avoid is updating
1672 ;; message 3, then 234, then 10, then 500, thus causing
1673 ;; large chunks of memory to be copied repeatedly as
1674 ;; the gap moves to accomodate the insertions.
1675 (let ((vm-key-functions '(vm-sort-compare-physical-order-r)))
1676 (setq mp (sort newlist 'vm-sort-compare-xxxxxx)))
1677 (while (and mp (or (not abort-if-input-pending) (not (input-pending-p))))
1678 (vm-stuff-attributes (car mp))
1679 (setq mp (cdr mp)))
1680 (if mp nil t)))
1681
1682 ;; we can be a bit lazy in this function since it's only called 1534 ;; we can be a bit lazy in this function since it's only called
1683 ;; from within vm-stuff-attributes. we don't worry about 1535 ;; from within vm-stuff-attributes. we don't worry about
1684 ;; restoring the modified flag, setting buffer-read-only, or 1536 ;; restoring the modified flag, setting buffer-read-only, or
1685 ;; about not moving point. 1537 ;; about not moving point.
1686 (defun vm-stuff-babyl-attributes (m for-other-folder) 1538 (defun vm-stuff-babyl-attributes (m for-other-folder)
2073 (interactive) 1925 (interactive)
2074 (vm-select-folder-buffer) 1926 (vm-select-folder-buffer)
2075 (if (not (memq major-mode '(vm-mode vm-virtual-mode))) 1927 (if (not (memq major-mode '(vm-mode vm-virtual-mode)))
2076 (error "%s must be invoked from a VM buffer." this-command)) 1928 (error "%s must be invoked from a VM buffer." this-command))
2077 (vm-check-for-killed-summary) 1929 (vm-check-for-killed-summary)
2078 (vm-check-for-killed-presentation) 1930
2079 1931 (run-hooks 'vm-quit-hook)
2080 (save-excursion (run-hooks 'vm-quit-hook))
2081
2082 (vm-garbage-collect-message)
2083 1932
2084 (vm-display nil nil '(vm-quit-just-bury) 1933 (vm-display nil nil '(vm-quit-just-bury)
2085 '(vm-quit-just-bury quitting)) 1934 '(vm-quit-just-bury quitting))
2086 (if vm-summary-buffer 1935 (if vm-summary-buffer
2087 (vm-display vm-summary-buffer nil nil nil)) 1936 (vm-display vm-summary-buffer nil nil nil))
2088 (if vm-summary-buffer 1937 (if vm-summary-buffer
2089 (vm-bury-buffer vm-summary-buffer)) 1938 (vm-bury-buffer vm-summary-buffer))
2090 (if vm-presentation-buffer-handle
2091 (vm-display vm-presentation-buffer-handle nil nil nil))
2092 (if vm-presentation-buffer-handle
2093 (vm-bury-buffer vm-presentation-buffer-handle))
2094 (vm-display (current-buffer) nil nil nil) 1939 (vm-display (current-buffer) nil nil nil)
2095 (vm-bury-buffer (current-buffer))) 1940 (vm-bury-buffer (current-buffer)))
2096 1941
2097 (defun vm-quit-just-iconify () 1942 (defun vm-quit-just-iconify ()
2098 "Iconify the frame and bury the current VM folder and summary buffers. 1943 "Iconify the frame and bury the current VM folder and summary buffers.
2100 (interactive) 1945 (interactive)
2101 (vm-select-folder-buffer) 1946 (vm-select-folder-buffer)
2102 (if (not (memq major-mode '(vm-mode vm-virtual-mode))) 1947 (if (not (memq major-mode '(vm-mode vm-virtual-mode)))
2103 (error "%s must be invoked from a VM buffer." this-command)) 1948 (error "%s must be invoked from a VM buffer." this-command))
2104 (vm-check-for-killed-summary) 1949 (vm-check-for-killed-summary)
2105 (vm-check-for-killed-presentation) 1950
2106 1951 (run-hooks 'vm-quit-hook)
2107 (save-excursion (run-hooks 'vm-quit-hook))
2108
2109 (vm-garbage-collect-message)
2110 1952
2111 (vm-display nil nil '(vm-quit-just-iconify) 1953 (vm-display nil nil '(vm-quit-just-iconify)
2112 '(vm-quit-just-iconify quitting)) 1954 '(vm-quit-just-iconify quitting))
2113 (let ((summary-buffer vm-summary-buffer) 1955 (vm-bury-buffer (current-buffer))
2114 (pres-buffer vm-presentation-buffer-handle)) 1956 (if vm-summary-buffer
2115 (vm-bury-buffer (current-buffer)) 1957 (vm-bury-buffer vm-summary-buffer))
2116 (if summary-buffer 1958 (vm-iconify-frame))
2117 (vm-bury-buffer summary-buffer))
2118 (if pres-buffer
2119 (vm-bury-buffer pres-buffer))
2120 (vm-iconify-frame)))
2121 1959
2122 (defun vm-quit-no-change () 1960 (defun vm-quit-no-change ()
2123 "Quit visiting the current folder without saving changes made to the folder." 1961 "Exit VM without saving changes made to the folder."
2124 (interactive) 1962 (interactive)
2125 (vm-quit t)) 1963 (vm-quit t))
2126 1964
2127 (defun vm-quit (&optional no-change) 1965 (defun vm-quit (&optional no-change)
2128 "Quit visiting the current folder, saving changes. Deleted messages are not expunged." 1966 "Quit VM, saving changes. Deleted messages are not expunged."
2129 (interactive) 1967 (interactive)
2130 (vm-select-folder-buffer) 1968 (vm-select-folder-buffer)
2131 (if (not (memq major-mode '(vm-mode vm-virtual-mode))) 1969 (if (not (memq major-mode '(vm-mode vm-virtual-mode)))
2132 (error "%s must be invoked from a VM buffer." this-command)) 1970 (error "%s must be invoked from a VM buffer." this-command))
2133 (vm-check-for-killed-summary) 1971 (vm-check-for-killed-summary)
2134 (vm-check-for-killed-presentation)
2135 (vm-display nil nil '(vm-quit vm-quit-no-change) 1972 (vm-display nil nil '(vm-quit vm-quit-no-change)
2136 (list this-command 'quitting)) 1973 (list this-command 'quitting))
2137 (let ((virtual (eq major-mode 'vm-virtual-mode))) 1974 (let ((virtual (eq major-mode 'vm-virtual-mode)))
2138 (cond 1975 (cond
2139 ((and (not virtual) no-change (buffer-modified-p) 1976 ((and (not virtual) no-change (buffer-modified-p)
2140 (or buffer-file-name buffer-offer-save)
2141 (not (zerop vm-messages-not-on-disk)) 1977 (not (zerop vm-messages-not-on-disk))
2142 ;; Folder may have been saved with C-x C-s and attributes may have 1978 ;; Folder may have been saved with C-x C-s and attributes may have
2143 ;; been changed after that; in that case vm-messages-not-on-disk 1979 ;; been changed after that; in that case vm-messages-not-on-disk
2144 ;; would not have been zeroed. However, all modification flag 1980 ;; would not have been zeroed. However, all modification flag
2145 ;; undos are cleared if VM actually modifies the folder buffer 1981 ;; undos are cleared if VM actually modifies the folder buffer
2152 "%d message%s have not been saved to disk, quit anyway? " 1988 "%d message%s have not been saved to disk, quit anyway? "
2153 vm-messages-not-on-disk 1989 vm-messages-not-on-disk
2154 (if (= 1 vm-messages-not-on-disk) "" "s"))))) 1990 (if (= 1 vm-messages-not-on-disk) "" "s")))))
2155 (error "Aborted")) 1991 (error "Aborted"))
2156 ((and (not virtual) 1992 ((and (not virtual)
2157 no-change 1993 no-change (buffer-modified-p) vm-confirm-quit
2158 (or buffer-file-name buffer-offer-save)
2159 (buffer-modified-p)
2160 vm-confirm-quit
2161 (not (y-or-n-p "There are unsaved changes, quit anyway? "))) 1994 (not (y-or-n-p "There are unsaved changes, quit anyway? ")))
2162 (error "Aborted")) 1995 (error "Aborted"))
2163 ((and (eq vm-confirm-quit t) 1996 ((and (eq vm-confirm-quit t)
2164 (not (y-or-n-p "Do you really want to quit? "))) 1997 (not (y-or-n-p "Do you really want to quit? ")))
2165 (error "Aborted"))) 1998 (error "Aborted")))
2166 1999
2167 (save-excursion (run-hooks 'vm-quit-hook)) 2000 (run-hooks 'vm-quit-hook)
2168
2169 (vm-garbage-collect-message)
2170 (vm-garbage-collect-folder)
2171 2001
2172 (vm-virtual-quit) 2002 (vm-virtual-quit)
2173 (if (and (not no-change) (not virtual)) 2003 (if (and (not no-change) (not virtual))
2174 (progn 2004 (progn
2175 ;; this could take a while, so give the user some feedback 2005 ;; this could take a while, so give the user some feedback
2176 (message "Quitting...") 2006 (vm-unsaved-message "Quitting...")
2177 (or vm-folder-read-only (eq major-mode 'vm-virtual-mode) 2007 (or vm-folder-read-only (eq major-mode 'vm-virtual-mode)
2178 (vm-change-all-new-to-unread)))) 2008 (vm-change-all-new-to-unread))))
2179 (if (and (buffer-modified-p) 2009 (if (and (buffer-modified-p) (not no-change) (not virtual))
2180 (or buffer-file-name buffer-offer-save)
2181 (not no-change)
2182 (not virtual))
2183 (vm-save-folder)) 2010 (vm-save-folder))
2184 (message "") 2011 (vm-unsaved-message "")
2185 (let ((summary-buffer vm-summary-buffer) 2012 (let ((summary-buffer vm-summary-buffer)
2186 (pres-buffer vm-presentation-buffer-handle)
2187 (mail-buffer (current-buffer))) 2013 (mail-buffer (current-buffer)))
2188 (if summary-buffer 2014 (if summary-buffer
2189 (progn 2015 (progn
2190 (vm-display summary-buffer nil nil nil) 2016 (vm-display vm-summary-buffer nil nil nil)
2191 (kill-buffer summary-buffer))) 2017 (kill-buffer summary-buffer)))
2192 (if pres-buffer
2193 (progn
2194 (vm-display pres-buffer nil nil nil)
2195 (kill-buffer pres-buffer)))
2196 (set-buffer mail-buffer) 2018 (set-buffer mail-buffer)
2197 (vm-display mail-buffer nil nil nil) 2019 (vm-display mail-buffer nil nil nil)
2198 ;; vm-display is not supposed to change the current buffer. 2020 ;; vm-display is not supposed to change the current buffer.
2199 ;; still it's better to be safe here. 2021 ;; still better to be safe here.
2200 (set-buffer mail-buffer) 2022 (set-buffer mail-buffer)
2201 (set-buffer-modified-p nil) 2023 (set-buffer-modified-p nil)
2202 (kill-buffer (current-buffer))) 2024 (kill-buffer (current-buffer)))
2203 (vm-update-summary-and-mode-line))) 2025 (vm-update-summary-and-mode-line)))
2204 2026
2205 (defun vm-start-itimers-if-needed () 2027 (defun vm-start-itimers-if-needed ()
2206 (cond ((and (not (natnump vm-flush-interval)) 2028 (if (or (natnump vm-flush-interval)
2207 (not (natnump vm-auto-get-new-mail)) 2029 (natnump vm-auto-get-new-mail))
2208 (not (natnump vm-mail-check-interval)))) 2030 (progn
2209 ((condition-case data 2031 (if (null
2210 (progn (require 'itimer) t) 2032 (condition-case data
2211 (error nil)) 2033 (progn (require 'itimer) t)
2212 (and (natnump vm-flush-interval) (not (get-itimer "vm-flush")) 2034 (error nil)))
2213 (start-itimer "vm-flush" 'vm-flush-itimer-function 2035 (setq vm-flush-interval t
2214 vm-flush-interval nil)) 2036 vm-auto-get-new-mail t)
2215 (and (natnump vm-auto-get-new-mail) (not (get-itimer "vm-get-mail")) 2037 (and (natnump vm-flush-interval) (not (get-itimer "vm-flush"))
2216 (start-itimer "vm-get-mail" 'vm-get-mail-itimer-function 2038 (start-itimer "vm-flush" 'vm-flush-itimer-function
2217 vm-auto-get-new-mail nil)) 2039 vm-flush-interval nil))
2218 (and (natnump vm-mail-check-interval) 2040 (and (natnump vm-auto-get-new-mail) (not (get-itimer "vm-get-mail"))
2219 (not (get-itimer "vm-check-mail")) 2041 (start-itimer "vm-get-mail" 'vm-get-mail-itimer-function
2220 (start-itimer "vm-check-mail" 'vm-check-mail-itimer-function 2042 vm-auto-get-new-mail nil))))))
2221 vm-mail-check-interval nil))) 2043
2222 ((condition-case data 2044 ;; support for numeric vm-auto-get-new-mail
2223 (progn (require 'timer) t) 2045 (defun vm-get-mail-itimer-function ()
2224 (error nil)) 2046 (if (integerp vm-auto-get-new-mail)
2225 (let (timer) 2047 (set-itimer-restart current-itimer vm-auto-get-new-mail))
2226 (and (natnump vm-flush-interval) 2048 (let ((b-list (buffer-list)))
2227 (not (vm-timer-using 'vm-flush-itimer-function))
2228 (setq timer (run-at-time vm-flush-interval vm-flush-interval
2229 'vm-flush-itimer-function nil))
2230 (timer-set-function timer 'vm-flush-itimer-function
2231 (list timer)))
2232 (and (natnump vm-mail-check-interval)
2233 (not (vm-timer-using 'vm-check-mail-itimer-function))
2234 (setq timer (run-at-time vm-mail-check-interval
2235 vm-mail-check-interval
2236 'vm-check-mail-itimer-function nil))
2237 (timer-set-function timer 'vm-check-mail-itimer-function
2238 (list timer)))
2239 (and (natnump vm-auto-get-new-mail)
2240 (not (vm-timer-using 'vm-get-mail-itimer-function))
2241 (setq timer (run-at-time vm-auto-get-new-mail
2242 vm-auto-get-new-mail
2243 'vm-get-mail-itimer-function nil))
2244 (timer-set-function timer 'vm-get-mail-itimer-function
2245 (list timer)))))
2246 (t
2247 (setq vm-flush-interval t
2248 vm-auto-get-new-mail t))))
2249
2250 (defun vm-timer-using (fun)
2251 (let ((p timer-list)
2252 (done nil))
2253 (while (and p (not done))
2254 (if (eq (aref (car p) 5) fun)
2255 (setq done t)
2256 (setq p (cdr p))))
2257 p ))
2258
2259 ;; support for vm-mail-check-interval
2260 ;; if timer argument is present, this means we're using the Emacs
2261 ;; 'timer package rather than the 'itimer package.
2262 (defun vm-check-mail-itimer-function (&optional timer)
2263 ;; FSF Emacs sets this non-nil, which means the user can't
2264 ;; interrupt the check. Bogus.
2265 (setq inhibit-quit nil)
2266 (if (integerp vm-mail-check-interval)
2267 (if timer
2268 (timer-set-time timer (current-time) vm-mail-check-interval)
2269 (set-itimer-restart current-itimer vm-mail-check-interval))
2270 ;; user has changed the variable value to something that
2271 ;; isn't a number, make the timer go away.
2272 (if timer
2273 (cancel-timer timer)
2274 (set-itimer-restart current-itimer nil)))
2275 (let ((b-list (buffer-list))
2276 (found-one nil)
2277 oldval)
2278 (while (and (not (input-pending-p)) b-list) 2049 (while (and (not (input-pending-p)) b-list)
2279 (save-excursion 2050 (save-excursion
2280 (set-buffer (car b-list)) 2051 (set-buffer (car b-list))
2281 (if (and (eq major-mode 'vm-mode) 2052 (if (and (eq major-mode 'vm-mode)
2282 (setq found-one t)
2283 ;; to avoid reentrance into the pop code
2284 (not vm-block-new-mail)
2285 ;; Don't bother checking if we already know from
2286 ;; a previous check that there's mail waiting
2287 ;; and the user hasn't retrieved it yet. Not
2288 ;; completely accurate, but saves network
2289 ;; connection build and tear down which is slow
2290 ;; for some users.
2291 (not vm-spooled-mail-waiting))
2292 (progn
2293 (setq oldval vm-spooled-mail-waiting)
2294 (vm-check-for-spooled-mail nil)
2295 (if (not (eq oldval vm-spooled-mail-waiting))
2296 (progn
2297 (intern (buffer-name) vm-buffers-needing-display-update)
2298 (vm-update-summary-and-mode-line))))))
2299 (setq b-list (cdr b-list)))
2300 ;; make the timer go away if we didn't encounter a vm-mode buffer.
2301 (if (and (not found-one) (null b-list))
2302 (if timer
2303 (cancel-timer timer)
2304 (set-itimer-restart current-itimer nil)))))
2305
2306 ;; support for numeric vm-auto-get-new-mail
2307 ;; if timer argument is present, this means we're using the Emacs
2308 ;; 'timer package rather than the 'itimer package.
2309 (defun vm-get-mail-itimer-function (&optional timer)
2310 ;; FSF Emacs sets this non-nil, which means the user can't
2311 ;; interrupt mail retrieval. Bogus.
2312 (setq inhibit-quit nil)
2313 (if (integerp vm-auto-get-new-mail)
2314 (if timer
2315 (timer-set-time timer (current-time) vm-auto-get-new-mail)
2316 (set-itimer-restart current-itimer vm-auto-get-new-mail))
2317 ;; user has changed the variable value to something that
2318 ;; isn't a number, make the timer go away.
2319 (if timer
2320 (cancel-timer timer)
2321 (set-itimer-restart current-itimer nil)))
2322 (let ((b-list (buffer-list))
2323 (found-one nil))
2324 (while (and (not (input-pending-p)) b-list)
2325 (save-excursion
2326 (set-buffer (car b-list))
2327 (if (and (eq major-mode 'vm-mode)
2328 (setq found-one t)
2329 (not (and (not (buffer-modified-p)) 2053 (not (and (not (buffer-modified-p))
2330 buffer-file-name 2054 buffer-file-name
2331 (file-newer-than-file-p 2055 (file-newer-than-file-p
2332 (make-auto-save-file-name) 2056 (make-auto-save-file-name)
2333 buffer-file-name))) 2057 buffer-file-name)))
2334 (not vm-block-new-mail) 2058 (not vm-block-new-mail)
2335 (not vm-folder-read-only) 2059 (not vm-folder-read-only)
2336 (vm-get-spooled-mail nil) 2060 (vm-get-spooled-mail)
2337 (vm-assimilate-new-messages t)) 2061 (vm-assimilate-new-messages t))
2338 (progn 2062 (progn
2339 ;; don't move the message pointer unless the folder 2063 ;; don't move the message pointer unless the folder
2340 ;; was empty. 2064 ;; was empty.
2341 (if (and (null vm-message-pointer) 2065 (if (and (null vm-message-pointer)
2342 (vm-thoughtfully-select-message)) 2066 (vm-thoughtfully-select-message))
2343 (vm-preview-current-message) 2067 (vm-preview-current-message)
2344 (vm-update-summary-and-mode-line))))) 2068 (vm-update-summary-and-mode-line)))))
2345 (setq b-list (cdr b-list))) 2069 (setq b-list (cdr b-list)))))
2346 ;; make the timer go away if we didn't encounter a vm-mode buffer.
2347 (if (and (not found-one) (null b-list))
2348 (if timer
2349 (cancel-timer timer)
2350 (set-itimer-restart current-itimer nil)))))
2351 2070
2352 ;; support for numeric vm-flush-interval 2071 ;; support for numeric vm-flush-interval
2353 ;; if timer argument is present, this means we're using the Emacs 2072 (defun vm-flush-itimer-function ()
2354 ;; 'timer package rather than the 'itimer package.
2355 (defun vm-flush-itimer-function (&optional timer)
2356 (if (integerp vm-flush-interval) 2073 (if (integerp vm-flush-interval)
2357 (if timer 2074 (set-itimer-restart current-itimer vm-flush-interval))
2358 (timer-set-time timer (current-time) vm-flush-interval)
2359 (set-itimer-restart current-itimer vm-flush-interval)))
2360 ;; if no vm-mode buffers are found, we might as well shut down the 2075 ;; if no vm-mode buffers are found, we might as well shut down the
2361 ;; flush itimer. 2076 ;; flush itimer.
2362 (if (not (vm-flush-cached-data)) 2077 (if (not (vm-flush-cached-data))
2363 (if timer 2078 (set-itimer-restart current-itimer nil)))
2364 (cancel-timer timer)
2365 (set-itimer-restart current-itimer nil))))
2366 2079
2367 ;; flush cached data in all vm-mode buffers. 2080 ;; flush cached data in all vm-mode buffers.
2368 ;; returns non-nil if any vm-mode buffers were found. 2081 ;; returns non-nil if any vm-mode buffers were found.
2369 (defun vm-flush-cached-data () 2082 (defun vm-flush-cached-data ()
2370 (save-excursion 2083 (save-excursion
2374 (set-buffer (car buf-list)) 2087 (set-buffer (car buf-list))
2375 (cond ((and (eq major-mode 'vm-mode) vm-message-list) 2088 (cond ((and (eq major-mode 'vm-mode) vm-message-list)
2376 (setq found-one t) 2089 (setq found-one t)
2377 (if (not (eq vm-modification-counter 2090 (if (not (eq vm-modification-counter
2378 vm-flushed-modification-counter)) 2091 vm-flushed-modification-counter))
2379 (progn 2092 (let ((mp vm-message-list))
2380 (vm-stuff-summary) 2093 (vm-stuff-summary)
2381 (vm-stuff-labels) 2094 (vm-stuff-labels)
2382 (and vm-message-order-changed 2095 (and vm-message-order-changed
2383 (vm-stuff-message-order)) 2096 (vm-stuff-message-order))
2384 (and (vm-stuff-folder-attributes t) 2097 (while (and mp (not (input-pending-p)))
2098 (if (vm-modflag-of (car mp))
2099 (vm-stuff-attributes (car mp)))
2100 (setq mp (cdr mp)))
2101 (and (null mp)
2385 (setq vm-flushed-modification-counter 2102 (setq vm-flushed-modification-counter
2386 vm-modification-counter)))))) 2103 vm-modification-counter))))))
2387 (setq buf-list (cdr buf-list))) 2104 (setq buf-list (cdr buf-list)))
2388 ;; if we haven't checked them all return non-nil so 2105 ;; if we haven't checked them all return non-nil so
2389 ;; the flusher won't give up trying. 2106 ;; the flusher won't give up trying.
2395 (if (and (eq major-mode 'vm-mode) (not vm-inhibit-write-file-hook)) 2112 (if (and (eq major-mode 'vm-mode) (not vm-inhibit-write-file-hook))
2396 ;; The vm-save-restriction isn't really necessary here, since 2113 ;; The vm-save-restriction isn't really necessary here, since
2397 ;; the stuff routines clean up after themselves, but should remain 2114 ;; the stuff routines clean up after themselves, but should remain
2398 ;; as a safeguard against the time when other stuff is added here. 2115 ;; as a safeguard against the time when other stuff is added here.
2399 (vm-save-restriction 2116 (vm-save-restriction
2400 (let ((buffer-read-only)) 2117 (let ((mp vm-message-list)
2401 (vm-stuff-folder-attributes nil) 2118 (buffer-read-only))
2402 (if vm-message-list 2119 (while mp
2403 (progn 2120 (if (vm-modflag-of (car mp))
2404 ;; get summary cache up-to-date 2121 (vm-stuff-attributes (car mp)))
2405 (vm-update-summary-and-mode-line) 2122 (setq mp (cdr mp)))
2406 (vm-stuff-bookmark) 2123 (if vm-message-list
2407 (vm-stuff-header-variables) 2124 (progn
2408 (vm-stuff-labels) 2125 ;; get summary cache up-to-date
2409 (vm-stuff-summary) 2126 (vm-update-summary-and-mode-line)
2410 (and vm-message-order-changed 2127 (vm-stuff-bookmark)
2411 (vm-stuff-message-order)))) 2128 (vm-stuff-header-variables)
2412 nil )))) 2129 (vm-stuff-labels)
2130 (vm-stuff-summary)
2131 (and vm-message-order-changed
2132 (vm-stuff-message-order))))
2133 nil ))))
2413 2134
2414 (defun vm-save-buffer (prefix) 2135 (defun vm-save-buffer (prefix)
2415 (interactive "P") 2136 (interactive "P")
2416 (vm-select-folder-buffer) 2137 (vm-select-folder-buffer)
2417 (vm-error-if-virtual-folder) 2138 (vm-error-if-virtual-folder)
2444 (vm-check-for-killed-summary) 2165 (vm-check-for-killed-summary)
2445 (vm-display nil nil '(vm-save-folder) '(vm-save-folder)) 2166 (vm-display nil nil '(vm-save-folder) '(vm-save-folder))
2446 (if (eq major-mode 'vm-virtual-mode) 2167 (if (eq major-mode 'vm-virtual-mode)
2447 (vm-virtual-save-folder prefix) 2168 (vm-virtual-save-folder prefix)
2448 (if (buffer-modified-p) 2169 (if (buffer-modified-p)
2449 (let (mp (newlist nil)) 2170 (let (mp)
2450 ;; stuff the attributes of messages that need it. 2171 ;; stuff the attributes of messages that need it.
2451 (message "Stuffing attributes...") 2172 (vm-unsaved-message "Stuffing attributes...")
2452 (vm-stuff-folder-attributes nil) 2173 (setq mp vm-message-list)
2174 (while mp
2175 (if (vm-modflag-of (car mp))
2176 (vm-stuff-attributes (car mp)))
2177 (setq mp (cdr mp)))
2453 ;; stuff bookmark and header variable values 2178 ;; stuff bookmark and header variable values
2454 (if vm-message-list 2179 (if vm-message-list
2455 (progn 2180 (progn
2456 ;; get summary cache up-to-date 2181 ;; get summary cache up-to-date
2457 (vm-update-summary-and-mode-line) 2182 (vm-update-summary-and-mode-line)
2459 (vm-stuff-header-variables) 2184 (vm-stuff-header-variables)
2460 (vm-stuff-labels) 2185 (vm-stuff-labels)
2461 (vm-stuff-summary) 2186 (vm-stuff-summary)
2462 (and vm-message-order-changed 2187 (and vm-message-order-changed
2463 (vm-stuff-message-order)))) 2188 (vm-stuff-message-order))))
2464 (message "Saving...") 2189 (vm-unsaved-message "Saving...")
2465 (let ((vm-inhibit-write-file-hook t)) 2190 (let ((vm-inhibit-write-file-hook t))
2466 (save-buffer prefix)) 2191 (save-buffer prefix))
2467 (vm-set-buffer-modified-p nil) 2192 (vm-set-buffer-modified-p nil)
2468 (vm-clear-modification-flag-undos) 2193 (vm-clear-modification-flag-undos)
2469 (setq vm-messages-not-on-disk 0) 2194 (setq vm-messages-not-on-disk 0)
2475 (y-or-n-p (format "%s is empty, remove it? " 2200 (y-or-n-p (format "%s is empty, remove it? "
2476 (or buffer-file-name (buffer-name))))) 2201 (or buffer-file-name (buffer-name)))))
2477 (condition-case () 2202 (condition-case ()
2478 (progn 2203 (progn
2479 (delete-file buffer-file-name) 2204 (delete-file buffer-file-name)
2480 (clear-visited-file-modtime)
2481 (message "%s removed" buffer-file-name)) 2205 (message "%s removed" buffer-file-name))
2482 ;; no can do, oh well. 2206 ;; no can do, oh well.
2483 (error nil))) 2207 (error nil)))
2484 (vm-update-summary-and-mode-line)) 2208 (vm-update-summary-and-mode-line))
2485 (message "No changes need to be saved")))) 2209 (message "No changes need to be saved"))))
2496 (vm-check-for-killed-summary) 2220 (vm-check-for-killed-summary)
2497 (vm-display nil nil '(vm-save-and-expunge-folder) 2221 (vm-display nil nil '(vm-save-and-expunge-folder)
2498 '(vm-save-and-expunge-folder)) 2222 '(vm-save-and-expunge-folder))
2499 (if (not vm-folder-read-only) 2223 (if (not vm-folder-read-only)
2500 (progn 2224 (progn
2501 (message "Expunging...") 2225 (vm-unsaved-message "Expunging...")
2502 (vm-expunge-folder t))) 2226 (vm-expunge-folder t)))
2503 (vm-save-folder prefix)) 2227 (vm-save-folder prefix))
2504 2228
2505 (defun vm-handle-file-recovery-or-reversion (recovery) 2229 (defun vm-handle-file-recovery-or-reversion (recovery)
2506 (if (and vm-summary-buffer (buffer-name vm-summary-buffer)) 2230 (if (and vm-summary-buffer (buffer-name vm-summary-buffer))
2545 "Display help for various VM activities." 2269 "Display help for various VM activities."
2546 (interactive) 2270 (interactive)
2547 (if (eq major-mode 'vm-summary-mode) 2271 (if (eq major-mode 'vm-summary-mode)
2548 (vm-select-folder-buffer)) 2272 (vm-select-folder-buffer))
2549 (let ((pop-up-windows (and pop-up-windows (eq vm-mutable-windows t))) 2273 (let ((pop-up-windows (and pop-up-windows (eq vm-mutable-windows t)))
2550 (pop-up-frames (and vm-mutable-frames vm-frame-per-help))) 2274 (pop-up-frames vm-mutable-frames))
2551 (cond 2275 (cond
2552 ((eq last-command 'vm-help) 2276 ((eq last-command 'vm-help)
2553 (describe-function major-mode)) 2277 (describe-function major-mode))
2554 ((eq vm-system-state 'previewing) 2278 ((eq vm-system-state 'previewing)
2555 (message "Type SPC to read message, n previews next message (? gives more help)")) 2279 (message "Type SPC to read message, n previews next message (? gives more help)"))
2560 (substitute-command-keys 2284 (substitute-command-keys
2561 "Type \\[vm-edit-message-end] to end edit, \\[vm-edit-message-abort] to abort with no change."))) 2285 "Type \\[vm-edit-message-end] to end edit, \\[vm-edit-message-abort] to abort with no change.")))
2562 ((eq major-mode 'mail-mode) 2286 ((eq major-mode 'mail-mode)
2563 (message 2287 (message
2564 (substitute-command-keys 2288 (substitute-command-keys
2565 "Type \\[vm-mail-send-and-exit] to send message, \\[kill-buffer] to discard this composition"))) 2289 "Type \\[vm-mail-send-and-exit] to send message, \\[kill-buffer] to discard this message")))
2566 (t (describe-mode))))) 2290 (t (describe-mode)))))
2567 2291
2568 (defun vm-spool-move-mail (source destination) 2292 (defun vm-spool-move-mail (source destination)
2569 (let ((handler (and (fboundp 'find-file-name-handler) 2293 (let ((handler (and (fboundp 'find-file-name-handler)
2570 (condition-case () 2294 (condition-case ()
2615 (setq crash-buf 2339 (setq crash-buf
2616 ;; crash box could contain a letter bomb... 2340 ;; crash box could contain a letter bomb...
2617 ;; force user notification of file variables for v18 Emacses 2341 ;; force user notification of file variables for v18 Emacses
2618 ;; enable-local-variables == nil disables them for newer Emacses 2342 ;; enable-local-variables == nil disables them for newer Emacses
2619 (let ((inhibit-local-variables t) 2343 (let ((inhibit-local-variables t)
2620 (enable-local-variables nil) 2344 (enable-local-variables nil))
2621 (coding-system-for-read 'no-conversion))
2622 (find-file-noselect crash-box))) 2345 (find-file-noselect crash-box)))
2623 (save-excursion 2346 (save-excursion
2624 (set-buffer crash-buf) 2347 (set-buffer crash-buf)
2625 (setq crash-folder-type (vm-get-folder-type)) 2348 (setq crash-folder-type (vm-get-folder-type))
2626 (if (and crash-folder-type vm-check-folder-types) 2349 (if (and crash-folder-type vm-check-folder-types)
2667 (insert-buffer-substring crash-buf 2390 (insert-buffer-substring crash-buf
2668 1 (1+ (save-excursion 2391 1 (1+ (save-excursion
2669 (set-buffer crash-buf) 2392 (set-buffer crash-buf)
2670 (widen) 2393 (widen)
2671 (buffer-size)))) 2394 (buffer-size))))
2395 (write-region opoint-max (point-max) buffer-file-name t t)
2396 (vm-increment vm-modification-counter)
2672 (setq got-mail (/= opoint-max (point-max))) 2397 (setq got-mail (/= opoint-max (point-max)))
2673 (if (not got-mail) 2398 (set-buffer-modified-p old-buffer-modified-p)
2674 nil
2675 (write-region opoint-max (point-max) buffer-file-name t t)
2676 (vm-increment vm-modification-counter)
2677 (set-buffer-modified-p old-buffer-modified-p))
2678 (kill-buffer crash-buf) 2399 (kill-buffer crash-buf)
2679 (if (not (stringp vm-keep-crash-boxes)) 2400 (if (not (stringp vm-keep-crash-boxes))
2680 (vm-error-free-call 'delete-file crash-box) 2401 (vm-error-free-call 'delete-file crash-box)
2681 (let ((time (decode-time (current-time))) 2402 (rename-file crash-box
2682 name) 2403 (concat (expand-file-name vm-keep-crash-boxes)
2683 (setq name 2404 (if (not
2684 (expand-file-name (format "Z-%02d-%02d-%05d" 2405 (= (aref vm-keep-crash-boxes
2685 (nth 4 time) 2406 (1- (length vm-keep-crash-boxes)))
2686 (nth 3 time) 2407 ?/))
2687 (% (vm-abs (random)) 100000)) 2408 "/"
2688 vm-keep-crash-boxes)) 2409 "")
2689 (while (file-exists-p name) 2410 "Z"
2690 (setq name 2411 (substring
2691 (expand-file-name (format "Z-%02d-%02d-%05d" 2412 (timezone-make-date-sortable
2692 (nth 4 time) 2413 (current-time-string))
2693 (nth 3 time) 2414 4)))
2694 (% (vm-abs (random)) 100000)) 2415 ;; guarantee that each new saved crashbox will have a
2695 vm-keep-crash-boxes))) 2416 ;; different name, assuming time doesn't reverse.
2696 (rename-file crash-box name))) 2417 (sleep-for 1))
2697 got-mail )))) 2418 got-mail ))))
2698 2419
2699 (defun vm-compute-spool-files () 2420 (defun vm-get-spooled-mail ()
2700 (let ((fallback-triples nil) 2421 (if vm-block-new-mail
2701 triples) 2422 (error "Can't get new mail until you save this folder."))
2702 (cond ((and buffer-file-name 2423 (let ((triples nil)
2703 (consp vm-spool-file-suffixes) 2424 ;; since we could accept-process-output here (POP code),
2704 (stringp vm-crash-box-suffix)) 2425 ;; a timer process might try to start retrieving mail
2705 (setq fallback-triples 2426 ;; before we finish. block these attempts.
2706 (mapcar (function 2427 (vm-block-new-mail t)
2707 (lambda (suffix) 2428 crash in maildrop popdrop
2708 (list buffer-file-name 2429 (got-mail nil))
2709 (concat buffer-file-name suffix)
2710 (concat buffer-file-name
2711 vm-crash-box-suffix))))
2712 vm-spool-file-suffixes))))
2713 (cond ((and buffer-file-name
2714 vm-make-spool-file-name vm-make-crash-box-name)
2715 (setq fallback-triples
2716 (nconc fallback-triples
2717 (list (list buffer-file-name
2718 (save-excursion
2719 (funcall vm-make-spool-file-name
2720 buffer-file-name))
2721 (save-excursion
2722 (funcall vm-make-crash-box-name
2723 buffer-file-name))))))))
2724 (cond ((null (vm-spool-files)) 2430 (cond ((null (vm-spool-files))
2725 (setq triples (list 2431 (setq triples (list
2726 (list vm-primary-inbox 2432 (list vm-primary-inbox
2727 (concat vm-spool-directory (user-login-name)) 2433 (concat vm-spool-directory (user-login-name))
2728 vm-crash-box)))) 2434 vm-crash-box))))
2731 (mapcar (function 2437 (mapcar (function
2732 (lambda (s) (list vm-primary-inbox s vm-crash-box))) 2438 (lambda (s) (list vm-primary-inbox s vm-crash-box)))
2733 (vm-spool-files)))) 2439 (vm-spool-files))))
2734 ((consp (car (vm-spool-files))) 2440 ((consp (car (vm-spool-files)))
2735 (setq triples (vm-spool-files)))) 2441 (setq triples (vm-spool-files))))
2736 (setq triples (append triples fallback-triples)) 2442 (while triples
2737 triples )) 2443 (setq in (expand-file-name (nth 0 (car triples)) vm-folder-directory)
2738 2444 maildrop (nth 1 (car triples))
2739 (defun vm-spool-check-mail (source) 2445 crash (nth 2 (car triples)))
2740 (let ((handler (and (fboundp 'find-file-name-handler) 2446 (if (eq (current-buffer) (vm-get-file-buffer in))
2741 (condition-case () 2447 (progn
2742 (find-file-name-handler source 'vm-spool-check-mail) 2448 (if (file-exists-p crash)
2743 (wrong-number-of-arguments 2449 (progn
2744 (find-file-name-handler source)))))) 2450 (message "Recovering messages from %s..." crash)
2745 (if handler 2451 (setq got-mail (or (vm-gobble-crash-box crash) got-mail))
2746 (funcall handler 'vm-spool-check-mail source) 2452 (message "Recovering messages from %s... done" crash)))
2747 (and (not (equal 0 (nth 7 (file-attributes source)))) 2453 (setq popdrop (and vm-recognize-pop-maildrops
2748 (file-readable-p source))))) 2454 (string-match vm-recognize-pop-maildrops
2749 2455 maildrop)
2750 (defun vm-check-for-spooled-mail (&optional interactive) 2456 ;; maildrop with password clipped
2751 (if vm-block-new-mail 2457 (vm-safe-popdrop-string maildrop)))
2752 nil 2458 (if (or popdrop
2753 (let ((triples (vm-compute-spool-files)) 2459 (and (not (equal 0 (nth 7 (file-attributes maildrop))))
2754 ;; since we could accept-process-output here (POP code), 2460 (file-readable-p maildrop)))
2755 ;; a timer process might try to start retrieving mail 2461 (progn
2756 ;; before we finish. block these attempts. 2462 (setq crash (expand-file-name crash vm-folder-directory))
2757 (vm-block-new-mail t) 2463 (if (not popdrop)
2758 (vm-pop-ok-to-ask interactive) 2464 (setq maildrop (expand-file-name maildrop)))
2759 (done nil) 2465 (if (if popdrop
2760 crash in maildrop popdrop 2466 (vm-pop-move-mail maildrop crash)
2761 (mail-waiting nil)) 2467 (vm-spool-move-mail maildrop crash))
2762 (while (and triples (not done)) 2468 (if (vm-gobble-crash-box crash)
2763 (setq in (expand-file-name (nth 0 (car triples)) vm-folder-directory) 2469 (progn
2764 maildrop (nth 1 (car triples)) 2470 (setq got-mail t)
2765 crash (nth 2 (car triples))) 2471 (message "Got mail from %s."
2766 (if (eq (current-buffer) (vm-get-file-buffer in)) 2472 (or popdrop maildrop)))))))))
2767 (progn 2473 (setq triples (cdr triples)))
2768 (if (file-exists-p crash) 2474 (if got-mail
2769 (progn 2475 (run-hooks 'vm-retrieved-spooled-mail-hook))
2770 (setq mail-waiting t 2476 got-mail ))
2771 done t))
2772 (setq popdrop (and vm-recognize-pop-maildrops
2773 (string-match vm-recognize-pop-maildrops
2774 maildrop)))
2775 (if (not interactive)
2776 ;; allow no error to be signaled
2777 (condition-case nil
2778 (setq mail-waiting
2779 (or mail-waiting
2780 (if popdrop
2781 (vm-pop-check-mail maildrop)
2782 (vm-spool-check-mail maildrop))))
2783 (error nil))
2784 (setq mail-waiting (or mail-waiting
2785 (if popdrop
2786 (vm-pop-check-mail maildrop)
2787 (vm-spool-check-mail maildrop)))))
2788 (if mail-waiting
2789 (setq done t)))))
2790 (setq triples (cdr triples)))
2791 (setq vm-spooled-mail-waiting mail-waiting)
2792 mail-waiting )))
2793
2794 (defun vm-get-spooled-mail (&optional interactive)
2795 (if vm-block-new-mail
2796 (error "Can't get new mail until you save this folder."))
2797 (let ((triples (vm-compute-spool-files))
2798 ;; since we could accept-process-output here (POP code),
2799 ;; a timer process might try to start retrieving mail
2800 ;; before we finish. block these attempts.
2801 (vm-block-new-mail t)
2802 (vm-pop-ok-to-ask interactive)
2803 crash in maildrop popdrop
2804 (got-mail nil))
2805 (if (and (not (verify-visited-file-modtime (current-buffer)))
2806 (or (null interactive)
2807 (not (yes-or-no-p
2808 (format
2809 "Folder %s changed on disk, discard those changes? "
2810 (buffer-name (current-buffer)))))))
2811 (progn
2812 (message "Folder %s changed on disk, consider M-x revert-buffer"
2813 (buffer-name (current-buffer)))
2814 (sleep-for 1)
2815 nil )
2816 (while triples
2817 (setq in (expand-file-name (nth 0 (car triples)) vm-folder-directory)
2818 maildrop (nth 1 (car triples))
2819 crash (nth 2 (car triples)))
2820 (if (eq (current-buffer) (vm-get-file-buffer in))
2821 (let (retrieval-function)
2822 (if (file-exists-p crash)
2823 (progn
2824 (message "Recovering messages from %s..." crash)
2825 (setq got-mail (or (vm-gobble-crash-box crash) got-mail))
2826 (message "Recovering messages from %s... done" crash)))
2827 (setq popdrop (and vm-recognize-pop-maildrops
2828 (string-match vm-recognize-pop-maildrops
2829 maildrop)
2830 ;; maildrop with password clipped
2831 (vm-safe-popdrop-string maildrop)))
2832 (if (or popdrop
2833 (and (not (equal 0 (nth 7 (file-attributes maildrop))))
2834 (file-readable-p maildrop)))
2835 (progn
2836 (setq crash (expand-file-name crash vm-folder-directory))
2837 (if (not popdrop)
2838 (setq maildrop (expand-file-name maildrop)
2839 retrieval-function 'vm-spool-move-mail)
2840 (setq retrieval-function 'vm-pop-move-mail))
2841 (if (if got-mail
2842 ;; don't allow errors to be signaled unless no
2843 ;; mail has been appended to the incore
2844 ;; copy of the folder. otherwise the
2845 ;; user will wonder where the mail is,
2846 ;; since it is not in the crash box or
2847 ;; the spool file and doesn't _appear_ to
2848 ;; be in the folder either.
2849 (condition-case error-data
2850 (funcall retrieval-function maildrop crash)
2851 (error (message "%s signaled: %s"
2852 (if popdrop
2853 'vm-pop-move-mail
2854 'vm-spool-move-mail)
2855 error-data)
2856 (sleep-for 2)
2857 ;; we don't know if mail was
2858 ;; put into the crash box or
2859 ;; not, so return t just to be
2860 ;; safe.
2861 t )
2862 (quit (message "quitting from %s..."
2863 (if popdrop
2864 'vm-pop-move-mail
2865 'vm-spool-move-mail))
2866 (sleep-for 1)
2867 ;; we don't know if mail was
2868 ;; put into the crash box or
2869 ;; not, so return t just to be
2870 ;; safe.
2871 t ))
2872 (funcall retrieval-function maildrop crash))
2873 (if (vm-gobble-crash-box crash)
2874 (progn
2875 (setq got-mail t)
2876 (message "Got mail from %s."
2877 (or popdrop maildrop)))))))))
2878 (setq triples (cdr triples)))
2879 ;; not really correct, but it is what the user expects to see.
2880 (if got-mail
2881 (setq vm-spooled-mail-waiting nil))
2882 (intern (buffer-name) vm-buffers-needing-display-update)
2883 (vm-update-summary-and-mode-line)
2884 (if got-mail
2885 (run-hooks 'vm-retrieved-spooled-mail-hook))
2886 got-mail )))
2887 2477
2888 (defun vm-safe-popdrop-string (drop) 2478 (defun vm-safe-popdrop-string (drop)
2889 (or (and (string-match "^\\([^:]+\\):[^:]+:[^:]+:\\([^:]+\\):[^:]+" drop) 2479 (or (and (string-match "^\\([^:]+\\):[^:]+:[^:]+:\\([^:]+\\):[^:]+" drop)
2890 (concat (substring drop (match-beginning 2) (match-end 2)) 2480 (concat (substring drop (match-beginning 2) (match-end 2))
2891 "@" 2481 "@"
2914 (vm-virtual-get-new-mail)) 2504 (vm-virtual-get-new-mail))
2915 ((null arg) 2505 ((null arg)
2916 (if (not (eq major-mode 'vm-mode)) 2506 (if (not (eq major-mode 'vm-mode))
2917 (vm-mode)) 2507 (vm-mode))
2918 (if (consp (car (vm-spool-files))) 2508 (if (consp (car (vm-spool-files)))
2919 (message "Checking for new mail for %s..." 2509 (vm-unsaved-message "Checking for new mail for %s..."
2920 (or buffer-file-name (buffer-name))) 2510 (or buffer-file-name (buffer-name)))
2921 (message "Checking for new mail...")) 2511 (vm-unsaved-message "Checking for new mail..."))
2922 (let (totals-blurb) 2512 (let (totals-blurb)
2923 (if (and (vm-get-spooled-mail t) (vm-assimilate-new-messages t)) 2513 (if (and (vm-get-spooled-mail) (vm-assimilate-new-messages t))
2924 (progn 2514 (progn
2925 ;; say this NOW, before the non-previewers read 2515 ;; say this NOW, before the non-previewers read
2926 ;; a message, alter the new message count and 2516 ;; a message, alter the new message count and
2927 ;; confuse themselves. 2517 ;; confuse themselves.
2928 (setq totals-blurb (vm-emit-totals-blurb)) 2518 (setq totals-blurb (vm-emit-totals-blurb))
2933 (message totals-blurb)) 2523 (message totals-blurb))
2934 (if (consp (car (vm-spool-files))) 2524 (if (consp (car (vm-spool-files)))
2935 (message "No new mail for %s" 2525 (message "No new mail for %s"
2936 (or buffer-file-name (buffer-name))) 2526 (or buffer-file-name (buffer-name)))
2937 (message "No new mail.")) 2527 (message "No new mail."))
2938 (and (interactive-p) (sit-for 4) (message ""))))) 2528 (and (interactive-p) (sit-for 4) (vm-unsaved-message "")))))
2939 (t 2529 (t
2940 (let ((buffer-read-only nil) 2530 (let ((buffer-read-only nil)
2941 folder mcount totals-blurb) 2531 folder mcount totals-blurb)
2942 (setq folder (read-file-name "Gather mail from folder: " 2532 (setq folder (read-file-name "Gather mail from folder: "
2943 vm-folder-directory t)) 2533 vm-folder-directory t))
2947 folder)) 2537 folder))
2948 (save-excursion 2538 (save-excursion
2949 (vm-save-restriction 2539 (vm-save-restriction
2950 (widen) 2540 (widen)
2951 (goto-char (point-max)) 2541 (goto-char (point-max))
2952 (let ((coding-system-for-read 'binary)) 2542 (insert-file-contents folder)))
2953 (insert-file-contents folder))))
2954 (setq mcount (length vm-message-list)) 2543 (setq mcount (length vm-message-list))
2955 (if (vm-assimilate-new-messages) 2544 (if (vm-assimilate-new-messages)
2956 (progn 2545 (progn
2957 ;; say this NOW, before the non-previewers read 2546 ;; say this NOW, before the non-previewers read
2958 ;; a message, alter the new message count and 2547 ;; a message, alter the new message count and
2972 (- (length vm-message-list) 2561 (- (length vm-message-list)
2973 mcount)))) 2562 mcount))))
2974 (message "No messages gathered.")))))) 2563 (message "No messages gathered."))))))
2975 2564
2976 ;; returns non-nil if there were any new messages 2565 ;; returns non-nil if there were any new messages
2977 (defun vm-assimilate-new-messages (&optional 2566 (defun vm-assimilate-new-messages (&optional dont-read-attributes gobble-order)
2978 dont-read-attributes
2979 gobble-order
2980 labels)
2981 (let ((tail-cons (vm-last vm-message-list)) 2567 (let ((tail-cons (vm-last vm-message-list))
2982 b-list new-messages) 2568 b-list new-messages)
2983 (save-excursion 2569 (save-excursion
2984 (vm-save-restriction 2570 (vm-save-restriction
2985 (widen) 2571 (widen)
3008 ;; it. Also something the user does when 2594 ;; it. Also something the user does when
3009 ;; vm-arrived-message-hook is run might affect it. 2595 ;; vm-arrived-message-hook is run might affect it.
3010 ;; vm-assimilate-new-messages returns this value so it must 2596 ;; vm-assimilate-new-messages returns this value so it must
3011 ;; not be mangled. 2597 ;; not be mangled.
3012 (setq new-messages (copy-sequence new-messages)) 2598 (setq new-messages (copy-sequence new-messages))
3013 ;; add the labels
3014 (if (and labels vm-burst-digest-messages-inherit-labels)
3015 (let ((mp new-messages))
3016 (while mp
3017 (vm-set-labels-of (car mp) (copy-sequence labels))
3018 (setq mp (cdr mp)))))
3019 (if vm-summary-show-threads 2599 (if vm-summary-show-threads
3020 (progn 2600 (progn
3021 ;; get numbering and summary of new messages done now 2601 ;; get numbering and summary of new messages done now
3022 ;; so that the sort code only has to worry about the 2602 ;; so that the sort code only has to worry about the
3023 ;; changes it needs to make. 2603 ;; changes it needs to make.
3096 (nreverse mlist)))) 2676 (nreverse mlist))))
3097 2677
3098 (defun vm-display-startup-message () 2678 (defun vm-display-startup-message ()
3099 (if (sit-for 5) 2679 (if (sit-for 5)
3100 (let ((lines vm-startup-message-lines)) 2680 (let ((lines vm-startup-message-lines))
3101 (message "VM %s, Copyright (C) 1997 Kyle E. Jones; type ? for help" 2681 (message "VM %s, Copyright (C) 1996 Kyle E. Jones; type ? for help"
3102 vm-version) 2682 vm-version)
3103 (setq vm-startup-message-displayed t) 2683 (setq vm-startup-message-displayed t)
3104 (while (and (sit-for 4) lines) 2684 (while (and (sit-for 4) lines)
3105 (message (substitute-command-keys (car lines))) 2685 (message (substitute-command-keys (car lines)))
3106 (setq lines (cdr lines))))) 2686 (setq lines (cdr lines)))))
3107 (message "")) 2687 (vm-unsaved-message ""))
3108 2688
3109 (defun vm-load-init-file (&optional interactive) 2689 (defun vm-load-init-file (&optional interactive)
3110 (interactive "p") 2690 (interactive "p")
3111 (if (or (not vm-init-file-loaded) interactive) 2691 (if (or (not vm-init-file-loaded) interactive)
3112 (progn 2692 (progn
3113 (and vm-init-file 2693 (and vm-init-file
3114 (load vm-init-file (not interactive) (not interactive) t)) 2694 (load vm-init-file (not interactive) (not interactive) t))
3115 (and vm-preferences-file (load vm-preferences-file t t t)))) 2695 (and vm-options-file (load vm-options-file t t t))))
3116 (setq vm-init-file-loaded t) 2696 (setq vm-init-file-loaded t)
3117 (vm-display nil nil '(vm-load-init-file) '(vm-load-init-file))) 2697 (vm-display nil nil '(vm-load-init-file) '(vm-load-init-file)))
3118 2698
3119 (defun vm-session-initialization () 2699 (defun vm-session-initialization ()
3120 ;; If this is the first time VM has been run in this Emacs session, 2700 ;; If this is the first time VM has been run in this Emacs session,
3139 (message "Folder is now %s" 2719 (message "Folder is now %s"
3140 (if vm-folder-read-only "read-only" "modifiable")) 2720 (if vm-folder-read-only "read-only" "modifiable"))
3141 (vm-display nil nil '(vm-toggle-read-only) '(vm-toggle-read-only)) 2721 (vm-display nil nil '(vm-toggle-read-only) '(vm-toggle-read-only))
3142 (vm-update-summary-and-mode-line)) 2722 (vm-update-summary-and-mode-line))
3143 2723
3144 (defvar scroll-in-place)
3145
3146 ;; this does the real major mode scutwork. 2724 ;; this does the real major mode scutwork.
3147 (defun vm-mode-internal () 2725 (defun vm-mode-internal ()
3148 (widen) 2726 (widen)
3149 (make-local-variable 'require-final-newline) 2727 (make-local-variable 'require-final-newline)
3150 ;; don't kill local variables, as there is some state we'd like to 2728 ;; don't kill local variables, as there is some state we'd like to
3154 (setq 2732 (setq
3155 major-mode 'vm-mode 2733 major-mode 'vm-mode
3156 mode-line-format vm-mode-line-format 2734 mode-line-format vm-mode-line-format
3157 mode-name "VM" 2735 mode-name "VM"
3158 ;; must come after the setting of major-mode 2736 ;; must come after the setting of major-mode
3159 mode-popup-menu (and vm-use-menus vm-popup-menu-on-mouse-3 2737 mode-popup-menu (and vm-use-menus
3160 (vm-menu-support-possible-p) 2738 (vm-menu-support-possible-p)
3161 (vm-menu-mode-menu)) 2739 (vm-menu-mode-menu))
3162 buffer-read-only t 2740 buffer-read-only t
3163 ;; If the user quits a vm-mode buffer, the default action is
3164 ;; to kill the buffer. Make a note that we should offer to
3165 ;; save this buffer even if it has no file associated with it.
3166 ;; We have no idea of the value of the data in the buffer
3167 ;; before it was put into vm-mode.
3168 buffer-offer-save t
3169 require-final-newline nil 2741 require-final-newline nil
3170 vm-thread-obarray nil 2742 vm-thread-obarray nil
3171 vm-thread-subject-obarray nil 2743 vm-thread-subject-obarray nil
3172 vm-label-obarray (make-vector 29 0) 2744 vm-label-obarray (make-vector 29 0)
3173 vm-last-message-pointer nil 2745 vm-last-message-pointer nil
3183 vm-virtual-buffers (vm-link-to-virtual-buffers) 2755 vm-virtual-buffers (vm-link-to-virtual-buffers)
3184 vm-folder-type (vm-get-folder-type)) 2756 vm-folder-type (vm-get-folder-type))
3185 (use-local-map vm-mode-map) 2757 (use-local-map vm-mode-map)
3186 (and (vm-menu-support-possible-p) 2758 (and (vm-menu-support-possible-p)
3187 (vm-menu-install-menus)) 2759 (vm-menu-install-menus))
3188 (add-hook 'kill-buffer-hook 'vm-garbage-collect-folder)
3189 (add-hook 'kill-buffer-hook 'vm-garbage-collect-message)
3190 ;; avoid the XEmacs file dialog box.
3191 (defvar use-dialog-box)
3192 (make-local-variable 'use-dialog-box)
3193 (setq use-dialog-box nil)
3194 ;; mail folders are precious. protect them by default.
3195 (make-local-variable 'file-precious-flag)
3196 (setq file-precious-flag t)
3197 ;; scroll in place messes with scroll-up and this loses
3198 (make-local-variable 'scroll-in-place)
3199 (setq scroll-in-place nil)
3200 (run-hooks 'vm-mode-hook) 2760 (run-hooks 'vm-mode-hook)
3201 ;; compatibility 2761 ;; compatibility
3202 (run-hooks 'vm-mode-hooks)) 2762 (run-hooks 'vm-mode-hooks))
3203 2763
3204 (defun vm-link-to-virtual-buffers () 2764 (defun vm-link-to-virtual-buffers ()
3299 ;; have changed. But I don't think anyone cares that 2859 ;; have changed. But I don't think anyone cares that
3300 ;; much and the summary regeneration would make this 2860 ;; much and the summary regeneration would make this
3301 ;; process slower. 2861 ;; process slower.
3302 (setq mp (cdr mp) n (1+ n)) 2862 (setq mp (cdr mp) n (1+ n))
3303 (if (zerop (% n modulus)) 2863 (if (zerop (% n modulus))
3304 (message "Converting... %d" n)))))) 2864 (vm-unsaved-message "Converting... %d" n))))))
3305 (vm-clear-modification-flag-undos) 2865 (vm-clear-modification-flag-undos)
3306 (intern (buffer-name) vm-buffers-needing-display-update) 2866 (intern (buffer-name) vm-buffers-needing-display-update)
3307 (vm-update-summary-and-mode-line) 2867 (vm-update-summary-and-mode-line)
3308 (message "Conversion complete.") 2868 (message "Conversion complete.")
3309 ;; message separator strings may have leaked into view 2869 ;; message separator strings may have leaked into view
3310 (if (> (point-max) (vm-text-end-of (car vm-message-pointer))) 2870 (if (> (point-max) (vm-text-end-of (car vm-message-pointer)))
3311 (narrow-to-region (point-min) (vm-text-end-of (car vm-message-pointer)))) 2871 (narrow-to-region (point-min) (vm-text-end-of (car vm-message-pointer))))
3312 (vm-display nil nil '(vm-change-folder-type) '(vm-change-folder-type))) 2872 (vm-display nil nil '(vm-change-folder-type) '(vm-change-folder-type)))
3313 2873
3314 (defun vm-garbage-collect-folder ()
3315 (save-excursion
3316 (while vm-folder-garbage-alist
3317 (condition-case nil
3318 (funcall (cdr (car vm-folder-garbage-alist))
3319 (car (car vm-folder-garbage-alist)))
3320 (error nil))
3321 (setq vm-folder-garbage-alist (cdr vm-folder-garbage-alist)))))
3322
3323 (defun vm-garbage-collect-message ()
3324 (save-excursion
3325 (while vm-message-garbage-alist
3326 (condition-case nil
3327 (funcall (cdr (car vm-message-garbage-alist))
3328 (car (car vm-message-garbage-alist)))
3329 (error nil))
3330 (setq vm-message-garbage-alist (cdr vm-message-garbage-alist)))))
3331
3332 (if (not (memq 'vm-write-file-hook write-file-hooks)) 2874 (if (not (memq 'vm-write-file-hook write-file-hooks))
3333 (setq write-file-hooks 2875 (setq write-file-hooks
3334 (cons 'vm-write-file-hook write-file-hooks))) 2876 (cons 'vm-write-file-hook write-file-hooks)))
3335 2877
3336 (if (not (memq 'vm-handle-file-recovery find-file-hooks)) 2878 (if (not (memq 'vm-handle-file-recovery find-file-hooks))