* wl-vars.el (wl-folder-process-duplicates-alist): New user option.
[elisp/wanderlust.git] / elmo / elmo-shimbun.el
index 424a254..11d3169 100644 (file)
 (require 'elmo-map)
 (require 'shimbun)
 
+(defcustom elmo-shimbun-check-interval 60
+  "*Check interval for shimbun."
+  :type 'integer
+  :group 'elmo)
+
+;; Internal variable.
+;; A list of elements like:
+;; ("server.group" . [header-list header-hash last-check]).
+(defvar elmo-shimbun-headers-cache nil)
+
 (eval-and-compile
   (luna-define-class elmo-shimbun-folder
-                    (elmo-map-folder) (shimbun header-hash group))
+                    (elmo-map-folder) (shimbun headers header-hash group))
   (luna-define-internal-accessors 'elmo-shimbun-folder))
 
+(defsubst elmo-shimbun-headers-cache-header-list (entry)
+  (aref entry 0))
+
+(defsubst elmo-shimbun-headers-cache-set-header-list (entry list)
+  (aset entry 0 list))
+
+(defsubst elmo-shimbun-headers-cache-header-hash (entry)
+  (aref entry 1))
+
+(defsubst elmo-shimbun-headers-cache-set-header-hash (entry hash)
+  (aset entry 1 hash))
+
+(defsubst elmo-shimbun-headers-cache-last-check (entry)
+  (aref entry 2))
+
+(defsubst elmo-shimbun-headers-cache-set-last-check (entry time)
+  (aset entry 2 time))
+
+(defsubst elmo-shimbun-lapse-seconds (time)
+  (let ((now (current-time)))
+    (+ (* (- (car now) (car time)) 65536)
+       (- (nth 1 now) (nth 1 time)))))
+
+(defsubst elmo-shimbun-headers-cache-check-p (cache)
+  (or (null (elmo-shimbun-headers-cache-last-check cache))
+      (and (elmo-shimbun-headers-cache-last-check cache)
+          (> (elmo-shimbun-lapse-seconds
+              (elmo-shimbun-headers-cache-last-check cache))
+             elmo-shimbun-check-interval))))
+
+(defun elmo-shimbun-get-headers (folder)
+  (shimbun-open-group
+   (elmo-shimbun-folder-shimbun-internal folder)
+   (elmo-shimbun-folder-group-internal folder))
+  (let* ((shimbun (elmo-shimbun-folder-shimbun-internal folder))
+        (key (concat (shimbun-server-internal shimbun)
+                     "." (shimbun-current-group-internal shimbun)))
+        (elmo-hash-minimum-size 0)
+        entry headers hash done)
+    (if (setq entry (cdr (assoc key elmo-shimbun-headers-cache)))
+       (unless (elmo-shimbun-headers-cache-check-p entry)
+         (elmo-shimbun-folder-set-headers-internal
+          folder
+          (elmo-shimbun-headers-cache-header-list entry))
+         (elmo-shimbun-folder-set-header-hash-internal
+          folder
+          (elmo-shimbun-headers-cache-header-hash entry))
+         (elmo-shimbun-headers-cache-header-list entry)
+         (setq done t)))
+    (unless done
+      (setq headers
+           (elmo-shimbun-folder-set-headers-internal
+            folder (shimbun-headers
+                    (elmo-shimbun-folder-shimbun-internal folder))))
+      (setq hash
+           (elmo-shimbun-folder-set-header-hash-internal
+            folder
+            (elmo-make-hash
+             (length (elmo-shimbun-folder-headers-internal folder)))))
+      ;; Set up header hash.
+      (dolist (header (elmo-shimbun-folder-headers-internal folder))
+       (elmo-set-hash-val
+        (shimbun-header-id header) header
+        (elmo-shimbun-folder-header-hash-internal folder)))
+      (if entry
+         (progn
+           (elmo-shimbun-headers-cache-set-header-list entry headers)
+           (elmo-shimbun-headers-cache-set-header-hash entry hash)
+           (elmo-shimbun-headers-cache-set-last-check entry (current-time)))
+       (setq elmo-shimbun-headers-cache
+             (cons (cons key (vector headers hash (current-time)))
+                   elmo-shimbun-headers-cache))))))
+
 (luna-define-method elmo-folder-initialize ((folder
                                             elmo-shimbun-folder)
                                            name)
-  (let ((server-group (split-string name "\\.")))
+  (let ((server-group (if (string-match "\\([^.]+\\)\\." name)
+                         (list (elmo-match-string 1 name)
+                               (substring name (match-end 0)))
+                       (list name))))
     (if (nth 0 server-group) ; server
        (elmo-shimbun-folder-set-shimbun-internal
         folder
 
 (luna-define-method elmo-folder-open-internal :before ((folder
                                                        elmo-shimbun-folder))
-  (shimbun-open-group
-   (elmo-shimbun-folder-shimbun-internal folder)
-   (elmo-shimbun-folder-group-internal folder))
-  (elmo-shimbun-folder-set-header-hash-internal
-   folder
-   (elmo-make-hash (length (shimbun-headers
-                           (elmo-shimbun-folder-shimbun-internal folder)))))
-  ;; Set up header hash.
-  (dolist (header (shimbun-headers (elmo-shimbun-folder-shimbun-internal
-                                   folder)))
-    (elmo-set-hash-val
-     (shimbun-header-id header) header
-     (elmo-shimbun-folder-header-hash-internal folder))))
+  (when (elmo-folder-plugged-p folder)
+    (elmo-shimbun-get-headers folder)))
 
 (luna-define-method elmo-folder-close-internal :after ((folder
                                                        elmo-shimbun-folder))
   (shimbun-close-group
    (elmo-shimbun-folder-shimbun-internal folder))
+  (elmo-shimbun-folder-set-headers-internal
+   folder nil)
   (elmo-shimbun-folder-set-header-hash-internal
    folder nil))
 
+(luna-define-method elmo-folder-plugged-p ((folder elmo-shimbun-folder))
+  (elmo-plugged-p
+   "shimbun" 
+   (shimbun-server-internal (elmo-shimbun-folder-shimbun-internal folder))
+   nil nil
+   (shimbun-server-internal (elmo-shimbun-folder-shimbun-internal folder))))
+                           
+(luna-define-method elmo-folder-set-plugged ((folder elmo-shimbun-folder)
+                                            plugged &optional add)
+  (elmo-set-plugged plugged
+                   "shimbun"
+                   (shimbun-server-internal
+                    (elmo-shimbun-folder-shimbun-internal folder))
+                   nil nil nil
+                   (shimbun-server-internal
+                    (elmo-shimbun-folder-shimbun-internal folder))
+                   add))
+
 (luna-define-method elmo-folder-check :after ((folder elmo-shimbun-folder))
-  (shimbun-close-group
-   (elmo-shimbun-folder-shimbun-internal folder))
-  (shimbun-open-group
-   (elmo-shimbun-folder-shimbun-internal folder)
-   (elmo-shimbun-folder-group-internal folder)))
+  (when (shimbun-current-group-internal 
+        (elmo-shimbun-folder-shimbun-internal folder))
+    ;; Discard current headers information.
+    (elmo-folder-close-internal folder)
+    (elmo-folder-open-internal folder)))
 
 (luna-define-method elmo-folder-expand-msgdb-path ((folder
                                                    elmo-shimbun-folder))
    (expand-file-name "shimbun" elmo-msgdb-dir)))
                     
 (defun elmo-shimbun-msgdb-create-entity (folder number)
-  (with-temp-buffer
-    (shimbun-header-insert
-     (elmo-get-hash-val
-      (elmo-map-message-location folder number)
-      (elmo-shimbun-folder-header-hash-internal folder)))
-    (elmo-msgdb-create-overview-from-buffer number)))
+  (let ((header (elmo-get-hash-val
+                (elmo-map-message-location folder number)
+                (elmo-shimbun-folder-header-hash-internal folder))))
+    (when header
+      (with-temp-buffer
+       (shimbun-header-insert
+        (elmo-shimbun-folder-shimbun-internal folder)
+        header)
+       (elmo-msgdb-create-overview-from-buffer number)))))
 
 (luna-define-method elmo-folder-msgdb-create ((folder elmo-shimbun-folder)
                                              numlist new-mark
                        (elmo-shimbun-folder-header-hash-internal folder)))
       (buffer-string))))
 
+(luna-define-method elmo-folder-list-messages-internal :around
+  ((folder elmo-shimbun-folder) &optional nohide)
+  (if (elmo-folder-plugged-p folder)
+      (luna-call-next-method)
+    t))
+
 (luna-define-method elmo-map-folder-list-message-locations
   ((folder elmo-shimbun-folder))
   (mapcar
    (function shimbun-header-id)
-   (shimbun-headers (elmo-shimbun-folder-shimbun-internal folder))))
+   (elmo-shimbun-folder-headers-internal folder)))
 
 (luna-define-method elmo-folder-list-subfolders ((folder elmo-shimbun-folder)
                                                 &optional one-level)
                (elmo-shimbun-folder-shimbun-internal folder))
               "."
               x))
-     (shimbun-groups-internal (elmo-shimbun-folder-shimbun-internal folder)))))
+     (shimbun-groups (elmo-shimbun-folder-shimbun-internal folder)))))
 
 (luna-define-method elmo-folder-exists-p ((folder elmo-shimbun-folder))
   (if (elmo-shimbun-folder-group-internal folder)
       (progn
        (member 
         (elmo-shimbun-folder-group-internal folder)
-        (shimbun-groups-internal (elmo-shimbun-folder-shimbun-internal
-                                  folder))))
+        (shimbun-groups (elmo-shimbun-folder-shimbun-internal
+                         folder))))
     t))
 
 (luna-define-method elmo-folder-search ((folder elmo-shimbun-folder)
 (luna-define-method elmo-folder-mark-as-read ((folder elmo-shimbun-folder)
                                              numbers)
   t)
-  
+
+(luna-define-method elmo-quit ((folder elmo-shimbun-folder))
+  (setq elmo-shimbun-headers-cache nil))
 (require 'product)
 (product-provide (provide 'elmo-shimbun) (require 'elmo-version))