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))
40 (defsubst elmo-msgdb-append-element (list element)
42 ;;; (append list (list element))
43 (nconc list (list element))
47 (defsubst elmo-msgdb-get-overview (msgdb)
49 (defsubst elmo-msgdb-get-number-alist (msgdb)
51 (defsubst elmo-msgdb-get-mark-alist (msgdb)
53 ;(defsubst elmo-msgdb-get-location (msgdb)
55 (defsubst elmo-msgdb-get-overviewht (msgdb)
59 ;; number <-> Message-ID handling
61 (defsubst elmo-msgdb-number-add (alist number id)
62 (let ((ret-val alist))
64 (elmo-msgdb-append-element ret-val (cons number id)))
68 ;; parsistent mark handling
71 (defvar elmo-msgdb-global-mark-alist nil)
73 (defun elmo-msgdb-global-mark-delete (msgid)
74 (let* ((path (expand-file-name
75 elmo-msgdb-global-mark-filename
76 elmo-msgdb-directory))
77 (malist (or elmo-msgdb-global-mark-alist
78 (setq elmo-msgdb-global-mark-alist
79 (elmo-object-load path))))
81 (when (setq match (assoc msgid malist))
82 (setq elmo-msgdb-global-mark-alist
83 (delete match elmo-msgdb-global-mark-alist))
84 (elmo-object-save path elmo-msgdb-global-mark-alist))))
86 (defun elmo-msgdb-global-mark-set (msgid mark)
87 (let* ((path (expand-file-name
88 elmo-msgdb-global-mark-filename
89 elmo-msgdb-directory))
90 (malist (or elmo-msgdb-global-mark-alist
91 (setq elmo-msgdb-global-mark-alist
92 (elmo-object-load path))))
94 (if (setq match (assoc msgid malist))
96 (setq elmo-msgdb-global-mark-alist
97 (nconc elmo-msgdb-global-mark-alist
98 (list (cons msgid mark)))))
99 (elmo-object-save path elmo-msgdb-global-mark-alist)))
101 (defun elmo-msgdb-global-mark-get (msgid)
102 (cdr (assoc msgid (or elmo-msgdb-global-mark-alist
103 (setq elmo-msgdb-global-mark-alist
106 elmo-msgdb-global-mark-filename
107 elmo-msgdb-directory)))))))
110 ;; persistent mark handling
112 (defun elmo-msgdb-mark-set (alist id mark)
113 (let ((ret-val alist)
115 (setq entity (assq id alist))
118 ;; delete this entity
119 (setq ret-val (delq entity alist))
121 (setcar (cdr entity) mark))
123 (setq ret-val (elmo-msgdb-append-element ret-val
127 (defun elmo-msgdb-mark-append (alist id mark)
129 (setq alist (elmo-msgdb-append-element alist
132 (defun elmo-msgdb-mark-alist-to-seen-list (number-alist mark-alist seen-marks)
133 "Make seen-list from MARK-ALIST."
134 (let ((seen-mark-list (string-to-char-list seen-marks))
137 (if (setq ent (assq (car (car number-alist)) mark-alist))
139 (memq (string-to-char (cadr ent)) seen-mark-list))
140 (setq ret-val (cons (cdr (car number-alist)) ret-val)))
141 (setq ret-val (cons (cdr (car number-alist)) ret-val)))
142 (setq number-alist (cdr number-alist)))
148 (defvar elmo-msgdb-decoded-cache-hashtb nil)
149 (make-variable-buffer-local 'elmo-msgdb-decoded-cache-hashtb)
151 (defsubst elmo-msgdb-get-decoded-cache (string)
152 (if elmo-use-decoded-cache
153 (let ((hashtb (or elmo-msgdb-decoded-cache-hashtb
154 (setq elmo-msgdb-decoded-cache-hashtb
155 (elmo-make-hash 2048))))
157 (or (elmo-get-hash-val string hashtb)
162 (decode-mime-charset-string string elmo-mime-charset))
165 (decode-mime-charset-string string elmo-mime-charset)))
171 (defsubst elmo-msgdb-get-field-value (field-name beg end buffer)
175 (narrow-to-region beg end)
176 (elmo-field-body field-name))))
178 (defun elmo-multiple-field-body (name &optional boundary)
181 (std11-narrow-to-header boundary)
182 (goto-char (point-min))
183 (let ((case-fold-search t)
185 (while (re-search-forward (concat "^" name ":[ \t]*") nil t)
188 (list (buffer-substring-no-properties
189 (match-end 0) (std11-field-end))))))
192 (defun elmo-multiple-fields-body-list (field-names &optional boundary)
193 "Return list of each field-bodies of FIELD-NAMES of the message header
194 in current buffer. If BOUNDARY is not nil, it is used as message
198 (std11-narrow-to-header boundary)
199 (let* ((case-fold-search t)
201 field-name field-body)
202 (while (setq field-name (car s-rest))
203 (goto-char (point-min))
204 (while (re-search-forward (concat "^" field-name ":[ \t]*") nil t)
207 (list (buffer-substring-no-properties
208 (match-end 0) (std11-field-end))))))
209 (setq s-rest (cdr s-rest)))
212 (defsubst elmo-msgdb-remove-field-string (string)
213 (if (string-match (concat std11-field-head-regexp "[ \t]*") string)
214 (substring string (match-end 0))
217 (defsubst elmo-msgdb-get-last-message-id (string)
223 (goto-char (point-max))
224 (when (search-backward "<" nil t)
226 (if (search-forward ">" nil t)
227 (elmo-replace-in-string
228 (buffer-substring beg (point)) "\n[ \t]*" ""))))))))
230 (defun elmo-msgdb-number-load (dir)
232 (expand-file-name elmo-msgdb-number-filename dir)))
234 (defun elmo-msgdb-overview-load (dir)
236 (expand-file-name elmo-msgdb-overview-filename dir)))
238 (defun elmo-msgdb-mark-load (dir)
240 (expand-file-name elmo-msgdb-mark-filename dir)))
242 (defsubst elmo-msgdb-seen-load (dir)
243 (elmo-object-load (expand-file-name
244 elmo-msgdb-seen-filename
247 (defun elmo-msgdb-number-save (dir obj)
249 (expand-file-name elmo-msgdb-number-filename dir)
252 (defun elmo-msgdb-mark-save (dir obj)
254 (expand-file-name elmo-msgdb-mark-filename dir)
257 (defun elmo-msgdb-change-mark (msgdb before after)
258 "Set the BEFORE marks to AFTER."
259 (let ((mark-alist (elmo-msgdb-get-mark-alist msgdb))
262 (setq entity (car mark-alist))
263 (when (string= (cadr entity) before)
264 (setcar (cdr entity) after))
265 (setq mark-alist (cdr mark-alist)))))
267 (defsubst elmo-msgdb-seen-save (dir obj)
269 (expand-file-name elmo-msgdb-seen-filename dir)
272 (defsubst elmo-msgdb-overview-save (dir overview)
274 (expand-file-name elmo-msgdb-overview-filename dir)
277 (defun elmo-msgdb-match-condition-primitive (condition entity numbers)
279 (let ((key (elmo-filter-key condition))
283 ((string= key "last")
284 (setq result (<= (length (memq
285 (elmo-msgdb-overview-entity-get-number
288 (string-to-int (elmo-filter-value condition)))))
289 ((string= key "first")
293 (elmo-msgdb-overview-entity-get-number
296 (string-to-int (elmo-filter-value condition)))))
297 ((string= key "from")
298 (setq result (string-match
299 (elmo-filter-value condition)
300 (elmo-msgdb-overview-entity-get-from entity))))
301 ((string= key "subject")
302 (setq result (string-match
303 (elmo-filter-value condition)
304 (elmo-msgdb-overview-entity-get-subject entity))))
306 (setq result (string-match
307 (elmo-filter-value condition)
308 (elmo-msgdb-overview-entity-get-to entity))))
310 (setq result (string-match
311 (elmo-filter-value condition)
312 (elmo-msgdb-overview-entity-get-cc entity))))
313 ((or (string= key "since")
314 (string= key "before"))
315 (let ((field-date (elmo-date-make-sortable-string
317 (elmo-msgdb-overview-entity-get-date entity)
318 (current-time-zone) nil)))
320 (elmo-date-make-sortable-string
321 (elmo-date-get-datevec
322 (elmo-filter-value condition)))))
323 (setq result (if (string= key "since")
324 (or (string= specified-date field-date)
325 (string< specified-date field-date))
326 (string< field-date specified-date)))))
327 ((member key elmo-msgdb-extra-fields)
328 (let ((extval (elmo-msgdb-overview-entity-get-extra-field entity key)))
329 (when (stringp extval)
330 (setq result (string-match
331 (elmo-filter-value condition)
334 (throw 'unresolved condition)))
335 (if (eq (elmo-filter-type condition) 'unmatch)
339 (defun elmo-msgdb-match-condition (condition entity numbers)
342 (elmo-msgdb-match-condition-primitive condition entity numbers))
343 ((eq (car condition) 'and)
344 (let ((lhs (elmo-msgdb-match-condition (nth 1 condition)
347 ((elmo-filter-condition-p lhs)
348 (let ((rhs (elmo-msgdb-match-condition (nth 2 condition)
350 (cond ((elmo-filter-condition-p rhs)
355 (elmo-msgdb-match-condition (nth 2 condition)
357 ((eq (car condition) 'or)
358 (let ((lhs (elmo-msgdb-match-condition (nth 1 condition)
361 ((elmo-filter-condition-p lhs)
362 (let ((rhs (elmo-msgdb-match-condition (nth 2 condition)
364 (cond ((elmo-filter-condition-p rhs)
373 (elmo-msgdb-match-condition (nth 2 condition)
374 entity numbers)))))))
376 (defun elmo-msgdb-delete-msgs (msgdb msgs)
377 "Delete MSGS from MSGDB
378 content of MSGDB is changed."
380 (let* (;(msgdb (elmo-folder-msgdb folder))
381 (overview (car msgdb))
382 (number-alist (cadr msgdb))
383 (mark-alist (caddr msgdb))
384 (hashtb (elmo-msgdb-get-overviewht msgdb))
385 (newmsgdb (list overview number-alist mark-alist hashtb))
387 ;; remove from current database.
392 (elmo-msgdb-overview-get-entity (car msgs) newmsgdb))
394 (when (and elmo-use-overview-hashtb hashtb)
395 (elmo-msgdb-clear-overview-hashtb ov-entity hashtb))
397 (delq (assq (car msgs) number-alist) number-alist))
398 (setq mark-alist (delq (assq (car msgs) mark-alist) mark-alist))
399 (setq msgs (cdr msgs)))
400 ;(elmo-folder-set-message-modified-internal folder t)
401 (setcar msgdb overview)
402 (setcar (cdr msgdb) number-alist)
403 (setcar (cddr msgdb) mark-alist)
404 (setcar (nthcdr 3 msgdb) hashtb))
407 (defsubst elmo-msgdb-set-overview (msgdb overview)
408 (setcar msgdb overview))
410 (defsubst elmo-msgdb-set-number-alist (msgdb number-alist)
411 (setcar (cdr msgdb) number-alist))
413 (defsubst elmo-msgdb-set-mark-alist (msgdb mark-alist)
414 (setcar (cddr msgdb) mark-alist))
416 (defsubst elmo-msgdb-overview-entity-get-references (entity)
417 (and entity (aref (cdr entity) 1)))
419 (defsubst elmo-msgdb-overview-entity-set-references (entity references)
420 (and entity (aset (cdr entity) 1 references))
423 ;; entity -> parent-entity
424 (defsubst elmo-msgdb-overview-get-parent-entity (entity database)
425 (setq entity (elmo-msgdb-overview-entity-get-references entity))
426 ;; entity is parent-id.
427 (and entity (assoc entity database)))
429 (defsubst elmo-msgdb-get-parent-entity (entity msgdb)
430 (setq entity (elmo-msgdb-overview-entity-get-references entity))
431 ;; entity is parent-id.
432 (and entity (elmo-msgdb-overview-get-entity entity msgdb)))
434 (defsubst elmo-msgdb-overview-entity-get-number (entity)
435 (and entity (aref (cdr entity) 0)))
437 (defsubst elmo-msgdb-overview-entity-get-from-no-decode (entity)
438 (and entity (aref (cdr entity) 2)))
440 (defsubst elmo-msgdb-overview-entity-get-from (entity)
442 (aref (cdr entity) 2)
443 (elmo-msgdb-get-decoded-cache (aref (cdr entity) 2))))
445 (defsubst elmo-msgdb-overview-entity-set-number (entity number)
446 (and entity (aset (cdr entity) 0 number))
448 ;;;(setcar (cadr entity) number) entity)
450 (defsubst elmo-msgdb-overview-entity-set-from (entity from)
451 (and entity (aset (cdr entity) 2 from))
454 (defsubst elmo-msgdb-overview-entity-get-subject (entity)
456 (aref (cdr entity) 3)
457 (elmo-msgdb-get-decoded-cache (aref (cdr entity) 3))))
459 (defsubst elmo-msgdb-overview-entity-get-subject-no-decode (entity)
460 (and entity (aref (cdr entity) 3)))
462 (defsubst elmo-msgdb-overview-entity-set-subject (entity subject)
463 (and entity (aset (cdr entity) 3 subject))
466 (defsubst elmo-msgdb-overview-entity-get-date (entity)
467 (and entity (aref (cdr entity) 4)))
469 (defsubst elmo-msgdb-overview-entity-set-date (entity date)
470 (and entity (aset (cdr entity) 4 date))
473 (defsubst elmo-msgdb-overview-entity-get-to (entity)
474 (and entity (aref (cdr entity) 5)))
476 (defsubst elmo-msgdb-overview-entity-get-cc (entity)
477 (and entity (aref (cdr entity) 6)))
479 (defsubst elmo-msgdb-overview-entity-get-size (entity)
480 (and entity (aref (cdr entity) 7)))
482 (defsubst elmo-msgdb-overview-entity-set-size (entity size)
483 (and entity (aset (cdr entity) 7 size))
486 (defsubst elmo-msgdb-overview-entity-get-id (entity)
487 (and entity (car entity)))
489 (defsubst elmo-msgdb-overview-entity-get-extra-field (entity field-name)
490 (let ((extra (and entity (aref (cdr entity) 8))))
492 (cdr (assoc field-name extra)))))
494 (defsubst elmo-msgdb-overview-entity-set-extra-field (entity field-name value)
495 (let ((extras (and entity (aref (cdr entity) 8)))
497 (if (setq extra (assoc field-name extras))
499 (elmo-msgdb-overview-entity-set-extra
501 (cons (cons field-name value) extras)))))
503 (defsubst elmo-msgdb-overview-entity-get-extra (entity)
504 (and entity (aref (cdr entity) 8)))
506 (defsubst elmo-msgdb-overview-entity-set-extra (entity extra)
507 (and entity (aset (cdr entity) 8 extra))
510 (defun elmo-msgdb-overview-get-entity-by-number (database number)
515 (if (eq (elmo-msgdb-overview-entity-get-number (car db)) number)
516 (setq entity (car db)
521 (defun elmo-msgdb-overview-get-entity (id msgdb)
523 (let ((ovht (elmo-msgdb-get-overviewht msgdb)))
524 (if ovht ; use overview hash
525 (if (stringp id) ;; ID is message-id
526 (elmo-get-hash-val id ovht)
527 (elmo-get-hash-val (format "#%d" id) ovht))
528 (let* ((overview (elmo-msgdb-get-overview msgdb))
529 (number-alist (elmo-msgdb-get-number-alist msgdb))
530 (message-id (if (stringp id)
531 id ;; ID is message-id
532 (cdr (assq id number-alist))))
535 (assoc message-id overview)
536 ;; ID is number. message-id is nil or no exists in number-alist.
537 (elmo-msgdb-overview-get-entity-by-number overview id)))))))
540 ;; deleted message handling
542 (defun elmo-msgdb-killed-list-load (dir)
544 (expand-file-name elmo-msgdb-killed-filename dir)
547 (defun elmo-msgdb-killed-list-save (dir killed-list)
549 (expand-file-name elmo-msgdb-killed-filename dir)
552 (defun elmo-msgdb-killed-message-p (killed-list msg)
553 (elmo-number-set-member msg killed-list))
555 (defun elmo-msgdb-set-as-killed (killed-list msg)
556 (elmo-number-set-append killed-list msg))
558 (defun elmo-msgdb-append-to-killed-list (folder msgs)
559 (elmo-folder-set-killed-list-internal
561 (elmo-number-set-append-list
562 (elmo-folder-killed-list-internal folder)
565 (defun elmo-msgdb-killed-list-length (killed-list)
566 (let ((killed killed-list)
569 (if (consp (car killed))
570 (setq ret-val (+ ret-val 1 (- (cdar killed) (caar killed))))
571 (setq ret-val (+ ret-val 1)))
572 (setq killed (cdr killed)))
575 (defun elmo-msgdb-max-of-killed (killed-list)
576 (let ((klist killed-list)
582 (if (consp (car klist))
586 (setq klist (cdr klist)))
589 (defun elmo-living-messages (messages killed-list)
592 (mapcar (lambda (number)
593 (unless (elmo-number-set-member number killed-list)
598 (defun elmo-msgdb-finfo-load ()
599 (elmo-object-load (expand-file-name
600 elmo-msgdb-finfo-filename
601 elmo-msgdb-directory)
602 elmo-mime-charset t))
604 (defun elmo-msgdb-finfo-save (finfo)
605 (elmo-object-save (expand-file-name
606 elmo-msgdb-finfo-filename
607 elmo-msgdb-directory)
608 finfo elmo-mime-charset))
610 (defun elmo-msgdb-flist-load (fname)
611 (let ((flist-file (expand-file-name
612 elmo-msgdb-flist-filename
614 (elmo-safe-filename fname)
615 (expand-file-name "folder" elmo-msgdb-directory)))))
616 (elmo-object-load flist-file elmo-mime-charset t)))
618 (defun elmo-msgdb-flist-save (fname flist)
619 (let ((flist-file (expand-file-name
620 elmo-msgdb-flist-filename
622 (elmo-safe-filename fname)
623 (expand-file-name "folder" elmo-msgdb-directory)))))
624 (elmo-object-save flist-file flist elmo-mime-charset)))
626 (defun elmo-crosspost-alist-load ()
627 (elmo-object-load (expand-file-name
628 elmo-crosspost-alist-filename
629 elmo-msgdb-directory)
632 (defun elmo-crosspost-alist-save (alist)
633 (elmo-object-save (expand-file-name
634 elmo-crosspost-alist-filename
635 elmo-msgdb-directory)
638 (defun elmo-msgdb-add-msgs-to-seen-list (msgs msgdb unread-marks seen-list)
640 (let* ((number-alist (elmo-msgdb-get-number-alist msgdb))
641 (mark-alist (elmo-msgdb-get-mark-alist msgdb))
644 (if (setq ent (assq (car msgs) mark-alist))
645 (unless (member (cadr ent) unread-marks) ;; not unread mark
647 (cons (cdr (assq (car msgs) number-alist)) seen-list)))
648 ;; no mark ... seen...
650 (cons (cdr (assq (car msgs) number-alist)) seen-list)))
651 (setq msgs (cdr msgs)))
654 (defun elmo-msgdb-get-message-id-from-buffer ()
655 (or (elmo-field-body "message-id")
656 ;; no message-id, so put dummy msgid.
657 (concat (timezone-make-date-sortable
658 (elmo-field-body "date"))
659 (nth 1 (eword-extract-address-components
660 (or (elmo-field-body "from") "nobody"))))))
662 (defsubst elmo-msgdb-create-overview-from-buffer (number &optional size time)
663 "Create overview entity from current buffer.
664 Header region is supposed to be narrowed."
666 (let ((extras elmo-msgdb-extra-fields)
667 message-id references from subject to cc date
669 (elmo-set-buffer-multibyte default-enable-multibyte-characters)
670 (setq message-id (elmo-msgdb-get-message-id-from-buffer))
672 (or (elmo-msgdb-get-last-message-id
673 (elmo-field-body "in-reply-to"))
674 (elmo-msgdb-get-last-message-id
675 (elmo-field-body "references"))))
676 (setq from (elmo-mime-string (elmo-delete-char
679 (elmo-field-body "from")
681 (setq subject (elmo-mime-string (or (elmo-field-body "subject")
683 (setq date (or (elmo-field-body "date") time))
684 (setq to (mapconcat 'identity (elmo-multiple-field-body "to") ","))
685 (setq cc (mapconcat 'identity (elmo-multiple-field-body "cc") ","))
687 (if (setq size (elmo-field-body "content-length"))
688 (setq size (string-to-int size))
689 (setq size 0)));; No mean...
691 (if (setq field-body (elmo-field-body (car extras)))
692 (setq extra (cons (cons (downcase (car extras))
694 (setq extras (cdr extras)))
695 (cons message-id (vector number references
696 from subject date to cc
700 (defun elmo-msgdb-copy-overview-entity (entity)
702 (copy-sequence (cdr entity))))
704 (defsubst elmo-msgdb-insert-file-header (file)
705 "Insert the header of the article."
707 insert-file-contents-pre-hook ; To avoid autoconv-xmas...
708 insert-file-contents-post-hook
710 (when (file-exists-p file)
711 ;; Read until header separator is found.
712 (while (and (eq elmo-msgdb-file-header-chop-length
714 (insert-file-contents-as-binary
716 (incf beg elmo-msgdb-file-header-chop-length))))
717 (prog1 (not (search-forward "\n\n" nil t))
718 (goto-char (point-max))))))))
720 (defsubst elmo-msgdb-create-overview-entity-from-file (number file)
721 (let (insert-file-contents-pre-hook ; To avoid autoconv-xmas...
722 insert-file-contents-post-hook header-end
723 (attrib (file-attributes file))
726 (if (not (file-exists-p file))
728 (setq size (nth 7 attrib))
729 (setq mtime (timezone-make-date-arpa-standard
730 (current-time-string (nth 5 attrib)) (current-time-zone)))
731 ;; insert header from file.
734 (elmo-msgdb-insert-file-header file)
735 (error (throw 'done nil)))
736 (goto-char (point-min))
738 (if (re-search-forward "\\(^--.*$\\)\\|\\(\n\n\\)" nil t)
741 (narrow-to-region (point-min) header-end)
742 (elmo-msgdb-create-overview-from-buffer number size mtime))))))
744 (defun elmo-msgdb-overview-sort-by-date (overview)
750 (timezone-make-date-sortable
751 (elmo-msgdb-overview-entity-get-date x))
752 (timezone-make-date-sortable
753 (elmo-msgdb-overview-entity-get-date y)))
756 (defun elmo-msgdb-sort-by-date (msgdb)
757 (message "Sorting...")
758 (let ((overview (elmo-msgdb-get-overview msgdb)))
759 (setq overview (elmo-msgdb-overview-sort-by-date overview))
760 (message "Sorting...done")
761 (list overview (nth 1 msgdb)(nth 2 msgdb))))
763 (defun elmo-msgdb-clear-overview-hashtb (entity hashtb)
766 elmo-use-overview-hashtb
768 (and (setq number (elmo-msgdb-overview-entity-get-number entity))
769 (elmo-clear-hash-val (format "#%d" number) hashtb))
770 (and (car entity) ;; message-id
771 (elmo-clear-hash-val (car entity) hashtb)))))
773 (defun elmo-msgdb-make-overview-hashtb (overview &optional hashtb)
774 (if (and elmo-use-overview-hashtb
776 (let ((hashtb (or hashtb ;; append
777 (elmo-make-hash (length overview)))))
781 (elmo-set-hash-val (caar overview) (car overview) hashtb))
784 (format "#%d" (elmo-msgdb-overview-entity-get-number (car overview)))
785 (car overview) hashtb)
786 (setq overview (cdr overview)))
790 (defsubst elmo-msgdb-append (msgdb msgdb-append &optional set-hash)
792 (nconc (car msgdb) (car msgdb-append))
793 (nconc (cadr msgdb) (cadr msgdb-append))
794 (nconc (caddr msgdb) (caddr msgdb-append))
796 (elmo-msgdb-make-overview-hashtb (car msgdb-append) (nth 3 msgdb)))))
798 (defsubst elmo-msgdb-clear (&optional msgdb)
802 (setcar (cdr msgdb) nil)
803 (setcar (cddr msgdb) nil)
804 (setcar (nthcdr 3 msgdb) (elmo-msgdb-make-overview-hashtb nil)))
805 (list nil nil nil (elmo-msgdb-make-overview-hashtb nil))))
807 (defsubst elmo-folder-get-info (folder &optional hashtb)
808 (elmo-get-hash-val folder
809 (or hashtb elmo-folder-info-hashtb)))
811 (defun elmo-folder-set-info-hashtb (folder max numbers &optional new unread)
812 (let ((info (elmo-folder-get-info folder)))
814 (or new (setq new (nth 0 info)))
815 (or unread (setq unread (nth 1 info)))
816 (or numbers (setq numbers (nth 2 info)))
817 (or max (setq max (nth 3 info))))
818 (elmo-set-hash-val folder
819 (list new unread numbers max)
820 elmo-folder-info-hashtb)))
822 (defun elmo-folder-set-info-max-by-numdb (folder msgdb-number)
823 (let ((num-db (sort (mapcar 'car msgdb-number) '<)))
824 (elmo-folder-set-info-hashtb
826 (or (nth (max 0 (1- (length num-db))) num-db) 0)
827 nil ;;(length num-db)
830 (defun elmo-folder-get-info-max (folder)
831 "Get folder info from cache."
832 (nth 3 (elmo-folder-get-info folder)))
834 (defun elmo-folder-get-info-length (folder)
835 (nth 2 (elmo-folder-get-info folder)))
837 (defun elmo-folder-get-info-unread (folder)
838 (nth 1 (elmo-folder-get-info folder)))
840 (defun elmo-folder-info-make-hashtb (info-alist hashtb)
841 (let* ((hashtb (or hashtb
842 (elmo-make-hash (length info-alist)))))
845 (let ((info (cadr x)))
846 (and (intern-soft (car x) hashtb)
847 (elmo-set-hash-val (car x)
848 (list (nth 2 info) ;; new
849 (nth 3 info) ;; unread
850 (nth 1 info) ;; length
854 (setq elmo-folder-info-hashtb hashtb)))
856 (defsubst elmo-msgdb-location-load (dir)
859 elmo-msgdb-location-filename
862 (defsubst elmo-msgdb-location-add (alist number location)
863 (let ((ret-val alist))
865 (elmo-msgdb-append-element ret-val (cons number location)))
868 (defsubst elmo-msgdb-location-save (dir alist)
871 elmo-msgdb-location-filename
875 (product-provide (provide 'elmo-msgdb) (require 'elmo-version))
877 ;;; elmo-msgdb.el ends here