From 3823cb47f19c37a739371e84d76f051cdcc365bd Mon Sep 17 00:00:00 2001 From: hmurata Date: Sun, 6 Jan 2002 10:46:18 +0000 Subject: [PATCH] * elmo.el (elmo-folder-search): Defined. Fixed docstring. (elmo-message-match-condition): New method. (elmo-folder-search-fast): New inline function. (elmo-msgdb-search): Removed. * elmo-filter.el (elmo-folder-msgdb-create): Create from msgdb of target folder if it is unplugged. (elmo-folder-list-messages-internal): Return t if target folder is unplugged and itself is persistent; In this case, use list be searched already. * elmo-msgdb.el (elmo-msgdb-search-internal): Removed. (elmo-msgdb-search-internal-primitive): Ditto. (elmo-msgdb-match-condition): New function. (elmo-msgdb-match-condition-primitive): Ditto. * elmo-util.el (elmo-filter-condition-p): New macro. * elmo-cache.el (elmo-folder-search): Removed. * elmo-localdir.el (elmo-folder-search): Ditto. * elmo-maildir.el (elmo-folder-search): Ditto. * elmo-mark.el (elmo-folder-search): Ditto. * elmo-nmz.el (elmo-folder-search): Ditto. * elmo-sendlog.el (elmo-folder-search): Ditto. * elmo-shimbun.el (elmo-folder-search): Ditto. * elmo-imap4.el (elmo-folder-search): Call method of parent class if folder is unplugged. * elmo-nntp.el (elmo-folder-search): Likewise. (elmo-nntp-search-internal): New function. --- elmo/ChangeLog | 38 ++++++++++++ elmo/elmo-cache.el | 23 -------- elmo/elmo-filter.el | 58 +++++++++++++++--- elmo/elmo-imap4.el | 18 +++--- elmo/elmo-localdir.el | 40 ------------- elmo/elmo-maildir.el | 21 ------- elmo/elmo-mark.el | 23 -------- elmo/elmo-msgdb.el | 157 +++++++++++++++++++++++++++++-------------------- elmo/elmo-nmz.el | 23 -------- elmo/elmo-nntp.el | 24 +++++--- elmo/elmo-sendlog.el | 23 -------- elmo/elmo-shimbun.el | 4 -- elmo/elmo-util.el | 3 + elmo/elmo.el | 105 +++++++++++++++++++++++++-------- 14 files changed, 291 insertions(+), 269 deletions(-) diff --git a/elmo/ChangeLog b/elmo/ChangeLog index 4b24448..95edb0f 100644 --- a/elmo/ChangeLog +++ b/elmo/ChangeLog @@ -1,5 +1,43 @@ 2002-01-06 Hiroya Murata + * elmo.el (elmo-folder-search): Defined. Fixed docstring. + (elmo-message-match-condition): New method. + (elmo-folder-search-fast): New inline function. + (elmo-msgdb-search): Removed. + + * elmo-filter.el (elmo-folder-msgdb-create): Create from msgdb of + target folder if it is unplugged. + (elmo-folder-list-messages-internal): Return t if target folder is + unplugged and itself is persistent; In this case, use list be + searched already. + + * elmo-msgdb.el (elmo-msgdb-search-internal): Removed. + (elmo-msgdb-search-internal-primitive): Ditto. + (elmo-msgdb-match-condition): New function. + (elmo-msgdb-match-condition-primitive): Ditto. + + * elmo-util.el (elmo-filter-condition-p): New macro. + + * elmo-cache.el (elmo-folder-search): Removed. + + * elmo-localdir.el (elmo-folder-search): Ditto. + + * elmo-maildir.el (elmo-folder-search): Ditto. + + * elmo-mark.el (elmo-folder-search): Ditto. + + * elmo-nmz.el (elmo-folder-search): Ditto. + + * elmo-sendlog.el (elmo-folder-search): Ditto. + + * elmo-shimbun.el (elmo-folder-search): Ditto. + + * elmo-imap4.el (elmo-folder-search): Call method of parent class + if folder is unplugged. + + * elmo-nntp.el (elmo-folder-search): Likewise. + (elmo-nntp-search-internal): New function. + * elmo-version.el (elmo-version): Up to 2.9.3. 2001-12-27 Hiroya Murata diff --git a/elmo/elmo-cache.el b/elmo/elmo-cache.el index 2824f85..b13248b 100644 --- a/elmo/elmo-cache.el +++ b/elmo/elmo-cache.el @@ -174,29 +174,6 @@ (luna-define-method elmo-folder-exists-p ((folder elmo-cache-folder)) t) -(luna-define-method elmo-folder-search ((folder elmo-cache-folder) - condition &optional from-msgs) - (let* ((msgs (or from-msgs (elmo-folder-list-messages folder))) - (number-list msgs) - (i 0) - (num (length msgs)) - file - matched - case-fold-search) - (while msgs - (if (and (setq file (elmo-message-file-name folder (car msgs))) - (file-exists-p file) - (elmo-file-field-condition-match file - condition - (car msgs) - number-list)) - (setq matched (nconc matched (list (car msgs))))) - (elmo-display-progress - 'elmo-internal-folder-search "Searching..." - (/ (* (setq i (1+ i)) 100) num)) - (setq msgs (cdr msgs))) - matched)) - (luna-define-method elmo-message-file-p ((folder elmo-cache-folder) number) t) diff --git a/elmo/elmo-filter.el b/elmo/elmo-filter.el index abaf702..3a29327 100644 --- a/elmo/elmo-filter.el +++ b/elmo/elmo-filter.el @@ -87,11 +87,48 @@ numlist new-mark already-mark seen-mark important-mark seen-list) - (elmo-folder-msgdb-create (elmo-filter-folder-target-internal folder) - numlist - new-mark - already-mark - seen-mark important-mark seen-list)) + (let ((target-folder (elmo-filter-folder-target-internal folder))) + (if (elmo-folder-plugged-p target-folder) + (elmo-folder-msgdb-create target-folder + numlist + new-mark + already-mark + seen-mark important-mark seen-list) + ;; Copy from msgdb of target folder if it is unplugged. + (let ((len (length numlist)) + (msgdb (elmo-folder-msgdb target-folder)) + overview number-alist mark-alist + message-id seen gmark) + (when (> len elmo-display-progress-threshold) + (elmo-progress-set 'elmo-folder-msgdb-create + len "Creating msgdb...")) + (unwind-protect + (dolist (number numlist) + (let ((entity (elmo-msgdb-overview-get-entity number msgdb))) + (when entity + (setq entity (elmo-msgdb-copy-overview-entity entity) + overview (elmo-msgdb-append-element overview entity) + message-id (elmo-msgdb-overview-entity-get-id entity) + number-alist (elmo-msgdb-number-add number-alist + number + message-id) + seen (member message-id seen-list)) + (if (setq gmark (or (elmo-msgdb-global-mark-get message-id) + (if (elmo-file-cache-exists-p message-id) + (if seen + nil + already-mark) + (if seen + nil ;;seen-mark + new-mark)))) + (setq mark-alist + (elmo-msgdb-mark-append + mark-alist + number + gmark))))) + (elmo-progress-notify 'elmo-folder-msgdb-create)) + (elmo-progress-clear 'elmo-folder-msgdb-create)) + (list overview number-alist mark-alist))))) (luna-define-method elmo-folder-append-buffer ((folder elmo-filter-folder) unread &optional number) @@ -113,8 +150,15 @@ (luna-define-method elmo-folder-list-messages-internal ((folder elmo-filter-folder) &optional nohide) - (elmo-folder-search (elmo-filter-folder-target-internal folder) - (elmo-filter-folder-condition-internal folder))) + (let ((target (elmo-filter-folder-target-internal folder))) + (if (or (elmo-folder-plugged-p target) + (not (elmo-folder-persistent-p folder))) + ;; search target folder + (elmo-folder-search + target + (elmo-filter-folder-condition-internal folder)) + ;; not available + t))) (defsubst elmo-filter-folder-list-unreads-internal (folder unread-marks mark-alist) diff --git a/elmo/elmo-imap4.el b/elmo/elmo-imap4.el index c9ae6e2..355b111 100644 --- a/elmo/elmo-imap4.el +++ b/elmo/elmo-imap4.el @@ -2205,14 +2205,16 @@ If optional argument REMOVE is non-nil, remove FLAG." folder session (nth 2 condition) from-msgs))) result (sort result '<)))))) -(luna-define-method elmo-folder-search ((folder elmo-imap4-folder) - condition &optional numbers) - (save-excursion - (let ((session (elmo-imap4-get-session folder))) - (elmo-imap4-session-select-mailbox - session - (elmo-imap4-folder-mailbox-internal folder)) - (elmo-imap4-search-internal folder session condition numbers)))) +(luna-define-method elmo-folder-search :around ((folder elmo-imap4-folder) + condition &optional numbers) + (if (elmo-folder-plugged-p folder) + (save-excursion + (let ((session (elmo-imap4-get-session folder))) + (elmo-imap4-session-select-mailbox + session + (elmo-imap4-folder-mailbox-internal folder)) + (elmo-imap4-search-internal folder session condition numbers))) + (luna-call-next-method))) (luna-define-method elmo-folder-msgdb-create-plugged ((folder elmo-imap4-folder) numbers &rest args) diff --git a/elmo/elmo-localdir.el b/elmo/elmo-localdir.el index b1f9ef9..f9e5c2f 100644 --- a/elmo/elmo-localdir.el +++ b/elmo/elmo-localdir.el @@ -323,46 +323,6 @@ (elmo-localdir-folder-directory-internal folder)) condition number number-list)) -(luna-define-method elmo-folder-search ((folder elmo-localdir-folder) - condition &optional numbers) - (let* ((msgs (or numbers (elmo-folder-list-messages folder))) - (num (length msgs)) - (i 0) - last cur number-list case-fold-search ret-val) - (cond - ;; short cut. - ((and (vectorp condition) - (not (eq (elmo-filter-type condition) 'unmatch)) - (string= (elmo-filter-key condition) "last")) - (nthcdr (max (- (length msgs) - (string-to-int (elmo-filter-value condition))) - 0) - msgs)) - ((and (vectorp condition) - (not (eq (elmo-filter-type condition) 'unmatch)) - (string= (elmo-filter-key condition) "first")) - (let ((rest (nthcdr (string-to-int (elmo-filter-value condition) ) - msgs))) - (mapcar '(lambda (x) - (delete x msgs)) rest)) - msgs) - (t - (setq number-list msgs) - (while msgs - (if (elmo-localdir-field-condition-match folder condition - (car msgs) number-list) - (setq ret-val (cons (car msgs) ret-val))) - (when (> num elmo-display-progress-threshold) - (setq i (1+ i)) - (setq cur (/ (* i 100) num)) - (unless (eq cur last) - (elmo-display-progress - 'elmo-localdir-search "Searching..." - cur) - (setq last cur))) - (setq msgs (cdr msgs))) - (nreverse ret-val))))) - (luna-define-method elmo-folder-pack-numbers ((folder elmo-localdir-folder)) (let* ((dir (elmo-localdir-folder-directory-internal folder)) (msgdb (elmo-folder-msgdb folder)) diff --git a/elmo/elmo-maildir.el b/elmo/elmo-maildir.el index ab3bf6a..0a91115 100644 --- a/elmo/elmo-maildir.el +++ b/elmo/elmo-maildir.el @@ -474,27 +474,6 @@ file name for maildir directories." t) (error nil)))) -(luna-define-method elmo-folder-search ((folder elmo-maildir-folder) - condition &optional numbers) - (save-excursion - (let* ((msgs (or numbers (elmo-folder-list-messages folder))) - (i 0) - case-fold-search matches - percent num - (len (length msgs)) - number-list msg-num) - (setq number-list msgs) - (dolist (number numbers) - (if (elmo-file-field-condition-match - (elmo-message-file-name folder number) - condition number number-list) - (setq matches (cons number matches))) - (setq i (1+ i)) - (elmo-display-progress - 'elmo-maildir-search "Searching..." - (/ (* i 100) len))) - (nreverse matches)))) - (require 'product) (product-provide (provide 'elmo-maildir) (require 'elmo-version)) diff --git a/elmo/elmo-mark.el b/elmo/elmo-mark.el index 35352db..02cdde2 100644 --- a/elmo/elmo-mark.el +++ b/elmo/elmo-mark.el @@ -164,29 +164,6 @@ (luna-define-method elmo-folder-writable-p ((folder elmo-mark-folder)) t) -(luna-define-method elmo-folder-search ((folder elmo-mark-folder) - condition &optional from-msgs) - (let* ((msgs (or from-msgs (elmo-folder-list-messages folder))) - (number-list msgs) - (i 0) - (num (length msgs)) - file - matched - case-fold-search) - (while msgs - (if (and (setq file (elmo-message-file-name folder (car msgs))) - (file-exists-p file) - (elmo-file-field-condition-match file - condition - (car msgs) - number-list)) - (setq matched (nconc matched (list (car msgs))))) - (elmo-display-progress - 'elmo-internal-folder-search "Searching..." - (/ (* (setq i (1+ i)) 100) num)) - (setq msgs (cdr msgs))) - matched)) - ;;; To override elmo-map-folder methods. (luna-define-method elmo-folder-list-unreads-internal ((folder elmo-mark-folder) unread-marks &optional mark-alist) diff --git a/elmo/elmo-msgdb.el b/elmo/elmo-msgdb.el index a1068dc..87c63d2 100644 --- a/elmo/elmo-msgdb.el +++ b/elmo/elmo-msgdb.el @@ -274,77 +274,104 @@ header separator." (expand-file-name elmo-msgdb-overview-filename dir) overview)) -(defun elmo-msgdb-search-internal-primitive (condition entity number-list) - (let ((key (elmo-filter-key condition)) - (case-fold-search t) - result) - (cond - ((string= key "last") - (setq result (<= (length (memq - (elmo-msgdb-overview-entity-get-number entity) - number-list)) - (string-to-int (elmo-filter-value condition))))) - ((string= key "first") - (setq result (< (- - (length number-list) - (length (memq - (elmo-msgdb-overview-entity-get-number entity) - number-list))) - (string-to-int (elmo-filter-value condition))))) - ((string= key "from") - (setq result (string-match - (elmo-filter-value condition) - (elmo-msgdb-overview-entity-get-from entity)))) - ((string= key "subject") - (setq result (string-match - (elmo-filter-value condition) - (elmo-msgdb-overview-entity-get-subject entity)))) - ((string= key "to") - (setq result (string-match - (elmo-filter-value condition) - (elmo-msgdb-overview-entity-get-to entity)))) - ((string= key "cc") - (setq result (string-match - (elmo-filter-value condition) - (elmo-msgdb-overview-entity-get-cc entity)))) - ((or (string= key "since") - (string= key "before")) - (let ((field-date (elmo-date-make-sortable-string - (timezone-fix-time - (elmo-msgdb-overview-entity-get-date entity) - (current-time-zone) nil))) - (specified-date - (elmo-date-make-sortable-string - (elmo-date-get-datevec - (elmo-filter-value condition))))) - (setq result (if (string= key "since") - (or (string= specified-date field-date) - (string< specified-date field-date)) - (string< field-date specified-date))))) - ((member key elmo-msgdb-extra-fields) - (let ((extval (elmo-msgdb-overview-entity-get-extra-field entity key))) - (if (stringp extval) +(defun elmo-msgdb-match-condition-primitive (condition entity numbers) + (catch 'unresolved + (let ((key (elmo-filter-key condition)) + (case-fold-search t) + result) + (cond + ((string= key "last") + (setq result (<= (length (memq + (elmo-msgdb-overview-entity-get-number + entity) + numbers)) + (string-to-int (elmo-filter-value condition))))) + ((string= key "first") + (setq result (< (- + (length numbers) + (length (memq + (elmo-msgdb-overview-entity-get-number + entity) + numbers))) + (string-to-int (elmo-filter-value condition))))) + ((string= key "from") + (setq result (string-match + (elmo-filter-value condition) + (elmo-msgdb-overview-entity-get-from entity)))) + ((string= key "subject") + (setq result (string-match + (elmo-filter-value condition) + (elmo-msgdb-overview-entity-get-subject entity)))) + ((string= key "to") + (setq result (string-match + (elmo-filter-value condition) + (elmo-msgdb-overview-entity-get-to entity)))) + ((string= key "cc") + (setq result (string-match + (elmo-filter-value condition) + (elmo-msgdb-overview-entity-get-cc entity)))) + ((or (string= key "since") + (string= key "before")) + (let ((field-date (elmo-date-make-sortable-string + (timezone-fix-time + (elmo-msgdb-overview-entity-get-date entity) + (current-time-zone) nil))) + (specified-date + (elmo-date-make-sortable-string + (elmo-date-get-datevec + (elmo-filter-value condition))))) + (setq result (if (string= key "since") + (or (string= specified-date field-date) + (string< specified-date field-date)) + (string< field-date specified-date))))) + ((member key elmo-msgdb-extra-fields) + (let ((extval (elmo-msgdb-overview-entity-get-extra-field entity key))) + (when (stringp extval) (setq result (string-match (elmo-filter-value condition) - extval)))))) - (if (eq (elmo-filter-type condition) 'unmatch) - (setq result (not result))) - result)) - -(defun elmo-msgdb-search-internal (condition entity number-list) + extval))))) + (t + (throw 'unresolved condition))) + (if (eq (elmo-filter-type condition) 'unmatch) + (not result) + result)))) + +(defun elmo-msgdb-match-condition (condition entity numbers) (cond ((vectorp condition) - (elmo-msgdb-search-internal-primitive condition entity number-list)) + (elmo-msgdb-match-condition-primitive condition entity numbers)) ((eq (car condition) 'and) - (and (elmo-msgdb-search-internal - (nth 1 condition) entity number-list) - (elmo-msgdb-search-internal - (nth 2 condition) entity number-list))) + (let ((lhs (elmo-msgdb-match-condition (nth 1 condition) + entity numbers))) + (cond + ((elmo-filter-condition-p lhs) + (let ((rhs (elmo-msgdb-match-condition (nth 2 condition) + entity numbers))) + (cond ((elmo-filter-condition-p rhs) + (list 'and lhs rhs)) + (rhs + lhs)))) + (lhs + (elmo-msgdb-match-condition (nth 2 condition) + entity numbers))))) ((eq (car condition) 'or) - (or (elmo-msgdb-search-internal - (nth 1 condition) entity number-list) - (elmo-msgdb-search-internal - (nth 2 condition) entity number-list))))) + (let ((lhs (elmo-msgdb-match-condition (nth 1 condition) + entity numbers))) + (cond + ((elmo-filter-condition-p lhs) + (let ((rhs (elmo-msgdb-match-condition (nth 2 condition) + entity numbers))) + (cond ((elmo-filter-condition-p rhs) + (list 'or lhs rhs)) + (rhs + t) + (t + lhs)))) + (lhs + t) + (t + (elmo-msgdb-match-condition (nth 2 condition) + entity numbers))))))) (defun elmo-msgdb-delete-msgs (msgdb msgs) "Delete MSGS from MSGDB diff --git a/elmo/elmo-nmz.el b/elmo/elmo-nmz.el index d603b0d..8bfd7bc 100644 --- a/elmo/elmo-nmz.el +++ b/elmo/elmo-nmz.el @@ -254,29 +254,6 @@ If the value is a list, all elements are used as index paths for namazu." (luna-define-method elmo-folder-exists-p ((folder elmo-nmz-folder)) t) -(luna-define-method elmo-folder-search ((folder elmo-nmz-folder) - condition &optional from-msgs) - (let* ((msgs (or from-msgs (elmo-folder-list-messages folder))) - (orig msgs) - (i 0) - case-fold-search matches - percent num - (num (length msgs))) - (while msgs - (if (elmo-file-field-condition-match - (elmo-map-message-location folder (car msgs)) - condition - (car msgs) - orig) - (setq matches (cons (car msgs) matches))) - (setq i (1+ i)) - (setq percent (/ (* i 100) num)) - (elmo-display-progress - 'elmo-nmz-search "Searching..." - percent) - (setq msgs (cdr msgs))) - matches)) - ;;; To override elmo-map-folder methods. (luna-define-method elmo-folder-list-unreads-internal ((folder elmo-nmz-folder) unread-marks &optional mark-alist) diff --git a/elmo/elmo-nntp.el b/elmo/elmo-nntp.el index 151ec94..1769323 100644 --- a/elmo/elmo-nntp.el +++ b/elmo/elmo-nntp.el @@ -1174,27 +1174,37 @@ Returns a list of cons cells like (NUMBER . VALUE)" (elmo-list-filter from-msgs result) result)))))) -(luna-define-method elmo-folder-search ((folder elmo-nntp-folder) - condition &optional from-msgs) +(defun elmo-nntp-search-internal (folder condition from-msgs) (let (result) (cond ((vectorp condition) (setq result (elmo-nntp-search-primitive folder condition from-msgs))) ((eq (car condition) 'and) - (setq result (elmo-folder-search folder (nth 1 condition) from-msgs) + (setq result (elmo-nntp-search-internal folder + (nth 1 condition) + from-msgs) result (elmo-list-filter result - (elmo-folder-search + (elmo-nntp-search-internal folder (nth 2 condition) from-msgs)))) ((eq (car condition) 'or) - (setq result (elmo-folder-search folder (nth 1 condition) from-msgs) + (setq result (elmo-nntp-search-internal folder + (nth 1 condition) + from-msgs) result (elmo-uniq-list (nconc result - (elmo-folder-search folder (nth 2 condition) - from-msgs))) + (elmo-nntp-search-internal folder + (nth 2 condition) + from-msgs))) result (sort result '<)))))) +(luna-define-method elmo-folder-search :around ((folder elmo-nntp-folder) + condition &optional from-msgs) + (if (elmo-folder-plugged-p folder) + (elmo-nntp-search-internal folder condition from-msgs) + (luna-call-next-method))) + (defun elmo-nntp-get-folders-info-prepare (folder session-keys) (condition-case () (let ((session (elmo-nntp-get-session folder)) diff --git a/elmo/elmo-sendlog.el b/elmo/elmo-sendlog.el index 87885fb..d0362c7 100644 --- a/elmo/elmo-sendlog.el +++ b/elmo/elmo-sendlog.el @@ -155,29 +155,6 @@ (elmo-folder-set-killed-list-internal folder killed-list)) t) -(luna-define-method elmo-folder-search ((folder elmo-sendlog-folder) - condition &optional from-msgs) - (let* ((msgs (or from-msgs (elmo-folder-list-messages folder))) - (number-list msgs) - (i 0) - (num (length msgs)) - file - matched - case-fold-search) - (while msgs - (if (and (setq file (elmo-message-file-name folder (car msgs))) - (file-exists-p file) - (elmo-file-field-condition-match file - condition - (car msgs) - number-list)) - (setq matched (nconc matched (list (car msgs))))) - (elmo-display-progress - 'elmo-internal-folder-search "Searching..." - (/ (* (setq i (1+ i)) 100) num)) - (setq msgs (cdr msgs))) - matched)) - (luna-define-method elmo-message-file-p ((folder elmo-sendlog-folder) number) t) diff --git a/elmo/elmo-shimbun.el b/elmo/elmo-shimbun.el index c11e5e6..2828509 100644 --- a/elmo/elmo-shimbun.el +++ b/elmo/elmo-shimbun.el @@ -479,10 +479,6 @@ update overview when message is fetched." folder)))) t)) -(luna-define-method elmo-folder-search ((folder elmo-shimbun-folder) - condition &optional from-msgs) - nil) - ;;; To override elmo-map-folder methods. (luna-define-method elmo-folder-list-unreads-internal ((folder elmo-shimbun-folder) unread-marks &optional mark-alist) diff --git a/elmo/elmo-util.el b/elmo/elmo-util.el index fe62464..cbb199c 100644 --- a/elmo/elmo-util.el +++ b/elmo/elmo-util.el @@ -793,6 +793,9 @@ Return value is a cons cell of (STRUCTURE . REST)" (setq l1 (cdr l1))) (cons diff1 (list l2))))) +(defmacro elmo-filter-condition-p (filter) + `(or (vectorp ,filter) (consp ,filter))) + (defmacro elmo-filter-type (filter) (` (aref (, filter) 0))) diff --git a/elmo/elmo.el b/elmo/elmo.el index a0d8cae..932c207 100644 --- a/elmo/elmo.el +++ b/elmo/elmo.el @@ -316,10 +316,18 @@ NUMBERS is a list of message numbers to be deleted.") (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-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 new-mark already-mark seen-mark important-mark seen-list) "Create a message database (implemented in each backends). @@ -701,6 +709,77 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-MARK-ALIST).") (elmo-folder-send folder 'elmo-folder-rename-internal new-folder) (elmo-msgdb-rename-path folder new-folder))) +(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 ((entity (elmo-msgdb-overview-get-entity number msgdb)) + result) + (if entity + (setq result (elmo-msgdb-match-condition + condition + entity + numbers)) + (setq result condition)) + (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))))) + +(defsubst elmo-folder-search-fast (folder condition numbers) + (when (and numbers + (vectorp condition) + (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 ((last (nthcdr (1- value) numbers))) + (when last + (setcdr last nil)) + numbers)))))) + +(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. @@ -1326,30 +1405,6 @@ If update process is interrupted, return nil." (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)) -- 1.7.10.4