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-clear-index
159 ;; elmo-folder-get-info
160 ;; elmo-folder-get-info-max
161 ;; elmo-folder-get-info-length
162 ;; elmo-folder-get-info-unread
164 ;; elmo-msgdb-list-flagged MSGDB FLAG
165 ;; (MACRO) elmo-msgdb-do-each-entity
167 (defun elmo-load-msgdb (path)
168 "Load the MSGDB from PATH."
169 (let ((inhibit-quit t))
170 (elmo-make-msgdb (elmo-msgdb-overview-load path)
171 (elmo-msgdb-number-load path)
172 (elmo-msgdb-mark-load path)
175 (defun elmo-make-msgdb (&optional overview number-alist mark-alist path)
177 (let ((msgdb (list overview number-alist mark-alist nil path)))
178 (elmo-msgdb-make-index msgdb)
181 (defun elmo-msgdb-list-messages (msgdb)
182 "Return a list of message numbers in the MSGDB."
183 (mapcar 'elmo-msgdb-overview-entity-get-number
184 (elmo-msgdb-get-overview msgdb)))
186 (defsubst elmo-msgdb-mark-to-flags (mark)
188 (and (string= mark elmo-msgdb-new-mark)
190 (and (string= mark elmo-msgdb-important-mark)
192 (and (member mark (elmo-msgdb-unread-marks))
194 (and (member mark (elmo-msgdb-answered-marks))
196 (and (not (member mark (elmo-msgdb-uncached-marks)))
199 (defsubst elmo-msgdb-flags-to-mark (flags cached use-cache)
200 (cond ((memq 'new flags)
202 ((memq 'important flags)
203 elmo-msgdb-important-mark)
204 ((memq 'answered flags)
206 elmo-msgdb-answered-cached-mark
207 elmo-msgdb-answered-uncached-mark))
208 ((memq 'unread flags)
210 elmo-msgdb-unread-cached-mark
211 elmo-msgdb-unread-uncached-mark))
213 (if (or cached (not use-cache))
215 elmo-msgdb-read-uncached-mark))))
217 (defsubst elmo-msgdb-get-mark (msgdb number)
218 "Get mark string from MSGDB which corresponds to the message with NUMBER."
219 (cadr (elmo-get-hash-val (format "#%d" number)
220 (elmo-msgdb-get-mark-hashtb msgdb))))
222 (defsubst elmo-msgdb-set-mark (msgdb number mark)
223 "Set MARK of the message with NUMBER in the MSGDB.
224 if MARK is nil, mark is removed."
225 (let ((elem (elmo-get-hash-val (format "#%d" number)
226 (elmo-msgdb-get-mark-hashtb msgdb))))
229 ;; Set mark of the elem
230 (setcar (cdr elem) mark)
231 ;; Delete elem from mark-alist
232 (elmo-msgdb-set-mark-alist
234 (delq elem (elmo-msgdb-get-mark-alist msgdb)))
235 (elmo-clear-hash-val (format "#%d" number)
236 (elmo-msgdb-get-mark-hashtb msgdb)))
238 ;; Append new element.
239 (elmo-msgdb-set-mark-alist
242 (elmo-msgdb-get-mark-alist msgdb)
243 (list (setq elem (list number mark)))))
244 (elmo-set-hash-val (format "#%d" number) elem
245 (elmo-msgdb-get-mark-hashtb msgdb))))
249 (defun elmo-msgdb-get-cached (msgdb number)
250 "Return non-nil if message is cached."
251 (not (member (elmo-msgdb-get-mark msgdb number)
252 (elmo-msgdb-uncached-marks))))
254 (defun elmo-msgdb-set-cached (msgdb number cached use-cache)
255 "Set message cache status.
256 If mark is changed, return non-nil."
257 (let* ((cur-mark (elmo-msgdb-get-mark msgdb number))
259 ((string= cur-mark elmo-msgdb-important-mark)
261 ((member cur-mark (elmo-msgdb-answered-marks))
263 ((not (member cur-mark (elmo-msgdb-unread-marks)))
265 (cur-cached (elmo-file-cache-exists-p
266 (elmo-msgdb-get-field msgdb number 'message-id))))
267 (unless (eq cached cur-cached)
270 (elmo-msgdb-set-mark msgdb number
271 (if (and use-cache (not cached))
272 elmo-msgdb-read-uncached-mark)))
275 (elmo-msgdb-set-mark msgdb number
277 elmo-msgdb-answered-cached-mark
278 elmo-msgdb-answered-uncached-mark)))
280 (elmo-msgdb-set-mark msgdb number
282 elmo-msgdb-unread-cached-mark
283 elmo-msgdb-unread-uncached-mark)))))))
285 (defsubst elmo-msgdb-flags (msgdb number)
286 (elmo-msgdb-mark-to-flags (elmo-msgdb-get-mark msgdb number)))
288 (defun elmo-msgdb-set-flag (msgdb folder number flag)
290 MSGDB is the ELMO msgdb.
291 FOLDER is a ELMO folder structure.
292 NUMBER is a message number to set flag.
293 FLAG is a symbol which is one of the following:
294 `read' ... Messages which are already read.
295 `important' ... Messages which are marked as important.
296 `answered' ... Messages which are marked as answered."
297 (let* ((cur-mark (elmo-msgdb-get-mark msgdb number))
298 (use-cache (elmo-message-use-cache-p folder number))
300 ((string= cur-mark elmo-msgdb-important-mark)
302 ((member cur-mark (elmo-msgdb-answered-marks))
304 ((not (member cur-mark (elmo-msgdb-unread-marks)))
306 (cur-cached (elmo-file-cache-exists-p
307 (elmo-msgdb-get-field msgdb number 'message-id)))
312 ((read important)) ; answered mark is overriden.
313 (t (elmo-msgdb-set-mark msgdb number
314 (if (and use-cache (not cur-cached))
315 elmo-msgdb-read-uncached-mark))
316 (setq mark-modified t))))
318 (unless (eq cur-flag 'important)
319 (elmo-msgdb-set-mark msgdb number elmo-msgdb-important-mark)
320 (setq mark-modified t)))
322 (unless (or (eq cur-flag 'answered) (eq cur-flag 'important))
323 (elmo-msgdb-set-mark msgdb number
325 elmo-msgdb-answered-cached-mark
326 elmo-msgdb-answered-uncached-mark)))
327 (setq mark-modified t)))
328 (if mark-modified (elmo-folder-set-mark-modified-internal folder t))))
330 (defun elmo-msgdb-unset-flag (msgdb folder number flag)
332 MSGDB is the ELMO msgdb.
333 FOLDER is a ELMO folder structure.
334 NUMBER is a message number to be set flag.
335 FLAG is a symbol which is one of the following:
336 `read' ... Messages which are already read.
337 `important' ... Messages which are marked as important.
338 `answered' ... Messages which are marked as answered."
339 (let* ((cur-mark (elmo-msgdb-get-mark msgdb number))
340 (use-cache (elmo-message-use-cache-p folder number))
342 ((string= cur-mark elmo-msgdb-important-mark)
344 ((member cur-mark (elmo-msgdb-answered-marks))
346 ((not (member cur-mark (elmo-msgdb-unread-marks)))
348 (cur-cached (elmo-file-cache-exists-p
349 (elmo-msgdb-get-field msgdb number 'message-id)))
353 (when (or (eq cur-flag 'read) (eq cur-flag 'answered))
354 (elmo-msgdb-set-mark msgdb number
356 elmo-msgdb-unread-cached-mark
357 elmo-msgdb-unread-uncached-mark))
358 (setq mark-modified t)))
360 (when (eq cur-flag 'important)
361 (elmo-msgdb-set-mark msgdb number nil)
362 (setq mark-modified t)))
364 (when (eq cur-flag 'answered)
365 (elmo-msgdb-set-mark msgdb number
366 (if (and use-cache (not cur-cached))
367 elmo-msgdb-read-uncached-mark))
368 (setq mark-modified t))))
369 (if mark-modified (elmo-folder-set-mark-modified-internal folder t))))
371 (defvar elmo-msgdb-unread-marks-internal nil)
372 (defsubst elmo-msgdb-unread-marks ()
373 "Return an unread mark list"
374 (or elmo-msgdb-unread-marks-internal
375 (setq elmo-msgdb-unread-marks-internal
376 (list elmo-msgdb-new-mark
377 elmo-msgdb-unread-uncached-mark
378 elmo-msgdb-unread-cached-mark))))
380 (defvar elmo-msgdb-answered-marks-internal nil)
381 (defsubst elmo-msgdb-answered-marks ()
382 "Return an answered mark list"
383 (or elmo-msgdb-answered-marks-internal
384 (setq elmo-msgdb-answered-marks-internal
385 (list elmo-msgdb-answered-cached-mark
386 elmo-msgdb-answered-uncached-mark))))
388 (defvar elmo-msgdb-uncached-marks-internal nil)
389 (defsubst elmo-msgdb-uncached-marks ()
390 (or elmo-msgdb-uncached-marks-internal
391 (setq elmo-msgdb-uncached-marks-internal
392 (list elmo-msgdb-new-mark
393 elmo-msgdb-answered-uncached-mark
394 elmo-msgdb-unread-uncached-mark
395 elmo-msgdb-read-uncached-mark))))
397 (defun elmo-msgdb-append-entity (msgdb entity &optional mark)
399 (let ((number (elmo-msgdb-overview-entity-get-number entity))
400 (message-id (elmo-msgdb-overview-entity-get-id entity)))
401 (elmo-msgdb-set-overview
403 (nconc (elmo-msgdb-get-overview msgdb)
405 (elmo-msgdb-set-number-alist
407 (nconc (elmo-msgdb-get-number-alist msgdb)
408 (list (cons number message-id))))
410 (elmo-msgdb-set-mark-alist
412 (nconc (elmo-msgdb-get-mark-alist msgdb)
413 (list (list number mark)))))
414 (elmo-msgdb-make-index
417 (list (list number mark))))))
419 (defsubst elmo-msgdb-get-number (msgdb message-id)
420 "Get number of the message which corrensponds to MESSAGE-ID from MSGDB."
421 (elmo-msgdb-overview-entity-get-number
422 (elmo-msgdb-overview-get-entity message-id msgdb)))
424 (defsubst elmo-msgdb-get-field (msgdb number field)
425 "Get FIELD value of the message with NUMBER from MSGDB."
427 (message-id (elmo-msgdb-overview-entity-get-id
428 (elmo-msgdb-overview-get-entity
430 (subject (elmo-msgdb-overview-entity-get-subject
431 (elmo-msgdb-overview-get-entity
433 (size (elmo-msgdb-overview-entity-get-size
434 (elmo-msgdb-overview-get-entity
436 (date (elmo-msgdb-overview-entity-get-date
437 (elmo-msgdb-overview-get-entity
439 (to (elmo-msgdb-overview-entity-get-to
440 (elmo-msgdb-overview-get-entity
442 (cc (elmo-msgdb-overview-entity-get-cc
443 (elmo-msgdb-overview-get-entity
446 (defun elmo-msgdb-append (msgdb msgdb-append)
447 "Return a list of messages which have duplicated message-id."
449 (elmo-msgdb-set-overview
451 (nconc (elmo-msgdb-get-overview msgdb)
452 (elmo-msgdb-get-overview msgdb-append)))
453 (elmo-msgdb-set-number-alist
455 (nconc (elmo-msgdb-get-number-alist msgdb)
456 (elmo-msgdb-get-number-alist msgdb-append)))
457 (elmo-msgdb-set-mark-alist
459 (nconc (elmo-msgdb-get-mark-alist msgdb)
460 (elmo-msgdb-get-mark-alist msgdb-append)))
461 (setq duplicates (elmo-msgdb-make-index
463 (elmo-msgdb-get-overview msgdb-append)
464 (elmo-msgdb-get-mark-alist msgdb-append)))
467 (or (elmo-msgdb-get-path msgdb)
468 (elmo-msgdb-get-path msgdb-append)))
471 (defun elmo-msgdb-merge (folder msgdb-merge)
472 "Return a list of messages which have duplicated message-id."
473 (let (msgdb duplicates)
474 (setq msgdb (or (elmo-folder-msgdb-internal folder)
475 (elmo-make-msgdb nil nil nil
476 (elmo-folder-msgdb-path folder))))
477 (setq duplicates (elmo-msgdb-append msgdb msgdb-merge))
478 (elmo-folder-set-msgdb-internal folder msgdb)
481 (defsubst elmo-msgdb-clear (&optional msgdb)
484 (elmo-msgdb-set-overview msgdb nil)
485 (elmo-msgdb-set-number-alist msgdb nil)
486 (elmo-msgdb-set-mark-alist msgdb nil)
487 (elmo-msgdb-set-index msgdb nil)
491 (defun elmo-msgdb-delete-msgs (msgdb msgs)
492 "Delete MSGS from MSGDB
493 content of MSGDB is changed."
494 (let* ((overview (car msgdb))
495 (number-alist (cadr msgdb))
496 (mark-alist (caddr msgdb))
497 (index (elmo-msgdb-get-index msgdb))
498 (newmsgdb (list overview number-alist mark-alist index
501 ;; remove from current database.
506 (elmo-msgdb-overview-get-entity (car msgs) newmsgdb))
508 (setq number-alist (delq (assq (car msgs) number-alist) number-alist))
509 (setq mark-alist (delq (assq (car msgs) mark-alist) mark-alist))
511 (when index (elmo-msgdb-clear-index msgdb ov-entity))
512 (setq msgs (cdr msgs)))
513 (elmo-msgdb-set-overview msgdb overview)
514 (elmo-msgdb-set-number-alist msgdb number-alist)
515 (elmo-msgdb-set-mark-alist msgdb mark-alist)
516 (elmo-msgdb-set-index msgdb index)
519 (defun elmo-msgdb-sort-entities (msgdb predicate &optional app-data)
520 (message "Sorting...")
521 (let ((overview (elmo-msgdb-get-overview msgdb)))
522 (elmo-msgdb-set-overview
524 (sort overview (lambda (a b) (funcall predicate a b app-data))))
525 (message "Sorting...done")
528 (defun elmo-msgdb-sort-by-date (msgdb)
529 (elmo-msgdb-sort-entities
531 (lambda (x y app-data)
534 (timezone-make-date-sortable
535 (elmo-msgdb-overview-entity-get-date x))
536 (timezone-make-date-sortable
537 (elmo-msgdb-overview-entity-get-date y)))
541 (defsubst elmo-msgdb-append-element (list element)
543 ;;; (append list (list element))
544 (nconc list (list element))
548 (defsubst elmo-msgdb-get-overview (msgdb)
550 (defsubst elmo-msgdb-get-number-alist (msgdb)
552 (defsubst elmo-msgdb-get-mark-alist (msgdb)
554 ;(defsubst elmo-msgdb-get-location (msgdb)
557 (defsubst elmo-msgdb-get-index (msgdb)
560 (defsubst elmo-msgdb-get-entity-hashtb (msgdb)
563 (defsubst elmo-msgdb-get-mark-hashtb (msgdb)
566 (defsubst elmo-msgdb-get-path (msgdb)
570 ;; number <-> Message-ID handling
572 (defsubst elmo-msgdb-number-add (alist number id)
573 (let ((ret-val alist))
575 (elmo-msgdb-append-element ret-val (cons number id)))
580 (defvar elmo-flag-table-filename "flag-table")
581 (defun elmo-flag-table-load (dir)
582 "Load flag hashtable for MSGDB."
583 (let ((table (elmo-make-hash))
584 ;; For backward compatibility
585 (seen-file (expand-file-name elmo-msgdb-seen-filename dir))
587 (when (file-exists-p seen-file)
588 (setq seen-list (elmo-object-load seen-file))
589 (delete-file seen-file))
590 (dolist (msgid seen-list)
591 (elmo-set-hash-val msgid 'read table))
592 (dolist (pair (elmo-object-load
593 (expand-file-name elmo-flag-table-filename dir)))
594 (elmo-set-hash-val (car pair) (cdr pair) table))
597 (defun elmo-flag-table-set (flag-table msg-id flag)
598 (elmo-set-hash-val msg-id flag flag-table))
600 (defun elmo-flag-table-get (flag-table msg-id)
601 (elmo-get-hash-val msg-id flag-table))
603 (defun elmo-flag-table-save (dir flag-table)
605 (expand-file-name elmo-flag-table-filename dir)
608 (mapatoms (lambda (atom)
609 (setq list (cons (cons (symbol-name atom)
615 ;; persistent mark handling
618 (defun elmo-msgdb-mark-append (alist id mark)
620 (setq alist (elmo-msgdb-append-element alist
623 (defsubst elmo-msgdb-length (msgdb)
624 (length (elmo-msgdb-get-overview msgdb)))
626 (defun elmo-msgdb-flag-table (msgdb &optional flag-table)
627 ;; Make a table of msgid flag (read, answered)
628 (let ((flag-table (or flag-table (elmo-make-hash (elmo-msgdb-length msgdb))))
630 (dolist (ov (elmo-msgdb-get-overview msgdb))
631 (setq mark (elmo-msgdb-get-mark
633 (elmo-msgdb-overview-entity-get-number ov)))
637 (elmo-msgdb-overview-entity-get-id ov)
640 ((and mark (member mark (elmo-msgdb-answered-marks)))
642 (elmo-msgdb-overview-entity-get-id ov)
645 ((and mark (not (member mark
646 (elmo-msgdb-unread-marks))))
648 (elmo-msgdb-overview-entity-get-id ov)
656 (defvar elmo-msgdb-decoded-cache-hashtb nil)
657 (make-variable-buffer-local 'elmo-msgdb-decoded-cache-hashtb)
659 (defsubst elmo-msgdb-get-decoded-cache (string)
660 (if elmo-use-decoded-cache
661 (let ((hashtb (or elmo-msgdb-decoded-cache-hashtb
662 (setq elmo-msgdb-decoded-cache-hashtb
663 (elmo-make-hash 2048))))
665 (or (elmo-get-hash-val string hashtb)
670 (decode-mime-charset-string string elmo-mime-charset))
673 (decode-mime-charset-string string elmo-mime-charset)))
678 (defun elmo-multiple-field-body (name &optional boundary)
681 (std11-narrow-to-header boundary)
682 (goto-char (point-min))
683 (let ((case-fold-search t)
685 (while (re-search-forward (concat "^" name ":[ \t]*") nil t)
688 (list (buffer-substring-no-properties
689 (match-end 0) (std11-field-end))))))
692 (defun elmo-multiple-fields-body-list (field-names &optional boundary)
693 "Return list of each field-bodies of FIELD-NAMES of the message header
694 in current buffer. If BOUNDARY is not nil, it is used as message
698 (std11-narrow-to-header boundary)
699 (let* ((case-fold-search t)
701 field-name field-body)
702 (while (setq field-name (car s-rest))
703 (goto-char (point-min))
704 (while (re-search-forward (concat "^" field-name ":[ \t]*") nil t)
707 (list (buffer-substring-no-properties
708 (match-end 0) (std11-field-end))))))
709 (setq s-rest (cdr s-rest)))
712 (defsubst elmo-msgdb-remove-field-string (string)
713 (if (string-match (concat std11-field-head-regexp "[ \t]*") string)
714 (substring string (match-end 0))
717 (defsubst elmo-msgdb-get-last-message-id (string)
723 (goto-char (point-max))
724 (when (search-backward "<" nil t)
726 (if (search-forward ">" nil t)
727 (elmo-replace-in-string
728 (buffer-substring beg (point)) "\n[ \t]*" ""))))))))
730 (defun elmo-msgdb-number-load (dir)
732 (expand-file-name elmo-msgdb-number-filename dir)))
734 (defun elmo-msgdb-overview-load (dir)
736 (expand-file-name elmo-msgdb-overview-filename dir)))
738 (defun elmo-msgdb-mark-load (dir)
740 (expand-file-name elmo-msgdb-mark-filename dir)))
742 (defsubst elmo-msgdb-seen-load (dir)
743 (elmo-object-load (expand-file-name
744 elmo-msgdb-seen-filename
747 (defun elmo-msgdb-number-save (dir obj)
749 (expand-file-name elmo-msgdb-number-filename dir)
752 (defun elmo-msgdb-mark-save (dir obj)
754 (expand-file-name elmo-msgdb-mark-filename dir)
757 (defun elmo-msgdb-change-mark (msgdb before after)
758 "Set the BEFORE marks to AFTER."
759 (let ((mark-alist (elmo-msgdb-get-mark-alist msgdb))
762 (setq entity (car mark-alist))
763 (when (string= (cadr entity) before)
764 (setcar (cdr entity) after))
765 (setq mark-alist (cdr mark-alist)))))
767 (defsubst elmo-msgdb-mark (flag cached &optional new)
773 elmo-msgdb-read-uncached-mark))
775 elmo-msgdb-important-mark)
778 elmo-msgdb-answered-cached-mark
779 elmo-msgdb-answered-uncached-mark))
782 elmo-msgdb-unread-cached-mark
783 elmo-msgdb-new-mark)))
787 elmo-msgdb-unread-cached-mark
788 elmo-msgdb-unread-uncached-mark))
790 elmo-msgdb-important-mark)
793 elmo-msgdb-answered-cached-mark
794 elmo-msgdb-answered-uncached-mark)))))
796 (defsubst elmo-msgdb-overview-save (dir overview)
798 (expand-file-name elmo-msgdb-overview-filename dir)
801 (defun elmo-msgdb-match-condition-primitive (condition mark entity numbers)
803 (let ((key (elmo-filter-key condition))
807 ((string= key "last")
808 (setq result (<= (length (memq
809 (elmo-msgdb-overview-entity-get-number
812 (string-to-int (elmo-filter-value condition)))))
813 ((string= key "first")
817 (elmo-msgdb-overview-entity-get-number
820 (string-to-int (elmo-filter-value condition)))))
821 ((string= key "flag")
824 ((string= (elmo-filter-value condition) "any")
826 (string= mark elmo-msgdb-read-uncached-mark))))
827 ((string= (elmo-filter-value condition) "digest")
829 (string= mark elmo-msgdb-read-uncached-mark)
830 (string= mark elmo-msgdb-answered-cached-mark)
831 (string= mark elmo-msgdb-answered-uncached-mark))))
832 ;; (member mark (append (elmo-msgdb-answered-marks)
833 ;; (list elmo-msgdb-important-mark)
834 ;; (elmo-msgdb-unread-marks))))
835 ((string= (elmo-filter-value condition) "unread")
836 (member mark (elmo-msgdb-unread-marks)))
837 ((string= (elmo-filter-value condition) "important")
838 (string= mark elmo-msgdb-important-mark))
839 ((string= (elmo-filter-value condition) "answered")
840 (member mark (elmo-msgdb-answered-marks))))))
841 ((string= key "from")
842 (setq result (string-match
843 (elmo-filter-value condition)
844 (elmo-msgdb-overview-entity-get-from entity))))
845 ((string= key "subject")
846 (setq result (string-match
847 (elmo-filter-value condition)
848 (elmo-msgdb-overview-entity-get-subject entity))))
850 (setq result (string-match
851 (elmo-filter-value condition)
852 (elmo-msgdb-overview-entity-get-to entity))))
854 (setq result (string-match
855 (elmo-filter-value condition)
856 (elmo-msgdb-overview-entity-get-cc entity))))
857 ((or (string= key "since")
858 (string= key "before"))
859 (let ((field-date (elmo-date-make-sortable-string
861 (elmo-msgdb-overview-entity-get-date entity)
862 (current-time-zone) nil)))
864 (elmo-date-make-sortable-string
865 (elmo-date-get-datevec
866 (elmo-filter-value condition)))))
867 (setq result (if (string= key "since")
868 (or (string= specified-date field-date)
869 (string< specified-date field-date))
870 (string< field-date specified-date)))))
871 ((member key elmo-msgdb-extra-fields)
872 (let ((extval (elmo-msgdb-overview-entity-get-extra-field entity key)))
873 (when (stringp extval)
874 (setq result (string-match
875 (elmo-filter-value condition)
878 (throw 'unresolved condition)))
879 (if (eq (elmo-filter-type condition) 'unmatch)
883 (defun elmo-msgdb-match-condition-internal (condition mark entity numbers)
886 (elmo-msgdb-match-condition-primitive condition mark entity numbers))
887 ((eq (car condition) 'and)
888 (let ((lhs (elmo-msgdb-match-condition-internal (nth 1 condition)
889 mark entity numbers)))
891 ((elmo-filter-condition-p lhs)
892 (let ((rhs (elmo-msgdb-match-condition-internal
893 (nth 2 condition) mark entity numbers)))
894 (cond ((elmo-filter-condition-p rhs)
899 (elmo-msgdb-match-condition-internal (nth 2 condition)
900 mark entity numbers)))))
901 ((eq (car condition) 'or)
902 (let ((lhs (elmo-msgdb-match-condition-internal (nth 1 condition)
903 mark entity numbers)))
905 ((elmo-filter-condition-p lhs)
906 (let ((rhs (elmo-msgdb-match-condition-internal (nth 2 condition)
907 mark entity numbers)))
908 (cond ((elmo-filter-condition-p rhs)
917 (elmo-msgdb-match-condition-internal (nth 2 condition)
918 mark entity numbers)))))))
920 (defun elmo-msgdb-match-condition (msgdb condition number numbers)
921 "Check whether the condition of the message is satisfied or not.
922 MSGDB is the msgdb to search from.
923 CONDITION is the search condition.
924 NUMBER is the message number to check.
925 NUMBERS is the target message number list.
926 Return CONDITION itself if no entity exists in msgdb."
927 (let ((entity (elmo-msgdb-overview-get-entity number msgdb)))
929 (elmo-msgdb-match-condition-internal condition
930 (elmo-msgdb-get-mark msgdb number)
934 (defsubst elmo-msgdb-set-overview (msgdb overview)
935 (setcar msgdb overview))
937 (defsubst elmo-msgdb-set-number-alist (msgdb number-alist)
938 (setcar (cdr msgdb) number-alist))
940 (defsubst elmo-msgdb-set-mark-alist (msgdb mark-alist)
941 (setcar (cddr msgdb) mark-alist))
943 (defsubst elmo-msgdb-set-index (msgdb index)
944 (setcar (cdddr msgdb) index))
946 (defsubst elmo-msgdb-set-path (msgdb path)
947 (setcar (cddddr msgdb) path))
949 (defsubst elmo-msgdb-overview-entity-get-references (entity)
950 (and entity (aref (cdr entity) 1)))
952 (defsubst elmo-msgdb-overview-entity-set-references (entity references)
953 (and entity (aset (cdr entity) 1 references))
956 ;; entity -> parent-entity
957 (defsubst elmo-msgdb-overview-get-parent-entity (entity database)
958 (setq entity (elmo-msgdb-overview-entity-get-references entity))
959 ;; entity is parent-id.
960 (and entity (assoc entity database)))
962 (defsubst elmo-msgdb-get-parent-entity (entity msgdb)
963 (setq entity (elmo-msgdb-overview-entity-get-references entity))
964 ;; entity is parent-id.
965 (and entity (elmo-msgdb-overview-get-entity entity msgdb)))
967 (defsubst elmo-msgdb-overview-entity-get-number (entity)
968 (and entity (aref (cdr entity) 0)))
970 (defsubst elmo-msgdb-overview-entity-get-from-no-decode (entity)
971 (and entity (aref (cdr entity) 2)))
973 (defsubst elmo-msgdb-overview-entity-get-from (entity)
975 (aref (cdr entity) 2)
976 (elmo-msgdb-get-decoded-cache (aref (cdr entity) 2))))
978 (defsubst elmo-msgdb-overview-entity-set-number (entity number)
979 (and entity (aset (cdr entity) 0 number))
981 ;;;(setcar (cadr entity) number) entity)
983 (defsubst elmo-msgdb-overview-entity-set-from (entity from)
984 (and entity (aset (cdr entity) 2 from))
987 (defsubst elmo-msgdb-overview-entity-get-subject (entity)
989 (aref (cdr entity) 3)
990 (elmo-msgdb-get-decoded-cache (aref (cdr entity) 3))))
992 (defsubst elmo-msgdb-overview-entity-get-subject-no-decode (entity)
993 (and entity (aref (cdr entity) 3)))
995 (defsubst elmo-msgdb-overview-entity-set-subject (entity subject)
996 (and entity (aset (cdr entity) 3 subject))
999 (defsubst elmo-msgdb-overview-entity-get-date (entity)
1000 (and entity (aref (cdr entity) 4)))
1002 (defsubst elmo-msgdb-overview-entity-set-date (entity date)
1003 (and entity (aset (cdr entity) 4 date))
1006 (defsubst elmo-msgdb-overview-entity-get-to (entity)
1007 (and entity (aref (cdr entity) 5)))
1009 (defsubst elmo-msgdb-overview-entity-get-cc (entity)
1010 (and entity (aref (cdr entity) 6)))
1012 (defsubst elmo-msgdb-overview-entity-get-size (entity)
1013 (and entity (aref (cdr entity) 7)))
1015 (defsubst elmo-msgdb-overview-entity-set-size (entity size)
1016 (and entity (aset (cdr entity) 7 size))
1019 (defsubst elmo-msgdb-overview-entity-get-id (entity)
1020 (and entity (car entity)))
1022 (defsubst elmo-msgdb-overview-entity-get-extra-field (entity field-name)
1023 (let ((field-name (downcase field-name))
1024 (extra (and entity (aref (cdr entity) 8))))
1026 (cdr (assoc field-name extra)))))
1028 (defsubst elmo-msgdb-overview-entity-set-extra-field (entity field-name value)
1029 (let ((field-name (downcase field-name))
1030 (extras (and entity (aref (cdr entity) 8)))
1032 (if (setq extra (assoc field-name extras))
1033 (setcdr extra value)
1034 (elmo-msgdb-overview-entity-set-extra
1036 (cons (cons field-name value) extras)))))
1038 (defsubst elmo-msgdb-overview-entity-get-extra (entity)
1039 (and entity (aref (cdr entity) 8)))
1041 (defsubst elmo-msgdb-overview-entity-set-extra (entity extra)
1042 (and entity (aset (cdr entity) 8 extra))
1046 (defsubst elmo-msgdb-message-entity (msgdb key)
1048 (cond ((stringp key) key)
1049 ((numberp key) (format "#%d" key)))
1050 (elmo-msgdb-get-entity-hashtb msgdb)))
1052 (defun elmo-msgdb-make-message-entity (&rest args)
1053 "Make an message entity."
1054 (cons (plist-get args :message-id)
1055 (vector (plist-get args :number)
1056 (plist-get args :references)
1057 (plist-get args :from)
1058 (plist-get args :subject)
1059 (plist-get args :date)
1060 (plist-get args :to)
1061 (plist-get args :cc)
1062 (plist-get args :size)
1063 (plist-get args :extra))))
1065 (defsubst elmo-msgdb-message-entity-field (entity field &optional decode)
1069 (to (aref (cdr entity) 5))
1070 (cc (aref (cdr entity) 6))
1071 (date (aref (cdr entity) 4))
1072 (subject (aref (cdr entity) 3))
1073 (from (aref (cdr entity) 2))
1074 (message-id (car entity))
1075 (references (aref (cdr entity) 1))
1076 (size (aref (cdr entity) 7))
1077 (t (cdr (assoc (symbol-name field) (aref (cdr entity) 8)))))))
1078 (if (and decode (memq field '(from subject)))
1079 (elmo-msgdb-get-decoded-cache field-value)
1082 (defsubst elmo-msgdb-message-entity-set-field (entity field value)
1085 (to (aset (cdr entity) 5 value))
1086 (cc (aset (cdr entity) 6 value))
1087 (date (aset (cdr entity) 4 value))
1088 (subject (aset (cdr entity) 3 value))
1089 (from (aset (cdr entity) 2 value))
1090 (message-id (setcar entity value))
1091 (references (aset (cdr entity) 1 value))
1092 (size (aset (cdr entity) 7 value))
1094 (let ((extras (and entity (aref (cdr entity) 8)))
1096 (if (setq extra (assoc field extras))
1097 (setcdr extra value)
1098 (aset (cdr entity) 8 (cons (cons (symbol-name field)
1099 value) extras))))))))
1102 (defun elmo-msgdb-overview-get-entity (id msgdb)
1104 (let ((ht (elmo-msgdb-get-entity-hashtb msgdb)))
1106 (if (stringp id) ;; ID is message-id
1107 (elmo-get-hash-val id ht)
1108 (elmo-get-hash-val (format "#%d" id) ht))))))
1111 ;; deleted message handling
1113 (defun elmo-msgdb-killed-list-load (dir)
1115 (expand-file-name elmo-msgdb-killed-filename dir)
1118 (defun elmo-msgdb-killed-list-save (dir killed-list)
1120 (expand-file-name elmo-msgdb-killed-filename dir)
1123 (defun elmo-msgdb-killed-message-p (killed-list msg)
1124 (elmo-number-set-member msg killed-list))
1126 (defun elmo-msgdb-set-as-killed (killed-list msg)
1127 (elmo-number-set-append killed-list msg))
1129 (defun elmo-msgdb-killed-list-length (killed-list)
1130 (let ((killed killed-list)
1133 (if (consp (car killed))
1134 (setq ret-val (+ ret-val 1 (- (cdar killed) (caar killed))))
1135 (setq ret-val (+ ret-val 1)))
1136 (setq killed (cdr killed)))
1139 (defun elmo-msgdb-max-of-killed (killed-list)
1140 (let ((klist killed-list)
1146 (if (consp (car klist))
1150 (setq klist (cdr klist)))
1153 (defun elmo-living-messages (messages killed-list)
1156 (mapcar (lambda (number)
1157 (unless (elmo-number-set-member number killed-list)
1162 (defun elmo-msgdb-finfo-load ()
1163 (elmo-object-load (expand-file-name
1164 elmo-msgdb-finfo-filename
1165 elmo-msgdb-directory)
1166 elmo-mime-charset t))
1168 (defun elmo-msgdb-finfo-save (finfo)
1169 (elmo-object-save (expand-file-name
1170 elmo-msgdb-finfo-filename
1171 elmo-msgdb-directory)
1172 finfo elmo-mime-charset))
1174 (defun elmo-msgdb-flist-load (fname)
1175 (let ((flist-file (expand-file-name
1176 elmo-msgdb-flist-filename
1178 (elmo-safe-filename fname)
1179 (expand-file-name "folder" elmo-msgdb-directory)))))
1180 (elmo-object-load flist-file elmo-mime-charset t)))
1182 (defun elmo-msgdb-flist-save (fname flist)
1183 (let ((flist-file (expand-file-name
1184 elmo-msgdb-flist-filename
1186 (elmo-safe-filename fname)
1187 (expand-file-name "folder" elmo-msgdb-directory)))))
1188 (elmo-object-save flist-file flist elmo-mime-charset)))
1190 (defun elmo-crosspost-alist-load ()
1191 (elmo-object-load (expand-file-name
1192 elmo-crosspost-alist-filename
1193 elmo-msgdb-directory)
1196 (defun elmo-crosspost-alist-save (alist)
1197 (elmo-object-save (expand-file-name
1198 elmo-crosspost-alist-filename
1199 elmo-msgdb-directory)
1202 (defun elmo-msgdb-get-message-id-from-buffer ()
1203 (let ((msgid (elmo-field-body "message-id")))
1205 (if (string-match "<\\(.+\\)>$" msgid)
1207 (concat "<" msgid ">")) ; Invaild message-id.
1208 ;; no message-id, so put dummy msgid.
1209 (concat "<" (timezone-make-date-sortable
1210 (elmo-field-body "date"))
1211 (nth 1 (eword-extract-address-components
1212 (or (elmo-field-body "from") "nobody"))) ">"))))
1214 (defsubst elmo-msgdb-create-overview-from-buffer (number &optional size time)
1215 "Create overview entity from current buffer.
1216 Header region is supposed to be narrowed."
1218 (let ((extras elmo-msgdb-extra-fields)
1219 (default-mime-charset default-mime-charset)
1220 message-id references from subject to cc date
1221 extra field-body charset)
1222 (elmo-set-buffer-multibyte default-enable-multibyte-characters)
1223 (setq message-id (elmo-msgdb-get-message-id-from-buffer))
1224 (and (setq charset (cdr (assoc "charset" (mime-read-Content-Type))))
1225 (setq charset (intern-soft charset))
1226 (setq default-mime-charset charset))
1228 (or (elmo-msgdb-get-last-message-id
1229 (elmo-field-body "in-reply-to"))
1230 (elmo-msgdb-get-last-message-id
1231 (elmo-field-body "references"))))
1232 (setq from (elmo-replace-in-string
1233 (elmo-mime-string (or (elmo-field-body "from")
1236 subject (elmo-replace-in-string
1237 (elmo-mime-string (or (elmo-field-body "subject")
1240 (setq date (or (elmo-field-body "date") time))
1241 (setq to (mapconcat 'identity (elmo-multiple-field-body "to") ","))
1242 (setq cc (mapconcat 'identity (elmo-multiple-field-body "cc") ","))
1244 (if (setq size (elmo-field-body "content-length"))
1245 (setq size (string-to-int size))
1246 (setq size 0)));; No mean...
1248 (if (setq field-body (elmo-field-body (car extras)))
1249 (setq extra (cons (cons (downcase (car extras))
1250 field-body) extra)))
1251 (setq extras (cdr extras)))
1252 (cons message-id (vector number references
1253 from subject date to cc
1257 (defun elmo-msgdb-copy-overview-entity (entity)
1259 (copy-sequence (cdr entity))))
1261 (defsubst elmo-msgdb-insert-file-header (file)
1262 "Insert the header of the article."
1264 insert-file-contents-pre-hook ; To avoid autoconv-xmas...
1265 insert-file-contents-post-hook
1267 (when (file-exists-p file)
1268 ;; Read until header separator is found.
1269 (while (and (eq elmo-msgdb-file-header-chop-length
1271 (insert-file-contents-as-binary
1273 (incf beg elmo-msgdb-file-header-chop-length))))
1274 (prog1 (not (search-forward "\n\n" nil t))
1275 (goto-char (point-max))))))))
1277 (defsubst elmo-msgdb-create-overview-entity-from-file (number file)
1278 (let (insert-file-contents-pre-hook ; To avoid autoconv-xmas...
1279 insert-file-contents-post-hook header-end
1280 (attrib (file-attributes file))
1283 (if (not (file-exists-p file))
1285 (setq size (nth 7 attrib))
1286 (setq mtime (timezone-make-date-arpa-standard
1287 (current-time-string (nth 5 attrib)) (current-time-zone)))
1288 ;; insert header from file.
1291 (elmo-msgdb-insert-file-header file)
1292 (error (throw 'done nil)))
1293 (goto-char (point-min))
1295 (if (re-search-forward "\\(^--.*$\\)\\|\\(\n\n\\)" nil t)
1298 (narrow-to-region (point-min) header-end)
1299 (elmo-msgdb-create-overview-from-buffer number size mtime))))))
1301 (defun elmo-msgdb-clear-index (msgdb entity)
1302 (let ((ehash (elmo-msgdb-get-entity-hashtb msgdb))
1303 (mhash (elmo-msgdb-get-mark-hashtb msgdb))
1305 (when (and entity ehash)
1306 (and (setq number (elmo-msgdb-overview-entity-get-number entity))
1307 (elmo-clear-hash-val (format "#%d" number) ehash))
1308 (and (car entity) ;; message-id
1309 (elmo-clear-hash-val (car entity) ehash)))
1310 (when (and entity mhash)
1311 (and (setq number (elmo-msgdb-overview-entity-get-number entity))
1312 (elmo-clear-hash-val (format "#%d" number) mhash)))))
1314 (defun elmo-msgdb-make-index-return (msgdb &optional overview mark-alist)
1315 "Append OVERVIEW and MARK-ALIST to the index of MSGDB.
1316 If OVERVIEW and MARK-ALIST are nil, make index for current MSGDB.
1317 Return the updated INDEX."
1319 (let* ((overview (or overview (elmo-msgdb-get-overview msgdb)))
1320 (mark-alist (or mark-alist (elmo-msgdb-get-mark-alist msgdb)))
1321 (index (elmo-msgdb-get-index msgdb))
1322 (ehash (or (car index) ;; append
1323 (elmo-make-hash (length overview))))
1324 (mhash (or (cdr index) ;; append
1325 (elmo-make-hash (length overview)))))
1327 ;; key is message-id
1329 (elmo-set-hash-val (caar overview) (car overview) ehash))
1333 (elmo-msgdb-overview-entity-get-number (car overview)))
1334 (car overview) ehash)
1335 (setq overview (cdr overview)))
1339 (format "#%d" (car (car mark-alist)))
1340 (car mark-alist) mhash)
1341 (setq mark-alist (cdr mark-alist)))
1342 (setq index (or index (cons ehash mhash)))
1343 (elmo-msgdb-set-index msgdb index)
1346 (defun elmo-msgdb-make-index (msgdb &optional overview mark-alist)
1347 "Append OVERVIEW and MARK-ALIST to the index of MSGDB.
1348 If OVERVIEW and MARK-ALIST are nil, make index for current MSGDB.
1349 Return a list of message numbers which have duplicated message-ids."
1351 (let* ((overview (or overview (elmo-msgdb-get-overview msgdb)))
1352 (mark-alist (or mark-alist (elmo-msgdb-get-mark-alist msgdb)))
1353 (index (elmo-msgdb-get-index msgdb))
1354 (ehash (or (car index) ;; append
1355 (elmo-make-hash (length overview))))
1356 (mhash (or (cdr index) ;; append
1357 (elmo-make-hash (length overview))))
1360 ;; key is message-id
1361 (if (elmo-get-hash-val (caar overview) ehash) ; duplicated.
1362 (setq duplicates (cons
1363 (elmo-msgdb-overview-entity-get-number
1367 (elmo-set-hash-val (caar overview) (car overview) ehash))
1371 (elmo-msgdb-overview-entity-get-number (car overview)))
1372 (car overview) ehash)
1373 (setq overview (cdr overview)))
1377 (format "#%d" (car (car mark-alist)))
1378 (car mark-alist) mhash)
1379 (setq mark-alist (cdr mark-alist)))
1380 (setq index (or index (cons ehash mhash)))
1381 (elmo-msgdb-set-index msgdb index)
1384 (defsubst elmo-folder-get-info (folder &optional hashtb)
1385 (elmo-get-hash-val folder
1386 (or hashtb elmo-folder-info-hashtb)))
1388 (defun elmo-folder-get-info-max (folder)
1389 "Get folder info from cache."
1390 (nth 3 (elmo-folder-get-info folder)))
1392 (defun elmo-folder-get-info-length (folder)
1393 (nth 2 (elmo-folder-get-info folder)))
1395 (defun elmo-folder-get-info-unread (folder)
1396 (nth 1 (elmo-folder-get-info folder)))
1398 (defsubst elmo-msgdb-location-load (dir)
1401 elmo-msgdb-location-filename
1404 (defsubst elmo-msgdb-location-add (alist number location)
1405 (let ((ret-val alist))
1407 (elmo-msgdb-append-element ret-val (cons number location)))
1410 (defsubst elmo-msgdb-location-save (dir alist)
1413 elmo-msgdb-location-filename
1416 (defun elmo-msgdb-list-flagged (msgdb flag)
1417 (let ((case-fold-search nil)
1418 mark-regexp matched)
1421 (setq mark-regexp (regexp-quote elmo-msgdb-new-mark)))
1423 (setq mark-regexp (elmo-regexp-opt (elmo-msgdb-unread-marks))))
1425 (setq mark-regexp (elmo-regexp-opt (elmo-msgdb-answered-marks))))
1427 (setq mark-regexp (regexp-quote elmo-msgdb-important-mark)))
1429 (setq mark-regexp (elmo-regexp-opt (elmo-msgdb-unread-marks))))
1431 (setq mark-regexp (elmo-regexp-opt
1432 (append (elmo-msgdb-unread-marks)
1433 (list elmo-msgdb-important-mark)))))
1435 (setq mark-regexp (elmo-regexp-opt
1437 (elmo-msgdb-unread-marks)
1438 (elmo-msgdb-answered-marks)
1439 (list elmo-msgdb-important-mark))))))
1442 (dolist (number (elmo-msgdb-list-messages msgdb))
1443 (let ((mark (elmo-msgdb-get-mark msgdb number)))
1444 (unless (and mark (string-match mark-regexp mark))
1445 (setq matched (cons number matched)))))
1446 (dolist (elem (elmo-msgdb-get-mark-alist msgdb))
1447 (if (string-match mark-regexp (cadr elem))
1448 (setq matched (cons (car elem) matched))))))
1452 (product-provide (provide 'elmo-msgdb) (require 'elmo-version))
1454 ;;; elmo-msgdb.el ends here