-;;; elmo.el -- Elisp Library for Message Orchestration
+;;; elmo.el --- Elisp Library for Message Orchestration.
;; Copyright (C) 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
(elmo-define-error 'elmo-error "Error" 'error)
(elmo-define-error 'elmo-open-error "Cannot open" 'elmo-error)
(elmo-define-error 'elmo-authenticate-error "Login failed" 'elmo-open-error)
-(elmo-define-error 'elmo-imap4-bye-error "IMAP4 BYE response" 'elmo-open-error)
+(elmo-define-error 'elmo-imap4-bye-error "IMAP4 session was terminated" 'elmo-open-error)
(defun elmo-define-folder (prefix backend)
"Define a folder.
message-modified ; message is modified.
mark-modified ; mark is modified.
process-duplicates ; read or hide
+ biff ; folder for biff
))
(luna-define-internal-accessors 'elmo-folder))
(save-match-data
(elmo-folder-send folder 'elmo-folder-initialize name))))
-(defmacro elmo-folder-msgdb (folder)
- "Return the msgdb of FOLDER (on-demand loading)."
- (` (or (elmo-folder-msgdb-internal (, folder))
- (elmo-folder-set-msgdb-internal (, folder)
- (elmo-msgdb-load (, folder))))))
+(luna-define-generic elmo-folder-msgdb (folder)
+ "Return the msgdb of FOLDER (on-demand loading).")
+
+(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))))
(luna-define-generic elmo-folder-open (folder &optional load-msgdb)
"Open and setup (load saved status) FOLDER.
"Get diff of FOLDER.
If optional NUMBERS is set, it is used as current NUMBERS.
Otherwise, saved status for folder is used for comparison.
-Return value is a cons cell of NEWS and MESSAGES.")
+Return value is cons cell or list:
+ - a cons cell (NEWS . MESSAGES)
+ - a list (RECENT UNSEEN MESSAGES) ; RECENT means NEWS, UNSEEN means UNREAD.")
(luna-define-generic elmo-folder-status (folder)
"Returns a cons cell of (MAX-NUMBER . MESSAGES) in the FOLDER.")
(luna-define-generic elmo-folder-reserve-status-p (folder)
"If non-nil, the folder should not close folder after `elmo-folder-status'.")
-(defun elmo-folder-list-messages (folder &optional visible-only)
+(defun elmo-folder-list-messages (folder &optional visible-only in-msgdb)
"Return a list of message numbers contained in FOLDER.
-If optional VISIBLE-ONLY is non-nil, killed messages are not listed."
- (let ((list (elmo-folder-list-messages-internal folder visible-only))
- (killed (elmo-folder-killed-list-internal folder))
- numbers)
- (setq numbers
- (if (listp list)
- list
- ;; Not available, use current list.
- (mapcar
- 'car
- (elmo-msgdb-get-number-alist (elmo-folder-msgdb folder)))))
- (elmo-living-messages numbers killed)))
-
-(defun elmo-folder-list-unreads (folder unread-marks)
- "Return a list of unread message numbers contained in FOLDER.
-UNREAD-MARKS is the unread marks."
- (let ((list (elmo-folder-list-unreads-internal folder
- unread-marks)))
- (if (listp list)
- list
- ;; Not available, use current mark.
- (delq nil
- (mapcar
- (function
- (lambda (x)
- (if (member (cadr x) unread-marks)
- (car x))))
- (elmo-msgdb-get-mark-alist (elmo-folder-msgdb folder)))))))
-
-(defun elmo-folder-list-importants (folder important-mark)
- "Returns a list of important message numbers contained in FOLDER.
-IMPORTANT-MARK is the important mark."
- (let ((importants (elmo-folder-list-importants-internal folder important-mark))
- (number-alist (elmo-msgdb-get-number-alist
- (elmo-folder-msgdb folder)))
- num-pair result)
+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."
+ (let ((list (if in-msgdb
+ t
+ (elmo-folder-list-messages-internal folder visible-only))))
+ (elmo-living-messages
+ (if (listp list)
+ list
+ ;; Use current list.
+ (mapcar
+ 'car
+ (elmo-msgdb-get-number-alist (elmo-folder-msgdb folder))))
+ (elmo-folder-killed-list-internal folder))))
+
+(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-method elmo-folder-list-unreads ((folder elmo-folder))
+ (delq nil
+ (mapcar
+ (lambda (x)
+ (if (member (cadr x) (elmo-msgdb-unread-marks))
+ (car x)))
+ (elmo-msgdb-get-mark-alist (elmo-folder-msgdb 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-dir)))))
- (if (and (string= important-mark (cdr mark-pair))
- (setq num-pair (rassoc (car mark-pair) number-alist)))
- (setq result (cons (car num-pair) result))))
- (if (listp importants)
- (elmo-uniq-list (nconc result importants))
- result)))
+ 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-method elmo-folder-list-importants ((folder elmo-folder))
+ (elmo-folder-list-messages-mark-match folder
+ (regexp-quote
+ elmo-msgdb-important-mark)))
+
+(luna-define-method elmo-folder-list-answereds ((folder elmo-folder))
+ (delq nil
+ (mapcar
+ (function
+ (lambda (x)
+ (if (member (cadr x) (elmo-msgdb-answered-marks))
+ (car x))))
+ (elmo-msgdb-get-mark-alist (elmo-folder-msgdb folder)))))
(luna-define-generic elmo-folder-list-messages-internal (folder &optional
visible-only)
;; Return t if the message list is not available.
)
-(luna-define-generic elmo-folder-list-unreads-internal (folder
- unread-marks
- &optional mark-alist)
- ;; Return a list of unread message numbers contained in FOLDER.
- ;; If optional MARK-ALIST is set, it is used as mark-alist.
- ;; Return t if this feature is not available.
- )
-
-(luna-define-generic elmo-folder-list-importants-internal (folder
- important-mark)
- ;; Return a list of important message numbers contained in FOLDER.
- ;; Return t if this feature is not available.
- )
-
(luna-define-generic elmo-folder-list-subfolders (folder &optional one-level)
"Returns a list of subfolders contained in FOLDER.
If optional argument ONE-LEVEL is non-nil, only children of FOLDER is returned.
-(a folder which have children is returned as a list)
+\(a folder which have children is returned as a list\)
Otherwise, all descendent folders are returned.")
(luna-define-generic elmo-folder-have-subfolder-p (folder)
(luna-define-generic elmo-folder-search (folder condition &optional numbers)
"Search and return list of message numbers.
FOLDER is the ELMO folder structure.
-CONDITION is a condition string for searching.
+CONDITION is a condition structure for searching.
If optional argument NUMBERS is specified and is a list of message numbers,
messages are searched from the list.")
-(luna-define-generic elmo-folder-msgdb-create
- (folder numbers new-mark already-mark seen-mark important-mark seen-list)
+(luna-define-generic elmo-message-match-condition (folder number
+ condition
+ numbers)
+ "Return non-nil when the message in the FOLDER with NUMBER is matched.
+CONDITION is a condition structure for testing.
+NUMBERS is a list of message numbers,
+use to be test for \"last\" and \"first\" predicates.")
+
+(luna-define-generic elmo-folder-msgdb-create (folder numbers id-mark-table)
"Create a message database (implemented in each backends).
FOLDER is the ELMO folder structure.
NUMBERS is a list of message numbers to create msgdb.
-NEW-MARK, ALREADY-MARK, SEEN-MARK, and IMPORTANT-MARK are mark string for
-new message, unread but cached message, read message and important message.
-SEEN-LIST is a list of message-id string which should be treated as read.")
+ID-MARK-TABLE is a hashtable of message-id and its status mark.")
(luna-define-generic elmo-folder-unmark-important (folder numbers)
"Un-mark messages as important.
FOLDER is the ELMO folder structure.
NUMBERS is a list of message numbers to be processed.")
-(luna-define-generic elmo-folder-unmark-read (folder numbers)
+(luna-define-generic elmo-folder-unmark-read (folder numbers
+ &optional ignore-flags)
"Un-mark messages as read.
FOLDER is the ELMO folder structure.
-NUMBERS is a list of message numbers to be processed.")
+NUMBERS is a list of message numbers to be processed.
+If IGNORE-FLAGS is non-nil, folder flags are not updated.")
-(luna-define-generic elmo-folder-mark-as-read (folder numbers)
+(luna-define-generic elmo-folder-mark-as-read (folder numbers
+ &optional ignore-flags)
"Mark 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.")
+
+(luna-define-generic elmo-folder-unmark-answered (folder numbers)
+ "Un-mark messages as answered.
+FOLDER is the ELMO folder structure.
+NUMBERS is a list of message numbers to be processed.")
+
+(luna-define-generic elmo-folder-mark-as-answered (folder numbers)
+ "Mark messages as answered.
+FOLDER is the ELMO folder structure.
NUMBERS is a list of message numbers to be processed.")
(luna-define-generic elmo-folder-append-buffer (folder unread &optional number)
(luna-define-generic elmo-folder-append-messages (folder
src-folder
numbers
- unread-marks
&optional
same-number)
"Append messages from folder.
(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.
-UNREAD-MARKS is a list of unread mark string.
If second optional argument SAME-NUMBER is specified,
message number is preserved (if possible).")
(setq message-id (elmo-msgdb-overview-entity-get-id entity))
(setq number (elmo-msgdb-overview-entity-get-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))))
(if (or ignore-cache
(null (elmo-file-cache-status cache-file)))
;; No cache or ignore-cache.
((folder elmo-folder) &optional visible-only)
t)
-(luna-define-method elmo-folder-list-unreads-internal
- ((folder elmo-folder) unread-marks &optional mark-alist)
- t)
-
-(luna-define-method elmo-folder-list-importants-internal
- ((folder elmo-folder) important-mark)
- t)
-
(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."
(luna-define-generic elmo-folder-newsgroups (folder)
"Return list of newsgroup name of FOLDER.")
+(luna-define-generic elmo-folder-search-requires-msgdb-p (folder condition)
+ "Return non-nil if searching in FOLDER by CONDITION requires msgdb fetch.")
+
+(defun elmo-folder-search-requires-msgdb-p-internal (folder condition)
+ (if (listp condition)
+ (or (elmo-folder-search-requires-msgdb-p-internal
+ folder (nth 1 condition))
+ (elmo-folder-search-requires-msgdb-p-internal
+ folder (nth 2 condition)))
+ (and (not (string= (elmo-filter-key condition) "last"))
+ (not (string= (elmo-filter-key condition) "first")))))
+
+(luna-define-method elmo-folder-search-requires-msgdb-p ((folder elmo-folder)
+ condition)
+ (elmo-folder-search-requires-msgdb-p-internal folder condition))
+
(luna-define-method elmo-folder-newsgroups ((folder elmo-folder))
nil)
(defun elmo-generic-folder-open (folder load-msgdb)
(let ((inhibit-quit t))
- (if load-msgdb
- (elmo-folder-set-msgdb-internal folder (elmo-msgdb-load folder)))
+ (if load-msgdb (elmo-folder-msgdb folder))
(elmo-folder-set-killed-list-internal
folder
(elmo-msgdb-killed-list-load (elmo-folder-msgdb-path folder))))
(elmo-folder-persistent-internal folder))
(luna-define-method elmo-folder-creatable-p ((folder elmo-folder))
- t) ; default is creatable.
+ nil) ; default is not creatable.
(luna-define-method elmo-folder-writable-p ((folder elmo-folder))
nil) ; default is not writable.
+(luna-define-method elmo-folder-delete ((folder elmo-folder))
+ (elmo-msgdb-delete-path folder))
+
(luna-define-method elmo-folder-rename ((folder elmo-folder) new-name)
(let* ((new-folder (elmo-make-folder new-name)))
(unless (eq (elmo-folder-type-internal folder)
(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)
+ (when (and numbers
+ (vectorp condition)
+ (member (elmo-filter-key condition) '("first" "last" "mark")))
+ (if (string= (elmo-filter-key condition) "mark")
+ (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) "any")
+ (nconc (elmo-folder-list-unreads folder)
+ (elmo-folder-list-importants folder)
+ (elmo-folder-list-answereds folder)))))
+ (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 ((last (nthcdr (1- value) numbers)))
+ (when last
+ (setcdr last nil))
+ numbers)))))))
+
+(luna-define-method elmo-folder-search ((folder elmo-folder)
+ condition
+ &optional numbers)
+ (let ((numbers (or numbers (elmo-folder-list-messages folder))))
+ (or (elmo-folder-search-fast folder condition numbers)
+ (let ((msgdb (elmo-folder-msgdb folder))
+ (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))
+ (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))
+ (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)
+ (elmo-buffer-field-condition-match condition number numbers)))))
+
(luna-define-method elmo-folder-pack-numbers ((folder elmo-folder))
nil) ; default is noop.
(setq elmo-folder-info-hashtb hashtb)))
(defsubst elmo-diff-new (diff)
- (when (consp (cdr diff))
- (car diff)))
+ (car diff))
(defsubst elmo-diff-unread (diff)
- (if (consp (cdr diff))
- (nth 1 diff)
- (car diff)))
+ (when (consp (cdr diff))
+ (nth 1 diff)))
(defsubst elmo-diff-all (diff)
(if (consp (cdr diff))
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))
+ (setq unsync (if (and in-db (car in-folder))
(- (car in-folder) in-db-max)
- (if (and in-folder
- (null in-db))
+ (if (and in-folder (null in-db))
(cdr in-folder)
- (if (null (car in-folder))
- nil))))
+ (car in-folder))))
(setq messages (cdr in-folder))
(if (and unsync messages (> unsync messages))
(setq unsync messages))
(luna-define-method elmo-folder-append-messages ((folder elmo-folder)
src-folder
numbers
- unread-marks
&optional
same-number)
(elmo-generic-folder-append-messages folder src-folder numbers
- unread-marks same-number))
+ same-number))
(defun elmo-generic-folder-append-messages (folder src-folder numbers
- unread-marks same-number)
+ same-number)
(let (unseen seen-list succeed-numbers failure cache)
(with-temp-buffer
+ (set-buffer-multibyte nil)
(while numbers
(setq failure nil)
(condition-case nil
- (progn
- (elmo-message-fetch
- src-folder (car numbers)
- (if (and (not (elmo-folder-plugged-p src-folder))
- elmo-enable-disconnected-operation
- (setq cache (elmo-file-cache-get
- (elmo-message-field
- src-folder (car numbers)
- 'message-id)))
- (eq (elmo-file-cache-status cache) 'entire))
- (elmo-make-fetch-strategy
- 'entire t nil (elmo-file-cache-path cache))
- (elmo-make-fetch-strategy 'entire t))
- nil (current-buffer)
- 'unread)
- (unless (eq (buffer-size) 0)
- (setq failure (not
- (elmo-folder-append-buffer
- folder
- (setq unseen (member (elmo-message-mark
- src-folder (car numbers))
- unread-marks))
- (if same-number (car numbers)))))))
+ (setq cache (elmo-file-cache-get
+ (elmo-message-field src-folder
+ (car numbers)
+ 'message-id))
+ failure
+ (not
+ (and
+ (elmo-message-fetch
+ src-folder (car numbers)
+ (if (elmo-folder-plugged-p src-folder)
+ (elmo-make-fetch-strategy
+ 'entire 'maybe nil
+ (and cache (elmo-file-cache-path cache)))
+ (or (and elmo-enable-disconnected-operation
+ cache
+ (eq (elmo-file-cache-status cache) 'entire)
+ (elmo-make-fetch-strategy
+ 'entire t nil
+ (elmo-file-cache-path cache)))
+ (error "Unplugged")))
+ nil (current-buffer)
+ 'unread)
+ (> (buffer-size) 0)
+ (elmo-folder-append-buffer
+ folder
+ (setq unseen (member (elmo-message-mark
+ src-folder (car numbers))
+ (elmo-msgdb-unread-marks)))
+ (if same-number (car numbers))))))
(error (setq failure t)))
;; FETCH & APPEND finished
(unless failure
no-delete-info
no-delete
same-number
- unread-marks
save-unread)
(save-excursion
(let* ((messages msgs)
(unless (setq succeeds (elmo-folder-append-messages dst-folder
src-folder
messages
- unread-marks
same-number))
(error "move: append message to %s failed"
(elmo-folder-name-internal dst-folder)))
(setq seen-list
(elmo-msgdb-add-msgs-to-seen-list
msgs (elmo-folder-msgdb src-folder)
- unread-marks seen-list))
+ seen-list))
(elmo-msgdb-seen-save dir seen-list))))
(if (and (not no-delete) succeeds)
(progn
folder
(elmo-folder-expand-msgdb-path folder))))
+(defun elmo-message-set-cached (folder number cached)
+ "Set cache status of the message mark.
+FOLDER is the ELMO folder structure.
+NUMBER is a number of the message.
+If CACHED is t, message mark is set as cached."
+ (when (elmo-msgdb-set-cached
+ (elmo-folder-msgdb folder) number cached)
+ (elmo-folder-set-mark-modified-internal folder t)))
+
+
(defun elmo-message-mark (folder number)
"Get mark of the message.
FOLDER is the ELMO folder structure.
NUMBER is a number of the message."
- (cadr (assq number (elmo-msgdb-get-mark-alist (elmo-folder-msgdb folder)))))
+ (elmo-msgdb-get-mark (elmo-folder-msgdb folder) number))
(defun elmo-folder-list-messages-mark-match (folder mark-regexp)
"List messages in the FOLDER which have a mark that matches MARK-REGEXP"
FOLDER is the ELMO folder structure.
NUMBER is a number of the message.
FIELD is a symbol of the field."
- (case field
- (message-id (elmo-msgdb-overview-entity-get-id
- (elmo-msgdb-overview-get-entity
- number (elmo-folder-msgdb folder))))
- (subject (elmo-msgdb-overview-entity-get-subject
- (elmo-msgdb-overview-get-entity
- number (elmo-folder-msgdb folder))))
- (size (elmo-msgdb-overview-entity-get-size
- (elmo-msgdb-overview-get-entity
- number (elmo-folder-msgdb folder))))
- (date (elmo-msgdb-overview-entity-get-date
- (elmo-msgdb-overview-get-entity
- number (elmo-folder-msgdb folder))))
- (to (elmo-msgdb-overview-entity-get-to
- (elmo-msgdb-overview-get-entity
- number (elmo-folder-msgdb folder))))
- (cc (elmo-msgdb-overview-entity-get-cc
- (elmo-msgdb-overview-get-entity
- number (elmo-folder-msgdb folder))))))
+ (elmo-msgdb-get-field (elmo-folder-msgdb folder) number field))
(defun elmo-message-set-mark (folder number mark)
- "Set mark for the message in the FOLDER with NUMBER as MARK."
- (elmo-msgdb-set-mark-alist
+ ;; Set mark for the message in the FOLDER with NUMBER as MARK.
+ (elmo-msgdb-set-mark
(elmo-folder-msgdb folder)
- (elmo-msgdb-mark-set
- (elmo-msgdb-get-mark-alist (elmo-folder-msgdb folder))
- number mark)))
+ number mark))
(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) numbers)
- t)
+(luna-define-method elmo-folder-unmark-important ((folder elmo-folder)
+ numbers)
+ (when (elmo-folder-msgdb-internal folder)
+ (dolist (number numbers)
+ (elmo-msgdb-unset-flag (elmo-folder-msgdb folder)
+ folder
+ number
+ 'important))))
(luna-define-method elmo-folder-mark-as-important ((folder elmo-folder)
numbers)
- t)
-
-(luna-define-method elmo-folder-unmark-read ((folder elmo-folder) numbers)
- t)
-
-(luna-define-method elmo-folder-mark-as-read ((folder elmo-folder) numbers)
- t)
+ (when (elmo-folder-msgdb-internal folder)
+ (dolist (number numbers)
+ (elmo-msgdb-set-flag (elmo-folder-msgdb folder)
+ folder
+ number
+ 'important))))
+
+(luna-define-method elmo-folder-unmark-read ((folder elmo-folder)
+ numbers
+ &optional ignore-flags)
+ (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)
+ numbers
+ &optional ignore-flag)
+ (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)
+ (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)
+ (when (elmo-folder-msgdb-internal folder)
+ (dolist (number numbers)
+ (elmo-msgdb-set-flag (elmo-folder-msgdb folder)
+ folder
+ number
+ 'answered))))
(luna-define-method elmo-folder-process-crosspost ((folder elmo-folder)
&optional
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.
(t
;; Do nothing.
(setq to-be-deleted nil)))
- (elmo-folder-set-msgdb-internal folder
- (elmo-msgdb-append
- (elmo-folder-msgdb folder)
- append-msgdb t))
(length to-be-deleted))
0))
(defun elmo-folder-confirm-appends (appends)
(let ((len (length appends))
in)
- (if (and (> len elmo-folder-update-threshold)
+ (if (and elmo-folder-update-threshold
+ (> len elmo-folder-update-threshold)
elmo-folder-update-confirm)
- (if (y-or-n-p (format "Too many messages(%d). Continue? " len))
+ (if (y-or-n-p (format "Too many messages(%d). Update all? " len))
appends
(setq in elmo-folder-update-threshold)
(catch 'end
in (string-to-int in))
(if (< len in)
(throw 'end len))
- (if (y-or-n-p (format "%d messages are disappeared. OK? "
+ (if (y-or-n-p (format "%d messages are not appeared. OK? "
(max (- len in) 0)))
(throw 'end in))))
(nthcdr (max (- len in) 0) appends))
- (if (and (> len elmo-folder-update-threshold)
+ (if (and elmo-folder-update-threshold
+ (> len elmo-folder-update-threshold)
(not elmo-folder-update-confirm))
(nthcdr (max (- len elmo-folder-update-threshold) 0) appends)
appends))))
(with-current-buffer outbuf
(erase-buffer)
(elmo-message-fetch-with-cache-process folder number
- strategy section unread)
- t)
+ strategy section unread))
(with-temp-buffer
(elmo-message-fetch-with-cache-process folder number
strategy section unread)
number strategy
&optional
section unread)
- (let (cache-path cache-file)
- (if (and (elmo-fetch-strategy-use-cache strategy)
- (setq cache-path (elmo-fetch-strategy-cache-path strategy))
- (setq cache-file (elmo-file-cache-expand-path
- cache-path
- section))
- (file-exists-p cache-file)
- (or (not (elmo-cache-path-section-p cache-file))
- (not (eq (elmo-fetch-strategy-entireness strategy) 'entire))))
- (insert-file-contents-as-binary cache-file)
- (elmo-message-fetch-internal folder number strategy section unread)
- (elmo-delete-cr-buffer)
- (when (and (> (buffer-size) 0)
- (elmo-fetch-strategy-save-cache strategy)
- (elmo-fetch-strategy-cache-path strategy))
- (elmo-file-cache-save
- (elmo-fetch-strategy-cache-path strategy)
- section)))))
+ (let ((cache-path (elmo-fetch-strategy-cache-path strategy))
+ (method-priorities
+ (cond ((eq (elmo-fetch-strategy-use-cache strategy) 'maybe)
+ '(entity cache))
+ ((elmo-fetch-strategy-use-cache strategy)
+ '(cache entity))
+ (t
+ '(entity))))
+ result err)
+ (while (and method-priorities
+ (null result))
+ (setq result
+ (case (car method-priorities)
+ (cache
+ (elmo-file-cache-load cache-path section))
+ (entity
+ (when (and (condition-case error
+ (elmo-message-fetch-internal folder number
+ strategy
+ section
+ 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))
+ t)))
+ method-priorities (cdr method-priorities)))
+ (or result
+ (and err (signal (car err) (cdr err))))))
(luna-define-method elmo-folder-clear ((folder elmo-folder)
&optional keep-killed)
(elmo-folder-set-msgdb-internal folder (elmo-msgdb-clear)))
(defun elmo-folder-synchronize (folder
- new-mark ;"N"
- unread-uncached-mark ;"U"
- unread-cached-mark ;"!"
- read-uncached-mark ;"u"
- important-mark ;"$"
&optional ignore-msgdb
no-check)
"Synchronize the folder data to the newest status.
FOLDER is the ELMO folder structure.
-NEW-MARK, UNREAD-CACHED-MARK, READ-UNCACHED-MARK, and IMPORTANT-MARK
-are mark strings for new messages, unread but cached messages,
-read but not cached messages, and important messages.
If optional IGNORE-MSGDB is non-nil, current msgdb is thrown away except
-read mark status. If IGNORE-MSGDB is 'visible-only, only visible messages
+flag status. If IGNORE-MSGDB is 'visible-only, only visible messages
\(the messages which are not in the killed-list\) are thrown away and
synchronized.
If NO-CHECK is non-nil, rechecking folder is skipped.
-Return a list of
-\(NEW-MSGDB DELETE-LIST CROSSED\)
-NEW-MSGDB is the newly appended msgdb.
-DELETE-LIST is a list of deleted message number.
-CROSSED is cross-posted message number.
+Return a list of a cross-posted message number.
If update process is interrupted, return nil."
(let ((killed-list (elmo-folder-killed-list-internal folder))
(before-append t)
(elmo-folder-msgdb folder)))
(if ignore-msgdb
(progn
- (setq seen-list (nconc
- (elmo-msgdb-mark-alist-to-seen-list
- number-alist mark-alist
- (concat important-mark read-uncached-mark))
- seen-list))
+ (setq seen-list (nconc (elmo-msgdb-seen-list
+ (elmo-folder-msgdb folder))
+ seen-list))
(elmo-folder-clear folder (eq ignore-msgdb 'visible-only))))
(unless no-check (elmo-folder-check folder))
(condition-case nil
(length new-list)))
(setq diff-2 (elmo-list-diff (car diff) new-list)))
(elmo-msgdb-append-to-killed-list folder (car diff-2)))
- ;; Don't delete important marked messages.
- (setq delete-list
- (if (eq (elmo-folder-type-internal folder) 'mark)
- (cadr diff)
- (elmo-delete-if
- (lambda (x)
- (and (setq mark (cadr (assq x mark-alist)))
- (string= mark important-mark)))
- ;; delete message list
- (cadr diff))))
+ (setq delete-list (cadr diff))
(if (or (equal diff '(nil nil))
(equal diff '(nil))
(and (eq (length (car diff)) 0)
(progn
(elmo-folder-update-number folder)
(elmo-folder-process-crosspost folder)
- (list nil nil nil) ; no updates.
+ 0 ; no updates.
)
(if delete-list (elmo-msgdb-delete-msgs
(elmo-folder-msgdb folder) delete-list))
(when new-list
(setq new-msgdb (elmo-folder-msgdb-create
- folder
- new-list
- new-mark unread-cached-mark
- read-uncached-mark important-mark
- seen-list))
+ folder new-list seen-list))
(elmo-msgdb-change-mark (elmo-folder-msgdb folder)
- new-mark unread-uncached-mark)
+ elmo-msgdb-new-mark
+ elmo-msgdb-unread-uncached-mark)
;; Clear seen-list.
(if (elmo-folder-persistent-p folder)
(setq seen-list (elmo-msgdb-seen-save
(elmo-folder-set-message-modified-internal folder t)
(elmo-folder-set-mark-modified-internal folder t))
;; return value.
- (list new-msgdb delete-list crossed)))
+ (or crossed 0)))
(quit
;; Resume to the original status.
(if before-append
(elmo-msgdb-get-number-alist
(elmo-folder-msgdb folder))))
-;;;
-(defun elmo-msgdb-search (folder condition msgdb)
- "Search messages which satisfy CONDITION from FOLDER with MSGDB."
- (let* ((condition (car (elmo-parse-search-condition condition)))
- (overview (elmo-msgdb-get-overview msgdb))
- (number-alist (elmo-msgdb-get-number-alist msgdb))
- (number-list (mapcar 'car number-alist))
- (length (length overview))
- (i 0)
- result)
- (if (not (elmo-condition-in-msgdb-p condition))
- (elmo-folder-search folder condition number-list)
- (while overview
- (if (elmo-msgdb-search-internal condition (car overview)
- number-list)
- (setq result
- (cons
- (elmo-msgdb-overview-entity-get-number (car overview))
- result)))
- (setq i (1+ i))
- (elmo-display-progress
- 'elmo-msgdb-search "Searching..." (/ (* i 100) length))
- (setq overview (cdr overview)))
- (nreverse result))))
-
-(defun elmo-msgdb-load (folder)
- (message "Loading msgdb for %s..." (elmo-folder-name-internal folder))
- (let* ((path (elmo-folder-msgdb-path folder))
- (overview (elmo-msgdb-overview-load path))
- (msgdb (list overview
- (elmo-msgdb-number-load path)
- (elmo-msgdb-mark-load path)
- (elmo-msgdb-make-overview-hashtb overview))))
- (message "Loading msgdb for %s...done" (elmo-folder-name-internal folder))
+(defun elmo-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
(elmo-msgdb-get-number-alist msgdb))
+
+ (unless silent
+ (message "Loading msgdb for %s...done"
+ (elmo-folder-name-internal folder)))
msgdb))
-
+
(defun elmo-msgdb-delete-path (folder)
(let ((path (elmo-folder-msgdb-path folder)))
(if (file-directory-p path)
(elmo-crosspost-alist-save elmo-crosspost-message-alist)
(setq elmo-crosspost-message-alist-modified nil))))
-(defun elmo-folder-make-temp-dir (folder)
+(defun elmo-folder-make-temporary-directory (folder)
;; Make a temporary directory for FOLDER.
(let ((temp-dir (make-temp-name
(concat
'elmo-imap4-default-user)
(elmo-define-obsolete-variable 'elmo-default-imap4-port
'elmo-imap4-default-port)
+(elmo-define-obsolete-variable 'elmo-default-imap4-stream-type
+ 'elmo-imap4-default-stream-type)
(elmo-define-obsolete-variable 'elmo-default-nntp-server
'elmo-nntp-default-server)
(elmo-define-obsolete-variable 'elmo-default-nntp-user
'elmo-nntp-default-user)
(elmo-define-obsolete-variable 'elmo-default-nntp-port
'elmo-nntp-default-port)
+(elmo-define-obsolete-variable 'elmo-default-nntp-stream-type
+ 'elmo-nntp-default-stream-type)
(elmo-define-obsolete-variable 'elmo-default-pop3-server
'elmo-pop3-default-server)
(elmo-define-obsolete-variable 'elmo-default-pop3-user
'elmo-pop3-default-authenticate-type)
(elmo-define-obsolete-variable 'elmo-default-pop3-port
'elmo-pop3-default-port)
+(elmo-define-obsolete-variable 'elmo-default-pop3-stream-type
+ 'elmo-pop3-default-stream-type)
+(elmo-define-obsolete-variable 'elmo-cache-dirname
+ 'elmo-cache-directory)
+(elmo-define-obsolete-variable 'elmo-msgdb-dir
+ 'elmo-msgdb-directory)
+
+;; Obsolete functions.
+;; 2001-12-11: *-dir -> *-directory
+(defalias 'elmo-folder-make-temp-dir 'elmo-folder-make-temporary-directory)
+(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))