* elmo-msgdb.el (elmo-msgdb-list-messages): Undo last change.
[elisp/wanderlust.git] / elmo / elmo-msgdb.el
index 49f1b45..8f91dc1 100644 (file)
@@ -58,7 +58,6 @@
   :type '(string :tag "Mark")
   :group 'elmo)
 
-;; Not implemented yet.
 (defcustom elmo-msgdb-answered-cached-mark "&"
   "Mark for answered and cached message."
   :type '(string :tag "Mark")
@@ -69,7 +68,7 @@
   :type '(string :tag "Mark")
   :group 'elmo)
 
-(defcustom elmo-msgdb-important-mark"$"
+(defcustom elmo-msgdb-important-mark "$"
   "Mark for important message."
   :type '(string :tag "Mark")
   :group 'elmo)
 ;; elmo-flag-table-get
 ;; elmo-flag-table-save
 
-;; elmo-msgdb-append-entity
-;; msgdb entity flag-table
+;; elmo-msgdb-append-entity MSGDB ENTITY MARK-OR-FLAGS
 
 ;; ENTITY elmo-msgdb-make-entity ARGS
 ;; VALUE elmo-msgdb-entity-field ENTITY
 ;; LIST-OF-MARKS elmo-msgdb-unread-marks 
 ;; LIST-OF-MARKS elmo-msgdb-answered-marks 
 ;; LIST-OF-MARKS elmo-msgdb-uncached-marks 
-;; elmo-msgdb-seen-save DIR OBJ
 ;; elmo-msgdb-overview-save DIR OBJ
 
 ;; elmo-msgdb-message-entity MSGDB KEY
     msgdb))
 
 (defun elmo-msgdb-list-messages (msgdb)
-  "List message numbers in the MSGDB."
-  (mapcar 'car (elmo-msgdb-get-number-alist msgdb)))
+  "Return a list of message numbers in the MSGDB."
+  (mapcar 'elmo-msgdb-overview-entity-get-number
+         (elmo-msgdb-get-overview msgdb)))
+
+(defsubst elmo-msgdb-mark-to-flags (mark)
+  (append
+   (and (string= mark elmo-msgdb-new-mark)
+       '(new))
+   (and (string= mark elmo-msgdb-important-mark)
+       '(important))
+   (and (member mark (elmo-msgdb-unread-marks))
+       '(unread))
+   (and (member mark (elmo-msgdb-answered-marks))
+       '(answered))
+   (and (not (member mark (elmo-msgdb-uncached-marks)))
+       '(cached))))
+
+(defsubst elmo-msgdb-flags-to-mark (flags cached use-cache)
+  (cond ((memq 'new flags)
+        elmo-msgdb-new-mark)
+       ((memq 'important flags)
+        elmo-msgdb-important-mark)
+       ((memq 'answered flags)
+        (if cached
+            elmo-msgdb-answered-cached-mark
+          elmo-msgdb-answered-uncached-mark))
+       ((memq 'unread flags)
+        (if cached
+            elmo-msgdb-unread-cached-mark
+          elmo-msgdb-unread-uncached-mark))
+       (t
+        (if (or cached (not use-cache))
+            nil
+          elmo-msgdb-read-uncached-mark))))
 
 (defsubst elmo-msgdb-get-mark (msgdb number)
   "Get mark string from MSGDB which corresponds to the message with NUMBER."
@@ -254,6 +283,9 @@ If mark is changed, return non-nil."
                                  elmo-msgdb-unread-cached-mark
                                elmo-msgdb-unread-uncached-mark)))))))
 
+(defsubst elmo-msgdb-flags (msgdb number)
+  (elmo-msgdb-mark-to-flags (elmo-msgdb-get-mark msgdb number)))
+
 (defun elmo-msgdb-set-flag (msgdb folder number flag)
   "Set message flag.
 MSGDB is the ELMO msgdb.
@@ -363,6 +395,28 @@ FLAG is a symbol which is one of the following:
                  elmo-msgdb-unread-uncached-mark
                  elmo-msgdb-read-uncached-mark))))
 
+(defun elmo-msgdb-append-entity (msgdb entity &optional mark)
+  (when entity
+    (let ((number (elmo-msgdb-overview-entity-get-number entity))
+         (message-id (elmo-msgdb-overview-entity-get-id entity)))
+      (elmo-msgdb-set-overview
+       msgdb
+       (nconc (elmo-msgdb-get-overview msgdb)
+             (list entity)))
+      (elmo-msgdb-set-number-alist
+       msgdb
+       (nconc (elmo-msgdb-get-number-alist msgdb)
+             (list (cons number message-id))))
+      (when mark
+       (elmo-msgdb-set-mark-alist
+        msgdb
+        (nconc (elmo-msgdb-get-mark-alist msgdb)
+               (list (list number mark)))))
+      (elmo-msgdb-make-index
+       msgdb
+       (list entity)
+       (list (list number mark))))))
+
 (defsubst elmo-msgdb-get-number (msgdb message-id)
   "Get number of the message which corrensponds to MESSAGE-ID from MSGDB."
   (elmo-msgdb-overview-entity-get-number
@@ -390,26 +444,50 @@ FLAG is a symbol which is one of the following:
         (elmo-msgdb-overview-get-entity
          number msgdb)))))
 
-(defsubst elmo-msgdb-append (msgdb msgdb-append)
-  (list
-   (nconc (car msgdb) (car msgdb-append))
-   (nconc (cadr msgdb) (cadr msgdb-append))
-   (nconc (caddr msgdb) (caddr msgdb-append))
-   (elmo-msgdb-make-index
-    msgdb
-    (elmo-msgdb-get-overview msgdb-append)
-    (elmo-msgdb-get-mark-alist msgdb-append))
-   (nth 4 msgdb)))
+(defun elmo-msgdb-append (msgdb msgdb-append)
+  "Return a list of messages which have duplicated message-id."
+  (let (duplicates)
+    (elmo-msgdb-set-overview
+     msgdb
+     (nconc (elmo-msgdb-get-overview msgdb)
+           (elmo-msgdb-get-overview msgdb-append)))
+    (elmo-msgdb-set-number-alist
+     msgdb
+     (nconc (elmo-msgdb-get-number-alist msgdb)
+           (elmo-msgdb-get-number-alist msgdb-append)))
+    (elmo-msgdb-set-mark-alist
+     msgdb
+     (nconc (elmo-msgdb-get-mark-alist msgdb)
+           (elmo-msgdb-get-mark-alist msgdb-append)))
+    (setq duplicates (elmo-msgdb-make-index
+                     msgdb
+                     (elmo-msgdb-get-overview msgdb-append)
+                     (elmo-msgdb-get-mark-alist msgdb-append)))
+    (elmo-msgdb-set-path
+     msgdb
+     (or (elmo-msgdb-get-path msgdb)
+        (elmo-msgdb-get-path msgdb-append)))
+    duplicates))
+
+(defun elmo-msgdb-merge (folder msgdb-merge)
+  "Return a list of messages which have duplicated message-id."
+  (let (msgdb duplicates)
+    (setq msgdb (or (elmo-folder-msgdb-internal folder)
+                   (elmo-make-msgdb nil nil nil
+                                    (elmo-folder-msgdb-path folder))))
+    (setq duplicates (elmo-msgdb-append msgdb msgdb-merge))
+    (elmo-folder-set-msgdb-internal folder msgdb)
+    duplicates))
 
 (defsubst elmo-msgdb-clear (&optional msgdb)
   (if msgdb
-      (list
-       (setcar msgdb nil)
-       (setcar (cdr msgdb) nil)
-       (setcar (cddr msgdb) nil)
-       (setcar (nthcdr 3 msgdb) nil)
-       (setcar (nthcdr 4 msgdb) nil))
-    (list nil nil nil nil nil)))
+      (progn
+       (elmo-msgdb-set-overview msgdb nil)
+       (elmo-msgdb-set-number-alist msgdb nil)
+       (elmo-msgdb-set-mark-alist msgdb nil)
+       (elmo-msgdb-set-index msgdb nil)
+       msgdb)
+    (elmo-make-msgdb)))
 
 (defun elmo-msgdb-delete-msgs (msgdb msgs)
   "Delete MSGS from MSGDB
@@ -433,18 +511,20 @@ content of MSGDB is changed."
       ;;
       (when index (elmo-msgdb-clear-index msgdb ov-entity))
       (setq msgs (cdr msgs)))
