(elmo-define-error 'elmo-authenticate-error "Login failed" 'elmo-open-error)
(elmo-define-error 'elmo-imap4-bye-error "IMAP4 session was terminated" 'elmo-open-error)
+;; autoloads
+(eval-and-compile
+ (autoload 'elmo-dop-queue-flush "elmo-dop")
+ (autoload 'elmo-nntp-post "elmo-nntp")
+ (autoload 'elmo-global-flag-initialize "elmo-flag")
+ (autoload 'elmo-global-flag-p "elmo-flag")
+ (autoload 'elmo-global-flag-detach "elmo-flag")
+ (autoload 'elmo-global-flag-detach-messages "elmo-flag")
+ (autoload 'elmo-global-flag-set "elmo-flag"))
+
(defun elmo-define-folder (prefix backend)
"Define a folder.
If a folder name begins with PREFIX, use BACKEND."
msgdb ; msgdb (may be nil).
killed-list ; killed list.
persistent ; non-nil if persistent.
- message-modified ; message is modified.
- mark-modified ; mark is modified.
process-duplicates ; read or hide
biff ; folder for biff
))
(setq prefix (substring name 0 1))
(setq name (substring name 1)))
(setq type (intern (car (setq split (split-string name ":")))))
- (if (> (length split) 2)
+ (if (>= (length split) 2)
(setq name (substring name (+ 1 (length (car split)))))
(error "Error in folder name `%s'" original))
(setq prefix (concat (car split) ":")))
(luna-define-method elmo-folder-msgdb ((folder elmo-folder))
(or (elmo-folder-msgdb-internal folder)
(elmo-folder-set-msgdb-internal folder
- (elmo-msgdb-load folder))))
+ (elmo-folder-msgdb-load folder))))
+
(luna-define-generic elmo-folder-open (folder &optional load-msgdb)
"Open and setup (load saved status) FOLDER.
If optional LOAD-MSGDB is non-nil, msgdb is loaded.
"Return a list of message numbers contained in FOLDER.
If optional VISIBLE-ONLY is non-nil, killed messages are not listed.
If second optional IN-MSGDB is non-nil, only messages in the msgdb are listed.")
+
(luna-define-method elmo-folder-list-messages ((folder elmo-folder)
&optional visible-only in-msgdb)
(let ((list (if in-msgdb
t
- (elmo-folder-list-messages-internal folder visible-only))))
- (setq list
- (if (listp list)
- list
- ;; Use current list.
- (elmo-msgdb-list-messages (elmo-folder-msgdb folder))))
+ (elmo-folder-list-messages-internal folder visible-only)))
+ (killed-list (elmo-folder-killed-list-internal folder)))
+ (unless (listp list)
+ ;; Use current list.
+ (setq list (elmo-msgdb-list-messages (elmo-folder-msgdb folder))))
(if visible-only
- (elmo-living-messages list (elmo-folder-killed-list-internal folder))
- list)))
+ (elmo-living-messages list killed-list)
+ (if in-msgdb
+ (elmo-uniq-list
+ (nconc (elmo-number-set-to-number-list killed-list) list)
+ #'delq)
+ list))))
(luna-define-generic elmo-folder-list-unreads (folder)
"Return a list of unread message numbers contained in FOLDER.")
(luna-define-generic elmo-folder-list-answereds (folder)
"Return a list of answered message numbers contained in FOLDER.")
-;; TODO: Should reconsider the structure of global mark.
-(defun elmo-folder-list-messages-with-global-mark (folder mark)
- (let (entity msgs)
- (dolist (mark-pair (or elmo-msgdb-global-mark-alist
- (setq elmo-msgdb-global-mark-alist
- (elmo-object-load
- (expand-file-name
- elmo-msgdb-global-mark-filename
- elmo-msgdb-directory)))))
- (if (and (string= mark (cdr mark-pair))
- (setq entity
- (elmo-msgdb-overview-get-entity (car mark-pair)
- (elmo-folder-msgdb
- folder))))
- (setq msgs (cons (elmo-msgdb-overview-entity-get-number entity)
- msgs))))
- msgs))
-
(luna-define-generic elmo-folder-list-flagged (folder flag &optional in-msgdb)
"List messages in the FOLDER with FLAG.
FLAG is a symbol which is one of the following:
(luna-define-generic elmo-folder-delete-messages (folder numbers)
"Delete messages.
FOLDER is the ELMO folder structure.
-NUMBERS is a list of message numbers to be deleted.")
+NUMBERS is a list of message numbers to be deleted.
+It is not recommended to use this function other than internal use.
+Use `elmo-folder-move-messages' with dst-folder 'null instead.")
(luna-define-generic elmo-folder-search (folder condition &optional numbers)
"Search and return list of message numbers.
NUMBERS is a list of message numbers to create msgdb.
FLAG-TABLE is a hashtable of message-id and flag.")
-(luna-define-generic elmo-folder-unmark-important (folder
+(luna-define-generic elmo-folder-unflag-important (folder
numbers
- &optional ignore-flags)
- "Un-mark messages as important.
+ &optional is-local)
+ "Un-flag messages as important.
FOLDER is the ELMO folder structure.
NUMBERS is a list of message numbers to be processed.
-If IGNORE-FLAGS is non-nil, folder flags are not updated.")
+If IS-LOCAL is non-nil, only the local flag is updated.")
-(luna-define-generic elmo-folder-mark-as-important (folder
+(luna-define-generic elmo-folder-flag-as-important (folder
numbers
- &optional ignore-flags)
- "Mark messages as important.
+ &optional is-local)
+ "Flag messages as important.
FOLDER is the ELMO folder structure.
NUMBERS is a list of message numbers to be processed.
-If IGNORE-FLAGS is non-nil, folder flags are not updated.")
+If IS-LOCAL is non-nil, only the local flag is updated.")
-(luna-define-generic elmo-folder-unmark-read (folder numbers
- &optional ignore-flags)
- "Un-mark messages as read.
+(luna-define-generic elmo-folder-unflag-read (folder numbers
+ &optional is-local)
+ "Un-flag messages as read.
FOLDER is the ELMO folder structure.
NUMBERS is a list of message numbers to be processed.
-If IGNORE-FLAGS is non-nil, folder flags are not updated.")
+If IS-LOCAL is non-nil, only the local flag is updated.")
-(luna-define-generic elmo-folder-mark-as-read (folder numbers
- &optional ignore-flags)
- "Mark messages as read.
+(luna-define-generic elmo-folder-flag-as-read (folder numbers
+ &optional is-local)
+ "Flag messages as read.
FOLDER is the ELMO folder structure.
NUMBERS is a list of message numbers to be processed.
-If IGNORE-FLAGS is non-nil, folder flags are not updated.")
+If IS-LOCAL is non-nil, only the local flag is updated.")
-(luna-define-generic elmo-folder-unmark-answered (folder numbers)
- "Un-mark messages as answered.
+(luna-define-generic elmo-folder-unflag-answered (folder numbers
+ &optional is-local)
+ "Un-flag messages as answered.
FOLDER is the ELMO folder structure.
-NUMBERS is a list of message numbers to be processed.")
+If IS-LOCAL is non-nil, only the local flag is updated.")
-(luna-define-generic elmo-folder-mark-as-answered (folder numbers)
- "Mark messages as answered.
+(luna-define-generic elmo-folder-flag-as-answered (folder numbers
+ &optional is-local)
+ "Flag messages as answered.
FOLDER is the ELMO folder structure.
-NUMBERS is a list of message numbers to be processed.")
+If IS-LOCAL is non-nil, only the local flag is updated.")
+
+(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
number)
"Append messages from folder.
FOLDER is the ELMO folder structure.
Caller should make sure FOLDER is `writable'.
-(Can be checked with `elmo-folder-writable-p').
+\(Can be checked with `elmo-folder-writable-p'\).
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\).")
(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)
+ "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))
+
+(defsubst elmo-message-flagged-p (folder number flag)
+ "Return non-nil if the message is set FLAG.
+FOLDER is a ELMO folder structure.
+NUMBER is a message number to test."
+ (let ((cur-flags (elmo-message-flags folder number)))
+ (case flag
+ (read
+ (not (memq 'unread cur-flags)))
+ (t
+ (memq flag cur-flags)))))
+
(luna-define-generic elmo-find-fetch-strategy
(folder entity &optional ignore-cache)
;; Returns the message fetching strategy suitable for the message.
(luna-define-method elmo-find-fetch-strategy
((folder elmo-folder) entity &optional ignore-cache)
(let (cache-file size message-id number)
- (setq size (elmo-msgdb-overview-entity-get-size entity))
- (setq message-id (elmo-msgdb-overview-entity-get-id entity))
- (setq number (elmo-msgdb-overview-entity-get-number entity))
+ (setq size (elmo-message-entity-field entity 'size))
+ (setq message-id (elmo-message-entity-field entity 'message-id))
+ (setq number (elmo-message-entity-number entity))
(setq cache-file (elmo-file-cache-get message-id))
(setq ignore-cache (or ignore-cache
(null (elmo-message-use-cache-p folder number))))
(defun elmo-folder-encache (folder numbers &optional unread)
"Encache messages in the FOLDER with NUMBERS.
-If UNREAD is non-nil, messages are not marked as read."
+If UNREAD is non-nil, messages are not flaged as read."
(dolist (number numbers)
(elmo-message-encache folder number unread)))
(luna-define-generic elmo-message-encache (folder number &optional read)
"Encache message in the FOLDER with NUMBER.
-If READ is non-nil, message is marked as read.")
+If READ is non-nil, message is flaged as read.")
(luna-define-method elmo-message-encache ((folder elmo-folder) number
&optional read)
- (elmo-message-fetch
- folder number
- (elmo-make-fetch-strategy 'entire
- nil ;use-cache
- t ;save-cache
- (elmo-file-cache-get-path
- (elmo-message-field
- folder number 'message-id)))
- nil nil (not read)))
+ (let (path)
+ (elmo-message-fetch
+ folder number
+ (elmo-make-fetch-strategy 'entire
+ nil ;use-cache
+ t ;save-cache
+ (setq path (elmo-file-cache-get-path
+ (elmo-message-field
+ folder number 'message-id))))
+ nil nil (not read))
+ path))
(luna-define-generic elmo-message-fetch (folder number strategy
&optional
is fetched (if possible).
If second optional argument OUTBUF is specified, fetched message is
inserted to the buffer and returns t if fetch was ended successfully.
-If third optional argument UNREAD is non-nil, message is not marked as read.
+If third optional argument UNREAD is non-nil, message is not flaged as read.
Returns non-nil if fetching was succeed.")
(luna-define-generic elmo-message-fetch-with-cache-process (folder
STRATEGY is the message fetching strategy.
If optional argument SECTION is specified, only the SECTION of the message
is fetched (if possible).
-If second optional argument UNREAD is non-nil, message is not marked as read.
+If second optional argument UNREAD is non-nil, message is not flaged as read.
Returns non-nil if fetching was succeed.")
(luna-define-generic elmo-message-fetch-internal (folder number strategy
STRATEGY is the message fetching strategy.
If optional argument SECTION is specified, only the SECTION of the message
is fetched (if possible).
-If second optional argument UNREAD is non-nil, message is not marked as read.
+If second optional argument UNREAD is non-nil, message is not flaged as read.
Returns non-nil if fetching was succeed.")
(luna-define-generic elmo-message-fetch-field (folder number field)
(luna-define-generic elmo-folder-process-crosspost (folder)
"Process crosspost for FOLDER.
-If NUMBER-ALIST is set, it is used as number-alist.
-Return a cons cell of (NUMBER-CROSSPOSTS . NEW-MARK-ALIST).")
-
-(luna-define-generic elmo-folder-append-msgdb (folder append-msgdb)
- "Append APPEND-MSGDB to the current msgdb of the folder.")
+Return a cons cell of (NUMBER-CROSSPOSTS . NEW-FLAG-ALIST).")
(luna-define-generic elmo-folder-newsgroups (folder)
"Return list of newsgroup name of FOLDER.")
(elmo-generic-folder-commit folder))
(defun elmo-generic-folder-commit (folder)
- (when (elmo-folder-persistent-p folder)
- (when (elmo-folder-message-modified-internal folder)
- (elmo-msgdb-overview-save
- (elmo-folder-msgdb-path folder)
- (elmo-msgdb-get-overview (elmo-folder-msgdb folder)))
- (elmo-msgdb-number-save
- (elmo-folder-msgdb-path folder)
- (elmo-msgdb-get-number-alist (elmo-folder-msgdb folder)))
- (elmo-folder-set-info-max-by-numdb
- folder
- (elmo-folder-list-messages folder nil 'in-msgdb))
- (elmo-folder-set-message-modified-internal folder nil)
- (elmo-msgdb-killed-list-save
- (elmo-folder-msgdb-path folder)
- (elmo-folder-killed-list-internal folder)))
- (when (elmo-folder-mark-modified-internal folder)
- (elmo-msgdb-mark-save
- (elmo-folder-msgdb-path folder)
- (elmo-msgdb-get-mark-alist (elmo-folder-msgdb folder)))
- (elmo-folder-set-mark-modified-internal folder nil))))
+ (let ((msgdb (elmo-folder-msgdb-internal folder)))
+ (when (and msgdb (elmo-folder-persistent-p folder))
+ (when (elmo-msgdb-message-modified-p msgdb)
+ (elmo-folder-set-info-max-by-numdb
+ folder
+ (elmo-folder-list-messages folder nil 'in-msgdb))
+ (elmo-msgdb-killed-list-save
+ (elmo-folder-msgdb-path folder)
+ (elmo-folder-killed-list-internal folder)))
+ (elmo-msgdb-save msgdb))))
(luna-define-method elmo-folder-close-internal ((folder elmo-folder))
;; do nothing.
(elmo-folder-send folder 'elmo-folder-rename-internal new-folder)
(elmo-msgdb-rename-path folder new-folder)))
-(defsubst elmo-folder-search-fast (folder condition numbers)
- "Search and return list of message numbers.
-Return t if CONDITION is not treated.
-FOLDER is the ELMO folder structure.
-CONDITION is a condition structure for searching.
-NUMBERS is a list of message numbers, messages are searched from the list."
- (if (and numbers
- (vectorp condition))
- (cond
- ((string= (elmo-filter-key condition) "flag")
- (let ((msgdb (elmo-folder-msgdb folder)))
- ;; msgdb should be synchronized at this point.
- (cond
- ((string= (elmo-filter-value condition) "unread")
- (elmo-folder-list-unreads folder))
- ((string= (elmo-filter-value condition) "important")
- (elmo-folder-list-importants folder))
- ((string= (elmo-filter-value condition) "answered")
- (elmo-folder-list-answereds folder))
- ((string= (elmo-filter-value condition) "digest")
- (nconc (elmo-folder-list-unreads folder)
- (elmo-folder-list-importants folder)))
- ((string= (elmo-filter-value condition) "any")
- (nconc (elmo-folder-list-unreads folder)
- (elmo-folder-list-importants folder)
- (elmo-folder-list-answereds folder))))))
- ((member (elmo-filter-key condition) '("first" "last"))
- (let ((len (length numbers))
- (lastp (string= (elmo-filter-key condition) "last"))
- (value (string-to-number (elmo-filter-value condition))))
- (when (eq (elmo-filter-type condition) 'unmatch)
- (setq lastp (not lastp)
- value (- len value)))
- (if lastp
- (nthcdr (max (- len value) 0) numbers)
- (when (> value 0)
- (let* ((numbers (copy-sequence numbers))
- (last (nthcdr (1- value) numbers)))
- (when last
- (setcdr last nil))
- numbers)))))
- (t
- t))
- t))
-
(luna-define-method elmo-folder-search ((folder elmo-folder)
condition
&optional numbers)
(let ((numbers (or numbers (elmo-folder-list-messages folder)))
+ (msgdb (elmo-folder-msgdb folder))
results)
- (if (listp (setq results (elmo-folder-search-fast folder
- condition
- numbers)))
+ (setq results (elmo-msgdb-search msgdb condition numbers))
+ (if (listp results)
results
- (let ((msgdb (elmo-folder-msgdb folder))
- (len (length numbers))
+ (let ((len (length numbers))
matched)
- (when (> len elmo-display-progress-threshold)
- (elmo-progress-set 'elmo-folder-search len "Searching..."))
- (unwind-protect
- (dolist (number numbers)
- (let (result)
- (setq result (elmo-msgdb-match-condition
- msgdb
- condition
- number
- numbers))
- (when (elmo-filter-condition-p result)
- (setq result (elmo-message-match-condition
- folder
- number
- condition
- numbers)))
- (when result
- (setq matched (cons number matched))))
- (elmo-progress-notify 'elmo-folder-search))
- (elmo-progress-clear 'elmo-folder-search))
+ (elmo-with-progress-display (> len elmo-display-progress-threshold)
+ (elmo-folder-search len "Searching...")
+ (dolist (number numbers)
+ (let (result)
+ (setq result (elmo-msgdb-match-condition msgdb
+ condition
+ number
+ numbers))
+ (when (elmo-filter-condition-p result)
+ (setq result (elmo-message-match-condition folder
+ number
+ condition
+ numbers)))
+ (when result
+ (setq matched (cons number matched))))
+ (elmo-progress-notify 'elmo-folder-search)))
+ (message "Searching...done")
(nreverse matched)))))
(luna-define-method elmo-message-match-condition ((folder elmo-folder)
(defun elmo-folder-set-info-max-by-numdb (folder numbers)
"Set FOLDER info by MSGDB-NUMBER in msgdb."
- (let ((numbers (sort numbers '<)))
- (elmo-folder-set-info-hashtb
- folder
- (or (nth (max 0 (1- (length numbers))) numbers) 0)
- nil ;;(length num-db)
- )))
+ (elmo-folder-set-info-hashtb
+ folder
+ (or (car (sort numbers '>)) 0)
+ nil ;;(length num-db)
+ ))
(defun elmo-folder-get-info-max (folder)
"Return max number of FODLER from folder info."
(defsubst elmo-strict-folder-diff (folder)
"Return folder diff information strictly from FOLDER."
- (let* ((dir (elmo-folder-msgdb-path folder))
- (nalist (elmo-msgdb-get-number-alist (elmo-folder-msgdb folder)))
- (in-db (sort (mapcar 'car nalist) '<))
- (in-folder (elmo-folder-list-messages folder))
- append-list delete-list diff)
+ (let ((in-db (sort (elmo-msgdb-list-messages (elmo-folder-msgdb folder))
+ '<))
+ (in-folder (elmo-folder-list-messages folder))
+ append-list delete-list diff)
(cons (if (equal in-folder in-db)
0
(setq diff (elmo-list-diff in-folder in-db nil))
(luna-define-method elmo-folder-contains-type ((folder elmo-folder) type)
(eq (elmo-folder-type-internal folder) type))
+(luna-define-method elmo-folder-next-message-number ((folder elmo-folder))
+ (+ 1 (elmo-max-of-list (or (elmo-folder-list-messages folder)
+ '(0)))))
+
(luna-define-method elmo-folder-append-messages ((folder elmo-folder)
src-folder
numbers
(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 flag mark
+ unseen table flags
succeed-numbers failure cache id)
(setq table (elmo-flag-table-load (elmo-folder-msgdb-path folder)))
(with-temp-buffer
id (and src-msgdb-exists
(elmo-message-field src-folder (car numbers)
'message-id))
- mark (and src-msgdb-exists
- (elmo-message-mark src-folder (car numbers)))
- flag (and id
- (cond
- ((null mark) 'read)
- ((member mark (elmo-msgdb-answered-marks))
- 'answered)
- ;;
- ((not (member mark (elmo-msgdb-unread-marks)))
- 'read))))
+ flags (elmo-message-flags src-folder (car numbers)))
(condition-case nil
(setq cache (elmo-file-cache-get id)
failure
(> (buffer-size) 0)
(elmo-folder-append-buffer
folder
- flag
+ (or flags '(read))
(if same-number (car numbers))))))
(error (setq failure t)))
;; FETCH & APPEND finished
(unless failure
(when id
- (elmo-flag-table-set table id flag))
+ (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)))
;; Arguments should be reduced.
(defun elmo-folder-move-messages (src-folder msgs dst-folder
- &optional msgdb
- no-delete-info
+ &optional
no-delete
- same-number
- save-unread)
+ same-number)
(save-excursion
(let* ((messages msgs)
(elmo-inhibit-display-retrieval-progress t)
(progn
(if (and (elmo-folder-delete-messages src-folder succeeds)
(elmo-folder-detach-messages src-folder succeeds))
- (setq result t)
+ (progn
+ (elmo-global-flag-detach-messages
+ src-folder succeeds (eq dst-folder 'null))
+ (setq result t))
(message "move: delete messages from %s failed."
(elmo-folder-name-internal src-folder))
(setq result nil))
folder
(elmo-folder-expand-msgdb-path folder))))
+(luna-define-generic elmo-message-cached-p (folder number)
+ "Return non-nil if the message is cached.")
+
+(luna-define-method elmo-message-cached-p ((folder elmo-folder) number)
+ (elmo-message-flagged-p folder number 'cached))
+
(defun elmo-message-accessible-p (folder number)
"Get accessibility of the message.
Return non-nil when message is accessible."
(or (elmo-folder-plugged-p folder)
(elmo-folder-local-p folder)
- (elmo-msgdb-get-cached (elmo-folder-msgdb folder) number)))
+ (elmo-message-cached-p folder number)))
(luna-define-generic elmo-message-set-cached (folder number cached)
"Set cache status of the message in the msgdb.
(luna-define-method elmo-message-set-cached ((folder elmo-folder)
number cached)
- (when (elmo-msgdb-set-cached (elmo-folder-msgdb folder)
- number
- cached
- (elmo-message-use-cache-p folder number))
- (elmo-folder-set-mark-modified-internal folder t)))
+ (if cached
+ (elmo-msgdb-set-flag (elmo-folder-msgdb folder) number 'cached)
+ (elmo-msgdb-unset-flag (elmo-folder-msgdb folder) number 'cached)))
(defun elmo-message-copy-entity (entity)
- ;;
- (elmo-msgdb-copy-overview-entity entity))
-
-(defun elmo-message-entity-set-number (entity number)
- (elmo-msgdb-overview-entity-set-number entity number))
+ (elmo-msgdb-copy-message-entity (elmo-message-entity-handler entity)
+ entity))
(luna-define-generic elmo-message-entity (folder key)
"Return the message-entity structure which matches to the KEY.
;; List all message entities in the FOLDER.
(mapcar
(lambda (number) (elmo-message-entity folder number))
- (elmo-folder-list-messages folder t t)))
+ (elmo-folder-list-messages folder nil t))) ; XXX killed-list is not used.
(defmacro elmo-folder-do-each-message-entity (spec &rest form)
"Iterator for message entity in the folder.
`(dolist (,(car spec) (elmo-folder-list-message-entities ,(car (cdr spec))))
,@form))
-(defmacro elmo-message-entity-number (entity)
- `(elmo-msgdb-overview-entity-get-number ,entity))
-
-(defun elmo-message-entity-field (entity field &optional decode)
- "Get message entity field value.
-ENTITY is the message entity structure obtained by `elmo-message-entity'.
-FIELD is the symbol of the field name.
-if optional DECODE is non-nil, returned value is decoded."
- (elmo-msgdb-message-entity-field entity field decode))
-
-(defun elmo-message-entity-set-field (entity field value)
- "Set message entity field value.
-ENTITY is the message entity structure.
-FIELD is the symbol of the field name.
-VALUE is the field value (raw)."
- (elmo-msgdb-message-entity-set-field entity field value))
-
(luna-define-generic elmo-folder-count-flags (folder)
"Count flagged message number in the msgdb of the FOLDER.
Return a list of numbers (`new' `unread' `answered')")
(luna-define-method elmo-folder-count-flags ((folder elmo-folder))
- (let ((new 0)
- (unreads 0)
- (answered 0))
- (dolist (elem (elmo-msgdb-get-mark-alist (elmo-folder-msgdb folder)))
- (cond
- ((string= (cadr elem) elmo-msgdb-new-mark)
- (incf new))
- ((member (cadr elem) (elmo-msgdb-unread-marks))
- (incf unreads))
- ((member (cadr elem) (elmo-msgdb-answered-marks))
- (incf answered))))
- (list new unreads answered)))
-
-(defun elmo-message-set-flag (folder number flag)
+ (let* ((flag-count (elmo-msgdb-flag-count (elmo-folder-msgdb folder)))
+ (new (or (cdr (assq 'new flag-count)) 0))
+ (unread (or (cdr (assq 'unread flag-count)) 0))
+ (answered(or (cdr (assq 'answered flag-count)) 0)))
+ (list new (- unread new) answered)))
+
+(defun elmo-message-set-flag (folder number flag &optional is-local)
"Set message flag.
FOLDER is a ELMO folder structure.
NUMBER is a message number to set flag.
`answered' (set the message as answered)
`important' (set the message as important)
'sugar' flag:
- `read' (remove new and unread flags)")
-
-(defun elmo-message-unset-flag (folder number flag)
+ `read' (remove new and unread flags)
+If optional IS-LOCAL is non-nil, update only local (not server) status."
+ ;; XXX Transitional implementation.
+ (case flag
+ (unread
+ (elmo-folder-unflag-read folder (list number) is-local))
+ (read
+ (elmo-folder-flag-as-read folder (list number) is-local))
+ (answered
+ (elmo-folder-flag-as-answered folder (list number) is-local))
+ (important
+ (elmo-folder-flag-as-important folder (list number) is-local))))
+
+(defun elmo-message-unset-flag (folder number flag &optional is-local)
"Unset message flag.
FOLDER is a ELMO folder structure.
NUMBER is a message number to set flag.
`answered' (remove answered flag)
`important' (remove important flag)
'sugar' flag:
- `read' (set unread flag)")
-
-(luna-define-generic elmo-message-mark (folder number)
- "Get mark of the message.
-FOLDER is the ELMO folder structure.
-NUMBER is a number of the message.")
-
-(luna-define-method elmo-message-mark ((folder elmo-folder) number)
- (when (zerop (elmo-folder-length folder))
- (error "Cannot treat this folder correctly."))
- (elmo-msgdb-get-mark (elmo-folder-msgdb folder) number))
+ `read' (set unread flag)
+If optional IS-LOCAL is non-nil, update only local (not server) status."
+ ;; XXX Transitional implementation.
+ (case flag
+ (unread
+ (elmo-folder-flag-as-read folder (list number) is-local))
+ (read
+ (elmo-folder-unflag-read folder (list number) is-local))
+ (answered
+ (elmo-folder-unflag-answered folder (list number) is-local))
+ (important
+ (elmo-folder-unflag-important folder (list number) is-local))))
(luna-define-generic elmo-message-field (folder number field)
"Get message field value in the msgdb.
FIELD is a symbol of the field.")
(luna-define-method elmo-message-field ((folder elmo-folder) number field)
- (when (zerop (elmo-folder-length folder))
- (error "Cannot treat this folder correctly."))
- (elmo-msgdb-get-field (elmo-folder-msgdb folder) number field))
+ (elmo-message-entity-field (elmo-message-entity folder number) field))
(luna-define-method elmo-message-use-cache-p ((folder elmo-folder) number)
nil) ; default is not use cache.
(luna-define-method elmo-message-folder ((folder elmo-folder) number)
folder) ; default is folder
-(luna-define-method elmo-folder-unmark-important ((folder elmo-folder)
+(luna-define-method elmo-folder-unflag-important ((folder elmo-folder)
numbers
- &optional ignore-flags)
+ &optional is-local)
(when (elmo-folder-msgdb-internal folder)
(dolist (number numbers)
+ (when (elmo-global-flag-p 'important)
+ (elmo-global-flag-detach 'important folder number 'remove-if-none))
(elmo-msgdb-unset-flag (elmo-folder-msgdb folder)
- folder
number
'important))))
-(luna-define-method elmo-folder-mark-as-important ((folder elmo-folder)
+(luna-define-method elmo-folder-flag-as-important ((folder elmo-folder)
numbers
- &optional ignore-flags)
- (when (elmo-folder-msgdb-internal folder)
- (dolist (number numbers)
- (elmo-msgdb-set-flag (elmo-folder-msgdb folder)
- folder
- number
- 'important))))
+ &optional is-local)
+ (let (path message-id)
+ (when (elmo-folder-msgdb-internal folder)
+ (dolist (number numbers)
+ ;; important message should always be a read message.
+ (if (eq (elmo-file-cache-exists-p
+ (setq message-id
+ (elmo-message-field folder number 'message-id)))
+ 'entire)
+ (elmo-folder-flag-as-read folder (list number)))
+ (when (elmo-global-flag-p 'important)
+ (elmo-global-flag-set 'important folder number message-id))
+ (elmo-msgdb-set-flag (elmo-folder-msgdb folder)
+ number
+ 'important)))))
-(luna-define-method elmo-folder-unmark-read ((folder elmo-folder)
+(luna-define-method elmo-folder-unflag-read ((folder elmo-folder)
numbers
- &optional ignore-flags)
+ &optional is-local)
(when (elmo-folder-msgdb-internal folder)
(dolist (number numbers)
(elmo-msgdb-unset-flag (elmo-folder-msgdb folder)
- folder
number
'read))))
-(luna-define-method elmo-folder-mark-as-read ((folder elmo-folder)
+(luna-define-method elmo-folder-flag-as-read ((folder elmo-folder)
numbers
- &optional ignore-flag)
+ &optional is-local)
(when (elmo-folder-msgdb-internal folder)
(dolist (number numbers)
(elmo-msgdb-set-flag (elmo-folder-msgdb folder)
- folder
number
'read))))
-(luna-define-method elmo-folder-unmark-answered ((folder elmo-folder) numbers)
+(luna-define-method elmo-folder-unflag-answered ((folder elmo-folder)
+ numbers
+ &optional is-local)
(when (elmo-folder-msgdb-internal folder)
(dolist (number numbers)
(elmo-msgdb-unset-flag (elmo-folder-msgdb folder)
- folder
number
'answered))))
-(luna-define-method elmo-folder-mark-as-answered ((folder elmo-folder) numbers)
+(luna-define-method elmo-folder-flag-as-answered ((folder elmo-folder)
+ numbers
+ &optional is-local)
(when (elmo-folder-msgdb-internal folder)
(dolist (number numbers)
(elmo-msgdb-set-flag (elmo-folder-msgdb folder)
- folder
number
'answered))))
;; flag-table)
;; "Append ENTITY to the folder.")
-(defun elmo-generic-folder-append-msgdb (folder append-msgdb)
+(defun elmo-msgdb-merge (folder msgdb-merge)
+ "Return a list of messages which have duplicated message-id."
+ (let (msgdb duplicates)
+ (setq msgdb (or (elmo-folder-msgdb-internal folder)
+ (elmo-make-msgdb (elmo-folder-msgdb-path folder))))
+ (setq duplicates (elmo-msgdb-append msgdb msgdb-merge))
+ (elmo-folder-set-msgdb-internal folder msgdb)
+ duplicates))
+
+(defsubst elmo-folder-append-msgdb (folder append-msgdb)
(if append-msgdb
- (let* ((number-alist (elmo-msgdb-get-number-alist append-msgdb))
- (all-alist (copy-sequence (append
- (elmo-msgdb-get-number-alist
- (elmo-folder-msgdb folder))
- number-alist)))
- (cur number-alist)
- pair overview
- to-be-deleted
- mark-alist)
- (elmo-folder-set-msgdb-internal folder
- (elmo-msgdb-append
- (elmo-folder-msgdb folder)
- append-msgdb))
- (while cur
- (setq all-alist (delq (car cur) all-alist))
- ;; same message id exists.
- (if (setq pair (rassoc (cdr (car cur)) all-alist))
- (setq to-be-deleted (nconc to-be-deleted (list (car pair)))))
- (setq cur (cdr cur)))
+ (let ((duplicates (elmo-msgdb-merge folder append-msgdb)))
(cond ((eq (elmo-folder-process-duplicates-internal folder)
'hide)
- ;; Hide duplicates.
- (setq overview (elmo-delete-if
- (lambda (x)
- (memq (elmo-msgdb-overview-entity-get-number
- x)
- to-be-deleted))
- (elmo-msgdb-get-overview append-msgdb)))
- ;; Should be mark as read.
- (elmo-folder-mark-as-read folder to-be-deleted)
- (elmo-msgdb-set-overview append-msgdb overview))
+ ;; Let duplicates be a temporary killed message.
+ (elmo-folder-kill-messages folder duplicates)
+ ;; Should be flag as read.
+ (elmo-folder-flag-as-read folder duplicates))
((eq (elmo-folder-process-duplicates-internal folder)
'read)
- ;; Mark as read duplicates.
- (elmo-folder-mark-as-read folder to-be-deleted))
+ ;; Flag as read duplicates.
+ (elmo-folder-flag-as-read folder duplicates))
(t
;; Do nothing.
- (setq to-be-deleted nil)))
- (length to-be-deleted))
+ (setq duplicates nil)))
+ (length duplicates))
0))
-(luna-define-method elmo-folder-append-msgdb ((folder elmo-folder)
- append-msgdb)
- (elmo-generic-folder-append-msgdb folder append-msgdb))
-
(defun elmo-folder-confirm-appends (appends)
(let ((len (length appends))
in)
(or result
(and err (signal (car err) (cdr err))))))
-(defun elmo-folder-kill-messages-before (folder msg)
+(defun elmo-folder-kill-messages-range (folder beg end)
(elmo-folder-set-killed-list-internal
folder
- (list (cons 1 msg))))
+ (nconc
+ (elmo-folder-killed-list-internal folder)
+ (list (cons beg end)))))
(defun elmo-folder-kill-messages (folder numbers)
"Kill(hide) messages in the FOLDER with NUMBERS."
- (elmo-folder-set-killed-list-internal
- folder
- (elmo-number-set-append-list (elmo-folder-killed-list-internal
- folder) 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)))
(luna-define-method elmo-folder-clear ((folder elmo-folder)
&optional keep-killed)
(unless keep-killed
(elmo-folder-set-killed-list-internal folder nil))
- (elmo-folder-set-msgdb-internal folder (elmo-msgdb-clear)))
+ (if (eq elmo-msgdb-convert-type 'sync)
+ (elmo-folder-set-msgdb-internal
+ folder
+ (elmo-make-msgdb (elmo-folder-msgdb-path folder)))
+ (elmo-msgdb-clear (elmo-folder-msgdb folder))))
(luna-define-generic elmo-folder-synchronize (folder
&optional
no-check)
(let ((killed-list (elmo-folder-killed-list-internal folder))
(before-append t)
- number-alist
- old-msgdb diff diff-2 delete-list new-list new-msgdb mark
+ old-msgdb diff diff-2 delete-list new-list new-msgdb flag
flag-table crossed after-append)
(setq old-msgdb (elmo-folder-msgdb folder))
(setq flag-table (elmo-flag-table-load (elmo-folder-msgdb-path folder)))
(when (and (not (eq (length (car diff))
(length new-list)))
(setq diff-2 (elmo-list-diff (car diff) new-list)))
- (elmo-folder-kill-messages-before folder
- (nth (- (length (car diff-2)) 1)
- (car diff-2))))
+ (elmo-folder-kill-messages-range
+ folder
+ (car (car diff-2))
+ (nth (- (length (car diff-2)) 1) (car diff-2))))
(setq delete-list (cadr diff))
(if (or (equal diff '(nil nil))
(equal diff '(nil))
(when delete-list
(elmo-folder-detach-messages folder delete-list))
(when new-list
- (elmo-msgdb-change-mark (elmo-folder-msgdb folder)
- elmo-msgdb-new-mark
- elmo-msgdb-unread-uncached-mark)
+ (elmo-msgdb-out-of-date-messages (elmo-folder-msgdb folder))
(setq new-msgdb (elmo-folder-msgdb-create
folder new-list flag-table))
;; Clear flag-table
(setq before-append nil)
(setq crossed (elmo-folder-append-msgdb folder new-msgdb))
;; process crosspost.
- ;; Return a cons cell of (NUMBER-CROSSPOSTS . NEW-MARK-ALIST).
- (elmo-folder-process-crosspost folder)
- (elmo-folder-set-message-modified-internal folder t)
- (elmo-folder-set-mark-modified-internal folder t))
+ ;; Return a cons cell of (NUMBER-CROSSPOSTS . NEW-FLAG-ALIST).
+ (elmo-folder-process-crosspost folder))
;; return value.
(or crossed 0)))
(quit
(luna-define-method elmo-folder-detach-messages ((folder elmo-folder)
numbers)
- (elmo-msgdb-delete-msgs (elmo-folder-msgdb folder) numbers))
+ (elmo-msgdb-delete-messages (elmo-folder-msgdb folder) numbers))
(luna-define-generic elmo-folder-length (folder)
"Return number of messages in the FOLDER.")
(elmo-msgdb-length (elmo-folder-msgdb folder))
0))
-(defun elmo-msgdb-load (folder &optional silent)
+(defun elmo-folder-msgdb-load (folder &optional silent)
(unless silent
(message "Loading msgdb for %s..." (elmo-folder-name-internal folder)))
(let ((msgdb (elmo-load-msgdb (elmo-folder-msgdb-path folder))))
(elmo-folder-set-info-max-by-numdb
folder
- (mapcar 'elmo-msgdb-overview-entity-get-number
- (elmo-msgdb-get-overview msgdb)))
+ (elmo-msgdb-list-messages msgdb))
(unless silent
(message "Loading msgdb for %s...done"
(elmo-folder-name-internal folder)))
"Initialize ELMO module."
(elmo-crosspost-message-alist-load)
(elmo-resque-obsolete-variables)
+ (elmo-global-flag-initialize)
(elmo-dop-queue-load))
(defun elmo-quit ()
(while types
(setq class
(luna-find-class
- (intern (format "elmo-%s-folder" (symbol-name (cdr (car types)))))))
+ (intern (format "elmo-%s-folder"
+ (symbol-name (cdr (car types)))))))
;; Call all folder's `elmo-quit' method.
(if class
(dolist (func (luna-class-find-functions class 'elmo-quit))
(error "Cannot rename %s folder"
(symbol-name (elmo-folder-type-internal folder))))
-
;;; Define folders.
(elmo-define-folder ?% 'imap4)
(elmo-define-folder ?- 'nntp)
(make-obsolete 'elmo-folder-make-temp-dir
'elmo-folder-make-temporary-directory)
-
-;; autoloads
-(autoload 'elmo-dop-queue-flush "elmo-dop")
-(autoload 'elmo-nntp-post "elmo-nntp")
-
(require 'product)
(product-provide (provide 'elmo) (require 'elmo-version))