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