1 ;;; wl-folder.el -- Folder mode for Wanderlust.
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>
6 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
7 ;; Masahiro MURATA <muse@ba2.so-net.ne.jp>
8 ;; Keywords: mail, net news
10 ;; This file is part of Wanderlust (Yet Another Message Interface on Emacsen).
12 ;; This program is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
17 ;; This program is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 ;; Boston, MA 02111-1307, USA.
39 (require 'easymenu) ; needed here.
50 (unless (boundp ':file)
51 (set (make-local-variable ':file) nil))
52 (defun-maybe mmelmo-cleanup-entity-buffers ()))
54 (defvar wl-folder-buffer-name "Folder")
55 (defvar wl-folder-entity nil) ; desktop entity.
56 (defvar wl-folder-group-alist nil) ; opened or closed
57 (defvar wl-folder-entity-id nil) ; id
58 (defvar wl-folder-entity-hashtb nil)
59 (defvar wl-folder-entity-id-name-hashtb nil)
60 (defvar wl-folder-newsgroups-hashtb nil)
61 (defvar wl-folder-info-alist-modified nil)
62 (defvar wl-folder-completion-func nil)
64 (defvar wl-folder-mode-map nil)
66 (defvar wl-folder-buffer-disp-summary nil)
67 (defvar wl-folder-buffer-cur-entity-id nil)
68 (defvar wl-folder-buffer-cur-path nil)
69 (defvar wl-folder-buffer-cur-point nil)
71 (make-variable-buffer-local 'wl-folder-buffer-disp-summary)
72 (make-variable-buffer-local 'wl-folder-buffer-cur-entity-id)
73 (make-variable-buffer-local 'wl-folder-buffer-cur-path)
74 (make-variable-buffer-local 'wl-folder-buffer-cur-point)
76 (defconst wl-folder-entity-regexp "^\\([ ]*\\)\\(\\[[\\+-]\\]\\)?\\([^\\[].+\\):[-*0-9]+/[-*0-9]+/[-*0-9]+")
77 (defconst wl-folder-group-regexp "^\\([ ]*\\)\\[\\([\\+-]\\)\\]\\(.+\\):[-0-9-]+/[0-9-]+/[0-9-]+\n")
78 ;; 1:indent 2:opened 3:group-name
79 (defconst wl-folder-unsync-regexp ":[^0\\*][0-9]*/[0-9\\*-]+/[0-9\\*-]+$")
81 (defvar wl-folder-mode-menu-spec
83 ["Enter Current Folder" wl-folder-jump-to-current-entity t]
84 ["Prev Folder" wl-folder-prev-entity t]
85 ["Next Folder" wl-folder-next-entity t]
86 ["Check Current Folder" wl-folder-check-current-entity t]
87 ["Sync Current Folder" wl-folder-sync-current-entity t]
88 ["Drop Current Folder" wl-folder-drop-unsync-current-entity t]
89 ["Prefetch Current Folder" wl-folder-prefetch-current-entity t]
90 ["Mark as Read all Current Folder" wl-folder-mark-as-read-all-current-entity t]
91 ["Expire Current Folder" wl-folder-expire-current-entity t]
92 ["Empty trash" wl-folder-empty-trash t]
93 ["Flush queue" wl-folder-flush-queue t]
94 ["Open All" wl-folder-open-all t]
95 ["Open All Unread folder" wl-folder-open-all-unread-folder t]
96 ["Close All" wl-folder-close-all t]
98 ["Add folder" wl-fldmgr-add t]
99 ["Add group" wl-fldmgr-make-group t]
100 ["Copy" wl-fldmgr-copy t]
101 ["Cut" wl-fldmgr-cut t]
102 ["Paste" wl-fldmgr-yank t]
103 ["Set petname" wl-fldmgr-set-petname t]
104 ["Rename" wl-fldmgr-rename t]
105 ["Save" wl-fldmgr-save-folders t]
107 ["Unsubscribe" wl-fldmgr-unsubscribe t]
108 ["Display all" wl-fldmgr-access-display-all t])
110 ["Write a message" wl-draft t]
112 ["Toggle Plug Status" wl-toggle-plugged t]
113 ["Change Plug Status" wl-plugged-change t]
115 ["Save Current Status" wl-save t]
116 ["Update Satus" wl-status-update t]
121 (defun wl-folder-setup-mouse ()
122 (define-key wl-folder-mode-map 'button2 'wl-folder-click)
123 (define-key wl-folder-mode-map 'button4 'wl-folder-prev-entity)
124 (define-key wl-folder-mode-map 'button5 'wl-folder-next-entity)
125 (define-key wl-folder-mode-map [(shift button4)]
126 'wl-folder-prev-unread)
127 (define-key wl-folder-mode-map [(shift button5)]
128 'wl-folder-next-unread))
130 (defun wl-folder-setup-mouse ())
131 (defun wl-folder-setup-mouse ()
132 (define-key wl-folder-mode-map [mouse-2] 'wl-folder-click)
133 (define-key wl-folder-mode-map [mouse-4] 'wl-folder-prev-entity)
134 (define-key wl-folder-mode-map [mouse-5] 'wl-folder-next-entity)
135 (define-key wl-folder-mode-map [S-mouse-4] 'wl-folder-prev-unread)
136 (define-key wl-folder-mode-map [S-mouse-5] 'wl-folder-next-unread))))
138 (if wl-folder-mode-map
140 (setq wl-folder-mode-map (make-sparse-keymap))
141 (define-key wl-folder-mode-map " " 'wl-folder-jump-to-current-entity)
142 ; (define-key wl-folder-mode-map "\M- " 'wl-folder-open-close)
143 (define-key wl-folder-mode-map "/" 'wl-folder-open-close)
144 (define-key wl-folder-mode-map "\C-m" 'wl-folder-jump-to-current-entity)
145 (define-key wl-folder-mode-map "\M-\C-m" 'wl-folder-update-recursive-current-entity)
146 (define-key wl-folder-mode-map "rc" 'wl-folder-mark-as-read-all-region)
147 (define-key wl-folder-mode-map "c" 'wl-folder-mark-as-read-all-current-entity)
148 (define-key wl-folder-mode-map "g" 'wl-folder-goto-folder)
149 (define-key wl-folder-mode-map "j" 'wl-folder-jump-to-current-entity)
150 (define-key wl-folder-mode-map "w" 'wl-draft)
151 (define-key wl-folder-mode-map "W" 'wl-folder-write-current-folder)
152 (define-key wl-folder-mode-map "\C-c\C-o" 'wl-jump-to-draft-buffer)
153 (define-key wl-folder-mode-map "rS" 'wl-folder-sync-region)
154 (define-key wl-folder-mode-map "S" 'wl-folder-sync-current-entity)
155 (define-key wl-folder-mode-map "rs" 'wl-folder-check-region)
156 (define-key wl-folder-mode-map "s" 'wl-folder-check-current-entity)
157 (define-key wl-folder-mode-map "I" 'wl-folder-prefetch-current-entity)
158 (define-key wl-folder-mode-map "D" 'wl-folder-drop-unsync-current-entity)
159 (define-key wl-folder-mode-map "p" 'wl-folder-prev-entity)
160 (define-key wl-folder-mode-map "n" 'wl-folder-next-entity)
161 (define-key wl-folder-mode-map "v" 'wl-folder-toggle-disp-summary)
162 (define-key wl-folder-mode-map "P" 'wl-folder-prev-unread)
163 (define-key wl-folder-mode-map "N" 'wl-folder-next-unread)
164 (define-key wl-folder-mode-map "J" 'wl-folder-jump-folder)
165 (define-key wl-folder-mode-map "f" 'wl-folder-goto-first-unread-folder)
166 (define-key wl-folder-mode-map "o" 'wl-folder-open-all-unread-folder)
167 (define-key wl-folder-mode-map "[" 'wl-folder-open-all)
168 (define-key wl-folder-mode-map "]" 'wl-folder-close-all)
169 (define-key wl-folder-mode-map "e" 'wl-folder-expire-current-entity)
170 (define-key wl-folder-mode-map "E" 'wl-folder-empty-trash)
171 (define-key wl-folder-mode-map "F" 'wl-folder-flush-queue)
172 (define-key wl-folder-mode-map "q" 'wl-exit)
173 (define-key wl-folder-mode-map "z" 'wl-folder-suspend)
174 (define-key wl-folder-mode-map "\M-t" 'wl-toggle-plugged)
175 (define-key wl-folder-mode-map "\C-t" 'wl-plugged-change)
176 (define-key wl-folder-mode-map "<" 'beginning-of-buffer)
177 (define-key wl-folder-mode-map ">" 'end-of-buffer)
180 (define-key wl-folder-mode-map "m" 'wl-fldmgr-mode-map))
181 (define-key wl-folder-mode-map "*" 'wl-fldmgr-make-multi)
182 (define-key wl-folder-mode-map "+" 'wl-fldmgr-make-group)
183 (define-key wl-folder-mode-map "|" 'wl-fldmgr-make-filter)
184 (define-key wl-folder-mode-map "\M-c" 'wl-fldmgr-copy)
185 (define-key wl-folder-mode-map "\M-w" 'wl-fldmgr-copy-region)
186 (define-key wl-folder-mode-map "\C-k" 'wl-fldmgr-cut)
187 (define-key wl-folder-mode-map "\C-w" 'wl-fldmgr-cut-region)
188 (define-key wl-folder-mode-map "\C-y" 'wl-fldmgr-yank)
189 (define-key wl-folder-mode-map "R" 'wl-fldmgr-rename)
190 (define-key wl-folder-mode-map "u" 'wl-fldmgr-unsubscribe)
191 (define-key wl-folder-mode-map "ru" 'wl-fldmgr-unsubscribe-region)
192 (define-key wl-folder-mode-map "U" 'wl-fldmgr-unsubscribe-region)
193 (define-key wl-folder-mode-map "l" 'wl-fldmgr-access-display-normal)
194 (define-key wl-folder-mode-map "L" 'wl-fldmgr-access-display-all)
195 (define-key wl-folder-mode-map "Z" 'wl-status-update)
196 (define-key wl-folder-mode-map "\C-x\C-s" 'wl-save)
197 (define-key wl-folder-mode-map "\M-s" 'wl-save)
198 (define-key wl-folder-mode-map "\C-xk" 'wl-folder-mimic-kill-buffer)
199 (define-key wl-folder-mode-map "\M-\C-a"
200 'wl-folder-goto-top-of-current-folder)
201 (define-key wl-folder-mode-map "\M-\C-e"
202 'wl-folder-goto-bottom-of-current-folder)
204 (wl-folder-setup-mouse)
208 "Menu used in Folder mode."
209 wl-folder-mode-menu-spec))
211 (defmacro wl-folder-unread-regex (group)
212 (` (concat "^[ ]*.+:[0-9\\*-]+/[^0\\*][0-9]*/[0-9\\*-]+$"
217 (defmacro wl-folder-buffer-group-p ()
218 (` (save-excursion (beginning-of-line)
219 (looking-at wl-folder-group-regexp))))
221 (defmacro wl-folder-folder-name ()
224 (if (or (looking-at "^[ ]*\\[[\\+-]\\]\\(.+\\):[-0-9\\*-]+/[0-9\\*-]+/[0-9\\*-]+\n")
225 (looking-at "^[ ]*\\([^\\[].+\\):.*\n"))
226 (wl-match-buffer 1)))))
228 (defmacro wl-folder-entity-name ()
231 (if (looking-at "^[ ]*\\([^\\[].+\\):.*\n")
232 (wl-match-buffer 1)))))
234 (defun wl-folder-buffer-search-group (group)
237 "^\\([ \t]*\\)\\[[\\+-]\\]"
238 (regexp-quote group) ":[-0-9-]+/[0-9-]+/[0-9-]+") nil t))
240 (defun wl-folder-buffer-search-entity (folder &optional searchname)
241 (let ((search (or searchname (wl-folder-get-petname folder))))
245 (regexp-quote search) ":[-0-9\\*-]+/[0-9\\*-]+/[0-9\\*-]+") nil t)))
247 (defsubst wl-folder-get-folder-name-by-id (entity-id &optional hashtb)
248 (and (numberp entity-id)
249 (elmo-get-hash-val (format "#%d" entity-id)
250 (or hashtb wl-folder-entity-id-name-hashtb))))
252 (defsubst wl-folder-set-id-name (entity-id entity &optional hashtb)
253 (and (numberp entity-id)
254 (elmo-set-hash-val (format "#%d" entity-id)
255 entity (or hashtb wl-folder-entity-id-name-hashtb))))
257 (defmacro wl-folder-get-entity-id (entity)
258 (` (or (get-text-property 0
261 (, entity)))) ;; for nemacs
263 (defmacro wl-folder-get-entity-from-buffer (&optional getid)
264 (` (let ((id (get-text-property (point)
265 'wl-folder-entity-id)))
266 (if (not id) ;; for nemacs
267 (wl-folder-get-realname (wl-folder-folder-name))
270 (wl-folder-get-folder-name-by-id id))))))
272 (defmacro wl-folder-entity-exists-p (entity &optional hashtb)
273 (` (let ((sym (intern-soft (, entity)
274 (or (, hashtb) wl-folder-entity-hashtb))))
275 (and sym (boundp sym)))))
277 (defmacro wl-folder-clear-entity-info (entity &optional hashtb)
278 (` (let ((sym (intern-soft (, entity)
279 (or (, hashtb) wl-folder-entity-hashtb))))
283 (defmacro wl-folder-get-entity-info (entity &optional hashtb)
284 (` (elmo-get-hash-val (, entity) (or (, hashtb) wl-folder-entity-hashtb))))
286 (defmacro wl-folder-set-entity-info (entity value &optional hashtb)
287 (` (let* ((hashtb (or (, hashtb) wl-folder-entity-hashtb))
288 (info (wl-folder-get-entity-info (, entity) hashtb)))
289 (elmo-set-hash-val (, entity)
290 (if (< (length (, value)) 4)
291 (append (, value) (list (nth 3 info)))
295 (defun wl-folder-persistent-p (folder)
296 (or (elmo-get-hash-val folder wl-folder-entity-hashtb) ; on Folder mode.
298 (let ((li wl-save-folder-list))
300 (if (string-match (car li) folder)
302 (setq li (cdr li)))))
304 (let ((li wl-no-save-folder-list))
306 (if (string-match (car li) folder)
308 (setq li (cdr li))))))))
310 (defun wl-folder-prev-entity ()
314 (defun wl-folder-next-entity ()
318 (defun wl-folder-prev-entity-skip-invalid (&optional hereto)
319 "move to previous entity. skip unsubscribed or removed entity."
323 (if (re-search-backward wl-folder-entity-regexp nil t)
325 (goto-char (point-min))))
327 (defun wl-folder-next-entity-skip-invalid (&optional hereto)
328 "Move to next entity. skip unsubscribed or removed entity."
333 (if (re-search-forward wl-folder-entity-regexp nil t)
335 (goto-char (point-max))))
337 (defun wl-folder-search-group-entity-by-name (name entity)
338 (wl-folder-search-entity-by-name name entity 'group))
340 (defun wl-folder-search-entity-by-name (name entity &optional type)
341 (let ((entities (list entity))
345 (setq entity (wl-pop entities))
348 (if (and (not (eq type 'folder))
349 (string= name (car entity)))
350 (throw 'done entity))
352 (wl-push entities entity-stack))
353 (setq entities (nth 2 entity)))
354 ((and (not (eq type 'group))
356 (if (string= name entity)
357 (throw 'done entity))))
359 (setq entities (wl-pop entity-stack)))))))
361 (defun wl-folder-search-entity-list-by-name (name entity &optional get-id)
362 (let ((entities (list entity))
363 entity-stack ret-val)
365 (setq entity (wl-pop entities))
369 (wl-push entities entity-stack))
370 (setq entities (nth 2 entity)))
372 (if (string= name entity)
373 (wl-append ret-val (if get-id
374 (list (wl-folder-get-entity-id entity))
377 (setq entities (wl-pop entity-stack))))
380 (defun wl-folder-get-prev-folder (id &optional unread)
381 (let ((name (if (stringp id)
383 (wl-folder-get-folder-name-by-id id)))
384 entity entity-stack last-entity finfo
385 (entities (list wl-folder-entity)))
388 (setq entity (wl-pop entities))
391 ;; (if (and (string= name (car entity))
392 ;; (eq id (wl-folder-get-entity-id (car entity))))
393 ;; (throw 'done last-entity))
395 (wl-push entities entity-stack))
396 (setq entities (nth 2 entity)))
398 (if (and (string= name entity)
399 ;; don't use eq, `id' is string on Nemacs.
400 (equal id (wl-folder-get-entity-id entity)))
401 (throw 'done last-entity))
403 (and (setq finfo (wl-folder-get-entity-info entity))
404 (and (nth 0 finfo)(nth 1 finfo))
405 (> (+ (nth 0 finfo)(nth 1 finfo)) 0)))
406 (setq last-entity entity))))
408 (setq entities (wl-pop entity-stack)))))))
410 (defun wl-folder-get-next-folder (id &optional unread)
411 (let ((name (if (stringp id)
413 (wl-folder-get-folder-name-by-id id)))
414 entity entity-stack found finfo
415 (entities (list wl-folder-entity)))
418 (setq entity (wl-pop entities))
421 ;;; (if (and (string= name (car entity))
422 ;;; (eq id (wl-folder-get-entity-id (car entity))))
425 (wl-push entities entity-stack))
426 (setq entities (nth 2 entity)))
429 (when (or (not unread)
430 (and (setq finfo (wl-folder-get-entity-info entity))
431 (and (nth 0 finfo)(nth 1 finfo))
432 (> (+ (nth 0 finfo)(nth 1 finfo)) 0)))
433 (throw 'done entity))
434 (if (and (string= name entity)
435 ;; don't use eq, `id' is string on Nemacs.
436 (equal id (wl-folder-get-entity-id entity)))
439 (setq entities (wl-pop entity-stack)))))))
441 (defun wl-folder-flush-queue ()
444 (let ((cur-buf (current-buffer))
445 (wl-auto-select-first nil)
448 (if elmo-enable-disconnected-operation
449 (elmo-dop-queue-flush 'force)) ; Try flushing all queue.
450 (if (not (elmo-list-folder wl-queue-folder))
451 (message "No sending queue exists.")
452 (if wl-stay-folder-window
453 (wl-folder-select-buffer
454 (wl-summary-get-buffer-create wl-queue-folder)))
455 (wl-summary-goto-folder-subr wl-queue-folder 'force-update nil)
457 (wl-draft-queue-flush)
458 (if (get-buffer-window cur-buf)
459 (select-window (get-buffer-window cur-buf)))
461 (if wl-stay-folder-window
462 (wl-folder-toggle-disp-summary 'off wl-queue-folder)
463 (switch-to-buffer cur-buf))))))
465 (defun wl-folder-empty-trash ()
468 (let ((cur-buf (current-buffer))
469 (wl-auto-select-first nil)
471 (if wl-stay-folder-window
472 (wl-folder-select-buffer
473 (wl-summary-get-buffer-create wl-trash-folder)))
474 (wl-summary-goto-folder-subr wl-trash-folder 'force-update nil nil t)
475 (setq trash-buf (current-buffer))
477 (setq emptied (wl-summary-delete-all-msgs))
479 (setq wl-thread-entities nil
480 wl-thread-entity-list nil)
481 (if wl-summary-cache-use (wl-summary-save-view-cache))
482 (wl-summary-msgdb-save))
483 (if (get-buffer-window cur-buf)
484 (select-window (get-buffer-window cur-buf)))
487 (wl-folder-set-folder-updated wl-trash-folder '(0 0 0)))
488 (if wl-stay-folder-window
489 (wl-folder-toggle-disp-summary 'off wl-trash-folder)
490 (switch-to-buffer cur-buf))
492 (kill-buffer trash-buf)))))
494 (defun wl-folder-goto-top-of-current-folder (&optional arg)
495 "Move backward to the top of the current folder group.
496 Optional argument ARG is repeart count."
498 (if (re-search-backward
499 "^ *\\[[\\+-]\\]" nil t (if arg (prefix-numeric-value arg)))
501 (goto-char (point-min))))
503 (defun wl-folder-goto-bottom-of-current-folder (indent)
504 "Move forward to the bottom of the current folder group."
509 (if (looking-at "^ *")
510 (buffer-substring (match-beginning 0)(1- (match-end 0)))
514 (while (re-search-forward "^ *" nil t)
515 (if (<= (length (match-string 0))
519 (goto-char (point-max))))
521 (defsubst wl-folder-update-group (entity diffs &optional is-group)
522 (let ((path (wl-folder-get-path
524 (wl-folder-get-entity-id entity)
527 ;; delete itself from path
528 (setq path (delete (nth (- (length path) 1) path) path)))
529 (goto-char (point-min))
532 ;; goto the path line.
533 (if (or (eq (car path) 0) ; update desktop
534 (wl-folder-buffer-search-group
535 (wl-folder-get-petname
536 (if (stringp (car path))
538 (wl-folder-get-folder-name-by-id
541 (wl-folder-update-diff-line diffs)
543 (setq path (cdr path))))))
545 (defun wl-folder-maybe-load-folder-list (entity)
546 (when (null (caddr entity))
548 (elmo-msgdb-flist-load (car entity)))
552 (wl-folder-entity-assign-id entity
553 wl-folder-entity-id-name-hashtb
555 (setq diffs (wl-fldmgr-add-entity-hashtb (list entity)))
556 (unless (equal diffs '(0 0 0))
557 (wl-folder-update-group (car entity) diffs t)))))))
559 (defsubst wl-folder-force-fetch-p (entity)
561 ((consp wl-force-fetch-folders)
562 (wl-string-match-member entity wl-force-fetch-folders))
564 wl-force-fetch-folders)))
566 (defun wl-folder-jump-to-current-entity (&optional arg)
567 "Enter the current folder. If optional ARG exists, update folder list."
570 (let (entity beg end indent opened fname err fld-name)
572 ((looking-at wl-folder-group-regexp)
574 (setq fname (wl-folder-get-realname (wl-match-buffer 3)))
575 (setq indent (wl-match-buffer 1))
576 (setq opened (wl-match-buffer 2))
577 (if (string= opened "+")
579 (setq entity (wl-folder-search-group-entity-by-name
584 (wl-folder-update-recursive-current-entity entity)
586 (setcdr (assoc (car entity) wl-folder-group-alist) t)
587 (if (eq 'access (cadr entity))
588 (wl-folder-maybe-load-folder-list entity))
589 (condition-case errobj
591 (if (or (wl-folder-force-fetch-p (car entity))
593 (eq 'access (cadr entity))
594 (null (caddr entity))))
595 (wl-folder-update-newest indent entity)
596 (wl-folder-insert-entity indent entity))
597 (wl-highlight-folder-path wl-folder-buffer-cur-path))
600 (setcdr (assoc fname wl-folder-group-alist) nil))
602 (elmo-display-error errobj t)
605 (setcdr (assoc fname wl-folder-group-alist) nil)))
607 (let ((buffer-read-only nil))
608 (delete-region (save-excursion (beginning-of-line)
610 (save-excursion (end-of-line)
616 (progn (wl-folder-goto-bottom-of-current-folder indent)
619 (setq entity (wl-folder-search-group-entity-by-name
622 (let ((buffer-read-only nil))
623 (delete-region beg end))
624 (setcdr (assoc (car entity) wl-folder-group-alist) nil)
625 (wl-folder-insert-entity indent entity) ; insert entity
627 (wl-highlight-folder-path wl-folder-buffer-cur-path)
628 ; (wl-delete-all-overlays)
629 ; (wl-highlight-folder-current-line)
631 ((setq fld-name (wl-folder-entity-name))
634 (wl-folder-set-current-entity-id
635 (wl-folder-get-entity-from-buffer))
636 (setq fld-name (wl-folder-get-realname fld-name)))
637 (wl-folder-set-current-entity-id
638 (get-text-property (point) 'wl-folder-entity-id))
639 (setq fld-name (wl-folder-get-folder-name-by-id
640 wl-folder-buffer-cur-entity-id)))
641 (let ((summary-buf (wl-summary-get-buffer-create fld-name arg))
643 (if (or wl-stay-folder-window wl-summary-use-frame)
644 (wl-folder-select-buffer summary-buf)
646 (get-buffer-window summary-buf))
648 (wl-summary-goto-folder-subr fld-name
649 (wl-summary-get-sync-range fld-name)
651 (set-buffer-modified-p nil))
653 (defun wl-folder-close-entity (entity)
654 (let ((entities (list entity))
657 (setq entity (wl-pop entities))
660 (setcdr (assoc (car entity) wl-folder-group-alist) nil)
662 (wl-push entities entity-stack))
663 (setq entities (nth 2 entity))))
665 (setq entities (wl-pop entity-stack))))))
667 (defun wl-folder-update-recursive-current-entity (&optional entity)
669 (when (wl-folder-buffer-group-p)
671 ((string= (wl-match-buffer 2) "+")
675 (wl-folder-search-group-entity-by-name
676 (wl-folder-get-realname (wl-match-buffer 3))
678 (let ((inhibit-read-only t)
679 (entities (list entity))
680 entity-stack err indent)
681 (while (and entities (not err))
682 (setq entity (wl-pop entities))
685 (wl-folder-close-entity entity)
686 (setcdr (assoc (car entity) wl-folder-group-alist) t)
687 (unless (wl-folder-buffer-search-group
688 (wl-folder-get-petname (car entity)))
689 (error "%s: not found group" (car entity)))
690 (setq indent (wl-match-buffer 1))
691 (if (eq 'access (cadr entity))
692 (wl-folder-maybe-load-folder-list entity))
696 (condition-case errobj
697 (wl-folder-update-newest indent entity)
700 (setcdr (assoc (car entity) wl-folder-group-alist) nil))
702 (elmo-display-error errobj t)
705 (setcdr (assoc (car entity) wl-folder-group-alist) nil)))
707 (delete-region (save-excursion (beginning-of-line)
709 (save-excursion (end-of-line)
713 (wl-push entities entity-stack))
714 (setq entities (nth 2 entity))))
716 (setq entities (wl-pop entity-stack)))))
717 (set-buffer-modified-p nil)))
719 (wl-folder-jump-to-current-entity)))))
721 (defun wl-folder-no-auto-check-folder-p (folder)
724 (let ((li wl-auto-check-folder-list))
726 (if (string-match (car li) folder)
728 (setq li (cdr li)))))
731 (let ((li wl-auto-uncheck-folder-list))
733 (if (string-match (car li) folder)
734 (throw 'found t)) ; no check!
735 (setq li (cdr li))))))))
737 (defsubst wl-folder-add-folder-info (pre-value value)
739 (+ (or (nth 0 pre-value) 0) (or (nth 0 value) 0))
740 (+ (or (nth 1 pre-value) 0) (or (nth 1 value) 0))
741 (+ (or (nth 2 pre-value) 0) (or (nth 2 value) 0))))
743 (defun wl-folder-check-entity (entity &optional auto)
744 "Check unsync message number."
745 (let ((start-pos (point))
747 (run-hooks 'wl-folder-check-entity-pre-hook)
748 (if (and (consp entity) ;; group entity
749 wl-folder-check-async) ;; very fast
750 (setq ret-val (wl-folder-check-entity-async entity auto))
754 (let ((flist (if auto
756 'wl-folder-no-auto-check-folder-p
759 (wl-folder-check-entity-pre-hook nil)
760 (wl-folder-check-entity-hook nil)
764 (wl-folder-add-folder-info
766 (wl-folder-check-entity (car flist))))
767 (setq flist (cdr flist)))
768 ;(wl-folder-buffer-search-entity (car entity))
769 ;(wl-folder-update-line ret-val)
771 ((and (stringp entity)
772 (elmo-folder-plugged-p entity))
773 (message "Checking \"%s\"" entity)
774 (setq ret-val (wl-folder-check-one-entity entity))
775 (goto-char start-pos)
778 (message "Uncheck(unplugged) \"%s\"" entity)))))
780 (message "Checking \"%s\" is done."
781 (if (consp entity) (car entity) entity)))
782 (run-hooks 'wl-folder-check-entity-hook)
785 ;; All contained folders are imap4 and persistent flag, then
787 (defun wl-folder-use-server-diff-p (folder)
788 (let ((spec (elmo-folder-get-spec folder)))
790 ((eq (car spec) 'multi)
791 (let ((folders (cdr spec)))
794 (if (wl-folder-use-server-diff-p (car folders))
796 (setq folders (cdr folders)))
798 ((eq (car spec) 'filter)
799 (wl-folder-use-server-diff-p (nth 2 spec)))
800 ((eq (car spec) 'imap4)
801 (and wl-folder-use-server-diff
802 (elmo-imap4-use-flag-p spec)))
805 (defun wl-folder-check-one-entity (entity)
806 (let* ((elmo-use-server-diff (wl-folder-use-server-diff-p entity))
807 (nums (condition-case err
808 (if (wl-string-match-member entity wl-strict-diff-folders)
809 (elmo-strict-folder-diff entity)
810 (elmo-folder-diff entity))
812 ;; maybe not exist folder.
813 (if (and (not (memq 'elmo-open-error
814 (get (car err) 'error-conditions)))
815 (not (elmo-folder-exists-p entity)))
816 (wl-folder-create-subr entity)
817 (signal (car err) (cdr err))))))
819 (if (and (eq wl-folder-notify-deleted 'sync)
821 (or (> 0 (car nums)) (> 0 (cdr nums))))
823 (wl-folder-sync-entity entity)
824 (setq nums (elmo-folder-diff entity)))
825 (unless wl-folder-notify-deleted
826 (setq unsync (if (and (car nums) (> 0 (car nums))) 0 (car nums)))
827 (setq nomif (if (and (car nums) (> 0 (cdr nums))) 0 (cdr nums)))
828 (setq nums (cons unsync nomif)))
829 (wl-folder-entity-hashtb-set wl-folder-entity-hashtb entity
834 ;; If server diff, All unreads are
835 ;; treated as unsync.
836 (if elmo-use-server-diff 0)
837 (elmo-folder-get-info-unread entity)
838 (wl-summary-count-unread
839 (elmo-msgdb-mark-load
840 (elmo-msgdb-expand-path entity))
843 (get-buffer wl-folder-buffer-name)))
844 (setq wl-folder-info-alist-modified t)
846 (list (if wl-folder-notify-deleted
848 (max (or (car nums) 0))) unread (cdr nums))))
850 (defun wl-folder-check-entity-async (entity &optional auto)
851 (let ((elmo-nntp-groups-async t)
854 'wl-folder-no-auto-check-folder-p
855 (wl-folder-get-entity-list entity))
856 (wl-folder-get-entity-list entity)))
857 (nntp-connection-keys nil)
858 folder spec-list local-elist net-elist server
861 (if (not (elmo-folder-plugged-p (car elist)))
862 (message "Uncheck \"%s\"" (car elist))
864 (elmo-folder-get-primitive-spec-list (elmo-string (car elist))))
865 (cond ((assq 'nntp spec-list)
866 (wl-append net-elist (list (car elist)))
868 (when (eq (caar spec-list) 'nntp)
869 (when (not (string= server (elmo-nntp-spec-hostname (car spec-list))))
870 (setq server (elmo-nntp-spec-hostname (car spec-list)))
871 (message "Checking on \"%s\"" server))
872 (setq nntp-connection-keys
873 (elmo-nntp-get-folders-info-prepare
875 nntp-connection-keys)))
876 (setq spec-list (cdr spec-list))))
878 (wl-append local-elist (list (car elist))))))
879 (setq elist (cdr elist)))
880 ;; check local entity at first
881 (while (setq folder (pop local-elist))
882 (if (not (elmo-folder-plugged-p folder))
883 (message "Uncheck \"%s\"" folder)
884 (message "Checking \"%s\"" folder)
886 (wl-folder-add-folder-info
888 (wl-folder-check-one-entity folder)))
891 ;; check network entity at last
893 (elmo-nntp-get-folders-info nntp-connection-keys)
894 (while (setq folder (pop net-elist))
895 (if (not (elmo-folder-plugged-p folder))
896 (message "Uncheck \"%s\"" folder)
897 (message "Checking \"%s\"" folder)
899 (wl-folder-add-folder-info
901 (wl-folder-check-one-entity folder)))
907 (defun wl-folder-resume-entity-hashtb-by-finfo (entity-hashtb info-alist)
908 "Resume unread info for entity alist."
911 (setq info (nth 1 (car info-alist)))
912 (wl-folder-set-entity-info (caar info-alist)
913 (list (nth 2 info)(nth 3 info)(nth 1 info))
915 (setq info-alist (cdr info-alist)))))
917 (defun wl-folder-move-path (path)
918 (let ((fp (if (consp path)
921 (wl-folder-get-path wl-folder-entity path))))
922 (goto-char (point-min))
925 (when (equal (car fp)
926 (wl-folder-get-entity-from-buffer t))
928 (setq wl-folder-buffer-cur-point (point)))
930 (and wl-folder-buffer-cur-point
931 (goto-char wl-folder-buffer-cur-point))))
933 (defun wl-folder-set-current-entity-id (entity-id)
934 (let ((buf (get-buffer wl-folder-buffer-name)))
938 (setq wl-folder-buffer-cur-entity-id entity-id)
939 (setq wl-folder-buffer-cur-path (wl-folder-get-path wl-folder-entity
941 (wl-highlight-folder-path wl-folder-buffer-cur-path)
942 (and wl-folder-move-cur-folder
943 wl-folder-buffer-cur-point
944 (goto-char wl-folder-buffer-cur-point))))
945 (if (eq (current-buffer) buf)
946 (and wl-folder-move-cur-folder
947 wl-folder-buffer-cur-point
948 (goto-char wl-folder-buffer-cur-point)))))
950 (defun wl-folder-check-current-entity ()
951 "Check folder at position.
952 If current line is group folder, check all sub entries."
954 (let* ((entity-name (wl-folder-get-entity-from-buffer))
955 (group (wl-folder-buffer-group-p))
956 (desktop (string= entity-name wl-folder-desktop-name)))
958 (wl-folder-check-entity
960 (wl-folder-search-group-entity-by-name entity-name
965 (defun wl-folder-sync-entity (entity &optional unread-only)
966 "Synchronize the msgdb of ENTITY."
969 (let ((flist (nth 2 entity)))
971 (wl-folder-sync-entity (car flist) unread-only)
972 (setq flist (cdr flist)))))
974 (let ((nums (wl-folder-get-entity-info entity))
975 (wl-summary-highlight (if (or (wl-summary-sticky-p entity)
976 (wl-summary-always-sticky-folder-p
978 wl-summary-highlight))
979 wl-auto-select-first new unread)
980 (setq new (or (car nums) 0))
981 (setq unread (or (cadr nums) 0))
982 (if (or (not unread-only)
983 (or (< 0 new) (< 0 unread)))
984 (let ((wl-summary-buffer-name (concat
985 wl-summary-buffer-name
986 (symbol-name this-command)))
987 (wl-summary-use-frame nil)
988 (wl-message-buf-name (concat wl-message-buf-name
989 (symbol-name this-command))))
990 (save-window-excursion
992 (wl-summary-goto-folder-subr entity
993 (wl-summary-get-sync-range entity)
995 (wl-summary-exit)))))))))
997 (defun wl-folder-sync-current-entity (&optional unread-only)
998 "Synchronize the folder at position.
999 If current line is group folder, check all subfolders."
1002 (let ((entity-name (wl-folder-get-entity-from-buffer))
1003 (group (wl-folder-buffer-group-p)))
1004 (when (and entity-name
1005 (y-or-n-p (format "Sync %s?" entity-name)))
1006 (wl-folder-sync-entity
1008 (wl-folder-search-group-entity-by-name entity-name
1012 (message "Syncing %s is done!" entity-name)))))
1014 (defun wl-folder-mark-as-read-all-entity (entity)
1015 "Mark as read all messages in the ENTITY."
1018 (let ((flist (nth 2 entity)))
1020 (wl-folder-mark-as-read-all-entity (car flist))
1021 (setq flist (cdr flist)))))
1023 (let ((nums (wl-folder-get-entity-info entity))
1024 (wl-summary-highlight (if (or (wl-summary-sticky-p entity)
1025 (wl-summary-always-sticky-folder-p
1027 wl-summary-highlight))
1028 wl-auto-select-first new unread)
1029 (setq new (or (car nums) 0))
1030 (setq unread (or (cadr nums) 0))
1031 (if (or (< 0 new) (< 0 unread))
1032 (let ((wl-summary-buffer-name (concat
1033 wl-summary-buffer-name
1034 (symbol-name this-command)))
1035 (wl-summary-use-frame nil)
1036 (wl-message-buf-name (concat wl-message-buf-name
1037 (symbol-name this-command))))
1038 (save-window-excursion
1040 (wl-summary-goto-folder-subr entity
1041 (wl-summary-get-sync-range entity)
1043 (wl-summary-mark-as-read-all)
1044 (wl-summary-exit))))
1047 (defun wl-folder-mark-as-read-all-current-entity ()
1048 "Mark as read all messages in the folder at position.
1049 If current line is group folder, all subfolders are marked."
1052 (let ((entity-name (wl-folder-get-entity-from-buffer))
1053 (group (wl-folder-buffer-group-p))
1055 (when (and entity-name
1056 (y-or-n-p (format "Mark all messages in %s as read?" entity-name)))
1057 (wl-folder-mark-as-read-all-entity
1059 (wl-folder-search-group-entity-by-name entity-name
1062 (message "All messages in %s are marked!" entity-name)))))
1064 (defun wl-folder-check-region (beg end)
1073 (let ((inhibit-read-only t)
1075 (while (< (point) end)
1076 ;; normal folder entity
1077 (if (looking-at "^[\t ]*\\([^\\[]+\\):\\(.*\\)\n")
1079 (setq entity (wl-folder-get-entity-from-buffer))
1080 (if (not (elmo-folder-plugged-p entity))
1081 (message "Uncheck %s" entity)
1082 (message "Checking %s" entity)
1083 (wl-folder-check-one-entity entity)
1088 (defun wl-folder-sync-region (beg end)
1097 (while (< (point) end)
1098 ;; normal folder entity
1099 (if (looking-at "^[\t ]*\\([^\\[]+\\):\\(.*\\)\n")
1101 (let ((inhibit-read-only t)
1103 (setq entity (wl-folder-get-entity-from-buffer))
1104 (wl-folder-sync-entity entity)
1105 (message "Syncing %s is done!" entity)
1110 (defun wl-folder-mark-as-read-all-region (beg end)
1119 (while (< (point) end)
1120 ;; normal folder entity
1121 (if (looking-at "^[\t ]*\\([^\\[]+\\):\\(.*\\)\n")
1123 (let ((inhibit-read-only t)
1125 (setq entity (wl-folder-get-entity-from-buffer))
1126 (wl-folder-mark-as-read-all-entity entity)
1127 (message "All messages in %s are marked!" entity)
1132 (defsubst wl-create-access-init-load-p (folder)
1133 (let ((no-load-regexp (when (and
1134 (not wl-folder-init-load-access-folders)
1135 wl-folder-init-no-load-access-folders)
1136 (mapconcat 'identity
1137 wl-folder-init-no-load-access-folders
1139 (load-regexp (and wl-folder-init-load-access-folders
1140 (mapconcat 'identity
1141 wl-folder-init-load-access-folders
1143 (cond (load-regexp (string-match load-regexp folder))
1144 (t (not (and no-load-regexp
1145 (string-match no-load-regexp folder)))))))
1147 (defun wl-create-access-folder-entity (name)
1149 (when (wl-create-access-init-load-p name)
1150 (setq flists (elmo-msgdb-flist-load name)) ; load flist.
1151 (setq flist (car flists))
1153 (when (consp (car flist))
1154 (setcdr (cdar flist)
1155 (wl-create-access-folder-entity (caar flist))))
1156 (setq flist (cdr flist)))
1159 (defun wl-create-folder-entity-from-buffer ()
1160 "Create folder entity recursively."
1162 ((looking-at "^[ \t]*$") ; blank line
1163 (goto-char (+ 1(match-end 0)))
1165 ((looking-at "^#.*$") ; comment
1166 (goto-char (+ 1 (match-end 0)))
1168 ((looking-at "^[\t ]*\\(.+\\)[\t ]*{[\t ]*$") ; group definition
1169 (let (name entity flist)
1170 (setq name (wl-match-buffer 1))
1171 (goto-char (+ 1 (match-end 0)))
1172 (while (setq entity (wl-create-folder-entity-from-buffer))
1173 (unless (eq entity 'ignore)
1174 (wl-append flist (list entity))))
1175 (if (looking-at "^[\t ]*}[\t ]*$") ; end of group
1177 (goto-char (+ 1 (match-end 0)))
1178 (if (wl-string-assoc name wl-folder-petname-alist)
1179 (error "%s already defined as petname" name))
1180 (list name 'group flist))
1181 (error "Syntax error in folder definition"))))
1182 ((looking-at "^[\t ]*\\([^\t \n]+\\)[\t ]*/$") ; access it!
1184 (setq name (wl-match-buffer 1))
1185 (goto-char (+ 1 (match-end 0)))
1186 ; (condition-case ()
1188 ; (setq flist (elmo-list-folders name)))
1189 ; (error (message "Access to folder %s failed." name)))
1190 ;; (setq flist (elmo-msgdb-flist-load name)) ; load flist.
1191 ;; (setq unsublist (nth 1 flist))
1192 ;; (setq flist (car flist))
1193 ;; (list name 'access flist unsublist)))
1194 (append (list name 'access) (wl-create-access-folder-entity name))))
1195 ;((looking-at "^[\t ]*\\([^\t \n}]+\\)[\t ]*\\(\"[^\"]*\"\\)?[\t ]*$") ; normal folder entity
1196 ((looking-at "^[\t ]*=[ \t]+\\([^\n]+\\)$"); petname definition
1197 (goto-char (+ 1 (match-end 0)))
1198 (let ((rest (elmo-match-buffer 1))
1200 (when (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 (elmo-match-string 1 rest)
1207 ((looking-at "^[ \t]*}[ \t]*$") ; end of group
1209 ((looking-at "^.*$") ; normal folder entity
1210 (goto-char (+ 1 (match-end 0)))
1211 (let ((rest (elmo-match-buffer 0))
1213 (if (string-match "\\(\"[^\"]*\"\\)[\t ]*$" rest)
1215 (setq petname (elmo-delete-char ?\" (elmo-match-string 1 rest)))
1216 (setq rest (substring rest 0 (match-beginning 0)))
1217 (when (string-match "^[\t ]*\\(.*[^\t ]+\\)[\t ]+$" rest)
1218 (wl-folder-append-petname
1219 (setq realname (elmo-match-string 1 rest))
1222 (if (string-match "^[\t ]*\\(.+\\)$" rest)
1223 (elmo-match-string 1 rest)
1226 (defun wl-folder-create-folder-entity ()
1227 "Create folder entries."
1228 (let ((tmp-buf (get-buffer-create " *wl-folder-tmp*"))
1232 (with-current-buffer tmp-buf
1234 (insert-file-contents wl-folders-file)
1235 (goto-char (point-min))
1236 (while (and (not (eobp))
1237 (setq entity (wl-create-folder-entity-from-buffer)))
1238 (unless (eq entity 'ignore)
1239 (wl-append ret-val (list entity)))))
1240 (kill-buffer tmp-buf))
1242 (setq ret-val (list wl-folder-desktop-name 'group ret-val))))
1244 (defun wl-folder-entity-assign-id (entity &optional hashtb on-noid)
1245 (let ((hashtb (or hashtb
1246 (setq wl-folder-entity-id-name-hashtb
1247 (elmo-make-hash wl-folder-entity-id))))
1248 (entities (list entity))
1251 (setq entity (wl-pop entities))
1254 (when (not (and on-noid
1255 (get-text-property 0
1256 'wl-folder-entity-id
1258 (put-text-property 0 (length (car entity))
1259 'wl-folder-entity-id
1262 (wl-folder-set-id-name wl-folder-entity-id
1263 (car entity) hashtb))
1265 (wl-push entities entity-stack))
1266 (setq entities (nth 2 entity)))
1268 (when (not (and on-noid
1269 (get-text-property 0
1270 'wl-folder-entity-id
1272 (put-text-property 0 (length entity)
1273 'wl-folder-entity-id
1276 (wl-folder-set-id-name wl-folder-entity-id
1278 (setq wl-folder-entity-id (+ 1 wl-folder-entity-id))
1280 (setq entities (wl-pop entity-stack))))))
1282 (defun wl-folder-click (e)
1287 (wl-folder-jump-to-current-entity)))
1289 (defun wl-folder-select-buffer (buffer)
1290 (let ((gbw (get-buffer-window buffer))
1293 (progn (select-window gbw)
1295 (unless wl-summary-use-frame
1298 (split-window-horizontally wl-folder-window-width)
1302 (if wl-summary-use-frame
1303 (switch-to-buffer-other-frame buffer)
1304 (switch-to-buffer buffer))
1307 (defun wl-folder-toggle-disp-summary (&optional arg folder)
1309 (if (or (and folder (assoc folder wl-folder-group-alist))
1310 (and (interactive-p) (wl-folder-buffer-group-p)))
1311 (error "This command is not available on Group"))
1313 (let (wl-auto-select-first)
1316 (setq wl-folder-buffer-disp-summary t))
1318 (setq wl-folder-buffer-disp-summary nil)
1319 ;; hide wl-summary window.
1320 (let ((cur-buf (current-buffer))
1321 (summary-buffer (wl-summary-get-buffer folder)))
1322 (wl-folder-select-buffer summary-buffer)
1324 (select-window (get-buffer-window cur-buf))))
1326 (setq wl-folder-buffer-disp-summary
1327 (not wl-folder-buffer-disp-summary))
1328 (let ((cur-buf (current-buffer))
1330 (when (looking-at "^[ ]*\\([^\\[].+\\):.*\n")
1331 (setq folder-name (wl-folder-get-entity-from-buffer))
1332 (if wl-folder-buffer-disp-summary
1334 (wl-folder-select-buffer
1335 (wl-summary-get-buffer-create folder-name))
1337 (wl-summary-goto-folder-subr folder-name 'no-sync nil)
1338 (select-window (get-buffer-window cur-buf))))
1339 (wl-folder-select-buffer (wl-summary-get-buffer folder-name))
1341 (select-window (get-buffer-window cur-buf)))))))))
1343 (defun wl-folder-prev-unsync ()
1344 "Move cursor to the previous unsync folder."
1347 (setq start-point (point))
1349 (if (re-search-backward wl-folder-unsync-regexp nil t)
1351 (goto-char start-point)
1352 (message "No more unsync folder"))))
1354 (defun wl-folder-next-unsync (&optional plugged)
1355 "Move cursor to the next unsync."
1357 (let (start-point entity)
1358 (setq start-point (point))
1361 (while (re-search-forward wl-folder-unsync-regexp nil t)
1362 (if (or (wl-folder-buffer-group-p)
1365 (wl-folder-get-realname
1366 (wl-folder-folder-name)))
1367 (elmo-folder-plugged-p entity))
1370 (goto-char start-point)
1371 (message "No more unsync folder"))))
1373 (defun wl-folder-prev-unread (&optional group)
1374 "Move cursor to the previous unread folder."
1377 (setq start-point (point))
1379 (if (re-search-backward (wl-folder-unread-regex group) nil t)
1382 (wl-folder-folder-name))
1383 (goto-char start-point)
1384 (message "No more unread folder")
1387 (defun wl-folder-next-unread (&optional group)
1388 "Move cursor to the next unread folder."
1391 (setq start-point (point))
1393 (if (re-search-forward (wl-folder-unread-regex group) nil t)
1396 (wl-folder-folder-name))
1397 (goto-char start-point)
1398 (message "No more unread folder")
1401 (defun wl-folder-mode ()
1402 "Major mode for Wanderlust Folder.
1403 See Info under Wanderlust for full documentation.
1406 \\{wl-folder-mode-map}
1408 Entering Folder mode calls the value of `wl-folder-mode-hook'."
1410 (setq major-mode 'wl-folder-mode)
1411 (setq mode-name "Folder")
1412 (use-local-map wl-folder-mode-map)
1413 (setq buffer-read-only t)
1414 (setq inhibit-read-only nil)
1415 (setq truncate-lines t)
1416 (setq wl-folder-buffer-cur-entity-id nil
1417 wl-folder-buffer-cur-path nil
1418 wl-folder-buffer-cur-point nil)
1419 (wl-mode-line-buffer-identification)
1420 (easy-menu-add wl-folder-mode-menu)
1421 ;; This hook may contain the functions `wl-folder-init-icons' and
1422 ;; `wl-setup-folder' for reasons of system internal to accord
1423 ;; facilities for the Emacs variants.
1424 (run-hooks 'wl-folder-mode-hook))
1426 (defun wl-folder-append-petname (realname petname)
1428 ;; check group name.
1429 (if (wl-folder-search-group-entity-by-name petname wl-folder-entity)
1430 (error "%s already defined as group name" petname))
1431 (when (setq pentry (wl-string-assoc realname wl-folder-petname-alist))
1432 (setq wl-folder-petname-alist
1433 (delete pentry wl-folder-petname-alist)))
1434 (wl-append wl-folder-petname-alist
1435 (list (cons realname petname)))))
1437 (defun wl-folder (&optional arg)
1439 (let (initialize folder-buf)
1440 (if (setq folder-buf (get-buffer wl-folder-buffer-name))
1441 (if wl-folder-use-frame
1443 (save-selected-window
1444 (dolist (frame (visible-frame-list))
1445 (select-frame frame)
1446 (if (get-buffer-window folder-buf)
1447 (setq select-frame frame))))
1449 (select-frame select-frame)
1450 (switch-to-buffer folder-buf)))
1451 (switch-to-buffer folder-buf))
1452 (if wl-folder-use-frame
1453 (switch-to-buffer-other-frame
1454 (get-buffer-create wl-folder-buffer-name))
1455 (switch-to-buffer (get-buffer-create wl-folder-buffer-name)))
1456 (switch-to-buffer (get-buffer wl-folder-buffer-name))
1459 (set-buffer wl-folder-buffer-name)
1460 (let ((inhibit-read-only t)
1461 (buffer-read-only nil))
1463 (setcdr (assoc (car wl-folder-entity) wl-folder-group-alist) t)
1465 (wl-folder-insert-entity " " wl-folder-entity)))
1466 (set-buffer-modified-p nil)
1468 (setq initialize t))
1471 (defun wl-folder-auto-check ()
1472 "Check and update folders in `wl-auto-check-folder-name'."
1474 (when (get-buffer wl-folder-buffer-name)
1475 (switch-to-buffer wl-folder-buffer-name)
1477 ((eq wl-auto-check-folder-name 'none))
1478 ((or (consp wl-auto-check-folder-name)
1479 (stringp wl-auto-check-folder-name))
1480 (let ((folder-list (if (consp wl-auto-check-folder-name)
1481 wl-auto-check-folder-name
1482 (list wl-auto-check-folder-name)))
1485 (if (setq entity (wl-folder-search-entity-by-name
1488 (wl-folder-check-entity entity 'auto))
1489 (setq folder-list (cdr folder-list)))))
1491 (wl-folder-check-entity wl-folder-entity 'auto)))))
1493 (defun wl-folder-set-folder-updated (name value)
1496 (if (setq buf (get-buffer wl-folder-buffer-name))
1497 (wl-folder-entity-hashtb-set
1498 wl-folder-entity-hashtb name value buf))
1499 ;;; (elmo-folder-set-info-hashtb (elmo-string name)
1504 (setq wl-folder-info-alist-modified t))))
1506 (defun wl-folder-calc-finfo (entity)
1507 ;; calcurate finfo without inserting.
1508 (let ((entities (list entity))
1510 new unread all nums)
1512 (setq entity (wl-pop entities))
1516 (wl-push entities entity-stack))
1517 (setq entities (nth 2 entity)))
1519 (setq nums (wl-folder-get-entity-info entity))
1520 (setq new (+ (or new 0) (or (nth 0 nums) 0)))
1521 (setq unread (+ (or unread 0)
1522 (or (and (nth 0 nums)(nth 1 nums)
1523 (+ (nth 0 nums)(nth 1 nums))) 0)))
1524 (setq all (+ (or all 0) (or (nth 2 nums) 0)))))
1526 (setq entities (wl-pop entity-stack))))
1527 (list new unread all)))
1529 (defsubst wl-folder-make-save-access-list (list)
1530 (mapcar '(lambda (x)
1533 (list (elmo-string (car x)) 'access))
1538 (defun wl-folder-update-newest (indent entity)
1539 (let (ret-val new unread all)
1542 (let ((inhibit-read-only t)
1543 (buffer-read-only nil)
1544 (flist (nth 2 entity))
1545 (as-opened (cdr (assoc (car entity) wl-folder-group-alist)))
1550 (let (update-flist flist-unsub new-flist removed group-name-end)
1551 (when (and (eq (cadr entity) 'access)
1552 (elmo-folder-plugged-p (car entity)))
1553 (message "Fetching folder entries...")
1554 (when (setq new-flist
1556 (elmo-string (car entity))
1559 wl-folder-hierarchy-access-folders)))
1561 (wl-folder-update-access-group entity new-flist))
1562 (setq flist (nth 1 update-flist))
1563 (when (car update-flist) ;; diff
1564 (setq flist-unsub (nth 2 update-flist))
1565 (setq removed (nth 3 update-flist))
1566 (elmo-msgdb-flist-save
1569 (wl-folder-make-save-access-list flist)
1570 (wl-folder-make-save-access-list flist-unsub)))
1571 (wl-folder-entity-assign-id
1573 wl-folder-entity-id-name-hashtb
1575 (setq wl-folder-entity-hashtb
1576 (wl-folder-create-entity-hashtb
1578 wl-folder-entity-hashtb
1580 (setq wl-folder-newsgroups-hashtb
1582 (wl-folder-create-newsgroups-hashtb
1584 wl-folder-newsgroups-hashtb))))
1585 (message "Fetching folder entries...done"))
1586 (wl-folder-insert-entity indent entity))))))))
1588 (defun wl-folder-insert-entity (indent entity &optional onlygroup)
1589 (let (ret-val new unread all)
1592 (let ((inhibit-read-only t)
1593 (buffer-read-only nil)
1594 (flist (nth 2 entity))
1595 (as-opened (cdr (assoc (car entity) wl-folder-group-alist)))
1598 ;;; (insert indent "[" (if as-opened "-" "+") "]" (car entity) "\n")
1599 ;;; (save-excursion (forward-line -1)
1600 ;;; (wl-highlight-folder-current-line))
1604 (let (update-flist flist-unsub new-flist removed group-name-end)
1605 ;;; (when (and (eq (cadr entity) 'access)
1607 ;;; (message "fetching folder entries...")
1608 ;;; (when (setq new-flist
1609 ;;; (elmo-list-folders
1610 ;;; (elmo-string (car entity))
1611 ;;; (wl-string-member
1613 ;;; wl-folder-hierarchy-access-folders)
1615 ;;; (setq update-flist
1616 ;;; (wl-folder-update-access-group entity new-flist))
1617 ;;; (setq flist (nth 1 update-flist))
1618 ;;; (when (car update-flist) ;; diff
1619 ;;; (setq flist-unsub (nth 2 update-flist))
1620 ;;; (setq removed (nth 3 update-flist))
1621 ;;; (elmo-msgdb-flist-save
1624 ;;; (wl-folder-make-save-access-list flist)
1625 ;;; (wl-folder-make-save-access-list flist-unsub)))
1627 ;;; ;; reconstruct wl-folder-entity-id-name-hashtb and
1628 ;;; ;; wl-folder-entity-hashtb
1630 ;;; (wl-folder-entity-assign-id
1632 ;;; wl-folder-entity-id-name-hashtb
1634 ;;; (setq wl-folder-entity-hashtb
1635 ;;; (wl-folder-create-entity-hashtb
1637 ;;; wl-folder-entity-hashtb
1639 ;;; (setq wl-folder-newsgroups-hashtb
1641 ;;; (wl-folder-create-newsgroups-hashtb
1643 ;;; wl-folder-newsgroups-hashtb))))
1644 ;;; (message "fetching folder entries...done"))
1645 (insert indent "[" (if as-opened "-" "+") "]"
1646 (wl-folder-get-petname (car entity)))
1647 (setq group-name-end (point))
1649 (put-text-property beg (point) 'wl-folder-entity-id
1650 (get-text-property 0 'wl-folder-entity-id
1656 wl-folder-removed-mark
1657 (if (listp (car removed))
1658 (concat "[+]" (caar removed))
1661 (save-excursion (forward-line -1)
1662 (wl-highlight-folder-current-line))
1663 (setq removed (cdr removed)))
1664 (remove-text-properties beg (point) '(wl-folder-entity-id)))
1665 (let* ((len (length flist))
1670 (wl-folder-insert-entity
1671 (concat indent " ") (car flist)))
1672 (setq new (+ (or new 0) (or (nth 0 ret-val) 0)))
1673 (setq unread (+ (or unread 0) (or (nth 1 ret-val) 0)))
1674 (setq all (+ (or all 0) (or (nth 2 ret-val) 0)))
1676 (> len elmo-display-progress-threshold))
1678 (elmo-display-progress
1679 'wl-folder-insert-entity "Inserting group %s..."
1680 (/ (* i 100) len) (car entity)))
1681 (setq flist (cdr flist))))
1683 (goto-char group-name-end)
1684 (delete-region (point) (save-excursion (end-of-line)
1686 (insert (format ":%d/%d/%d" (or new 0)
1687 (or unread 0) (or all 0)))
1688 (setq ret-val (list new unread all))
1689 (wl-highlight-folder-current-line ret-val)))
1690 (setq ret-val (wl-folder-calc-finfo entity))
1691 (insert indent "[" (if as-opened "-" "+") "]"
1692 (wl-folder-get-petname (car entity))
1694 (or (nth 0 ret-val) 0)
1695 (or (nth 1 ret-val) 0)
1696 (or (nth 2 ret-val) 0))
1698 (put-text-property beg (point) 'wl-folder-entity-id
1699 (get-text-property 0 'wl-folder-entity-id
1701 (save-excursion (forward-line -1)
1702 (wl-highlight-folder-current-line ret-val)))))
1704 (let* ((inhibit-read-only t)
1705 (buffer-read-only nil)
1706 (nums (wl-folder-get-entity-info entity))
1709 (insert indent (wl-folder-get-petname entity)
1710 (format ":%s/%s/%s\n"
1711 (or (setq new (nth 0 nums)) "*")
1712 (or (setq unread (and (nth 0 nums)(nth 1 nums)
1713 (+ (nth 0 nums)(nth 1 nums))))
1715 (or (setq all (nth 2 nums)) "*")))
1716 (put-text-property beg (point) 'wl-folder-entity-id
1717 (get-text-property 0 'wl-folder-entity-id entity))
1718 (save-excursion (forward-line -1)
1719 (wl-highlight-folder-current-line nums))
1720 (setq ret-val (list new unread all)))))
1721 (set-buffer-modified-p nil)
1724 (defun wl-folder-check-all ()
1726 (wl-folder-check-entity wl-folder-entity))
1728 (defun wl-folder-entity-hashtb-set (entity-hashtb name value buffer)
1735 (setq cur-val (wl-folder-get-entity-info name entity-hashtb))
1736 (setq new-diff (- (or (nth 0 value) 0) (or (nth 0 cur-val) 0)))
1739 (- (or (nth 1 value) 0) (or (nth 1 cur-val) 0))))
1740 (setq all-diff (- (or (nth 2 value) 0) (or (nth 2 cur-val) 0)))
1741 (setq diffs (list new-diff unread-diff all-diff))
1742 (unless (and (nth 0 cur-val)
1743 (equal diffs '(0 0 0)))
1744 (wl-folder-set-entity-info name value entity-hashtb)
1748 (setq entity-list (wl-folder-search-entity-list-by-name
1749 name wl-folder-entity))
1751 (wl-folder-update-group (car entity-list) diffs)
1752 (setq entity-list (cdr entity-list)))
1753 (goto-char (point-min))
1754 (while (wl-folder-buffer-search-entity name)
1755 (wl-folder-update-line value)))))))
1757 (defun wl-folder-update-unread (folder unread)
1758 (save-window-excursion
1759 (let ((buf (get-buffer wl-folder-buffer-name))
1762 ;;(fld (elmo-string folder))
1763 value newvalue entity-list)
1764 ;;; Update folder-info
1765 ;;; (elmo-folder-set-info-hashtb fld nil nil nil unread)
1766 (setq cur-unread (or (nth 1 (wl-folder-get-entity-info folder)) 0))
1767 (setq unread-diff (- (or unread 0) cur-unread))
1768 (setq value (wl-folder-get-entity-info folder))
1770 (setq newvalue (list (nth 0 value)
1773 (wl-folder-set-entity-info folder newvalue)
1774 (setq wl-folder-info-alist-modified t)
1776 (not (eq unread-diff 0)))
1781 (setq entity-list (wl-folder-search-entity-list-by-name
1782 folder wl-folder-entity))
1784 (wl-folder-update-group (car entity-list) (list 0
1787 (setq entity-list (cdr entity-list)))
1788 (goto-char (point-min))
1789 (while (wl-folder-buffer-search-entity folder)
1790 (wl-folder-update-line newvalue)))))))))
1792 (defun wl-folder-create-entity-hashtb (entity &optional hashtb reconst)
1793 (let ((hashtb (or hashtb (elmo-make-hash wl-folder-entity-id)))
1794 (entities (list entity))
1797 (setq entity (wl-pop entities))
1801 (wl-push entities entity-stack))
1802 (setq entities (nth 2 entity)))
1804 (when (not (and reconst
1805 (wl-folder-get-entity-info entity)))
1806 (wl-folder-set-entity-info entity
1810 (setq entities (wl-pop entity-stack))))
1813 ;; Unsync number is reserved.
1814 ;;(defun wl-folder-reconstruct-entity-hashtb (entity &optional hashtb id-name)
1815 ;; (let* ((hashtb (or hashtb (elmo-make-hash wl-folder-entity-id)))
1816 ;; (entities (list entity))
1819 ;; (setq entity (wl-pop entities))
1823 ;; (wl-folder-set-id-name (wl-folder-get-entity-id (car entity))
1826 ;; (wl-push entities entity-stack))
1827 ;; (setq entities (nth 2 entity))
1829 ;; ((stringp entity)
1830 ;; (wl-folder-set-entity-info entity
1831 ;; (wl-folder-get-entity-info entity)
1834 ;; (wl-folder-set-id-name (wl-folder-get-entity-id entity)
1837 ;; (setq entities (wl-pop entity-stack))))
1840 (defun wl-folder-create-newsgroups-from-nntp-access2 (entity)
1841 (let ((flist (nth 2 entity))
1850 (wl-folder-create-newsgroups-from-nntp-access2 fld)
1851 (nth 1 (elmo-folder-get-spec fld))))
1853 (elmo-nntp-make-groups-hashtb folders 1024))
1856 (defun wl-folder-create-newsgroups-from-nntp-access (entity)
1857 (let ((flist (nth 2 entity))
1862 ((consp (car flist))
1863 (wl-folder-create-newsgroups-from-nntp-access (car flist)))
1865 (list (nth 1 (elmo-folder-get-spec (car flist)))))))
1866 (setq flist (cdr flist)))
1869 (defun wl-folder-create-newsgroups-hashtb (entity &optional is-list info)
1870 (let ((entities (if is-list entity (list entity)))
1871 entity-stack spec-list folders fld make-hashtb)
1872 (and info (message "Creating newsgroups..."))
1874 (setq entity (wl-pop entities))
1877 (if (eq (nth 1 entity) 'access)
1878 (when (eq (elmo-folder-get-type (car entity)) 'nntp)
1880 (wl-folder-create-newsgroups-from-nntp-access entity))
1881 (setq make-hashtb t))
1883 (wl-push entities entity-stack))
1884 (setq entities (nth 2 entity))))
1886 (setq spec-list (elmo-folder-get-primitive-spec-list entity))
1888 (when (and (eq (caar spec-list) 'nntp)
1889 (setq fld (nth 1 (car spec-list))))
1890 (wl-append folders (list (elmo-string fld))))
1891 (setq spec-list (cdr spec-list)))))
1893 (setq entities (wl-pop entity-stack))))
1894 (and info (message "Creating newsgroups...done"))
1895 (if (or folders make-hashtb)
1896 (elmo-nntp-make-groups-hashtb folders))))
1898 (defun wl-folder-get-path (entity target-id &optional string)
1899 (let ((entities (list entity))
1900 entity-stack result-path)
1904 (setq entity (wl-pop entities))
1907 (if (and (or (not string) (string= string (car entity)))
1908 ;; don't use eq, `id' is string on Nemacs.
1909 (equal target-id (wl-folder-get-entity-id (car entity))))
1911 (wl-push target-id result-path))
1912 (wl-push (wl-folder-get-entity-id (car entity)) result-path))
1913 (wl-push entities entity-stack)
1914 (setq entities (nth 2 entity)))
1916 (if (and (or (not string) (string= string entity))
1917 ;; don't use eq, `id' is string on Nemacs.
1918 (equal target-id (wl-folder-get-entity-id entity)))
1920 (wl-push target-id result-path)))))
1922 (while (and entity-stack
1924 (setq result-path (cdr result-path))
1925 (setq entities (wl-pop entity-stack)))))))))
1927 (defun wl-folder-create-group-alist (entity)
1929 (let ((flist (nth 2 entity))
1930 (cur-alist (list (cons (car entity) nil)))
1933 (if (consp (car flist))
1934 (wl-append append-alist
1935 (wl-folder-create-group-alist (car flist))))
1936 (setq flist (cdr flist)))
1937 (append cur-alist append-alist))))
1939 (defun wl-folder-init-info-hashtb ()
1940 (let ((info-alist (and wl-folder-info-save
1941 (elmo-msgdb-finfo-load))))
1942 (elmo-folder-info-make-hashtb
1944 wl-folder-entity-hashtb)))
1945 ;;; (wl-folder-resume-entity-hashtb-by-finfo
1946 ;;; wl-folder-entity-hashtb
1949 (defun wl-folder-cleanup-variables ()
1950 (setq wl-folder-entity nil
1951 wl-folder-entity-hashtb nil
1952 wl-folder-entity-id-name-hashtb nil
1953 wl-folder-group-alist nil
1954 wl-folder-petname-alist nil
1955 wl-folder-newsgroups-hashtb nil
1956 wl-fldmgr-cut-entity-list nil
1957 wl-fldmgr-modified nil
1958 wl-fldmgr-modified-access-list nil
1962 (defun wl-make-plugged-alist ()
1963 (let ((entity-list (wl-folder-get-entity-list wl-folder-entity))
1964 (add (not wl-reset-plugged-alist)))
1966 (elmo-folder-set-plugged
1967 (elmo-string (car entity-list)) wl-plugged add)
1968 (setq entity-list (cdr entity-list)))
1969 ;; smtp posting server
1970 (when wl-smtp-posting-server
1971 (elmo-set-plugged wl-plugged
1972 wl-smtp-posting-server ; server
1973 (or (and (boundp 'smtp-service) smtp-service)
1975 nil nil "smtp" add))
1976 ;; nntp posting server
1977 (when wl-nntp-posting-server
1978 (elmo-set-plugged wl-plugged
1979 wl-nntp-posting-server
1980 elmo-default-nntp-port
1981 nil nil "nntp" add))
1982 (run-hooks 'wl-make-plugged-hook)))
1984 (defvar wl-folder-init-func 'wl-local-folder-init)
1986 (defun wl-folder-init ()
1987 "Call `wl-folder-init-func' function."
1989 (funcall wl-folder-init-func))
1991 (defun wl-local-folder-init ()
1992 "Initialize local folder."
1993 (message "Initializing folder...")
1995 (set-buffer wl-folder-buffer-name)
1996 (let ((entity (wl-folder-create-folder-entity))
1997 (inhibit-read-only t))
1998 (setq wl-folder-entity entity)
1999 (setq wl-folder-entity-id 0)
2000 (wl-folder-entity-assign-id wl-folder-entity)
2001 (setq wl-folder-entity-hashtb
2002 (wl-folder-create-entity-hashtb entity))
2003 (setq wl-folder-group-alist
2004 (wl-folder-create-group-alist entity))
2005 (setq wl-folder-newsgroups-hashtb
2006 (wl-folder-create-newsgroups-hashtb wl-folder-entity))
2007 (wl-folder-init-info-hashtb)))
2008 (message "Initializing folder...done"))
2010 (defun wl-folder-get-realname (petname)
2014 wl-folder-petname-alist))
2017 (defun wl-folder-get-petname (folder)
2021 wl-folder-petname-alist))
2024 (defun wl-folder-get-entity-with-petname ()
2025 (let ((alist wl-folder-petname-alist)
2026 (hashtb (copy-sequence wl-folder-entity-hashtb)))
2028 (wl-folder-set-entity-info (cdar alist) nil hashtb)
2029 (setq alist (cdr alist)))
2032 (defun wl-folder-get-newsgroups (folder)
2033 "Return Newsgroups field value string for FOLDER newsgroup.
2034 If FOLDER is multi, return comma separated string (cross post)."
2035 (let ((flist (elmo-folder-get-primitive-folder-list folder)) ; multi
2037 (while (setq fld (car flist))
2039 (cond ((eq 'nntp (elmo-folder-get-type fld))
2040 (nth 1 (elmo-folder-get-spec fld)))
2041 ((eq 'localnews (elmo-folder-get-type fld))
2042 (elmo-replace-in-string
2043 (nth 1 (elmo-folder-get-spec fld)) "/" "\\."))))
2045 (setq newsgroups (if (stringp newsgroups)
2046 (concat newsgroups "," ret)
2048 (setq flist (cdr flist)))
2049 (list nil nil newsgroups)))
2051 (defun wl-folder-guess-mailing-list-by-refile-rule (folder)
2052 "Return ML address guess by FOLDER.
2053 Use `wl-subscribed-mailing-list' and `wl-refile-rule-alist'.
2055 (setq folder (car (elmo-folder-get-primitive-folder-list folder)))
2056 (unless (memq (elmo-folder-get-type folder)
2058 (let ((rules wl-refile-rule-alist)
2059 mladdress tokey toalist histkey)
2061 (if (or (and (stringp (car (car rules)))
2062 (string-match "[Tt]o" (car (car rules))))
2063 (and (listp (car (car rules)))
2064 (elmo-string-matched-member "to" (car (car rules))
2066 (setq toalist (append toalist (cdr (car rules)))))
2067 (setq rules (cdr rules)))
2068 (setq tokey (car (rassoc folder toalist)))
2069 ;;; (setq histkey (car (rassoc folder wl-refile-alist)))
2070 ;; case-ignore search `wl-subscribed-mailing-list'
2073 (elmo-string-matched-member tokey wl-subscribed-mailing-list t)
2077 (defun wl-folder-guess-mailing-list-by-folder-name (folder)
2078 "Return ML address guess by FOLDER name's last hierarchy.
2079 Use `wl-subscribed-mailing-list'."
2080 (setq folder (car (elmo-folder-get-primitive-folder-list folder)))
2081 (when (memq (elmo-folder-get-type folder)
2082 '(localdir imap4 maildir))
2083 (let (key mladdress)
2084 (setq folder ; make folder name simple
2085 (if (eq 'imap4 (elmo-folder-get-type folder))
2086 (elmo-imap4-spec-mailbox (elmo-imap4-get-spec folder))
2087 (substring folder 1)))
2088 (if (string-match "@" folder)
2089 (setq folder (substring folder 0 (match-beginning 0))))
2090 (when (string-match "[^\\./]+$" folder) ; last hierarchy
2091 (setq key (regexp-quote
2092 (concat (substring folder (match-beginning 0)) "@")))
2094 (elmo-string-matched-member
2095 key wl-subscribed-mailing-list 'case-ignore))
2096 (if (stringp mladdress)
2097 (list mladdress nil nil)
2100 (defun wl-folder-update-diff-line (diffs)
2101 (let ((inhibit-read-only t)
2102 (buffer-read-only nil)
2104 cur-unread new-unread
2109 (setq id (get-text-property (point) 'wl-folder-entity-id))
2110 (when (looking-at "^[ ]*\\(.*\\):\\([0-9\\*-]*\\)/\\([0-9\\*-]*\\)/\\([0-9\\*]*\\)")
2111 ;;(looking-at "^[ ]*\\([^\\[].+\\):\\([0-9\\*-]*/[0-9\\*-]*/[0-9\\*]*\\)")
2112 (setq cur-new (string-to-int
2113 (wl-match-buffer 2)))
2114 (setq cur-unread (string-to-int
2115 (wl-match-buffer 3)))
2116 (setq cur-all (string-to-int
2117 (wl-match-buffer 4)))
2118 (delete-region (match-beginning 2)
2120 (goto-char (match-beginning 2))
2121 (insert (format "%s/%s/%s"
2122 (setq new-new (+ cur-new (nth 0 diffs)))
2123 (setq new-unread (+ cur-unread (nth 1 diffs)))
2124 (setq new-all (+ cur-all (nth 2 diffs)))))
2125 (put-text-property (match-beginning 2) (point)
2126 'wl-folder-entity-id id)
2127 (if wl-use-highlight-mouse-line
2128 (put-text-property (match-beginning 2) (point)
2129 'mouse-face 'highlight))
2130 (wl-highlight-folder-group-line (list new-new new-unread new-all))
2131 (setq buffer-read-only t)
2132 (set-buffer-modified-p nil)))))
2134 (defun wl-folder-update-line (nums &optional is-group)
2135 (let ((inhibit-read-only t)
2136 (buffer-read-only nil)
2140 (setq id (get-text-property (point) 'wl-folder-entity-id))
2141 (if (looking-at "^[ ]*\\(.*\\):\\([0-9\\*-]*/[0-9\\*-]*/[0-9\\*]*\\)")
2142 ;;; (looking-at "^[ ]*\\([^\\[].+\\):\\([0-9\\*-]*/[0-9\\*-]*/[0-9\\*]*\\)")
2144 (delete-region (match-beginning 2)
2146 (goto-char (match-beginning 2))
2147 (insert (format "%s/%s/%s"
2148 (or (nth 0 nums) "*")
2149 (or (and (nth 0 nums)(nth 1 nums)
2150 (+ (nth 0 nums)(nth 1 nums)))
2152 (or (nth 2 nums) "*")))
2153 (put-text-property (match-beginning 2) (point)
2154 'wl-folder-entity-id id)
2156 ;; update only colors
2157 (wl-highlight-folder-group-line nums)
2158 (wl-highlight-folder-current-line nums))
2159 (set-buffer-modified-p nil))))))
2161 (defun wl-folder-goto-folder (&optional arg)
2163 (wl-folder-goto-folder-subr nil arg))
2165 (defun wl-folder-goto-folder-subr (&optional folder sticky)
2167 (let (summary-buf fld-name entity id error-selecting)
2168 ;;; (setq fld-name (wl-folder-get-entity-from-buffer))
2169 ;;; (if (or (null fld-name)
2170 ;;; (assoc fld-name wl-folder-group-alist))
2171 (setq fld-name wl-default-folder)
2172 (setq fld-name (or folder
2173 (wl-summary-read-folder fld-name)))
2174 (if (and (setq entity
2175 (wl-folder-search-entity-by-name fld-name
2178 (setq id (wl-folder-get-entity-id entity)))
2179 (wl-folder-set-current-entity-id id))
2180 (setq summary-buf (wl-summary-get-buffer-create fld-name sticky))
2181 (if (or wl-stay-folder-window wl-summary-use-frame)
2182 (wl-folder-select-buffer summary-buf)
2183 (if (and summary-buf
2184 (get-buffer-window summary-buf))
2186 (wl-summary-goto-folder-subr fld-name
2187 (wl-summary-get-sync-range fld-name)
2190 (defun wl-folder-suspend ()
2192 (run-hooks 'wl-folder-suspend-hook)
2193 (wl-folder-info-save)
2194 (wl-crosspost-alist-save)
2196 (format "^\\(%s\\)$"
2197 (mapconcat 'identity
2198 (list (format "%s\\(:.*\\)?"
2199 (default-value 'wl-message-buf-name))
2200 wl-original-buf-name)
2202 (if (fboundp 'mmelmo-cleanup-entity-buffers)
2203 (mmelmo-cleanup-entity-buffers))
2204 (bury-buffer wl-folder-buffer-name)
2205 (delete-windows-on wl-folder-buffer-name t))
2207 (defun wl-folder-info-save ()
2208 (when (and wl-folder-info-save
2209 wl-folder-info-alist-modified)
2210 (let ((entities (list wl-folder-entity))
2211 entity entity-stack info-alist info)
2213 (setq entity (wl-pop entities))
2217 (wl-push entities entity-stack))
2218 (setq entities (nth 2 entity)))
2220 (when (and (setq info (elmo-folder-get-info entity))
2221 (not (equal info '(nil))))
2222 (wl-append info-alist (list (list (elmo-string entity)
2223 (list (nth 3 info) ;; max
2224 (nth 2 info) ;; length
2226 (nth 1 info)) ;; unread
2229 (setq entities (wl-pop entity-stack))))
2230 (elmo-msgdb-finfo-save info-alist)
2231 (setq wl-folder-info-alist-modified nil))))
2233 (defun wl-folder-goto-first-unread-folder (&optional arg)
2235 (let ((entities (list wl-folder-entity))
2236 entity entity-stack ret-val
2241 (setq entity (wl-pop entities))
2245 (wl-push entities entity-stack))
2246 (setq entities (nth 2 entity)))
2248 (if (and (setq finfo (wl-folder-get-entity-info entity))
2249 (and (nth 0 finfo)(nth 1 finfo))
2250 (> (+ (nth 0 finfo)(nth 1 finfo)) 0))
2251 (throw 'done entity))
2252 (wl-append ret-val (list entity))))
2254 (setq entities (wl-pop entity-stack))))))
2258 (wl-folder-jump-folder first-entity)
2260 (wl-folder-goto-folder-subr first-entity))
2261 (message "No unread folder"))))
2263 (defun wl-folder-jump-folder (&optional fld-name noopen)
2266 (setq fld-name (wl-summary-read-folder wl-default-folder)))
2267 (goto-char (point-min))
2269 (wl-folder-open-folder fld-name))
2270 (and (wl-folder-buffer-search-entity fld-name)
2271 (beginning-of-line)))
2273 (defun wl-folder-get-entity-list (entity)
2274 (let ((entities (list entity))
2275 entity-stack ret-val)
2277 (setq entity (wl-pop entities))
2281 (wl-push entities entity-stack))
2282 (setq entities (nth 2 entity)))
2284 (wl-append ret-val (list entity))))
2286 (setq entities (wl-pop entity-stack))))
2289 (defun wl-folder-open-unread-folder (entity)
2291 (let ((alist (wl-folder-get-entity-list entity))
2293 finfo path-list path id)
2295 (when (and (setq finfo (wl-folder-get-entity-info (car alist)))
2296 (nth 0 finfo) (nth 1 finfo)
2297 (> (+ (nth 0 finfo)(nth 1 finfo)) 0))
2298 (setq unread (+ unread (+ (nth 0 finfo)(nth 1 finfo))))
2299 (setq id (wl-folder-get-entity-id (car alist)))
2300 (setq path (delete id (wl-folder-get-path
2304 (if (not (member path path-list))
2305 (wl-append path-list (list path))))
2306 (setq alist (cdr alist)))
2308 (wl-folder-open-folder-sub (car path-list))
2309 (setq path-list (cdr path-list)))
2310 (message "%s unread folder"
2311 (if (> unread 0) unread "No")))))
2313 (defun wl-folder-open-unread-current-entity ()
2315 (let ((entity-name (wl-folder-get-entity-from-buffer))
2316 (group (wl-folder-buffer-group-p)))
2318 (wl-folder-open-unread-folder
2320 (wl-folder-search-group-entity-by-name entity-name
2324 (defun wl-folder-open-only-unread-folder ()
2327 (wl-folder-prev-entity-skip-invalid t)
2328 (wl-folder-get-entity-from-buffer t))))
2329 (wl-folder-open-all-unread-folder)
2331 (goto-char (point-max))
2332 (while (and (re-search-backward
2333 "^[ ]*\\[[-]\\].+:0/0/[0-9-]+" nil t)
2335 (wl-folder-jump-to-current-entity) ;; close it
2337 (wl-folder-move-path id)
2340 (defun wl-folder-open-all-unread-folder (&optional arg)
2343 (wl-folder-prev-entity-skip-invalid t)
2344 (wl-folder-get-entity-from-buffer t))))
2345 (wl-folder-open-unread-folder wl-folder-entity)
2347 (wl-folder-move-path id)
2348 (goto-char (point-min))
2349 (wl-folder-next-unread t))))
2351 (defun wl-folder-open-folder (&optional fld-name)
2354 (setq fld-name (wl-summary-read-folder wl-default-folder)))
2355 (let* ((id (wl-folder-get-entity-id
2356 (wl-folder-search-entity-by-name fld-name wl-folder-entity
2358 (path (and id (wl-folder-get-path wl-folder-entity id))))
2360 (wl-folder-open-folder-sub path))))
2362 (defun wl-folder-open-folder-sub (path)
2363 (let ((inhibit-read-only t)
2364 (buffer-read-only nil)
2368 (goto-char (point-min))
2370 (wl-folder-buffer-search-group
2371 (wl-folder-get-petname
2372 (if (stringp (car path))
2374 (wl-folder-get-folder-name-by-id
2377 (setq path (cdr path))
2378 (if (and (looking-at wl-folder-group-regexp)
2379 (string= "+" (wl-match-buffer 2)));; closed group
2381 (setq indent (wl-match-buffer 1))
2382 (setq name (wl-folder-get-realname (wl-match-buffer 3)))
2383 (setq entity (wl-folder-search-group-entity-by-name
2387 (setcdr (assoc (car entity) wl-folder-group-alist) t)
2388 (if (eq 'access (cadr entity))
2389 (wl-folder-maybe-load-folder-list entity))
2390 (wl-folder-insert-entity indent entity)
2391 (delete-region (save-excursion (beginning-of-line)
2393 (save-excursion (end-of-line)
2395 (set-buffer-modified-p nil))))
2397 (defun wl-folder-open-all-pre ()
2398 (let ((entities (list wl-folder-entity))
2399 entity entity-stack group-entry)
2401 (setq entity (wl-pop entities))
2404 (unless (or (not (setq group-entry
2405 (assoc (car entity) wl-folder-group-alist)))
2407 (setcdr group-entry t)
2408 (when (eq 'access (cadr entity))
2409 (wl-folder-maybe-load-folder-list entity)))
2411 (wl-push entities entity-stack))
2412 (setq entities (nth 2 entity))))
2414 (setq entities (wl-pop entity-stack))))))
2416 (defun wl-folder-open-all (&optional refresh)
2418 (let* ((inhibit-read-only t)
2419 (buffer-read-only nil)
2420 (len (length wl-folder-group-alist))
2425 (wl-folder-prev-entity-skip-invalid t)
2426 (wl-folder-get-entity-from-buffer t)))
2427 (alist wl-folder-group-alist))
2429 (setcdr (pop alist) t))
2431 (wl-folder-insert-entity " " wl-folder-entity)
2432 (wl-folder-move-path id))
2433 (message "Opening all folders...")
2434 (wl-folder-open-all-pre)
2436 (goto-char (point-min))
2437 (while (re-search-forward
2438 "^\\([ ]*\\)\\[\\([+]\\)\\]\\(.+\\):[-0-9-]+/[0-9-]+/[0-9-]+\n"
2440 (setq indent (wl-match-buffer 1))
2441 (setq name (wl-folder-get-realname (wl-match-buffer 3)))
2442 (setq entity (wl-folder-search-group-entity-by-name
2446 (setcdr (assoc (car entity) wl-folder-group-alist) t)
2448 (wl-folder-insert-entity indent entity)
2449 (delete-region (save-excursion (beginning-of-line)
2451 (save-excursion (end-of-line)
2453 (when (> len elmo-display-progress-threshold)
2455 (if (or (zerop (% i 5)) (= i len))
2456 (elmo-display-progress
2457 'wl-folder-open-all "Opening all folders..."
2458 (/ (* i 100) len)))))
2459 (when (> len elmo-display-progress-threshold)
2460 (elmo-display-progress
2461 'wl-folder-open-all "Opening all folders..." 100))))
2462 (message "Opening all folders...done")
2463 (set-buffer-modified-p nil)))
2465 (defun wl-folder-close-all ()
2467 (let ((inhibit-read-only t)
2468 (buffer-read-only nil)
2469 (alist wl-folder-group-alist)
2471 (wl-folder-prev-entity-skip-invalid t)
2472 (wl-folder-get-entity-from-buffer t))))
2474 (setcdr (car alist) nil)
2475 (setq alist (cdr alist)))
2476 (setcdr (assoc (car wl-folder-entity) wl-folder-group-alist) t)
2478 (wl-folder-insert-entity " " wl-folder-entity)
2479 (wl-folder-move-path id)
2481 (set-buffer-modified-p nil)))
2483 (defun wl-folder-open-close ()
2484 "Open or close parent entity."
2488 (if (wl-folder-buffer-group-p)
2489 ;; if group (whether opend or closed.)
2490 (wl-folder-jump-to-current-entity)
2493 (setq indent (save-excursion
2494 (re-search-forward "\\([ ]*\\)." nil t)
2495 (wl-match-buffer 1)))
2496 (while (looking-at indent)
2498 (wl-folder-jump-to-current-entity))))
2500 (defsubst wl-folder-access-subscribe-p (group folder)
2501 (let (subscr regexp match)
2502 (if (setq subscr (wl-get-assoc-list-value
2503 wl-folder-access-subscribe-alist
2506 (setq regexp (mapconcat 'identity (cdr subscr) "\\|"))
2507 (setq match (string-match regexp folder))
2513 (defun wl-folder-update-access-group (entity new-flist)
2514 (let* ((flist (nth 2 entity))
2515 (unsubscribes (nth 3 entity))
2516 (len (+ (length flist) (length unsubscribes)))
2518 diff new-unsubscribes removes
2519 subscribed-list folder group entry)
2520 ;; check subscribed groups
2523 ((listp (car flist)) ;; group
2524 (setq group (elmo-string (caar flist)))
2526 ((assoc group new-flist) ;; found in new-flist
2527 (setq new-flist (delete (assoc group new-flist)
2529 (if (wl-folder-access-subscribe-p (car entity) group)
2530 (wl-append subscribed-list (list (car flist)))
2531 (wl-append new-unsubscribes (list (car flist)))
2534 (setq wl-folder-group-alist
2535 (delete (wl-string-assoc group wl-folder-group-alist)
2536 wl-folder-group-alist))
2537 (wl-append removes (list (list group))))))
2539 (setq folder (elmo-string (car flist)))
2541 ((member folder new-flist) ;; found in new-flist
2542 (setq new-flist (delete folder new-flist))
2543 (if (wl-folder-access-subscribe-p (car entity) folder)
2544 (wl-append subscribed-list (list (car flist)))
2545 (wl-append new-unsubscribes (list folder))
2548 (wl-append removes (list folder))))))
2549 (when (> len elmo-display-progress-threshold)
2551 (if (or (zerop (% i 10)) (= i len))
2552 (elmo-display-progress
2553 'wl-folder-update-access-group "Updating access group..."
2554 (/ (* i 100) len))))
2555 (setq flist (cdr flist)))
2556 ;; check unsubscribed groups
2559 ((listp (car unsubscribes))
2560 (when (setq entry (assoc (caar unsubscribes) new-flist))
2561 (setq new-flist (delete entry new-flist))
2562 (wl-append new-unsubscribes (list (car unsubscribes)))))
2564 (when (member (car unsubscribes) new-flist)
2565 (setq new-flist (delete (car unsubscribes) new-flist))
2566 (wl-append new-unsubscribes (list (car unsubscribes))))))
2567 (when (> len elmo-display-progress-threshold)
2569 (if (or (zerop (% i 10)) (= i len))
2570 (elmo-display-progress
2571 'wl-folder-update-access-group "Updating access group..."
2572 (/ (* i 100) len))))
2573 (setq unsubscribes (cdr unsubscribes)))
2575 (if (or new-flist removes)
2578 (mapcar '(lambda (x)
2579 (cond ((consp x) (list (car x) 'access))
2583 (let ((new-list new-flist))
2585 (if (not (wl-folder-access-subscribe-p
2587 (if (listp (car new-list))
2592 (wl-append new-unsubscribes (list (car new-list)))
2593 (setq new-flist (delete (car new-list) new-flist)))
2595 ((listp (car new-list))
2596 ;; check group exists
2597 (if (wl-string-assoc (caar new-list) wl-folder-group-alist)
2599 (message "%s: group already exists." (caar new-list))
2601 (wl-append new-unsubscribes (list (car new-list)))
2602 (setq new-flist (delete (car new-list) new-flist)))
2603 (wl-append wl-folder-group-alist
2604 (list (cons (caar new-list) nil)))))))
2605 (setq new-list (cdr new-list))))
2607 (message "%d new folder(s)." (length new-flist))
2608 (message "Updating access group...done"))
2609 (wl-append new-flist subscribed-list) ;; new is first
2610 (run-hooks 'wl-folder-update-access-group-hook)
2611 (setcdr (cdr entity) (list new-flist new-unsubscribes))
2612 (list diff new-flist new-unsubscribes removes)))
2614 (defun wl-folder-prefetch-entity (entity)
2615 "Prefetch all new messages in the ENTITY."
2618 (let ((flist (nth 2 entity))
2623 (setq result (wl-folder-prefetch-entity (car flist)))
2624 (setq sum-done (+ sum-done (car result)))
2625 (setq sum-all (+ sum-all (cdr result)))
2626 (setq flist (cdr flist)))
2627 (message "Prefetched %d/%d message(s) in \"%s\"."
2629 (wl-folder-get-petname (car entity)))
2630 (cons sum-done sum-all)))
2632 (let ((nums (wl-folder-get-entity-info entity))
2633 (wl-summary-highlight (if (or (wl-summary-sticky-p entity)
2634 (wl-summary-always-sticky-folder-p
2636 wl-summary-highlight))
2637 wl-summary-exit-next-move
2638 wl-auto-select-first ret-val
2640 (setq count (or (car nums) 0))
2641 (setq count (+ count (wl-folder-count-incorporates entity)))
2642 (if (or (null (car nums)) ; unknown
2644 (let ((wl-summary-buffer-name (concat
2645 wl-summary-buffer-name
2646 (symbol-name this-command)))
2647 (wl-summary-use-frame nil)
2648 (wl-message-buf-name (concat wl-message-buf-name
2649 (symbol-name this-command))))
2650 (save-window-excursion
2652 (wl-summary-goto-folder-subr entity
2653 (wl-summary-get-sync-range entity)
2655 (setq ret-val (wl-summary-incorporate))
2660 (defun wl-folder-count-incorporates (folder)
2661 (let ((marks (elmo-msgdb-mark-load (elmo-msgdb-expand-path folder)))
2664 (if (member (cadr (car marks))
2665 wl-summary-incorporate-marks)
2667 (setq marks (cdr marks)))
2670 (defun wl-folder-prefetch-current-entity (&optional no-check)
2671 "Prefetch all uncached messages in the folder at position.
2672 If current line is group folder, all subfolders are prefetched."
2675 (let ((entity-name (wl-folder-get-entity-from-buffer))
2676 (group (wl-folder-buffer-group-p))
2677 wl-folder-check-entity-hook
2682 (wl-folder-search-group-entity-by-name entity-name
2686 (wl-folder-check-entity entity))
2687 (wl-folder-prefetch-entity entity)))))
2689 (defun wl-folder-drop-unsync-entity (entity)
2690 "Drop all unsync messages in the ENTITY."
2693 (let ((flist (nth 2 entity)))
2695 (wl-folder-drop-unsync-entity (car flist))
2696 (setq flist (cdr flist)))))
2698 (let ((nums (wl-folder-get-entity-info entity))
2699 wl-summary-highlight wl-auto-select-first new)
2700 (setq new (or (car nums) 0))
2702 (let ((wl-summary-buffer-name (concat
2703 wl-summary-buffer-name
2704 (symbol-name this-command)))
2705 (wl-summary-use-frame nil)
2706 (wl-message-buf-name (concat wl-message-buf-name
2707 (symbol-name this-command))))
2708 (save-window-excursion
2710 (wl-summary-goto-folder-subr entity 'no-sync nil)
2711 (wl-summary-drop-unsync)
2712 (wl-summary-exit)))))))))
2714 (defun wl-folder-drop-unsync-current-entity (&optional force-check)
2715 "Drop all unsync messages in the folder at position.
2716 If current line is group folder, all subfolders are dropped.
2717 If optional arg exists, don't check any folders."
2720 (let ((entity-name (wl-folder-get-entity-from-buffer))
2721 (group (wl-folder-buffer-group-p))
2722 wl-folder-check-entity-hook
2724 (when (and entity-name
2726 "Drop all unsync messages in %s?" entity-name)))
2729 (wl-folder-search-group-entity-by-name entity-name
2732 (if (null force-check)
2733 (wl-folder-check-entity entity))
2734 (wl-folder-drop-unsync-entity entity)
2735 (message "All unsync messages in %s are dropped!" entity-name)))))
2737 (defun wl-folder-write-current-folder ()
2738 "Write message to current folder's newsgroup or mailing-list.
2739 Call `wl-summary-write-current-folder' with current folder name."
2741 (unless (wl-folder-buffer-group-p)
2742 (wl-summary-write-current-folder
2743 (wl-folder-get-realname (wl-folder-entity-name)))))
2745 (defun wl-folder-mimic-kill-buffer ()
2746 "Kill the current (Folder) buffer with query."
2748 (let ((bufname (read-buffer (format "Kill buffer: (default %s) "
2750 wl-interactive-exit)
2751 (if (or (not bufname)
2752 (string-equal bufname "")
2753 (string-equal bufname (buffer-name)))
2755 (kill-buffer bufname))))
2757 (defun wl-folder-create-subr (entity)
2758 (if (not (elmo-folder-creatable-p entity))
2759 (error "Folder %s is not found" entity)
2761 (format "Folder %s does not exist, create it?"
2764 (setq wl-folder-entity-hashtb
2765 (wl-folder-create-entity-hashtb
2766 entity wl-folder-entity-hashtb))
2767 (unless (elmo-create-folder entity)
2768 (error "Create folder failed")))
2769 (error "Folder %s is not created" entity))))
2771 (defun wl-folder-confirm-existence (folder &optional force)
2773 (unless (elmo-folder-exists-p folder)
2774 (wl-folder-create-subr folder))
2775 (unless (or (wl-folder-entity-exists-p folder)
2776 (file-exists-p (elmo-msgdb-expand-path folder))
2777 (elmo-folder-exists-p folder))
2778 (wl-folder-create-subr folder))))
2781 (product-provide (provide 'wl-folder) (require 'wl-version))
2783 ;;; wl-folder.el ends here