1 ;;; elmo-msgdb.el --- Message Database for ELMO.
3 ;; Copyright (C) 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
4 ;; Copyright (C) 2000 Masahiro MURATA <muse@ba2.so-net.ne.jp>
6 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
7 ;; Masahiro MURATA <muse@ba2.so-net.ne.jp>
8 ;; Keywords: mail, net news
10 ;; This file is part of ELMO (Elisp Library for Message Orchestration).
12 ;; This program is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
17 ;; This program is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 ;; Boston, MA 02111-1307, USA.
34 (eval-when-compile (require 'cl))
41 (defcustom elmo-msgdb-new-mark "N"
42 "Mark for new message."
43 :type '(string :tag "Mark")
46 (defcustom elmo-msgdb-unread-uncached-mark "U"
47 "Mark for unread and uncached message."
48 :type '(string :tag "Mark")
51 (defcustom elmo-msgdb-unread-cached-mark "!"
52 "Mark for unread but already cached message."
53 :type '(string :tag "Mark")
56 (defcustom elmo-msgdb-read-uncached-mark "u"
57 "Mark for read but uncached message."
58 :type '(string :tag "Mark")
61 (defcustom elmo-msgdb-answered-cached-mark "&"
62 "Mark for answered and cached message."
63 :type '(string :tag "Mark")
66 (defcustom elmo-msgdb-answered-uncached-mark "A"
67 "Mark for answered but cached message."
68 :type '(string :tag "Mark")
71 (defcustom elmo-msgdb-important-mark "$"
72 "Mark for important message."
73 :type '(string :tag "Mark")
78 ;; MSGDB elmo-load-msgdb PATH
79 ;; MARK elmo-msgdb-get-mark MSGDB NUMBER
81 ;; CACHED elmo-msgdb-get-cached MSGDB NUMBER
82 ;; VOID elmo-msgdb-set-cached MSGDB NUMBER CACHED USE-CACHE
83 ;; VOID elmo-msgdb-set-flag MSGDB FOLDER NUMBER FLAG
84 ;; VOID elmo-msgdb-unset-flag MSGDB FOLDER NUMBER FLAG
86 ;; LIST-OF-NUMBERS elmo-msgdb-count-marks MSGDB
87 ;; NUMBER elmo-msgdb-get-number MSGDB MESSAGE-ID
88 ;; FIELD-VALUE elmo-msgdb-get-field MSGDB NUMBER FIELD
89 ;; MSGDB elmo-msgdb-append MSGDB MSGDB-APPEND
90 ;; MSGDB elmo-msgdb-clear MSGDB
91 ;; elmo-msgdb-delete-msgs MSGDB NUMBERS
92 ;; elmo-msgdb-sort-by-date MSGDB
95 ;; LIST-OF-NUMBERS elmo-msgdb-list-messages MSGDB
97 ;; elmo-flag-table-load
98 ;; elmo-flag-table-set
99 ;; elmo-flag-table-get
100 ;; elmo-flag-table-save
102 ;; elmo-msgdb-append-entity MSGDB ENTITY MARK-OR-FLAGS
104 ;; ENTITY elmo-msgdb-make-entity ARGS
105 ;; VALUE elmo-msgdb-entity-field ENTITY
108 ;; OVERVIEW elmo-msgdb-get-overview MSGDB
109 ;; NUMBER-ALIST elmo-msgdb-get-number-alist MSGDB
110 ;; MARK-ALIST elmo-msgdb-get-mark-alist MSGDB
111 ;; elmo-msgdb-change-mark MSGDB BEFORE AFTER
113 ;; (for internal use?)
114 ;; LIST-OF-MARKS elmo-msgdb-unread-marks
115 ;; LIST-OF-MARKS elmo-msgdb-answered-marks
116 ;; LIST-OF-MARKS elmo-msgdb-uncached-marks
117 ;; elmo-msgdb-overview-save DIR OBJ
119 ;; elmo-msgdb-message-entity MSGDB KEY
122 ;; elmo-msgdb-overview-entity-get-references ENTITY
123 ;; elmo-msgdb-overview-entity-set-references ENTITY
124 ;; elmo-msgdb-get-parent-entity ENTITY MSGDB
125 ;; elmo-msgdb-overview-enitty-get-number ENTITY
126 ;; elmo-msgdb-overview-enitty-get-from-no-decode ENTITY
127 ;; elmo-msgdb-overview-enitty-get-from ENTITY
128 ;; elmo-msgdb-overview-enitty-get-subject-no-decode ENTITY
129 ;; elmo-msgdb-overview-enitty-get-subject ENTITY
130 ;; elmo-msgdb-overview-enitty-get-date ENTITY
131 ;; elmo-msgdb-overview-enitty-get-to ENTITY
132 ;; elmo-msgdb-overview-enitty-get-cc ENTITY
133 ;; elmo-msgdb-overview-enitty-get-size ENTITY
134 ;; elmo-msgdb-overview-enitty-get-id ENTITY
135 ;; elmo-msgdb-overview-enitty-get-extra-field ENTITY
136 ;; elmo-msgdb-overview-enitty-get-extra ENTITY
137 ;; elmo-msgdb-overview-get-entity ID MSGDB
139 ;; elmo-msgdb-killed-list-load DIR
140 ;; elmo-msgdb-killed-list-save DIR
141 ;; elmo-msgdb-append-to-killed-list FOLDER MSG
142 ;; elmo-msgdb-killed-list-length KILLED-LIST
143 ;; elmo-msgdb-max-of-killed KILLED-LIST
144 ;; elmo-msgdb-killed-message-p KILLED-LIST MSG
145 ;; elmo-living-messages MESSAGES KILLED-LIST
146 ;; elmo-msgdb-finfo-load
147 ;; elmo-msgdb-finfo-save
148 ;; elmo-msgdb-flist-load
149 ;; elmo-msgdb-flist-save
151 ;; elmo-crosspost-alist-load
152 ;; elmo-crosspost-alist-save
154 ;; elmo-msgdb-create-overview-from-buffer NUMBER SIZE TIME
155 ;; elmo-msgdb-copy-overview-entity ENTITY
156 ;; elmo-msgdb-create-overview-entity-from-file NUMBER FILE
157 ;; elmo-msgdb-overview-sort-by-date OVERVIEW
158 ;; elmo-msgdb-clear-index
160 ;; elmo-folder-get-info
161 ;; elmo-folder-get-info-max
162 ;; elmo-folder-get-info-length
163 ;; elmo-folder-get-info-unread
165 ;; elmo-msgdb-list-flagged MSGDB FLAG
166 ;; (MACRO) elmo-msgdb-do-each-entity
168 (defun elmo-load-msgdb (path)
169 "Load the MSGDB from PATH."
170 (let ((inhibit-quit t))
171 (elmo-make-msgdb (elmo-msgdb-overview-load path)
172 (elmo-msgdb-number-load path)
173 (elmo-msgdb-mark-load path)
176 (defun elmo-make-msgdb (&optional overview number-alist mark-alist path)
178 (let ((msgdb (list overview number-alist mark-alist nil path)))
179 (elmo-msgdb-make-index msgdb)
182 (defun elmo-msgdb-list-messages (msgdb-or-path)
183 "Return a list of message numbers in the msgdb.
184 If MSGDB-OR-PATH is a msgdb structure, use it as a msgdb.
185 If argument is a string, use it as a path to load message entities."
186 (mapcar 'elmo-msgdb-overview-entity-get-number
187 (if (stringp msgdb-or-path)
188 (elmo-msgdb-overview-load msgdb-or-path)
189 (elmo-msgdb-get-overview msgdb-or-path))))
191 (defsubst elmo-msgdb-mark-to-flags (mark)
193 (and (string= mark elmo-msgdb-new-mark)
195 (and (string= mark elmo-msgdb-important-mark)
197 (and (member mark (elmo-msgdb-unread-marks))
199 (and (member mark (elmo-msgdb-answered-marks))
201 (and (not (member mark (elmo-msgdb-uncached-marks)))
204 (defsubst elmo-msgdb-flags-to-mark (flags cached use-cache)
205 (cond ((memq 'new flags)
207 ((memq 'important flags)
208 elmo-msgdb-important-mark)
209 ((memq 'answered flags)
211 elmo-msgdb-answered-cached-mark
212 elmo-msgdb-answered-uncached-mark))
213 ((memq 'unread flags)
215 elmo-msgdb-unread-cached-mark
216 elmo-msgdb-unread-uncached-mark))
218 (if (or cached (not use-cache))
220 elmo-msgdb-read-uncached-mark))))
222 (defsubst elmo-msgdb-get-mark (msgdb number)
223 "Get mark string from MSGDB which corresponds to the message with NUMBER."
224 (cadr (elmo-get-hash-val (format "#%d" number)
225 (elmo-msgdb-get-mark-hashtb msgdb))))
227 (defsubst elmo-msgdb-set-mark (msgdb number mark)
228 "Set MARK of the message with NUMBER in the MSGDB.
229 if MARK is nil, mark is removed."
230 (let ((elem (elmo-get-hash-val (format "#%d" number)
231 (elmo-msgdb-get-mark-hashtb msgdb))))
234 ;; Set mark of the elem
235 (setcar (cdr elem) mark)
236 ;; Delete elem from mark-alist
237 (elmo-msgdb-set-mark-alist
239 (delq elem (elmo-msgdb-get-mark-alist msgdb)))
240 (elmo-clear-hash-val (format "#%d" number)
241 (elmo-msgdb-get-mark-hashtb msgdb)))
243 ;; Append new element.
244 (elmo-msgdb-set-mark-alist
247 (elmo-msgdb-get-mark-alist msgdb)
248 (list (setq elem (list number mark)))))
249 (elmo-set-hash-val (format "#%d" number) elem
250 (elmo-msgdb-get-mark-hashtb msgdb))))
254 (defun elmo-msgdb-get-cached (msgdb number)
255 "Return non-nil if message is cached."
256 (not (member (elmo-msgdb-get-mark msgdb number)
257 (elmo-msgdb-uncached-marks))))
259 (defun elmo-msgdb-set-cached (msgdb number cached use-cache)
260 "Set message cache status.
261 If mark is changed, return non-nil."
262 (let* ((cur-mark (elmo-msgdb-get-mark msgdb number))
264 ((string= cur-mark elmo-msgdb-important-mark)
266 ((member cur-mark (elmo-msgdb-answered-marks))
268 ((not (member cur-mark (elmo-msgdb-unread-marks)))
270 (cur-cached (elmo-file-cache-exists-p
271 (elmo-msgdb-get-field msgdb number 'message-id))))
272 (unless (eq cached cur-cached)
275 (elmo-msgdb-set-mark msgdb number
276 (if (and use-cache (not cached))
277 elmo-msgdb-read-uncached-mark)))
280 (elmo-msgdb-set-mark msgdb number
282 elmo-msgdb-answered-cached-mark
283 elmo-msgdb-answered-uncached-mark)))
285 (elmo-msgdb-set-mark msgdb number
287 elmo-msgdb-unread-cached-mark
288 elmo-msgdb-unread-uncached-mark)))))))
290 (defun elmo-msgdb-set-flag (msgdb folder number flag)
292 MSGDB is the ELMO msgdb.
293 FOLDER is a ELMO folder structure.
294 NUMBER is a message number to set flag.
295 FLAG is a symbol which is one of the following:
296 `read' ... Messages which are already read.
297 `important' ... Messages which are marked as important.
298 `answered' ... Messages which are marked as answered."
299 (let* ((cur-mark (elmo-msgdb-get-mark msgdb number))
300 (use-cache (elmo-message-use-cache-p folder number))
302 ((string= cur-mark elmo-msgdb-important-mark)
304 ((member cur-mark (elmo-msgdb-answered-marks))
306 ((not (member cur-mark (elmo-msgdb-unread-marks)))
308 (cur-cached (elmo-file-cache-exists-p
309 (elmo-msgdb-get-field msgdb number 'message-id)))
314 ((read important)) ; answered mark is overriden.
315 (t (elmo-msgdb-set-mark msgdb number
316 (if (and use-cache (not cur-cached))
317 elmo-msgdb-read-uncached-mark))
318 (setq mark-modified t))))
320 (unless (eq cur-flag 'important)
321 (elmo-msgdb-set-mark msgdb number elmo-msgdb-important-mark)
322 (setq mark-modified t)))
324 (unless (or (eq cur-flag 'answered) (eq cur-flag 'important))
325 (elmo-msgdb-set-mark msgdb number
327 elmo-msgdb-answered-cached-mark
328 elmo-msgdb-answered-uncached-mark)))
329 (setq mark-modified t)))
330 (if mark-modified (elmo-folder-set-mark-modified-internal folder t))))
332 (defun elmo-msgdb-unset-flag (msgdb folder number flag)
334 MSGDB is the ELMO msgdb.
335 FOLDER is a ELMO folder structure.
336 NUMBER is a message number to be set flag.
337 FLAG is a symbol which is one of the following:
338 `read' ... Messages which are already read.
339 `important' ... Messages which are marked as important.
340 `answered' ... Messages which are marked as answered."
341 (let* ((cur-mark (elmo-msgdb-get-mark msgdb number))
342 (use-cache (elmo-message-use-cache-p folder number))
344 ((string= cur-mark elmo-msgdb-important-mark)
346 ((member cur-mark (elmo-msgdb-answered-marks))
348 ((not (member cur-mark (elmo-msgdb-unread-marks)))
350 (cur-cached (elmo-file-cache-exists-p
351 (elmo-msgdb-get-field msgdb number 'message-id)))
355 (when (or (eq cur-flag 'read) (eq cur-flag 'answered))
356 (elmo-msgdb-set-mark msgdb number
358 elmo-msgdb-unread-cached-mark
359 elmo-msgdb-unread-uncached-mark))
360 (setq mark-modified t)))
362 (when (eq cur-flag 'important)
363 (elmo-msgdb-set-mark msgdb number nil)
364 (setq mark-modified t)))
366 (when (eq cur-flag 'answered)
367 (elmo-msgdb-set-mark msgdb number
368 (if (and use-cache (not cur-cached))
369 elmo-msgdb-read-uncached-mark))
370 (setq mark-modified t))))
371 (if mark-modified (elmo-folder-set-mark-modified-internal folder t))))
373 (defvar elmo-msgdb-unread-marks-internal nil)
374 (defsubst elmo-msgdb-unread-marks ()
375 "Return an unread mark list"
376 (or elmo-msgdb-unread-marks-internal
377 (setq elmo-msgdb-unread-marks-internal
378 (list elmo-msgdb-new-mark
379 elmo-msgdb-unread-uncached-mark
380 elmo-msgdb-unread-cached-mark))))
382 (defvar elmo-msgdb-answered-marks-internal nil)
383 (defsubst elmo-msgdb-answered-marks ()
384 "Return an answered mark list"
385 (or elmo-msgdb-answered-marks-internal
386 (setq elmo-msgdb-answered-marks-internal
387 (list elmo-msgdb-answered-cached-mark
388 elmo-msgdb-answered-uncached-mark))))
390 (defvar elmo-msgdb-uncached-marks-internal nil)
391 (defsubst elmo-msgdb-uncached-marks ()
392 (or elmo-msgdb-uncached-marks-internal
393 (setq elmo-msgdb-uncached-marks-internal
394 (list elmo-msgdb-new-mark
395 elmo-msgdb-answered-uncached-mark
396 elmo-msgdb-unread-uncached-mark
397 elmo-msgdb-read-uncached-mark))))
399 (defun elmo-msgdb-append-entity (msgdb entity &optional mark)
401 (let ((number (elmo-msgdb-overview-entity-get-number entity))
402 (message-id (elmo-msgdb-overview-entity-get-id entity)))
403 (elmo-msgdb-set-overview
405 (nconc (elmo-msgdb-get-overview msgdb)
407 (elmo-msgdb-set-number-alist
409 (nconc (elmo-msgdb-get-number-alist msgdb)
410 (list (cons number message-id))))
412 (elmo-msgdb-set-mark-alist
414 (nconc (elmo-msgdb-get-mark-alist msgdb)
415 (list (list number mark)))))
416 (elmo-msgdb-make-index
419 (list (list number mark))))))
421 (defsubst elmo-msgdb-get-number (msgdb message-id)
422 "Get number of the message which corrensponds to MESSAGE-ID from MSGDB."
423 (elmo-msgdb-overview-entity-get-number
424 (elmo-msgdb-overview-get-entity message-id msgdb)))
426 (defsubst elmo-msgdb-get-field (msgdb number field)
427 "Get FIELD value of the message with NUMBER from MSGDB."
429 (message-id (elmo-msgdb-overview-entity-get-id
430 (elmo-msgdb-overview-get-entity
432 (subject (elmo-msgdb-overview-entity-get-subject
433 (elmo-msgdb-overview-get-entity
435 (size (elmo-msgdb-overview-entity-get-size
436 (elmo-msgdb-overview-get-entity
438 (date (elmo-msgdb-overview-entity-get-date
439 (elmo-msgdb-overview-get-entity
441 (to (elmo-msgdb-overview-entity-get-to
442 (elmo-msgdb-overview-get-entity
444 (cc (elmo-msgdb-overview-entity-get-cc
445 (elmo-msgdb-overview-get-entity
448 (defun elmo-msgdb-append (msgdb msgdb-append)
449 "Return a list of messages which have duplicated message-id."
451 (elmo-msgdb-set-overview
453 (nconc (elmo-msgdb-get-overview msgdb)
454 (elmo-msgdb-get-overview msgdb-append)))
455 (elmo-msgdb-set-number-alist
457 (nconc (elmo-msgdb-get-number-alist msgdb)
458 (elmo-msgdb-get-number-alist msgdb-append)))
459 (elmo-msgdb-set-mark-alist
461 (nconc (elmo-msgdb-get-mark-alist msgdb)
462 (elmo-msgdb-get-mark-alist msgdb-append)))
463 (setq duplicates (elmo-msgdb-make-index
465 (elmo-msgdb-get-overview msgdb-append)
466 (elmo-msgdb-get-mark-alist msgdb-append)))
469 (or (elmo-msgdb-get-path msgdb)
470 (elmo-msgdb-get-path msgdb-append)))
473 (defun elmo-msgdb-merge (folder msgdb-merge)
474 "Return a list of messages which have duplicated message-id."
475 (let (msgdb duplicates)
476 (setq msgdb (or (elmo-folder-msgdb-internal folder)
477 (elmo-make-msgdb nil nil nil
478 (elmo-folder-msgdb-path folder))))
479 (elmo-msgdb-set-overview
481 (nconc (elmo-msgdb-get-overview msgdb)
482 (elmo-msgdb-get-overview msgdb-merge)))
483 (elmo-msgdb-set-number-alist
485 (nconc (elmo-msgdb-get-number-alist msgdb)
486 (elmo-msgdb-get-number-alist msgdb-merge)))
487 (elmo-msgdb-set-mark-alist
489 (nconc (elmo-msgdb-get-mark-alist msgdb)
490 (elmo-msgdb-get-mark-alist msgdb-merge)))
491 (setq duplicates (elmo-msgdb-make-index
493 (elmo-msgdb-get-overview msgdb-merge)
494 (elmo-msgdb-get-mark-alist msgdb-merge)))
497 (or (elmo-msgdb-get-path msgdb)
498 (elmo-msgdb-get-path msgdb-merge)))
499 (elmo-folder-set-msgdb-internal folder msgdb)
502 (defsubst elmo-msgdb-clear (&optional msgdb)
505 (elmo-msgdb-set-overview msgdb nil)
506 (elmo-msgdb-set-number-alist msgdb nil)
507 (elmo-msgdb-set-mark-alist msgdb nil)
508 (elmo-msgdb-set-index msgdb nil)
512 (defun elmo-msgdb-delete-msgs (msgdb msgs)
513 "Delete MSGS from MSGDB
514 content of MSGDB is changed."
515 (let* ((overview (car msgdb))
516 (number-alist (cadr msgdb))
517 (mark-alist (caddr msgdb))
518 (index (elmo-msgdb-get-index msgdb))
519 (newmsgdb (list overview number-alist mark-alist index
522 ;; remove from current database.
527 (elmo-msgdb-overview-get-entity (car msgs) newmsgdb))
529 (setq number-alist (delq (assq (car msgs) number-alist) number-alist))
530 (setq mark-alist (delq (assq (car msgs) mark-alist) mark-alist))
532 (when index (elmo-msgdb-clear-index msgdb ov-entity))
533 (setq msgs (cdr msgs)))
534 (elmo-msgdb-set-overview msgdb overview)
535 (elmo-msgdb-set-number-alist msgdb number-alist)
536 (elmo-msgdb-set-mark-alist msgdb mark-alist)
537 (elmo-msgdb-set-index msgdb index)
540 (defun elmo-msgdb-sort-by-date (msgdb)
541 (message "Sorting...")
542 (let ((overview (elmo-msgdb-get-overview msgdb)))
543 (elmo-msgdb-set-overview
545 (elmo-msgdb-overview-sort-by-date overview))
546 (message "Sorting...done")
550 (defsubst elmo-msgdb-append-element (list element)
552 ;;; (append list (list element))
553 (nconc list (list element))
557 (defsubst elmo-msgdb-get-overview (msgdb)
559 (defsubst elmo-msgdb-get-number-alist (msgdb)
561 (defsubst elmo-msgdb-get-mark-alist (msgdb)
563 ;(defsubst elmo-msgdb-get-location (msgdb)
566 (defsubst elmo-msgdb-get-index (msgdb)
569 (defsubst elmo-msgdb-get-entity-hashtb (msgdb)
572 (defsubst elmo-msgdb-get-mark-hashtb (msgdb)
575 (defsubst elmo-msgdb-get-path (msgdb)
579 ;; number <-> Message-ID handling
581 (defsubst elmo-msgdb-number-add (alist number id)
582 (let ((ret-val alist))
584 (elmo-msgdb-append-element ret-val (cons number id)))
589 (defvar elmo-flag-table-filename "flag-table")
590 (defun elmo-flag-table-load (dir)
591 "Load flag hashtable for MSGDB."
592 (let ((table (elmo-make-hash))
593 ;; For backward compatibility
594 (seen-file (expand-file-name elmo-msgdb-seen-filename dir))
596 (when (file-exists-p seen-file)
597 (setq seen-list (elmo-object-load seen-file))
598 (delete-file seen-file))
599 (dolist (msgid seen-list)
600 (elmo-set-hash-val msgid 'read table))
601 (dolist (pair (elmo-object-load
602 (expand-file-name elmo-flag-table-filename dir)))
603 (elmo-set-hash-val (car pair) (cdr pair) table))
606 (defun elmo-flag-table-set (flag-table msg-id flag)
607 (elmo-set-hash-val msg-id flag flag-table))
609 (defun elmo-flag-table-get (flag-table msg-id)
610 (elmo-get-hash-val msg-id flag-table))
612 (defun elmo-flag-table-save (dir flag-table)
614 (expand-file-name elmo-flag-table-filename dir)
617 (mapatoms (lambda (atom)
618 (setq list (cons (cons (symbol-name atom)
624 ;; persistent mark handling
627 (defun elmo-msgdb-mark-append (alist id mark)
629 (setq alist (elmo-msgdb-append-element alist
632 (defsubst elmo-msgdb-length (msgdb)
633 (length (elmo-msgdb-get-overview msgdb)))
635 (defun elmo-msgdb-flag-table (msgdb &optional flag-table)
636 ;; Make a table of msgid flag (read, answered)
637 (let ((flag-table (or flag-table (elmo-make-hash (elmo-msgdb-length msgdb))))
639 (dolist (ov (elmo-msgdb-get-overview msgdb))
640 (setq mark (elmo-msgdb-get-mark
642 (elmo-msgdb-overview-entity-get-number ov)))
646 (elmo-msgdb-overview-entity-get-id ov)
649 ((and mark (member mark (elmo-msgdb-answered-marks)))
651 (elmo-msgdb-overview-entity-get-id ov)
654 ((and mark (not (member mark
655 (elmo-msgdb-unread-marks))))
657 (elmo-msgdb-overview-entity-get-id ov)
665 (defvar elmo-msgdb-decoded-cache-hashtb nil)
666 (make-variable-buffer-local 'elmo-msgdb-decoded-cache-hashtb)
668 (defsubst elmo-msgdb-get-decoded-cache (string)
669 (if elmo-use-decoded-cache
670 (let ((hashtb (or elmo-msgdb-decoded-cache-hashtb
671 (setq elmo-msgdb-decoded-cache-hashtb
672 (elmo-make-hash 2048))))
674 (or (elmo-get-hash-val string hashtb)
679 (decode-mime-charset-string string elmo-mime-charset))
682 (decode-mime-charset-string string elmo-mime-charset)))
687 (defun elmo-multiple-field-body (name &optional boundary)
690 (std11-narrow-to-header boundary)
691 (goto-char (point-min))
692 (let ((case-fold-search t)
694 (while (re-search-forward (concat "^" name ":[ \t]*") nil t)
697 (list (buffer-substring-no-properties
698 (match-end 0) (std11-field-end))))))
701 (defun elmo-multiple-fields-body-list (field-names &optional boundary)
702 "Return list of each field-bodies of FIELD-NAMES of the message header
703 in current buffer. If BOUNDARY is not nil, it is used as message
707 (std11-narrow-to-header boundary)
708 (let* ((case-fold-search t)
710 field-name field-body)
711 (while (setq field-name (car s-rest))
712 (goto-char (point-min))
713 (while (re-search-forward (concat "^" field-name ":[ \t]*") nil t)
716 (list (buffer-substring-no-properties
717 (match-end 0) (std11-field-end))))))
718 (setq s-rest (cdr s-rest)))
721 (defsubst elmo-msgdb-remove-field-string (string)
722 (if (string-match (concat std11-field-head-regexp "[ \t]*") string)
723 (substring string (match-end 0))
726 (defsubst elmo-msgdb-get-last-message-id (string)
732 (goto-char (point-max))
733 (when (search-backward "<" nil t)
735 (if (search-forward ">" nil t)
736 (elmo-replace-in-string
737 (buffer-substring beg (point)) "\n[ \t]*" ""))))))))
739 (defun elmo-msgdb-number-load (dir)
741 (expand-file-name elmo-msgdb-number-filename dir)))
743 (defun elmo-msgdb-overview-load (dir)
745 (expand-file-name elmo-msgdb-overview-filename dir)))
747 (defun elmo-msgdb-mark-load (dir)
749 (expand-file-name elmo-msgdb-mark-filename dir)))
751 (defsubst elmo-msgdb-seen-load (dir)
752 (elmo-object-load (expand-file-name
753 elmo-msgdb-seen-filename
756 (defun elmo-msgdb-number-save (dir obj)
758 (expand-file-name elmo-msgdb-number-filename dir)
761 (defun elmo-msgdb-mark-save (dir obj)
763 (expand-file-name elmo-msgdb-mark-filename dir)
766 (defun elmo-msgdb-change-mark (msgdb before after)
767 "Set the BEFORE marks to AFTER."
768 (let ((mark-alist (elmo-msgdb-get-mark-alist msgdb))
771 (setq entity (car mark-alist))
772 (when (string= (cadr entity) before)
773 (setcar (cdr entity) after))
774 (setq mark-alist (cdr mark-alist)))))
776 (defsubst elmo-msgdb-mark (flag cached &optional new)
782 elmo-msgdb-read-uncached-mark))
784 elmo-msgdb-important-mark)
787 elmo-msgdb-answered-cached-mark
788 elmo-msgdb-answered-uncached-mark))
791 elmo-msgdb-unread-cached-mark
792 elmo-msgdb-new-mark)))
796 elmo-msgdb-unread-cached-mark
797 elmo-msgdb-unread-uncached-mark))
799 elmo-msgdb-important-mark)
802 elmo-msgdb-answered-cached-mark
803 elmo-msgdb-answered-uncached-mark)))))
805 (defsubst elmo-msgdb-overview-save (dir overview)
807 (expand-file-name elmo-msgdb-overview-filename dir)
810 (defun elmo-msgdb-match-condition-primitive (condition mark entity numbers)
812 (let ((key (elmo-filter-key condition))
816 ((string= key "last")
817 (setq result (<= (length (memq
818 (elmo-msgdb-overview-entity-get-number
821 (string-to-int (elmo-filter-value condition)))))
822 ((string= key "first")
826 (elmo-msgdb-overview-entity-get-number
829 (string-to-int (elmo-filter-value condition)))))
830 ((string= key "flag")
833 ((string= (elmo-filter-value condition) "any")
835 (string= mark elmo-msgdb-read-uncached-mark))))
836 ((string= (elmo-filter-value condition) "digest")
838 (string= mark elmo-msgdb-read-uncached-mark)
839 (string= mark elmo-msgdb-answered-cached-mark)
840 (string= mark elmo-msgdb-answered-uncached-mark))))
841 ;; (member mark (append (elmo-msgdb-answered-marks)
842 ;; (list elmo-msgdb-important-mark)
843 ;; (elmo-msgdb-unread-marks))))
844 ((string= (elmo-filter-value condition) "unread")
845 (member mark (elmo-msgdb-unread-marks)))
846 ((string= (elmo-filter-value condition) "important")
847 (string= mark elmo-msgdb-important-mark))
848 ((string= (elmo-filter-value condition) "answered")
849 (member mark (elmo-msgdb-answered-marks))))))
850 ((string= key "from")
851 (setq result (string-match
852 (elmo-filter-value condition)
853 (elmo-msgdb-overview-entity-get-from entity))))
854 ((string= key "subject")
855 (setq result (string-match
856 (elmo-filter-value condition)
857 (elmo-msgdb-overview-entity-get-subject entity))))
859 (setq result (string-match
860 (elmo-filter-value condition)
861 (elmo-msgdb-overview-entity-get-to entity))))
863 (setq result (string-match
864 (elmo-filter-value condition)
865 (elmo-msgdb-overview-entity-get-cc entity))))
866 ((or (string= key "since")
867 (string= key "before"))
868 (let ((field-date (elmo-date-make-sortable-string
870 (elmo-msgdb-overview-entity-get-date entity)
871 (current-time-zone) nil)))
873 (elmo-date-make-sortable-string
874 (elmo-date-get-datevec
875 (elmo-filter-value condition)))))
876 (setq result (if (string= key "since")
877 (or (string= specified-date field-date)
878 (string< specified-date field-date))
879 (string< field-date specified-date)))))
880 ((member key elmo-msgdb-extra-fields)
881 (let ((extval (elmo-msgdb-overview-entity-get-extra-field entity key)))
882 (when (stringp extval)
883 (setq result (string-match
884 (elmo-filter-value condition)
887 (throw 'unresolved condition)))
888 (if (eq (elmo-filter-type condition) 'unmatch)
892 (defun elmo-msgdb-match-condition-internal (condition mark entity numbers)
895 (elmo-msgdb-match-condition-primitive condition mark entity numbers))
896 ((eq (car condition) 'and)
897 (let ((lhs (elmo-msgdb-match-condition-internal (nth 1 condition)
898 mark entity numbers)))
900 ((elmo-filter-condition-p lhs)
901 (let ((rhs (elmo-msgdb-match-condition-internal
902 (nth 2 condition) mark entity numbers)))
903 (cond ((elmo-filter-condition-p rhs)
908 (elmo-msgdb-match-condition-internal (nth 2 condition)
909 mark entity numbers)))))
910 ((eq (car condition) 'or)
911 (let ((lhs (elmo-msgdb-match-condition-internal (nth 1 condition)
912 mark entity numbers)))
914 ((elmo-filter-condition-p lhs)
915 (let ((rhs (elmo-msgdb-match-condition-internal (nth 2 condition)
916 mark entity numbers)))
917 (cond ((elmo-filter-condition-p rhs)
926 (elmo-msgdb-match-condition-internal (nth 2 condition)
927 mark entity numbers)))))))
929 (defun elmo-msgdb-match-condition (msgdb condition number numbers)
930 "Check whether the condition of the message is satisfied or not.
931 MSGDB is the msgdb to search from.
932 CONDITION is the search condition.
933 NUMBER is the message number to check.
934 NUMBERS is the target message number list.
935 Return CONDITION itself if no entity exists in msgdb."
936 (let ((entity (elmo-msgdb-overview-get-entity number msgdb)))
938 (elmo-msgdb-match-condition-internal condition
939 (elmo-msgdb-get-mark msgdb number)
943 (defsubst elmo-msgdb-set-overview (msgdb overview)
944 (setcar msgdb overview))
946 (defsubst elmo-msgdb-set-number-alist (msgdb number-alist)
947 (setcar (cdr msgdb) number-alist))
949 (defsubst elmo-msgdb-set-mark-alist (msgdb mark-alist)
950 (setcar (cddr msgdb) mark-alist))
952 (defsubst elmo-msgdb-set-index (msgdb index)
953 (setcar (cdddr msgdb) index))
955 (defsubst elmo-msgdb-set-path (msgdb path)
956 (setcar (cddddr msgdb) path))
958 (defsubst elmo-msgdb-overview-entity-get-references (entity)
959 (and entity (aref (cdr entity) 1)))
961 (defsubst elmo-msgdb-overview-entity-set-references (entity references)
962 (and entity (aset (cdr entity) 1 references))
965 ;; entity -> parent-entity
966 (defsubst elmo-msgdb-overview-get-parent-entity (entity database)
967 (setq entity (elmo-msgdb-overview-entity-get-references entity))
968 ;; entity is parent-id.
969 (and entity (assoc entity database)))
971 (defsubst elmo-msgdb-get-parent-entity (entity msgdb)
972 (setq entity (elmo-msgdb-overview-entity-get-references entity))
973 ;; entity is parent-id.
974 (and entity (elmo-msgdb-overview-get-entity entity msgdb)))
976 (defsubst elmo-msgdb-overview-entity-get-number (entity)
977 (and entity (aref (cdr entity) 0)))
979 (defsubst elmo-msgdb-overview-entity-get-from-no-decode (entity)
980 (and entity (aref (cdr entity) 2)))
982 (defsubst elmo-msgdb-overview-entity-get-from (entity)
984 (aref (cdr entity) 2)
985 (elmo-msgdb-get-decoded-cache (aref (cdr entity) 2))))
987 (defsubst elmo-msgdb-overview-entity-set-number (entity number)
988 (and entity (aset (cdr entity) 0 number))
990 ;;;(setcar (cadr entity) number) entity)
992 (defsubst elmo-msgdb-overview-entity-set-from (entity from)
993 (and entity (aset (cdr entity) 2 from))
996 (defsubst elmo-msgdb-overview-entity-get-subject (entity)
998 (aref (cdr entity) 3)
999 (elmo-msgdb-get-decoded-cache (aref (cdr entity) 3))))
1001 (defsubst elmo-msgdb-overview-entity-get-subject-no-decode (entity)
1002 (and entity (aref (cdr entity) 3)))
1004 (defsubst elmo-msgdb-overview-entity-set-subject (entity subject)
1005 (and entity (aset (cdr entity) 3 subject))
1008 (defsubst elmo-msgdb-overview-entity-get-date (entity)
1009 (and entity (aref (cdr entity) 4)))
1011 (defsubst elmo-msgdb-overview-entity-set-date (entity date)
1012 (and entity (aset (cdr entity) 4 date))
1015 (defsubst elmo-msgdb-overview-entity-get-to (entity)
1016 (and entity (aref (cdr entity) 5)))
1018 (defsubst elmo-msgdb-overview-entity-get-cc (entity)
1019 (and entity (aref (cdr entity) 6)))
1021 (defsubst elmo-msgdb-overview-entity-get-size (entity)
1022 (and entity (aref (cdr entity) 7)))
1024 (defsubst elmo-msgdb-overview-entity-set-size (entity size)
1025 (and entity (aset (cdr entity) 7 size))
1028 (defsubst elmo-msgdb-overview-entity-get-id (entity)
1029 (and entity (car entity)))
1031 (defsubst elmo-msgdb-overview-entity-get-extra-field (entity field-name)
1032 (let ((field-name (downcase field-name))
1033 (extra (and entity (aref (cdr entity) 8))))
1035 (cdr (assoc field-name extra)))))
1037 (defsubst elmo-msgdb-overview-entity-set-extra-field (entity field-name value)
1038 (let ((field-name (downcase field-name))
1039 (extras (and entity (aref (cdr entity) 8)))
1041 (if (setq extra (assoc field-name extras))
1042 (setcdr extra value)
1043 (elmo-msgdb-overview-entity-set-extra
1045 (cons (cons field-name value) extras)))))
1047 (defsubst elmo-msgdb-overview-entity-get-extra (entity)
1048 (and entity (aref (cdr entity) 8)))
1050 (defsubst elmo-msgdb-overview-entity-set-extra (entity extra)
1051 (and entity (aset (cdr entity) 8 extra))
1055 (defsubst elmo-msgdb-message-entity (msgdb key)
1057 (cond ((stringp key) key)
1058 ((numberp key) (format "#%d" key)))
1059 (elmo-msgdb-get-entity-hashtb msgdb)))
1061 (defun elmo-msgdb-make-message-entity (&rest args)
1062 "Make an message entity."
1063 (cons (plist-get args :message-id)
1064 (vector (plist-get args :number)
1065 (plist-get args :references)
1066 (plist-get args :from)
1067 (plist-get args :subject)
1068 (plist-get args :date)
1069 (plist-get args :to)
1070 (plist-get args :cc)
1071 (plist-get args :size)
1072 (plist-get args :extra))))
1074 (defsubst elmo-msgdb-message-entity-field (entity field &optional decode)
1078 (to (aref (cdr entity) 5))
1079 (cc (aref (cdr entity) 6))
1080 (date (aref (cdr entity) 4))
1081 (subject (aref (cdr entity) 3))
1082 (from (aref (cdr entity) 2))
1083 (message-id (car entity))
1084 (references (aref (cdr entity) 1))
1085 (size (aref (cdr entity) 7))
1086 (t (cdr (assoc (symbol-name field) (aref (cdr entity) 8)))))))
1087 (if (and decode (memq field '(from subject)))
1088 (elmo-msgdb-get-decoded-cache field-value)
1091 (defsubst elmo-msgdb-message-entity-set-field (entity field value)
1094 (to (aset (cdr entity) 5 value))
1095 (cc (aset (cdr entity) 6 value))
1096 (date (aset (cdr entity) 4 value))
1097 (subject (aset (cdr entity) 3 value))
1098 (from (aset (cdr entity) 2 value))
1099 (message-id (setcar entity value))
1100 (references (aset (cdr entity) 1 value))
1101 (size (aset (cdr entity) 7 value))
1103 (let ((extras (and entity (aref (cdr entity) 8)))
1105 (if (setq extra (assoc field extras))
1106 (setcdr extra value)
1107 (aset (cdr entity) 8 (cons (cons (symbol-name field)
1108 value) extras))))))))
1111 (defun elmo-msgdb-overview-get-entity (id msgdb)
1113 (let ((ht (elmo-msgdb-get-entity-hashtb msgdb)))
1115 (if (stringp id) ;; ID is message-id
1116 (elmo-get-hash-val id ht)
1117 (elmo-get-hash-val (format "#%d" id) ht))))))
1120 ;; deleted message handling
1122 (defun elmo-msgdb-killed-list-load (dir)
1124 (expand-file-name elmo-msgdb-killed-filename dir)
1127 (defun elmo-msgdb-killed-list-save (dir killed-list)
1129 (expand-file-name elmo-msgdb-killed-filename dir)
1132 (defun elmo-msgdb-killed-message-p (killed-list msg)
1133 (elmo-number-set-member msg killed-list))
1135 (defun elmo-msgdb-set-as-killed (killed-list msg)
1136 (elmo-number-set-append killed-list msg))
1138 (defun elmo-msgdb-killed-list-length (killed-list)
1139 (let ((killed killed-list)
1142 (if (consp (car killed))
1143 (setq ret-val (+ ret-val 1 (- (cdar killed) (caar killed))))
1144 (setq ret-val (+ ret-val 1)))
1145 (setq killed (cdr killed)))
1148 (defun elmo-msgdb-max-of-killed (killed-list)
1149 (let ((klist killed-list)
1155 (if (consp (car klist))
1159 (setq klist (cdr klist)))
1162 (defun elmo-living-messages (messages killed-list)
1165 (mapcar (lambda (number)
1166 (unless (elmo-number-set-member number killed-list)
1171 (defun elmo-msgdb-finfo-load ()
1172 (elmo-object-load (expand-file-name
1173 elmo-msgdb-finfo-filename
1174 elmo-msgdb-directory)
1175 elmo-mime-charset t))
1177 (defun elmo-msgdb-finfo-save (finfo)
1178 (elmo-object-save (expand-file-name
1179 elmo-msgdb-finfo-filename
1180 elmo-msgdb-directory)
1181 finfo elmo-mime-charset))
1183 (defun elmo-msgdb-flist-load (fname)
1184 (let ((flist-file (expand-file-name
1185 elmo-msgdb-flist-filename
1187 (elmo-safe-filename fname)
1188 (expand-file-name "folder" elmo-msgdb-directory)))))
1189 (elmo-object-load flist-file elmo-mime-charset t)))
1191 (defun elmo-msgdb-flist-save (fname flist)
1192 (let ((flist-file (expand-file-name
1193 elmo-msgdb-flist-filename
1195 (elmo-safe-filename fname)
1196 (expand-file-name "folder" elmo-msgdb-directory)))))
1197 (elmo-object-save flist-file flist elmo-mime-charset)))
1199 (defun elmo-crosspost-alist-load ()
1200 (elmo-object-load (expand-file-name
1201 elmo-crosspost-alist-filename
1202 elmo-msgdb-directory)
1205 (defun elmo-crosspost-alist-save (alist)
1206 (elmo-object-save (expand-file-name
1207 elmo-crosspost-alist-filename
1208 elmo-msgdb-directory)
1211 (defun elmo-msgdb-get-message-id-from-buffer ()
1212 (let ((msgid (elmo-field-body "message-id")))
1214 (if (string-match "<\\(.+\\)>$" msgid)
1216 (concat "<" msgid ">")) ; Invaild message-id.
1217 ;; no message-id, so put dummy msgid.
1218 (concat "<" (timezone-make-date-sortable
1219 (elmo-field-body "date"))
1220 (nth 1 (eword-extract-address-components
1221 (or (elmo-field-body "from") "nobody"))) ">"))))
1223 (defsubst elmo-msgdb-create-overview-from-buffer (number &optional size time)
1224 "Create overview entity from current buffer.
1225 Header region is supposed to be narrowed."
1227 (let ((extras elmo-msgdb-extra-fields)
1228 (default-mime-charset default-mime-charset)
1229 message-id references from subject to cc date
1230 extra field-body charset)
1231 (elmo-set-buffer-multibyte default-enable-multibyte-characters)
1232 (setq message-id (elmo-msgdb-get-message-id-from-buffer))
1233 (and (setq charset (cdr (assoc "charset" (mime-read-Content-Type))))
1234 (setq charset (intern-soft charset))
1235 (setq default-mime-charset charset))
1237 (or (elmo-msgdb-get-last-message-id
1238 (elmo-field-body "in-reply-to"))
1239 (elmo-msgdb-get-last-message-id
1240 (elmo-field-body "references"))))
1241 (setq from (elmo-replace-in-string
1242 (elmo-mime-string (or (elmo-field-body "from")
1245 subject (elmo-replace-in-string
1246 (elmo-mime-string (or (elmo-field-body "subject")
1249 (setq date (or (elmo-field-body "date") time))
1250 (setq to (mapconcat 'identity (elmo-multiple-field-body "to") ","))
1251 (setq cc (mapconcat 'identity (elmo-multiple-field-body "cc") ","))
1253 (if (setq size (elmo-field-body "content-length"))
1254 (setq size (string-to-int size))
1255 (setq size 0)));; No mean...
1257 (if (setq field-body (elmo-field-body (car extras)))
1258 (setq extra (cons (cons (downcase (car extras))
1259 field-body) extra)))
1260 (setq extras (cdr extras)))
1261 (cons message-id (vector number references
1262 from subject date to cc
1266 (defun elmo-msgdb-copy-overview-entity (entity)
1268 (copy-sequence (cdr entity))))
1270 (defsubst elmo-msgdb-insert-file-header (file)
1271 "Insert the header of the article."
1273 insert-file-contents-pre-hook ; To avoid autoconv-xmas...
1274 insert-file-contents-post-hook
1276 (when (file-exists-p file)
1277 ;; Read until header separator is found.
1278 (while (and (eq elmo-msgdb-file-header-chop-length
1280 (insert-file-contents-as-binary
1282 (incf beg elmo-msgdb-file-header-chop-length))))
1283 (prog1 (not (search-forward "\n\n" nil t))
1284 (goto-char (point-max))))))))
1286 (defsubst elmo-msgdb-create-overview-entity-from-file (number file)
1287 (let (insert-file-contents-pre-hook ; To avoid autoconv-xmas...
1288 insert-file-contents-post-hook header-end
1289 (attrib (file-attributes file))
1292 (if (not (file-exists-p file))
1294 (setq size (nth 7 attrib))
1295 (setq mtime (timezone-make-date-arpa-standard
1296 (current-time-string (nth 5 attrib)) (current-time-zone)))
1297 ;; insert header from file.
1300 (elmo-msgdb-insert-file-header file)
1301 (error (throw 'done nil)))
1302 (goto-char (point-min))
1304 (if (re-search-forward "\\(^--.*$\\)\\|\\(\n\n\\)" nil t)
1307 (narrow-to-region (point-min) header-end)
1308 (elmo-msgdb-create-overview-from-buffer number size mtime))))))
1310 (defun elmo-msgdb-overview-sort-by-date (overview)
1316 (timezone-make-date-sortable
1317 (elmo-msgdb-overview-entity-get-date x))
1318 (timezone-make-date-sortable
1319 (elmo-msgdb-overview-entity-get-date y)))
1322 (defun elmo-msgdb-clear-index (msgdb entity)
1323 (let ((ehash (elmo-msgdb-get-entity-hashtb msgdb))
1324 (mhash (elmo-msgdb-get-mark-hashtb msgdb))
1326 (when (and entity ehash)
1327 (and (setq number (elmo-msgdb-overview-entity-get-number entity))
1328 (elmo-clear-hash-val (format "#%d" number) ehash))
1329 (and (car entity) ;; message-id
1330 (elmo-clear-hash-val (car entity) ehash)))
1331 (when (and entity mhash)
1332 (and (setq number (elmo-msgdb-overview-entity-get-number entity))
1333 (elmo-clear-hash-val (format "#%d" number) mhash)))))
1335 (defun elmo-msgdb-make-index-return (msgdb &optional overview mark-alist)
1336 "Append OVERVIEW and MARK-ALIST to the index of MSGDB.
1337 If OVERVIEW and MARK-ALIST are nil, make index for current MSGDB.
1338 Return the updated INDEX."
1340 (let* ((overview (or overview (elmo-msgdb-get-overview msgdb)))
1341 (mark-alist (or mark-alist (elmo-msgdb-get-mark-alist msgdb)))
1342 (index (elmo-msgdb-get-index msgdb))
1343 (ehash (or (car index) ;; append
1344 (elmo-make-hash (length overview))))
1345 (mhash (or (cdr index) ;; append
1346 (elmo-make-hash (length overview)))))
1348 ;; key is message-id
1350 (elmo-set-hash-val (caar overview) (car overview) ehash))
1354 (elmo-msgdb-overview-entity-get-number (car overview)))
1355 (car overview) ehash)
1356 (setq overview (cdr overview)))
1360 (format "#%d" (car (car mark-alist)))
1361 (car mark-alist) mhash)
1362 (setq mark-alist (cdr mark-alist)))
1363 (setq index (or index (cons ehash mhash)))
1364 (elmo-msgdb-set-index msgdb index)
1367 (defun elmo-msgdb-make-index (msgdb &optional overview mark-alist)
1368 "Append OVERVIEW and MARK-ALIST to the index of MSGDB.
1369 If OVERVIEW and MARK-ALIST are nil, make index for current MSGDB.
1370 Return a list of message numbers which have duplicated message-ids."
1372 (let* ((overview (or overview (elmo-msgdb-get-overview msgdb)))
1373 (mark-alist (or mark-alist (elmo-msgdb-get-mark-alist msgdb)))
1374 (index (elmo-msgdb-get-index msgdb))
1375 (ehash (or (car index) ;; append
1376 (elmo-make-hash (length overview))))
1377 (mhash (or (cdr index) ;; append
1378 (elmo-make-hash (length overview))))
1381 ;; key is message-id
1382 (if (elmo-get-hash-val (caar overview) ehash) ; duplicated.
1383 (setq duplicates (cons
1384 (elmo-msgdb-overview-entity-get-number
1388 (elmo-set-hash-val (caar overview) (car overview) ehash))
1392 (elmo-msgdb-overview-entity-get-number (car overview)))
1393 (car overview) ehash)
1394 (setq overview (cdr overview)))
1398 (format "#%d" (car (car mark-alist)))
1399 (car mark-alist) mhash)
1400 (setq mark-alist (cdr mark-alist)))
1401 (setq index (or index (cons ehash mhash)))
1402 (elmo-msgdb-set-index msgdb index)
1405 (defsubst elmo-folder-get-info (folder &optional hashtb)
1406 (elmo-get-hash-val folder
1407 (or hashtb elmo-folder-info-hashtb)))
1409 (defun elmo-folder-get-info-max (folder)
1410 "Get folder info from cache."
1411 (nth 3 (elmo-folder-get-info folder)))
1413 (defun elmo-folder-get-info-length (folder)
1414 (nth 2 (elmo-folder-get-info folder)))
1416 (defun elmo-folder-get-info-unread (folder)
1417 (nth 1 (elmo-folder-get-info folder)))
1419 (defsubst elmo-msgdb-location-load (dir)
1422 elmo-msgdb-location-filename
1425 (defsubst elmo-msgdb-location-add (alist number location)
1426 (let ((ret-val alist))
1428 (elmo-msgdb-append-element ret-val (cons number location)))
1431 (defsubst elmo-msgdb-location-save (dir alist)
1434 elmo-msgdb-location-filename
1437 (defun elmo-msgdb-list-flagged (msgdb flag)
1438 (let ((case-fold-search nil)
1439 mark-regexp matched)
1442 (setq mark-regexp (regexp-quote elmo-msgdb-new-mark)))
1444 (setq mark-regexp (elmo-regexp-opt (elmo-msgdb-unread-marks))))
1446 (setq mark-regexp (elmo-regexp-opt (elmo-msgdb-answered-marks))))
1448 (setq mark-regexp (regexp-quote elmo-msgdb-important-mark)))
1450 (setq mark-regexp (elmo-regexp-opt (elmo-msgdb-unread-marks))))
1452 (setq mark-regexp (elmo-regexp-opt
1453 (append (elmo-msgdb-unread-marks)
1454 (list elmo-msgdb-important-mark)))))
1456 (setq mark-regexp (elmo-regexp-opt
1458 (elmo-msgdb-unread-marks)
1459 (elmo-msgdb-answered-marks)
1460 (list elmo-msgdb-important-mark))))))
1463 (dolist (number (elmo-msgdb-list-messages msgdb))
1464 (let ((mark (elmo-msgdb-get-mark msgdb number)))
1465 (unless (and mark (string-match mark-regexp mark))
1466 (setq matched (cons number matched)))))
1467 (dolist (elem (elmo-msgdb-get-mark-alist msgdb))
1468 (if (string-match mark-regexp (cadr elem))
1469 (setq matched (cons (car elem) matched))))))
1473 (product-provide (provide 'elmo-msgdb) (require 'elmo-version))
1475 ;;; elmo-msgdb.el ends here