Synch up with main trunk and so on.
[elisp/wanderlust.git] / elmo / elmo-map.el
1 ;;; elmo-map.el -- A ELMO folder class with message number mapping.
2
3 ;; Copyright (C) 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 ;; Folders which do not have unique message numbers but unique message names
28 ;; should inherit this folder.
29
30 ;;; Code:
31 ;; 
32 (require 'elmo)
33 (require 'elmo-msgdb)
34
35 (eval-when-compile (require 'cl))
36
37 (eval-and-compile
38   ;; location-hash: location->number mapping
39   ;; number-hash:   number->location mapping
40   (luna-define-class elmo-map-folder (elmo-folder)
41                      (location-alist number-max location-hash))
42   (luna-define-internal-accessors 'elmo-map-folder))
43
44 (defun elmo-map-folder-numbers-to-locations (folder numbers)
45   (let (locations pair)
46     (dolist (number numbers)
47       (if (setq pair (elmo-get-hash-val
48                       (concat "#" (int-to-string number))
49                       (elmo-map-folder-location-hash-internal folder)))
50           (setq locations (cons (cdr pair) locations))))
51     (nreverse locations)))
52
53 (defun elmo-map-folder-locations-to-numbers (folder locations)
54   (let (numbers pair)
55     (dolist (location locations)
56       (if (setq pair (elmo-get-hash-val
57                       location
58                       (elmo-map-folder-location-hash-internal folder)))
59           (setq numbers (cons (car pair) numbers))))
60     (nreverse numbers)))
61
62 (luna-define-generic elmo-map-folder-list-message-locations (folder)
63   "Return a location list of the FOLDER.")
64
65 (luna-define-generic elmo-map-folder-unmark-important (folder locations)
66   "")
67
68 (luna-define-generic elmo-map-folder-mark-as-important (folder locations)
69   "")
70
71 (luna-define-generic elmo-map-folder-unmark-read (folder locations)
72   "")
73
74 (luna-define-generic elmo-map-folder-mark-as-read (folder locations)
75   "")
76
77 (luna-define-generic elmo-map-message-fetch (folder location
78                                                     strategy
79                                                     &optional
80                                                     section
81                                                     outbuf unseen)
82   "")
83
84 (luna-define-generic elmo-map-folder-list-unreads (folder)
85   "")
86
87 (luna-define-generic elmo-map-folder-list-importants (folder)
88   "")
89
90 (luna-define-generic elmo-map-folder-delete-messages (folder locations)
91   "")
92
93 (luna-define-method elmo-folder-status ((folder elmo-map-folder))
94   (elmo-folder-open-internal folder)
95   (prog1
96       (let ((numbers (mapcar
97                       'car
98                       (elmo-map-folder-location-alist-internal folder))))
99         (cons (elmo-max-of-list numbers)
100               (length numbers)))
101     ;; No save.
102     (elmo-folder-close-internal folder)))
103
104 (defun elmo-map-message-number (folder location)
105   "Return number of the message in the FOLDER with LOCATION."
106   (car (elmo-get-hash-val
107         location
108         (elmo-map-folder-location-hash-internal folder))))
109
110 (defun elmo-map-message-location (folder number)
111   "Return location of the message in the FOLDER with NUMBER."
112   (cdr (elmo-get-hash-val
113         (concat "#" (int-to-string number))
114         (elmo-map-folder-location-hash-internal folder))))
115
116 (luna-define-method elmo-folder-pack-number ((folder elmo-map-folder))
117   (let* ((msgdb (elmo-folder-msgdb-internal folder))
118          (old-number-alist (elmo-msgdb-get-number-alist msgdb))
119          (old-overview (elmo-msgdb-get-overview msgdb))
120          (old-mark-alist (elmo-msgdb-get-mark-alist msgdb))
121          (old-location (elmo-map-folder-location-alist-internal folder))
122          old-number overview number-alist mark-alist location
123          mark (number 1))
124     (setq overview old-overview)
125     (while old-overview
126       (setq old-number
127             (elmo-msgdb-overview-entity-get-number (car old-overview)))
128       (elmo-msgdb-overview-entity-set-number (car old-overview) number)
129       (setq number-alist
130             (cons (cons number (cdr (assq old-number old-number-alist)))
131                   number-alist))
132       (when (setq mark (cadr (assq old-number old-mark-alist)))
133         (setq mark-alist
134               (elmo-msgdb-mark-append
135                mark-alist number mark)))
136       (setq location
137             (cons (cons number
138                         (elmo-map-message-location folder old-number))
139                   location))
140       (setq number (1+ number))
141       (setq old-overview (cdr old-overview)))
142     (elmo-map-folder-location-setup folder (nreverse location))
143     (elmo-folder-set-msgdb-internal
144      folder
145      (list overview
146            (nreverse number-alist)
147            (nreverse mark-alist)
148            (elmo-msgdb-make-overview-hashtb overview)))))
149
150 (defun elmo-map-folder-location-setup (folder locations)
151   (elmo-map-folder-set-location-alist-internal
152    folder
153    locations)
154   (elmo-map-folder-set-location-hash-internal
155    folder (elmo-make-hash
156            (* 2 (length locations))))
157   (elmo-map-folder-set-number-max-internal folder 0)
158   ;; Set number-max and hashtables.
159   (dolist (location-cons locations)
160     (if (< (elmo-map-folder-number-max-internal folder)
161            (car location-cons))
162         (elmo-map-folder-set-number-max-internal folder (car location-cons)))
163     (elmo-set-hash-val (cdr location-cons)
164                        location-cons
165                        (elmo-map-folder-location-hash-internal folder))
166     (elmo-set-hash-val (concat "#" (int-to-string (car location-cons)))
167                        location-cons
168                        (elmo-map-folder-location-hash-internal folder))))
169
170 (defun elmo-map-folder-update-locations (folder locations)
171   ;; A subroutine to make location-alist.
172   ;; location-alist is existing location-alist.
173   ;; locations is the newest locations.
174   (let* ((location-alist (elmo-map-folder-location-alist-internal folder))
175          (locations-in-db (mapcar 'cdr location-alist))
176          new-locs new-alist deleted-locs pair i)
177     (setq new-locs
178           (elmo-delete-if (function
179                            (lambda (x) (member x locations-in-db)))
180                           locations))
181     (setq deleted-locs
182           (elmo-delete-if (function
183                            (lambda (x) (member x locations)))
184                           locations-in-db))
185     (dolist (location deleted-locs)
186       (setq location-alist
187             (delq (setq pair
188                         (elmo-get-hash-val
189                          location
190                          (elmo-map-folder-location-hash-internal
191                           folder)))
192                   location-alist))
193       (elmo-clear-hash-val (concat "#" (int-to-string (car pair)))
194                            (elmo-map-folder-location-hash-internal
195                             folder))
196       (elmo-clear-hash-val location
197                            (elmo-map-folder-location-hash-internal
198                             folder)))
199     (setq i (elmo-map-folder-number-max-internal folder))
200     (dolist (location new-locs)
201       (setq i (1+ i))
202       (elmo-map-folder-set-number-max-internal folder i)
203       (setq new-alist (cons (setq pair (cons i location)) new-alist))
204       (setq new-alist (nreverse new-alist))
205       (elmo-set-hash-val (concat "#" (int-to-string i))
206                          pair
207                          (elmo-map-folder-location-hash-internal
208                           folder))
209       (elmo-set-hash-val location
210                          pair
211                          (elmo-map-folder-location-hash-internal
212                           folder)))
213     (setq location-alist (nconc location-alist new-alist))
214     (elmo-map-folder-set-location-alist-internal folder location-alist)))
215
216 (luna-define-method elmo-folder-open-internal ((folder elmo-map-folder))
217   (elmo-map-folder-location-setup
218    folder 
219    (elmo-msgdb-location-load (elmo-folder-msgdb-path folder)))
220   (elmo-map-folder-update-locations
221    folder
222    (elmo-map-folder-list-message-locations folder)))
223
224 (luna-define-method elmo-folder-commit :after ((folder elmo-map-folder))
225   (when (elmo-folder-persistent-p folder)
226     (elmo-msgdb-location-save (elmo-folder-msgdb-path folder)
227                               (elmo-map-folder-location-alist-internal
228                                folder))))
229
230 (luna-define-method elmo-folder-close-internal ((folder elmo-map-folder))
231   (elmo-map-folder-set-location-alist-internal folder nil)
232   (elmo-map-folder-set-location-hash-internal folder nil))
233   
234 (luna-define-method elmo-folder-check ((folder elmo-map-folder))
235   (elmo-map-folder-update-locations
236    folder
237    (elmo-map-folder-list-message-locations folder)))
238
239 (luna-define-method elmo-folder-list-messages-internal
240   ((folder elmo-map-folder) &optional nohide)
241   (mapcar 'car (elmo-map-folder-location-alist-internal folder)))
242
243 (luna-define-method elmo-folder-unmark-important ((folder elmo-map-folder)
244                                                   numbers)
245   (elmo-map-folder-unmark-important
246    folder
247    (elmo-map-folder-numbers-to-locations folder numbers)))
248
249 (luna-define-method elmo-folder-mark-as-important ((folder elmo-map-folder)
250                                                    numbers)
251   (elmo-map-folder-mark-as-important
252    folder
253    (elmo-map-folder-numbers-to-locations folder numbers)))
254
255 (luna-define-method elmo-folder-unmark-read ((folder elmo-map-folder)
256                                              numbers)
257   (elmo-map-folder-unmark-read
258    folder
259    (elmo-map-folder-numbers-to-locations folder numbers)))
260
261 (luna-define-method elmo-folder-mark-as-read ((folder elmo-map-folder) numbers)
262   (elmo-map-folder-mark-as-read
263    folder
264    (elmo-map-folder-numbers-to-locations folder numbers)))
265
266 (luna-define-method elmo-message-fetch ((folder elmo-map-folder) number
267                                         strategy section outbuf unread)
268   (elmo-map-message-fetch
269    folder
270    (elmo-map-message-location folder number)
271    strategy section outbuf unread))
272
273 (luna-define-method elmo-folder-list-unreads-internal
274   ((folder elmo-map-folder) unread-marks &optional mark-alist)
275   (elmo-map-folder-locations-to-numbers
276    folder
277    (elmo-map-folder-list-unreads folder)))
278
279 (luna-define-method elmo-folder-list-importants-internal
280   ((folder elmo-map-folder) important-mark)
281   (elmo-map-folder-locations-to-numbers
282    folder
283    (elmo-map-folder-list-importants folder)))
284
285 (luna-define-method elmo-folder-delete-messages ((folder elmo-map-folder)
286                                                  numbers)
287   (elmo-map-folder-delete-messages
288    folder
289    (elmo-map-folder-numbers-to-locations folder numbers))
290   (dolist (number numbers)
291     (elmo-map-folder-set-location-alist-internal
292      folder
293      (delq (elmo-get-hash-val
294             (concat "#" (int-to-string number))
295             (elmo-map-folder-location-hash-internal
296              folder))
297            (elmo-map-folder-location-alist-internal folder))))
298   t) ; success
299   
300
301 (require 'product)
302 (product-provide (provide 'elmo-map) (require 'elmo-version))
303
304 ;;; elmo-map.el ends here