* elmo.el (elmo-message-flags): Add optional argument `msgid'.
[elisp/wanderlust.git] / elmo / elmo.el
index 80ba5fc..d974213 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.
                                     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
                                     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)
       (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
        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)
   `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.")
 
 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.
                                                       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 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
 
 (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-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.
   "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.
 
 (defsubst elmo-message-flagged-p (folder number flag)
   "Return non-nil if the message is set FLAG.
@@ -774,22 +787,30 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-FLAG-ALIST).")
 (luna-define-method elmo-message-match-condition ((folder elmo-folder)
                                                  number condition
                                                  numbers)
 (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))
+  (let* (cache cache-path
+        (filename (cond
+                   ((elmo-message-file-name folder number))
+                   ((progn
+                      (setq cache (elmo-file-cache-get
+                                   (elmo-message-field folder number
+                                                       'message-id)))
+                      (setq cache-path (elmo-file-cache-path cache))
+                      (and cache-path
+                           (not (elmo-cache-path-section-p cache-path))))
+                    cache-path))))
+    (when (and filename (file-readable-p filename))
       (with-temp-buffer
       (with-temp-buffer
-       (insert-file-contents-as-binary filename)
+       (elmo-set-buffer-multibyte nil)
+       ;;(insert-file-contents-as-binary filename)
+       (elmo-message-fetch folder number
+                           (elmo-make-fetch-strategy 'entire
+                                                     (and cache t)
+                                                     nil
+                                                     cache-path)
+                           nil (current-buffer) t)
        (elmo-set-buffer-multibyte default-enable-multibyte-characters)
        (elmo-set-buffer-multibyte default-enable-multibyte-characters)
-       ;; Should consider charset?
-       (decode-mime-charset-region (point-min) (point-max) elmo-mime-charset)
+       (decode-coding-region (point-min) (point-max)
+                             elmo-mime-display-as-is-coding-system)
        (elmo-buffer-field-condition-match condition number numbers)))))
 
 (luna-define-method elmo-folder-pack-numbers ((folder elmo-folder))
        (elmo-buffer-field-condition-match condition number numbers)))))
 
 (luna-define-method elmo-folder-pack-numbers ((folder elmo-folder))
@@ -817,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)
 
 (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)
 ;;; Folder info
 ;; Folder info is a message number information cache (hashtable)
 (defsubst elmo-folder-get-info (folder &optional hashtb)
@@ -963,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))))
 (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)
        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)
     (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
        (condition-case nil
            (setq cache (elmo-file-cache-get id)
                  failure
@@ -997,18 +1050,19 @@ Return a cons cell of (NUMBER-CROSSPOSTS . NEW-FLAG-ALIST).")
                    (> (buffer-size) 0)
                    (elmo-folder-append-buffer
                     folder
                    (> (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
                     (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)
          (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.
       succeed-numbers)))
 
 ;; Arguments should be reduced.
@@ -1178,6 +1232,18 @@ FIELD is a symbol of the field.")
 (luna-define-method elmo-message-field ((folder elmo-folder) number field)
   (elmo-message-entity-field (elmo-message-entity folder number) field))
 
 (luna-define-method elmo-message-field ((folder elmo-folder) number field)
   (elmo-message-entity-field (elmo-message-entity folder number) field))
 
+(luna-define-generic elmo-message-set-field (folder number field value)
+  "Set message field value in the msgdb.
+FOLDER is the ELMO folder structure.
+NUMBER is a number of the message.
+FIELD is a symbol of the field.
+VALUE is a value to set.")
+
+(luna-define-method elmo-message-set-field ((folder elmo-folder) number
+                                           field value)
+  (elmo-message-entity-set-field (elmo-message-entity folder number)
+                                field value))
+
 (luna-define-method elmo-message-use-cache-p ((folder elmo-folder) number)
   nil) ; default is not use cache.
 
 (luna-define-method elmo-message-use-cache-p ((folder elmo-folder) number)
   nil) ; default is not use cache.
 
@@ -1363,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."
 
 (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)
-      (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)
 
 (luna-define-method elmo-folder-clear ((folder elmo-folder)
                                       &optional keep-killed)