-    (setcar msgdb overview)
-    (setcar (cdr msgdb) number-alist)
-    (setcar (cddr msgdb) mark-alist)
-    (setcar (nthcdr 3 msgdb) index)
+    (elmo-msgdb-set-overview msgdb overview)
+    (elmo-msgdb-set-number-alist msgdb number-alist)
+    (elmo-msgdb-set-mark-alist msgdb mark-alist)
+    (elmo-msgdb-set-index msgdb index)
     t)) ;return value
 
 (defun elmo-msgdb-sort-by-date (msgdb)
   (message "Sorting...")
   (let ((overview (elmo-msgdb-get-overview msgdb)))
-    (setq overview (elmo-msgdb-overview-sort-by-date overview))
+    (elmo-msgdb-set-overview
+     msgdb
+     (elmo-msgdb-overview-sort-by-date overview))
     (message "Sorting...done")
-    (list overview (nth 1 msgdb)(nth 2 msgdb))))
+    msgdb))
 
 ;;;
 (defsubst elmo-msgdb-append-element (list element)
@@ -702,11 +782,6 @@ header separator."
           elmo-msgdb-answered-cached-mark
         elmo-msgdb-answered-uncached-mark)))))
 
-(defsubst elmo-msgdb-seen-save (dir obj)
-  (elmo-object-save
-   (expand-file-name elmo-msgdb-seen-filename dir)
-   obj))
-
 (defsubst elmo-msgdb-overview-save (dir overview)
   (elmo-object-save
    (expand-file-name elmo-msgdb-overview-filename dir)
@@ -989,7 +1064,7 @@ Return CONDITION itself if no entity exists in msgdb."
                (references (aref (cdr entity) 1))
                (size (aref (cdr entity) 7))
                (t (cdr (assoc (symbol-name field) (aref (cdr entity) 8)))))))
