X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=elmo%2Felmo.el;h=3bebcca10bddb5b8b08b15cb7f80254601f784de;hb=ede1058ec4d4f93ab8f873045c79cfffb4710781;hp=9d606fc06ad29bedc30cc5cd38336b602c078f87;hpb=1757a3594b18a902939fdea5b0f5ec8207ac3a7c;p=elisp%2Fwanderlust.git diff --git a/elmo/elmo.el b/elmo/elmo.el index 9d606fc..3bebcca 100644 --- a/elmo/elmo.el +++ b/elmo/elmo.el @@ -79,6 +79,18 @@ Otherwise, entire fetching of the message is aborted without confirmation." (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-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") + (autoload 'elmo-get-global-flags "elmo-flag") + (autoload 'elmo-global-mark-migrate "elmo-flag") + (autoload 'elmo-folder-list-global-flag-messages "elmo-flag")) + (defun elmo-define-folder (prefix backend) "Define a folder. If a folder name begins with PREFIX, use BACKEND." @@ -92,8 +104,8 @@ If a folder name begins with PREFIX, use BACKEND." (defmacro elmo-folder-type (name) "Get folder type from NAME string." - (` (and (stringp (, name)) - (cdr (assoc (string-to-char (, name)) elmo-folder-type-alist))))) + `(and (stringp ,name) + (cdr (assoc (string-to-char ,name) elmo-folder-type-alist)))) ;;; ELMO folder ;; A elmo folder provides uniformed (orchestrated) access @@ -105,9 +117,8 @@ If a folder name begins with PREFIX, use BACKEND." path ; directory path for msgdb. msgdb ; msgdb (may be nil). killed-list ; killed list. + flag-table ; flag table. persistent ; non-nil if persistent. - message-modified ; message is modified. - flag-modified ; flag is modified. process-duplicates ; read or hide biff ; folder for biff )) @@ -205,12 +216,6 @@ Return value is cons cell or list: (luna-define-generic elmo-folder-reserve-status-p (folder) "If non-nil, the folder should not close folder after `elmo-folder-status'.") -(luna-define-generic elmo-folder-set-message-modified (folder modified) - "Set FOLDER as modified.") -(luna-define-method elmo-folder-set-message-modified ((folder elmo-folder) - modified) - (elmo-folder-set-message-modified-internal folder modified)) - (luna-define-generic elmo-folder-list-messages (folder &optional visible-only in-msgdb) "Return a list of message numbers contained in FOLDER. @@ -228,15 +233,17 @@ If second optional IN-MSGDB is non-nil, only messages in the msgdb are listed.") (setq list (elmo-msgdb-list-messages (elmo-folder-msgdb folder)))) (if visible-only (elmo-living-messages list killed-list) - (elmo-uniq-list - (nconc (elmo-number-set-to-number-list killed-list) list))))) + (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-unreads (folder) - "Return a list of unread message numbers contained in FOLDER.") -(luna-define-generic elmo-folder-list-importants (folder) - "Return a list of important message numbers contained in FOLDER.") -(luna-define-generic elmo-folder-list-answereds (folder) - "Return a list of answered message numbers contained in FOLDER.") +(luna-define-generic elmo-folder-list-messages-internal (folder &optional + visible-only) + ;; Return a list of message numbers contained in FOLDER. + ;; Return t if the message list is not available. + ) (luna-define-generic elmo-folder-list-flagged (folder flag &optional in-msgdb) "List messages in the FOLDER with FLAG. @@ -247,30 +254,30 @@ FLAG is a symbol which is one of the following: `important' (marked as important) 'sugar' flags: `read' (not unread) - `digest' (unread + important) - `any' (digest + answered) - + `digest' (unread + important + other flags) + `any' (digest + answered + other flags) If optional IN-MSGDB is non-nil, retrieve flag information from msgdb.") (luna-define-method elmo-folder-list-flagged ((folder elmo-folder) flag &optional in-msgdb) - ;; Currently, only in-msgdb is implemented. - (elmo-msgdb-list-flagged (elmo-folder-msgdb folder) flag)) - -(luna-define-method elmo-folder-list-unreads ((folder elmo-folder)) - (elmo-folder-list-flagged folder 'unread)) - -(luna-define-method elmo-folder-list-importants ((folder elmo-folder)) - (elmo-folder-list-flagged folder 'important)) + (let ((msgs (if in-msgdb + t + (elmo-folder-list-flagged-internal folder flag)))) + (unless (listp msgs) + (setq msgs (elmo-msgdb-list-flagged (elmo-folder-msgdb folder) flag))) + (if in-msgdb + msgs + (elmo-uniq-list + (nconc (elmo-folder-list-global-flag-messages folder flag) msgs) + #'delq)))) -(luna-define-method elmo-folder-list-answereds ((folder elmo-folder)) - (elmo-folder-list-flagged folder 'answered)) +(luna-define-generic elmo-folder-list-flagged-internal (folder flag) + "Return a list of message in the FOLDER with FLAG. +Return t if the message list is not available.") -(luna-define-generic elmo-folder-list-messages-internal (folder &optional - visible-only) - ;; Return a list of message numbers contained in FOLDER. - ;; Return t if the message list is not available. - ) +(luna-define-method elmo-folder-list-flagged-internal ((folder elmo-folder) + flag) + t) (luna-define-generic elmo-folder-list-subfolders (folder &optional one-level) "Returns a list of subfolders contained in FOLDER. @@ -333,55 +340,48 @@ FOLDER is the ELMO folder structure. 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-unflag-important (folder - numbers - &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 IS-LOCAL is non-nil, only the local flag is updated.") - -(luna-define-generic elmo-folder-flag-as-important (folder - numbers - &optional is-local) - "Flag messages as important. -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-set-flag (folder numbers flag + &optional is-local) + "Set messages flag. +FOLDER is a ELMO folder structure. +NUMBERS is a list of message number to set flag. -(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 IS-LOCAL is non-nil, only the local flag is updated.") +FLAG is a symbol which is one of the following: + `unread' (set the message as unread) + `answered' (set the message as answered) + `important' (set the message as important) +'sugar' flag: + `read' (remove new and unread flags) +If optional IS-LOCAL is non-nil, update only local (not server) status.") -(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 IS-LOCAL is non-nil, only the local flag is updated.") +(luna-define-generic elmo-folder-unset-flag (folder numbers flag + &optional is-local) + "Unset messages flag. +FOLDER is a ELMO folder structure. +NUMBERS is a list of message number to unset flag. -(luna-define-generic elmo-folder-unflag-answered (folder numbers - &optional is-local) - "Un-flag messages as answered. -FOLDER is the ELMO folder structure. -If IS-LOCAL is non-nil, only the local flag is updated.") +FLAG is a symbol which is one of the following: + `unread' (remove unread and new flag) + `answered' (remove answered flag) + `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-flag-as-answered (folder numbers - &optional is-local) - "Flag messages as answered. -FOLDER is the ELMO folder structure. -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 +(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 @@ -453,6 +453,34 @@ Return newly created temporary directory name which contains temporary files.") (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 &optional msgid) + "Return a list of flags. +FOLDER is a ELMO folder structure. +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. +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. @@ -562,6 +590,9 @@ If READ is non-nil, message is flaged as read.") 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 @@ -672,8 +703,6 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-FLAG-ALIST).") (elmo-msgdb-killed-list-save (elmo-folder-msgdb-path folder) (elmo-folder-killed-list-internal folder))) - (elmo-folder-set-message-modified folder nil) - (elmo-folder-set-flag-modified-internal folder nil) (elmo-msgdb-save msgdb)))) (luna-define-method elmo-folder-close-internal ((folder elmo-folder)) @@ -725,104 +754,63 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-FLAG-ALIST).") (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) 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)) @@ -850,6 +838,39 @@ NUMBERS is a list of message numbers, messages are searched from the list." (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) @@ -873,7 +894,7 @@ NUMBERS is a list of message numbers, messages are searched from the list." "Set FOLDER info by MSGDB-NUMBER in msgdb." (elmo-folder-set-info-hashtb folder - (or (car (sort numbers '>)) 0) + (if numbers (apply #'max numbers) 0) nil ;;(length num-db) )) @@ -952,9 +973,8 @@ NUMBERS is a list of message numbers, messages are searched from the list." (let ((number-list (elmo-folder-list-messages folder nil 'in-msgdb))) ;; No info-cache. - (setq in-db (sort number-list '<)) - (setq in-db-max (or (nth (max 0 (1- (length in-db))) in-db) - 0)) + (setq in-db number-list) + (setq in-db-max (if in-db (apply #'max in-db) 0)) (elmo-folder-set-info-hashtb folder in-db-max nil)) (setq in-db-max cached-in-db-max)) (setq unsync (if (and in-db (car in-folder)) @@ -982,6 +1002,10 @@ NUMBERS is a list of message numbers, messages are searched from the list." (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 @@ -993,17 +1017,16 @@ NUMBERS is a list of message numbers, messages are searched from the list." (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 @@ -1027,18 +1050,19 @@ NUMBERS is a list of message numbers, messages are searched from the list." (> (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. @@ -1121,7 +1145,7 @@ If CACHED is t, message is set as cached.") (elmo-msgdb-unset-flag (elmo-folder-msgdb folder) number 'cached))) (defun elmo-message-copy-entity (entity) - (elmo-msgdb-copy-message-entity (elmo-message-entity-db entity) + (elmo-msgdb-copy-message-entity (elmo-message-entity-handler entity) entity)) (luna-define-generic elmo-message-entity (folder key) @@ -1158,71 +1182,16 @@ ENTITY is the message-entity to get the parent.") `(dolist (,(car spec) (elmo-folder-list-message-entities ,(car (cdr spec)))) ,@form)) -(defmacro elmo-message-entity-number (entity) - `(elmo-msgdb-message-entity-number (elmo-message-entity-db ,entity) - ,entity)) - -(defmacro elmo-message-entity-set-number (entity number) - `(elmo-msgdb-message-entity-set-number (elmo-message-entity-db ,entity) - ,entity - ,number)) - -(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 - (elmo-message-entity-db entity) - 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 - (elmo-message-entity-db entity) - 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) - flags) - (dolist (number (elmo-folder-list-messages folder 'visible 'in-msgdb)) - (setq flags (elmo-message-flags folder number)) - (cond - ((memq 'new flags) - (incf new)) - ((memq 'unread flags) - (incf unreads)) - ((memq 'answered flags) - (incf answered)))) - (list new unreads answered))) - -(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))))) + (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. @@ -1237,15 +1206,7 @@ FLAG is a symbol which is one of the following: `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)))) + (elmo-folder-set-flag folder (list number) flag is-local)) (defun elmo-message-unset-flag (folder number flag &optional is-local) "Unset message flag. @@ -1260,15 +1221,7 @@ FLAG is a symbol which is one of the following: `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)))) + (elmo-folder-unset-flag folder (list number) flag is-local)) (luna-define-generic elmo-message-field (folder number field) "Get message field value in the msgdb. @@ -1277,80 +1230,76 @@ NUMBER is a number of the message. 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-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. (luna-define-method elmo-message-folder ((folder elmo-folder) number) folder) ; default is folder -(luna-define-method elmo-folder-unflag-important ((folder elmo-folder) - numbers - &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) - number - 'important)))) - -(luna-define-method elmo-folder-flag-as-important ((folder elmo-folder) - numbers - &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-unflag-read ((folder elmo-folder) - numbers - &optional is-local) - (when (elmo-folder-msgdb-internal folder) - (dolist (number numbers) - (elmo-msgdb-unset-flag (elmo-folder-msgdb folder) - number - 'read)))) - -(luna-define-method elmo-folder-flag-as-read ((folder elmo-folder) - numbers - &optional is-local) +(luna-define-method elmo-folder-set-flag ((folder elmo-folder) + numbers + flag + &optional is-local) (when (elmo-folder-msgdb-internal folder) (dolist (number numbers) + (when (elmo-global-flag-p flag) + (let ((message-id (elmo-message-field folder number 'message-id))) + (elmo-global-flag-set flag folder number message-id))) (elmo-msgdb-set-flag (elmo-folder-msgdb folder) number - 'read)))) - -(luna-define-method elmo-folder-unflag-answered ((folder elmo-folder) - numbers - &optional is-local) + flag)))) + +(defun elmo-message-has-global-flag-p (folder number) + "Return non-nil when the message in the FOLDER with NUMBER has global flag." + (let ((flags (elmo-message-flags folder number)) + result) + (while flags + (when (and (elmo-global-flag-p (car flags)) + (not (memq (car flags) '(answered unread cached)))) + (setq result t + flags nil)) + (setq flags (cdr flags))) + result)) + +(defun elmo-message-set-global-flags (folder number flags &optional local) + "Set global flags of the message in the FOLDER with NUMBER as FLAGS. +If Optional LOCAL is non-nil, don't update server flag." + (dolist (flag flags) + (unless (elmo-global-flag-p flag) + (error "Not a global flag"))) + (let ((old-flags (elmo-get-global-flags (elmo-message-flags folder number)))) + (dolist (flag flags) + (unless (memq flag old-flags) + (elmo-message-set-flag folder number flag local))) + (dolist (flag old-flags) + (unless (memq flag flags) + (elmo-message-unset-flag folder number flag local))))) + +(luna-define-method elmo-folder-unset-flag ((folder elmo-folder) + numbers + flag + &optional is-local) (when (elmo-folder-msgdb-internal folder) (dolist (number numbers) + (when (elmo-global-flag-p flag) + (elmo-global-flag-detach flag folder number 'always)) (elmo-msgdb-unset-flag (elmo-folder-msgdb folder) number - 'answered)))) - -(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) - number - 'answered)))) + flag)))) (luna-define-method elmo-folder-process-crosspost ((folder elmo-folder)) ;; Do nothing. @@ -1378,11 +1327,11 @@ FIELD is a symbol of the field.") ;; 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)) + (elmo-folder-set-flag folder duplicates 'read)) ((eq (elmo-folder-process-duplicates-internal folder) 'read) ;; Flag as read duplicates. - (elmo-folder-flag-as-read folder duplicates)) + (elmo-folder-set-flag folder duplicates 'read)) (t ;; Do nothing. (setq duplicates nil))) @@ -1416,6 +1365,10 @@ FIELD is a symbol of the field.") (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 @@ -1459,7 +1412,6 @@ FIELD is a symbol of the field.") 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)) @@ -1468,18 +1420,21 @@ FIELD is a symbol of the field.") (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))) - + (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) @@ -1495,7 +1450,8 @@ FIELD is a symbol of the field.") &optional disable-killed ignore-msgdb - no-check) + no-check + mask) "Synchronize the folder data to the newest status. FOLDER is the ELMO folder structure. @@ -1503,14 +1459,17 @@ If optional DISABLE-KILLED is non-nil, killed messages are also synchronized. 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 @@ -1531,15 +1490,18 @@ If update process is interrupted, return nil.") 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)) (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)) @@ -1564,9 +1526,7 @@ If update process is interrupted, return nil.") (setq crossed (elmo-folder-append-msgdb folder new-msgdb)) ;; process crosspost. ;; Return a cons cell of (NUMBER-CROSSPOSTS . NEW-FLAG-ALIST). - (elmo-folder-process-crosspost folder) - (elmo-folder-set-message-modified folder t) - (elmo-folder-set-flag-modified-internal folder t)) + (elmo-folder-process-crosspost folder)) ;; return value. (or crossed 0))) (quit @@ -1669,8 +1629,8 @@ Return a hashtable for newsgroups." "Initialize ELMO module." (elmo-crosspost-message-alist-load) (elmo-resque-obsolete-variables) - (elmo-global-flag-initialize) - (elmo-dop-queue-load)) + (elmo-dop-queue-load) + (run-hooks 'elmo-init-hook)) (defun elmo-quit () "Quit and cleanup ELMO." @@ -1752,16 +1712,6 @@ Return a hashtable for newsgroups." (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") -(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") - (require 'product) (product-provide (provide 'elmo) (require 'elmo-version))