1 ;;; modb-standard.el --- Standartd Implement of MODB.
3 ;; Copyright (C) 2003 Yuuichi Teranishi <teranisi@gohome.org>
5 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Hiroya Murata <lapis-lazuli@pop06.odn.ne.jp>
7 ;; Keywords: mail, net news
9 ;; This file is part of ELMO (Elisp Library for Message Orchestration).
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
32 (eval-when-compile (require 'cl))
36 (require 'modb-entity)
39 (defcustom modb-standard-divide-number 500
40 "*Standard modb divide entity number."
41 :type '(choice (const :tag "Not divide" nil)
45 (defvar modb-standard-entity-filename "entity"
46 "Message entity database.")
48 (defvar modb-standard-flag-filename "flag"
49 "Message number <=> Flag status database.")
51 (defvar modb-standard-msgid-filename "msgid"
52 "Message number <=> Message-Id database.")
55 (luna-define-class modb-standard (modb-generic)
56 (number-list ; sorted list of message numbers.
57 entity-map ; number, msg-id -> entity mapping.
58 flag-map ; number -> flag-list mapping
60 (luna-define-internal-accessors 'modb-standard))
62 ;; for internal use only
63 (defsubst modb-standard-key (number)
64 (concat "#" (number-to-string number)))
66 (defsubst modb-standard-entity-id (entity)
67 (if (eq 'autoload (car-safe entity))
69 (elmo-msgdb-overview-entity-get-id entity)))
71 (defsubst modb-standard-entity-map (modb)
72 (or (modb-standard-entity-map-internal modb)
73 (modb-standard-set-entity-map-internal
75 (elmo-make-hash (elmo-msgdb-length modb)))))
77 (defsubst modb-standard-flag-map (modb)
78 (or (modb-standard-flag-map-internal modb)
79 (modb-standard-set-flag-map-internal
81 (elmo-make-hash (elmo-msgdb-length modb)))))
83 (defsubst modb-standard-set-message-modified (modb number)
84 (if modb-standard-divide-number
85 (let ((section (/ number modb-standard-divide-number))
86 (modified (modb-generic-message-modified-internal modb)))
87 (unless (memq section modified)
88 (modb-generic-set-message-modified-internal
89 modb (cons section modified))))
90 (modb-generic-set-message-modified-internal modb t)))
92 (defsubst modb-standard-set-flag-modified (modb number)
93 (modb-generic-set-flag-modified-internal modb t))
95 (defsubst modb-standard-message-flags (modb number)
96 (cdr (elmo-get-hash-val (modb-standard-key number)
97 (modb-standard-flag-map-internal modb))))
99 (defsubst modb-standard-match-flags (check-flags flags)
102 (when (memq (car check-flags) flags)
104 (setq check-flags (cdr check-flags)))))
107 ;; save and load functions
108 (defun modb-standard-load-msgid (modb path)
109 (let* ((alist (elmo-object-load
110 (expand-file-name modb-standard-msgid-filename path)))
111 (table (or (modb-standard-entity-map-internal modb)
112 (elmo-make-hash (length alist))))
115 (setq info (cons 'autoload pair))
116 (elmo-set-hash-val (modb-standard-key (car pair)) info table)
117 (elmo-set-hash-val (cdr pair) info table)
118 (setq numbers (cons (car pair) numbers)))
119 (modb-standard-set-number-list-internal modb (nreverse numbers))
120 (modb-standard-set-entity-map-internal modb table)))
122 (defun modb-standard-save-msgid (modb path)
123 (let ((table (modb-standard-entity-map-internal modb))
125 (dolist (number (modb-standard-number-list-internal modb))
126 (setq entity (elmo-get-hash-val (modb-standard-key number) table))
127 (setq alist (cons (cons number (modb-standard-entity-id entity))
130 (expand-file-name modb-standard-msgid-filename path)
133 (defun modb-standard-load-flag (modb path)
134 (let ((table (or (modb-standard-flag-map-internal modb)
135 (elmo-make-hash (elmo-msgdb-length modb)))))
136 (dolist (info (elmo-object-load
137 (expand-file-name modb-standard-flag-filename path)))
138 (elmo-set-hash-val (modb-standard-key (car info)) info table))
139 (modb-standard-set-flag-map-internal modb table)))
141 (defun modb-standard-save-flag (modb path)
142 (let (table flist info)
143 (when (setq table (modb-standard-flag-map-internal modb))
146 (setq info (symbol-value atom))
148 (setq flist (cons info flist))))
151 (expand-file-name modb-standard-flag-filename path)
154 (defsubst modb-standard-entity-filename (section)
156 (concat modb-standard-entity-filename
158 (number-to-string section))
159 modb-standard-entity-filename))
161 (defun modb-standard-load-entity (modb path &optional section)
162 (let ((table (or (modb-standard-entity-map-internal modb)
163 (elmo-make-hash (elmo-msgdb-length modb)))))
164 (dolist (entity (elmo-object-load
166 (modb-standard-entity-filename section)
168 (elmo-set-hash-val (modb-standard-key
169 (elmo-msgdb-overview-entity-get-number entity))
172 (elmo-set-hash-val (elmo-msgdb-overview-entity-get-id entity)
175 (modb-standard-set-entity-map-internal modb table)))
177 (defsubst modb-standard-save-entity-1 (modb path &optional section)
178 (let ((table (modb-standard-entity-map-internal modb))
179 (filename (expand-file-name
180 (modb-standard-entity-filename section) path))
182 (dolist (number (modb-standard-number-list-internal modb))
183 (when (and (or (null section)
184 (= section (/ number modb-standard-divide-number)))
185 (setq entity (elmo-msgdb-message-entity modb number)))
186 (setq entities (cons entity entities))))
188 (elmo-object-save filename entities)
189 (ignore-errors (delete-file filename)))))
191 (defun modb-standard-save-entity (modb path)
192 (let ((sections (modb-generic-message-modified-internal modb)))
193 (cond ((listp sections)
194 (dolist (section sections)
195 (modb-standard-save-entity-1 modb path section)))
197 (modb-standard-save-entity-1 modb path)))))
201 (luna-define-method elmo-msgdb-load ((msgdb modb-standard))
202 (let ((inhibit-quit t)
203 (path (elmo-msgdb-location msgdb)))
204 (when (file-exists-p (expand-file-name modb-standard-flag-filename path))
205 (modb-standard-load-msgid msgdb path)
206 (modb-standard-load-flag msgdb path)
207 (unless modb-standard-divide-number
208 (modb-standard-load-entity msgdb path))
211 (luna-define-method elmo-msgdb-save ((msgdb modb-standard))
212 (let ((path (elmo-msgdb-location msgdb)))
213 (when (elmo-msgdb-message-modified-p msgdb)
214 (modb-standard-save-msgid msgdb path)
215 (modb-standard-save-entity msgdb path)
216 (modb-generic-set-message-modified-internal msgdb nil))
217 (when (elmo-msgdb-flag-modified-p msgdb)
218 (modb-standard-save-flag msgdb path)
219 (modb-generic-set-flag-modified-internal msgdb nil))))
221 (luna-define-method elmo-msgdb-append :around ((msgdb modb-standard)
223 (when (> (elmo-msgdb-length msgdb-append) 0)
224 (if (eq (luna-class-name msgdb-append) 'modb-standard)
225 (let ((numbers (modb-standard-number-list-internal msgdb-append))
228 (modb-standard-set-number-list-internal
230 (nconc (modb-standard-number-list-internal msgdb)
233 (let ((table (modb-standard-entity-map msgdb))
235 (dolist (number numbers)
236 (setq entity (elmo-msgdb-message-entity msgdb-append number)
237 msg-id (modb-standard-entity-id entity))
238 (if (elmo-get-hash-val msg-id table)
239 (setq duplicates (cons number duplicates))
240 (elmo-set-hash-val msg-id entity table))
241 (elmo-set-hash-val (modb-standard-key number)
245 (let ((table (modb-standard-flag-map msgdb)))
248 (elmo-set-hash-val (symbol-name atom)
251 (modb-standard-flag-map msgdb-append)))
252 ;; modification flags
253 (dolist (number (modb-standard-number-list-internal msgdb-append))
254 (modb-standard-set-message-modified msgdb number)
255 (modb-standard-set-flag-modified msgdb number))
257 (luna-call-next-method))))
259 (luna-define-method elmo-msgdb-clear :after ((msgdb modb-standard))
260 (modb-standard-set-number-list-internal msgdb nil)
261 (modb-standard-set-entity-map-internal msgdb nil)
262 (modb-standard-set-flag-map-internal msgdb nil))
264 (luna-define-method elmo-msgdb-length ((msgdb modb-standard))
265 (length (modb-standard-number-list-internal msgdb)))
267 (luna-define-method elmo-msgdb-flags ((msgdb modb-standard) number)
268 (modb-standard-message-flags msgdb number))
270 (luna-define-method elmo-msgdb-set-flag ((msgdb modb-standard)
274 (elmo-msgdb-unset-flag msgdb number 'unread))
276 (elmo-msgdb-unset-flag msgdb number 'cached))
278 (let* ((cur-flags (modb-standard-message-flags msgdb number))
279 (new-flags (copy-sequence cur-flags)))
280 (and (memq 'new new-flags)
281 (setq new-flags (delq 'new new-flags)))
282 (or (memq flag new-flags)
283 (setq new-flags (cons flag new-flags)))
284 (when (and (eq flag 'unread)
285 (memq 'answered new-flags))
286 (setq new-flags (delq 'answered new-flags)))
287 (unless (equal new-flags cur-flags)
288 (elmo-set-hash-val (modb-standard-key number)
289 (cons number new-flags)
290 (modb-standard-flag-map msgdb))
291 (modb-standard-set-flag-modified msgdb number))))))
293 (luna-define-method elmo-msgdb-unset-flag ((msgdb modb-standard)
297 (elmo-msgdb-set-flag msgdb number 'unread))
299 (elmo-msgdb-set-flag msgdb number 'cached))
301 (let* ((cur-flags (modb-standard-message-flags msgdb number))
302 (new-flags (copy-sequence cur-flags)))
303 (and (memq 'new new-flags)
304 (setq new-flags (delq 'new new-flags)))
305 (and (memq flag new-flags)
306 (setq new-flags (delq flag new-flags)))
307 (when (and (eq flag 'unread)
308 (memq 'answered new-flags))
309 (setq new-flags (delq 'answered new-flags)))
310 (unless (equal new-flags cur-flags)
311 (elmo-set-hash-val (modb-standard-key number)
312 (cons number new-flags)
313 (modb-standard-flag-map msgdb))
314 (modb-standard-set-flag-modified msgdb number))))))
316 (luna-define-method elmo-msgdb-list-messages ((msgdb modb-standard))
318 (modb-standard-number-list-internal msgdb)))
320 (luna-define-method elmo-msgdb-list-flagged ((msgdb modb-standard) flag)
324 (dolist (number (modb-standard-number-list-internal msgdb))
325 (unless (memq 'unread (modb-standard-message-flags msgdb number))
326 (setq matched (cons number matched)))))
330 (setq entry (symbol-value atom))
331 (when (modb-standard-match-flags '(unread important)
333 (setq matched (cons (car entry) matched))))
334 (modb-standard-flag-map msgdb)))
338 (setq entry (symbol-value atom))
339 (when (modb-standard-match-flags '(unread important answered)
341 (setq matched (cons (car entry) matched))))
342 (modb-standard-flag-map msgdb)))
346 (setq entry (symbol-value atom))
347 (when (memq flag (cdr entry))
348 (setq matched (cons (car entry) matched))))
349 (modb-standard-flag-map msgdb))))
352 (luna-define-method elmo-msgdb-append-entity ((msgdb modb-standard)
353 entity &optional flags)
354 (let ((number (elmo-msgdb-overview-entity-get-number entity))
355 (msg-id (elmo-msgdb-overview-entity-get-id entity))
358 (modb-standard-set-number-list-internal
360 (nconc (modb-standard-number-list-internal msgdb)
363 (let ((table (modb-standard-entity-map msgdb)))
364 (setq duplicate (elmo-get-hash-val msg-id table))
365 (elmo-set-hash-val (modb-standard-key number) entity table)
366 (elmo-set-hash-val msg-id entity table))
367 ;; modification flags
368 (modb-standard-set-message-modified msgdb number)
372 (modb-standard-key number)
374 (modb-standard-flag-map msgdb))
375 (modb-standard-set-flag-modified msgdb number))
378 (luna-define-method elmo-msgdb-delete-messages ((msgdb modb-standard)
380 (let ((number-list (modb-standard-number-list-internal msgdb))
381 (entity-map (modb-standard-entity-map-internal msgdb))
382 (flag-map (modb-standard-flag-map-internal msgdb))
384 (dolist (number numbers)
385 (setq key (modb-standard-key number)
386 entity (elmo-get-hash-val key entity-map))
388 (setq number-list (delq number number-list))
390 (elmo-clear-hash-val key entity-map)
391 (elmo-clear-hash-val (modb-standard-entity-id entity) entity-map)
393 (elmo-clear-hash-val key flag-map)
394 (modb-standard-set-message-modified msgdb number)
395 (modb-standard-set-flag-modified msgdb number))
396 (modb-standard-set-number-list-internal msgdb number-list)
397 (modb-standard-set-entity-map-internal msgdb entity-map)
398 (modb-standard-set-flag-map-internal msgdb flag-map)))
400 (luna-define-method elmo-msgdb-sort-entities ((msgdb modb-standard)
401 predicate &optional app-data)
402 (message "Sorting...")
403 (let ((numbers (modb-standard-number-list-internal msgdb)))
404 (modb-standard-set-number-list-internal
406 (sort numbers (lambda (a b)
408 (elmo-msgdb-message-entity msgdb a)
409 (elmo-msgdb-message-entity msgdb b)
411 (message "Sorting...done")
414 (luna-define-method elmo-msgdb-message-entity ((msgdb modb-standard) key)
415 (let ((ret (elmo-get-hash-val
416 (cond ((stringp key) key)
417 ((numberp key) (modb-standard-key key)))
418 (modb-standard-entity-map-internal msgdb))))
419 (if (eq 'autoload (car-safe ret))
420 (when modb-standard-divide-number
421 (modb-standard-load-entity
423 (elmo-msgdb-location msgdb)
424 (/ (nth 1 ret) modb-standard-divide-number))
426 (cond ((stringp key) key)
427 ((numberp key) (modb-standard-key key)))
428 (modb-standard-entity-map-internal msgdb)))
433 (product-provide (provide 'modb-standard) (require 'elmo-version))
435 ;;; modb-standard.el ends here