Synch up with main trunk, implemented elmo-cache-folder, and so on.
authorteranisi <teranisi>
Sat, 24 Feb 2001 01:02:48 +0000 (01:02 +0000)
committerteranisi <teranisi>
Sat, 24 Feb 2001 01:02:48 +0000 (01:02 +0000)
14 files changed:
doc/wl-ja.texi
doc/wl.texi
elmo/ChangeLog
elmo/elmo-cache.el
elmo/elmo-internal.el
elmo/elmo-mark.el
elmo/elmo-msgdb.el
elmo/elmo-net.el
elmo/elmo-util.el
elmo/elmo.el
wl/ChangeLog
wl/wl-summary.el
wl/wl-util.el
wl/wl-vars.el

index 0d06ecf..3dfa134 100644 (file)
@@ -639,6 +639,7 @@ LDAP \e$B$rMxMQ$9$k>l9g$O!"\e(B@code{wl-ldap-server}\e$B!"\e(B@code{wl-ldap-port},
 
 \e$B5/F0$7$?$"$H$G%U%)%k%@0lMw$N%P%C%U%!$+$i9XFI%U%)%k%@$rDI2C\e(B/\e$BJT=8$9$k$3$H\e(B
 \e$B$b2DG=$G$9$N$G!"$3$N9`$OHt$P$7$F$b9=$$$^$;$s!#\e(B
+@xref{Folder Manager}.
 
 @file{~/.folders} \e$B$N=q$-J}$O$H$F$bC1=c$G$9!#$3$s$J$+$s$8$G$9!#\e(B
 
