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.
36 (luna-define-class elmo-multi-folder (elmo-folder)
37 (children divide-number))
38 (luna-define-internal-accessors 'elmo-multi-folder))
40 (luna-define-method elmo-folder-initialize ((folder
43 (elmo-multi-folder-set-children-internal
45 (mapcar 'elmo-make-folder (split-string name ",")))
46 (elmo-multi-folder-set-divide-number-internal
48 elmo-multi-divide-number)
51 (luna-define-method elmo-folder-open-internal ((folder elmo-multi-folder))
52 (dolist (fld (elmo-multi-folder-children-internal folder))
53 (elmo-folder-open-internal fld)))
55 (luna-define-method elmo-folder-check ((folder elmo-multi-folder))
56 (dolist (fld (elmo-multi-folder-children-internal folder))
57 (elmo-folder-check fld)))
59 (luna-define-method elmo-folder-close-internal ((folder elmo-multi-folder))
60 (dolist (fld (elmo-multi-folder-children-internal folder))
61 (elmo-folder-close-internal fld)))
63 (luna-define-method elmo-folder-expand-msgdb-path ((folder
65 (expand-file-name (elmo-replace-string-as-filename
66 (elmo-folder-name-internal folder))
67 (expand-file-name "multi"
70 (luna-define-method elmo-folder-get-primitive-list ((folder elmo-multi-folder))
73 'elmo-folder-get-primitive-list
74 (elmo-multi-folder-children-internal folder))))
76 (luna-define-method elmo-folder-contains-type ((folder elmo-multi-folder) type)
77 (let ((children (elmo-multi-folder-children-internal folder))
80 (when (elmo-folder-contains-type (car children) type)
83 (setq children (cdr children)))
86 (luna-define-method elmo-message-use-cache-p ((folder elmo-multi-folder)
88 (elmo-message-use-cache-p
89 (nth (- (/ number (elmo-multi-folder-divide-number-internal folder)) 1)
90 (elmo-multi-folder-children-internal folder))
91 (% number (elmo-multi-folder-divide-number-internal folder))))
93 (luna-define-method elmo-message-folder ((folder elmo-multi-folder)
95 (nth (- (/ number (elmo-multi-folder-divide-number-internal folder)) 1)
96 (elmo-multi-folder-children-internal folder)))
98 (defun elmo-multi-msgdb (msgdb base)
99 (list (mapcar (function
101 (elmo-msgdb-overview-entity-set-number
104 (elmo-msgdb-overview-entity-get-number x)))))
114 (cdr x)))) (nth 2 msgdb))))
116 (defun elmo-multi-split-numbers (folder numlist &optional as-is)
117 (let ((numbers (sort numlist '<))
118 (divider (elmo-multi-folder-divide-number-internal folder))
120 one-list numbers-list)
122 (setq cur-number (+ cur-number 1))
127 (* divider cur-number))
129 (setq one-list (nconc
135 (* divider cur-number))))))
136 (setq numbers (cdr numbers)))
137 (setq numbers-list (nconc numbers-list (list one-list))))
140 (luna-define-method elmo-folder-msgdb-create ((folder elmo-multi-folder)
141 numbers new-mark already-mark
142 seen-mark important-mark
144 (let* ((folders (elmo-multi-folder-children-internal folder))
145 overview number-alist mark-alist entity
150 (setq numbers-list (elmo-multi-split-numbers folder numbers))
152 (while (< cur-number (length folders))
153 (if (nth cur-number numbers-list)
158 (elmo-folder-msgdb-create (nth cur-number folders)
159 (nth cur-number numbers-list)
160 new-mark already-mark
161 seen-mark important-mark
163 (* (elmo-multi-folder-divide-number-internal folder)
165 (setq cur-number (1+ cur-number)))
166 (elmo-msgdb-sort-by-date msgdb)))
168 (defsubst elmo-multi-folder-append-msgdb (folder append-msgdb)
169 (let* ((number-alist (elmo-msgdb-get-number-alist append-msgdb))
170 (all-alist (copy-sequence (append
171 (elmo-msgdb-get-number-alist
172 (elmo-folder-msgdb-internal folder))
178 (setq all-alist (delq (car cur) all-alist))
179 ;; same message id exists.
180 (if (setq same (rassoc (cdr (car cur)) all-alist))
181 (unless (= (/ (car (car cur))
182 (elmo-multi-folder-divide-number-internal folder))
184 (elmo-multi-folder-divide-number-internal folder)))
185 ;; base is also same...delete it!
186 (setq to-be-deleted (append to-be-deleted (list (car cur))))))
187 (setq cur (cdr cur)))
188 (setq mark-alist (elmo-delete-if
191 (assq (car x) to-be-deleted)))
192 (elmo-msgdb-get-mark-alist append-msgdb)))
193 (elmo-msgdb-set-mark-alist append-msgdb mark-alist)
194 (elmo-folder-set-msgdb-internal folder
196 (elmo-folder-msgdb-internal folder)
198 (length to-be-deleted)))
200 (luna-define-method elmo-folder-append-msgdb ((folder elmo-multi-folder)
202 (elmo-multi-folder-append-msgdb folder append-msgdb))
204 (defmacro elmo-multi-real-folder-number (folder number)
205 "Returns a cons cell of real FOLDER and NUMBER."
208 (elmo-multi-folder-divide-number-internal (, folder)))
209 1) (elmo-multi-folder-children-internal (, folder)))
210 (% (, number) (elmo-multi-folder-divide-number-internal
213 (defsubst elmo-multi-find-fetch-strategy (folder entity ignore-cache)
215 (let ((pair (elmo-multi-real-folder-number
217 (elmo-msgdb-overview-entity-get-number entity)))
218 (new-entity (elmo-msgdb-copy-overview-entity entity)))
220 (elmo-msgdb-overview-entity-set-number new-entity (cdr pair)))
221 (elmo-find-fetch-strategy (car pair) new-entity ignore-cache))
222 (elmo-make-fetch-strategy 'entire)))
224 (luna-define-method elmo-find-fetch-strategy
225 ((folder elmo-multi-folder)
226 entity &optional ignore-cache)
227 (elmo-multi-find-fetch-strategy folder entity ignore-cache))
229 (luna-define-method elmo-message-fetch ((folder elmo-multi-folder)
231 &optional section outbuf unseen)
232 (let ((pair (elmo-multi-real-folder-number folder number)))
233 (elmo-message-fetch (car pair) (cdr pair) strategy section outbuf unseen)))
235 (luna-define-method elmo-folder-delete-messages ((folder elmo-multi-folder)
237 (let ((flds (elmo-multi-folder-children-internal folder))
240 (setq one-list-list (elmo-multi-split-numbers folder numbers))
241 (while (< cur-number (length flds))
242 (elmo-folder-delete-messages (nth cur-number flds)
243 (nth cur-number one-list-list))
244 (setq cur-number (+ 1 cur-number)))
247 (luna-define-method elmo-folder-diff ((folder elmo-multi-folder)
249 (elmo-multi-folder-diff folder numbers))
251 (defun elmo-multi-folder-diff (folder numbers)
252 (let ((flds (elmo-multi-folder-children-internal folder))
253 (numbers (mapcar 'car
254 (elmo-msgdb-number-load
255 (elmo-folder-msgdb-path folder))))
256 (killed (elmo-msgdb-killed-list-load (elmo-folder-msgdb-path folder)))
263 (elmo-multi-split-numbers folder
266 (elmo-number-set-to-number-list killed)
269 (setq diffs (nconc diffs (list (elmo-folder-diff
272 (setq count (+ 1 count))
273 (setq num-list (cdr num-list))
274 (setq flds (cdr flds)))
276 (and (car (car diffs))
277 (setq unsync (+ unsync (car (car diffs)))))
278 (setq messages (+ messages (cdr (car diffs))))
279 (setq diffs (cdr diffs)))
280 (elmo-folder-set-info-hashtb folder nil messages)
281 (cons unsync messages)))
283 (defun elmo-multi-split-mark-alist (folder mark-alist)
285 (alist (sort (copy-sequence mark-alist)
286 (lambda (pair1 pair2)
287 (< (car pair1)(car pair2)))))
290 (setq cur-number (+ cur-number 1))
294 (/ (- (car (car alist))
295 (* (elmo-multi-folder-divide-number-internal
297 (elmo-multi-folder-divide-number-internal folder))))
298 (setq one-alist (nconc
301 (list (% (car (car alist))
302 (* (elmo-multi-folder-divide-number-internal
304 (cadr (car alist))))))
305 (setq alist (cdr alist)))
306 (setq result (nconc result (list one-alist))))
309 (luna-define-method elmo-folder-list-unreads-internal
310 ((folder elmo-multi-folder) unread-marks)
311 (elmo-multi-folder-list-unreads-internal folder unread-marks))
313 (defun elmo-multi-folder-list-unreads-internal (folder unread-marks)
314 (let ((folders (elmo-multi-folder-children-internal folder))
315 (mark-alists (elmo-multi-split-mark-alist
317 (elmo-msgdb-get-mark-alist
318 (elmo-folder-msgdb-internal folder))))
323 (setq cur-number (+ cur-number 1))
324 (unless (listp (setq unreads
325 (elmo-folder-list-unreads-internal
326 (car folders) unread-marks)))
327 (setq unreads (delq nil
330 (if (member (cadr x) unread-marks)
332 (car mark-alists)))))
339 (elmo-multi-folder-divide-number-internal
342 (setq mark-alists (cdr mark-alists)
343 folders (cdr folders)))
346 (luna-define-method elmo-folder-list-importants-internal
347 ((folder elmo-multi-folder) important-mark)
348 (let ((folders (elmo-multi-folder-children-internal folder))
349 (mark-alists (elmo-multi-split-mark-alist
351 (elmo-msgdb-get-mark-alist
352 (elmo-folder-msgdb-internal folder))))
357 (setq cur-number (+ cur-number 1))
358 (unless (listp (setq importants
359 (elmo-folder-list-importants-internal
360 (car folders) important-mark)))
361 (setq importants (delq nil
364 (if (string= (cadr x) important-mark)
366 (car mark-alists)))))
368 (nconc all-importants
373 (elmo-multi-folder-divide-number-internal
376 (setq mark-alists (cdr mark-alists)
377 folders (cdr folders)))
380 (luna-define-method elmo-folder-list-messages-internal
381 ((folder elmo-multi-folder))
382 (let* ((flds (elmo-multi-folder-children-internal folder))
386 (setq cur-number (+ cur-number 1))
387 (setq numbers (append
393 (* (elmo-multi-folder-divide-number-internal
394 folder) cur-number) x)))
395 (elmo-folder-list-messages-internal (car flds)))))
396 (setq flds (cdr flds)))
399 (luna-define-method elmo-folder-exists-p ((folder elmo-multi-folder))
400 (let ((flds (elmo-multi-folder-children-internal folder)))
403 (unless (elmo-folder-exists-p (car flds))
405 (setq flds (cdr flds)))
408 (luna-define-method elmo-folder-creatable-p ((folder elmo-multi-folder))
409 (let ((flds (elmo-multi-folder-children-internal folder)))
412 (when (and (elmo-folder-creatable-p (car flds))
413 (not (elmo-folder-exists-p (car flds))))
414 ;; If folder already exists, don't to `creatable'.
415 ;; Because this function is called, when folder doesn't exists.
416 (throw 'creatable t))
417 (setq flds (cdr flds)))
420 (luna-define-method elmo-folder-create ((folder elmo-multi-folder))
421 (let ((flds (elmo-multi-folder-children-internal folder)))
424 (unless (or (elmo-folder-exists-p (car flds))
425 (elmo-folder-create (car flds)))
427 (setq flds (cdr flds)))
430 (luna-define-method elmo-folder-search ((folder elmo-multi-folder)
431 condition &optional numlist)
432 (let* ((flds (elmo-multi-folder-children-internal folder))
434 numlist-list cur-numlist ; for filtered search.
438 (elmo-multi-split-numbers folder numlist t)))
440 (setq cur-number (+ cur-number 1))
442 (setq cur-numlist (car numlist-list))
443 (if (null cur-numlist)
444 ;; t means filter all.
445 (setq cur-numlist t)))
446 (setq ret-val (append
454 (* (elmo-multi-folder-divide-number-internal
455 folder) cur-number) x)))
457 (car flds) condition)))))
459 (setq numlist-list (cdr numlist-list)))
460 (setq flds (cdr flds)))
463 (luna-define-method elmo-message-use-cache-p ((folder elmo-multi-folder)
465 (let ((pair (elmo-multi-real-folder-number folder number)))
466 (elmo-message-use-cache-p (car pair) (cdr pair))))
468 (luna-define-method elmo-message-file-p ((folder elmo-multi-folder) number)
469 (let ((pair (elmo-multi-real-folder-number folder number)))
470 (elmo-message-file-p (car pair) (cdr pair))))
472 (luna-define-method elmo-message-file-name ((folder elmo-multi-folder) number)
473 (let ((pair (elmo-multi-real-folder-number folder number)))
474 (elmo-message-file-name (car pair) (cdr pair))))
476 (luna-define-method elmo-folder-plugged-p ((folder elmo-multi-folder))
477 (let ((flds (elmo-multi-folder-children-internal folder)))
480 (unless (elmo-folder-plugged-p (car flds))
481 (throw 'plugged nil))
482 (setq flds (cdr flds)))
485 (luna-define-method elmo-folder-set-plugged ((folder elmo-multi-folder)
487 (let ((flds (elmo-multi-folder-children-internal folder)))
489 (elmo-folder-set-plugged fld plugged add))))
491 (defun elmo-multi-folder-numbers-list-assoc (folder folder-numbers)
493 (while folder-numbers
494 (when (string= (elmo-folder-name-internal (car (car folder-numbers)))
495 (elmo-folder-name-internal folder))
496 (setq ent (car folder-numbers)
498 (setq folder-numbers (cdr folder-numbers)))
501 (defun elmo-multi-make-folder-numbers-list (folder msgs)
502 (let ((msg-list msgs)
506 (when (and (numberp (car msg-list))
507 (> (car msg-list) 0))
508 (setq pair (elmo-multi-real-folder-number folder (car msg-list)))
509 (if (setq fld-list (elmo-multi-folder-numbers-list-assoc
512 (setcdr fld-list (cons (cdr pair) (cdr fld-list)))
513 (setq ret-val (cons (cons (car pair) (list (cdr pair))) ret-val))))
514 (setq msg-list (cdr msg-list)))
517 (luna-define-method elmo-folder-mark-as-important ((folder elmo-multi-folder)
519 (dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
520 (elmo-folder-mark-as-important (car folder-numbers)
521 (cdr folder-numbers)))
524 (luna-define-method elmo-folder-unmark-important ((folder elmo-multi-folder)
526 (dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
527 (elmo-folder-unmark-important (car folder-numbers)
528 (cdr folder-numbers)))
531 (luna-define-method elmo-folder-mark-as-read ((folder elmo-multi-folder)
533 (dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
534 (elmo-folder-mark-as-read (car folder-numbers)
535 (cdr folder-numbers)))
538 (luna-define-method elmo-folder-unmark-read ((folder elmo-multi-folder)
540 (dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
541 (elmo-folder-unmark-read (car folder-numbers)
542 (cdr folder-numbers)))
546 (product-provide (provide 'elmo-multi) (require 'elmo-version))
548 ;;; elmo-multi.el ends here