(lambda (port)
(write-header-fields (message-header-fields message) port)
(write-message-body message port))))
-
+\f
(define (message-time message)
- (let ((date (get-first-header-field-value message "date" #f)))
- (and date
- (parse-header-field-date date))))
+ (intern-property! message '|#[(edwin imail)message-time]|
+ (lambda (message)
+ (let ((date (get-first-header-field-value message "date" #f)))
+ (and date
+ (parse-header-field-date date))))))
+
+(define (message-subject message)
+ (intern-property! message '|#[(edwin imail)message-subject|
+ (lambda (message)
+ (cond ((get-first-header-field-value message "subject" #f)
+ => strip-subject-re)
+ (else "")))))
+
+(define (strip-subject-re subject)
+ (let ((end (string-length subject)))
+ (let loop ((start 0))
+ (if (and (fix:<= 3 (fix:- end start))
+ (substring-prefix-ci? "Re:" 0 3 subject (fix:+ start 3) end))
+ (loop
+ (substring-find-next-char-in-set subject (fix:+ start 3) end
+ char-set:subject-content))
+ (string-tail subject start)))))
+
+(define char-set:subject-content (char-set-invert (char-set #\space #\tab)))
+
+(define (message-author message)
+ (intern-property! message '|#[(edwin imail)message-author|
+ (lambda (message)
+ (or (get-first-header-field-address message "from" #f)
+ (get-first-header-field-address message "sender" #f)
+ ""))))
+
+(define (message-recipient message)
+ (intern-property! message '|#[(edwin imail)message-recipient]|
+ (lambda ()
+ (or (get-first-header-field-address message "to" #f)
+ (get-first-header-field-address message "apparently-to" #f)
+ ""))))
+
+(define (get-first-header-field-address message name error?)
+ (let ((v (get-first-header-field-value message name error?)))
+ (and v
+ (rfc822:first-address v))))
\f
;;;; Message Navigation
(else s))))
(define (message-summary-subject-string message)
- (let ((s
- (let ((s (or (get-first-header-field-value message "subject" #f) "")))
- (let ((regs (re-string-match "\\(re:[ \t]*\\)+" s #t)))
- (if regs
- (string-tail s (re-match-end-index 0 regs))
- s)))))
- (let ((i (string-find-next-char s #\newline)))
- (if i
- (string-head s i)
- s))))
+ (let ((subject (message-subject message)))
+ (cond ((string-find-next-char subject #\newline)
+ => (lambda (line-end) (string-head subject line-end)))
+ (else subject))))
\f
;;;; Navigation
(set-buffer-point! buffer point)
(mark-temporary! point)
value)))
-
-(define (message-subject message)
- (let ((subject (get-first-header-field-value message "subject" #f)))
- (if subject
- (strip-subject-re subject)
- "")))
-
-(define (strip-subject-re subject)
- (if (string-prefix-ci? "re:" subject)
- (strip-subject-re (string-trim-left (string-tail subject 3)))
- subject))
-
-(define (message-author message)
- (or (get-first-header-field-address message "from" #f)
- (get-first-header-field-address message "sender" #f)
- ""))
-
-(define (message-recipient message)
- (or (get-first-header-field-address message "to" #f)
- (get-first-header-field-address message "apparently-to" #f)
- ""))
-
-(define (get-first-header-field-address message name error?)
- (let ((v (get-first-header-field-value message name error?)))
- (and v
- (rfc822:first-address v))))
\f
;;;; Folder Operations
(define (remove-property! object key)
(set-object-properties! object (del-assq! key (object-properties object))))
+(define (intern-property! object key generator)
+ (let* ((default (cons 0 0))
+ (datum (get-property object key default)))
+ (if (eq? datum default)
+ (let ((datum (generator object)))
+ (store-property! object key datum)
+ datum)
+ datum)))
+\f
;;;; Modification events
(define-class <modification-event-mixin> ()