1 ;;; elmo-multi.el --- Multiple Folder Interface for ELMO.
3 ;; Copyright (C) 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
5 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Keywords: mail, net news
8 ;; This file is part of ELMO (Elisp Library for Message Orchestration).
10 ;; This program is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
35 (defvar elmo-multi-divide-number 100000
36 "*Multi divider number.")
40 (luna-define-class elmo-multi-folder (elmo-folder)
41 (children divide-number))
42 (luna-define-internal-accessors 'elmo-multi-folder))
44 (luna-define-method elmo-folder-initialize ((folder
47 (while (> (length (car (setq name (elmo-parse-token name ",")))) 0)
48 (elmo-multi-folder-set-children-internal
50 (nconc (elmo-multi-folder-children-internal
52 (list (elmo-make-folder (car name)))))
53 (setq name (cdr name))
54 (when (and (> (length name) 0)
55 (eq (aref name 0) ?,))
56 (setq name (substring name 1))))
57 (elmo-multi-folder-set-divide-number-internal
59 elmo-multi-divide-number)
62 (luna-define-method elmo-folder-open-internal ((folder elmo-multi-folder))
63 (dolist (fld (elmo-multi-folder-children-internal folder))
64 (elmo-folder-open-internal fld)))
66 (luna-define-method elmo-folder-check ((folder elmo-multi-folder))
67 (dolist (fld (elmo-multi-folder-children-internal folder))
68 (elmo-folder-check fld)))
70 (luna-define-method elmo-folder-close-internal ((folder elmo-multi-folder))
71 (dolist (fld (elmo-multi-folder-children-internal folder))
72 (elmo-folder-close-internal fld)))
74 (luna-define-method elmo-folder-close :after ((folder elmo-multi-folder))
75 (dolist (fld (elmo-multi-folder-children-internal folder))
76 (elmo-folder-set-msgdb-internal fld nil)))
78 (luna-define-method elmo-folder-synchronize ((folder elmo-multi-folder)
79 &optional ignore-msgdb
81 (dolist (fld (elmo-multi-folder-children-internal folder))
82 (elmo-folder-synchronize fld ignore-msgdb no-check)))
84 (luna-define-method elmo-folder-expand-msgdb-path ((folder
86 (expand-file-name (elmo-replace-string-as-filename
87 (elmo-folder-name-internal folder))
88 (expand-file-name "multi"
89 elmo-msgdb-directory)))
91 (luna-define-method elmo-folder-newsgroups ((folder elmo-multi-folder))
95 'elmo-folder-newsgroups
98 'elmo-folder-get-primitive-list
99 (elmo-multi-folder-children-internal folder)))))))
101 (luna-define-method elmo-folder-get-primitive-list ((folder elmo-multi-folder))
104 'elmo-folder-get-primitive-list
105 (elmo-multi-folder-children-internal folder))))
107 (luna-define-method elmo-folder-contains-type ((folder elmo-multi-folder) type)
108 (let ((children (elmo-multi-folder-children-internal folder))
111 (when (elmo-folder-contains-type (car children) type)
114 (setq children (cdr children)))
117 (luna-define-method elmo-message-folder ((folder elmo-multi-folder)
119 (nth (- (/ number (elmo-multi-folder-divide-number-internal folder)) 1)
120 (elmo-multi-folder-children-internal folder)))
122 (luna-define-method elmo-message-entity ((folder elmo-folder) key)
125 (elmo-msgdb-message-entity (elmo-folder-msgdb
126 (elmo-message-folder folder key))
129 (let ((children (elmo-multi-folder-children-internal folder))
132 (when (setq match (elmo-message-entity (car children) key))
134 (setq children (cdr children)))
137 (defun elmo-multi-msgdb (msgdb base)
138 (list (mapcar (function
140 (elmo-msgdb-overview-entity-set-number
143 (elmo-msgdb-overview-entity-get-number x)))))
153 (cdr x)))) (nth 2 msgdb))))
155 (defun elmo-multi-split-numbers (folder numlist &optional as-is)
156 (let ((numbers (sort numlist '<))
157 (divider (elmo-multi-folder-divide-number-internal folder))
159 one-list numbers-list)
161 (setq cur-number (+ cur-number 1))
166 (* divider cur-number))
168 (setq one-list (nconc
174 (* divider cur-number))))))
175 (setq numbers (cdr numbers)))
176 (setq numbers-list (nconc numbers-list (list one-list))))
179 (luna-define-method elmo-folder-msgdb-create ((folder elmo-multi-folder)
181 (let* ((folders (elmo-multi-folder-children-internal folder))
182 overview number-alist mark-alist entity
187 (setq numbers-list (elmo-multi-split-numbers folder numbers))
189 (while (< cur-number (length folders))
190 (if (nth cur-number numbers-list)
195 (elmo-folder-msgdb-create (nth cur-number folders)
196 (nth cur-number numbers-list)
198 (* (elmo-multi-folder-divide-number-internal folder)
200 (setq cur-number (1+ cur-number)))
201 (elmo-msgdb-sort-by-date msgdb)))
203 (luna-define-method elmo-folder-process-crosspost ((folder elmo-multi-folder))
204 (dolist (child (elmo-multi-folder-children-internal folder))
205 (elmo-folder-process-crosspost child)))
207 (defsubst elmo-multi-folder-append-msgdb (folder append-msgdb)
209 (let* ((number-alist (elmo-msgdb-get-number-alist append-msgdb))
210 (all-alist (copy-sequence (append
211 (elmo-msgdb-get-number-alist
212 (elmo-folder-msgdb folder))
215 overview to-be-deleted
218 (setq all-alist (delq (car cur) all-alist))
219 ;; same message id exists.
220 (if (setq same (rassoc (cdr (car cur)) all-alist))
221 (unless (= (/ (car (car cur))
222 (elmo-multi-folder-divide-number-internal folder))
224 (elmo-multi-folder-divide-number-internal folder)))
225 ;; base is also same...delete it!
227 (append to-be-deleted (list (car (car cur)))))))
228 (setq cur (cdr cur)))
229 (cond ((eq (elmo-folder-process-duplicates-internal folder)
232 (elmo-msgdb-append-to-killed-list folder to-be-deleted)
233 (setq overview (elmo-delete-if
235 (memq (elmo-msgdb-overview-entity-get-number
238 (elmo-msgdb-get-overview append-msgdb)))
239 ;; Should be mark as read.
240 (elmo-folder-mark-as-read folder to-be-deleted)
241 (elmo-msgdb-set-overview append-msgdb overview))
242 ((eq (elmo-folder-process-duplicates-internal folder)
244 ;; Mark as read duplicates.
245 (elmo-folder-mark-as-read folder to-be-deleted))
248 (setq to-be-deleted nil)))
249 (elmo-folder-set-msgdb-internal folder
251 (elmo-folder-msgdb folder)
253 (length to-be-deleted))
256 (luna-define-method elmo-folder-append-msgdb ((folder elmo-multi-folder)
258 (elmo-multi-folder-append-msgdb folder append-msgdb))
260 (defmacro elmo-multi-real-folder-number (folder number)
261 "Returns a cons cell of real FOLDER and NUMBER."
264 (elmo-multi-folder-divide-number-internal (, folder)))
265 1) (elmo-multi-folder-children-internal (, folder)))
266 (% (, number) (elmo-multi-folder-divide-number-internal
269 (defsubst elmo-multi-find-fetch-strategy (folder entity ignore-cache)
271 (let ((pair (elmo-multi-real-folder-number
273 (elmo-msgdb-overview-entity-get-number entity)))
274 (new-entity (elmo-msgdb-copy-overview-entity entity)))
276 (elmo-msgdb-overview-entity-set-number new-entity (cdr pair)))
277 (elmo-find-fetch-strategy (car pair) new-entity ignore-cache))
278 (elmo-make-fetch-strategy 'entire)))
280 (luna-define-method elmo-find-fetch-strategy
281 ((folder elmo-multi-folder)
282 entity &optional ignore-cache)
283 (elmo-multi-find-fetch-strategy folder entity ignore-cache))
285 (luna-define-method elmo-message-fetch ((folder elmo-multi-folder)
287 &optional section outbuf unseen)
288 (let ((pair (elmo-multi-real-folder-number folder number)))
289 (elmo-message-fetch (car pair) (cdr pair) strategy section outbuf unseen)))
291 (luna-define-method elmo-folder-delete-messages ((folder elmo-multi-folder)
293 (let ((flds (elmo-multi-folder-children-internal folder))
296 (setq one-list-list (elmo-multi-split-numbers folder numbers))
297 (while (< cur-number (length flds))
298 (elmo-folder-delete-messages (nth cur-number flds)
299 (nth cur-number one-list-list))
300 (setq cur-number (+ 1 cur-number)))
303 (luna-define-method elmo-folder-diff ((folder elmo-multi-folder)
305 (elmo-multi-folder-diff folder numbers))
307 (defun elmo-multi-folder-diff (folder numbers)
308 (let ((flds (elmo-multi-folder-children-internal folder))
309 (numbers (mapcar 'car
310 (elmo-msgdb-number-load
311 (elmo-folder-msgdb-path folder))))
312 (killed (elmo-msgdb-killed-list-load (elmo-folder-msgdb-path folder)))
318 ;; If first time, dummy numbers is used as current number list.
321 (divider (elmo-multi-folder-divide-number-internal folder)))
322 (dolist (folder flds)
325 (cons (* i divider) numbers)))))
327 (elmo-multi-split-numbers folder
330 (elmo-number-set-to-number-list killed)
333 (setq nums (elmo-folder-diff (car flds) (car num-list))
334 nums (cons (or (elmo-diff-unread nums)
335 (elmo-diff-new nums))
336 (elmo-diff-all nums)))
337 (setq diffs (nconc diffs (list nums)))
338 (setq count (+ 1 count))
339 (setq num-list (cdr num-list))
340 (setq flds (cdr flds)))
342 (and (car (car diffs))
343 (setq unsync (+ unsync (car (car diffs)))))
344 (setq messages (+ messages (cdr (car diffs))))
345 (setq diffs (cdr diffs)))
346 (elmo-folder-set-info-hashtb folder nil messages)
347 (cons unsync messages)))
349 (defun elmo-multi-split-number-alist (folder number-alist)
350 (let ((alist (sort (copy-sequence number-alist)
351 (lambda (pair1 pair2)
352 (< (car pair1)(car pair2)))))
356 (setq cur-number (+ cur-number 1))
360 (/ (- (setq num (car (car alist)))
361 (* elmo-multi-divide-number cur-number))
362 (elmo-multi-folder-divide-number-internal folder))))
363 (setq one-alist (nconc
367 (% num (* (elmo-multi-folder-divide-number-internal
369 (cdr (car alist))))))
370 (setq alist (cdr alist)))
371 (setq split (nconc split (list one-alist))))
374 (defun elmo-multi-split-mark-alist (folder mark-alist)
376 (alist (sort (copy-sequence mark-alist)
377 (lambda (pair1 pair2)
378 (< (car pair1)(car pair2)))))
381 (setq cur-number (+ cur-number 1))
385 (/ (- (car (car alist))
386 (* (elmo-multi-folder-divide-number-internal
388 (elmo-multi-folder-divide-number-internal folder))))
389 (setq one-alist (nconc
392 (list (% (car (car alist))
393 (* (elmo-multi-folder-divide-number-internal
395 (cadr (car alist))))))
396 (setq alist (cdr alist)))
397 (setq result (nconc result (list one-alist))))
400 (luna-define-method elmo-folder-list-unreads ((folder elmo-multi-folder))
403 (dolist (child (elmo-multi-folder-children-internal folder))
404 (setq cur-number (+ cur-number 1))
410 (elmo-multi-folder-divide-number-internal
412 (elmo-folder-list-unreads child)))))
415 (luna-define-method elmo-folder-list-answereds ((folder elmo-multi-folder))
418 (dolist (child (elmo-multi-folder-children-internal folder))
419 (setq cur-number (+ cur-number 1))
425 (elmo-multi-folder-divide-number-internal
427 (elmo-folder-list-answereds child)))))
430 (luna-define-method elmo-folder-list-importants ((folder elmo-multi-folder))
433 (dolist (child (elmo-multi-folder-children-internal folder))
434 (setq cur-number (+ cur-number 1))
440 (elmo-multi-folder-divide-number-internal
442 (elmo-folder-list-importants child)))))
445 (elmo-folder-list-messages-with-global-mark
446 folder elmo-msgdb-important-mark)))))
448 (luna-define-method elmo-folder-list-messages-internal
449 ((folder elmo-multi-folder) &optional nohide)
450 (let* ((flds (elmo-multi-folder-children-internal folder))
454 (setq cur-number (+ cur-number 1))
455 (setq list (elmo-folder-list-messages-internal (car flds)))
464 (* (elmo-multi-folder-divide-number-internal
465 folder) cur-number) x)))
471 (eq cur-number (/ num
472 (elmo-multi-folder-divide-number-internal
476 (elmo-msgdb-get-number-alist
477 (elmo-folder-msgdb folder)))))))
478 (setq flds (cdr flds)))
481 (luna-define-method elmo-folder-exists-p ((folder elmo-multi-folder))
482 (let ((flds (elmo-multi-folder-children-internal folder)))
485 (unless (elmo-folder-exists-p (car flds))
487 (setq flds (cdr flds)))
490 (luna-define-method elmo-folder-creatable-p ((folder elmo-multi-folder))
491 (let ((flds (elmo-multi-folder-children-internal folder)))
494 (when (and (elmo-folder-creatable-p (car flds))
495 (not (elmo-folder-exists-p (car flds))))
496 ;; If folder already exists, don't to `creatable'.
497 ;; Because this function is called, when folder doesn't exists.
498 (throw 'creatable t))
499 (setq flds (cdr flds)))
502 (luna-define-method elmo-folder-create ((folder elmo-multi-folder))
503 (let ((flds (elmo-multi-folder-children-internal folder)))
506 (unless (or (elmo-folder-exists-p (car flds))
507 (elmo-folder-create (car flds)))
509 (setq flds (cdr flds)))
512 (luna-define-method elmo-folder-search ((folder elmo-multi-folder)
513 condition &optional numlist)
514 (let* ((flds (elmo-multi-folder-children-internal folder))
516 numlist-list cur-numlist ; for filtered search.
520 (elmo-multi-split-numbers folder numlist t)))
522 (setq cur-number (+ cur-number 1))
524 (setq cur-numlist (car numlist-list))
525 (if (null cur-numlist)
526 ;; t means filter all.
527 (setq cur-numlist t)))
528 (setq ret-val (append
536 (* (elmo-multi-folder-divide-number-internal
537 folder) cur-number) x)))
539 (car flds) condition)))))
541 (setq numlist-list (cdr numlist-list)))
542 (setq flds (cdr flds)))
545 (luna-define-method elmo-message-use-cache-p ((folder elmo-multi-folder)
547 (let ((pair (elmo-multi-real-folder-number folder number)))
548 (elmo-message-use-cache-p (car pair) (cdr pair))))
550 (luna-define-method elmo-message-file-p ((folder elmo-multi-folder) number)
551 (let ((pair (elmo-multi-real-folder-number folder number)))
552 (elmo-message-file-p (car pair) (cdr pair))))
554 (luna-define-method elmo-message-file-name ((folder elmo-multi-folder) number)
555 (let ((pair (elmo-multi-real-folder-number folder number)))
556 (elmo-message-file-name (car pair) (cdr pair))))
558 (luna-define-method elmo-folder-plugged-p ((folder elmo-multi-folder))
559 (let ((flds (elmo-multi-folder-children-internal folder)))
562 (unless (elmo-folder-plugged-p (car flds))
563 (throw 'plugged nil))
564 (setq flds (cdr flds)))
567 (luna-define-method elmo-folder-set-plugged ((folder elmo-multi-folder)
569 (let ((flds (elmo-multi-folder-children-internal folder)))
571 (elmo-folder-set-plugged fld plugged add))))
573 (defun elmo-multi-folder-numbers-list-assoc (folder folder-numbers)
575 (while folder-numbers
576 (when (string= (elmo-folder-name-internal (car (car folder-numbers)))
577 (elmo-folder-name-internal folder))
578 (setq ent (car folder-numbers)
580 (setq folder-numbers (cdr folder-numbers)))
583 (defun elmo-multi-make-folder-numbers-list (folder msgs)
584 (let ((msg-list msgs)
588 (when (and (numberp (car msg-list))
589 (> (car msg-list) 0))
590 (setq pair (elmo-multi-real-folder-number folder (car msg-list)))
591 (if (setq fld-list (elmo-multi-folder-numbers-list-assoc
594 (setcdr fld-list (cons (cdr pair) (cdr fld-list)))
595 (setq ret-val (cons (cons (car pair) (list (cdr pair))) ret-val))))
596 (setq msg-list (cdr msg-list)))
599 (luna-define-method elmo-folder-mark-as-important :before ((folder
604 (dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
605 (elmo-folder-mark-as-important (car folder-numbers)
609 (luna-define-method elmo-folder-unmark-important :before ((folder
614 (dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
615 (elmo-folder-unmark-important (car folder-numbers)
619 (luna-define-method elmo-folder-mark-as-read :before ((folder
622 &optional ignore-flag)
623 (dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
624 (elmo-folder-mark-as-read (car folder-numbers)
628 (luna-define-method elmo-folder-unmark-read :before ((folder
631 &optional ignore-flag)
632 (dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
633 (elmo-folder-unmark-read (car folder-numbers)
637 (luna-define-method elmo-folder-mark-as-answered :before ((folder
640 (dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
641 (elmo-folder-mark-as-answered (car folder-numbers)
642 (cdr folder-numbers))))
644 (luna-define-method elmo-folder-unmark-answered :before ((folder
647 (dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
648 (elmo-folder-unmark-answered (car folder-numbers)
649 (cdr folder-numbers))))
652 (product-provide (provide 'elmo-multi) (require 'elmo-version))
654 ;;; elmo-multi.el ends here