* etc/icons/wl-draft-save-and-exit-up.xpm: Modified.
[elisp/wanderlust.git] / elmo / elmo.el
index 49a8794..b2a437c 100644 (file)
@@ -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)))
 
+(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-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)))))
+
+(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.
 
@@ -784,13 +863,11 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-MARK-ALIST).")
     (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))
@@ -886,6 +963,7 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-MARK-ALIST).")
                                                   unread-marks 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
@@ -1176,7 +1254,7 @@ FIELD is a symbol of the field."
                                                           section unread)
   (let ((cache-path (elmo-fetch-strategy-cache-path strategy))
        (method-priorities
-        (cond ((eq (elmo-fetch-strategy-use-cache strategy) 'meybe)
+        (cond ((eq (elmo-fetch-strategy-use-cache strategy) 'maybe)
                '(entity cache))
               ((elmo-fetch-strategy-use-cache strategy)
                '(cache entity))
@@ -1278,16 +1356,7 @@ If update process is interrupted, return 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)
@@ -1335,30 +1404,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))
@@ -1485,12 +1530,16 @@ Return a hashtable for newsgroups."
                               '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
@@ -1499,6 +1548,8 @@ Return a hashtable for newsgroups."
                               '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