Mercurial > hg > xemacs-beta
comparison lisp/vm/vm-virtual.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 859a2309aef8 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 ;;; Virtual folders for VM | |
2 ;;; Copyright (C) 1990, 1993, 1994, 1995 Kyle E. Jones | |
3 ;;; | |
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 | |
6 ;;; the Free Software Foundation; either version 1, or (at your option) | |
7 ;;; any later version. | |
8 ;;; | |
9 ;;; This program is distributed in the hope that it will be useful, | |
10 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 ;;; GNU General Public License for more details. | |
13 ;;; | |
14 ;;; You should have received a copy of the GNU General Public License | |
15 ;;; along with this program; if not, write to the Free Software | |
16 ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
17 | |
18 (provide 'vm-virtual) | |
19 | |
20 ;; This function builds the virtual message list. | |
21 ;; | |
22 ;; If the new-messages argument is nil, the message list is | |
23 ;; derived from the folders listed in the virtual folder | |
24 ;; definition and selected by the various selectors. The | |
25 ;; resulting message list is assigned to vm-message-list. | |
26 ;; | |
27 ;; If new-messages is non-nil then it is a list of messages to be | |
28 ;; tried against the selector parts of the virtual folder | |
29 ;; definition. Matching messages are added to | |
30 ;; vm-message-list, instead of replacing it. | |
31 ;; | |
32 ;; The messages in new-messages must all be in the same real folder. | |
33 (defun vm-build-virtual-message-list (new-messages) | |
34 (let ((clauses (cdr vm-virtual-folder-definition)) | |
35 | |
36 (message-set (make-vector 311 0)) | |
37 (vbuffer (current-buffer)) | |
38 (mirrored vm-virtual-mirror) | |
39 (case-fold-search t) | |
40 (tail-cons (vm-last vm-message-list)) | |
41 (new-message-list nil) | |
42 | |
43 ;; selectors | |
44 (any 'vm-vs-any) | |
45 (and 'vm-vs-and) | |
46 (or 'vm-vs-or) | |
47 (not 'vm-vs-not) | |
48 (header 'vm-vs-header) | |
49 (label 'vm-vs-label) | |
50 (text 'vm-vs-text) | |
51 (recipient 'vm-vs-recipient) | |
52 (author 'vm-vs-author) | |
53 (subject 'vm-vs-subject) | |
54 (sent-before 'vm-vs-sent-before) | |
55 (sent-after 'vm-vs-sent-after) | |
56 (more-chars-than 'vm-vs-more-chars-than) | |
57 (less-chars-than 'vm-vs-less-chars-than) | |
58 (more-lines-than 'vm-vs-more-lines-than) | |
59 (less-lines-than 'vm-vs-less-lines-than) | |
60 (new 'vm-vs-new) | |
61 (unread 'vm-vs-unread) | |
62 (read 'vm-vs-read) | |
63 (deleted 'vm-vs-deleted) | |
64 (replied 'vm-vs-replied) | |
65 (forwarded 'vm-vs-forwarded) | |
66 (filed 'vm-vs-filed) | |
67 (written 'vm-vs-written) | |
68 (edited 'vm-vs-edited) | |
69 (marked 'vm-vs-marked) | |
70 | |
71 virtual location-vector | |
72 message mp folders folder | |
73 selectors sel-list selector arglist i | |
74 real-buffers-used) | |
75 ;; Since there is at most one virtual message in the folder | |
76 ;; buffer of a virtual folder, the location data vector (and | |
77 ;; the markers in it) of all virtual messages in a virtual | |
78 ;; folder is shared. We initialize the vector here if it | |
79 ;; hasn't been created already. | |
80 (if vm-message-list | |
81 (setq location-vector (vm-location-data-of (car vm-message-pointer))) | |
82 (setq i 0 | |
83 location-vector (make-vector vm-location-data-vector-length nil)) | |
84 (while (< i vm-location-data-vector-length) | |
85 (aset location-vector i (vm-marker nil)) | |
86 (vm-increment i))) | |
87 ;; To keep track of the messages in a virtual folder to | |
88 ;; prevent duplicates we create and maintain a set that | |
89 ;; contain all the real messages. | |
90 (setq mp vm-message-list) | |
91 (while mp | |
92 (intern (vm-message-id-number-of (vm-real-message-of (car mp))) | |
93 message-set) | |
94 (setq mp (cdr mp))) | |
95 ;; now select the messages | |
96 (save-excursion | |
97 (while clauses | |
98 (setq folders (car (car clauses)) | |
99 selectors (cdr (car clauses))) | |
100 (while folders | |
101 (setq folder (car folders)) | |
102 (and (stringp folder) | |
103 (setq folder (expand-file-name folder vm-folder-directory))) | |
104 (and (listp folder) | |
105 (setq folder (eval folder))) | |
106 (cond | |
107 ((null folder) | |
108 ;; folder was a s-expr which returned nil | |
109 ;; skip it | |
110 nil ) | |
111 ((and (stringp folder) (file-directory-p folder)) | |
112 (setq folders (nconc folders | |
113 (vm-delete-backup-file-names | |
114 (vm-delete-auto-save-file-names | |
115 (vm-delete-directory-file-names | |
116 (directory-files folder t nil))))))) | |
117 ((or (null new-messages) | |
118 ;; If we're assimilating messages into an | |
119 ;; existing virtual folder, only allow selectors | |
120 ;; that would be normally applied to this folder. | |
121 (and (bufferp folder) | |
122 (eq (vm-buffer-of (car new-messages)) folder)) | |
123 (and (stringp folder) | |
124 (eq (vm-buffer-of (car new-messages)) | |
125 ;; letter bomb protection | |
126 ;; set inhibit-local-variables to t for v18 Emacses | |
127 ;; set enable-local-variables to nil for newer Emacses | |
128 (let ((inhibit-local-variables t) | |
129 (enable-local-variables nil)) | |
130 (find-file-noselect folder))))) | |
131 (set-buffer (or (and (bufferp folder) folder) | |
132 (vm-get-file-buffer folder) | |
133 (find-file-noselect folder))) | |
134 (if (eq major-mode 'vm-virtual-mode) | |
135 (setq virtual t | |
136 real-buffers-used | |
137 (append vm-real-buffers real-buffers-used)) | |
138 (setq virtual nil) | |
139 (if (not (memq (current-buffer) real-buffers-used)) | |
140 (setq real-buffers-used (cons (current-buffer) | |
141 real-buffers-used))) | |
142 (if (not (eq major-mode 'vm-mode)) | |
143 (vm-mode))) | |
144 ;; change (sexpr) into ("/file" "/file2" ...) | |
145 ;; this assumes that there will never be (sexpr sexpr2) | |
146 ;; in a virtual folder spec. | |
147 (if (bufferp folder) | |
148 (if virtual | |
149 (setcar (car clauses) | |
150 (delq nil | |
151 (mapcar 'buffer-file-name vm-real-buffers))) | |
152 (if buffer-file-name | |
153 (setcar (car clauses) (list buffer-file-name))))) | |
154 ;; if new-messages non-nil use it instead of the | |
155 ;; whole message list | |
156 (setq mp (or new-messages vm-message-list)) | |
157 (while mp | |
158 (if (and (not (intern-soft | |
159 (vm-message-id-number-of | |
160 (vm-real-message-of (car mp))) | |
161 message-set)) | |
162 (if virtual | |
163 (save-excursion | |
164 (set-buffer | |
165 (vm-buffer-of | |
166 (vm-real-message-of | |
167 (car mp)))) | |
168 (apply 'vm-vs-or (vm-real-message-of (car mp)) | |
169 selectors)) | |
170 (apply 'vm-vs-or (car mp) selectors))) | |
171 (progn | |
172 (intern | |
173 (vm-message-id-number-of | |
174 (vm-real-message-of (car mp))) | |
175 message-set) | |
176 (setq message (copy-sequence | |
177 (vm-real-message-of (car mp)))) | |
178 (if mirrored | |
179 () | |
180 (vm-set-mirror-data-of | |
181 message | |
182 (make-vector vm-mirror-data-vector-length nil)) | |
183 (vm-set-virtual-messages-sym-of | |
184 message (make-symbol "<v>")) | |
185 (vm-set-virtual-messages-of message nil) | |
186 (vm-set-attributes-of | |
187 message | |
188 (make-vector vm-attributes-vector-length nil))) | |
189 (vm-set-location-data-of message location-vector) | |
190 (vm-set-softdata-of | |
191 message | |
192 (make-vector vm-softdata-vector-length nil)) | |
193 (vm-set-real-message-sym-of | |
194 message | |
195 (vm-real-message-sym-of (car mp))) | |
196 (vm-set-message-type-of message vm-folder-type) | |
197 (vm-set-message-id-number-of message | |
198 vm-message-id-number) | |
199 (vm-increment vm-message-id-number) | |
200 (vm-set-buffer-of message vbuffer) | |
201 (vm-set-reverse-link-sym-of message (make-symbol "<--")) | |
202 (vm-set-reverse-link-of message tail-cons) | |
203 (if (null tail-cons) | |
204 (setq new-message-list (list message) | |
205 tail-cons new-message-list) | |
206 (setcdr tail-cons (list message)) | |
207 (if (null new-message-list) | |
208 (setq new-message-list (cdr tail-cons))) | |
209 (setq tail-cons (cdr tail-cons))))) | |
210 (setq mp (cdr mp))))) | |
211 (setq folders (cdr folders))) | |
212 (setq clauses (cdr clauses)))) | |
213 ; this doesn't need to work currently, but it might someday | |
214 ; (if virtual | |
215 ; (setq real-buffers-used (vm-delete-duplicates real-buffers-used))) | |
216 (vm-increment vm-modification-counter) | |
217 ;; Until this point the user doesn't really have a virtual | |
218 ;; folder, as the virtual messages haven't been linked to the | |
219 ;; real messages, virtual buffers to the real buffers, and no | |
220 ;; message list has been installed. | |
221 ;; | |
222 ;; Now we tie it all together, with this section of code being | |
223 ;; uninterruptible. | |
224 (let ((inhibit-quit t)) | |
225 (if (null vm-real-buffers) | |
226 (setq vm-real-buffers real-buffers-used)) | |
227 (save-excursion | |
228 (while real-buffers-used | |
229 (set-buffer (car real-buffers-used)) | |
230 (if (not (memq vbuffer vm-virtual-buffers)) | |
231 (setq vm-virtual-buffers (cons vbuffer vm-virtual-buffers))) | |
232 (setq real-buffers-used (cdr real-buffers-used)))) | |
233 (setq mp new-message-list) | |
234 (while mp | |
235 (vm-set-virtual-messages-of | |
236 (vm-real-message-of (car mp)) | |
237 (cons (car mp) (vm-virtual-messages-of (car mp)))) | |
238 (setq mp (cdr mp))) | |
239 (if vm-message-list | |
240 (progn | |
241 (vm-set-summary-redo-start-point new-message-list) | |
242 (vm-set-numbering-redo-start-point new-message-list)) | |
243 (vm-set-summary-redo-start-point t) | |
244 (vm-set-numbering-redo-start-point t) | |
245 (setq vm-message-list new-message-list))))) | |
246 | |
247 (defun vm-create-virtual-folder (selector &optional arg read-only) | |
248 "Create a new virtual folder from messages in the current folder. | |
249 The messages will be chosen by applying the selector you specify, | |
250 which is normally read from the minibuffer. | |
251 | |
252 Prefix arg means the new virtual folder should be visited read only." | |
253 (interactive | |
254 (let ((last-command last-command) | |
255 (this-command this-command) | |
256 (prefix current-prefix-arg)) | |
257 (vm-select-folder-buffer) | |
258 (nconc (vm-read-virtual-selector "Create virtual folder of messages: ") | |
259 (list prefix)))) | |
260 (vm-select-folder-buffer) | |
261 (vm-check-for-killed-summary) | |
262 (vm-error-if-folder-empty) | |
263 (let (vm-virtual-folder-alist name) | |
264 (if arg | |
265 (setq name (format "%s %s %s" (buffer-name) selector arg)) | |
266 (setq name (format "%s %s" (buffer-name) selector))) | |
267 (setq vm-virtual-folder-alist | |
268 (list | |
269 (list name | |
270 (list (list (list 'get-buffer (buffer-name))) | |
271 (if arg (list selector arg) (list selector)))))) | |
272 (vm-visit-virtual-folder name read-only))) | |
273 | |
274 (defun vm-apply-virtual-folder (name &optional read-only) | |
275 "Apply the selectors of a named virtual folder to the current folder | |
276 and create a virtual folder containing the selected messages. | |
277 | |
278 Prefix arg means the new virtual folder should be visited read only." | |
279 (interactive | |
280 (let ((last-command last-command) | |
281 (this-command this-command)) | |
282 (list | |
283 (completing-read "Apply this virtual folder's selectors: " | |
284 vm-virtual-folder-alist nil t) | |
285 current-prefix-arg))) | |
286 (vm-select-folder-buffer) | |
287 (vm-check-for-killed-summary) | |
288 (vm-error-if-folder-empty) | |
289 (let ((vfolder (assoc name vm-virtual-folder-alist)) | |
290 clauses vm-virtual-folder-alist) | |
291 (or vfolder (error "No such virtual folder, %s" name)) | |
292 (setq vfolder (vm-copy vfolder)) | |
293 (setq clauses (cdr vfolder)) | |
294 (while clauses | |
295 (setcar (car clauses) (list (list 'get-buffer (buffer-name)))) | |
296 (setq clauses (cdr clauses))) | |
297 (setcar vfolder (format "%s/%s" (buffer-name) (car vfolder))) | |
298 (setq vm-virtual-folder-alist (list vfolder)) | |
299 (vm-visit-virtual-folder (car vfolder) read-only))) | |
300 | |
301 (defun vm-toggle-virtual-mirror () | |
302 (interactive) | |
303 (vm-select-folder-buffer) | |
304 (vm-check-for-killed-summary) | |
305 (if (not (eq major-mode 'vm-virtual-mode)) | |
306 (error "This is not a virtual folder.")) | |
307 (let ((mp vm-message-list) | |
308 (inhibit-quit t) | |
309 modified undo-list) | |
310 (setq undo-list vm-saved-undo-record-list | |
311 vm-saved-undo-record-list vm-undo-record-list | |
312 vm-undo-record-list undo-list | |
313 vm-undo-record-pointer undo-list) | |
314 (setq modified vm-saved-buffer-modified-p | |
315 vm-saved-buffer-modified-p (buffer-modified-p)) | |
316 (set-buffer-modified-p modified) | |
317 (if vm-virtual-mirror | |
318 (while mp | |
319 (vm-set-attributes-of | |
320 (car mp) (or (vm-saved-virtual-attributes-of (car mp)) | |
321 (make-vector vm-attributes-vector-length nil))) | |
322 (vm-set-mirror-data-of | |
323 (car mp) (or (vm-saved-virtual-mirror-data-of (car mp)) | |
324 (make-vector vm-mirror-data-vector-length nil))) | |
325 (vm-mark-for-summary-update (car mp) t) | |
326 (setq mp (cdr mp))) | |
327 (while mp | |
328 ;; mark for summary update _before_ we set this message to | |
329 ;; be mirrored. this will prevent the real message and | |
330 ;; the other messages that will share attributes with | |
331 ;; this message from having their summaries | |
332 ;; updated... they don't need it. | |
333 (vm-mark-for-summary-update (car mp) t) | |
334 (vm-set-saved-virtual-attributes-of | |
335 (car mp) (vm-attributes-of (car mp))) | |
336 (vm-set-saved-virtual-mirror-data-of | |
337 (car mp) (vm-mirror-data-of (car mp))) | |
338 (vm-set-attributes-of | |
339 (car mp) (vm-attributes-of (vm-real-message-of (car mp)))) | |
340 (vm-set-mirror-data-of | |
341 (car mp) (vm-mirror-data-of (vm-real-message-of (car mp)))) | |
342 (setq mp (cdr mp)))) | |
343 (setq vm-virtual-mirror (not vm-virtual-mirror)) | |
344 (vm-increment vm-modification-counter)) | |
345 (vm-update-summary-and-mode-line) | |
346 (message "Virtual folder now %s the underlying real folder%s." | |
347 (if vm-virtual-mirror "mirrors" "does not mirror") | |
348 (if (cdr vm-real-buffers) "s" ""))) | |
349 | |
350 (defun vm-virtual-help () | |
351 (interactive) | |
352 (vm-display nil nil '(vm-virtual-help) '(vm-virtual-help)) | |
353 (message "VV = visit, VA = apply selectors, VC = create, VM = toggle virtual mirror")) | |
354 | |
355 (defun vm-delete-directory-file-names (list) | |
356 (vm-delete 'file-directory-p list)) | |
357 | |
358 (defun vm-delete-backup-file-names (list) | |
359 (vm-delete 'backup-file-name-p list)) | |
360 | |
361 (defun vm-delete-auto-save-file-names (list) | |
362 (vm-delete 'auto-save-file-name-p list)) | |
363 | |
364 (defun vm-vs-or (m &rest selectors) | |
365 (let ((result nil) selector arglist) | |
366 (while selectors | |
367 (setq selector (car (car selectors)) | |
368 arglist (cdr (car selectors)) | |
369 result (apply (symbol-value selector) m arglist) | |
370 selectors (if result nil (cdr selectors)))) | |
371 result )) | |
372 | |
373 (defun vm-vs-and (m &rest selectors) | |
374 (let ((result t) selector arglist) | |
375 (while selectors | |
376 (setq selector (car (car selectors)) | |
377 arglist (cdr (car selectors)) | |
378 result (apply (symbol-value selector) m arglist) | |
379 selectors (if (null result) nil (cdr selectors)))) | |
380 result )) | |
381 | |
382 (defun vm-vs-not (m arg) | |
383 (let ((selector (car arg)) | |
384 (arglist (cdr arg))) | |
385 (not (apply (symbol-value selector) m arglist)))) | |
386 | |
387 (defun vm-vs-any (m) t) | |
388 | |
389 (defun vm-vs-author (m arg) | |
390 (or (string-match arg (vm-su-full-name m)) | |
391 (string-match arg (vm-su-from m)))) | |
392 | |
393 (defun vm-vs-recipient (m arg) | |
394 (or (string-match arg (vm-su-to m)) | |
395 (string-match arg (vm-su-to-names m)))) | |
396 | |
397 (defun vm-vs-subject (m arg) | |
398 (string-match arg (vm-su-subject m))) | |
399 | |
400 (defun vm-vs-sent-before (m arg) | |
401 (string< (vm-so-sortable-datestring m) (vm-timezone-make-date-sortable arg))) | |
402 | |
403 (defun vm-vs-sent-after (m arg) | |
404 (string< (vm-timezone-make-date-sortable arg) (vm-so-sortable-datestring m))) | |
405 | |
406 (defun vm-vs-header (m arg) | |
407 (save-excursion | |
408 (save-restriction | |
409 (widen) | |
410 (goto-char (vm-headers-of m)) | |
411 (re-search-forward arg (vm-text-of m) t)))) | |
412 | |
413 (defun vm-vs-label (m arg) | |
414 (vm-member arg (vm-labels-of m))) | |
415 | |
416 (defun vm-vs-text (m arg) | |
417 (save-excursion | |
418 (save-restriction | |
419 (widen) | |
420 (goto-char (vm-text-of m)) | |
421 (re-search-forward arg (vm-text-end-of m) t)))) | |
422 | |
423 (defun vm-vs-more-chars-than (m arg) | |
424 (> (string-to-int (vm-su-byte-count m)) arg)) | |
425 | |
426 (defun vm-vs-less-chars-than (m arg) | |
427 (< (string-to-int (vm-su-byte-count m)) arg)) | |
428 | |
429 (defun vm-vs-more-lines-than (m arg) | |
430 (> (string-to-int (vm-su-line-count m)) arg)) | |
431 | |
432 (defun vm-vs-less-lines-than (m arg) | |
433 (< (string-to-int (vm-su-line-count m)) arg)) | |
434 | |
435 (defun vm-vs-new (m) (vm-new-flag m)) | |
436 (defun vm-vs-unread (m) (vm-unread-flag m)) | |
437 (defun vm-vs-read (m) (not (or (vm-new-flag m) (vm-unread-flag m)))) | |
438 (defun vm-vs-deleted (m) (vm-deleted-flag m)) | |
439 (defun vm-vs-replied (m) (vm-replied-flag m)) | |
440 (defun vm-vs-forwarded (m) (vm-forwarded-flag m)) | |
441 (defun vm-vs-filed (m) (vm-filed-flag m)) | |
442 (defun vm-vs-written (m) (vm-written-flag m)) | |
443 (defun vm-vs-marked (m) (vm-mark-of m)) | |
444 (defun vm-vs-edited (m) (vm-edited-flag m)) | |
445 | |
446 (put 'header 'vm-virtual-selector-clause "with header matching") | |
447 (put 'label 'vm-virtual-selector-clause "with label of") | |
448 (put 'text 'vm-virtual-selector-clause "with text matching") | |
449 (put 'recipient 'vm-virtual-selector-clause "with recipient matching") | |
450 (put 'author 'vm-virtual-selector-clause "with author matching") | |
451 (put 'subject 'vm-virtual-selector-clause "with subject matching") | |
452 (put 'sent-before 'vm-virtual-selector-clause "sent before") | |
453 (put 'sent-after 'vm-virtual-selector-clause "sent after") | |
454 (put 'more-chars-than 'vm-virtual-selector-clause | |
455 "with more characters than") | |
456 (put 'less-chars-than 'vm-virtual-selector-clause | |
457 "with less characters than") | |
458 (put 'more-lines-than 'vm-virtual-selector-clause "with more lines than") | |
459 (put 'less-lines-than 'vm-virtual-selector-clause "with less lines than") | |
460 | |
461 (defun vm-read-virtual-selector (prompt) | |
462 (let (selector (arg nil)) | |
463 (setq selector | |
464 (vm-read-string prompt vm-supported-interactive-virtual-selectors) | |
465 selector (intern selector)) | |
466 (if (memq selector '(header label text recipient | |
467 author subject | |
468 sent-before sent-after | |
469 more-chars-than more-lines-than | |
470 less-chars-than less-lines-than)) | |
471 (progn | |
472 (setq prompt (concat (substring prompt 0 -2) " " | |
473 (get selector 'vm-virtual-selector-clause) | |
474 ": ")) | |
475 (cond ((memq selector '(more-chars-than more-lines-than | |
476 less-chars-than less-lines-than)) | |
477 (setq arg (vm-read-number prompt))) | |
478 ((eq selector 'label) | |
479 (let ((vm-completion-auto-correct nil) | |
480 (completion-ignore-case t)) | |
481 (setq arg (downcase | |
482 (vm-read-string | |
483 prompt | |
484 (vm-obarray-to-string-list | |
485 vm-label-obarray) | |
486 nil))))) | |
487 (t (setq arg (read-string prompt)))))) | |
488 (list selector arg))) | |
489 | |
490 ;; clear away links between real and virtual folders when | |
491 ;; a vm-quit is performed in either type folder. | |
492 (defun vm-virtual-quit () | |
493 (save-excursion | |
494 (cond ((eq major-mode 'vm-virtual-mode) | |
495 ;; don't trust blindly, user might have killed some of | |
496 ;; these buffers. | |
497 (setq vm-real-buffers (vm-delete 'buffer-name vm-real-buffers t)) | |
498 (let ((bp vm-real-buffers) | |
499 (mp vm-message-list) | |
500 (b (current-buffer)) | |
501 ;; lock out interrupts here | |
502 (inhibit-quit t)) | |
503 (while bp | |
504 (set-buffer (car bp)) | |
505 (setq vm-virtual-buffers (delq b vm-virtual-buffers) | |
506 bp (cdr bp))) | |
507 (while mp | |
508 (vm-set-virtual-messages-of | |
509 (vm-real-message-of (car mp)) | |
510 (delq (car mp) (vm-virtual-messages-of | |
511 (vm-real-message-of (car mp))))) | |
512 (setq mp (cdr mp))))) | |
513 ((eq major-mode 'vm-mode) | |
514 ;; don't trust blindly, user might have killed some of | |
515 ;; these buffers. | |
516 (setq vm-virtual-buffers | |
517 (vm-delete 'buffer-name vm-virtual-buffers t)) | |
518 (let ((bp vm-virtual-buffers) | |
519 (mp vm-message-list) | |
520 vmp | |
521 (b (current-buffer)) | |
522 ;; lock out interrupts here | |
523 (inhibit-quit t)) | |
524 (while mp | |
525 (setq vmp (vm-virtual-messages-of (car mp))) | |
526 (while vmp | |
527 ;; we'll clear these messages from the virtual | |
528 ;; folder by looking for messages that have a "Q" | |
529 ;; id number associated with them. | |
530 (vm-set-message-id-number-of (car vmp) "Q") | |
531 (setq vmp (cdr vmp))) | |
532 (vm-set-virtual-messages-of (car mp) nil) | |
533 (setq mp (cdr mp))) | |
534 (while bp | |
535 (set-buffer (car bp)) | |
536 (setq vm-real-buffers (delq b vm-real-buffers)) | |
537 ;; set the message pointer to a new value if it is | |
538 ;; now invalid. | |
539 (setq vmp vm-message-pointer) | |
540 (while (and vm-message-pointer | |
541 (equal "Q" (vm-message-id-number-of | |
542 (car vm-message-pointer)))) | |
543 (setq vm-message-pointer | |
544 (cdr vm-message-pointer))) | |
545 ;; if there were no good messages ahead, try going | |
546 ;; backward. | |
547 (if (null vm-message-pointer) | |
548 (progn | |
549 (setq vm-message-pointer vmp) | |
550 (while (and vm-message-pointer | |
551 (equal "Q" (vm-message-id-number-of | |
552 (car vm-message-pointer)))) | |
553 (setq vm-message-pointer | |
554 (vm-reverse-link-of (car vm-message-pointer)))))) | |
555 ;; expunge the virtual messages associated with | |
556 ;; real messages that are going away. | |
557 (setq vm-message-list | |
558 (vm-delete (function | |
559 (lambda (m) | |
560 (equal "Q" (vm-message-id-number-of m)))) | |
561 vm-message-list nil)) | |
562 (if (null vm-message-pointer) | |
563 (setq vm-message-pointer vm-message-list)) | |
564 ;; same for vm-last-message-pointer | |
565 (if (null vm-last-message-pointer) | |
566 (setq vm-last-message-pointer nil)) | |
567 (vm-clear-virtual-quit-invalidated-undos) | |
568 (vm-reverse-link-messages) | |
569 (vm-set-numbering-redo-start-point t) | |
570 (vm-set-summary-redo-start-point t) | |
571 (if vm-message-pointer | |
572 (vm-preview-current-message) | |
573 (vm-update-summary-and-mode-line)) | |
574 (setq bp (cdr bp)))))))) | |
575 | |
576 (defun vm-virtual-save-folder (prefix) | |
577 (save-excursion | |
578 ;; don't trust blindly, user might have killed some of | |
579 ;; these buffers. | |
580 (setq vm-real-buffers (vm-delete 'buffer-name vm-real-buffers t)) | |
581 (let ((bp vm-real-buffers)) | |
582 (while bp | |
583 (set-buffer (car bp)) | |
584 (vm-save-folder prefix) | |
585 (setq bp (cdr bp))))) | |
586 (vm-set-buffer-modified-p nil) | |
587 (vm-clear-modification-flag-undos) | |
588 (vm-update-summary-and-mode-line)) | |
589 | |
590 (defun vm-virtual-get-new-mail () | |
591 (save-excursion | |
592 ;; don't trust blindly, user might have killed some of | |
593 ;; these buffers. | |
594 (setq vm-real-buffers (vm-delete 'buffer-name vm-real-buffers t)) | |
595 (let ((bp vm-real-buffers)) | |
596 (while bp | |
597 (set-buffer (car bp)) | |
598 (condition-case error-data | |
599 (vm-get-new-mail) | |
600 (folder-read-only | |
601 (message "Folder is read only: %s" | |
602 (or buffer-file-name (buffer-name))) | |
603 (sit-for 1)) | |
604 (unrecognized-folder-type | |
605 (message "Folder type is unrecognized: %s" | |
606 (or buffer-file-name (buffer-name))) | |
607 (sit-for 1))) | |
608 (setq bp (cdr bp))))) | |
609 (vm-emit-totals-blurb)) | |
610 | |
611 (defun vm-make-virtual-copy (m) | |
612 (widen) | |
613 (let ((virtual-buffer (current-buffer)) | |
614 (real-m (vm-real-message-of m)) | |
615 (buffer-read-only nil) | |
616 (modified (buffer-modified-p))) | |
617 (unwind-protect | |
618 (save-excursion | |
619 (set-buffer (vm-buffer-of real-m)) | |
620 (save-restriction | |
621 (widen) | |
622 ;; must reference this now so that headers will be in | |
623 ;; their final position before the message is copied. | |
624 ;; otherwise the vheader offset computed below will be wrong. | |
625 (vm-vheaders-of real-m) | |
626 (copy-to-buffer virtual-buffer (vm-start-of real-m) | |
627 (vm-end-of real-m)))) | |
628 (set-buffer-modified-p modified)) | |
629 (set-marker (vm-start-of m) (point-min)) | |
630 (set-marker (vm-headers-of m) (+ (vm-start-of m) | |
631 (- (vm-headers-of real-m) | |
632 (vm-start-of real-m)))) | |
633 (set-marker (vm-vheaders-of m) (+ (vm-start-of m) | |
634 (- (vm-vheaders-of real-m) | |
635 (vm-start-of real-m)))) | |
636 (set-marker (vm-text-of m) (+ (vm-start-of m) (- (vm-text-of real-m) | |
637 (vm-start-of real-m)))) | |
638 (set-marker (vm-text-end-of m) (+ (vm-start-of m) | |
639 (- (vm-text-end-of real-m) | |
640 (vm-start-of real-m)))) | |
641 (set-marker (vm-end-of m) (+ (vm-start-of m) (- (vm-end-of real-m) | |
642 (vm-start-of real-m)))))) |