@@ -5727,6 +5728,7 @@ pop3                    \e$B!_\e(B    \e$B"$\e(B    \e$B"$\e(B    \e$B"$\e(B
 * mu-cite::                     mu-cite.el
 * x-face-mule::                 x-face-mule.el
 * dired-dd::                    dired-dd.el
+* MHC::                         MHC
 @end menu
 
 
@@ -5875,7 +5877,7 @@ bitmap-mule 8.0\e$B0J9_$KIUB0$N\e(B @file{x-face-mule.el}
 (\e$BJQ?t\e(B @code{wl-auto-insert-x-face} \e$B$,\e(B non-nil \e$B$N>l9g\e(B)
 
 
-@node dired-dd,  , x-face-mule, Living with other packages
+@node dired-dd, MHC, x-face-mule, Living with other packages
 @subsection dired-dd(Dired-DragDrop)
 @pindex Dired-DragDrop
 @pindex Dired-DD
@@ -5901,6 +5903,34 @@ Emacs \e$B$GJT=8Cf$NAp9F%P%C%U%!$X\e(B dired \e$B$+$i%I%i%C%0\e(B&\e$B%I%m%C%W$9$k$@$
 @end group
 @end lisp
 
+@node MHC, , dired-dd, Living with other packages
+@subsection mhc.el
+@pindex MHC
+
+Message Harmonized Calendaring system
+(@uref{http://www.quickhack.net/mhc/})
+
+MHC \e$B$rMQ$$$k$H!"%a%C%;!<%8$r85$KM=DjI=$r:n$l$^$9!#\e(B
+
+mhc-0.25 \e$B$N>l9g!'\e(B
+
+@lisp
+@group
+(setq mhc-mailer-package 'wl)
+(autoload 'mhc-mode "mhc" nil t)
+(add-hook 'wl-summary-mode-hook 'mhc-mode)
+(add-hook 'wl-folder-mode-hook 'mhc-mode)
+@end group
+@end lisp
+
+mhc-current \e$B$N>l9g!'\e(B
+
+@lisp
+@group
+(autoload 'mhc-wl-setup "mhc-wl")
+(add-hook 'wl-init-hook 'mhc-wl-setup)
+@end group
+@end lisp
 
 @node Highlights, Biff, Living with other packages, Customization
 @section \e$B%O%$%i%$%H$N@_Dj\e(B
@@ -6162,6 +6192,16 @@ face \e$B$N@_Dj$O\e(B @file{.emacs} \e$B$K=q$/$3$H$O$G$-$J$$$N$G\e(B @file{~/.wl} \e$
 @vindex wl-biff-check-interval
 \e$B=i4|@_Dj$O\e(B 40 (\e$BC10L\e(B:\e$BIC\e(B)\e$B!#\e(B
 \e$B$3$NCM$4$H$K%a!<%kCe?.$N%A%'%C%/$r9T$J$$$^$9!#\e(B
+
+@item wl-biff-notify-hook
+@vindex wl-biff-notify-hook
+\e$B=i4|@_Dj$O\e(B @code{nil}\e$B!#\e(B
+\e$B?7$7$$%a!<%k$,FO$$$?:]$K<B9T$5$l$k%U%C%/!#\e(B
+\e$BNc$($P%S!<%W2;$rLD$i$9$J$i\e(B
+@lisp
+(setq wl-biff-notify-hook '(beep))
+@end lisp
+\e$B$N$h$&$K@_Dj$7$^$9!#\e(B
 @end table
 
 
index ab5a1da..146f53e 100644 (file)
@@ -610,6 +610,7 @@ the program @command{ldapsearch}.
 
 You can skip this section because it is possible to add/edit the
 subscribe folders from the buffer for list of folders.
+@xref{Folder Manager}.
 
 Define the folders you want to subscribe in file @file{~/.folders}.  The
 contents written in @file{~/.folders} become the folders which you
@@ -5789,6 +5790,7 @@ Examples with other packages.
 * mu-cite::                     mu-cite.el
 * x-face-mule::                 x-face-mule.el
 * dired-dd::                    dired-dd.el
+* MHC::                         MHC
 @end menu
 
 
@@ -5933,7 +5935,7 @@ value of the variable @code{wl-x-face-file}), it is inserted as a
 @code{wl-auto-insert-x-face} is non-nil).
 
 
-@node dired-dd,  , x-face-mule, Living with other packages
+@node dired-dd, MHC, x-face-mule, Living with other packages
 @subsection dired-dd(Dired-DragDrop)
 @pindex Dired-DragDrop
 @pindex Dired-DD
@@ -5960,6 +5962,34 @@ specific, but general-purpose for tm/SEMI).
 @end group
 @end lisp
 
+@node MHC, , dired-dd, Living with other packages
+@subsection mhc.el
+@pindex MHC
+
+Message Harmonized Calendaring system
+(@uref{http://www.quickhack.net/mhc/})
+
+By using MHC, you can make a calendar from the messages.
+
+For mhc-0.25:
+
+@lisp
+@group
+(setq mhc-mailer-package 'wl)
+(autoload 'mhc-mode "mhc" nil t)
+(add-hook 'wl-summary-mode-hook 'mhc-mode)
+(add-hook 'wl-folder-mode-hook 'mhc-mode)
+@end group
+@end lisp
+
+For mhc-current:
+
+@lisp
+@group
+(autoload 'mhc-wl-setup "mhc-wl")
+(add-hook 'wl-init-hook 'mhc-wl-setup)
+@end group
+@end lisp
 
 @node Highlights, Biff, Living with other packages, Customization
 @section Highlights
@@ -6230,6 +6260,15 @@ If @code{nil}, wl doesn't check mail arrival.
 @vindex wl-biff-check-interval
 The initial setting is 40 (in seconds).
 Check mail arrival in this period. 
+
+@item wl-biff-notify-hook
+@vindex wl-biff-notify-hook
+The initial setting is @code{nil}.
+This is a hook run at the arrival of the new mail.
+To beep, set as:
+@lisp
+(setq wl-biff-notify-hook '(beep))
+@end lisp
 @end table
 
 
index f79f2c4..bbeff02 100644 (file)
@@ -1,3 +1,24 @@
+2001-02-23  Yuuichi Teranishi  <teranisi@gohome.org>
+
+       * elmo-util.el (toplevel): Require 'poem;
+       Some functions are moved from elmo-cache.el.
+
+       * elmo-net.el (toplevel): Require 'elmo-cache.
+
+       * elmo-msgdb.el (toplevel): Don't require 'elmo-cache.
+
+       * elmo.el (toplevel): Ditto.
+
+       * elmo-cache.el: Rewrite with luna;
+       Some functions are moved to elmo-util.el.
+
+       * elmo-internal.el (elmo-internal-folder-list): New variable.
+       (elmo-internal-folder-initialize): Rewrite.
+       (elmo-folder-list-subfolders): Ditto.
+
+       * elmo-cache.el (elmo-cache-search-all): Eliminated.
+       (elmo-cache-collect-sub-directories): Ditto.
+
 2001-02-22  Yuuichi Teranishi  <teranisi@gohome.org>
 
        * elmo-version.el (elmo-version): Up to 2.5.8.
index 1f5eb79..6ae218c 100644 (file)
 ;; 
 (require 'elmo-vars)
 (require 'elmo-util)
-
-(defsubst elmo-cache-to-msgid (filename)
-  (concat "<" (elmo-recover-string-from-filename filename) ">"))
-
-;;; File cache.
-
-(defun elmo-file-cache-get-path (msgid &optional section)
-  "Get cache path for MSGID.
-If optional argument SECTION is specified, partial cache path is returned."
-  (if (setq msgid (elmo-msgid-to-cache msgid))
-      (expand-file-name
-       (if section
-          (format "%s/%s/%s/%s/%s"
-                  elmo-msgdb-dir
-                  elmo-cache-dirname
-                  (elmo-cache-get-path-subr msgid)
-                  msgid
-                  section)
-        (format "%s/%s/%s/%s"
-                elmo-msgdb-dir
-                elmo-cache-dirname
-                (elmo-cache-get-path-subr msgid)
-                msgid)))))
-
-(defmacro elmo-file-cache-expand-path (path section)
-  "Return file name for the file-cache corresponds to the section.
-PATH is the file-cache path.
-SECTION is the section string."
-  (` (expand-file-name (or (, section) "") (, path))))
-
-(defun elmo-file-cache-delete (path)
-  "Delete a cache on PATH."
-  (let (files)
-    (when (file-exists-p path)
-      (if (file-directory-p path)
-         (progn
-           (setq files (directory-files path t "^[^\\.]"))
-           (while files
-             (delete-file (car files))
-             (setq files (cdr files)))
-           (delete-directory path))
-       (delete-file path)))))
-
-(defun elmo-file-cache-exists-p (msgid)
-  "Returns 'section or 'entire if a cache which corresponds to MSGID exists."
-  (elmo-file-cache-status (elmo-file-cache-get msgid)))
-
-(defun elmo-file-cache-save (cache-path section)
-  "Save current buffer as cache on PATH."
-  (let ((path (if section (expand-file-name section cache-path) cache-path))
-       files dir)
-    (if (and (null section)
-            (file-directory-p path))
-       (progn
-         (setq files (directory-files path t "^[^\\.]"))
-         (while files
-           (delete-file (car files))
-           (setq files (cdr files)))
-         (delete-directory path))
-      (if (and section
-              (not (file-directory-p cache-path)))
-         (delete-file cache-path)))
-    (when path
-      (setq dir (directory-file-name (file-name-directory path)))
-      (if (not (file-exists-p dir))
-         (elmo-make-directory dir))
-      (write-region-as-binary (point-min) (point-max)
-                             path nil 'no-msg))))
-
-(defmacro elmo-make-file-cache (path status)
-  "PATH is the cache file name.
-STATUS is one of 'section, 'entire or nil.
- nil means no cache exists.
-'section means partial section cache exists.
-'entire means entire cache exists.
-If the cache is partial file-cache, TYPE is 'partial."
-  (` (cons (, path) (, status))))
-
-(defmacro elmo-file-cache-path (file-cache)
-  "Returns the file path of the FILE-CACHE."
-  (` (car (, file-cache))))
-
-(defmacro elmo-file-cache-status (file-cache)
-  "Returns the status of the FILE-CACHE."
-  (` (cdr (, file-cache))))
-
-(defun elmo-file-cache-get (msgid &optional section)
-  "Returns the current file-cache object associated with MSGID.
-MSGID is the message-id of the message.
-If optional argument SECTION is specified, get partial file-cache object
-associated with SECTION."
-  (if msgid
-      (let ((path (elmo-cache-get-path msgid)))
-       (if (and path (file-exists-p path))
-           (if (file-directory-p path)
-               (if section
-                   (if (file-exists-p (setq path (expand-file-name
-                                                  section path)))
-                       (cons path 'section))
-                 ;; section is not specified but sectional.
-                 (cons path 'section))
-             ;; not directory.
-             (unless section
-               (cons path 'entire)))
-         ;; no cache.
-         (cons path nil)))))
-
-;;;
-(defun elmo-cache-expire ()
-  (interactive)
-  (let* ((completion-ignore-case t)
-        (method (completing-read (format "Expire by (%s): "
-                                         elmo-cache-expire-default-method)
-                                 '(("size" . "size")
-                                   ("age" . "age")))))
-    (if (string= method "")
-       (setq method elmo-cache-expire-default-method))
-    (funcall (intern (concat "elmo-cache-expire-by-" method)))))
-
-(defun elmo-read-float-value-from-minibuffer (prompt &optional initial)
-  (let ((str (read-from-minibuffer prompt initial)))
-    (cond
-     ((string-match "[0-9]*\\.[0-9]+" str)
-      (string-to-number str))
-     ((string-match "[0-9]+" str)
-      (string-to-number (concat str ".0")))
-     (t (error "%s is not number" str)))))
-
-(defun elmo-cache-expire-by-size (&optional kbytes)
-  "Expire cache file by size.
-If KBYTES is kilo bytes (This value must be float)."
-  (interactive)
-  (let ((size (or kbytes
-                 (and (interactive-p)
-                      (elmo-read-float-value-from-minibuffer
-                       "Enter cache disk size (Kbytes): "
-                       (number-to-string
-                        (if (integerp elmo-cache-expire-default-size)
-                            (float elmo-cache-expire-default-size)
-                          elmo-cache-expire-default-size))))
-                 (if (integerp elmo-cache-expire-default-size)
-                     (float elmo-cache-expire-default-size))))
-       (locked (elmo-dop-lock-list-load))
-       (count 0)
-       (Kbytes 1024)
-       total beginning)
-    (message "Checking disk usage...")
-    (setq total (/ (elmo-disk-usage
-                   (expand-file-name
-                    elmo-cache-dirname elmo-msgdb-dir)) Kbytes))
-    (setq beginning total)
-    (message "Checking disk usage...done")
-    (let ((cfl (elmo-cache-get-sorted-cache-file-list))
-         (deleted 0)
-         oldest
-         cur-size cur-file)
-      (while (and (<= size total)
-                 (setq oldest (elmo-cache-get-oldest-cache-file-entity cfl)))
-       (setq cur-file (expand-file-name (car (cdr oldest)) (car oldest)))
-       (setq cur-size (/ (elmo-disk-usage cur-file) Kbytes))
-       (when (elmo-cache-force-delete cur-file locked)
-         (setq count (+ count 1))
-         (message "%d cache(s) are expired." count))
-       (setq deleted (+ deleted cur-size))
-       (setq total (- total cur-size)))
-      (message "%d cache(s) are expired from disk (%d Kbytes/%d Kbytes)."
-              count deleted beginning))))
-
-(defun elmo-cache-make-file-entity (filename path)
-  (cons filename (elmo-get-last-accessed-time filename path)))
-
-(defun elmo-cache-get-oldest-cache-file-entity (cache-file-list)
-  (let ((cfl cache-file-list)
-       flist firsts oldest-entity wonlist)
-    (while cfl
-      (setq flist (cdr (car cfl)))
-      (setq firsts (append firsts (list
-                                  (cons (car (car cfl))
-                                        (car flist)))))
-      (setq cfl (cdr cfl)))
-;;; (prin1 firsts)
-    (while firsts
-      (if (and (not oldest-entity)
-              (cdr (cdr (car firsts))))
-         (setq oldest-entity (car firsts)))
-      (if (and (cdr (cdr (car firsts)))
-              (cdr (cdr oldest-entity))
-              (> (cdr (cdr oldest-entity)) (cdr (cdr (car firsts)))))
-         (setq oldest-entity (car firsts)))
-      (setq firsts (cdr firsts)))
-    (setq wonlist (assoc (car oldest-entity) cache-file-list))
-    (and wonlist
-        (setcdr wonlist (delete (car (cdr wonlist)) (cdr wonlist))))
-    oldest-entity))
-
-(defun elmo-cache-get-sorted-cache-file-list ()
-  (let ((dirs (directory-files
-              (expand-file-name elmo-cache-dirname elmo-msgdb-dir)
-              t "^[^\\.]"))
-       (i 0) num
-       elist
-       ret-val)
-    (setq num (length dirs))
-    (message "Collecting cache info...")
-    (while dirs
-      (setq elist (mapcar (lambda (x)
-                           (elmo-cache-make-file-entity x (car dirs)))
-                         (directory-files (car dirs) nil "^[^\\.]")))
-      (setq ret-val (append ret-val
-                           (list (cons
-                                  (car dirs)
-                                  (sort
-                                   elist
-                                   (lambda (x y)
-                                     (< (cdr x)
-                                        (cdr y))))))))
-      (when (> num elmo-display-progress-threshold)
-       (setq i (+ i 1))
-       (elmo-display-progress
-        'elmo-cache-get-sorted-cache-file-list "Collecting cache info..."
-        (/ (* i 100) num)))
-      (setq dirs (cdr dirs)))
-    (message "Collecting cache info...done")
-    ret-val))
-
-(defun elmo-cache-expire-by-age (&optional days)
-  (let ((age (or (and days (int-to-string days))
-                (and (interactive-p)
-                     (read-from-minibuffer
-                      (format "Enter days (%s): "
-                              elmo-cache-expire-default-age)))
-                (int-to-string elmo-cache-expire-default-age)))
-       (dirs (directory-files
-              (expand-file-name elmo-cache-dirname elmo-msgdb-dir)
-              t "^[^\\.]"))
-       (locked (elmo-dop-lock-list-load))
-       (count 0)
-       curtime)
-    (if (string= age "")
-       (setq age elmo-cache-expire-default-age)
-      (setq age (string-to-int age)))
-    (setq curtime (current-time))
-    (setq curtime (+ (* (nth 0 curtime)
-                       (float 65536)) (nth 1 curtime)))
-    (while dirs
-      (let ((files (directory-files (car dirs) t "^[^\\.]"))
-           (limit-age (* age 86400)))
-       (while files
-         (when (> (- curtime (elmo-get-last-accessed-time (car files)))
-                  limit-age)
-           (when (elmo-cache-force-delete (car files) locked)
-             (setq count (+ 1 count))
-             (message "%d cache file(s) are expired." count)))
-         (setq files (cdr files))))
-      (setq dirs (cdr dirs)))))
-
-(defun elmo-cache-search-all (folder condition from-msgs)
-  (let* ((number-alist (elmo-msgdb-number-load
-                       (elmo-msgdb-expand-path folder)))
-        (number-list (or from-msgs (mapcar 'car number-alist)))
-        (num (length number-alist))
-        cache-file
-        ret-val
-        case-fold-search msg
-        percent i)
-    (setq i 0)
-    (while number-alist
-      (if (and (memq (car (car number-alist)) number-list)
-              (setq cache-file (elmo-cache-exists-p (cdr (car
-                                                          number-alist))
-                                                    folder
-                                                    (car (car
-                                                          number-alist))))
-              (elmo-file-field-condition-match cache-file condition
-                                               (car (car number-alist))
-                                               number-list))
-         (setq ret-val (append ret-val (list (caar number-alist)))))
-      (when (> num elmo-display-progress-threshold)
-       (setq i (1+ i))
-       (setq percent (/ (* i 100) num))
-       (elmo-display-progress
-        'elmo-cache-search-all "Searching..."
-        percent))
-      (setq number-alist (cdr number-alist)))
-    ret-val))
-
-(defun elmo-cache-collect-sub-directories (init dir &optional recursively)
-  "Collect subdirectories under DIR."
-  (let ((dirs
-        (delete (expand-file-name elmo-cache-dirname
-                                  elmo-msgdb-dir)
-                (directory-files dir t "^[^\\.]")))
-       ret-val)
-    (setq dirs (elmo-delete-if (lambda (x) (not (file-directory-p x))) dirs))
-    (setq ret-val (append init dirs))
-    (while (and recursively dirs)
-      (setq ret-val
-           (elmo-cache-collect-sub-directories
-            ret-val
-            (car dirs) recursively))
-      (setq dirs (cdr dirs)))
-    ret-val))
-
-(defun elmo-msgid-to-cache (msgid)
-  (when (and msgid
-            (string-match "<\\(.+\\)>$" msgid))
-    (elmo-replace-string-as-filename (elmo-match-string 1 msgid))))
-
-(defun elmo-cache-get-path (msgid &optional folder number)
-  "Get path for cache file associated with MSGID, FOLDER, and NUMBER."
-  (if (setq msgid (elmo-msgid-to-cache msgid))
-      (expand-file-name
-       (expand-file-name
-       (if folder
-           (format "%s/%s/%s@%s"
-                   (elmo-cache-get-path-subr msgid)
-                   msgid
-                   (or number "")
-                   (elmo-safe-filename folder))
-         (format "%s/%s"
-                 (elmo-cache-get-path-subr msgid)
-                 msgid))
-       (expand-file-name elmo-cache-dirname
-                         elmo-msgdb-dir)))))
-
-(defsubst elmo-cache-get-path-subr (msgid)
-  (let ((chars '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?A ?B ?C ?D ?E ?F))
-       (clist (string-to-char-list msgid))
-       (sum 0))
-    (while clist
-      (setq sum (+ sum (car clist)))
-      (setq clist (cdr clist)))
-    (format "%c%c"
-           (nth (% (/ sum 16) 2) chars)
-           (nth (% sum 16) chars))))
-  
+(require 'elmo)
+(require 'elmo-map)
+(require 'elmo-dop)
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; 
-;;
 ;; cache backend by Kenichi OKADA <okada@opaopa.org>
 ;;
+(eval-and-compile
+  (luna-define-class elmo-cache-folder (elmo-map-folder) (dir-name directory))
+  (luna-define-internal-accessors 'elmo-cache-folder))
+
+(luna-define-method elmo-folder-initialize ((folder elmo-cache-folder)
+                                           name)
+  (when (string-match "\\([^/]*\\)/?\\(.*\\)$" name)
+    (elmo-cache-folder-set-dir-name-internal
+     folder
+     (elmo-match-string 2 name))
+    (elmo-cache-folder-set-directory-internal
+     folder
+     (expand-file-name (elmo-match-string 2 name)
+                      (expand-file-name elmo-cache-dirname elmo-msgdb-dir)))
+    folder))
+
+(luna-define-method elmo-folder-expand-msgdb-path ((folder elmo-cache-folder))
+  (expand-file-name (elmo-cache-folder-dir-name-internal folder)
+                   (expand-file-name "internal/cache"
+                                     elmo-msgdb-dir)))
+
+(luna-define-method elmo-map-folder-list-message-locations
+  ((folder elmo-cache-folder))
+  (elmo-cache-folder-list-message-locations folder))
+
+(defun elmo-cache-folder-list-message-locations (folder)
+  (mapcar 'file-name-nondirectory
+         (elmo-delete-if
+          'file-directory-p
+          (directory-files (elmo-cache-folder-directory-internal folder)
+                           t "^[^@]+@[^@]+$" t))))
+
+(luna-define-method elmo-folder-list-subfolders ((folder elmo-cache-folder)
+                                                &optional one-level)
+  (delq nil (mapcar
+            (lambda (f) (if (file-directory-p f)
+                            (concat (elmo-folder-prefix-internal folder)
+                                    "cache/"
+                                    (file-name-nondirectory f))))
+            (directory-files (elmo-cache-folder-directory-internal folder)
+                             t "^[^.].*+"))))
+
+(luna-define-method elmo-folder-message-file-p ((folder elmo-cache-folder))
+  t)
 
-(defsubst elmo-cache-get-folder-directory (spec)
-  (if (file-name-absolute-p (nth 1 spec))
-      (nth 1 spec) ; already full path.
-    (expand-file-name (nth 1 spec)
-                     (expand-file-name elmo-cache-dirname elmo-msgdb-dir))))
-
-(defun elmo-cache-msgdb-expand-path (spec)
-  (let ((fld-name (nth 1 spec)))
-    (expand-file-name fld-name
-                     (expand-file-name "internal/cache"
-                                       elmo-msgdb-dir))))
-
-(defun elmo-cache-number-to-filename (spec number)
-  (let ((number-alist
-        (elmo-cache-list-folder-subr spec nil t)))
-    (elmo-msgid-to-cache
-     (cdr (assq number number-alist)))))
-
-(defsubst elmo-cache-msgdb-create-overview-entity-from-file (number file)
-  (save-excursion
-    (let ((tmp-buffer (get-buffer-create " *ELMO Cache Temp*"))
-         insert-file-contents-pre-hook   ; To avoid autoconv-xmas...
-         insert-file-contents-post-hook header-end
-         (attrib (file-attributes file))
-         ret-val size mtime)
-      (set-buffer tmp-buffer)
-      (erase-buffer)
-      (if (not (file-exists-p file))
+(luna-define-method elmo-message-file-name ((folder elmo-cache-folder)
+                                           number)
+  (expand-file-name
+   (elmo-map-message-location folder number)
+   (elmo-cache-folder-directory-internal folder)))
+
+(luna-define-method elmo-folder-msgdb-create ((folder elmo-cache-folder)
+                                             numbers new-mark
+                                             already-mark seen-mark
+                                             important-mark
+                                             seen-list)
+  (let ((i 0)
+       (len (length numbers))
+       overview number-alist mark-alist entity message-id
+       num mark)
+    (message "Creating msgdb...")
+    (while numbers
+      (setq entity
+           (elmo-msgdb-create-overview-entity-from-file
+            (car numbers) (elmo-message-file-name folder (car numbers))))
+      (if (null entity)
          ()
-       (setq size (nth 7 attrib))
-       (setq mtime (timezone-make-date-arpa-standard
-                    (current-time-string (nth 5 attrib)) (current-time-zone)))
-       ;; insert header from file.
-       (catch 'done
-         (condition-case nil
-             (elmo-msgdb-insert-file-header file)
-           (error (throw 'done nil)))
-         (goto-char (point-min))
-         (setq header-end
-               (if (re-search-forward "\\(^--.*$\\)\\|\\(\n\n\\)" nil t)
-                   (point)
-                 (point-max)))
-         (narrow-to-region (point-min) header-end)
-         (setq ret-val (elmo-msgdb-create-overview-from-buffer number size mtime))
-         (kill-buffer tmp-buffer))
-       ret-val))))
-
-(defun elmo-cache-msgdb-create-as-numlist (spec numlist new-mark
-                                                  already-mark seen-mark
-                                                  important-mark seen-list)
-  (when numlist
-    (let ((dir (elmo-cache-get-folder-directory spec))
-         (nalist (elmo-cache-list-folder-subr spec nil t))
-         overview number-alist mark-alist entity message-id
-         i percent len num seen gmark)
-      (setq len (length numlist))
-      (setq i 0)
-      (message "Creating msgdb...")
-      (while numlist
-       (setq entity
-             (elmo-cache-msgdb-create-overview-entity-from-file
-              (car numlist)
-              (expand-file-name
-               (elmo-msgid-to-cache
-                (setq message-id (cdr (assq (car numlist) nalist)))) dir)))
-       (if (null entity)
-           ()
-         (setq num (elmo-msgdb-overview-entity-get-number entity))
-         (setq overview
-               (elmo-msgdb-append-element
-                overview entity))
-         (setq number-alist
-               (elmo-msgdb-number-add number-alist num message-id))
-         (setq seen (member message-id seen-list))
-         (if (setq gmark (or (elmo-msgdb-global-mark-get message-id)
-                             (if seen
-                                 nil
-                               new-mark)))
-             (setq mark-alist
-                   (elmo-msgdb-mark-append
-                    mark-alist
-                    num
-                    gmark))))
+       (setq num (elmo-msgdb-overview-entity-get-number entity))
+       (setq overview
+             (elmo-msgdb-append-element
+              overview entity))
+       (setq message-id (elmo-msgdb-overview-entity-get-id entity))
+       (setq number-alist
+             (elmo-msgdb-number-add number-alist
+                                    num
+                                    message-id))
+       (if (setq mark (or (elmo-msgdb-global-mark-get message-id)
+                          (if (member message-id seen-list) nil new-mark)))
+           (setq mark-alist
+                 (elmo-msgdb-mark-append
+                  mark-alist
+                  num mark)))
        (when (> len elmo-display-progress-threshold)
          (setq i (1+ i))
-         (setq percent (/ (* i 100) len))
          (elmo-display-progress
-          'elmo-cache-msgdb-create-as-numlist "Creating msgdb..."
-          percent))
-       (setq numlist (cdr numlist)))
-      (message "Creating msgdb...done")
-      (list overview number-alist mark-alist))))
-
-(defalias 'elmo-cache-msgdb-create 'elmo-cache-msgdb-create-as-numlist)
-
-(defun elmo-cache-list-folders (spec &optional hierarchy)
-  (let ((folder (concat "'cache" (nth 1 spec))))
-    (elmo-cache-list-folders-subr folder hierarchy)))
-
-(defun elmo-cache-list-folders-subr (folder &optional hierarchy)
-  (let ((case-fold-search t)
-       folders curdir dirent relpath abspath attr
-       subprefix subfolder)
-    (condition-case ()
-       (progn
-         (setq curdir
-               (expand-file-name
-                (nth 1 (elmo-folder-get-spec folder))
-                (expand-file-name elmo-cache-dirname elmo-msgdb-dir)))
-         (if (string-match "^[+=$!]$" folder) ; localdir, archive, localnews
-             (setq subprefix folder)
-           (setq subprefix (concat folder elmo-path-sep)))
-           ;; include parent
-           ;(setq folders (list folder)))
-         (setq dirent (directory-files curdir nil "^[01][0-9A-F]$"))
-         (catch 'done
-          (while dirent
-           (setq relpath (car dirent))
-           (setq dirent (cdr dirent))
-           (setq abspath (expand-file-name relpath curdir))
-           (and
-            (eq (nth 0 (setq attr (file-attributes abspath))) t)
-            (setq subfolder (concat subprefix relpath))
-            (setq folders (nconc folders (list subfolder))))))
-         folders)
-      (file-error folders))))
-
-(defsubst elmo-cache-list-folder-subr (spec &optional nonsort nonalist)
-  (let* ((dir (elmo-cache-get-folder-directory spec))
-        (flist (mapcar 'file-name-nondirectory
-                       (elmo-delete-if 'file-directory-p
-                                       (directory-files
-                                        dir t "^[^@]+@[^@]+$" t))))
-        (folder (concat "'cache/" (nth 1 spec)))
-        (number-alist (or (elmo-msgdb-number-load
-                           (elmo-msgdb-expand-path folder))
-                          (list nil)))
-        nlist)
-    (setq nlist
-         (mapcar '(lambda (filename)
-                    (elmo-cache-filename-to-number filename number-alist))
-                 flist))
-    (if nonalist
-       number-alist
-      (if nonsort
-         (cons (or (elmo-max-of-list nlist) 0) (length nlist))
-       (sort nlist '<)))))
-
-(defsubst elmo-cache-filename-to-number (filename number-alist)
-  (let* ((msgid (elmo-cache-to-msgid filename))
-        number)
-    (or (car (rassoc msgid number-alist))
-       (prog1
-           (setq number (+ (or (caar (last number-alist))
-                               0) 1))
-         (if (car number-alist)
-             (nconc number-alist
-                    (list (cons number msgid)))
-           (setcar number-alist (cons number msgid)))))))
-
-(defun elmo-cache-append-msg (spec string message-id &optional msg no-see)
-  (let ((dir (elmo-cache-get-folder-directory spec))
-       (tmp-buffer (get-buffer-create " *ELMO Temp buffer*"))
-       filename)
-    (save-excursion
-      (set-buffer tmp-buffer)
-      (erase-buffer)
-      (setq filename (expand-file-name (elmo-msgid-to-cache message-id) dir))
-      (unwind-protect
-         (if (file-writable-p filename)
-             (progn
-               (insert string)
-               (as-binary-output-file
-                (write-region (point-min) (point-max) filename nil 'no-msg))
-               t)
-           nil)
-       (kill-buffer tmp-buffer)))))
-
-(defun elmo-cache-delete-msg (spec number locked)
-  (let* ((dir (elmo-cache-get-folder-directory spec))
-        (file (expand-file-name
-               (elmo-cache-number-to-filename spec number) dir)))
-    ;; return nil if failed.
-    (elmo-cache-force-delete file locked)))
-
-(defun elmo-cache-read-msg (spec number outbuf &optional set-mark)
-  (save-excursion
-    (let* ((dir (elmo-cache-get-folder-directory spec))
-          (file (expand-file-name
-                 (elmo-cache-number-to-filename spec number) dir)))
-      (set-buffer outbuf)
-      (erase-buffer)
-      (when (file-exists-p file)
-       (as-binary-input-file (insert-file-contents file))
-       (elmo-delete-cr-get-content-type)))))
-
-(defun elmo-cache-delete-msgs (spec msgs)
-  (let ((locked (elmo-dop-lock-list-load)))
-    (not (memq nil
-              (mapcar '(lambda (msg) (elmo-cache-delete-msg spec msg locked))
-                      msgs)))))
-
-(defun elmo-cache-list-folder (spec)   ; called by elmo-cache-search()
-  (let ((killed (and elmo-use-killed-list
-                    (elmo-msgdb-killed-list-load
-                     (elmo-msgdb-expand-path spec))))
-       numbers)
-    (setq numbers (elmo-cache-list-folder-subr spec))
-    (elmo-living-messages numbers killed)))
-
-(defun elmo-cache-max-of-folder (spec)
-  (elmo-cache-list-folder-subr spec t))
-
-(defun elmo-cache-check-validity (spec validity-file)
-  t)
-
-(defun elmo-cache-sync-validity (spec validity-file)
+          'elmo-cache-folder-msgdb-create "Creating msgdb..."
+          (/ (* i 100) len))))
+      (setq numbers (cdr numbers)))
+    (message "Creating msgdb...done")
+    (list overview number-alist mark-alist)))
+
+(luna-define-method elmo-folder-append-buffer ((folder elmo-cache-folder)
+                                              unread
+                                              &optional number)
+  ;; dir-name is changed according to msgid.
+  (unless (elmo-cache-folder-dir-name-internal folder)
+    (let* ((file (elmo-file-cache-get-path (std11-field-body "message-id")))
+          (dir (directory-file-name (file-name-directory file))))
+      (unless (file-exists-p dir)
+       (elmo-make-directory dir))
+      (when (file-writable-p file)
+       (write-region-as-binary
+        (point-min) (point-max) file nil 'no-msg))))
   t)
 
-(defun elmo-cache-folder-exists-p (spec)
-  (file-directory-p (elmo-cache-get-folder-directory spec)))
-
-(defun elmo-cache-folder-creatable-p (spec)
+(luna-define-method elmo-map-folder-delete-messages ((folder elmo-cache-folder)
+                                                    locations)
+  (dolist (location locations)
+    (elmo-file-cache-delete
+     (expand-file-name location
+                      (elmo-cache-folder-directory-internal folder)))))
+
+(defsubst elmo-cache-folder-map-message-fetch (folder location strategy
+                                                     section outbuf unseen)
+  (let ((file (expand-file-name
+              location
+              (elmo-cache-folder-directory-internal folder))))
+    (when (file-exists-p file)
+      (if outbuf
+         (with-current-buffer outbuf
+           (erase-buffer)
+           (insert-file-contents-as-binary file)
+           (elmo-delete-cr-buffer)
+           t)
+       (with-temp-buffer
+         (insert-file-contents-as-binary file)
+         (elmo-delete-cr-buffer)
+         (buffer-string))))))
+
+(luna-define-method elmo-map-message-fetch ((folder elmo-cache-folder)
+                                           location strategy &optional
+                                           section outbuf unseen)
+  (elmo-cache-folder-map-message-fetch folder location strategy
+                                      section outbuf unseen))
+
+(luna-define-method elmo-folder-creatable-p ((folder elmo-cache-folder))
   nil)
 
-(defun elmo-cache-create-folder (spec)
-  nil)
+(luna-define-method elmo-folder-exists-p ((folder elmo-cache-folder))
+  t)
 
-(defun elmo-cache-search (spec condition &optional from-msgs)
-  (let* ((number-alist (elmo-cache-list-folder-subr spec nil t))
-        (msgs (or from-msgs (mapcar 'car number-alist)))
+(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))
-        (i 0) case-fold-search ret-val)
+        file
+        matched
+        case-fold-search)
     (while msgs
-      (if (elmo-file-field-condition-match
-          (expand-file-name
-           (elmo-msgid-to-cache
-            (cdr (assq (car msgs) number-alist)))
-           (elmo-cache-get-folder-directory spec))
-          condition
-          (car msgs)
-          msgs)
-         (setq ret-val (cons (car msgs) ret-val)))
-      (when (> num elmo-display-progress-threshold)
-       (setq i (1+ i))
-       (elmo-display-progress
-        'elmo-cache-search "Searching..."
-        (/ (* i 100) num)))
+      (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)))
-    (nreverse ret-val)))
+    matched))
 
-;;; (localdir, maildir, localnews) -> cache
-(defun elmo-cache-copy-msgs (dst-spec msgs src-spec
-                                     &optional loc-alist same-number)
-  (let ((dst-dir
-        (elmo-cache-get-folder-directory dst-spec))
-       (next-num (1+ (car (elmo-cache-list-folder-subr dst-spec t))))
-       (number-alist
-        (elmo-msgdb-number-load
-         (elmo-msgdb-expand-path src-spec))))
-    (if same-number (error "Not implemented"))
-    (while msgs
-      (elmo-copy-file
-       ;; src file
-       (elmo-call-func src-spec "get-msg-filename" (car msgs) loc-alist)
-       ;; dst file
-       (expand-file-name
-       (elmo-msgid-to-cache
-        (cdr (assq (if same-number (car msgs) next-num) number-alist)))
-       dst-dir))
-      (if (and (setq msgs (cdr msgs))
-              (not same-number))
-         (setq next-num (1+ next-num))))
-    t))
+(luna-define-method elmo-message-file-p ((folder elmo-cache-folder) number)
+  t)
 
-(defun elmo-cache-use-cache-p (spec number)
-  nil)
+;;; To override elmo-map-folder methods.
+(luna-define-method elmo-folder-list-unreads-internal
+  ((folder elmo-cache-folder) unread-marks &optional mark-alist)
+  t)
 
-(defun elmo-cache-local-file-p (spec number)
+(luna-define-method elmo-folder-list-importants-internal
+  ((folder elmo-cache-folder) important-mark)
   t)
 
-(defun elmo-cache-get-msg-filename (spec number &optional loc-alist)
-  (expand-file-name
-   (elmo-cache-number-to-filename spec number)
-   (elmo-cache-get-folder-directory spec)))
+(luna-define-method elmo-folder-unmark-important ((folder elmo-cache-folder)
+                                                 numbers)
+  t)
+
+(luna-define-method elmo-folder-mark-as-important ((folder elmo-cache-folder)
+                                                  numbers)
+  t)
 
-(defalias 'elmo-cache-sync-number-alist
-  'elmo-generic-sync-number-alist)
-(defalias 'elmo-cache-list-folder-unread
-  'elmo-generic-list-folder-unread)
-(defalias 'elmo-cache-list-folder-important
-  'elmo-generic-list-folder-important)
-(defalias 'elmo-cache-commit 'elmo-generic-commit)
-(defalias 'elmo-cache-folder-diff 'elmo-generic-folder-diff)
+(luna-define-method elmo-folder-unmark-read ((folder elmo-cache-folder)
+                                            numbers)
+  t)
+
+(luna-define-method elmo-folder-mark-as-read ((folder elmo-cache-folder)
+                                             numbers)
+  t)
 
 (require 'product)
 (product-provide (provide 'elmo-cache) (require 'elmo-version))
index b9de021..9db3b9a 100644 (file)
                                            name)
   (elmo-internal-folder-initialize folder name))
 
+(defvar elmo-internal-folder-list '(mark cache))
+
 (defun elmo-internal-folder-initialize (folder name)
-  (cond ((string-match "^mark" name)
-        (require 'elmo-mark)
-        (elmo-folder-initialize
-         (luna-make-entity
-          'elmo-mark-folder
-          :type 'mark
-          :prefix (elmo-folder-prefix-internal folder)
-          :name (elmo-folder-name-internal folder)
-          :persistent (elmo-folder-persistent-internal folder))
-         name))
-       ((string-match "^cache" name)
-        (require 'elmo-cache)
-        ;; XXX FIXME: elmo-cache-folder initialization
-        folder)
-       (t folder)))
+  (let ((fsyms elmo-internal-folder-list)
+       fname class sym)
+    (if (progn (while fsyms
+                (setq fname (symbol-name (car fsyms)))
+                (when (string-match (concat "^" fname) name)
+                  (require (intern (concat "elmo-" fname)))
+                  (setq class (intern (concat "elmo-" fname "-folder"))
+                        sym (intern fname)
+                        fsyms nil))
+                (setq fsyms (cdr fsyms)))
+              class)
+       (elmo-folder-initialize
+        (luna-make-entity
+         class
+         :type sym
+         :prefix (elmo-folder-prefix-internal folder)
+         :name (elmo-folder-name-internal folder)
+         :persistent (elmo-folder-persistent-internal folder))
+        name)
+      folder)))
 
 (luna-define-method elmo-folder-list-subfolders ((folder elmo-internal-folder)
                                                 &optional one-level)
-  (list (list "'cache") "'mark"))
+  (mapcar
+   (lambda (x)
+     (list (concat (elmo-folder-prefix-internal folder)
+                  (symbol-name x))))
+   elmo-internal-folder-list))
 
 (require 'product)
 (product-provide (provide 'elmo-internal) (require 'elmo-version))
index 5d569bb..eef8c3f 100644 (file)
         dir)
     (when path
       (setq dir (directory-file-name (file-name-directory path)))
-      (if (not (file-exists-p dir))
-         (elmo-make-directory dir))
-      (as-binary-output-file (write-region (point-min) (point-max)
-                                          path nil 'no-msg)))
+      (unless (file-exists-p dir)
+       (elmo-make-directory dir))
+      (when (file-writable-p path)
+       (write-region-as-binary (point-min) (point-max)
+                               path nil 'no-msg)))
     (elmo-msgdb-global-mark-set msgid 
                                (elmo-mark-folder-mark-internal folder))))
 
         file
         matched
         case-fold-search)
-    (setq num (length msgs))
     (while msgs
       (if (and (setq file (elmo-message-file-name folder (car msgs)))
               (file-exists-p file)
index 3ef50ce..04f9df4 100644 (file)
@@ -36,7 +36,6 @@
 (require 'elmo-util)
 (require 'emu)
 (require 'std11)
-(require 'elmo-cache)
 
 (defsubst elmo-msgdb-append-element (list element)
   (if list
index 6e49166..9df58e1 100644 (file)
@@ -31,6 +31,7 @@
 (require 'elmo-util)
 (require 'elmo-dop)
 (require 'elmo-vars)
+(require 'elmo-cache)
 (require 'elmo)
 
 ;;; Code:
index a3d97c4..24ee64f 100644 (file)
@@ -35,6 +35,7 @@
 (require 'std11)
 (require 'eword-decode)
 (require 'utf7)
+(require 'poem)
 
 (defmacro elmo-set-buffer-multibyte (flag)
   "Set the multibyte flag of the current buffer to FLAG."
@@ -1362,6 +1363,298 @@ NUMBER-SET is altered."
                                   (match-end matchn)) list)))
     (nreverse list)))
 
+;;; File cache.
+(defsubst elmo-cache-to-msgid (filename)
+  (concat "<" (elmo-recover-string-from-filename filename) ">"))
+
+(defsubst elmo-cache-get-path-subr (msgid)
+  (let ((chars '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?A ?B ?C ?D ?E ?F))
+       (clist (string-to-char-list msgid))
+       (sum 0))
+    (while clist
+      (setq sum (+ sum (car clist)))
+      (setq clist (cdr clist)))
+    (format "%c%c"
+           (nth (% (/ sum 16) 2) chars)
+           (nth (% sum 16) chars))))
+
+(defun elmo-file-cache-get-path (msgid &optional section)
+  "Get cache path for MSGID.
+If optional argument SECTION is specified, partial cache path is returned."
+  (if (setq msgid (elmo-msgid-to-cache msgid))
+      (expand-file-name
+       (if section
+          (format "%s/%s/%s/%s/%s"
+                  elmo-msgdb-dir
+                  elmo-cache-dirname
+                  (elmo-cache-get-path-subr msgid)
+                  msgid
+                  section)
+        (format "%s/%s/%s/%s"
+                elmo-msgdb-dir
+                elmo-cache-dirname
+                (elmo-cache-get-path-subr msgid)
+                msgid)))))
+
+(defmacro elmo-file-cache-expand-path (path section)
+  "Return file name for the file-cache corresponds to the section.
+PATH is the file-cache path.
+SECTION is the section string."
+  (` (expand-file-name (or (, section) "") (, path))))
+
+(defun elmo-file-cache-delete (path)
+  "Delete a cache on PATH."
+  (let (files)
+    (when (file-exists-p path)
+      (if (file-directory-p path)
+         (progn
+           (setq files (directory-files path t "^[^\\.]"))
+           (while files
+             (delete-file (car files))
+             (setq files (cdr files)))
+           (delete-directory path))
+       (delete-file path)))))
+
+(defun elmo-file-cache-exists-p (msgid)
+  "Returns 'section or 'entire if a cache which corresponds to MSGID exists."
+  (elmo-file-cache-status (elmo-file-cache-get msgid)))
+
+(defun elmo-file-cache-save (cache-path section)
+  "Save current buffer as cache on PATH."
+  (let ((path (if section (expand-file-name section cache-path) cache-path))
+       files dir)
+    (if (and (null section)
+            (file-directory-p path))
+       (progn
+         (setq files (directory-files path t "^[^\\.]"))
+         (while files
+           (delete-file (car files))
+           (setq files (cdr files)))
+         (delete-directory path))
+      (if (and section
+              (not (file-directory-p cache-path)))
+         (delete-file cache-path)))
+    (when path
+      (setq dir (directory-file-name (file-name-directory path)))
+      (if (not (file-exists-p dir))
+         (elmo-make-directory dir))
+      (write-region-as-binary (point-min) (point-max)
+                             path nil 'no-msg))))
+
+(defmacro elmo-make-file-cache (path status)
+  "PATH is the cache file name.
+STATUS is one of 'section, 'entire or nil.
+ nil means no cache exists.
+'section means partial section cache exists.
+'entire means entire cache exists.
+If the cache is partial file-cache, TYPE is 'partial."
+  (` (cons (, path) (, status))))
+
+(defmacro elmo-file-cache-path (file-cache)
+  "Returns the file path of the FILE-CACHE."
+  (` (car (, file-cache))))
+
+(defmacro elmo-file-cache-status (file-cache)
+  "Returns the status of the FILE-CACHE."
+  (` (cdr (, file-cache))))
+
+(defun elmo-file-cache-get (msgid &optional section)
+  "Returns the current file-cache object associated with MSGID.
+MSGID is the message-id of the message.
+If optional argument SECTION is specified, get partial file-cache object
+associated with SECTION."
+  (if msgid
+      (let ((path (elmo-cache-get-path msgid)))
+       (if (and path (file-exists-p path))
+           (if (file-directory-p path)
+               (if section
+                   (if (file-exists-p (setq path (expand-file-name
+                                                  section path)))
+                       (cons path 'section))
+                 ;; section is not specified but sectional.
+                 (cons path 'section))
+             ;; not directory.
+             (unless section
+               (cons path 'entire)))
+         ;; no cache.
+         (cons path nil)))))
+
+;;;
+;; Expire cache.
+
+(defun elmo-cache-expire ()
+  (interactive)
+  (let* ((completion-ignore-case t)
+        (method (completing-read (format "Expire by (%s): "
+                                         elmo-cache-expire-default-method)
+                                 '(("size" . "size")
+                                   ("age" . "age")))))
+    (if (string= method "")
+       (setq method elmo-cache-expire-default-method))
+    (funcall (intern (concat "elmo-cache-expire-by-" method)))))
+
+(defun elmo-read-float-value-from-minibuffer (prompt &optional initial)
+  (let ((str (read-from-minibuffer prompt initial)))
+    (cond
+     ((string-match "[0-9]*\\.[0-9]+" str)
+      (string-to-number str))
+     ((string-match "[0-9]+" str)
+      (string-to-number (concat str ".0")))
+     (t (error "%s is not number" str)))))
+
+(defun elmo-cache-expire-by-size (&optional kbytes)
+  "Expire cache file by size.
+If KBYTES is kilo bytes (This value must be float)."
+  (interactive)
+  (let ((size (or kbytes
+                 (and (interactive-p)
+                      (elmo-read-float-value-from-minibuffer
+                       "Enter cache disk size (Kbytes): "
+                       (number-to-string
+                        (if (integerp elmo-cache-expire-default-size)
+                            (float elmo-cache-expire-default-size)
+                          elmo-cache-expire-default-size))))
+                 (if (integerp elmo-cache-expire-default-size)
+                     (float elmo-cache-expire-default-size))))
+       (count 0)
+       (Kbytes 1024)
+       total beginning)
+    (message "Checking disk usage...")
+    (setq total (/ (elmo-disk-usage
+                   (expand-file-name
+                    elmo-cache-dirname elmo-msgdb-dir)) Kbytes))
+    (setq beginning total)
+    (message "Checking disk usage...done")
+    (let ((cfl (elmo-cache-get-sorted-cache-file-list))
+         (deleted 0)
+         oldest
+         cur-size cur-file)
+      (while (and (<= size total)
+                 (setq oldest (elmo-cache-get-oldest-cache-file-entity cfl)))
+       (setq cur-file (expand-file-name (car (cdr oldest)) (car oldest)))
+       (setq cur-size (/ (elmo-disk-usage cur-file) Kbytes))
+       (when (elmo-file-cache-delete cur-file)
+         (setq count (+ count 1))
+         (message "%d cache(s) are expired." count))
+       (setq deleted (+ deleted cur-size))
+       (setq total (- total cur-size)))
+      (message "%d cache(s) are expired from disk (%d Kbytes/%d Kbytes)."
+              count deleted beginning))))
+
+(defun elmo-cache-make-file-entity (filename path)
+  (cons filename (elmo-get-last-accessed-time filename path)))
+
+(defun elmo-cache-get-oldest-cache-file-entity (cache-file-list)
+  (let ((cfl cache-file-list)
+       flist firsts oldest-entity wonlist)
+    (while cfl
+      (setq flist (cdr (car cfl)))
+      (setq firsts (append firsts (list
+                                  (cons (car (car cfl))
+                                        (car flist)))))
+      (setq cfl (cdr cfl)))
+;;; (prin1 firsts)
+    (while firsts
+      (if (and (not oldest-entity)
+              (cdr (cdr (car firsts))))
+         (setq oldest-entity (car firsts)))
+      (if (and (cdr (cdr (car firsts)))
+              (cdr (cdr oldest-entity))
+              (> (cdr (cdr oldest-entity)) (cdr (cdr (car firsts)))))
+         (setq oldest-entity (car firsts)))
+      (setq firsts (cdr firsts)))
+    (setq wonlist (assoc (car oldest-entity) cache-file-list))
+    (and wonlist
+        (setcdr wonlist (delete (car (cdr wonlist)) (cdr wonlist))))
+    oldest-entity))
+
+(defun elmo-cache-get-sorted-cache-file-list ()
+  (let ((dirs (directory-files
+              (expand-file-name elmo-cache-dirname elmo-msgdb-dir)
+              t "^[^\\.]"))
+       (i 0) num
+       elist
+       ret-val)
+    (setq num (length dirs))
+    (message "Collecting cache info...")
+    (while dirs
+      (setq elist (mapcar (lambda (x)
+                           (elmo-cache-make-file-entity x (car dirs)))
+                         (directory-files (car dirs) nil "^[^\\.]")))
+      (setq ret-val (append ret-val
+                           (list (cons
+                                  (car dirs)
+                                  (sort
+                                   elist
+                                   (lambda (x y)
+                                     (< (cdr x)
+                                        (cdr y))))))))
+      (when (> num elmo-display-progress-threshold)
+       (setq i (+ i 1))
+       (elmo-display-progress
+        'elmo-cache-get-sorted-cache-file-list "Collecting cache info..."
+        (/ (* i 100) num)))
+      (setq dirs (cdr dirs)))
+    (message "Collecting cache info...done")
+    ret-val))
+
+(defun elmo-cache-expire-by-age (&optional days)
+  (let ((age (or (and days (int-to-string days))
+                (and (interactive-p)
+                     (read-from-minibuffer
+                      (format "Enter days (%s): "
+                              elmo-cache-expire-default-age)))
+                (int-to-string elmo-cache-expire-default-age)))
+       (dirs (directory-files
+              (expand-file-name elmo-cache-dirname elmo-msgdb-dir)
+              t "^[^\\.]"))
+       (count 0)
+       curtime)
+    (if (string= age "")
+       (setq age elmo-cache-expire-default-age)
+      (setq age (string-to-int age)))
+    (setq curtime (current-time))
+    (setq curtime (+ (* (nth 0 curtime)
+                       (float 65536)) (nth 1 curtime)))
+    (while dirs
+      (let ((files (directory-files (car dirs) t "^[^\\.]"))
+           (limit-age (* age 86400)))
+       (while files
+         (when (> (- curtime (elmo-get-last-accessed-time (car files)))
+                  limit-age)
+           (when (elmo-file-cache-delete (car files))
+             (setq count (+ 1 count))
+             (message "%d cache file(s) are expired." count)))
+         (setq files (cdr files))))
+      (setq dirs (cdr dirs)))))
+
+;;;
+;; msgid to path.
+(defun elmo-msgid-to-cache (msgid)
+  (when (and msgid
+            (string-match "<\\(.+\\)>$" msgid))
+    (elmo-replace-string-as-filename (elmo-match-string 1 msgid))))
+
+(defun elmo-cache-get-path (msgid &optional folder number)
+  "Get path for cache file associated with MSGID, FOLDER, and NUMBER."
+  (if (setq msgid (elmo-msgid-to-cache msgid))
+      (expand-file-name
+       (expand-file-name
+       (if folder
+           (format "%s/%s/%s@%s"
+                   (elmo-cache-get-path-subr msgid)
+                   msgid
+                   (or number "")
+                   (elmo-safe-filename folder))
+         (format "%s/%s"
+                 (elmo-cache-get-path-subr msgid)
+                 msgid))
+       (expand-file-name elmo-cache-dirname
+                         elmo-msgdb-dir)))))
+
+;;;
+;; Warnings.
+
 (defconst elmo-warning-buffer-name "*elmo warning*")
 
 (defun elmo-warning (&rest args)
index 168f8e9..61520d3 100644 (file)
@@ -40,7 +40,6 @@
 (require 'elmo-vars)
 (require 'elmo-util)
 (require 'elmo-msgdb)
-(require 'elmo-cache)
 
 (eval-when-compile (require 'cl))
 
index cc4101d..28c98ec 100644 (file)
@@ -1,3 +1,21 @@
+2001-02-24  Yuuichi Teranishi  <teranisi@gohome.org>
+
+       * wl-util.el (wl-regexp-opt): New function.
+
+       * wl-summary.el (wl-summary-delete-messages-on-buffer): Delete
+       number from `wl-summary-buffer-number-list'.
+       (wl-summary-goto-folder-subr): Load msgdb before resuming summary view;
+       Call `wl-summary-rescan' if `wl-summary-cache-use' is nil.
+       (wl-summary-move-spec-alist): Changed default setting.
+
+2001-02-23  Yoichi NAKAYAMA  <yoichi@eken.phys.nagoya-u.ac.jp>
+
+       * wl-vars.el (wl-biff-notify-hook): New hook.
+       * wl-util.el (wl-biff-notify): Run `wl-biff-notify-hook' at
+       the arrival of new mail.
+       (Based on the patch from Hironori Fukuchi <nory@valis.co.jp>
+       and advice by Yuuichi Teranishi  <teranisi@gohome.org>)
+
 2001-02-23  Yuuichi Teranishi  <teranisi@gohome.org>
 
        * wl-summary.el (wl-summary-default-get-next-msg): Fix (num => msg).
@@ -11,7 +29,7 @@
        * wl-thread.el (toplevel): require 'cl.
        (wl-thread-resume-entity): Call wl-thread-make-number-list.
        (wl-thread-make-number-list): New function.
-       (wl-thread-entity-make-number-list-from-children): Ditt.
+       (wl-thread-entity-make-number-list-from-children): Ditto.
        (wl-thread-entity-insert-as-top): Update wl-summary-buffer-number-list.
        (wl-thread-entity-insert-as-children): Likewise.
        (wl-thread-delete-message): Likewise.
index c1ef434..6eb0dc8 100644 (file)
@@ -1823,7 +1823,8 @@ If ARG is non-nil, checking is omitted."
              (progn
                (delete-region (match-beginning 0) (match-end 0))
                (delete-char 1) ; delete '\n'
-               )))
+               (setq wl-summary-buffer-number-list
+                     (delq (car msgs) wl-summary-buffer-number-list)))))
        (when (and deleting-info
                   (> len elmo-display-progress-threshold))
          (setq i (1+ i))
@@ -2562,8 +2563,10 @@ If ARG, without confirm."
          (let ((case-fold-search nil)
                (inhibit-read-only t)
                (buffer-read-only nil))
+           ;; Select folder
+           (elmo-folder-open folder)
            (erase-buffer)
-           ;; resume summary cache
+           ;; Resume summary view
            (if wl-summary-cache-use
                (let* ((dir (elmo-folder-msgdb-path folder))
                       (cache (expand-file-name wl-summary-cache-file dir))
@@ -2580,9 +2583,12 @@ If ARG, without confirm."
                          (wl-summary-load-file-object view)))
                  (if (eq wl-summary-buffer-view 'thread)
                      (wl-thread-resume-entity folder)
-                   (wl-summary-make-number-list))))
-           ;; Select folder
-           (elmo-folder-open folder)
+                   (wl-summary-make-number-list)))
+             (setq wl-summary-buffer-view
+                   (wl-summary-load-file-object
+                    (expand-file-name wl-summary-view-file
+                                      (elmo-folder-msgdb-path folder))))
+             (wl-summary-rescan))
            (wl-summary-count-unread
             (elmo-msgdb-get-mark-alist (wl-summary-buffer-msgdb)))
            (wl-summary-update-modeline)))
@@ -4295,11 +4301,18 @@ If ARG, exit virtual folder."
       (elmo-date-get-week year month mday))))
 
 (defvar wl-summary-move-spec-alist
-  '((new . ((p . "\\(N\\|\\$\\)")
-           (p . "\\(U\\|!\\)")
-           (t . nil)))
-    (unread . ((p . "\\(N\\|\\$\\|U\\|!\\)")
-              (t . nil)))))
+  (` ((new . ((t . nil)
+             (p . (, wl-summary-new-mark))
+             (p . (, (wl-regexp-opt
+                      (list wl-summary-unread-uncached-mark
+                            wl-summary-unread-cached-mark))))
+             (p . (, (regexp-quote wl-summary-important-mark)))))
+      (unread . ((t . nil)
+                (p . (, (wl-regexp-opt
+                         (list wl-summary-new-mark
+                               wl-summary-unread-uncached-mark
+                               wl-summary-unread-cached-mark))))
+                (p . (, (regexp-quote wl-summary-important-mark))))))))
 
 (defsubst wl-summary-next-message (num direction hereto)
   (let ((cur-spec (cdr (assq wl-summary-move-order 
index c934171..91d3cd9 100644 (file)
@@ -786,13 +786,13 @@ This function is imported from Emacs 20.7."
   (fset 'wl-biff-start 'ignore)))
 
 (defsubst wl-biff-notify (new-mails notify-minibuf)
-  (if (and (not wl-modeline-biff-status) (> new-mails 0))
-      (run-hooks 'wl-biff-notify-hook))
+  (when (and (not wl-modeline-biff-status) (> new-mails 0))
+    (run-hooks 'wl-biff-notify-hook))
   (setq wl-modeline-biff-status (> new-mails 0))
   (force-mode-line-update t)
   (when notify-minibuf
     (cond ((zerop new-mails) (message "No mail."))
-         ((eq 1 new-mails) (message "You have a new mail."))
+         ((= 1 new-mails) (message "You have a new mail."))
          (t (message "You have %d new mails." new-mails)))))
 
 ;; Internal variable.
@@ -863,6 +863,18 @@ This function is imported from Emacs 20.7."
                      notify-minibuf)
       (setq wl-biff-check-folders-running nil))))
 
+(if (and (fboundp 'regexp-opt)
+        (not (featurep 'xemacs)))
+    (defalias 'wl-regexp-opt 'regexp-opt)
+  (defun wl-regexp-opt (strings &optional paren)
+    "Return a regexp to match a string in STRINGS.
+Each string should be unique in STRINGS and should not contain any regexps,
+quoted or not.  If optional PAREN is non-nil, ensure that the returned regexp
+is enclosed by at least one regexp grouping construct."
+    (let ((open-paren (if paren "\\(" "")) (close-paren (if paren "\\)" "")))
+      (concat open-paren (mapconcat 'regexp-quote strings "\\|")
+             close-paren))))
+
 (require 'product)
 (product-provide (provide 'wl-util) (require 'wl-version))
 
index a3cd860..2208974 100644 (file)
@@ -468,6 +468,8 @@ reasons of system internal to accord facilities for the Emacs variants.")
   "A hook called when exit wanderlust.")
 (defvar wl-folder-suspend-hook nil
   "A hook called when suspend wanderlust.")
+(defvar wl-biff-notify-hook nil
+  "A hook called when a biff-notification is invoked.")
 (defvar wl-auto-check-folder-pre-hook nil
   "A hook called before auto check folders.")
 (defvar wl-auto-check-folder-hook nil