* test-elmo-util.el (test-elmo-number-set-delete-1): New testcase.
[elisp/wanderlust.git] / elmo / elmo-flag.el
index 781b31b..23344bb 100644 (file)
 (eval-when-compile (require 'cl))
 
 ;;; Code:
-(defcustom elmo-preserved-flags '(answered cached new unread)
-  "Reserved flags which are not treated as global."
-  :type '(repeat (symbol :tag "flag")))
-
-(defcustom elmo-global-flag-list '(important)
+(defcustom elmo-global-flags '(important)
   "A list of flag symbol which is managed globally by the flag folder."
   :type '(repeat symbol)
   :group 'elmo)
 
+(defcustom elmo-local-flags '(unread any digest)
+  "A list of flag symbol which is not treated as global flag."
+  :type '(repeat symbol)
+  :group 'elmo)
+
 (defvar elmo-global-flag-folder-alist nil
   "Internal variable to hold global-flag-folder structures.")
 
 (eval-and-compile
   (luna-define-class elmo-flag-folder (elmo-localdir-folder)
-                    (flag minfo minfo-hash))
+                    (flag minfo minfo-hash max-number))
   (luna-define-internal-accessors 'elmo-flag-folder))
 
 (luna-define-method elmo-folder-initialize ((folder
@@ -52,7 +53,7 @@
                                            name)
   (if (string-match "flag/\\([a-z]+\\)" name)
       (setq name (match-string 1 name))
-    (setq name (symbol-name (car elmo-global-flag-list)))
+    (setq name (symbol-name (car elmo-global-flags)))
     (elmo-folder-set-name-internal
      folder
      (concat (elmo-folder-name-internal folder) "/" name)))
@@ -61,8 +62,8 @@
            msgdb-path)
        (elmo-flag-folder-set-flag-internal folder flag)
        (unless (elmo-global-flag-p flag)
-         (setq elmo-global-flag-list
-               (nconc elmo-global-flag-list (list flag))))
+         (setq elmo-global-flags
+               (nconc elmo-global-flags (list flag))))
        ;; must be AFTER set flag slot.
        (setq msgdb-path (elmo-folder-msgdb-path folder))
        (unless (file-directory-p msgdb-path)
        (elmo-localdir-folder-set-directory-internal
         folder
         msgdb-path)
+       (if (file-exists-p (expand-file-name "max" msgdb-path))
+           (elmo-flag-folder-set-max-number-internal
+            folder
+            (elmo-object-load (expand-file-name "max" msgdb-path))))
        (if (file-exists-p (expand-file-name ".minfo" msgdb-path))
            (elmo-flag-folder-set-minfo-internal
             folder
                                                elmo-flag-folder))
   (elmo-object-save
    (expand-file-name ".minfo" (elmo-folder-msgdb-path folder))
-   (elmo-flag-folder-minfo-internal folder)))
+   (elmo-flag-folder-minfo-internal folder))
+  (if (elmo-flag-folder-max-number-internal folder)
+      (elmo-object-save
+       (expand-file-name "max" (elmo-folder-msgdb-path folder))
+       (elmo-flag-folder-max-number-internal folder))))
 
 (luna-define-method elmo-folder-list-subfolders ((folder elmo-flag-folder)
                                                 &optional one-level)
-  (mapcar (lambda (flag)
-           (concat
-            (elmo-folder-prefix-internal folder)
-            (symbol-name (elmo-folder-type-internal folder))
-            "/"
-            (symbol-name flag)))
-         elmo-global-flag-list))
+  (let ((dir (expand-file-name "flag" elmo-msgdb-directory)))
+    (mapcar (lambda (flag)
+             (concat
+              (elmo-folder-prefix-internal folder)
+              (symbol-name (elmo-folder-type-internal folder))
+              "/"
+              (symbol-name flag)))
+           (elmo-uniq-list
+            (append
+             (mapcar 'intern (delete ".." (delete "." (directory-files dir))))
+             elmo-global-flags)))))
 
 (defun elmo-flag-folder-delete-message (folder number
                                               &optional keep-referrer)
      (delq elem (elmo-flag-folder-minfo-internal folder))))
   t)
 
-(luna-define-method elmo-folder-delete-messages ((folder
-                                                 elmo-flag-folder)
-                                                numbers)
+(luna-define-method elmo-folder-delete-messages-internal ((folder
+                                                          elmo-flag-folder)
+                                                         numbers)
   (dolist (number numbers)
     (elmo-flag-folder-delete-message folder number)
     (elmo-localdir-delete-message folder number))
 
 (defmacro elmo-flag-get-folder (flag)
   "Get the flag folder structure for FLAG."
-  `(when (memq ,flag elmo-global-flag-list)
+  `(when (memq ,flag elmo-global-flags)
      (elmo-make-folder (concat  "'flag/" (symbol-name ,flag)))))
 
 (defun elmo-flag-folder-referrer (folder number)
@@ -221,13 +234,13 @@ NUMBER is the number of the message."
 ;;; Global-Flag API
 (defun elmo-global-flag-p (flag)
   "Return non-nil when FLAG is global."
-  (memq flag elmo-global-flag-list))
+  (memq flag elmo-global-flags))
 
 (defun elmo-global-flags (fname number)
   "Return a list of global flags for the message.
 FNAME is the name string of the folder.
 NUMBER is the number of the message."
-  (let ((flag-list elmo-global-flag-list)
+  (let ((flag-list elmo-global-flags)
        folder matches)
     (while flag-list
       (setq folder (elmo-flag-get-folder (car flag-list)))
@@ -245,11 +258,10 @@ FOLDER is the elmo folder structure.
 FLAG is the symbol of the flag."
   (when (elmo-global-flag-p flag)
     (let ((flag-folder (elmo-flag-get-folder flag))
-         result entity)
+         result number)
       (dolist (elem (elmo-flag-folder-minfo-internal flag-folder))
-       (if (setq entity (elmo-message-entity folder (nth 1 elem)))
-           (setq result (cons (elmo-message-entity-number entity)
-                              result))))
+       (if (setq number (elmo-message-number folder (nth 1 elem)))
+           (setq result (cons number result))))
       result)))
 
 ;;;
@@ -264,7 +276,13 @@ NUMBER is the message number."
   (dolist (flag flags)
     (elmo-global-flag-set flag folder number message-id)))
 
+(defun elmo-local-flag-p (flag)
+  "Return non-nil when flag is not appropriate for global flag."
+  (memq flag elmo-local-flags))
+
 (defsubst elmo-global-flag-set-internal (flag folder number message-id)
+  (when (elmo-local-flag-p flag)
+    (error "Cannot treat `%s' as global flag." flag))
   (when message-id
     (let ((flag-folder (elmo-flag-get-folder flag))
          cache new-file new-number elem)
@@ -287,10 +305,17 @@ NUMBER is the message number."
                               (elmo-flag-folder-minfo-hash-internal
                                flag-folder)))
        ;; Append new element.
+       (elmo-flag-folder-set-max-number-internal
+        flag-folder
+        (+ (or (elmo-flag-folder-max-number-internal flag-folder)
+               ;; This is the first time.
+               (car (elmo-folder-status flag-folder)))
+           1))
        (setq new-file
              (expand-file-name
               (int-to-string
-               (setq new-number (1+ (car (elmo-folder-status flag-folder)))))
+               (setq new-number
+                     (elmo-flag-folder-max-number-internal flag-folder)))
               (elmo-localdir-folder-directory-internal flag-folder)))
        (with-temp-buffer
          (setq cache (and message-id (elmo-file-cache-get message-id)))
@@ -377,7 +402,7 @@ NUMBERS is the message number list.
 If optional DELETE-IF-NONE is non-nil, delete message from flag folder when
 the message is not flagged in any folder."
   (unless (eq (elmo-folder-type-internal folder) 'flag)
-    (dolist (flag elmo-global-flag-list)
+    (dolist (flag elmo-global-flags)
       (dolist (number numbers)
        (elmo-global-flag-detach flag folder number delete-if-none)))))
 
@@ -388,7 +413,7 @@ If FLAGS is `t', all global flags becomes candidates.
 If optional IGNORE-PRESERVED is non-nil, preserved flags
 \(answered, cached, new, unread\) are not included."
   (let ((result (copy-sequence (if (eq flags t)
-                                  (setq flags elmo-global-flag-list)
+                                  (setq flags elmo-global-flags)
                                 flags))))
     (while flags
       (unless (elmo-global-flag-p (car flags))
@@ -431,6 +456,12 @@ If optional IGNORE-PRESERVED is non-nil, preserved flags
            (elmo-global-flag-set 'important nil nil (car elem))))))
     (message "Upgrading flag structure...done")))
 
+(luna-define-method elmo-folder-delete :around ((folder elmo-flag-folder))
+  (let ((flag (elmo-flag-folder-flag-internal folder)))
+    (when (luna-call-next-method)
+      (setq elmo-global-flags (delq flag elmo-global-flags))
+      t)))
+
 (require 'product)
 (product-provide (provide 'elmo-flag) (require 'elmo-version))