Fixed conventional headers. Use --- Instead of -- in the first line.
[elisp/wanderlust.git] / elmo / elmo-multi.el
1 ;;; elmo-multi.el --- Multiple Folder Interface for ELMO.
2
3 ;; Copyright (C) 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
4
5 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Keywords: mail, net news
7
8 ;; This file is part of ELMO (Elisp Library for Message Orchestration).
9
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)
13 ;; any later version.
14 ;;
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.
19 ;;
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.
24 ;;
25
26 ;;; Commentary:
27 ;;
28
29 ;;; Code:
30 ;;
31
32 (require 'elmo)
33 (require 'luna)
34
35 (defvar elmo-multi-divide-number 100000
36   "*Multi divider number.")
37
38 ;;; ELMO Multi folder
39 (eval-and-compile
40   (luna-define-class elmo-multi-folder (elmo-folder)
41                      (children divide-number))
42   (luna-define-internal-accessors 'elmo-multi-folder))
43
44 (luna-define-method elmo-folder-initialize ((folder
45                                              elmo-multi-folder)
46                                             name)
47   (while (> (length (car (setq name (elmo-parse-token name ",")))) 0)
48     (elmo-multi-folder-set-children-internal
49      folder
50      (nconc (elmo-multi-folder-children-internal
51              folder)
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
58    folder
59    elmo-multi-divide-number)
60   folder)
61
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)))
65
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)))
69
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)))
73
74 (luna-define-method elmo-folder-expand-msgdb-path ((folder
75                                                     elmo-multi-folder))
76   (expand-file-name (elmo-replace-string-as-filename
77                      (elmo-folder-name-internal folder))
78                     (expand-file-name "multi"
79                                       elmo-msgdb-dir)))
80
81 (luna-define-method elmo-folder-newsgroups ((folder elmo-multi-folder))
82   (delq nil
83         (elmo-flatten
84          (mapcar
85           'elmo-folder-newsgroups
86           (elmo-flatten
87            (mapcar
88             'elmo-folder-get-primitive-list
89             (elmo-multi-folder-children-internal folder)))))))
90
91 (luna-define-method elmo-folder-get-primitive-list ((folder elmo-multi-folder))
92   (elmo-flatten
93    (mapcar
94     'elmo-folder-get-primitive-list
95     (elmo-multi-folder-children-internal folder))))
96
97 (luna-define-method elmo-folder-contains-type ((folder elmo-multi-folder) type)
98   (let ((children (elmo-multi-folder-children-internal folder))
99         match)
100     (while children
101       (when (elmo-folder-contains-type (car children) type)
102         (setq match t)
103         (setq children nil))
104       (setq children (cdr children)))
105     match))
106
107 (luna-define-method elmo-message-use-cache-p ((folder elmo-multi-folder)
108                                              number)
109   (elmo-message-use-cache-p
110    (nth (- (/ number (elmo-multi-folder-divide-number-internal folder)) 1)
111         (elmo-multi-folder-children-internal folder))
112    (% number (elmo-multi-folder-divide-number-internal folder))))
113
114 (luna-define-method elmo-message-folder ((folder elmo-multi-folder)
115                                          number)
116   (nth (- (/ number (elmo-multi-folder-divide-number-internal folder)) 1)
117        (elmo-multi-folder-children-internal folder)))
118
119 (defun elmo-multi-msgdb (msgdb base)
120   (list (mapcar (function
121                  (lambda (x)
122                    (elmo-msgdb-overview-entity-set-number
123                     x
124                     (+ base
125                        (elmo-msgdb-overview-entity-get-number x)))))
126                 (nth 0 msgdb))
127         (mapcar (function
128                  (lambda (x) (cons
129                               (+ base (car x))
130                               (cdr x))))
131                 (nth 1 msgdb))
132         (mapcar (function
133                  (lambda (x) (cons
134                               (+ base (car x))
135                               (cdr x)))) (nth 2 msgdb))))
136
137 (defun elmo-multi-split-numbers (folder numlist &optional as-is)
138   (let ((numbers (sort numlist '<))
139         (divider (elmo-multi-folder-divide-number-internal folder))
140         (cur-number 0)
141         one-list numbers-list)
142     (while numbers
143       (setq cur-number (+ cur-number 1))
144       (setq one-list nil)
145       (while (and numbers
146                   (eq 0
147                       (/ (- (car numbers)
148                             (* divider cur-number))
149                          divider)))
150         (setq one-list (nconc
151                         one-list
152                         (list
153                          (if as-is
154                              (car numbers)
155                            (% (car numbers)
156                               (* divider cur-number))))))
157         (setq numbers (cdr numbers)))
158       (setq numbers-list (nconc numbers-list (list one-list))))
159     numbers-list))
160
161 (luna-define-method elmo-folder-msgdb-create ((folder elmo-multi-folder)
162                                               numbers new-mark already-mark
163                                               seen-mark important-mark
164                                               seen-list)
165   (let* ((folders (elmo-multi-folder-children-internal folder))
166          overview number-alist mark-alist entity
167          numbers-list
168          cur-number
169          i percent num
170          msgdb)
171     (setq numbers-list (elmo-multi-split-numbers folder numbers))
172     (setq cur-number 0)
173     (while (< cur-number (length folders))
174       (if (nth cur-number numbers-list)
175           (setq msgdb
176                 (elmo-msgdb-append
177                  msgdb
178                  (elmo-multi-msgdb
179                   (elmo-folder-msgdb-create (nth cur-number folders)
180                                             (nth cur-number numbers-list)
181                                             new-mark already-mark
182                                             seen-mark important-mark
183                                             seen-list)
184                   (* (elmo-multi-folder-divide-number-internal folder)
185                      (1+ cur-number))))))
186       (setq cur-number (1+ cur-number)))
187     (elmo-msgdb-sort-by-date msgdb)))
188
189 (luna-define-method elmo-folder-process-crosspost ((folder elmo-multi-folder)
190                                                    &optional
191                                                    number-alist)
192   (let ((number-alists (elmo-multi-split-number-alist
193                         folder
194                         (elmo-msgdb-get-number-alist
195                          (elmo-folder-msgdb folder))))
196         (cur-number 1))
197     (dolist (child (elmo-multi-folder-children-internal folder))
198       (elmo-folder-process-crosspost child (car number-alists))
199       (setq cur-number (+ 1 cur-number)
200             number-alists (cdr number-alists)))))
201
202 (defsubst elmo-multi-folder-append-msgdb (folder append-msgdb)
203   (if append-msgdb
204       (let* ((number-alist (elmo-msgdb-get-number-alist append-msgdb))
205              (all-alist (copy-sequence (append
206                                         (elmo-msgdb-get-number-alist
207                                          (elmo-folder-msgdb folder))
208                                         number-alist)))
209              (cur number-alist)
210              overview to-be-deleted
211              mark-alist same)
212         (while cur
213           (setq all-alist (delq (car cur) all-alist))
214           ;; same message id exists.
215           (if (setq same (rassoc (cdr (car cur)) all-alist))
216               (unless (= (/ (car (car cur))
217                             (elmo-multi-folder-divide-number-internal folder))
218                          (/ (car same)
219                             (elmo-multi-folder-divide-number-internal folder)))
220                 ;; base is also same...delete it!
221                 (setq to-be-deleted
222                       (append to-be-deleted (list (car (car cur)))))))
223           (setq cur (cdr cur)))
224         (cond ((eq (elmo-folder-process-duplicates-internal folder)
225                    'hide)
226                ;; Hide duplicates.
227                (elmo-msgdb-append-to-killed-list folder to-be-deleted)
228                (setq overview (elmo-delete-if
229                                (lambda (x)
230                                  (memq (elmo-msgdb-overview-entity-get-number
231                                         x)
232                                        to-be-deleted))
233                                (elmo-msgdb-get-overview append-msgdb)))
234                ;; Should be mark as read.
235                (elmo-folder-mark-as-read folder to-be-deleted)
236                (elmo-msgdb-set-overview append-msgdb overview))
237               ((eq (elmo-folder-process-duplicates-internal folder)
238                    'read)
239                ;; Mark as read duplicates.
240                (elmo-folder-mark-as-read folder to-be-deleted))
241               (t
242                ;; Do nothing.
243                (setq to-be-deleted nil)))
244         (elmo-folder-set-msgdb-internal folder
245                                         (elmo-msgdb-append
246                                          (elmo-folder-msgdb folder)
247                                          append-msgdb t))
248         (length to-be-deleted))
249     0))
250
251 (luna-define-method elmo-folder-append-msgdb ((folder elmo-multi-folder)
252                                               append-msgdb)
253   (elmo-multi-folder-append-msgdb folder append-msgdb))
254
255 (defmacro elmo-multi-real-folder-number (folder number)
256   "Returns a cons cell of real FOLDER and NUMBER."
257   (` (cons (nth (- 
258                  (/ (, number)
259                     (elmo-multi-folder-divide-number-internal (, folder)))
260                  1) (elmo-multi-folder-children-internal (, folder)))
261            (% (, number) (elmo-multi-folder-divide-number-internal
262                           (, folder))))))
263
264 (defsubst elmo-multi-find-fetch-strategy (folder entity ignore-cache)
265   (if entity
266       (let ((pair (elmo-multi-real-folder-number
267                    folder
268                    (elmo-msgdb-overview-entity-get-number entity)))
269             (new-entity (elmo-msgdb-copy-overview-entity entity)))
270         (setq new-entity
271               (elmo-msgdb-overview-entity-set-number new-entity (cdr pair)))
272         (elmo-find-fetch-strategy (car pair) new-entity ignore-cache))
273     (elmo-make-fetch-strategy 'entire)))
274
275 (luna-define-method elmo-find-fetch-strategy
276   ((folder elmo-multi-folder)
277    entity &optional ignore-cache)
278   (elmo-multi-find-fetch-strategy folder entity ignore-cache))
279
280 (luna-define-method elmo-message-fetch ((folder elmo-multi-folder)
281                                         number strategy
282                                         &optional section outbuf unseen)
283   (let ((pair (elmo-multi-real-folder-number folder number)))
284     (elmo-message-fetch (car pair) (cdr pair) strategy section outbuf unseen)))
285
286 (luna-define-method elmo-folder-delete-messages ((folder elmo-multi-folder)
287                                                  numbers)
288   (let ((flds (elmo-multi-folder-children-internal folder))
289         one-list-list
290         (cur-number 0))
291     (setq one-list-list (elmo-multi-split-numbers folder numbers))
292     (while (< cur-number (length flds))
293       (elmo-folder-delete-messages (nth cur-number flds)
294                                    (nth cur-number one-list-list))
295       (setq cur-number (+ 1 cur-number)))
296     t))
297
298 (luna-define-method elmo-folder-diff ((folder elmo-multi-folder)
299                                       &optional numbers)
300   (elmo-multi-folder-diff folder numbers))
301
302 (defun elmo-multi-folder-diff (folder numbers)
303   (let ((flds (elmo-multi-folder-children-internal folder))
304         (numbers (mapcar 'car
305                          (elmo-msgdb-number-load
306                           (elmo-folder-msgdb-path folder))))
307         (killed (elmo-msgdb-killed-list-load (elmo-folder-msgdb-path folder)))
308         (count 0)
309         (unsync 0)
310         (messages 0)
311         num-list
312         diffs nums)
313     ;; If first time, dummy numbers is used as current number list.
314     (unless numbers
315       (let ((i 0)
316             (divider (elmo-multi-folder-divide-number-internal folder)))
317         (dolist (folder flds)
318           (setq i (+ i 1))
319           (setq numbers
320                 (cons (* i divider) numbers)))))
321     (setq num-list
322           (elmo-multi-split-numbers folder
323                                     (elmo-uniq-list
324                                      (nconc
325                                       (elmo-number-set-to-number-list killed)
326                                       numbers))))
327     (while flds
328       (setq nums (elmo-folder-diff (car flds) (car num-list))
329             nums (cons (elmo-diff-unread nums) (elmo-diff-all nums)))
330       (setq diffs (nconc diffs (list nums)))
331       (setq count (+ 1 count))
332       (setq num-list (cdr num-list))
333       (setq flds (cdr flds)))
334     (while diffs
335       (and (car (car diffs))
336            (setq unsync (+ unsync (car (car diffs)))))
337       (setq messages  (+ messages (cdr (car diffs))))
338       (setq diffs (cdr diffs)))
339     (elmo-folder-set-info-hashtb folder nil messages)
340     (cons unsync messages)))
341
342 (defun elmo-multi-split-number-alist (folder number-alist)
343   (let ((alist (sort (copy-sequence number-alist)
344                      (lambda (pair1 pair2)
345                        (< (car pair1)(car pair2)))))
346         (cur-number 0)
347         one-alist split num)
348     (while alist
349       (setq cur-number (+ cur-number 1))
350       (setq one-alist nil)
351       (while (and alist
352                   (eq 0
353                       (/ (- (setq num (car (car alist)))
354                             (* elmo-multi-divide-number cur-number))
355                          (elmo-multi-folder-divide-number-internal folder))))
356         (setq one-alist (nconc
357                          one-alist
358                          (list
359                           (cons
360                            (% num (* (elmo-multi-folder-divide-number-internal
361                                       folder) cur-number))
362                            (cdr (car alist))))))
363         (setq alist (cdr alist)))
364       (setq split (nconc split (list one-alist))))
365     split))
366
367 (defun elmo-multi-split-mark-alist (folder mark-alist)
368   (let ((cur-number 0)
369         (alist (sort (copy-sequence mark-alist)
370                      (lambda (pair1 pair2)
371                        (< (car pair1)(car pair2)))))
372         one-alist result)
373     (while alist
374       (setq cur-number (+ cur-number 1))
375       (setq one-alist nil)
376       (while (and alist
377                   (eq 0
378                       (/ (- (car (car alist))
379                             (* (elmo-multi-folder-divide-number-internal
380                                 folder) cur-number))
381                          (elmo-multi-folder-divide-number-internal folder))))
382         (setq one-alist (nconc
383                          one-alist
384                          (list
385                           (list (% (car (car alist))
386                                    (* (elmo-multi-folder-divide-number-internal
387                                        folder) cur-number))
388                                 (cadr (car alist))))))
389         (setq alist (cdr alist)))
390       (setq result (nconc result (list one-alist))))
391     result))
392
393 (luna-define-method elmo-folder-list-unreads-internal
394   ((folder elmo-multi-folder) unread-marks &optional mark-alist)
395   (elmo-multi-folder-list-unreads-internal folder unread-marks))
396
397 (defun elmo-multi-folder-list-unreads-internal (folder unread-marks)
398   (let ((folders (elmo-multi-folder-children-internal folder))
399         (mark-alists (elmo-multi-split-mark-alist
400                       folder
401                       (elmo-msgdb-get-mark-alist
402                        (elmo-folder-msgdb folder))))
403         (cur-number 0)
404         unreads
405         all-unreads)
406     (while folders
407       (setq cur-number (+ cur-number 1))
408       (unless (listp (setq unreads
409                            (elmo-folder-list-unreads-internal
410                             (car folders) unread-marks (car mark-alists))))
411         (setq unreads (delq  nil
412                              (mapcar
413                               (lambda (x)
414                                 (if (member (cadr x) unread-marks)
415                                     (car x)))
416                               (car mark-alists)))))
417       (setq all-unreads
418             (nconc all-unreads
419                    (mapcar 
420                     (lambda (x)
421                       (+ x
422                          (* cur-number
423                             (elmo-multi-folder-divide-number-internal
424                              folder))))            
425                     unreads)))
426       (setq mark-alists (cdr mark-alists)
427             folders (cdr folders)))
428     all-unreads))
429
430 (luna-define-method elmo-folder-list-importants-internal
431   ((folder elmo-multi-folder) important-mark)
432   (let ((folders (elmo-multi-folder-children-internal folder))
433         (mark-alists (elmo-multi-split-mark-alist
434                       folder
435                       (elmo-msgdb-get-mark-alist
436                        (elmo-folder-msgdb folder))))
437         (cur-number 0)
438         importants
439         all-importants)
440     (while folders
441       (setq cur-number (+ cur-number 1))
442       (when (listp (setq importants
443                          (elmo-folder-list-importants-internal
444                           (car folders) important-mark)))
445         (setq all-importants
446               (nconc all-importants
447                      (mapcar 
448                       (lambda (x)
449                         (+ x
450                            (* cur-number
451                               (elmo-multi-folder-divide-number-internal
452                                folder))))                  
453                       importants))))
454       (setq mark-alists (cdr mark-alists)
455             folders (cdr folders)))
456     all-importants))
457
458 (luna-define-method elmo-folder-list-messages-internal
459   ((folder elmo-multi-folder) &optional nohide)
460   (let* ((flds (elmo-multi-folder-children-internal folder))
461          (cur-number 0)
462          list numbers)
463     (while flds
464       (setq cur-number (+ cur-number 1))
465       (setq list (elmo-folder-list-messages-internal (car flds)))
466       (setq numbers
467             (append
468              numbers
469              (if (listp list)
470                  (mapcar
471                   (function
472                    (lambda (x)
473                      (+
474                       (* (elmo-multi-folder-divide-number-internal
475                           folder) cur-number) x)))
476                   list)
477                ;; Use current list.
478                (elmo-delete-if
479                 (lambda (num)
480                   (not
481                    (eq cur-number (/ num
482                                      (elmo-multi-folder-divide-number-internal
483                                       folder)))))
484                 (mapcar
485                  'car
486                  (elmo-msgdb-get-number-alist
487                   (elmo-folder-msgdb folder)))))))
488       (setq flds (cdr flds)))
489     numbers))
490
491 (luna-define-method elmo-folder-exists-p ((folder elmo-multi-folder))
492   (let ((flds (elmo-multi-folder-children-internal folder)))
493     (catch 'exists
494       (while flds
495         (unless (elmo-folder-exists-p (car flds))
496           (throw 'exists nil))
497         (setq flds (cdr flds)))
498       t)))
499
500 (luna-define-method elmo-folder-creatable-p ((folder elmo-multi-folder))
501   (let ((flds (elmo-multi-folder-children-internal folder)))
502     (catch 'creatable
503       (while flds
504         (when (and (elmo-folder-creatable-p (car flds))
505                    (not (elmo-folder-exists-p (car flds))))
506           ;; If folder already exists, don't to `creatable'.
507           ;; Because this function is called, when folder doesn't exists.
508           (throw 'creatable t))
509         (setq flds (cdr flds)))
510       nil)))
511
512 (luna-define-method elmo-folder-create ((folder elmo-multi-folder))
513   (let ((flds (elmo-multi-folder-children-internal folder)))
514     (catch 'create
515       (while flds
516         (unless (or (elmo-folder-exists-p (car flds))
517                     (elmo-folder-create (car flds)))
518           (throw 'create nil))
519         (setq flds (cdr flds)))
520       t)))
521
522 (luna-define-method elmo-folder-search ((folder elmo-multi-folder)
523                                         condition &optional numlist)
524   (let* ((flds (elmo-multi-folder-children-internal folder))
525          (cur-number 0)
526          numlist-list cur-numlist ; for filtered search.
527          ret-val)
528     (if numlist
529         (setq numlist-list
530               (elmo-multi-split-numbers folder numlist t)))
531     (while flds
532       (setq cur-number (+ cur-number 1))
533       (when numlist
534         (setq cur-numlist (car numlist-list))
535         (if (null cur-numlist)
536             ;; t means filter all.
537             (setq cur-numlist t)))
538       (setq ret-val (append
539                      ret-val
540                      (elmo-list-filter
541                       cur-numlist
542                       (mapcar
543                        (function
544                         (lambda (x)
545                           (+
546                            (* (elmo-multi-folder-divide-number-internal
547                                folder) cur-number) x)))
548                        (elmo-folder-search
549                         (car flds) condition)))))
550       (when numlist
551         (setq numlist-list (cdr numlist-list)))
552       (setq flds (cdr flds)))
553     ret-val))
554
555 (luna-define-method elmo-message-use-cache-p ((folder elmo-multi-folder)
556                                               number)
557   (let ((pair (elmo-multi-real-folder-number folder number)))
558     (elmo-message-use-cache-p (car pair) (cdr pair))))
559
560 (luna-define-method elmo-message-file-p ((folder elmo-multi-folder) number)
561   (let ((pair (elmo-multi-real-folder-number folder number)))
562     (elmo-message-file-p (car pair) (cdr pair))))
563
564 (luna-define-method elmo-message-file-name ((folder elmo-multi-folder) number)
565   (let ((pair (elmo-multi-real-folder-number folder number)))
566     (elmo-message-file-name (car pair) (cdr pair))))
567   
568 (luna-define-method elmo-folder-plugged-p ((folder elmo-multi-folder))
569   (let ((flds (elmo-multi-folder-children-internal folder)))
570     (catch 'plugged
571       (while flds
572         (unless (elmo-folder-plugged-p (car flds))
573           (throw 'plugged nil))
574         (setq flds (cdr flds)))
575       t)))
576
577 (luna-define-method elmo-folder-set-plugged ((folder elmo-multi-folder)
578                                              plugged add)
579   (let ((flds  (elmo-multi-folder-children-internal folder)))
580     (dolist (fld flds)
581       (elmo-folder-set-plugged fld plugged add))))
582
583 (defun elmo-multi-folder-numbers-list-assoc (folder folder-numbers)
584   (let (ent)
585     (while folder-numbers
586       (when (string= (elmo-folder-name-internal (car (car folder-numbers)))
587                      (elmo-folder-name-internal folder))
588         (setq ent (car folder-numbers)
589               folder-numbers nil))
590       (setq folder-numbers (cdr folder-numbers)))
591     ent))
592
593 (defun elmo-multi-make-folder-numbers-list (folder msgs)
594   (let ((msg-list msgs)
595         pair fld-list
596         ret-val)
597     (while msg-list
598       (when (and (numberp (car msg-list))
599                  (> (car msg-list) 0))
600         (setq pair (elmo-multi-real-folder-number folder (car msg-list)))
601         (if (setq fld-list (elmo-multi-folder-numbers-list-assoc
602                             (car pair)
603                             ret-val))
604             (setcdr fld-list (cons (cdr pair) (cdr fld-list)))
605           (setq ret-val (cons (cons (car pair) (list (cdr pair))) ret-val))))
606       (setq msg-list (cdr msg-list)))
607     ret-val))
608
609 (luna-define-method elmo-folder-mark-as-important ((folder elmo-multi-folder)
610                                                    numbers)
611   (dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
612     (elmo-folder-mark-as-important (car folder-numbers)
613                                    (cdr folder-numbers)))
614   t)
615
616 (luna-define-method elmo-folder-unmark-important ((folder elmo-multi-folder)
617                                                   numbers)
618   (dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
619     (elmo-folder-unmark-important (car folder-numbers)
620                                   (cdr folder-numbers)))
621   t)
622
623 (luna-define-method elmo-folder-mark-as-read ((folder elmo-multi-folder)
624                                               numbers)
625   (dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
626     (elmo-folder-mark-as-read (car folder-numbers)
627                               (cdr folder-numbers)))
628   t)
629
630 (luna-define-method elmo-folder-unmark-read ((folder elmo-multi-folder)
631                                              numbers)
632   (dolist (folder-numbers (elmo-multi-make-folder-numbers-list folder numbers))
633     (elmo-folder-unmark-read (car folder-numbers)
634                              (cdr folder-numbers)))
635   t)
636
637 (require 'product)
638 (product-provide (provide 'elmo-multi) (require 'elmo-version))
639
640 ;;; elmo-multi.el ends here