-        (if decode
+        (if (and decode (memq field '(from subject)))
             (elmo-msgdb-get-decoded-cache field-value)
           field-value))))
 
@@ -1237,7 +1312,7 @@ Header region is supposed to be narrowed."
       (and (setq number (elmo-msgdb-overview-entity-get-number entity))
           (elmo-clear-hash-val (format "#%d" number) mhash)))))
 
-(defun elmo-msgdb-make-index (msgdb &optional overview mark-alist)
+(defun elmo-msgdb-make-index-return (msgdb &optional overview mark-alist)
   "Append OVERVIEW and MARK-ALIST to the index of MSGDB.
 If OVERVIEW and MARK-ALIST are nil, make index for current MSGDB.
 Return the updated INDEX."
@@ -1269,6 +1344,44 @@ Return the updated INDEX."
       (elmo-msgdb-set-index msgdb index)
       index)))
 
+(defun elmo-msgdb-make-index (msgdb &optional overview mark-alist)
+  "Append OVERVIEW and MARK-ALIST to the index of MSGDB.
+If OVERVIEW and MARK-ALIST are nil, make index for current MSGDB.
+Return a list of message numbers which have duplicated message-ids."
+  (when msgdb
+    (let* ((overview (or overview (elmo-msgdb-get-overview msgdb)))
+          (mark-alist (or mark-alist (elmo-msgdb-get-mark-alist msgdb)))
+          (index (elmo-msgdb-get-index msgdb))
+          (ehash (or (car index) ;; append
+                     (elmo-make-hash (length overview))))
+          (mhash (or (cdr index) ;; append
+                     (elmo-make-hash (length overview))))
+          duplicates)
+      (while overview
+       ;; key is message-id
+       (if (elmo-get-hash-val (caar overview) ehash) ; duplicated.
+           (setq duplicates (cons
+                             (elmo-msgdb-overview-entity-get-number
+                              (car overview))
+                             duplicates)))
+       (if (caar overview)
+           (elmo-set-hash-val (caar overview) (car overview) ehash))
+       ;; key is number
+       (elmo-set-hash-val
+        (format "#%d"
+                (elmo-msgdb-overview-entity-get-number (car overview)))
+        (car overview) ehash)
+       (setq overview (cdr overview)))
+      (while mark-alist
+       ;; key is number
+       (elmo-set-hash-val
+        (format "#%d" (car (car mark-alist)))
+        (car mark-alist) mhash)
+       (setq mark-alist (cdr mark-alist)))
+      (setq index (or index (cons ehash mhash)))
+      (elmo-msgdb-set-index msgdb index)
+      duplicates)))
+
 (defsubst elmo-folder-get-info (folder &optional hashtb)
   (elmo-get-hash-val folder
                     (or hashtb elmo-folder-info-hashtb)))
@@ -1327,10 +1440,10 @@ Return the updated INDEX."
                           (list elmo-msgdb-important-mark))))))
     (when mark-regexp
       (if (eq flag 'read)
-         (dolist (number (elmo-msgdb-get-number-alist msgdb))
-           (unless (string-match mark-regexp (elmo-msgdb-get-mark
-                                              msgdb number))
-             (setq matched (cons number matched))))
+         (dolist (number (elmo-msgdb-list-messages msgdb))
+           (let ((mark (elmo-msgdb-get-mark msgdb number)))
+             (unless (and mark (string-match mark-regexp mark))
+               (setq matched (cons number matched)))))
        (dolist (elem (elmo-msgdb-get-mark-alist msgdb))
          (if (string-match mark-regexp (cadr elem))
              (setq matched (cons (car elem) matched))))))