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-expand-msgdb-path ((folder
76
(expand-file-name (elmo-replace-string-as-filename
77
(elmo-folder-name-internal folder))
78
(expand-file-name "multi"
79
elmo-msgdb-directory)))
81
(luna-define-method elmo-folder-newsgroups ((folder elmo-multi-folder))
85
'elmo-folder-newsgroups
88
'elmo-folder-get-primitive-list
89
(elmo-multi-folder-children-internal folder)))))))
91
(luna-define-method elmo-folder-get-primitive-list ((folder elmo-multi-folder))
94
'elmo-folder-get-primitive-list
95
(elmo-multi-folder-children-internal folder))))
97
(luna-define-method elmo-folder-contains-type ((folder elmo-multi-folder) type)
98
(let ((children (elmo-multi-folder-children-internal folder))
101
(when (elmo-folder-contains-type (car children) type)
104
(setq children (cdr children)))
107
(luna-define-method elmo-message-folder ((folder elmo-multi-folder)
109
(nth (- (/ number (elmo-multi-folder-divide-number-internal folder)) 1)
110
(elmo-multi-folder-children-internal folder)))
112
(defun elmo-multi-msgdb (msgdb base)
113
(list (mapcar (function
115
(elmo-msgdb-overview-entity-set-number
118
(elmo-msgdb-overview-entity-get-number x)))))
128
(cdr x)))) (nth 2 msgdb))))
130
(defun elmo-multi-split-numbers (folder numlist &optional as-is)
131
(let ((numbers (sort numlist '<))
132
(divider (elmo-multi-folder-divide-number-internal folder))
134
one-list numbers-list)
136
(setq cur-number (+ cur-number 1))
141
(* divider cur-number))
143
(setq one-list (nconc
149
(* divider cur-number))))))
150
(setq numbers (cdr numbers)))
151
(setq numbers-list (nconc numbers-list (list one-list))))
154
(luna-define-method elmo-folder-msgdb-create ((folder elmo-multi-folder)
155
numbers new-mark already-mark
156
seen-mark important-mark
158
(let* ((folders (elmo-multi-folder-children-internal folder))
159
overview number-alist mark-alist entity
164
(setq numbers-list (elmo-multi-split-numbers folder numbers))
166
(while (< cur-number (length folders))
167
(if (nth cur-number numbers-list)
172
(elmo-folder-msgdb-create (nth cur-number folders)
173
(nth cur-number numbers-list)
174
new-mark already-mark
175
seen-mark important-mark
177
(* (elmo-multi-folder-divide-number-internal folder)
179
(setq cur-number (1+ cur-number)))
180
(elmo-msgdb-sort-by-date msgdb)))
182
(luna-define-method elmo-folder-process-crosspost ((folder elmo-multi-folder)
185
(let ((number-alists (elmo-multi-split-number-alist
187
(elmo-msgdb-get-number-alist
188
(elmo-folder-msgdb folder))))
190
(dolist (child (elmo-multi-folder-children-internal folder))
191
(elmo-folder-process-crosspost child (car number-alists))
192
(setq cur-number (+ 1 cur-number)
193
number-alists (cdr number-alists)))))
195
(defsubst elmo-multi-folder-append-msgdb (folder append-msgdb)
197
(let* ((number-alist (elmo-msgdb-get-number-alist append-msgdb))
198
(all-alist (copy-sequence (append
199
(elmo-msgdb-get-number-alist
200
(elmo-folder-msgdb folder))
203
overview to-be-deleted
206
(setq all-alist (delq (car cur) all-alist))
207
;; same message id exists.
208
(if (setq same (rassoc (cdr (car cur)) all-alist))
209
(unless (= (/ (car (car cur))
210
(elmo-multi-folder-divide-number-internal folder))
212
(elmo-multi-folder-divide-number-internal folder)))
213
;; base is also same...delete it!
215
(append to-be-deleted (list (car (car cur)))))))
216
(setq cur (cdr cur)))
217
(cond ((eq (elmo-folder-process-duplicates-internal folder)
220
(elmo-msgdb-append-to-killed-list folder to-be-deleted)
221
(setq overview (elmo-delete-if
223
(memq (elmo-msgdb-overview-entity-get-number
226
(elmo-msgdb-get-overview append-msgdb)))
227
;; Should be mark as read.
228
(elmo-folder-mark-as-read folder to-be-deleted)
229
(elmo-msgdb-set-overview append-msgdb overview))
230
((eq (elmo-folder-process-duplicates-internal folder)
232
;; Mark as read duplicates.
233
(elmo-folder-mark-as-read folder to-be-deleted))
236
(setq to-be-deleted nil)))
237
(elmo-folder-set-msgdb-internal folder
239
(elmo-folder-msgdb folder)
241
(length to-be-deleted))
244
(luna-define-method elmo-folder-append-msgdb ((folder elmo-multi-folder)
246
(elmo-multi-folder-append-msgdb folder append-msgdb))
248
(defmacro elmo-multi-real-folder-number (folder number)
249
"Returns a cons cell of real FOLDER and NUMBER."
252
(elmo-multi-folder-divide-number-internal (, folder)))
253
1) (elmo-multi-folder-children-internal (, folder)))
254
(% (, number) (elmo-multi-folder-divide-number-internal
257
(defsubst elmo-multi-find-fetch-strategy (folder entity ignore-cache)
259
(let ((pair (elmo-multi-real-folder-number
261
(elmo-msgdb-overview-entity-get-number entity)))
262
(new-entity (elmo-msgdb-copy-overview-entity entity)))
264
(elmo-msgdb-overview-entity-set-number new-entity (cdr pair)))
265
(elmo-find-fetch-strategy (car pair) new-entity ignore-cache))
266
(elmo-make-fetch-strategy 'entire)))
268
(luna-define-method elmo-find-fetch-strategy
269
((folder elmo-multi-folder)
270
entity &optional ignore-cache)
271
(elmo-multi-find-fetch-strategy folder entity ignore-cache))
273
(luna-define-method elmo-message-fetch ((folder elmo-multi-folder)
275
&optional section outbuf unseen)
276
(let ((pair (elmo-multi-real-folder-number folder number)))
277
(elmo-message-fetch (car pair) (cdr pair) strategy section outbuf unseen)))
279
(luna-define-method elmo-folder-delete-messages ((folder elmo-multi-folder)
281
(let ((flds (elmo-multi-folder-children-internal folder))
284
(setq one-list-list (elmo-multi-split-numbers folder numbers))
285
(while (< cur-number (length flds))
286
(elmo-folder-delete-messages (nth cur-number flds)
287
(nth cur-number one-list-list))
288
(setq cur-number (+ 1 cur-number)))
291
(luna-define-method elmo-folder-diff ((folder elmo-multi-folder)
293
(elmo-multi-folder-diff folder numbers))
295
(defun elmo-multi-folder-diff (folder numbers)
296
(let ((flds (elmo-multi-folder-children-internal folder))
297
(numbers (mapcar 'car
298
(elmo-msgdb-number-load
299
(elmo-folder-msgdb-path folder))))
300
(killed (elmo-msgdb-killed-list-load (elmo-folder-msgdb-path folder)))
306
;; If first time, dummy numbers is used as current number list.
309
(divider (elmo-multi-folder-divide-number-internal folder)))
310
(dolist (folder flds)
313
(cons (* i divider) numbers)))))
315
(elmo-multi-split-numbers folder
318
(elmo-number-set-to-number-list killed)
321
(setq nums (elmo-folder-diff (car flds) (car num-list))
322
nums (cons (elmo-diff-unread nums) (elmo-diff-all nums)))
323
(setq diffs (nconc diffs (list nums)))
324
(setq count (+ 1 count))
325
(setq num-list (cdr num-list))
326
(setq flds (cdr flds)))
328
(and (car (car diffs))
329
(setq unsync (+ unsync (car (car diffs)))))
330
(setq messages (+ messages (cdr (car diffs))))
331
(setq diffs (cdr diffs)))
332
(elmo-folder-set-info-hashtb folder nil messages)
333
(cons unsync messages)))
335
(defun elmo-multi-split-number-alist (folder number-alist)
336
(let ((alist (sort (copy-sequence number-alist)
337
(lambda (pair1 pair2)
338
(< (car pair1)(car pair2)))))
342
(setq cur-number (+ cur-number 1))
346
(/ (- (setq num (car (car alist)))
347
(* elmo-multi-divide-number cur-number))
348
(elmo-multi-folder-divide-number-internal folder))))
349
(setq one-alist (nconc
353
(% num (* (elmo-multi-folder-divide-number-internal
355
(cdr (car alist))))))
356
(setq alist (cdr alist)))
357
(setq split (nconc split (list one-alist))))
360
(defun elmo-multi-split-mark-alist (folder mark-alist)
362
(alist (sort (copy-sequence mark-alist)
363
(lambda (pair1 pair2)
364
(< (car pair1)(car pair2)))))
367
(setq cur-number (+ cur-number 1))
371
(/ (- (car (car alist))
372
(* (elmo-multi-folder-divide-number-internal
374
(elmo-multi-folder-divide-number-internal folder))))
375
(setq one-alist (nconc
378
(list (% (car (car alist))
379
(* (elmo-multi-folder-divide-number-internal
381
(cadr (car alist))))))
382
(setq alist (cdr alist)))
383
(setq result (nconc result (list one-alist))))
386
(luna-define-method elmo-folder-list-unreads-internal
387
((folder elmo-multi-folder) unread-marks &optional mark-alist)
388
(elmo-multi-folder-list-unreads-internal folder unread-marks))
390
(defun elmo-multi-folder-list-unreads-internal (folder unread-marks)
391
(let ((folders (elmo-multi-folder-children-internal folder))
392
(mark-alists (elmo-multi-split-mark-alist
394
(elmo-msgdb-get-mark-alist
395
(elmo-folder-msgdb folder))))
400
(setq cur-number (+ cur-number 1))
401
(unless (listp (setq unreads
402
(elmo-folder-list-unreads-internal
403
(car folders) unread-marks (car mark-alists))))
404
(setq unreads (delq nil
407
(if (member (cadr x) unread-marks)
409
(car mark-alists)))))
416
(elmo-multi-folder-divide-number-internal
419
(setq mark-alists (cdr mark-alists)
420
folders (cdr folders)))
423
(luna-define-method elmo-folder-list-importants-internal
424
((folder elmo-multi-folder) important-mark)
425
(let ((folders (elmo-multi-folder-children-internal folder))
426
(mark-alists (elmo-multi-split-mark-alist
428
(elmo-msgdb-get-mark-alist
429
(elmo-folder-msgdb folder))))
434
(setq cur-number (+ cur-number 1))
435
(when (listp (setq importants
436
(elmo-folder-list-importants-internal
437
(car folders) important-mark)))
439
(nconc all-importants
444
(elmo-multi-folder-divide-number-internal
447
(setq mark-alists (cdr mark-alists)
448
folders (cdr folders)))
451
(luna-define-method elmo-folder-list-messages-internal
452
((folder elmo-multi-folder) &optional nohide)
453
(let* ((flds (elmo-multi-folder-children-internal folder))
457
(setq cur-number (+ cur-number 1))
458
(setq list (elmo-folder-list-messages-internal (car flds)))
467
(* (elmo-multi-folder-divide-number-internal
468
folder) cur-number) x)))
474
(eq cur-number (/ num
475
(elmo-multi-folder-divide-number-internal
479
(elmo-msgdb-get-number-alist
480
(elmo-folder-msgdb folder)))))))
481
(setq flds (cdr flds)))
484
(luna-define-method elmo-folder-exists-p ((folder elmo-multi-folder))
485
(let ((flds (elmo-multi-folder-children-internal folder)))
488
(unless (elmo-folder-exists-p (car flds))
490
(setq flds (cdr flds)))
493
(luna-define-method elmo-folder-creatable-p ((folder elmo-multi-folder))
494
(let ((flds (elmo-multi-folder-children-internal folder)))
497
(when (and (elmo-folder-creatable-p (car flds))
498
(not (elmo-folder-exists-p (car flds))))
499
;; If folder already exists, don't to `creatable'.
500
;; Because this function is called, when folder doesn't exists.
501
(throw 'creatable t))
502
(setq flds (cdr flds)))
505
(luna-define-method elmo-folder-create ((folder elmo-multi-folder))
506
(let ((flds (elmo-multi-folder-children-internal folder)))
509
(unless (or (elmo-folder-exists-p (car flds))
510
(elmo-folder-create (car flds)))
512
(setq flds (cdr flds)))
515
(luna-define-method elmo-folder-search ((folder elmo-multi-folder)
516
condition &optional numlist)
517
(let* ((flds (elmo-multi-folder-children-internal folder))
519
numlist-list cur-numlist ; for filtered search.
523
(elmo-multi-split-numbers folder numlist t)))
525
(setq cur-number (+ cur-number 1))
527
(setq cur-numlist (car numlist-list))
528
(if (null cur-numlist)
529
;; t means filter all.
530
(setq cur-numlist t)))
531
(setq ret-val (append
539
(* (elmo-multi-folder-divide-number-internal
540
folder) cur-number) x)))
542
(car flds) condition)))))
544
(setq numlist-list (cdr numlist-list)))
545
(setq flds (cdr flds)))
548
(luna-define-method elmo-message-use-cache-p ((folder elmo-multi-folder)
550
(let ((pair (elmo-multi-real-folder-number folder number)))
551
(elmo-message-use-cache-p (car pair) (cdr pair))))
553
(luna-define-method elmo-message-file-p ((folder elmo-multi-folder) number)
554
(let ((pair (elmo-multi-real-folder-number folder number)))
555
(elmo-message-file-p (car pair) (cdr pair))))
557
(luna-define-method elmo-message-file-name ((folder elmo-multi-folder) number)
558
(let ((pair (elmo-multi-real-folder-number folder number)))
559
(elmo-message-file-name (car pair) (cdr pair))))
561
(luna-define-method elmo-folder-plugged-p ((folder elmo-multi-folder))
562
(let ((flds (elmo-multi-folder-children-internal folder)))
565
(unless (elmo-folder-plugged-p (car flds))
566
(throw 'plugged nil))
567
(setq flds (cdr flds)))
570
(luna-define-method elmo-folder-set-plugged ((folder elmo-multi-folder)
572
(let ((flds (elmo-multi-folder-children-internal folder)))
574
(elmo-folder-set-plugged fld plugged add))))
576
(defun elmo-multi-folder-numbers-list-assoc (folder folder-numbers)
578
(while folder-numbers
579
(when (string= (elmo-folder-name-internal (car (car folder-numbers)))
580
(elmo-folder-name-internal folder))
581
(setq ent (car folder-numbers)
583
(setq folder-numbers (cdr folder-numbers)))
586
(defun elmo-multi-make-folder-numbers-list (folder msgs)
587
(let ((msg-list msgs)
591
(when (and (numberp (car msg-list))
592
(> (car msg-list) 0))
593
(setq pair (elmo-multi-real-folder-number folder (car msg-list)))
594
(if (setq fld-list (elmo-multi-folder-numbers-list-assoc
597
(setcdr fld-list (cons (cdr pair) (cdr fld-list)))
598
(setq ret-val (cons (cons (car pair) (list (cdr pair))) ret-val))))
599
(setq msg-list (cdr msg-list)))
602
(luna-define-method elmo-folder-mark-as-important ((folder elmo-multi-folder)
604
(dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
605
(elmo-folder-mark-as-important (car folder-numbers)
606
(cdr folder-numbers)))
609
(luna-define-method elmo-folder-unmark-important ((folder elmo-multi-folder)
611
(dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
612
(elmo-folder-unmark-important (car folder-numbers)
613
(cdr folder-numbers)))
616
(luna-define-method elmo-folder-mark-as-read ((folder elmo-multi-folder)
618
(dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
619
(elmo-folder-mark-as-read (car folder-numbers)
620
(cdr folder-numbers)))
623
(luna-define-method elmo-folder-unmark-read ((folder elmo-multi-folder)
625
(dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
626
(elmo-folder-unmark-read (car folder-numbers)
627
(cdr folder-numbers)))
631
(product-provide (provide 'elmo-multi) (require 'elmo-version))
633
;;; elmo-multi.el ends here