1 ;;; elmo2.el -- ELMO main file (I don't remember why this is 2).
3 ;; Copyright 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
5 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Keywords: mail, net news
7 ;; Time-stamp: <00/04/20 10:03:08 teranisi>
9 ;; This file is part of ELMO (Elisp Library for Message Orchestration).
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
41 (require 'elmo-localdir)
46 ; (require 'elmo-multi)
47 (require 'elmo-filter)
48 (require 'elmo-archive)
49 ;(require 'elmo-cache2)
52 (if (or (featurep 'dbm)
55 (featurep 'berkeley-db))
56 (require 'elmo-database))
60 (if (featurep 'elmo-imap4)
61 (elmo-imap4-flush-connection))
62 (if (featurep 'elmo-nntp)
63 (elmo-nntp-flush-connection))
64 (if (featurep 'elmo-pop3)
65 (elmo-pop3-flush-connection))
66 (if (get-buffer elmo-work-buf-name)
67 (kill-buffer elmo-work-buf-name))
70 (defun elmo-cleanup-variables ()
71 (setq elmo-folder-info-hashtb nil
72 elmo-nntp-groups-hashtb nil
73 elmo-nntp-list-folders-cache nil
76 ;; (cons of max . estimated message number) elmo-max-of-folder (folder)
77 (defun elmo-max-of-folder (folder)
78 (if (elmo-folder-plugged-p folder)
79 (elmo-call-func folder "max-of-folder")
80 (elmo-dop-max-of-folder folder)))
82 ;; list elmo-list-folder (folder)
83 (defun elmo-list-folder (folder)
84 (if (elmo-folder-plugged-p folder)
85 (elmo-call-func folder "list-folder")
86 (elmo-dop-list-folder folder)))
88 ;; list elmo-list-folders (folder)
90 (defun elmo-list-folders (folder &optional hierarchy)
91 (elmo-call-func folder "list-folders" hierarchy))
93 ;; bool elmo-folder-exists-p (folder)
94 (defun elmo-folder-exists-p (folder)
95 (if (elmo-folder-plugged-p folder)
96 (elmo-call-func folder "folder-exists-p")
97 (elmo-dop-folder-exists-p folder)))
99 ;; bool elmo-folder-creatable-p (folder)
100 (defun elmo-folder-creatable-p (folder)
101 (elmo-call-func folder "folder-creatable-p"))
103 ;; bool elmo-create-folder (folder)
105 (defun elmo-create-folder (folder)
106 (if (elmo-folder-plugged-p folder)
107 (elmo-call-func folder "create-folder")
108 (elmo-dop-create-folder folder)))
110 (defun elmo-delete-folder (folder)
111 (let ((type (elmo-folder-get-type folder)))
112 (if (or (not (memq type '(localdir localnews archive imap4 maildir)))
113 (if (elmo-folder-plugged-p folder)
114 (elmo-call-func folder "delete-folder")
115 (elmo-dop-delete-folder folder)))
116 ;; If folder doesn't support delete folder, delete msgdb path only.
117 (elmo-msgdb-delete-path folder))))
119 (defun elmo-rename-folder (old-folder new-folder)
120 (let ((old-type (elmo-folder-get-type old-folder))
121 (new-type (elmo-folder-get-type new-folder)))
122 (if (not (eq old-type new-type))
123 (error "not same folder type")
124 (unless (and (memq old-type '(localdir localnews archive imap4))
125 (elmo-folder-identical-system-p old-folder new-folder))
126 (error "rename folder not supported"))
127 (if (elmo-folder-plugged-p old-folder)
129 (if (or (file-exists-p (elmo-msgdb-expand-path new-folder))
130 (elmo-folder-exists-p new-folder))
131 (error "already exists folder: %s" new-folder)
133 (elmo-call-func old-folder "rename-folder"
134 (elmo-folder-get-spec new-folder))
135 (elmo-msgdb-rename-path old-folder new-folder))
136 (elmo-dop-rename-folder old-folder new-folder)))))
138 (defun elmo-read-msg-no-cache (folder msg outbuf &optional msgdb force-reload)
139 "Read messsage into outbuf without cacheing.
140 If msgdb is specified, use cache."
142 (when (and (not force-reload)
149 (cdr (assq msg (elmo-msgdb-get-number-alist msgdb)))
152 (elmo-call-func folder "read-msg" msg outbuf))))
154 (defun elmo-force-cache-msg (folder number msgid &optional loc-alist)
155 "Force cache message."
156 (let* ((cache-file (elmo-cache-get-path msgid))
159 (setq dir (directory-file-name (file-name-directory cache-file)))
160 (if (not (file-exists-p dir))
161 (elmo-make-directory dir))
162 (if (elmo-local-file-p folder number)
163 (elmo-copy-file (elmo-get-msg-filename folder number loc-alist)
166 (elmo-call-func folder "read-msg" number (current-buffer))
167 (as-binary-output-file
168 (write-region (point-min) (point-max) cache-file nil 'no-msg)))))))
170 (defun elmo-prefetch-msg (folder msg outbuf msgdb)
171 "Read message into outbuf with cacheing."
173 (let* ((number-alist (elmo-msgdb-get-number-alist
174 (or msgdb (elmo-msgdb-load folder))))
175 (dir (elmo-msgdb-expand-path folder))
176 (message-id (cdr (assq msg number-alist)))
179 ret-val part-num real-fld-num)
181 (if (elmo-cache-exists-p message-id)
183 ;; cache doesn't exist.
184 (setq real-fld-num (elmo-get-real-folder-number
186 (setq type (elmo-folder-get-type (car real-fld-num)))
187 (cond ((eq type 'imap4)
188 (setq ret-val (elmo-imap4-prefetch-msg
189 (elmo-folder-get-spec (car real-fld-num))
192 ((elmo-folder-local-p (car real-fld-num)))
193 (t (setq ret-val (elmo-call-func (car real-fld-num)
195 (cdr real-fld-num) outbuf))))
197 (elmo-cache-save message-id
198 (elmo-string-partial-p ret-val)
202 (defun elmo-prefetch-msgs (folder msgs)
203 "prefetch messages for queueing."
204 (let* ((msgdb (elmo-msgdb-load folder))
205 (number-alist (elmo-msgdb-get-number-alist msgdb))
210 (setq msg (car msgs))
211 (setq msgid (cdr (assq msg number-alist)))
212 (message "%s:Prefetching... %d/%d message(s)"
214 (setq count (+ 1 count)) len)
215 (elmo-force-cache-msg folder msg msgid)
216 (setq msgs (cdr msgs)))))
218 ;; elmo-read-msg (folder msg outbuf msgdb)
220 (defun elmo-read-msg (folder msg outbuf msgdb &optional force-reload)
221 "Read message into outbuf."
222 (let ((inhibit-read-only t))
223 (if (not (elmo-use-cache-p folder msg))
224 (elmo-read-msg-no-cache folder msg outbuf msgdb force-reload)
225 (elmo-read-msg-with-cache folder msg outbuf msgdb force-reload))))
227 (defun elmo-read-msg-with-cache (folder msg outbuf msgdb
228 &optional force-reload)
229 "Read message into outbuf with cacheing."
230 (let* ((number-alist (elmo-msgdb-get-number-alist
231 (or msgdb (elmo-msgdb-load folder))))
232 (dir (elmo-msgdb-expand-path folder))
233 (message-id (cdr (assq msg number-alist)))
234 (type (elmo-folder-number-get-type folder msg))
236 ret-val part-num real-fld-num)
238 (if (and (not force-reload)
239 (not (elmo-local-file-p folder msg)))
240 (setq ret-val (elmo-cache-read message-id folder msg)))
243 ;; cache doesn't exist.
244 (setq real-fld-num (elmo-get-real-folder-number
246 (if (setq ret-val (elmo-call-func (car real-fld-num)
248 (cdr real-fld-num) outbuf))
249 (if (not (elmo-local-file-p folder msg))
250 (elmo-cache-save message-id
251 (elmo-string-partial-p ret-val)
255 (defun elmo-copy-msgs (src-folder msgs dst-folder &optional msgdb same-number)
256 (let* ((src-spec (elmo-folder-get-spec src-folder))
258 (elmo-msgdb-get-location msgdb)
259 (elmo-msgdb-location-load
260 (elmo-msgdb-expand-path nil src-spec)))))
261 (if (eq (car src-spec) 'archive)
262 (elmo-archive-copy-msgs-froms
263 (elmo-folder-get-spec dst-folder)
264 msgs src-spec loc-alist same-number)
265 (elmo-call-func dst-folder "copy-msgs"
266 msgs src-spec loc-alist same-number))))
268 (defun elmo-move-msgs (src-folder msgs dst-folder
269 &optional msgdb all done
275 (let* ((db (or msgdb (elmo-msgdb-load src-folder)))
276 (number-alist (elmo-msgdb-get-number-alist db))
277 (mark-alist (elmo-msgdb-get-mark-alist db))
280 (all-msg-num (or all len))
281 (done-msg-num (or done 0))
282 (tmp-buf (get-buffer-create " *elmo-move-msg*"))
284 ret-val real-fld-num done-copy dir
285 mes-string message-id src-cache i percent unseen seen-list)
286 (setq i done-msg-num)
288 (when (and (not (eq dst-folder 'null))
289 (elmo-folder-direct-copy-p src-folder dst-folder))
290 (message (concat (if no-delete "Copying" "Moving")
291 " %d message(s)...") (length messages))
292 (unless (elmo-copy-msgs src-folder
297 (error "Copy message to %s failed" dst-folder))
300 (setq real-fld-num (elmo-get-real-folder-number src-folder
302 (setq message-id (cdr (assq (car messages) number-alist)))
304 (if (and (not (eq dst-folder 'null))
305 (not (and unread-marks
307 (cadr (assq (car messages) mark-alist))
309 (setq seen-list (cons message-id seen-list)))
310 (unless (or (eq dst-folder 'null) done-copy)
311 (if (and (elmo-folder-plugged-p src-folder)
312 (elmo-folder-plugged-p dst-folder)
313 (elmo-folder-identical-system-p (car real-fld-num)
315 ;; online and identical system...so copy 'em!
317 (elmo-copy-msgs (car real-fld-num)
318 (list (cdr real-fld-num))
322 (error "Copy message to %s failed" dst-folder))
323 ;; use cache if exists.
324 (elmo-read-msg src-folder (car messages) tmp-buf msgdb)
325 (unless (elmo-append-msg dst-folder (buffer-string) message-id
326 (if same-number (car messages))
327 ;; null means all unread.
328 (or (null unread-marks)
330 (error "move: append message to %s failed" dst-folder))))
331 ;; delete src cache if it is partial.
332 (elmo-cache-delete-partial message-id src-folder (car messages))
333 (setq ret-val (append ret-val (list (car messages))))
335 (setq percent (/ (* i 100) all-msg-num))
337 (elmo-display-progress
338 'elmo-move-msgs "Copying messages..."
340 (elmo-display-progress
341 'elmo-move-msgs "Moving messages..."
343 (setq messages (cdr messages)))
345 (unless (eq dst-folder 'null)
346 (setq dir (elmo-msgdb-expand-path dst-folder))
347 (elmo-msgdb-seen-save dir
348 (append (elmo-msgdb-seen-load dir) seen-list)))
349 (kill-buffer tmp-buf)
350 (if (and (not no-delete) ret-val)
352 (if (not no-delete-info)
353 (message "Cleaning up src folder..."))
354 (if (and (elmo-delete-msgs src-folder ret-val db)
355 (elmo-msgdb-delete-msgs src-folder ret-val db t))
357 (message "move: delete messages from %s failed." src-folder)
361 (not no-delete-info))
362 (message "Cleaning up src folder...done.")
367 (message "Copying messages...done.")
370 (message "No message was moved.")
371 (message "Moving messages failed.")
375 ;; boolean elmo-delete-msgs (folder msgs)
376 (defun elmo-delete-msgs (folder msgs &optional msgdb)
377 ;; remove from real folder.
378 (if (elmo-folder-plugged-p folder)
379 (elmo-call-func folder "delete-msgs" msgs)
380 (elmo-dop-delete-msgs folder msgs msgdb)))
383 ;; Server side search.
385 (defun elmo-search (folder condition &optional from-msgs)
386 (let ((type (elmo-folder-get-type folder)))
387 (if (elmo-folder-plugged-p folder)
388 (elmo-call-func folder "search" condition from-msgs)
389 (elmo-cache-search-all folder condition from-msgs))))
391 (defun elmo-msgdb-create (folder numlist new-mark already-mark
392 seen-mark important-mark seen-list)
393 (if (elmo-folder-plugged-p folder)
394 (elmo-call-func folder "msgdb-create" numlist new-mark already-mark
395 seen-mark important-mark seen-list)
396 (elmo-dop-msgdb-create folder numlist new-mark already-mark
397 seen-mark important-mark seen-list)))
399 (defun elmo-make-folder-numbers-list (folder msgs)
400 (let ((msg-list msgs)
404 (when (> (car msg-list) 0)
405 (setq pair (elmo-get-real-folder-number folder (car msg-list)))
406 (if (setq fld-list (assoc (car pair) ret-val))
407 (setcdr fld-list (cons (cdr pair) (cdr fld-list)))
408 (setq ret-val (cons (cons (car pair) (list (cdr pair))) ret-val))))
409 (setq msg-list (cdr msg-list)))
412 (defun elmo-call-func-on-markable-msgs (folder func-name msgs msgdb)
414 (let ((folder-numbers (elmo-make-folder-numbers-list folder msgs))
416 (while folder-numbers
419 (elmo-folder-get-spec
420 (car (car folder-numbers)))))
422 (memq type '(maildir internal)))
423 (if (elmo-folder-plugged-p folder)
424 (elmo-call-func (car (car folder-numbers)) func-name
425 (cdr (car folder-numbers)))
426 (if elmo-enable-disconnected-operation
427 (elmo-dop-call-func-on-msgs
428 (car (car folder-numbers)) ; real folder
430 (cdr (car folder-numbers)) ; real number
432 (error "Unplugged"))))
433 (setq folder-numbers (cdr folder-numbers))))))
435 (defun elmo-unmark-important (folder msgs msgdb)
436 (elmo-call-func-on-markable-msgs folder "unmark-important" msgs msgdb))
438 (defun elmo-mark-as-important (folder msgs msgdb)
439 (elmo-call-func-on-markable-msgs folder "mark-as-important" msgs msgdb))
441 (defun elmo-mark-as-read (folder msgs msgdb)
442 (elmo-call-func-on-markable-msgs folder "mark-as-read" msgs msgdb))
444 (defun elmo-mark-as-unread (folder msgs msgdb)
445 (elmo-call-func-on-markable-msgs folder "mark-as-unread" msgs msgdb))
447 (defun elmo-msgdb-create-as-numlist (folder numlist new-mark already-mark
448 seen-mark important-mark seen-list)
449 (if (elmo-folder-plugged-p folder)
450 (elmo-call-func folder "msgdb-create-as-numlist" numlist
451 new-mark already-mark seen-mark important-mark seen-list)
452 (elmo-dop-msgdb-create-as-numlist
453 folder numlist new-mark already-mark
454 seen-mark important-mark seen-list)))
456 ;; msgdb elmo-msgdb-load (folder)
457 (defun elmo-msgdb-load (folder &optional spec)
458 (message "Loading msgdb for %s..." folder)
459 (let* ((path (elmo-msgdb-expand-path folder spec))
461 (list (elmo-msgdb-overview-load path)
462 (elmo-msgdb-number-load path)
463 (elmo-msgdb-mark-load path)
464 (elmo-msgdb-location-load path))))
465 (message "Loading msgdb for %s...done." folder)
466 (elmo-folder-set-info-max-by-numdb folder (nth 1 ret-val))
469 ;; boolean elmo-msgdb-save (folder msgdb)
470 (defun elmo-msgdb-save (folder msgdb)
471 (message "Saving msgdb for %s..." folder)
473 (let ((path (elmo-msgdb-expand-path folder)))
474 (elmo-msgdb-overview-save path (car msgdb))
475 (elmo-msgdb-number-save path (cadr msgdb))
476 (elmo-msgdb-mark-save path (caddr msgdb))
477 (elmo-msgdb-location-save path (cadddr msgdb))
478 ;(elmo-sync-validity folder);; for validity check!!
480 (message "Saving msgdb for %s...done." folder)
481 (elmo-folder-set-info-max-by-numdb folder (cadr msgdb)))
483 (defun elmo-msgdb-add-msgs-to-seen-list-subr (msgs msgdb seen-marks seen-list)
485 (let* ((seen-mark-list (string-to-char-list seen-marks))
486 (number-alist (elmo-msgdb-get-number-alist msgdb))
487 (mark-alist (elmo-msgdb-get-mark-alist msgdb))
490 (if (setq ent (assq (car msgs) mark-alist))
491 (if (memq (string-to-char (cadr ent)) seen-mark-list)
493 (cons (cdr (assq (car msgs) number-alist)) seen-list)))
494 ;; no mark ... seen...
496 (cons (cdr (assq (car msgs) number-alist)) seen-list)))
497 (setq msgs (cdr msgs)))
500 (defun elmo-msgdb-add-msgs-to-seen-list (folder msgs msgdb seen-marks)
502 (unless (eq folder 'null) ;; black hole
503 (let* ((dir (elmo-msgdb-expand-path folder))
504 (seen-list (elmo-msgdb-seen-load dir)))
506 (elmo-msgdb-add-msgs-to-seen-list-subr
507 msgs msgdb seen-marks seen-list))
508 (elmo-msgdb-seen-save dir seen-list))))
510 ;; msgdb elmo-append-msg (folder string)
511 (defun elmo-append-msg (folder string &optional message-id msg no-see)
512 (let ((type (elmo-folder-get-type folder))
514 (cond ((eq type 'imap4)
515 (if (elmo-folder-plugged-p folder)
516 (elmo-call-func folder "append-msg" string msg no-see)
517 (elmo-dop-append-msg folder string message-id)))
520 (elmo-cache-append-msg
521 (elmo-folder-get-spec folder)
522 string message-id msg no-see)
523 (error "elmo-cache-append-msg require message-id")))
525 (elmo-call-func folder "append-msg" string msg no-see)))))
527 (defun elmo-check-validity (folder)
528 (elmo-call-func folder "check-validity"
530 elmo-msgdb-validity-filename
531 (elmo-msgdb-expand-path folder))))
533 (defun elmo-pack-number (folder msgdb arg)
534 (if (string-match "^[\\+=].*" folder)
535 (elmo-call-func folder "pack-number" msgdb arg)
536 (error "pack-number not supported")))
538 (defun elmo-sync-validity (folder)
539 (elmo-call-func folder "sync-validity"
541 elmo-msgdb-validity-filename
542 (elmo-msgdb-expand-path folder))))
544 (defun elmo-use-cache-p (folder number)
545 (elmo-call-func folder "use-cache-p" number)
548 (defun elmo-local-file-p (folder number)
549 (elmo-call-func folder "local-file-p" number))
551 (defun elmo-folder-portinfo (folder)
553 (elmo-call-func folder "portinfo")
556 (defun elmo-folder-plugged-p (folder)
558 (or (elmo-folder-local-p folder)
559 (elmo-call-func folder "plugged-p"))))
561 (defun elmo-folder-set-plugged (folder plugged &optional add)
562 (if (elmo-folder-local-p folder)
564 (elmo-call-func folder "set-plugged" plugged add)))
566 (defun elmo-generic-sync-number-alist (spec number-alist)
567 "Just return number-alist."
570 (defun elmo-generic-list-folder-unread (spec mark-alist unread-marks)
574 (function (lambda (x)
575 (if (member (cadr (assq (car x) mark-alist)) unread-marks)
579 (defun elmo-generic-list-folder-important (spec overview)
582 (defun elmo-update-number (folder msgdb)
583 (when (elmo-folder-plugged-p folder)
584 (message "Synchronize number...")
585 (let* ((numlist (elmo-msgdb-get-number-alist msgdb))
586 (len (length numlist))
588 (if (eq (length (setq
590 (elmo-call-func folder "sync-number-alist" numlist)))
593 (elmo-msgdb-set-number-alist msgdb new-numlist)
594 (message "Synchronize number...done.")
597 (defun elmo-get-msg-filename (folder number &optional loc-alist)
598 "Available if elmo-local-file-p is t."
599 (elmo-call-func folder "get-msg-filename" number loc-alist))
601 (defun elmo-strict-folder-diff (fld &optional number-alist)
603 (let* ((dir (elmo-msgdb-expand-path fld))
604 (nalist (or number-alist
605 (elmo-msgdb-number-load dir)))
606 (in-db (sort (mapcar 'car nalist) '<))
607 (in-folder (elmo-list-folder fld))
608 append-list delete-list diff)
609 (cons (if (equal in-folder in-db)
611 (setq diff (elmo-list-diff
615 (setq append-list (car diff))
616 (setq delete-list (cadr diff))
620 (- 0 (length delete-list))
622 (length in-folder))))
624 (defun elmo-list-folder-unread (folder mark-alist unread-marks)
625 (elmo-call-func folder "list-folder-unread" mark-alist unread-marks))
627 (defun elmo-list-folder-important (folder overview)
629 ;; server side importants...(append only.)
630 (if (elmo-folder-plugged-p folder)
631 (setq importants (elmo-call-func folder "list-folder-important"
633 (or elmo-msgdb-global-mark-alist
634 (setq elmo-msgdb-global-mark-alist
635 (elmo-object-load (expand-file-name
636 elmo-msgdb-global-mark-filename
640 (if (assoc (elmo-msgdb-overview-entity-get-id (car overview))
641 elmo-msgdb-global-mark-alist)
642 (setq importants (cons
643 (elmo-msgdb-overview-entity-get-number
646 (setq overview (cdr overview)))
649 (defun elmo-generic-commit (folder)
652 (defun elmo-commit (folder)
653 (elmo-call-func folder "commit"))
655 ;; returns cons cell of (unsync . number-of-messages-in-folder)
656 (defun elmo-folder-diff (fld &optional number-alist)
658 (let ((type (elmo-folder-get-type fld)))
659 (cond ((eq type 'multi)
660 (elmo-multi-folder-diff fld))
661 ((and (eq type 'filter)
662 (or (elmo-multi-p fld)
664 (vectorp (nth 1 (elmo-folder-get-spec fld)))))
665 ;; not partial...unsync number is unknown.
667 (cdr (elmo-folder-diff
668 (nth 2 (elmo-folder-get-spec fld)))))))
669 ((and (eq type 'imap4)
670 elmo-use-server-diff)
671 (elmo-call-func fld "server-diff")) ;; imap4 server side diff.
673 (let ((cached-in-db-max (elmo-folder-get-info-max fld))
674 (in-folder (elmo-max-of-folder fld))
679 (not cached-in-db-max))
680 (let* ((dir (elmo-msgdb-expand-path fld))
681 (nalist (or number-alist
682 (elmo-msgdb-number-load dir))))
684 (setq in-db (sort (mapcar 'car nalist) '<))
685 (setq in-db-max (or (nth (max 0 (1- (length in-db))) in-db)
687 (if (not number-alist)
688 ;; Number-alist is not used.
689 (elmo-folder-set-info-hashtb fld in-db-max
692 ;; (and in-db (length in-db))
695 ;; info-cache exists.
696 (setq in-db-max cached-in-db-max))
697 (setq unsync (if (and in-db
699 (- (car in-folder) in-db-max)
703 (if (null (car in-folder))
705 (setq nomif (cdr in-folder))
706 (if (and unsync nomif (> unsync nomif))
708 (cons (or unsync 0) (or nomif 0)))))))
710 (defsubst elmo-folder-get-info (folder &optional hashtb)
711 (elmo-get-hash-val folder
712 (or hashtb elmo-folder-info-hashtb)))
714 (defun elmo-folder-set-info-hashtb (folder max numbers &optional new unread)
715 (let ((info (elmo-folder-get-info folder)))
717 (or new (setq new (nth 0 info)))
718 (or unread (setq unread (nth 1 info)))
719 (or numbers (setq numbers (nth 2 info)))
720 (or max (setq max (nth 3 info))))
721 (elmo-set-hash-val folder
722 (list new unread numbers max)
723 elmo-folder-info-hashtb)))
725 (defun elmo-multi-get-number-alist-list (number-alist)
726 (let ((alist (sort number-alist (function (lambda (x y) (< (car x)
729 one-alist ret-val num)
731 (setq cur-number (+ cur-number 1))
735 (/ (- (setq num (car (car alist)))
736 (* elmo-multi-divide-number cur-number))
737 elmo-multi-divide-number)))
738 (setq one-alist (nconc
742 (% num (* elmo-multi-divide-number cur-number))
743 (cdr (car alist))))))
744 (setq alist (cdr alist)))
745 (setq ret-val (nconc ret-val (list one-alist))))
748 (defun elmo-multi-folder-diff (fld)
749 (let ((flds (cdr (elmo-folder-get-spec fld)))
751 (elmo-multi-get-number-alist-list
752 (elmo-msgdb-number-load (elmo-msgdb-expand-path fld))))
754 diffs (unsync 0) (nomif 0))
756 (setq diffs (nconc diffs (list (elmo-folder-diff (car flds)
760 (setq count (+ 1 count))
761 (setq flds (cdr flds)))
763 (setq unsync (+ unsync (car (car diffs))))
764 (setq nomif (+ nomif (cdr (car diffs))))
765 (setq diffs (cdr diffs)))
766 (elmo-folder-set-info-hashtb fld nil nomif)
767 (cons unsync nomif)))
769 (defun elmo-folder-set-info-max-by-numdb (folder msgdb-number)
770 (let ((num-db (sort (mapcar 'car msgdb-number) '<)))
771 (elmo-folder-set-info-hashtb
773 (or (nth (max 0 (1- (length num-db))) num-db) 0)
774 nil ;;(length num-db)
777 (defun elmo-folder-get-info-max (folder)
778 "Get folder info from cache."
779 (nth 3 (elmo-folder-get-info folder)))
781 (defun elmo-folder-get-info-length (folder)
782 (nth 2 (elmo-folder-get-info folder)))
784 (defun elmo-folder-get-info-unread (folder)
785 (nth 1 (elmo-folder-get-info folder)))
787 (defun elmo-folder-info-make-hashtb (info-alist hashtb)
788 (let* ((hashtb (or hashtb
789 (elmo-make-hash (length info-alist)))))
792 (let ((info (cadr x)))
793 (and (intern-soft (car x) hashtb)
794 (elmo-set-hash-val (car x)
795 (list (nth 2 info) ;; new
796 (nth 3 info) ;; unread
797 (nth 1 info) ;; length
801 (setq elmo-folder-info-hashtb hashtb)))
803 (defun elmo-crosspost-message-set (message-id folders &optional type)
804 (if (assoc message-id elmo-crosspost-message-alist)
805 (setcdr (assoc message-id elmo-crosspost-message-alist)
807 (setq elmo-crosspost-message-alist
808 (nconc elmo-crosspost-message-alist
809 (list (list message-id folders type))))))
811 (defun elmo-crosspost-message-delete (message-id folders)
812 (let* ((id-fld (assoc message-id elmo-crosspost-message-alist))
813 (folder-list (nth 1 id-fld)))
815 (if (setq folder-list (elmo-delete-lists folders folder-list))
816 (setcar (cdr id-fld) folder-list)
817 (setq elmo-crosspost-message-alist
818 (delete id-fld elmo-crosspost-message-alist))))))
821 (defun elmo-get-msgs-with-mark (mark-alist mark)
824 (if (string= (cadr (car mark-alist)) mark)
825 (cons (car (car mark-alist)) ret-val))
826 (setq mark-alist (cdr mark-alist)))
829 (defun elmo-buffer-cache-message (fld msg &optional msgdb force-reload)
830 (let* ((msg-id (cdr (assq msg (elmo-msgdb-get-number-alist msgdb))))
831 (hit (elmo-buffer-cache-hit (list fld msg msg-id)))
834 (elmo-buffer-cache-sort
835 (elmo-buffer-cache-entry-make (list fld msg msg-id) hit))
836 (setq hit (elmo-buffer-cache-add (list fld msg msg-id)))
838 (if (or force-reload read)
842 (elmo-read-msg fld msg
846 (elmo-buffer-cache-delete)
847 (error "read message %s/%s is quitted" fld msg))
849 (elmo-buffer-cache-delete)
850 (signal (car err) (cdr err))
851 nil))) ;; will not be used
852 hit)) ;; retrun value
854 (defun elmo-read-msg-with-buffer-cache (fld msg outbuf msgdb &optional force-reload)
855 (if elmo-use-buffer-cache
857 (when (setq hit (elmo-buffer-cache-message
858 (elmo-string fld) msg
863 (setq start (point-min) end (point-max)))
864 (insert-buffer-substring hit start end)))
865 (elmo-read-msg fld msg outbuf msgdb force-reload)))
867 (defun elmo-folder-pipe-p (folder)
868 (let ((type (elmo-folder-get-type folder)))
871 (let ((flds (cdr (elmo-folder-get-spec folder))))
874 (if (elmo-folder-pipe-p (car flds))
881 (nth 2 (elmo-folder-get-spec folder))))
886 (defun elmo-multi-p (folder)
887 (let ((type (elmo-folder-get-type folder)))
893 (elmo-pipe-spec-dst (elmo-folder-get-spec folder))))
896 (nth 2 (elmo-folder-get-spec folder))))
901 (defun elmo-get-real-folder-number (folder number)
902 (let ((type (elmo-folder-get-type folder)))
905 (elmo-multi-get-real-folder-number folder number))
907 (elmo-get-real-folder-number
908 (elmo-pipe-spec-dst (elmo-folder-get-spec folder) )
911 (elmo-get-real-folder-number
912 (nth 2 (elmo-folder-get-spec folder)) number))
917 (defun elmo-folder-get-primitive-spec-list (folder &optional spec-list)
918 (let ((type (elmo-folder-get-type folder))
921 ((or (eq type 'multi)
923 (let ((flds (cdr (elmo-folder-get-spec folder)))
926 (setq spec (elmo-folder-get-primitive-spec-list (car flds)))
927 (if (not (memq (car spec) specs))
928 (setq specs (append specs spec)))
929 (setq flds (cdr flds)))))
932 (elmo-folder-get-primitive-spec-list
933 (nth 2 (elmo-folder-get-spec folder)))))
935 (setq specs (list (elmo-folder-get-spec folder)))
939 (defun elmo-folder-get-primitive-folder-list (folder)
940 (let* ((type (elmo-folder-get-type folder)))
942 ((or (eq type 'multi)
944 (let ((flds (cdr (elmo-folder-get-spec folder)))
947 (setq ret-val (append ret-val
948 (elmo-folder-get-primitive-folder-list
950 (setq flds (cdr flds)))
953 (elmo-folder-get-primitive-folder-list
954 (nth 2 (elmo-folder-get-spec folder))))
959 (defun elmo-folder-contains-multi (folder)
960 (let ((cur-spec (elmo-folder-get-spec folder)))
964 ((eq (car cur-spec) 'filter)
965 (setq cur-spec (elmo-folder-get-spec (nth 2 cur-spec))))
966 ((eq (car cur-spec) 'pipe)
967 (setq cur-spec (elmo-folder-get-spec (elmo-pipe-spec-src cur-spec))))
968 ((eq (car cur-spec) 'multi)
970 (t (setq cur-spec nil)))))
973 (defun elmo-folder-contains-type (folder type)
974 (let ((spec (elmo-folder-get-spec folder)))
976 ((eq (car spec) 'filter)
977 (elmo-folder-contains-type (nth 2 spec) type))
978 ((eq (car spec) 'pipe)
979 (elmo-folder-contains-type (elmo-pipe-spec-dst spec) type))
980 ((eq (car spec) 'multi)
981 (let ((folders (cdr spec)))
984 (if (elmo-folder-contains-type (car folders) type)
986 (setq folders (cdr folders))))))
987 ((eq (car spec) type)
991 (defun elmo-folder-number-get-spec (folder number)
992 (let ((type (elmo-folder-get-type folder)))
995 (elmo-multi-folder-number-get-spec folder number))
997 (elmo-folder-number-get-spec
998 (elmo-pipe-spec-dst (elmo-folder-get-spec folder)) number))
1000 (elmo-folder-number-get-spec
1001 (nth 2 (elmo-folder-get-spec folder)) number))
1003 (elmo-folder-get-spec folder)
1006 (defun elmo-folder-number-get-type (folder number)
1007 (car (elmo-folder-number-get-spec folder number)))
1009 (defun elmo-multi-folder-number-get-spec (folder number)
1010 (let* ((spec (elmo-folder-get-spec folder))
1012 (fld (nth (- (/ number elmo-multi-divide-number) 1) flds)))
1013 (elmo-folder-number-get-spec fld number)))
1016 (autoload 'elmo-imap4-get-connection "elmo-imap4")
1017 (autoload 'elmo-nntp-make-groups-hashtb "elmo-nntp")
1018 (autoload 'elmo-nntp-post "elmo-nntp")
1019 (autoload 'elmo-localdir-max-of-folder "elmo-localdir")
1020 (autoload 'elmo-localdir-msgdb-create-overview-entity-from-file "elmo-localdir")
1021 (autoload 'elmo-multi-folder-diff "elmo-multi")
1022 (autoload 'elmo-archive-copy-msgs-froms "elmo-archive")
1024 ;;; elmo2.el ends here