1 ;;; wl-folder.el -- Folder mode for Wanderlust.
3 ;; Copyright 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
5 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Keywords: mail, net news
8 ;; This file is part of Wanderlust (Yet Another Message Interface on Emacsen).
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)
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.
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.
37 (require 'easymenu) ; needed here.
48 (unless (boundp ':file)
49 (set (make-local-variable ':file) nil))
50 (defun-maybe mmelmo-cleanup-entity-buffers ()))
52 (defvar wl-folder-buffer-name "Folder")
53 (defvar wl-folder-entity nil) ; desktop entity.
54 (defvar wl-folder-group-alist nil) ; opened or closed
55 (defvar wl-folder-entity-id nil) ; id
56 (defvar wl-folder-entity-hashtb nil)
57 (defvar wl-folder-entity-id-name-hashtb nil)
58 (defvar wl-folder-newsgroups-hashtb nil)
59 (defvar wl-folder-info-alist-modified nil)
60 (defvar wl-folder-completion-func nil)
62 (defvar wl-folder-mode-map nil)
64 (defvar wl-folder-buffer-disp-summary nil)
65 (defvar wl-folder-buffer-cur-entity-id nil)
66 (defvar wl-folder-buffer-cur-path nil)
67 (defvar wl-folder-buffer-cur-point nil)
69 (make-variable-buffer-local 'wl-folder-buffer-disp-summary)
70 (make-variable-buffer-local 'wl-folder-buffer-cur-entity-id)
71 (make-variable-buffer-local 'wl-folder-buffer-cur-path)
72 (make-variable-buffer-local 'wl-folder-buffer-cur-point)
74 (defconst wl-folder-entity-regexp "^\\([ ]*\\)\\(\\[[\\+-]\\]\\)?\\([^\\[].+\\):[-*0-9]+/[-*0-9]+/[-*0-9]+")
75 (defconst wl-folder-group-regexp "^\\([ ]*\\)\\[\\([\\+-]\\)\\]\\(.+\\):[-0-9-]+/[0-9-]+/[0-9-]+\n")
76 ;; 1:indent 2:opened 3:group-name
77 (defconst wl-folder-unsync-regexp ":[^0\\*][0-9]*/[0-9\\*-]+/[0-9\\*-]+$")
79 (defvar wl-folder-mode-menu-spec
81 ["Enter Current Folder" wl-folder-jump-to-current-entity t]
82 ["Prev Folder" wl-folder-prev-entity t]
83 ["Next Folder" wl-folder-next-entity t]
84 ["Check Current Folder" wl-folder-check-current-entity t]
85 ["Sync Current Folder" wl-folder-sync-current-entity t]
86 ["Drop Current Folder" wl-folder-drop-unsync-current-entity t]
87 ["Prefetch Current Folder" wl-folder-prefetch-current-entity t]
88 ["Mark as Read all Current Folder" wl-folder-mark-as-read-all-current-entity t]
89 ["Expire Current Folder" wl-folder-expire-current-entity t]
90 ["Empty trash" wl-folder-empty-trash t]
91 ["Flush queue" wl-folder-flush-queue t]
92 ["Open All" wl-folder-open-all t]
93 ["Open All Unread folder" wl-folder-open-all-unread-folder t]
94 ["Close All" wl-folder-close-all t]
96 ["Add folder" wl-fldmgr-add t]
97 ["Add group" wl-fldmgr-make-group t]
98 ["Copy" wl-fldmgr-copy t]
99 ["Cut" wl-fldmgr-cut t]
100 ["Paste" wl-fldmgr-yank t]
101 ["Set petname" wl-fldmgr-set-petname t]
102 ["Rename" wl-fldmgr-rename t]
103 ["Save" wl-fldmgr-save-folders t]
105 ["Unsubscribe" wl-fldmgr-unsubscribe t]
106 ["Display all" wl-fldmgr-access-display-all t])
108 ["Write a message" wl-draft t]
110 ["Toggle Plug Status" wl-toggle-plugged t]
111 ["Change Plug Status" wl-plugged-change t]
113 ["Save Current Status" wl-save t]
114 ["Update Satus" wl-status-update t]
119 (defun wl-folder-setup-mouse ()
120 (define-key wl-folder-mode-map 'button2 'wl-folder-click)
121 (define-key wl-folder-mode-map 'button4 'wl-folder-prev-entity)
122 (define-key wl-folder-mode-map 'button5 'wl-folder-next-entity)
123 (define-key wl-folder-mode-map [(shift button4)]
124 'wl-folder-prev-unread)
125 (define-key wl-folder-mode-map [(shift button5)]
126 'wl-folder-next-unread))
128 (defun wl-folder-setup-mouse ())
129 (defun wl-folder-setup-mouse ()
130 (define-key wl-folder-mode-map [mouse-2] 'wl-folder-click)
131 (define-key wl-folder-mode-map [mouse-4] 'wl-folder-prev-entity)
132 (define-key wl-folder-mode-map [mouse-5] 'wl-folder-next-entity)
133 (define-key wl-folder-mode-map [S-mouse-4] 'wl-folder-prev-unread)
134 (define-key wl-folder-mode-map [S-mouse-5] 'wl-folder-next-unread))))
136 (if wl-folder-mode-map
138 (setq wl-folder-mode-map (make-sparse-keymap))
139 (define-key wl-folder-mode-map " " 'wl-folder-jump-to-current-entity)
140 ; (define-key wl-folder-mode-map "\M- " 'wl-folder-open-close)
141 (define-key wl-folder-mode-map "/" 'wl-folder-open-close)
142 (define-key wl-folder-mode-map "\C-m" 'wl-folder-jump-to-current-entity)
143 (define-key wl-folder-mode-map "\M-\C-m" 'wl-folder-update-recursive-current-entity)
144 (define-key wl-folder-mode-map "rc" 'wl-folder-mark-as-read-all-region)
145 (define-key wl-folder-mode-map "c" 'wl-folder-mark-as-read-all-current-entity)
146 (define-key wl-folder-mode-map "g" 'wl-folder-goto-folder)
147 (define-key wl-folder-mode-map "j" 'wl-folder-jump-to-current-entity)
148 (define-key wl-folder-mode-map "w" 'wl-draft)
149 (define-key wl-folder-mode-map "W" 'wl-folder-write-current-newsgroup)
150 (define-key wl-folder-mode-map "\C-c\C-o" 'wl-jump-to-draft-buffer)
151 (define-key wl-folder-mode-map "rS" 'wl-folder-sync-region)
152 (define-key wl-folder-mode-map "S" 'wl-folder-sync-current-entity)
153 (define-key wl-folder-mode-map "rs" 'wl-folder-check-region)
154 (define-key wl-folder-mode-map "s" 'wl-folder-check-current-entity)
155 (define-key wl-folder-mode-map "I" 'wl-folder-prefetch-current-entity)
156 (define-key wl-folder-mode-map "D" 'wl-folder-drop-unsync-current-entity)
157 (define-key wl-folder-mode-map "p" 'wl-folder-prev-entity)
158 (define-key wl-folder-mode-map "n" 'wl-folder-next-entity)
159 (define-key wl-folder-mode-map "v" 'wl-folder-toggle-disp-summary)
160 (define-key wl-folder-mode-map "P" 'wl-folder-prev-unread)
161 (define-key wl-folder-mode-map "N" 'wl-folder-next-unread)
162 (define-key wl-folder-mode-map "J" 'wl-folder-jump-folder)
163 (define-key wl-folder-mode-map "f" 'wl-folder-goto-first-unread-folder)
164 (define-key wl-folder-mode-map "o" 'wl-folder-open-all-unread-folder)
165 (define-key wl-folder-mode-map "[" 'wl-folder-open-all)
166 (define-key wl-folder-mode-map "]" 'wl-folder-close-all)
167 (define-key wl-folder-mode-map "e" 'wl-folder-expire-current-entity)
168 (define-key wl-folder-mode-map "E" 'wl-folder-empty-trash)
169 (define-key wl-folder-mode-map "F" 'wl-folder-flush-queue)
170 (define-key wl-folder-mode-map "q" 'wl-exit)
171 (define-key wl-folder-mode-map "z" 'wl-folder-suspend)
172 (define-key wl-folder-mode-map "\M-t" 'wl-toggle-plugged)
173 (define-key wl-folder-mode-map "\C-t" 'wl-plugged-change)
174 (define-key wl-folder-mode-map "<" 'beginning-of-buffer)
175 (define-key wl-folder-mode-map ">" 'end-of-buffer)
178 (define-key wl-folder-mode-map "m" 'wl-fldmgr-mode-map))
179 (define-key wl-folder-mode-map "*" 'wl-fldmgr-make-multi)
180 (define-key wl-folder-mode-map "+" 'wl-fldmgr-make-group)
181 (define-key wl-folder-mode-map "|" 'wl-fldmgr-make-filter)
182 (define-key wl-folder-mode-map "\M-c" 'wl-fldmgr-copy)
183 (define-key wl-folder-mode-map "\M-w" 'wl-fldmgr-copy-region)
184 (define-key wl-folder-mode-map "\C-k" 'wl-fldmgr-cut)
185 (define-key wl-folder-mode-map "\C-w" 'wl-fldmgr-cut-region)
186 (define-key wl-folder-mode-map "\C-y" 'wl-fldmgr-yank)
187 (define-key wl-folder-mode-map "R" 'wl-fldmgr-rename)
188 (define-key wl-folder-mode-map "u" 'wl-fldmgr-unsubscribe)
189 (define-key wl-folder-mode-map "ru" 'wl-fldmgr-unsubscribe-region)
190 (define-key wl-folder-mode-map "U" 'wl-fldmgr-unsubscribe-region)
191 (define-key wl-folder-mode-map "l" 'wl-fldmgr-access-display-normal)
192 (define-key wl-folder-mode-map "L" 'wl-fldmgr-access-display-all)
193 (define-key wl-folder-mode-map "Z" 'wl-status-update)
194 (define-key wl-folder-mode-map "\C-x\C-s" 'wl-save)
195 (define-key wl-folder-mode-map "\M-s" 'wl-save)
196 (define-key wl-folder-mode-map "\C-xk" 'wl-folder-mimic-kill-buffer)
197 (define-key wl-folder-mode-map "\M-\C-a"
198 'wl-folder-goto-top-of-current-folder)
199 (define-key wl-folder-mode-map "\M-\C-e"
200 'wl-folder-goto-bottom-of-current-folder)
202 (wl-folder-setup-mouse)
206 "Menu used in Folder mode."
207 wl-folder-mode-menu-spec))
209 (defmacro wl-folder-unread-regex (group)
210 (` (concat "^[ ]*.+:[0-9\\*-]+/[^0\\*][0-9]*/[0-9\\*-]+$"
215 (defmacro wl-folder-buffer-group-p ()
216 (` (save-excursion (beginning-of-line)
217 (looking-at wl-folder-group-regexp))))
219 (defmacro wl-folder-folder-name ()
222 (if (or (looking-at "^[ ]*\\[[\\+-]\\]\\(.+\\):[-0-9\\*-]+/[0-9\\*-]+/[0-9\\*-]+\n")
223 (looking-at "^[ ]*\\([^\\[].+\\):.*\n"))
224 (wl-match-buffer 1)))))
226 (defmacro wl-folder-entity-name ()
229 (if (looking-at "^[ ]*\\([^\\[].+\\):.*\n")
230 (wl-match-buffer 1)))))
232 (defun wl-folder-buffer-search-group (group)
235 "^\\([ \t]*\\)\\[[\\+-]\\]"
236 (regexp-quote group) ":[-0-9-]+/[0-9-]+/[0-9-]+") nil t))
238 (defun wl-folder-buffer-search-entity (folder &optional searchname)
239 (let ((search (or searchname (wl-folder-get-petname folder))))
243 (regexp-quote search) ":[-0-9\\*-]+/[0-9\\*-]+/[0-9\\*-]+") nil t)))
245 (defsubst wl-folder-get-folder-name-by-id (entity-id &optional hashtb)
246 (and (numberp entity-id)
247 (elmo-get-hash-val (format "#%d" entity-id)
248 (or hashtb wl-folder-entity-id-name-hashtb))))
250 (defsubst wl-folder-set-id-name (entity-id entity &optional hashtb)
251 (and (numberp entity-id)
252 (elmo-set-hash-val (format "#%d" entity-id)
253 entity (or hashtb wl-folder-entity-id-name-hashtb))))
255 (defmacro wl-folder-get-entity-id (entity)
256 (` (or (get-text-property 0
259 (, entity)))) ;; for nemacs
261 (defmacro wl-folder-get-entity-from-buffer (&optional getid)
262 (` (let ((id (get-text-property (point)
263 'wl-folder-entity-id)))
264 (if (not id) ;; for nemacs
265 (wl-folder-get-realname (wl-folder-folder-name))
268 (wl-folder-get-folder-name-by-id id))))))
270 (defmacro wl-folder-entity-exists-p (entity &optional hashtb)
271 (` (let ((sym (intern-soft (, entity)
272 (or (, hashtb) wl-folder-entity-hashtb))))
273 (and sym (boundp sym)))))
275 (defmacro wl-folder-clear-entity-info (entity &optional hashtb)
276 (` (let ((sym (intern-soft (, entity)
277 (or (, hashtb) wl-folder-entity-hashtb))))
281 (defmacro wl-folder-get-entity-info (entity &optional hashtb)
282 (` (elmo-get-hash-val (, entity) (or (, hashtb) wl-folder-entity-hashtb))))
284 (defmacro wl-folder-set-entity-info (entity value &optional hashtb)
285 (` (let* ((hashtb (or (, hashtb) wl-folder-entity-hashtb))
286 (info (wl-folder-get-entity-info (, entity) hashtb)))
287 (elmo-set-hash-val (, entity)
288 (if (< (length (, value)) 4)
289 (append (, value) (list (nth 3 info)))
293 (defun wl-folder-persistent-p (folder)
294 (or (elmo-get-hash-val folder wl-folder-entity-hashtb) ; on Folder mode.
296 (let ((li wl-save-folder-list))
298 (if (string-match (car li) folder)
300 (setq li (cdr li)))))
302 (let ((li wl-no-save-folder-list))
304 (if (string-match (car li) folder)
306 (setq li (cdr li))))))))
308 (defun wl-folder-prev-entity ()
312 (defun wl-folder-next-entity ()
316 (defun wl-folder-prev-entity-skip-invalid (&optional hereto)
317 "move to previous entity. skip unsubscribed or removed entity."
321 (if (re-search-backward wl-folder-entity-regexp nil t)
323 (goto-char (point-min))))
325 (defun wl-folder-next-entity-skip-invalid (&optional hereto)
326 "move to next entity. skip unsubscribed or removed entity."
331 (if (re-search-forward wl-folder-entity-regexp nil t)
333 (goto-char (point-max))))
335 (defun wl-folder-search-group-entity-by-name (name entity)
336 (wl-folder-search-entity-by-name name entity 'group))
338 (defun wl-folder-search-entity-by-name (name entity &optional type)
339 (let ((entities (list entity))
343 (setq entity (wl-pop entities))
346 (if (and (not (eq type 'folder))
347 (string= name (car entity)))
348 (throw 'done entity))
350 (wl-push entities entity-stack))
351 (setq entities (nth 2 entity)))
352 ((and (not (eq type 'group))
354 (if (string= name entity)
355 (throw 'done entity))))
357 (setq entities (wl-pop entity-stack)))))))
359 (defun wl-folder-search-entity-list-by-name (name entity &optional get-id)
360 (let ((entities (list entity))
361 entity-stack ret-val)
363 (setq entity (wl-pop entities))
367 (wl-push entities entity-stack))
368 (setq entities (nth 2 entity)))
370 (if (string= name entity)
371 (wl-append ret-val (if get-id
372 (list (wl-folder-get-entity-id entity))
375 (setq entities (wl-pop entity-stack))))
378 (defun wl-folder-get-prev-folder (id &optional unread)
379 (let ((name (if (stringp id)
381 (wl-folder-get-folder-name-by-id id)))
382 entity entity-stack last-entity finfo
383 (entities (list wl-folder-entity)))
386 (setq entity (wl-pop entities))
389 ;; (if (and (string= name (car entity))
390 ;; (eq id (wl-folder-get-entity-id (car entity))))
391 ;; (throw 'done last-entity))
393 (wl-push entities entity-stack))
394 (setq entities (nth 2 entity)))
396 (if (and (string= name entity)
397 ;; don't use eq, `id' is string on Nemacs.
398 (equal id (wl-folder-get-entity-id entity)))
399 (throw 'done last-entity))
401 (and (setq finfo (wl-folder-get-entity-info entity))
402 (and (nth 0 finfo)(nth 1 finfo))
403 (> (+ (nth 0 finfo)(nth 1 finfo)) 0)))
404 (setq last-entity entity))))
406 (setq entities (wl-pop entity-stack)))))))
408 (defun wl-folder-get-next-folder (id &optional unread)
409 (let ((name (if (stringp id)
411 (wl-folder-get-folder-name-by-id id)))
412 entity entity-stack found finfo
413 (entities (list wl-folder-entity)))
416 (setq entity (wl-pop entities))
419 ;; (if (and (string= name (car entity))
420 ;; (eq id (wl-folder-get-entity-id (car entity))))
423 (wl-push entities entity-stack))
424 (setq entities (nth 2 entity)))
427 (when (or (not unread)
428 (and (setq finfo (wl-folder-get-entity-info entity))
429 (and (nth 0 finfo)(nth 1 finfo))
430 (> (+ (nth 0 finfo)(nth 1 finfo)) 0)))
431 (throw 'done entity))
432 (if (and (string= name entity)
433 ;; don't use eq, `id' is string on Nemacs.
434 (equal id (wl-folder-get-entity-id entity)))
437 (setq entities (wl-pop entity-stack)))))))
439 (defun wl-folder-flush-queue ()
442 (let ((cur-buf (current-buffer))
443 (wl-auto-select-first nil)
446 (if elmo-enable-disconnected-operation
447 (elmo-dop-queue-flush 'force)) ; Try flushing all queue.
448 (if (not (elmo-list-folder wl-queue-folder))
449 (message "No sending queue exists.")
450 (if wl-stay-folder-window
451 (wl-folder-select-buffer
452 (wl-summary-get-buffer-create wl-queue-folder)))
453 (wl-summary-goto-folder-subr wl-queue-folder 'force-update nil)
455 (wl-draft-queue-flush)
456 (if (get-buffer-window cur-buf)
457 (select-window (get-buffer-window cur-buf)))
459 (if wl-stay-folder-window
460 (wl-folder-toggle-disp-summary 'off wl-queue-folder)
461 (switch-to-buffer cur-buf))))))
463 (defun wl-folder-empty-trash ()
466 (let ((cur-buf (current-buffer))
467 (wl-auto-select-first nil)
469 (if wl-stay-folder-window
470 (wl-folder-select-buffer
471 (wl-summary-get-buffer-create wl-trash-folder)))
472 (wl-summary-goto-folder-subr wl-trash-folder 'force-update nil nil t)
473 (setq trash-buf (current-buffer))
475 (setq emptied (wl-summary-delete-all-msgs))
477 (setq wl-thread-entities nil
478 wl-thread-entity-list nil)
479 (if wl-summary-cache-use (wl-summary-save-view-cache))
480 (wl-summary-msgdb-save))
481 (if (get-buffer-window cur-buf)
482 (select-window (get-buffer-window cur-buf)))
485 (wl-folder-set-folder-updated wl-trash-folder '(0 0 0)))
486 (if wl-stay-folder-window
487 (wl-folder-toggle-disp-summary 'off wl-trash-folder)
488 (switch-to-buffer cur-buf))
490 (kill-buffer trash-buf)))))
492 (defun wl-folder-goto-top-of-current-folder (&optional arg)
493 "Move backward to the top of the current folder group.
494 Optional argument ARG is repeart count."
496 (if (re-search-backward
497 "^ *\\[[\\+-]\\]" nil t (if arg (prefix-numeric-value arg)))
499 (goto-char (point-min))))
501 (defun wl-folder-goto-bottom-of-current-folder (indent)
502 "Move forward to the bottom of the current folder group."
507 (if (looking-at "^ *")
508 (buffer-substring (match-beginning 0)(1- (match-end 0)))
512 (while (re-search-forward "^ *" nil t)
513 (if (<= (length (match-string 0))
517 (goto-char (point-max))))
519 (defsubst wl-folder-update-group (entity diffs &optional is-group)
520 (let ((path (wl-folder-get-path
522 (wl-folder-get-entity-id entity)
525 ;; delete itself from path
526 (setq path (delete (nth (- (length path) 1) path) path)))
527 (goto-char (point-min))
530 ;; goto the path line.
531 (if (or (eq (car path) 0) ; update desktop
532 (wl-folder-buffer-search-group
533 (wl-folder-get-petname
534 (if (stringp (car path))
536 (wl-folder-get-folder-name-by-id
539 (wl-folder-update-diff-line diffs)
541 (setq path (cdr path))))))
543 (defun wl-folder-maybe-load-folder-list (entity)
544 (when (null (caddr entity))
546 (elmo-msgdb-flist-load (car entity)))
550 (wl-folder-entity-assign-id entity
551 wl-folder-entity-id-name-hashtb
553 (setq diffs (wl-fldmgr-add-entity-hashtb (list entity)))
554 (unless (equal diffs '(0 0 0))
555 (wl-folder-update-group (car entity) diffs t)))))))
557 (defsubst wl-folder-force-fetch-p (entity)
559 ((consp wl-force-fetch-folders)
560 (wl-string-match-member entity wl-force-fetch-folders))
562 wl-force-fetch-folders)))
564 (defun wl-folder-jump-to-current-entity (&optional arg)
565 "Enter the current folder. If optional arg exists, update folder list. "
568 (let (entity beg end indent opened fname err fld-name)
570 ((looking-at wl-folder-group-regexp)
572 (setq fname (wl-folder-get-realname (wl-match-buffer 3)))
573 (setq indent (wl-match-buffer 1))
574 (setq opened (wl-match-buffer 2))
575 (if (string= opened "+")
577 (setq entity (wl-folder-search-group-entity-by-name
582 (wl-folder-update-recursive-current-entity entity)
584 (setcdr (assoc (car entity) wl-folder-group-alist) t)
585 (if (eq 'access (cadr entity))
586 (wl-folder-maybe-load-folder-list entity))
587 (condition-case errobj
589 (if (or (wl-folder-force-fetch-p (car entity))
591 (eq 'access (cadr entity))
592 (null (caddr entity))))
593 (wl-folder-update-newest indent entity)
594 (wl-folder-insert-entity indent entity))
595 (wl-highlight-folder-path wl-folder-buffer-cur-path))
598 (setcdr (assoc fname wl-folder-group-alist) nil))
600 (elmo-display-error errobj t)
603 (setcdr (assoc fname wl-folder-group-alist) nil)))
605 (let ((buffer-read-only nil))
606 (delete-region (save-excursion (beginning-of-line)
608 (save-excursion (end-of-line)
614 (progn (wl-folder-goto-bottom-of-current-folder indent)
617 (setq entity (wl-folder-search-group-entity-by-name
620 (let ((buffer-read-only nil))
621 (delete-region beg end))
622 (setcdr (assoc (car entity) wl-folder-group-alist) nil)
623 (wl-folder-insert-entity indent entity) ; insert entity
625 (wl-highlight-folder-path wl-folder-buffer-cur-path)
626 ; (wl-delete-all-overlays)
627 ; (wl-highlight-folder-current-line)
629 ((setq fld-name (wl-folder-entity-name))
632 (wl-folder-set-current-entity-id
633 (wl-folder-get-entity-from-buffer))
634 (setq fld-name (wl-folder-get-realname fld-name)))
635 (wl-folder-set-current-entity-id
636 (get-text-property (point) 'wl-folder-entity-id))
637 (setq fld-name (wl-folder-get-folder-name-by-id
638 wl-folder-buffer-cur-entity-id)))
639 (let ((summary-buf (wl-summary-get-buffer-create fld-name arg))
641 (if wl-stay-folder-window
642 (wl-folder-select-buffer summary-buf)
644 (get-buffer-window summary-buf))
646 (wl-summary-goto-folder-subr fld-name
647 (wl-summary-get-sync-range fld-name)
649 (set-buffer-modified-p nil))
651 (defun wl-folder-close-entity (entity)
652 (let ((entities (list entity))
655 (setq entity (wl-pop entities))
658 (setcdr (assoc (car entity) wl-folder-group-alist) nil)
660 (wl-push entities entity-stack))
661 (setq entities (nth 2 entity))))
663 (setq entities (wl-pop entity-stack))))))
665 (defun wl-folder-update-recursive-current-entity (&optional entity)
667 (when (wl-folder-buffer-group-p)
669 ((string= (wl-match-buffer 2) "+")
673 (wl-folder-search-group-entity-by-name
674 (wl-folder-get-realname (wl-match-buffer 3))
676 (let ((inhibit-read-only t)
677 (entities (list entity))
678 entity-stack err indent)
679 (while (and entities (not err))
680 (setq entity (wl-pop entities))
683 (wl-folder-close-entity entity)
684 (setcdr (assoc (car entity) wl-folder-group-alist) t)
685 (unless (wl-folder-buffer-search-group
686 (wl-folder-get-petname (car entity)))
687 (error "%s: not found group" (car entity)))
688 (setq indent (wl-match-buffer 1))
689 (if (eq 'access (cadr entity))
690 (wl-folder-maybe-load-folder-list entity))
694 (condition-case errobj
695 (wl-folder-update-newest indent entity)
698 (setcdr (assoc (car entity) wl-folder-group-alist) nil))
700 (elmo-display-error errobj t)
703 (setcdr (assoc (car entity) wl-folder-group-alist) nil)))
705 (delete-region (save-excursion (beginning-of-line)
707 (save-excursion (end-of-line)
711 (wl-push entities entity-stack))
712 (setq entities (nth 2 entity))))
714 (setq entities (wl-pop entity-stack)))))
715 (set-buffer-modified-p nil)))
717 (wl-folder-jump-to-current-entity)))))
719 (defun wl-folder-no-auto-check-folder-p (folder)
722 (let ((li wl-auto-check-folder-list))
724 (if (string-match (car li) folder)
726 (setq li (cdr li)))))
729 (let ((li wl-auto-uncheck-folder-list))
731 (if (string-match (car li) folder)
732 (throw 'found t)) ; no check!
733 (setq li (cdr li))))))))
735 (defsubst wl-folder-add-folder-info (pre-value value)
737 (+ (or (nth 0 pre-value) 0) (or (nth 0 value) 0))
738 (+ (or (nth 1 pre-value) 0) (or (nth 1 value) 0))
739 (+ (or (nth 2 pre-value) 0) (or (nth 2 value) 0))))
741 (defun wl-folder-check-entity (entity &optional auto)
742 "Check unsync message number."
743 (let ((start-pos (point))
745 (run-hooks 'wl-folder-check-entity-pre-hook)
746 (if (and (consp entity) ;; group entity
747 wl-folder-check-async) ;; very fast
748 (setq ret-val (wl-folder-check-entity-async entity auto))
752 (let ((flist (if auto
754 'wl-folder-no-auto-check-folder-p
757 (wl-folder-check-entity-pre-hook nil)
758 (wl-folder-check-entity-hook nil)
762 (wl-folder-add-folder-info
764 (wl-folder-check-entity (car flist))))
765 (setq flist (cdr flist)))
766 ;(wl-folder-buffer-search-entity (car entity))
767 ;(wl-folder-update-line ret-val)
769 ((and (stringp entity)
770 (elmo-folder-plugged-p entity))
771 (message "Checking \"%s\"" entity)
772 (setq ret-val (wl-folder-check-one-entity entity))
773 (goto-char start-pos)
776 (message "Uncheck(unplugged) \"%s\"" entity)))))
778 (message "Checking \"%s\" is done."
779 (if (consp entity) (car entity) entity)))
780 (run-hooks 'wl-folder-check-entity-hook)
783 ;; All contained folders are imap4 and persistent flag, then
785 (defun wl-folder-use-server-diff-p (folder)
786 (let ((spec (elmo-folder-get-spec folder)))
788 ((eq (car spec) 'multi)
789 (let ((folders (cdr spec)))
792 (if (wl-folder-use-server-diff-p (car folders))
794 (setq folders (cdr folders)))
796 ((eq (car spec) 'filter)
797 (wl-folder-use-server-diff-p (nth 2 spec)))
798 ((eq (car spec) 'imap4)
799 (and wl-folder-use-server-diff
800 (elmo-imap4-use-flag-p spec)))
803 (defun wl-folder-check-one-entity (entity)
804 (let* ((elmo-use-server-diff (wl-folder-use-server-diff-p entity))
805 (nums (condition-case err
806 (if (wl-string-match-member entity wl-strict-diff-folders)
807 (elmo-strict-folder-diff entity)
808 (elmo-folder-diff entity))
810 ;; maybe not exist folder.
811 (if (and (not (memq 'elmo-open-error
812 (get (car err) 'error-conditions)))
813 (not (elmo-folder-exists-p entity)))
814 (wl-folder-create-subr entity)
815 (signal (car err) (cdr err))))))
817 (if (and (eq wl-folder-notify-deleted 'sync)
819 (or (> 0 (car nums)) (> 0 (cdr nums))))
821 (wl-folder-sync-entity entity)
822 (setq nums (elmo-folder-diff entity)))
823 (unless wl-folder-notify-deleted
824 (setq unsync (if (and (car nums) (> 0 (car nums))) 0 (car nums)))
825 (setq nomif (if (and (car nums) (> 0 (cdr nums))) 0 (cdr nums)))
826 (setq nums (cons unsync nomif)))
827 (wl-folder-entity-hashtb-set wl-folder-entity-hashtb entity
832 ;; If server diff, All unreads are
833 ;; treated as unsync.
834 (if elmo-use-server-diff 0)
835 (elmo-folder-get-info-unread entity)
836 (wl-summary-count-unread
837 (elmo-msgdb-mark-load
838 (elmo-msgdb-expand-path entity))
842 (setq wl-folder-info-alist-modified t)
844 (list (if wl-folder-notify-deleted
846 (max (or (car nums) 0))) unread (cdr nums))))
848 (defun wl-folder-check-entity-async (entity &optional auto)
849 (let ((elmo-nntp-groups-async t)
852 'wl-folder-no-auto-check-folder-p
853 (wl-folder-get-entity-list entity))
854 (wl-folder-get-entity-list entity)))
855 (nntp-connection-keys nil)
856 folder spec-list local-elist net-elist server
859 (if (not (elmo-folder-plugged-p (car elist)))
860 (message "Uncheck \"%s\"" (car elist))
862 (elmo-folder-get-primitive-spec-list (elmo-string (car elist))))
863 (cond ((assq 'nntp spec-list)
864 (wl-append net-elist (list (car elist)))
866 (when (eq (caar spec-list) 'nntp)
867 (when (not (string= server (elmo-nntp-spec-hostname (car spec-list))))
868 (setq server (elmo-nntp-spec-hostname (car spec-list)))
869 (message "Checking on \"%s\"" server))
870 (setq nntp-connection-keys
871 (elmo-nntp-get-folders-info-prepare
873 nntp-connection-keys)))
874 (setq spec-list (cdr spec-list))))
876 (wl-append local-elist (list (car elist))))))
877 (setq elist (cdr elist)))
878 ;; check local entity at first
879 (while (setq folder (pop local-elist))
880 (if (not (elmo-folder-plugged-p folder))
881 (message "Uncheck \"%s\"" folder)
882 (message "Checking \"%s\"" folder)
884 (wl-folder-add-folder-info
886 (wl-folder-check-one-entity folder)))
889 ;; check network entity at last
891 (elmo-nntp-get-folders-info nntp-connection-keys)
892 (while (setq folder (pop net-elist))
893 (if (not (elmo-folder-plugged-p folder))
894 (message "Uncheck \"%s\"" folder)
895 (message "Checking \"%s\"" folder)
897 (wl-folder-add-folder-info
899 (wl-folder-check-one-entity folder)))
905 (defun wl-folder-resume-entity-hashtb-by-finfo (entity-hashtb info-alist)
906 "Resume unread info for entity alist."
909 (setq info (nth 1 (car info-alist)))
910 (wl-folder-set-entity-info (caar info-alist)
911 (list (nth 2 info)(nth 3 info)(nth 1 info))
913 (setq info-alist (cdr info-alist)))))
915 (defun wl-folder-move-path (path)
916 (let ((fp (if (consp path)
919 (wl-folder-get-path wl-folder-entity path))))
920 (goto-char (point-min))
923 (when (equal (car fp)
924 (wl-folder-get-entity-from-buffer t))
926 (setq wl-folder-buffer-cur-point (point)))
928 (and wl-folder-buffer-cur-point
929 (goto-char wl-folder-buffer-cur-point))))
931 (defun wl-folder-set-current-entity-id (entity-id)
932 (let ((buf (get-buffer wl-folder-buffer-name)))
936 (setq wl-folder-buffer-cur-entity-id entity-id)
937 (setq wl-folder-buffer-cur-path (wl-folder-get-path wl-folder-entity
939 (wl-highlight-folder-path wl-folder-buffer-cur-path)
940 (and wl-folder-move-cur-folder
941 wl-folder-buffer-cur-point
942 (goto-char wl-folder-buffer-cur-point))))
943 (if (eq (current-buffer) buf)
944 (and wl-folder-move-cur-folder
945 wl-folder-buffer-cur-point
946 (goto-char wl-folder-buffer-cur-point)))))
948 (defun wl-folder-check-current-entity ()
949 "Check folder at position.
950 If current line is group folder, check all sub entries."
952 (let* ((entity-name (wl-folder-get-entity-from-buffer))
953 (group (wl-folder-buffer-group-p))
954 (desktop (string= entity-name wl-folder-desktop-name)))
956 (wl-folder-check-entity
958 (wl-folder-search-group-entity-by-name entity-name
963 (defun wl-folder-sync-entity (entity &optional unread-only)
964 "Synchronize the msgdb of ENTITY."
967 (let ((flist (nth 2 entity)))
969 (wl-folder-sync-entity (car flist) unread-only)
970 (setq flist (cdr flist)))))
972 (let ((nums (wl-folder-get-entity-info entity))
973 (wl-summary-highlight (if (or (wl-summary-sticky-p entity)
974 (wl-summary-always-sticky-folder-p
976 wl-summary-highlight))
977 wl-auto-select-first new unread)
978 (setq new (or (car nums) 0))
979 (setq unread (or (cadr nums) 0))
980 (if (or (not unread-only)
981 (or (< 0 new) (< 0 unread)))
982 (save-window-excursion
984 (wl-summary-goto-folder-subr entity
985 (wl-summary-get-sync-range entity)
987 (wl-summary-exit))))))))
989 (defun wl-folder-sync-current-entity (&optional unread-only)
990 "Synchronize the folder at position.
991 If current line is group folder, check all subfolders."
994 (let ((entity-name (wl-folder-get-entity-from-buffer))
995 (group (wl-folder-buffer-group-p)))
996 (when (and entity-name
997 (y-or-n-p (format "Sync %s?" entity-name)))
998 (wl-folder-sync-entity
1000 (wl-folder-search-group-entity-by-name entity-name
1004 (message "Syncing %s is done!" entity-name)))))
1006 (defun wl-folder-mark-as-read-all-entity (entity)
1007 "Mark as read all messages in the ENTITY"
1010 (let ((flist (nth 2 entity)))
1012 (wl-folder-mark-as-read-all-entity (car flist))
1013 (setq flist (cdr flist)))))
1015 (let ((nums (wl-folder-get-entity-info entity))
1016 (wl-summary-highlight (if (or (wl-summary-sticky-p entity)
1017 (wl-summary-always-sticky-folder-p
1019 wl-summary-highlight))
1020 wl-auto-select-first new unread)
1021 (setq new (or (car nums) 0))
1022 (setq unread (or (cadr nums) 0))
1023 (if (or (< 0 new) (< 0 unread))
1024 (save-window-excursion
1026 (wl-summary-goto-folder-subr entity
1027 (wl-summary-get-sync-range entity)
1029 (wl-summary-mark-as-read-all)
1033 (defun wl-folder-mark-as-read-all-current-entity ()
1034 "Mark as read all messages in the folder at position.
1035 If current line is group folder, all subfolders are marked."
1038 (let ((entity-name (wl-folder-get-entity-from-buffer))
1039 (group (wl-folder-buffer-group-p))
1041 (when (and entity-name
1042 (y-or-n-p (format "Mark all messages in %s as read?" entity-name)))
1043 (wl-folder-mark-as-read-all-entity
1045 (wl-folder-search-group-entity-by-name entity-name
1048 (message "All messages in %s are marked!" entity-name)))))
1050 (defun wl-folder-check-region (beg end)
1059 (let ((inhibit-read-only t)
1061 (while (< (point) end)
1062 ;; normal folder entity
1063 (if (looking-at "^[\t ]*\\([^\\[]+\\):\\(.*\\)\n")
1065 (setq entity (wl-folder-get-entity-from-buffer))
1066 (if (not (elmo-folder-plugged-p entity))
1067 (message "Uncheck %s" entity)
1068 (message "Checking %s" entity)
1069 (wl-folder-check-one-entity entity)
1074 (defun wl-folder-sync-region (beg end)
1083 (while (< (point) end)
1084 ;; normal folder entity
1085 (if (looking-at "^[\t ]*\\([^\\[]+\\):\\(.*\\)\n")
1087 (let ((inhibit-read-only t)
1089 (setq entity (wl-folder-get-entity-from-buffer))
1090 (wl-folder-sync-entity entity)
1091 (message "Syncing %s is done!" entity)
1096 (defun wl-folder-mark-as-read-all-region (beg end)
1105 (while (< (point) end)
1106 ;; normal folder entity
1107 (if (looking-at "^[\t ]*\\([^\\[]+\\):\\(.*\\)\n")
1109 (let ((inhibit-read-only t)
1111 (setq entity (wl-folder-get-entity-from-buffer))
1112 (wl-folder-mark-as-read-all-entity entity)
1113 (message "All messages in %s are marked!" entity)
1118 (defsubst wl-create-access-init-load-p (folder)
1119 (let ((no-load-regexp (when (and
1120 (not wl-folder-init-load-access-folders)
1121 wl-folder-init-no-load-access-folders)
1122 (mapconcat 'identity
1123 wl-folder-init-no-load-access-folders
1125 (load-regexp (and wl-folder-init-load-access-folders
1126 (mapconcat 'identity
1127 wl-folder-init-load-access-folders
1129 (cond (load-regexp (string-match load-regexp folder))
1130 (t (not (and no-load-regexp
1131 (string-match no-load-regexp folder)))))))
1133 (defun wl-create-access-folder-entity (name)
1135 (when (wl-create-access-init-load-p name)
1136 (setq flists (elmo-msgdb-flist-load name)) ; load flist.
1137 (setq flist (car flists))
1139 (when (consp (car flist))
1140 (setcdr (cdar flist)
1141 (wl-create-access-folder-entity (caar flist))))
1142 (setq flist (cdr flist)))
1145 (defun wl-create-folder-entity-from-buffer ()
1146 "Create folder entity recursively."
1148 ((looking-at "^[ \t]*$") ; blank line
1149 (goto-char (+ 1(match-end 0)))
1151 ((looking-at "^#.*$") ; comment
1152 (goto-char (+ 1 (match-end 0)))
1154 ((looking-at "^[\t ]*\\(.+\\)[\t ]*{[\t ]*$") ; group definition
1155 (let (name entity flist)
1156 (setq name (wl-match-buffer 1))
1157 (goto-char (+ 1 (match-end 0)))
1158 (while (setq entity (wl-create-folder-entity-from-buffer))
1159 (unless (eq entity 'ignore)
1160 (wl-append flist (list entity))))
1161 (if (looking-at "^[\t ]*}[\t ]*$") ; end of group
1163 (goto-char (+ 1 (match-end 0)))
1164 (if (wl-string-assoc name wl-folder-petname-alist)
1165 (error "%s already defined as petname" name))
1166 (list name 'group flist))
1167 (error "Syntax error in folder definition"))))
1168 ((looking-at "^[\t ]*\\([^\t \n]+\\)[\t ]*/$") ; access it!
1170 (setq name (wl-match-buffer 1))
1171 (goto-char (+ 1 (match-end 0)))
1172 ; (condition-case ()
1174 ; (setq flist (elmo-list-folders name)))
1175 ; (error (message "Access to folder %s failed." name)))
1176 ;; (setq flist (elmo-msgdb-flist-load name)) ; load flist.
1177 ;; (setq unsublist (nth 1 flist))
1178 ;; (setq flist (car flist))
1179 ;; (list name 'access flist unsublist)))
1180 (append (list name 'access) (wl-create-access-folder-entity name))))
1181 ;((looking-at "^[\t ]*\\([^\t \n}]+\\)[\t ]*\\(\"[^\"]*\"\\)?[\t ]*$") ; normal folder entity
1182 ((looking-at "^[\t ]*=[ \t]+\\([^\n]+\\)$"); petname definition
1183 (goto-char (+ 1 (match-end 0)))
1184 (let ((rest (elmo-match-buffer 1))
1186 (when (string-match "\\(\"[^\"]*\"\\)[\t ]*$" rest)
1187 (setq petname (elmo-delete-char ?\" (elmo-match-string 1 rest)))
1188 (setq rest (substring rest 0 (match-beginning 0))))
1189 (when (string-match "^[\t ]*\\(.*[^\t ]+\\)[\t ]+$" rest)
1190 (wl-folder-append-petname (elmo-match-string 1 rest)
1193 ((looking-at "^[ \t]*}[ \t]*$") ; end of group
1195 ((looking-at "^.*$") ; normal folder entity
1196 (goto-char (+ 1 (match-end 0)))
1197 (let ((rest (elmo-match-buffer 0))
1199 (if (string-match "\\(\"[^\"]*\"\\)[\t ]*$" rest)
1201 (setq petname (elmo-delete-char ?\" (elmo-match-string 1 rest)))
1202 (setq rest (substring rest 0 (match-beginning 0)))
1203 (when (string-match "^[\t ]*\\(.*[^\t ]+\\)[\t ]+$" rest)
1204 (wl-folder-append-petname
1205 (setq realname (elmo-match-string 1 rest))
1208 (if (string-match "^[\t ]*\\(.+\\)$" rest)
1209 (elmo-match-string 1 rest)
1212 (defun wl-folder-create-folder-entity ()
1213 "Create folder entries."
1214 (let ((tmp-buf (get-buffer-create " *wl-folder-tmp*"))
1218 (with-current-buffer tmp-buf
1220 (insert-file-contents wl-folders-file)
1221 (goto-char (point-min))
1222 (while (and (not (eobp))
1223 (setq entity (wl-create-folder-entity-from-buffer)))
1224 (unless (eq entity 'ignore)
1225 (wl-append ret-val (list entity)))))
1226 (kill-buffer tmp-buf))
1228 (setq ret-val (list wl-folder-desktop-name 'group ret-val))))
1230 (defun wl-folder-entity-assign-id (entity &optional hashtb on-noid)
1231 (let ((hashtb (or hashtb
1232 (setq wl-folder-entity-id-name-hashtb
1233 (elmo-make-hash wl-folder-entity-id))))
1234 (entities (list entity))
1237 (setq entity (wl-pop entities))
1240 (when (not (and on-noid
1241 (get-text-property 0
1242 'wl-folder-entity-id
1244 (put-text-property 0 (length (car entity))
1245 'wl-folder-entity-id
1248 (wl-folder-set-id-name wl-folder-entity-id
1249 (car entity) hashtb))
1251 (wl-push entities entity-stack))
1252 (setq entities (nth 2 entity)))
1254 (when (not (and on-noid
1255 (get-text-property 0
1256 'wl-folder-entity-id
1258 (put-text-property 0 (length entity)
1259 'wl-folder-entity-id
1262 (wl-folder-set-id-name wl-folder-entity-id
1264 (setq wl-folder-entity-id (+ 1 wl-folder-entity-id))
1266 (setq entities (wl-pop entity-stack))))))
1268 (defun wl-folder-click (e)
1273 (wl-folder-jump-to-current-entity)))
1275 (defun wl-folder-select-buffer (buffer)
1276 (let ((gbw (get-buffer-window buffer))
1279 (progn (select-window gbw)
1283 (split-window-horizontally wl-folder-window-width)
1287 (switch-to-buffer buffer)
1291 (defun wl-folder-toggle-disp-summary (&optional arg folder)
1293 (if (or (and folder (assoc folder wl-folder-group-alist))
1294 (and (interactive-p) (wl-folder-buffer-group-p)))
1295 (error "This command is not available on Group"))
1297 (let (wl-auto-select-first)
1300 (setq wl-folder-buffer-disp-summary t))
1302 (setq wl-folder-buffer-disp-summary nil)
1303 ;; hide wl-summary window.
1304 (let ((cur-buf (current-buffer))
1305 (summary-buffer (wl-summary-get-buffer folder)))
1306 (wl-folder-select-buffer summary-buffer)
1308 (select-window (get-buffer-window cur-buf))))
1310 (setq wl-folder-buffer-disp-summary
1311 (not wl-folder-buffer-disp-summary))
1312 (let ((cur-buf (current-buffer))
1314 (when (looking-at "^[ ]*\\([^\\[].+\\):.*\n")
1315 (setq folder-name (wl-folder-get-entity-from-buffer))
1316 (if wl-folder-buffer-disp-summary
1318 (wl-folder-select-buffer
1319 (wl-summary-get-buffer-create folder-name))
1321 (wl-summary-goto-folder-subr folder-name 'no-sync nil)
1322 (select-window (get-buffer-window cur-buf))))
1323 (wl-folder-select-buffer (wl-summary-get-buffer folder-name))
1325 (select-window (get-buffer-window cur-buf)))))))))
1327 (defun wl-folder-prev-unsync ()
1328 "move cursor to the previous unsync folder."
1331 (setq start-point (point))
1333 (if (re-search-backward wl-folder-unsync-regexp nil t)
1335 (goto-char start-point)
1336 (message "No more unsync folder"))))
1338 (defun wl-folder-next-unsync (&optional plugged)
1339 "move cursor to the next unsync."
1341 (let (start-point entity)
1342 (setq start-point (point))
1345 (while (re-search-forward wl-folder-unsync-regexp nil t)
1346 (if (or (wl-folder-buffer-group-p)
1349 (wl-folder-get-realname
1350 (wl-folder-folder-name)))
1351 (elmo-folder-plugged-p entity))
1354 (goto-char start-point)
1355 (message "No more unsync folder"))))
1357 (defun wl-folder-prev-unread (&optional group)
1358 "move cursor to the previous unread folder."
1361 (setq start-point (point))
1363 (if (re-search-backward (wl-folder-unread-regex group) nil t)
1366 (wl-folder-folder-name))
1367 (goto-char start-point)
1368 (message "No more unread folder")
1371 (defun wl-folder-next-unread (&optional group)
1372 "move cursor to the next unread folder."
1375 (setq start-point (point))
1377 (if (re-search-forward (wl-folder-unread-regex group) nil t)
1380 (wl-folder-folder-name))
1381 (goto-char start-point)
1382 (message "No more unread folder")
1385 (defun wl-folder-mode ()
1386 "Major mode for Wanderlust Folder.
1387 See info under Wanderlust for full documentation.
1390 \\{wl-folder-mode-map}
1392 Entering Folder mode calls the value of `wl-folder-mode-hook'."
1394 (setq major-mode 'wl-folder-mode)
1395 (setq mode-name "Folder")
1396 (use-local-map wl-folder-mode-map)
1397 (setq buffer-read-only t)
1398 (setq inhibit-read-only nil)
1399 (setq truncate-lines t)
1400 (setq wl-folder-buffer-cur-entity-id nil
1401 wl-folder-buffer-cur-path nil
1402 wl-folder-buffer-cur-point nil)
1403 (wl-mode-line-buffer-identification)
1404 (easy-menu-add wl-folder-mode-menu)
1405 ;; This hook may contain the functions `wl-folder-init-icons' and
1406 ;; `wl-setup-folder' for reasons of system internal to accord
1407 ;; facilities for the Emacs variants.
1408 (run-hooks 'wl-folder-mode-hook))
1410 (defun wl-folder-append-petname (realname petname)
1412 ;; check group name.
1413 (if (wl-folder-search-group-entity-by-name petname wl-folder-entity)
1414 (error "%s already defined as group name" petname))
1415 (when (setq pentry (wl-string-assoc realname wl-folder-petname-alist))
1416 (setq wl-folder-petname-alist
1417 (delete pentry wl-folder-petname-alist)))
1418 (wl-append wl-folder-petname-alist
1419 (list (cons realname petname)))))
1421 (defun wl-folder (&optional arg)
1424 ; (delete-other-windows)
1425 (if (get-buffer wl-folder-buffer-name)
1426 (switch-to-buffer wl-folder-buffer-name)
1427 (switch-to-buffer (get-buffer-create wl-folder-buffer-name))
1430 (set-buffer wl-folder-buffer-name)
1431 (let ((inhibit-read-only t)
1432 (buffer-read-only nil))
1434 (setcdr (assoc (car wl-folder-entity) wl-folder-group-alist) t)
1436 (wl-folder-insert-entity " " wl-folder-entity)))
1437 (set-buffer-modified-p nil)
1439 (setq initialize t))
1442 (defun wl-folder-auto-check ()
1443 "Check and update folders in `wl-auto-check-folder-name'."
1445 (when (get-buffer wl-folder-buffer-name)
1446 (switch-to-buffer wl-folder-buffer-name)
1448 ((eq wl-auto-check-folder-name 'none))
1449 ((or (consp wl-auto-check-folder-name)
1450 (stringp wl-auto-check-folder-name))
1451 (let ((folder-list (if (consp wl-auto-check-folder-name)
1452 wl-auto-check-folder-name
1453 (list wl-auto-check-folder-name)))
1456 (if (setq entity (wl-folder-search-entity-by-name
1459 (wl-folder-check-entity entity 'auto))
1460 (setq folder-list (cdr folder-list)))))
1462 (wl-folder-check-entity wl-folder-entity 'auto)))))
1464 (defun wl-folder-set-folder-updated (name value)
1467 (if (setq buf (get-buffer wl-folder-buffer-name))
1468 (wl-folder-entity-hashtb-set
1469 wl-folder-entity-hashtb name value buf))
1470 ;; (elmo-folder-set-info-hashtb (elmo-string name)
1475 (setq wl-folder-info-alist-modified t))))
1477 (defun wl-folder-calc-finfo (entity)
1478 ;; calcurate finfo without inserting.
1479 (let ((entities (list entity))
1481 new unread all nums)
1483 (setq entity (wl-pop entities))
1487 (wl-push entities entity-stack))
1488 (setq entities (nth 2 entity)))
1490 (setq nums (wl-folder-get-entity-info entity))
1491 (setq new (+ (or new 0) (or (nth 0 nums) 0)))
1492 (setq unread (+ (or unread 0)
1493 (or (and (nth 0 nums)(nth 1 nums)
1494 (+ (nth 0 nums)(nth 1 nums))) 0)))
1495 (setq all (+ (or all 0) (or (nth 2 nums) 0)))))
1497 (setq entities (wl-pop entity-stack))))
1498 (list new unread all)))
1500 (defsubst wl-folder-make-save-access-list (list)
1501 (mapcar '(lambda (x)
1504 (list (elmo-string (car x)) 'access))
1509 (defun wl-folder-update-newest (indent entity)
1510 (let (ret-val new unread all)
1513 (let ((inhibit-read-only t)
1514 (buffer-read-only nil)
1515 (flist (nth 2 entity))
1516 (as-opened (cdr (assoc (car entity) wl-folder-group-alist)))
1521 (let (update-flist flist-unsub new-flist removed group-name-end)
1522 (when (and (eq (cadr entity) 'access)
1523 (elmo-folder-plugged-p (car entity)))
1524 (message "Fetching folder entries...")
1525 (when (setq new-flist
1527 (elmo-string (car entity))
1530 wl-folder-hierarchy-access-folders)))
1532 (wl-folder-update-access-group entity new-flist))
1533 (setq flist (nth 1 update-flist))
1534 (when (car update-flist) ;; diff
1535 (setq flist-unsub (nth 2 update-flist))
1536 (setq removed (nth 3 update-flist))
1537 (elmo-msgdb-flist-save
1540 (wl-folder-make-save-access-list flist)
1541 (wl-folder-make-save-access-list flist-unsub)))
1542 (wl-folder-entity-assign-id
1544 wl-folder-entity-id-name-hashtb
1546 (setq wl-folder-entity-hashtb
1547 (wl-folder-create-entity-hashtb
1549 wl-folder-entity-hashtb
1551 (setq wl-folder-newsgroups-hashtb
1553 (wl-folder-create-newsgroups-hashtb
1555 wl-folder-newsgroups-hashtb))))
1556 (message "Fetching folder entries...done"))
1557 (wl-folder-insert-entity indent entity))))))))
1559 (defun wl-folder-insert-entity (indent entity &optional onlygroup)
1560 (let (ret-val new unread all)
1563 (let ((inhibit-read-only t)
1564 (buffer-read-only nil)
1565 (flist (nth 2 entity))
1566 (as-opened (cdr (assoc (car entity) wl-folder-group-alist)))
1569 ; (insert indent "[" (if as-opened "-" "+") "]" (car entity) "\n")
1570 ; (save-excursion (forward-line -1)
1571 ; (wl-highlight-folder-current-line))
1575 (let (update-flist flist-unsub new-flist removed group-name-end)
1576 ; (when (and (eq (cadr entity) 'access)
1578 ; (message "fetching folder entries...")
1579 ; (when (setq new-flist
1580 ; (elmo-list-folders
1581 ; (elmo-string (car entity))
1584 ; wl-folder-hierarchy-access-folders)
1586 ; (setq update-flist
1587 ; (wl-folder-update-access-group entity new-flist))
1588 ; (setq flist (nth 1 update-flist))
1589 ; (when (car update-flist) ;; diff
1590 ; (setq flist-unsub (nth 2 update-flist))
1591 ; (setq removed (nth 3 update-flist))
1592 ; (elmo-msgdb-flist-save
1595 ; (wl-folder-make-save-access-list flist)
1596 ; (wl-folder-make-save-access-list flist-unsub)))
1598 ; ;; reconstruct wl-folder-entity-id-name-hashtb and
1599 ; ;; wl-folder-entity-hashtb
1601 ; (wl-folder-entity-assign-id
1603 ; wl-folder-entity-id-name-hashtb
1605 ; (setq wl-folder-entity-hashtb
1606 ; (wl-folder-create-entity-hashtb
1608 ; wl-folder-entity-hashtb
1610 ; (setq wl-folder-newsgroups-hashtb
1612 ; (wl-folder-create-newsgroups-hashtb
1614 ; wl-folder-newsgroups-hashtb))))
1615 ; (message "fetching folder entries...done"))
1616 (insert indent "[" (if as-opened "-" "+") "]"
1617 (wl-folder-get-petname (car entity)))
1618 (setq group-name-end (point))
1620 (put-text-property beg (point) 'wl-folder-entity-id
1621 (get-text-property 0 'wl-folder-entity-id
1627 wl-folder-removed-mark
1628 (if (listp (car removed))
1629 (concat "[+]" (caar removed))
1632 (save-excursion (forward-line -1)
1633 (wl-highlight-folder-current-line))
1634 (setq removed (cdr removed)))
1635 (remove-text-properties beg (point) '(wl-folder-entity-id)))
1636 (let* ((len (length flist))
1641 (wl-folder-insert-entity
1642 (concat indent " ") (car flist)))
1643 (setq new (+ (or new 0) (or (nth 0 ret-val) 0)))
1644 (setq unread (+ (or unread 0) (or (nth 1 ret-val) 0)))
1645 (setq all (+ (or all 0) (or (nth 2 ret-val) 0)))
1647 (> len elmo-display-progress-threshold))
1649 (elmo-display-progress
1650 'wl-folder-insert-entity "Inserting group %s..."
1651 (/ (* i 100) len) (car entity)))
1652 (setq flist (cdr flist))))
1654 (goto-char group-name-end)
1655 (delete-region (point) (save-excursion (end-of-line)
1657 (insert (format ":%d/%d/%d" (or new 0)
1658 (or unread 0) (or all 0)))
1659 (setq ret-val (list new unread all))
1660 (wl-highlight-folder-current-line ret-val)))
1661 (setq ret-val (wl-folder-calc-finfo entity))
1662 (insert indent "[" (if as-opened "-" "+") "]"
1663 (wl-folder-get-petname (car entity))
1665 (or (nth 0 ret-val) 0)
1666 (or (nth 1 ret-val) 0)
1667 (or (nth 2 ret-val) 0))
1669 (put-text-property beg (point) 'wl-folder-entity-id
1670 (get-text-property 0 'wl-folder-entity-id
1672 (save-excursion (forward-line -1)
1673 (wl-highlight-folder-current-line ret-val)))))
1675 (let* ((inhibit-read-only t)
1676 (buffer-read-only nil)
1677 (nums (wl-folder-get-entity-info entity))
1680 (insert indent (wl-folder-get-petname entity)
1681 (format ":%s/%s/%s\n"
1682 (or (setq new (nth 0 nums)) "*")
1683 (or (setq unread (and (nth 0 nums)(nth 1 nums)
1684 (+ (nth 0 nums)(nth 1 nums))))
1686 (or (setq all (nth 2 nums)) "*")))
1687 (put-text-property beg (point) 'wl-folder-entity-id
1688 (get-text-property 0 'wl-folder-entity-id entity))
1689 (save-excursion (forward-line -1)
1690 (wl-highlight-folder-current-line nums))
1691 (setq ret-val (list new unread all)))))
1692 (set-buffer-modified-p nil)
1695 (defun wl-folder-check-all ()
1697 (wl-folder-check-entity wl-folder-entity))
1699 (defun wl-folder-entity-hashtb-set (entity-hashtb name value buffer)
1706 (setq cur-val (wl-folder-get-entity-info name entity-hashtb))
1707 (setq new-diff (- (or (nth 0 value) 0) (or (nth 0 cur-val) 0)))
1710 (- (or (nth 1 value) 0) (or (nth 1 cur-val) 0))))
1711 (setq all-diff (- (or (nth 2 value) 0) (or (nth 2 cur-val) 0)))
1712 (setq diffs (list new-diff unread-diff all-diff))
1713 (unless (and (nth 0 cur-val)
1714 (equal diffs '(0 0 0)))
1715 (wl-folder-set-entity-info name value entity-hashtb)
1719 (setq entity-list (wl-folder-search-entity-list-by-name
1720 name wl-folder-entity))
1722 (wl-folder-update-group (car entity-list) diffs)
1723 (setq entity-list (cdr entity-list)))
1724 (goto-char (point-min))
1725 (while (wl-folder-buffer-search-entity name)
1726 (wl-folder-update-line value)))))))
1728 (defun wl-folder-update-unread (folder unread)
1729 (save-window-excursion
1730 (let ((buf (get-buffer wl-folder-buffer-name))
1733 ;;(fld (elmo-string folder))
1734 value newvalue entity-list)
1735 ;; Update folder-info
1736 ;;(elmo-folder-set-info-hashtb fld nil nil nil unread)
1737 (setq cur-unread (or (nth 1 (wl-folder-get-entity-info folder)) 0))
1738 (setq unread-diff (- (or unread 0) cur-unread))
1739 (setq value (wl-folder-get-entity-info folder))
1741 (setq newvalue (list (nth 0 value)
1744 (wl-folder-set-entity-info folder newvalue)
1745 (setq wl-folder-info-alist-modified t)
1747 (not (eq unread-diff 0)))
1752 (setq entity-list (wl-folder-search-entity-list-by-name
1753 folder wl-folder-entity))
1755 (wl-folder-update-group (car entity-list) (list 0
1758 (setq entity-list (cdr entity-list)))
1759 (goto-char (point-min))
1760 (while (wl-folder-buffer-search-entity folder)
1761 (wl-folder-update-line newvalue)))))))))
1763 (defun wl-folder-create-entity-hashtb (entity &optional hashtb reconst)
1764 (let ((hashtb (or hashtb (elmo-make-hash wl-folder-entity-id)))
1765 (entities (list entity))
1768 (setq entity (wl-pop entities))
1772 (wl-push entities entity-stack))
1773 (setq entities (nth 2 entity)))
1775 (when (not (and reconst
1776 (wl-folder-get-entity-info entity)))
1777 (wl-folder-set-entity-info entity
1781 (setq entities (wl-pop entity-stack))))
1784 ;; Unsync number is reserved.
1785 ;;(defun wl-folder-reconstruct-entity-hashtb (entity &optional hashtb id-name)
1786 ;; (let* ((hashtb (or hashtb (elmo-make-hash wl-folder-entity-id)))
1787 ;; (entities (list entity))
1790 ;; (setq entity (wl-pop entities))
1794 ;; (wl-folder-set-id-name (wl-folder-get-entity-id (car entity))
1797 ;; (wl-push entities entity-stack))
1798 ;; (setq entities (nth 2 entity))
1800 ;; ((stringp entity)
1801 ;; (wl-folder-set-entity-info entity
1802 ;; (wl-folder-get-entity-info entity)
1805 ;; (wl-folder-set-id-name (wl-folder-get-entity-id entity)
1808 ;; (setq entities (wl-pop entity-stack))))
1811 (defun wl-folder-create-newsgroups-from-nntp-access2 (entity)
1812 (let ((flist (nth 2 entity))
1821 (wl-folder-create-newsgroups-from-nntp-access2 fld)
1822 (nth 1 (elmo-folder-get-spec fld))))
1824 (elmo-nntp-make-groups-hashtb folders 1024))
1827 (defun wl-folder-create-newsgroups-from-nntp-access (entity)
1828 (let ((flist (nth 2 entity))
1833 ((consp (car flist))
1834 (wl-folder-create-newsgroups-from-nntp-access (car flist)))
1836 (list (nth 1 (elmo-folder-get-spec (car flist)))))))
1837 (setq flist (cdr flist)))
1840 (defun wl-folder-create-newsgroups-hashtb (entity &optional is-list info)
1841 (let ((entities (if is-list entity (list entity)))
1842 entity-stack spec-list folders fld make-hashtb)
1843 (and info (message "Creating newsgroups..."))
1845 (setq entity (wl-pop entities))
1848 (if (eq (nth 1 entity) 'access)
1849 (when (eq (elmo-folder-get-type (car entity)) 'nntp)
1851 (wl-folder-create-newsgroups-from-nntp-access entity))
1852 (setq make-hashtb t))
1854 (wl-push entities entity-stack))
1855 (setq entities (nth 2 entity))))
1857 (setq spec-list (elmo-folder-get-primitive-spec-list entity))
1859 (when (and (eq (caar spec-list) 'nntp)
1860 (setq fld (nth 1 (car spec-list))))
1861 (wl-append folders (list (elmo-string fld))))
1862 (setq spec-list (cdr spec-list)))))
1864 (setq entities (wl-pop entity-stack))))
1865 (and info (message "Creating newsgroups...done"))
1866 (if (or folders make-hashtb)
1867 (elmo-nntp-make-groups-hashtb folders))))
1869 (defun wl-folder-get-path (entity target-id &optional string)
1870 (let ((entities (list entity))
1871 entity-stack result-path)
1875 (setq entity (wl-pop entities))
1878 (if (and (or (not string) (string= string (car entity)))
1879 ;; don't use eq, `id' is string on Nemacs.
1880 (equal target-id (wl-folder-get-entity-id (car entity))))
1882 (wl-push target-id result-path))
1883 (wl-push (wl-folder-get-entity-id (car entity)) result-path))
1884 (wl-push entities entity-stack)
1885 (setq entities (nth 2 entity)))
1887 (if (and (or (not string) (string= string entity))
1888 ;; don't use eq, `id' is string on Nemacs.
1889 (equal target-id (wl-folder-get-entity-id entity)))
1891 (wl-push target-id result-path)))))
1893 (while (and entity-stack
1895 (setq result-path (cdr result-path))
1896 (setq entities (wl-pop entity-stack)))))))))
1898 (defun wl-folder-create-group-alist (entity)
1900 (let ((flist (nth 2 entity))
1901 (cur-alist (list (cons (car entity) nil)))
1904 (if (consp (car flist))
1905 (wl-append append-alist
1906 (wl-folder-create-group-alist (car flist))))
1907 (setq flist (cdr flist)))
1908 (append cur-alist append-alist))))
1910 (defun wl-folder-init-info-hashtb ()
1911 (let ((info-alist (and wl-folder-info-save
1912 (elmo-msgdb-finfo-load))))
1913 (elmo-folder-info-make-hashtb
1915 wl-folder-entity-hashtb)))
1916 ;; (wl-folder-resume-entity-hashtb-by-finfo
1917 ;; wl-folder-entity-hashtb
1920 (defun wl-folder-cleanup-variables ()
1921 (setq wl-folder-entity nil
1922 wl-folder-entity-hashtb nil
1923 wl-folder-entity-id-name-hashtb nil
1924 wl-folder-group-alist nil
1925 wl-folder-petname-alist nil
1926 wl-folder-newsgroups-hashtb nil
1927 wl-fldmgr-cut-entity-list nil
1928 wl-fldmgr-modified nil
1929 wl-fldmgr-modified-access-list nil
1933 (defun wl-make-plugged-alist ()
1934 (let ((entity-list (wl-folder-get-entity-list wl-folder-entity))
1935 (add (not wl-reset-plugged-alist)))
1937 (elmo-folder-set-plugged
1938 (elmo-string (car entity-list)) wl-plugged add)
1939 (setq entity-list (cdr entity-list)))
1940 ;; smtp posting server
1941 (when wl-smtp-posting-server
1942 (elmo-set-plugged wl-plugged
1943 wl-smtp-posting-server ; server
1944 (or (and (boundp 'smtp-service) smtp-service)
1946 nil nil "smtp" add))
1947 ;; nntp posting server
1948 (when wl-nntp-posting-server
1949 (elmo-set-plugged wl-plugged
1950 wl-nntp-posting-server
1951 elmo-default-nntp-port
1952 nil nil "nntp" add))
1953 ;; This hook may contain the functions `wl-plugged-init-icons' and
1954 ;; `wl-biff-init-icons' for reasons of system internal to accord
1955 ;; facilities for the Emacs variants.
1956 (run-hooks 'wl-make-plugged-hook)))
1958 (defvar wl-folder-init-func 'wl-local-folder-init)
1960 (defun wl-folder-init ()
1962 (funcall wl-folder-init-func))
1964 (defun wl-local-folder-init ()
1965 (message "Initializing folder...")
1967 (set-buffer wl-folder-buffer-name)
1968 (let ((entity (wl-folder-create-folder-entity))
1969 (inhibit-read-only t))
1970 (setq wl-folder-entity entity)
1971 (setq wl-folder-entity-id 0)
1972 (wl-folder-entity-assign-id wl-folder-entity)
1973 (setq wl-folder-entity-hashtb
1974 (wl-folder-create-entity-hashtb entity))
1975 (setq wl-folder-group-alist
1976 (wl-folder-create-group-alist entity))
1977 (setq wl-folder-newsgroups-hashtb
1978 (wl-folder-create-newsgroups-hashtb wl-folder-entity))
1979 (wl-folder-init-info-hashtb)))
1980 (message "Initializing folder...done"))
1982 (defun wl-folder-get-realname (petname)
1986 wl-folder-petname-alist))
1989 (defun wl-folder-get-petname (folder)
1993 wl-folder-petname-alist))
1996 (defun wl-folder-get-entity-with-petname ()
1997 (let ((alist wl-folder-petname-alist)
1998 (hashtb (copy-sequence wl-folder-entity-hashtb)))
2000 (wl-folder-set-entity-info (cdar alist) nil hashtb)
2001 (setq alist (cdr alist)))
2004 (defun wl-folder-update-diff-line (diffs)
2005 (let ((inhibit-read-only t)
2006 (buffer-read-only nil)
2008 cur-unread new-unread
2013 (setq id (get-text-property (point) 'wl-folder-entity-id))
2014 (when (looking-at "^[ ]*\\(.*\\):\\([0-9\\*-]*\\)/\\([0-9\\*-]*\\)/\\([0-9\\*]*\\)")
2015 ;;(looking-at "^[ ]*\\([^\\[].+\\):\\([0-9\\*-]*/[0-9\\*-]*/[0-9\\*]*\\)")
2016 (setq cur-new (string-to-int
2017 (wl-match-buffer 2)))
2018 (setq cur-unread (string-to-int
2019 (wl-match-buffer 3)))
2020 (setq cur-all (string-to-int
2021 (wl-match-buffer 4)))
2022 (delete-region (match-beginning 2)
2024 (goto-char (match-beginning 2))
2025 (insert (format "%s/%s/%s"
2026 (setq new-new (+ cur-new (nth 0 diffs)))
2027 (setq new-unread (+ cur-unread (nth 1 diffs)))
2028 (setq new-all (+ cur-all (nth 2 diffs)))))
2029 (put-text-property (match-beginning 2) (point)
2030 'wl-folder-entity-id id)
2031 (if wl-use-highlight-mouse-line
2032 (put-text-property (match-beginning 2) (point)
2033 'mouse-face 'highlight))
2034 (wl-highlight-folder-group-line (list new-new new-unread new-all))
2035 (setq buffer-read-only t)
2036 (set-buffer-modified-p nil)))))
2038 (defun wl-folder-update-line (nums &optional is-group)
2039 (let ((inhibit-read-only t)
2040 (buffer-read-only nil)
2044 (setq id (get-text-property (point) 'wl-folder-entity-id))
2045 (if (looking-at "^[ ]*\\(.*\\):\\([0-9\\*-]*/[0-9\\*-]*/[0-9\\*]*\\)")
2046 ;;(looking-at "^[ ]*\\([^\\[].+\\):\\([0-9\\*-]*/[0-9\\*-]*/[0-9\\*]*\\)")
2048 (delete-region (match-beginning 2)
2050 (goto-char (match-beginning 2))
2051 (insert (format "%s/%s/%s"
2052 (or (nth 0 nums) "*")
2053 (or (and (nth 0 nums)(nth 1 nums)
2054 (+ (nth 0 nums)(nth 1 nums)))
2056 (or (nth 2 nums) "*")))
2057 (put-text-property (match-beginning 2) (point)
2058 'wl-folder-entity-id id)
2060 ;; update only colors
2061 (wl-highlight-folder-group-line nums)
2062 (wl-highlight-folder-current-line nums))
2063 (set-buffer-modified-p nil))))))
2065 (defun wl-folder-goto-folder (&optional arg)
2067 (wl-folder-goto-folder-subr nil arg))
2069 (defun wl-folder-goto-folder-subr (&optional folder sticky)
2071 (let (summary-buf fld-name entity id error-selecting)
2072 ;; (setq fld-name (wl-folder-get-entity-from-buffer))
2073 ;; (if (or (null fld-name)
2074 ;; (assoc fld-name wl-folder-group-alist))
2075 (setq fld-name wl-default-folder)
2076 (setq fld-name (or folder
2077 (wl-summary-read-folder fld-name)))
2078 (if (and (setq entity
2079 (wl-folder-search-entity-by-name fld-name
2082 (setq id (wl-folder-get-entity-id entity)))
2083 (wl-folder-set-current-entity-id id))
2084 (setq summary-buf (wl-summary-get-buffer-create fld-name sticky))
2085 (if wl-stay-folder-window
2086 (wl-folder-select-buffer summary-buf)
2087 (if (and summary-buf
2088 (get-buffer-window summary-buf))
2090 (wl-summary-goto-folder-subr fld-name
2091 (wl-summary-get-sync-range fld-name)
2094 (defun wl-folder-suspend ()
2096 (run-hooks 'wl-folder-suspend-hook)
2097 (wl-folder-info-save)
2098 (wl-crosspost-alist-save)
2100 (format "^\\(%s\\)$"
2101 (mapconcat 'identity
2102 (list (format "%s\\(:.*\\)?"
2103 (default-value 'wl-message-buf-name))
2104 wl-original-buf-name)
2106 (if (fboundp 'mmelmo-cleanup-entity-buffers)
2107 (mmelmo-cleanup-entity-buffers))
2108 (bury-buffer wl-folder-buffer-name)
2109 (delete-windows-on wl-folder-buffer-name t))
2111 (defun wl-folder-info-save ()
2112 (when (and wl-folder-info-save
2113 wl-folder-info-alist-modified)
2114 (let ((entities (list wl-folder-entity))
2115 entity entity-stack info-alist info)
2117 (setq entity (wl-pop entities))
2121 (wl-push entities entity-stack))
2122 (setq entities (nth 2 entity)))
2124 (when (and (setq info (elmo-folder-get-info entity))
2125 (not (equal info '(nil))))
2126 (wl-append info-alist (list (list (elmo-string entity)
2127 (list (nth 3 info) ;; max
2128 (nth 2 info) ;; length
2130 (nth 1 info)) ;; unread
2133 (setq entities (wl-pop entity-stack))))
2134 (elmo-msgdb-finfo-save info-alist)
2135 (setq wl-folder-info-alist-modified nil))))
2137 (defun wl-folder-goto-first-unread-folder (&optional arg)
2139 (let ((entities (list wl-folder-entity))
2140 entity entity-stack ret-val
2145 (setq entity (wl-pop entities))
2149 (wl-push entities entity-stack))
2150 (setq entities (nth 2 entity)))
2152 (if (and (setq finfo (wl-folder-get-entity-info entity))
2153 (and (nth 0 finfo)(nth 1 finfo))
2154 (> (+ (nth 0 finfo)(nth 1 finfo)) 0))
2155 (throw 'done entity))
2156 (wl-append ret-val (list entity))))
2158 (setq entities (wl-pop entity-stack))))))
2162 (wl-folder-jump-folder first-entity)
2164 (wl-folder-goto-folder-subr first-entity))
2165 (message "No unread folder"))))
2167 (defun wl-folder-jump-folder (&optional fld-name noopen)
2170 (setq fld-name (wl-summary-read-folder wl-default-folder)))
2171 (goto-char (point-min))
2173 (wl-folder-open-folder fld-name))
2174 (and (wl-folder-buffer-search-entity fld-name)
2175 (beginning-of-line)))
2177 (defun wl-folder-get-entity-list (entity)
2178 (let ((entities (list entity))
2179 entity-stack ret-val)
2181 (setq entity (wl-pop entities))
2185 (wl-push entities entity-stack))
2186 (setq entities (nth 2 entity)))
2188 (wl-append ret-val (list entity))))
2190 (setq entities (wl-pop entity-stack))))
2193 (defun wl-folder-open-unread-folder (entity)
2195 (let ((alist (wl-folder-get-entity-list entity))
2197 finfo path-list path id)
2199 (when (and (setq finfo (wl-folder-get-entity-info (car alist)))
2200 (nth 0 finfo) (nth 1 finfo)
2201 (> (+ (nth 0 finfo)(nth 1 finfo)) 0))
2202 (setq unread (+ unread (+ (nth 0 finfo)(nth 1 finfo))))
2203 (setq id (wl-folder-get-entity-id (car alist)))
2204 (setq path (delete id (wl-folder-get-path
2208 (if (not (member path path-list))
2209 (wl-append path-list (list path))))
2210 (setq alist (cdr alist)))
2212 (wl-folder-open-folder-sub (car path-list))
2213 (setq path-list (cdr path-list)))
2214 (message "%s unread folder"
2215 (if (> unread 0) unread "No")))))
2217 (defun wl-folder-open-unread-current-entity ()
2219 (let ((entity-name (wl-folder-get-entity-from-buffer))
2220 (group (wl-folder-buffer-group-p)))
2222 (wl-folder-open-unread-folder
2224 (wl-folder-search-group-entity-by-name entity-name
2228 (defun wl-folder-open-only-unread-folder ()
2231 (wl-folder-prev-entity-skip-invalid t)
2232 (wl-folder-get-entity-from-buffer t))))
2233 (wl-folder-open-all-unread-folder)
2235 (goto-char (point-max))
2236 (while (and (re-search-backward
2237 "^[ ]*\\[[-]\\].+:0/0/[0-9-]+" nil t)
2239 (wl-folder-jump-to-current-entity) ;; close it
2241 (wl-folder-move-path id)
2244 (defun wl-folder-open-all-unread-folder (&optional arg)
2247 (wl-folder-prev-entity-skip-invalid t)
2248 (wl-folder-get-entity-from-buffer t))))
2249 (wl-folder-open-unread-folder wl-folder-entity)
2251 (wl-folder-move-path id)
2252 (goto-char (point-min))
2253 (wl-folder-next-unread t))))
2255 (defun wl-folder-open-folder (&optional fld-name)
2258 (setq fld-name (wl-summary-read-folder wl-default-folder)))
2259 (let* ((id (wl-folder-get-entity-id
2260 (wl-folder-search-entity-by-name fld-name wl-folder-entity
2262 (path (and id (wl-folder-get-path wl-folder-entity id))))
2264 (wl-folder-open-folder-sub path))))
2266 (defun wl-folder-open-folder-sub (path)
2267 (let ((inhibit-read-only t)
2268 (buffer-read-only nil)
2272 (goto-char (point-min))
2274 (wl-folder-buffer-search-group
2275 (wl-folder-get-petname
2276 (if (stringp (car path))
2278 (wl-folder-get-folder-name-by-id
2281 (setq path (cdr path))
2282 (if (and (looking-at wl-folder-group-regexp)
2283 (string= "+" (wl-match-buffer 2)));; closed group
2285 (setq indent (wl-match-buffer 1))
2286 (setq name (wl-folder-get-realname (wl-match-buffer 3)))
2287 (setq entity (wl-folder-search-group-entity-by-name
2291 (setcdr (assoc (car entity) wl-folder-group-alist) t)
2292 (if (eq 'access (cadr entity))
2293 (wl-folder-maybe-load-folder-list entity))
2294 (wl-folder-insert-entity indent entity)
2295 (delete-region (save-excursion (beginning-of-line)
2297 (save-excursion (end-of-line)
2299 (set-buffer-modified-p nil))))
2301 (defun wl-folder-open-all-pre ()
2302 (let ((entities (list wl-folder-entity))
2303 entity entity-stack group-entry)
2305 (setq entity (wl-pop entities))
2308 (unless (or (not (setq group-entry
2309 (assoc (car entity) wl-folder-group-alist)))
2311 (setcdr group-entry t)
2312 (when (eq 'access (cadr entity))
2313 (wl-folder-maybe-load-folder-list entity)))
2315 (wl-push entities entity-stack))
2316 (setq entities (nth 2 entity))))
2318 (setq entities (wl-pop entity-stack))))))
2320 (defun wl-folder-open-all (&optional refresh)
2322 (let* ((inhibit-read-only t)
2323 (buffer-read-only nil)
2324 (len (length wl-folder-group-alist))
2329 (wl-folder-prev-entity-skip-invalid t)
2330 (wl-folder-get-entity-from-buffer t)))
2331 (alist wl-folder-group-alist))
2333 (setcdr (pop alist) t))
2335 (wl-folder-insert-entity " " wl-folder-entity)
2336 (wl-folder-move-path id))
2337 (message "Opening all folders...")
2338 (wl-folder-open-all-pre)
2340 (goto-char (point-min))
2341 (while (re-search-forward
2342 "^\\([ ]*\\)\\[\\([+]\\)\\]\\(.+\\):[-0-9-]+/[0-9-]+/[0-9-]+\n"
2344 (setq indent (wl-match-buffer 1))
2345 (setq name (wl-folder-get-realname (wl-match-buffer 3)))
2346 (setq entity (wl-folder-search-group-entity-by-name
2350 (setcdr (assoc (car entity) wl-folder-group-alist) t)
2352 (wl-folder-insert-entity indent entity)
2353 (delete-region (save-excursion (beginning-of-line)
2355 (save-excursion (end-of-line)
2357 (when (> len elmo-display-progress-threshold)
2359 (if (or (zerop (% i 5)) (= i len))
2360 (elmo-display-progress
2361 'wl-folder-open-all "Opening all folders..."
2362 (/ (* i 100) len)))))
2363 (when (> len elmo-display-progress-threshold)
2364 (elmo-display-progress
2365 'wl-folder-open-all "Opening all folders..." 100))))
2366 (message "Opening all folders...done")
2367 (set-buffer-modified-p nil)))
2369 (defun wl-folder-close-all ()
2371 (let ((inhibit-read-only t)
2372 (buffer-read-only nil)
2373 (alist wl-folder-group-alist)
2375 (wl-folder-prev-entity-skip-invalid t)
2376 (wl-folder-get-entity-from-buffer t))))
2378 (setcdr (car alist) nil)
2379 (setq alist (cdr alist)))
2380 (setcdr (assoc (car wl-folder-entity) wl-folder-group-alist) t)
2382 (wl-folder-insert-entity " " wl-folder-entity)
2383 (wl-folder-move-path id)
2385 (set-buffer-modified-p nil)))
2387 (defun wl-folder-open-close ()
2388 "open or close parent entity."
2392 (if (wl-folder-buffer-group-p)
2393 ;; if group (whether opend or closed.)
2394 (wl-folder-jump-to-current-entity)
2397 (setq indent (save-excursion
2398 (re-search-forward "\\([ ]*\\)." nil t)
2399 (wl-match-buffer 1)))
2400 (while (looking-at indent)
2402 (wl-folder-jump-to-current-entity))))
2404 (defsubst wl-folder-access-subscribe-p (group folder)
2405 (let (subscr regexp match)
2406 (if (setq subscr (wl-get-assoc-list-value
2407 wl-folder-access-subscribe-alist
2410 (setq regexp (mapconcat 'identity (cdr subscr) "\\|"))
2411 (setq match (string-match regexp folder))
2417 (defun wl-folder-update-access-group (entity new-flist)
2418 (let* ((flist (nth 2 entity))
2419 (unsubscribes (nth 3 entity))
2420 (len (+ (length flist) (length unsubscribes)))
2422 diff new-unsubscribes removes
2423 subscribed-list folder group entry)
2424 ;; check subscribed groups
2427 ((listp (car flist)) ;; group
2428 (setq group (elmo-string (caar flist)))
2430 ((assoc group new-flist) ;; found in new-flist
2431 (setq new-flist (delete (assoc group new-flist)
2433 (if (wl-folder-access-subscribe-p (car entity) group)
2434 (wl-append subscribed-list (list (car flist)))
2435 (wl-append new-unsubscribes (list (car flist)))
2438 (setq wl-folder-group-alist
2439 (delete (wl-string-assoc group wl-folder-group-alist)
2440 wl-folder-group-alist))
2441 (wl-append removes (list (list group))))))
2443 (setq folder (elmo-string (car flist)))
2445 ((member folder new-flist) ;; found in new-flist
2446 (setq new-flist (delete folder new-flist))
2447 (if (wl-folder-access-subscribe-p (car entity) folder)
2448 (wl-append subscribed-list (list (car flist)))
2449 (wl-append new-unsubscribes (list folder))
2452 (wl-append removes (list folder))))))
2453 (when (> len elmo-display-progress-threshold)
2455 (if (or (zerop (% i 10)) (= i len))
2456 (elmo-display-progress
2457 'wl-folder-update-access-group "Updating access group..."
2458 (/ (* i 100) len))))
2459 (setq flist (cdr flist)))
2460 ;; check unsubscribed groups
2463 ((listp (car unsubscribes))
2464 (when (setq entry (assoc (caar unsubscribes) new-flist))
2465 (setq new-flist (delete entry new-flist))
2466 (wl-append new-unsubscribes (list (car unsubscribes)))))
2468 (when (member (car unsubscribes) new-flist)
2469 (setq new-flist (delete (car unsubscribes) new-flist))
2470 (wl-append new-unsubscribes (list (car unsubscribes))))))
2471 (when (> len elmo-display-progress-threshold)
2473 (if (or (zerop (% i 10)) (= i len))
2474 (elmo-display-progress
2475 'wl-folder-update-access-group "Updating access group..."
2476 (/ (* i 100) len))))
2477 (setq unsubscribes (cdr unsubscribes)))
2479 (if (or new-flist removes)
2482 (mapcar '(lambda (x)
2483 (cond ((consp x) (list (car x) 'access))
2487 (let ((new-list new-flist))
2489 (if (not (wl-folder-access-subscribe-p
2491 (if (listp (car new-list))
2496 (wl-append new-unsubscribes (list (car new-list)))
2497 (setq new-flist (delete (car new-list) new-flist)))
2499 ((listp (car new-list))
2500 ;; check group exists
2501 (if (wl-string-assoc (caar new-list) wl-folder-group-alist)
2503 (message "%s: group already exists." (caar new-list))
2505 (wl-append new-unsubscribes (list (car new-list)))
2506 (setq new-flist (delete (car new-list) new-flist)))
2507 (wl-append wl-folder-group-alist
2508 (list (cons (caar new-list) nil)))))))
2509 (setq new-list (cdr new-list))))
2511 (message "%d new folder(s)." (length new-flist))
2512 (message "Updating access group...done"))
2513 (wl-append new-flist subscribed-list) ;; new is first
2514 (run-hooks 'wl-folder-update-access-group-hook)
2515 (setcdr (cdr entity) (list new-flist new-unsubscribes))
2516 (list diff new-flist new-unsubscribes removes)))
2518 (defun wl-folder-prefetch-entity (entity)
2519 "Prefetch all new messages in the ENTITY"
2522 (let ((flist (nth 2 entity))
2527 (setq result (wl-folder-prefetch-entity (car flist)))
2528 (setq sum-done (+ sum-done (car result)))
2529 (setq sum-all (+ sum-all (cdr result)))
2530 (setq flist (cdr flist)))
2531 (message "Prefetched %d/%d message(s) in \"%s\"."
2533 (wl-folder-get-petname (car entity)))
2534 (cons sum-done sum-all)))
2536 (let ((nums (wl-folder-get-entity-info entity))
2537 (wl-summary-highlight (if (or (wl-summary-sticky-p entity)
2538 (wl-summary-always-sticky-folder-p
2540 wl-summary-highlight))
2541 wl-summary-exit-next-move
2542 wl-auto-select-first ret-val
2544 (setq count (or (car nums) 0))
2545 (setq count (+ count (wl-folder-count-incorporates entity)))
2546 (if (or (null (car nums)) ; unknown
2548 (save-window-excursion
2550 (wl-summary-goto-folder-subr entity
2551 (wl-summary-get-sync-range entity)
2553 (setq ret-val (wl-summary-incorporate))
2558 (defun wl-folder-count-incorporates (folder)
2559 (let ((marks (elmo-msgdb-mark-load (elmo-msgdb-expand-path folder)))
2562 (if (member (cadr (car marks))
2563 wl-summary-incorporate-marks)
2565 (setq marks (cdr marks)))
2568 (defun wl-folder-prefetch-current-entity (&optional no-check)
2569 "Prefetch all uncached messages in the folder at position.
2570 If current line is group folder, all subfolders are prefetched."
2573 (let ((entity-name (wl-folder-get-entity-from-buffer))
2574 (group (wl-folder-buffer-group-p))
2575 wl-folder-check-entity-hook
2580 (wl-folder-search-group-entity-by-name entity-name
2584 (wl-folder-check-entity entity))
2585 (wl-folder-prefetch-entity entity)))))
2587 (defun wl-folder-drop-unsync-entity (entity)
2588 "Drop all unsync messages in the ENTITY"
2591 (let ((flist (nth 2 entity)))
2593 (wl-folder-drop-unsync-entity (car flist))
2594 (setq flist (cdr flist)))))
2596 (let ((nums (wl-folder-get-entity-info entity))
2597 wl-summary-highlight wl-auto-select-first new)
2598 (setq new (or (car nums) 0))
2600 (save-window-excursion
2602 (wl-summary-goto-folder-subr entity 'no-sync nil)
2603 (wl-summary-drop-unsync)
2604 (wl-summary-exit))))))))
2606 (defun wl-folder-drop-unsync-current-entity (&optional force-check)
2607 "Drop all unsync messages in the folder at position.
2608 If current line is group folder, all subfolders are dropped.
2609 If optional arg exists, don't check any folders."
2612 (let ((entity-name (wl-folder-get-entity-from-buffer))
2613 (group (wl-folder-buffer-group-p))
2614 wl-folder-check-entity-hook
2616 (when (and entity-name
2618 "Drop all unsync messages in %s?" entity-name)))
2621 (wl-folder-search-group-entity-by-name entity-name
2624 (if (null force-check)
2625 (wl-folder-check-entity entity))
2626 (wl-folder-drop-unsync-entity entity)
2627 (message "All unsync messages in %s are dropped!" entity-name)))))
2629 (defun wl-folder-write-current-newsgroup ()
2631 (wl-summary-write-current-newsgroup (wl-folder-entity-name)))
2633 (defun wl-folder-mimic-kill-buffer ()
2634 "Kill the current (Folder) buffer with query."
2636 (let ((bufname (read-buffer (format "Kill buffer: (default %s) "
2638 wl-interactive-exit)
2639 (if (or (not bufname)
2640 (string-equal bufname "")
2641 (string-equal bufname (buffer-name)))
2643 (kill-buffer bufname))))
2645 (defun wl-folder-create-subr (entity)
2646 (if (not (elmo-folder-creatable-p entity))
2647 (error "Folder %s is not found" entity)
2649 (format "Folder %s does not exist, create it?"
2652 (setq wl-folder-entity-hashtb
2653 (wl-folder-create-entity-hashtb
2654 entity wl-folder-entity-hashtb))
2655 (unless (elmo-create-folder entity)
2656 (error "Create folder failed")))
2657 (error "Folder %s is not created" entity))))
2659 (defun wl-folder-confirm-existence (folder &optional force)
2661 (unless (elmo-folder-exists-p folder)
2662 (wl-folder-create-subr folder))
2663 (unless (or (wl-folder-entity-exists-p folder)
2664 (file-exists-p (elmo-msgdb-expand-path folder))
2665 (elmo-folder-exists-p folder))
2666 (wl-folder-create-subr folder))))
2669 (product-provide (provide 'wl-folder) (require 'wl-version))
2671 ;;; wl-folder.el ends here