Changed codename to Venus-pre2.
[elisp/wanderlust.git] / elmo / elmo.el
index a0d8cae..a59b76e 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).
@@ -477,6 +485,8 @@ Return newly created temporary directory name which contains temporary files.")
     (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.
@@ -682,7 +692,7 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-MARK-ALIST).")
   (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.
@@ -701,6 +711,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 +865,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))
@@ -851,8 +930,7 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-MARK-ALIST).")
                     (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))
@@ -886,6 +964,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
@@ -1011,7 +1090,7 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-MARK-ALIST).")
   "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"
@@ -1028,33 +1107,13 @@ NUMBER is a number of the message."
 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
+  (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.
@@ -1081,6 +1140,19 @@ FIELD is a symbol of the field."
   ;; Do nothing.
   )
 
+(defsubst elmo-folder-replace-marks (folder alist)
+  "Replace marks of the FOLDER according to ALIST."
+  (let (pair)
+    (dolist (elem (elmo-msgdb-get-mark-alist (elmo-folder-msgdb folder)))
+      (when (setq pair (assoc (cadr elem) alist))
+       (if (elmo-message-use-cache-p folder (car elem))
+           (elmo-msgdb-set-mark (elmo-folder-msgdb folder)
+                                (car elem)
+                                (cdr pair))
+         (elmo-msgdb-set-mark (elmo-folder-msgdb folder)
+                              (car elem)
+                              nil))))))
+
 (defun elmo-generic-folder-append-msgdb (folder append-msgdb)
   (if append-msgdb
       (let* ((number-alist (elmo-msgdb-get-number-alist append-msgdb))
@@ -1120,7 +1192,7 @@ FIELD is a symbol of the field."
        (elmo-folder-set-msgdb-internal folder
                                        (elmo-msgdb-append
                                         (elmo-folder-msgdb folder)
-                                        append-msgdb t))
+                                        append-msgdb))
        (length to-be-deleted))
     0))
 
@@ -1252,9 +1324,9 @@ If update process is interrupted, return nil."
     (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))
+                          (elmo-msgdb-seen-list
+                           (elmo-folder-msgdb folder)
+                           (list important-mark read-uncached-mark))
                           seen-list))
          (elmo-folder-clear folder (eq ignore-msgdb 'visible-only))))
     (unless no-check (elmo-folder-check folder))
@@ -1326,43 +1398,18 @@ 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))
-        (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)
@@ -1476,12 +1523,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
@@ -1490,6 +1541,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
@@ -1504,6 +1557,7 @@ Return a hashtable for newsgroups."
 
 ;; autoloads
 (autoload 'elmo-dop-queue-flush "elmo-dop")
+(autoload 'elmo-nntp-post "elmo-nntp")
 
 (require 'product)
 (product-provide (provide 'elmo) (require 'elmo-version))