;;; -*-Scheme-*-
;;;
-;;; $Id: imail-core.scm,v 1.144 2001/06/12 00:47:19 cph Exp $
+;;; $Id: imail-core.scm,v 1.145 2001/09/14 02:06:39 cph Exp $
;;;
;;; Copyright (c) 1999-2001 Massachusetts Institute of Technology
;;;
(define-method url-base-name ((resource <resource>))
(url-base-name (resource-locator resource)))
-(define-class <folder> (<resource>))
+(define-class <folder> (<resource>)
+ (permutation define accessor
+ initial-value #f))
+
+(define set-folder-permutation!
+ (let ((modifier (slot-modifier <folder> 'PERMUTATION)))
+ (lambda (folder permutation)
+ (modifier folder permutation)
+ (object-modified! folder 'PERMUTED))))
+
(define-class <container> (<resource>))
(define-method resource-type-name ((r <folder>)) r 'FOLDER)
(guarantee-index index 'GET-MESSAGE)
(if (not (< index (folder-length folder)))
(error:bad-range-argument index 'GET-MESSAGE))
- (%get-message folder index))
+ (%get-message folder
+ (let ((permutation (folder-permutation folder)))
+ (if permutation
+ (permute-index permutation folder index)
+ index))))
(define-generic %get-message (folder index))
(folder define standard
initial-value #f)
(index define standard
+ accessor %message-index
initial-value #f))
(define-method write-instance ((message <message>) port)
(write-char #\space port)
(write (message-folder message) port)
(write-char #\space port)
- (write (message-index message) port))))
+ (write (%message-index message) port))))
(define (guarantee-message message procedure)
(if (not (message? message))
(define-generic message-internal-time (message))
(define-generic message-length (message))
+(define (message-index message)
+ (let ((index (%message-index message))
+ (folder (message-folder message)))
+ (let ((permutation
+ (and folder
+ (folder-permutation folder))))
+ (if permutation
+ (unpermute-index permutation folder index)
+ index))))
+
(define %set-message-flags!
(let ((modifier (slot-modifier <message> 'FLAGS)))
(lambda (message flags)
(define (first-unseen-message folder)
(let ((end (folder-length folder)))
- (let loop ((start (first-unseen-message-index folder)))
+ (let loop
+ ((start
+ (if (folder-permutation folder)
+ 0
+ (first-unseen-message-index folder))))
(and (< start end)
(let ((message (get-message folder start)))
(if (message-seen? message)
message
(loop index)))))))))
\f
+;;;; Folder permutations
+
+(define-structure (folder-permutation
+ (type-descriptor folder-permutation-rtd)
+ (constructor make-folder-permutation (predicate)))
+ (predicate #f read-only #t)
+ (forward #f)
+ (reverse #f)
+ (modification-count -1))
+
+(define (permute-index permutation folder index)
+ (guarantee-valid-permutation permutation folder)
+ (let ((v (folder-permutation-forward permutation)))
+ (if (fix:< index (vector-length v))
+ (vector-ref v index)
+ index)))
+
+(define (unpermute-index permutation folder index)
+ (guarantee-valid-permutation permutation folder)
+ (let ((v (folder-permutation-reverse permutation)))
+ (if (fix:< index (vector-length v))
+ (vector-ref v index)
+ index)))
+
+(define (guarantee-valid-permutation permutation folder)
+ (let loop ()
+ (let ((count (object-modification-count folder)))
+ (if (not (= (folder-permutation-modification-count permutation) count))
+ (begin
+ (let ((n (folder-length folder)))
+ (let ((vf (make-vector n))
+ (vr (make-vector n)))
+ (do ((i 0 (fix:+ i 1)))
+ ((fix:= i n))
+ (vector-set! vf i (%get-message folder i)))
+ (sort! vf (folder-permutation-predicate permutation))
+ (do ((i 0 (fix:+ i 1)))
+ ((fix:= i n))
+ (let ((j (%message-index (vector-ref vf i))))
+ (vector-set! vf i j)
+ (vector-set! vr j i)))
+ (set-folder-permutation-forward! permutation vf)
+ (set-folder-permutation-reverse! permutation vr)))
+ (set-folder-permutation-modification-count! permutation count)
+ (loop))))))
+\f
;;;; Message flags
;;; Flags are markers that can be attached to messages. They indicate
;;; -*-Scheme-*-
;;;
-;;; $Id: imail-imap.scm,v 1.184 2001/07/21 03:53:36 cph Exp $
+;;; $Id: imail-imap.scm,v 1.185 2001/09/14 02:06:53 cph Exp $
;;;
;;; Copyright (c) 1999-2001 Massachusetts Institute of Technology
;;;
(if (not (initpred message))
(with-imap-message-open message
(lambda (connection)
- (let ((index (message-index message)))
+ (let ((index (%message-index message)))
(let ((suffix
(string-append " UID for message "
(number->string (+ index 1)))))
(let ((suffix
(string-append
" " noun " for message "
- (number->string (+ (message-index message) 1)))))
+ (number->string (+ (%message-index message) 1)))))
((imail-ui:message-wrapper "Reading" suffix)
(lambda ()
(imap:read-literal-progress-hook imail-ui:progress-meter
(reverse! messages)))))
(define (message-list->set messages)
- (let loop ((indexes (map message-index messages)) (groups '()))
+ (let loop ((indexes (map %message-index messages)) (groups '()))
(if (pair? indexes)
(let ((start (car indexes)))
(let parse-group ((this start) (rest (cdr indexes)))
(string-append " body"
(if (equal? section '(TEXT)) "" " part")
" for message "
- (number->string (+ (message-index message) 1)))))
+ (number->string (+ (%message-index message) 1)))))
((imail-ui:message-wrapper "Reading" suffix)
(lambda ()
(imap:read-literal-progress-hook imail-ui:progress-meter
(with-imap-connection-folder connection
(lambda (folder)
(process-fetch-attributes
- (get-message folder
- (- (imap:response:fetch-index response) 1))
+ (%get-message folder
+ (- (imap:response:fetch-index response) 1))
response)))
(eq? command 'FETCH))
(else