* elmo.el (elmo-folder-synchronize): Add 5th optional argument
[elisp/wanderlust.git] / elmo / elmo.el
index ea2b6a1..3bebcca 100644 (file)
@@ -117,6 +117,7 @@ If a folder name begins with PREFIX, use BACKEND."
                                     path   ; directory path for msgdb.
                                     msgdb  ; msgdb (may be nil).
                                     killed-list  ; killed list.
+                                    flag-table   ; flag table.
                                     persistent   ; non-nil if persistent.
                                     process-duplicates  ; read or hide
                                     biff   ; folder for biff
@@ -232,10 +233,10 @@ If second optional IN-MSGDB is non-nil, only messages in the msgdb are listed.")
       (setq list (elmo-msgdb-list-messages (elmo-folder-msgdb folder))))
     (if visible-only
        (elmo-living-messages list killed-list)
-      (if in-msgdb
-         (elmo-uniq-list
-          (nconc (elmo-number-set-to-number-list killed-list) list)
-          #'delq)
+      (if (and in-msgdb killed-list)
+         (elmo-uniq-sorted-list
+          (sort (nconc (elmo-number-set-to-number-list killed-list) list) #'<)
+          #'eq)
        list))))
 
 (luna-define-generic elmo-folder-list-messages-internal (folder &optional
@@ -365,19 +366,22 @@ FLAG is a symbol which is one of the following:
   `important' (remove important flag)
 'sugar' flag:
   `read'      (set unread flag)
+  `all'       (remove all flags)
 If optional IS-LOCAL is non-nil, update only local (not server) status.")
 
 (luna-define-generic elmo-folder-next-message-number (folder)
   "The next message number that will be assigned to a new message.
 FOLDER is the ELMO folder structure.")
 
-(luna-define-generic elmo-folder-append-buffer (folder &optional flag
+(luna-define-generic elmo-folder-append-buffer (folder &optional flags
                                                       number)
   "Append current buffer as a new message.
-FOLDER is the destination folder(ELMO folder structure).
-FLAG is the status of appended message.
+FOLDER is the destination folder (ELMO folder structure).
+FLAGS is the status of appended message (list of symbols).
+If it is nil, it is not that there is no flag and what is not defined is meant.
 If optional argument NUMBER is specified, the new message number is set
-\(if possible\).")
+\(if possible\).
+Return nil on failure.")
 
 (luna-define-generic elmo-folder-append-messages (folder
                                                  src-folder
@@ -449,13 +453,22 @@ Return newly created temporary directory name which contains temporary files.")
 (luna-define-generic elmo-message-file-p (folder number)
   "Return t if message in the FOLDER with NUMBER is a file.")
 
-(luna-define-generic elmo-message-flags (folder number)
+(luna-define-generic elmo-message-flags (folder number &optional msgid)
   "Return a list of flags.
 FOLDER is a ELMO folder structure.
-NUMBER is a number of the message.")
-
-(luna-define-method elmo-message-flags ((folder elmo-folder) number)
-  (elmo-msgdb-flags (elmo-folder-msgdb folder) number))
+NUMBER is a number of the message.
+If optional argument MSGID is specified,
+the message with NUMBER checks whether it has MSGID.")
+
+(luna-define-method elmo-message-flags ((folder elmo-folder) number
+                                       &optional msgid)
+  (if msgid
+      (let ((this-id (elmo-message-field folder number 'message-id)))
+       (and this-id
+            (string= this-id msgid)
+            (or (elmo-msgdb-flags (elmo-folder-msgdb folder) number)
+                '(read))))
+    (elmo-msgdb-flags (elmo-folder-msgdb folder) number)))
 
 (defsubst elmo-message-flagged-p (folder number flag)
   "Return non-nil if the message is set FLAG.
@@ -787,7 +800,7 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-FLAG-ALIST).")
                     cache-path))))
     (when (and filename (file-readable-p filename))
       (with-temp-buffer
-       (elmo-set-buffer-multibyte nil)
+       (set-buffer-multibyte nil)
        ;;(insert-file-contents-as-binary filename)
        (elmo-message-fetch folder number
                            (elmo-make-fetch-strategy 'entire
@@ -795,7 +808,7 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-FLAG-ALIST).")
                                                      nil
                                                      cache-path)
                            nil (current-buffer) t)
-       (elmo-set-buffer-multibyte default-enable-multibyte-characters)
+       (set-buffer-multibyte default-enable-multibyte-characters)
        (decode-coding-region (point-min) (point-max)
                              elmo-mime-display-as-is-coding-system)
        (elmo-buffer-field-condition-match condition number numbers)))))
@@ -825,6 +838,39 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-FLAG-ALIST).")
 (luna-define-method elmo-folder-have-subfolder-p ((folder elmo-folder))
   t)
 
+;; Flag table
+(luna-define-generic elmo-folder-flag-table (folder &optional if-exists)
+  "Return the flag-table of FOLDER.
+If optional argument IF-EXISTS is nil, load on demand.
+\(For internal use only.\)")
+
+(luna-define-generic elmo-folder-close-flag-table (folder)
+  "Close flag-table of FOLDER.")
+
+(luna-define-method elmo-folder-flag-table ((folder elmo-folder)
+                                           &optional if-exists)
+  (or (elmo-folder-flag-table-internal folder)
+      (unless if-exists
+       (elmo-folder-set-flag-table-internal
+        folder
+        (elmo-flag-table-load (elmo-folder-msgdb-path folder))))))
+
+(luna-define-method elmo-folder-close-flag-table ((folder elmo-folder))
+  (elmo-flag-table-save (elmo-folder-msgdb-path folder)
+                       (elmo-folder-flag-table folder))
+  (elmo-folder-set-flag-table-internal folder nil))
+
+(defun elmo-folder-preserve-flags (folder msgid flags)
+  "Preserve FLAGS into FOLDER for a message that has MSGID."
+  (when (and msgid flags)
+    (let ((flag-table (elmo-folder-flag-table folder 'if-exists))
+         load-now)
+      (when (setq load-now (null flag-table))
+       (setq flag-table (elmo-folder-flag-table folder)))
+      (elmo-flag-table-set flag-table msgid flags)
+      (when load-now
+       (elmo-folder-close-flag-table folder)))))
+
 ;;; Folder info
 ;; Folder info is a message number information cache (hashtable)
 (defsubst elmo-folder-get-info (folder &optional hashtb)
@@ -971,17 +1017,16 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-FLAG-ALIST).")
 (defun elmo-generic-folder-append-messages (folder src-folder numbers
                                                   same-number)
   (let ((src-msgdb-exists (not (zerop (elmo-folder-length src-folder))))
-       unseen table flags
+       unseen table
        succeed-numbers failure cache id)
-    (setq table (elmo-flag-table-load (elmo-folder-msgdb-path folder)))
+    (setq table (elmo-folder-flag-table folder))
     (with-temp-buffer
       (set-buffer-multibyte nil)
       (while numbers
        (setq failure nil
              id (and src-msgdb-exists
                      (elmo-message-field src-folder (car numbers)
-                                         'message-id))
-             flags (elmo-message-flags src-folder (car numbers)))
+                                         'message-id)))
        (condition-case nil
            (setq cache (elmo-file-cache-get id)
                  failure
@@ -1005,18 +1050,19 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-FLAG-ALIST).")
                    (> (buffer-size) 0)
                    (elmo-folder-append-buffer
                     folder
-                    (or flags '(read))
+                    (elmo-message-flags
+                     src-folder
+                     (car numbers)
+                     (elmo-msgdb-get-message-id-from-buffer))
                     (if same-number (car numbers))))))
          (error (setq failure t)))
        ;; FETCH & APPEND finished
        (unless failure
-         (when id
-           (elmo-flag-table-set table id flags))
          (setq succeed-numbers (cons (car numbers) succeed-numbers)))
        (elmo-progress-notify 'elmo-folder-move-messages)
        (setq numbers (cdr numbers)))
       (when (elmo-folder-persistent-p folder)
-       (elmo-flag-table-save (elmo-folder-msgdb-path folder) table))
+       (elmo-folder-close-flag-table folder))
       succeed-numbers)))
 
 ;; Arguments should be reduced.
@@ -1383,13 +1429,12 @@ If Optional LOCAL is non-nil, don't update server flag."
 
 (defun elmo-folder-kill-messages (folder numbers)
   "Kill(hide) messages in the FOLDER with NUMBERS."
-  (let ((msgdb (elmo-folder-msgdb folder))
-       (killed (elmo-folder-killed-list-internal folder)))
-    (dolist (number numbers)
-      (setq killed (elmo-number-set-append killed number))
-      (elmo-msgdb-unset-flag msgdb number 'all))
-    (elmo-folder-set-killed-list-internal folder killed)))
-
+  (elmo-folder-set-killed-list-internal
+   folder
+   (elmo-number-set-append-list
+    (elmo-folder-killed-list-internal folder)
+    numbers))
+  (elmo-folder-unset-flag folder numbers 'all 'local-only))
 
 (luna-define-method elmo-folder-clear ((folder elmo-folder)
                                       &optional keep-killed)
@@ -1405,7 +1450,8 @@ If Optional LOCAL is non-nil, don't update server flag."
                                              &optional
                                              disable-killed
                                              ignore-msgdb
-                                             no-check)
+                                             no-check
+                                             mask)
   "Synchronize the folder data to the newest status.
 FOLDER is the ELMO folder structure.
 
@@ -1413,6 +1459,8 @@ If optional DISABLE-KILLED is non-nil, killed messages are also synchronized.
 If optional IGNORE-MSGDB is non-nil, current msgdb is thrown away except
 flag status.
 If NO-CHECK is non-nil, rechecking folder is skipped.
+If optional argument MASK is specified and is a list of message numbers,
+synchronize messages only which are contained the list.
 Return amount of cross-posted messages.
 If update process is interrupted, return nil.")
 
@@ -1420,7 +1468,8 @@ If update process is interrupted, return nil.")
                                             &optional
                                             disable-killed
                                             ignore-msgdb
-                                            no-check)
+                                            no-check
+                                            mask)
   (let ((killed-list (elmo-folder-killed-list-internal folder))
        (before-append t)
        old-msgdb diff diff-2 delete-list new-list new-msgdb flag
@@ -1441,6 +1490,8 @@ If update process is interrupted, return nil.")
                                      folder
                                      (not disable-killed)
                                      'in-msgdb)))
+         (when (and mask (car diff))
+           (setcar diff (elmo-list-filter mask (car diff))))
          (message "Checking folder diff...done")
          (setq new-list (elmo-folder-confirm-appends (car diff)))
          ;; Set killed list as ((1 . MAX-OF-DISAPPEARED))