(defcustom elmo-message-fetch-threshold 30000
"Fetch threshold."
- :type 'integer
+ :type '(choice (integer :tag "Threshold (bytes)")
+ (const :tag "No limitation" nil))
:group 'elmo)
(defcustom elmo-message-fetch-confirm t
(defmacro elmo-folder-type (name)
"Get folder type from NAME string."
`(and (stringp ,name)
- (or (cdr (assoc (string-to-char ,name) elmo-folder-type-alist))
- (when (string-match "\\([^:]*\\):" ,name)
- (intern (match-string 1 ,name))))))
+ (cdr (assoc (string-to-char ,name) elmo-folder-type-alist))))
;;; ELMO folder
;; A elmo folder provides uniformed (orchestrated) access
path ; directory path for msgdb.
msgdb ; msgdb (may be nil).
killed-list ; killed list.
+ flag-table ; flag table.
persistent ; non-nil if persistent.
process-duplicates ; read or hide
biff ; folder for biff
(setq list (elmo-msgdb-list-messages (elmo-folder-msgdb folder))))
(if visible-only
(elmo-living-messages list killed-list)
- (if in-msgdb
- (elmo-uniq-list
- (nconc (elmo-number-set-to-number-list killed-list) list)
- #'delq)
+ (if (and in-msgdb killed-list)
+ (elmo-uniq-sorted-list
+ (sort (nconc (elmo-number-set-to-number-list killed-list) list) #'<)
+ #'eq)
list))))
(luna-define-generic elmo-folder-list-messages-internal (folder &optional
`important' (remove important flag)
'sugar' flag:
`read' (set unread flag)
+ `all' (remove all flags)
If optional IS-LOCAL is non-nil, update only local (not server) status.")
(luna-define-generic elmo-folder-next-message-number (folder)
"The next message number that will be assigned to a new message.
FOLDER is the ELMO folder structure.")
-(luna-define-generic elmo-folder-append-buffer (folder &optional flag
+(luna-define-generic elmo-folder-append-buffer (folder &optional flags
number)
"Append current buffer as a new message.
-FOLDER is the destination folder(ELMO folder structure).
-FLAG is the status of appended message.
+FOLDER is the destination folder (ELMO folder structure).
+FLAGS is the status of appended message (list of symbols).
+If it is nil, it is not that there is no flag and what is not defined is meant.
If optional argument NUMBER is specified, the new message number is set
-\(if possible\).")
+\(if possible\).
+Return nil on failure.")
(luna-define-generic elmo-folder-append-messages (folder
src-folder
SRC-FOLDER is the source ELMO folder structure.
NUMBERS is the message numbers to be appended in the SRC-FOLDER.
If second optional argument SAME-NUMBER is specified,
-message number is preserved \(if possible\).")
+message number is preserved \(if possible\).
+Returns a list of message numbers successfully appended.")
(luna-define-generic elmo-folder-pack-numbers (folder)
"Pack message numbers of FOLDER.")
(luna-define-generic elmo-message-file-p (folder number)
"Return t if message in the FOLDER with NUMBER is a file.")
-(luna-define-generic elmo-message-flags (folder number)
+(luna-define-generic elmo-message-flags (folder number &optional msgid)
"Return a list of flags.
FOLDER is a ELMO folder structure.
-NUMBER is a number of the message.")
-
-(luna-define-method elmo-message-flags ((folder elmo-folder) number)
- (elmo-msgdb-flags (elmo-folder-msgdb folder) number))
+NUMBER is a number of the message.
+If optional argument MSGID is specified,
+the message with NUMBER checks whether it has MSGID.")
+
+(luna-define-method elmo-message-flags ((folder elmo-folder) number
+ &optional msgid)
+ (if msgid
+ (let ((this-id (elmo-message-field folder number 'message-id)))
+ (and this-id
+ (string= this-id msgid)
+ (or (elmo-msgdb-flags (elmo-folder-msgdb folder) number)
+ '(read))))
+ (elmo-msgdb-flags (elmo-folder-msgdb folder) number)))
(defsubst elmo-message-flagged-p (folder number flag)
"Return non-nil if the message is set FLAG.
nil nil (not read))
path))
+(luna-define-generic elmo-message-fetch-bodystructure (folder number strategy)
+ "Fetch bodystructure of the message in FOLDER with NUMBER using STRATEGY.")
+
(luna-define-generic elmo-message-fetch (folder number strategy
&optional
section
(luna-define-method elmo-message-match-condition ((folder elmo-folder)
number condition
numbers)
- (let ((filename (cond
- ((elmo-message-file-name folder number))
- ((let* ((cache (elmo-file-cache-get
- (elmo-message-field folder number
- 'message-id)))
- (cache-path (elmo-file-cache-path cache)))
- (when (and cache-path
- (not (elmo-cache-path-section-p cache-path)))
- cache-path))))))
- (when (and filename
- (file-readable-p filename))
+ (let* (cache cache-path
+ (filename (cond
+ ((elmo-message-file-name folder number))
+ ((progn
+ (setq cache (elmo-file-cache-get
+ (elmo-message-field folder number
+ 'message-id)))
+ (setq cache-path (elmo-file-cache-path cache))
+ (and cache-path
+ (not (elmo-cache-path-section-p cache-path))))
+ cache-path))))
+ (when (and filename (file-readable-p filename))
(with-temp-buffer
- (insert-file-contents-as-binary filename)
- (elmo-set-buffer-multibyte default-enable-multibyte-characters)
- ;; Should consider charset?
- (decode-mime-charset-region (point-min) (point-max) elmo-mime-charset)
+ (set-buffer-multibyte nil)
+ ;;(insert-file-contents-as-binary filename)
+ (elmo-message-fetch folder number
+ (elmo-make-fetch-strategy 'entire
+ (and cache t)
+ nil
+ cache-path)
+ nil (current-buffer) t)
+ (set-buffer-multibyte default-enable-multibyte-characters)
+ (decode-coding-region (point-min) (point-max)
+ elmo-mime-display-as-is-coding-system)
(elmo-buffer-field-condition-match condition number numbers)))))
(luna-define-method elmo-folder-pack-numbers ((folder elmo-folder))
(luna-define-method elmo-folder-have-subfolder-p ((folder elmo-folder))
t)
+;; Flag table
+(luna-define-generic elmo-folder-flag-table (folder &optional if-exists)
+ "Return the flag-table of FOLDER.
+If optional argument IF-EXISTS is nil, load on demand.
+\(For internal use only.\)")
+
+(luna-define-generic elmo-folder-close-flag-table (folder)
+ "Close flag-table of FOLDER.")
+
+(luna-define-method elmo-folder-flag-table ((folder elmo-folder)
+ &optional if-exists)
+ (or (elmo-folder-flag-table-internal folder)
+ (unless if-exists
+ (elmo-folder-set-flag-table-internal
+ folder
+ (elmo-flag-table-load (elmo-folder-msgdb-path folder))))))
+
+(luna-define-method elmo-folder-close-flag-table ((folder elmo-folder))
+ (elmo-flag-table-save (elmo-folder-msgdb-path folder)
+ (elmo-folder-flag-table folder))
+ (elmo-folder-set-flag-table-internal folder nil))
+
+(defun elmo-folder-preserve-flags (folder msgid flags)
+ "Preserve FLAGS into FOLDER for a message that has MSGID."
+ (when (and msgid flags)
+ (let ((flag-table (elmo-folder-flag-table folder 'if-exists))
+ load-now)
+ (when (setq load-now (null flag-table))
+ (setq flag-table (elmo-folder-flag-table folder)))
+ (elmo-flag-table-set flag-table msgid flags)
+ (when load-now
+ (elmo-folder-close-flag-table folder)))))
+
;;; Folder info
;; Folder info is a message number information cache (hashtable)
(defsubst elmo-folder-get-info (folder &optional hashtb)
(defun elmo-generic-folder-append-messages (folder src-folder numbers
same-number)
(let ((src-msgdb-exists (not (zerop (elmo-folder-length src-folder))))
- unseen table flags
+ unseen table
succeed-numbers failure cache id)
- (setq table (elmo-flag-table-load (elmo-folder-msgdb-path folder)))
+ (setq table (elmo-folder-flag-table folder))
(with-temp-buffer
(set-buffer-multibyte nil)
(while numbers
(setq failure nil
id (and src-msgdb-exists
(elmo-message-field src-folder (car numbers)
- 'message-id))
- flags (elmo-message-flags src-folder (car numbers)))
+ 'message-id)))
(condition-case nil
(setq cache (elmo-file-cache-get id)
failure
(> (buffer-size) 0)
(elmo-folder-append-buffer
folder
- (or flags '(read))
+ (elmo-message-flags
+ src-folder
+ (car numbers)
+ (elmo-msgdb-get-message-id-from-buffer))
(if same-number (car numbers))))))
(error (setq failure t)))
;; FETCH & APPEND finished
(unless failure
- (when id
- (elmo-flag-table-set table id flags))
(setq succeed-numbers (cons (car numbers) succeed-numbers)))
(elmo-progress-notify 'elmo-folder-move-messages)
(setq numbers (cdr numbers)))
(when (elmo-folder-persistent-p folder)
- (elmo-flag-table-save (elmo-folder-msgdb-path folder) table))
+ (elmo-folder-close-flag-table folder))
succeed-numbers)))
;; Arguments should be reduced.
(luna-define-method elmo-message-field ((folder elmo-folder) number field)
(elmo-message-entity-field (elmo-message-entity folder number) field))
+(luna-define-generic elmo-message-set-field (folder number field value)
+ "Set message field value in the msgdb.
+FOLDER is the ELMO folder structure.
+NUMBER is a number of the message.
+FIELD is a symbol of the field.
+VALUE is a value to set.")
+
+(luna-define-method elmo-message-set-field ((folder elmo-folder) number
+ field value)
+ (elmo-message-entity-set-field (elmo-message-entity folder number)
+ field value))
+
(luna-define-method elmo-message-use-cache-p ((folder elmo-folder) number)
nil) ; default is not use cache.
(nthcdr (max (- len elmo-folder-update-threshold) 0) appends)
appends))))
+(luna-define-method elmo-message-fetch-bodystructure ((folder elmo-folder)
+ number strategy)
+ nil)
+
(luna-define-method elmo-message-fetch ((folder elmo-folder)
number strategy
&optional
unread)
(error (setq err error) nil))
(> (buffer-size) 0))
- (elmo-delete-cr-buffer)
(when (and (elmo-fetch-strategy-save-cache strategy)
cache-path)
(elmo-file-cache-save cache-path section))
(defun elmo-folder-kill-messages (folder numbers)
"Kill(hide) messages in the FOLDER with NUMBERS."
- (let ((msgdb (elmo-folder-msgdb folder))
- (killed (elmo-folder-killed-list-internal folder)))
- (dolist (number numbers)
- (elmo-number-set-append killed number)
- (elmo-msgdb-unset-flag msgdb number 'all))
- (elmo-folder-set-killed-list-internal folder killed)))
-
+ (elmo-folder-set-killed-list-internal
+ folder
+ (elmo-number-set-append-list
+ (elmo-folder-killed-list-internal folder)
+ numbers))
+ (elmo-folder-unset-flag folder numbers 'all 'local-only))
(luna-define-method elmo-folder-clear ((folder elmo-folder)
&optional keep-killed)
&optional
disable-killed
ignore-msgdb
- no-check)
+ no-check
+ mask)
"Synchronize the folder data to the newest status.
FOLDER is the ELMO folder structure.
If optional IGNORE-MSGDB is non-nil, current msgdb is thrown away except
flag status.
If NO-CHECK is non-nil, rechecking folder is skipped.
-Return a list of a cross-posted message number.
+If optional argument MASK is specified and is a list of message numbers,
+synchronize messages only which are contained the list.
+Return amount of cross-posted messages.
If update process is interrupted, return nil.")
(luna-define-method elmo-folder-synchronize ((folder elmo-folder)
&optional
disable-killed
ignore-msgdb
- no-check)
+ no-check
+ mask)
(let ((killed-list (elmo-folder-killed-list-internal folder))
(before-append t)
old-msgdb diff diff-2 delete-list new-list new-msgdb flag
folder
(not disable-killed)
'in-msgdb)))
+ (when (and mask (car diff))
+ (setcar diff (elmo-list-filter mask (car diff))))
(message "Checking folder diff...done")
(setq new-list (elmo-folder-confirm-appends (car diff)))
;; Set killed list as ((1 . MAX-OF-DISAPPEARED))