1 ;;; elmo-localdir.el -- Localdir Interface for ELMO.
3 ;; Copyright (C) 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
4 ;; Copyright (C) 1998,1999,2000 Masahiro MURATA <muse@ba2.so-net.ne.jp>
5 ;; Copyright (C) 1999,2000 Kenichi OKADA <okada@opaopa.org>
7 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
8 ;; Masahiro MURATA <muse@ba2.so-net.ne.jp>
9 ;; Kenichi OKADA <okada@opaopa.org>
10 ;; Keywords: mail, net news
12 ;; This file is part of ELMO (Elisp Library for Message Orchestration).
14 ;; This program is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation; either version 2, or (at your option)
19 ;; This program is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ;; GNU General Public License for more details.
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with GNU Emacs; see the file COPYING. If not, write to the
26 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27 ;; Boston, MA 02111-1307, USA.
35 (eval-when-compile (require 'cl))
40 (defcustom elmo-localdir-folder-path "~/Mail"
41 "*Local mail directory (MH format) path."
45 ;;; ELMO Local directory folder
47 (luna-define-class elmo-localdir-folder (elmo-folder)
49 (luna-define-internal-accessors 'elmo-localdir-folder))
51 ;;; elmo-localdir specific methods.
52 (luna-define-generic elmo-localdir-folder-path (folder)
53 "Return local directory path of the FOLDER.")
55 (luna-define-generic elmo-localdir-folder-name (folder name)
56 "Return directory NAME for FOLDER.")
58 (luna-define-method elmo-localdir-folder-path ((folder elmo-localdir-folder))
59 elmo-localdir-folder-path)
61 (luna-define-method elmo-localdir-folder-name ((folder elmo-localdir-folder)
65 (luna-define-method elmo-folder-initialize ((folder
68 (elmo-localdir-folder-set-dir-name-internal folder name)
69 (if (file-name-absolute-p name)
70 (elmo-localdir-folder-set-directory-internal
72 (expand-file-name name))
73 (elmo-localdir-folder-set-directory-internal
76 (elmo-localdir-folder-name folder name)
77 (elmo-localdir-folder-path folder))))
80 ;; open, check, commit, and close are generic.
82 (luna-define-method elmo-folder-exists-p ((folder elmo-localdir-folder))
83 (file-directory-p (elmo-localdir-folder-directory-internal folder)))
85 (luna-define-method elmo-folder-expand-msgdb-path ((folder
86 elmo-localdir-folder))
88 (elmo-replace-string-as-filename
89 (elmo-localdir-folder-dir-name-internal folder))
90 (expand-file-name ;;"localdir"
91 (symbol-name (elmo-folder-type-internal folder))
94 (luna-define-method elmo-message-file-name ((folder
97 (expand-file-name (int-to-string number)
98 (elmo-localdir-folder-directory-internal folder)))
100 (luna-define-method elmo-folder-message-file-number-p ((folder
101 elmo-localdir-folder))
104 (luna-define-method elmo-folder-message-file-directory ((folder
105 elmo-localdir-folder))
106 (elmo-localdir-folder-directory-internal folder))
108 (luna-define-method elmo-folder-message-make-temp-file-p
109 ((folder elmo-localdir-folder))
112 (luna-define-method elmo-folder-message-make-temp-files ((folder
113 elmo-localdir-folder)
117 (let ((temp-dir (elmo-folder-make-temp-dir folder))
118 (cur-number (if start-number 0)))
119 (dolist (number numbers)
120 (elmo-add-name-to-file
122 (int-to-string number)
123 (elmo-localdir-folder-directory-internal folder))
125 (int-to-string (if start-number (incf cur-number) number))
129 (defun elmo-localdir-msgdb-create-entity (dir number)
130 (elmo-msgdb-create-overview-entity-from-file
131 number (expand-file-name (int-to-string number) dir)))
133 (luna-define-method elmo-folder-msgdb-create ((folder elmo-localdir-folder)
141 (let ((dir (elmo-localdir-folder-directory-internal folder))
142 overview number-alist mark-alist entity message-id
145 (len (length numbers)))
146 (message "Creating msgdb...")
149 (elmo-localdir-msgdb-create-entity
153 (setq num (elmo-msgdb-overview-entity-get-number entity))
155 (elmo-msgdb-append-element
157 (setq message-id (elmo-msgdb-overview-entity-get-id entity))
159 (elmo-msgdb-number-add number-alist
162 (setq seen (member message-id seen-list))
163 (if (setq gmark (or (elmo-msgdb-global-mark-get message-id)
164 (if (elmo-file-cache-exists-p message-id) ; XXX
172 (elmo-msgdb-mark-append
176 (when (> len elmo-display-progress-threshold)
178 (elmo-display-progress
179 'elmo-localdir-msgdb-create-as-numbers "Creating msgdb..."
181 (setq numbers (cdr numbers)))
182 (message "Creating msgdb...done")
183 (list overview number-alist mark-alist))))
185 (luna-define-method elmo-folder-list-subfolders ((folder elmo-localdir-folder)
188 (lambda (x) (concat (elmo-folder-prefix-internal folder) x))
189 (elmo-list-subdirectories
190 (elmo-localdir-folder-path folder)
191 (or (elmo-localdir-folder-dir-name-internal folder) "")
194 (defsubst elmo-localdir-list-subr (folder &optional nonsort)
195 (let ((flist (mapcar 'string-to-int
197 (elmo-localdir-folder-directory-internal folder)
199 (killed (elmo-msgdb-killed-list-load (elmo-folder-msgdb-path folder))))
201 (cons (or (elmo-max-of-list flist) 0)
204 (elmo-msgdb-killed-list-length killed))
208 (luna-define-method elmo-folder-append-buffer ((folder elmo-localdir-folder)
211 (let ((filename (elmo-message-file-name
214 (1+ (car (elmo-folder-status folder)))))))
215 (if (file-writable-p filename)
216 (write-region-as-binary
217 (point-min) (point-max) filename nil 'no-msg)
220 (luna-define-method elmo-folder-append-messages :around ((folder elmo-localdir-folder)
223 &optional same-number)
224 (if (elmo-folder-message-file-p src-folder)
225 (let ((dir (elmo-localdir-folder-directory-internal folder))
227 (next-num (1+ (car (elmo-folder-status folder)))))
230 (elmo-message-file-name src-folder (car numbers))
233 (if same-number (car numbers) next-num))
235 (if (and (setq numbers (cdr numbers))
238 (if (elmo-localdir-locked-p)
240 (1+ (car (elmo-folder-status folder)))
243 (luna-call-next-method)))
245 (luna-define-method elmo-folder-delete-messages ((folder elmo-localdir-folder)
247 (dolist (number numbers)
248 (elmo-localdir-delete-message folder number))
251 (defun elmo-localdir-delete-message (folder number)
252 "Delete message in the FOLDER with NUMBER."
253 (let ((filename (elmo-message-file-name folder number)))
254 (when (and (string-match "[0-9]+" filename) ; for safety.
255 (file-exists-p filename)
256 (file-writable-p filename)
257 (not (file-directory-p filename)))
258 (delete-file filename)
261 (luna-define-method elmo-message-fetch ((folder elmo-localdir-folder)
263 &optional section outbuf unseen)
264 ;; strategy, section, unseen is ignored.
266 (with-current-buffer outbuf
268 (when (file-exists-p (elmo-message-file-name folder number))
269 (insert-file-contents-as-binary
270 (elmo-message-file-name folder number))
271 (elmo-delete-cr-buffer))
274 (when (file-exists-p (elmo-message-file-name folder number))
275 (insert-file-contents-as-binary (elmo-message-file-name folder number))
276 (elmo-delete-cr-buffer))
279 (luna-define-method elmo-folder-list-messages-internal
280 ((folder elmo-localdir-folder))
281 (elmo-localdir-list-subr folder))
283 (luna-define-method elmo-folder-status ((folder elmo-localdir-folder))
284 (elmo-localdir-list-subr folder t))
286 (luna-define-method elmo-folder-creatable-p ((folder elmo-localdir-folder))
289 (luna-define-method elmo-folder-create ((folder elmo-localdir-folder))
290 (let ((dir (elmo-localdir-folder-directory-internal folder)))
291 (if (file-directory-p dir)
293 (if (file-exists-p dir)
294 (error "Create folder failed")
295 (elmo-make-directory dir))
298 (luna-define-method elmo-folder-delete ((folder elmo-localdir-folder))
299 (let ((dir (elmo-localdir-folder-directory-internal folder)))
300 (if (not (file-directory-p dir))
301 (error "No such directory: %s" dir)
302 (elmo-delete-directory dir t)
305 (luna-define-method elmo-folder-rename-internal ((folder elmo-localdir-folder)
307 (let* ((old (elmo-localdir-folder-directory-internal folder))
308 (new (elmo-localdir-folder-directory-internal folder))
309 (new-dir (directory-file-name (file-name-directory new))))
310 (if (not (file-directory-p old))
311 (error "No such directory: %s" old)
312 (if (file-exists-p new)
313 (error "Already exists directory: %s" new)
314 (if (not (file-exists-p new-dir))
315 (elmo-make-directory new-dir))
316 (rename-file old new)
319 (defsubst elmo-localdir-field-condition-match (folder condition
321 (elmo-file-field-condition-match
322 (expand-file-name (int-to-string number)
323 (elmo-localdir-folder-directory-internal folder))
324 condition number number-list))
326 (luna-define-method elmo-folder-search ((folder elmo-localdir-folder)
327 condition &optional numbers)
328 (let* ((msgs (or numbers (elmo-folder-list-messages folder)))
331 number-list case-fold-search ret-val)
332 (setq number-list msgs)
334 (if (elmo-localdir-field-condition-match folder condition
335 (car msgs) number-list)
336 (setq ret-val (cons (car msgs) ret-val)))
337 (when (> num elmo-display-progress-threshold)
339 (elmo-display-progress
340 'elmo-localdir-search "Searching..."
342 (setq msgs (cdr msgs)))
345 (luna-define-method elmo-folder-pack-numbers ((folder elmo-localdir-folder))
346 (let* ((dir (elmo-localdir-folder-directory-internal folder))
347 (msgdb (elmo-folder-msgdb folder))
348 (onum-alist (elmo-msgdb-get-number-alist msgdb))
349 (omark-alist (elmo-msgdb-get-mark-alist (elmo-folder-msgdb msgdb)))
350 (new-number 1) ; first ordinal position in localdir
351 flist onum mark new-mark-alist total)
353 (if elmo-pack-number-check-strict
354 (elmo-folder-list-messages folder) ; allow localnews
355 (mapcar 'car onum-alist)))
356 (setq total (length flist))
358 (when (> total elmo-display-progress-threshold)
359 (elmo-display-progress
360 'elmo-folder-pack-numbers "Packing..."
361 (/ (* new-number 100) total)))
362 (setq onum (car flist))
363 (when (not (eq onum new-number)) ; why \=() is wrong..
367 (rename-file (int-to-string onum) (int-to-string new-number) t))
369 (elmo-msgdb-overview-entity-set-number
370 (elmo-msgdb-overview-get-entity onum msgdb)
372 ;; update number-alist
373 (setcar (assq onum onum-alist) new-number))
375 (when (setq mark (cadr (assq onum omark-alist)))
377 (elmo-msgdb-mark-append
380 (setq new-number (1+ new-number))
381 (setq flist (cdr flist)))
382 (message "Packing...done")
383 (elmo-folder-set-msgdb-internal
385 (list (elmo-msgdb-get-overview msgdb)
389 (elmo-msgdb-make-overview-hashtb
390 (elmo-msgdb-get-overview msgdb))))))
392 (luna-define-method elmo-folder-message-file-p ((folder elmo-localdir-folder))
395 (luna-define-method elmo-message-file-name ((folder elmo-localdir-folder)
398 (int-to-string number)
399 (elmo-localdir-folder-directory-internal folder)))
401 (defun elmo-localdir-locked-p ()
402 (if elmo-localdir-lockfile-list
403 (let ((lock elmo-localdir-lockfile-list))
406 (if (file-exists-p (car lock))
408 (setq lock (cdr lock)))))))
411 (product-provide (provide 'elmo-localdir) (require 'elmo-version))
413 ;;; elmo-localdir.el ends here