* mh-acros.el:
[bpt/emacs.git] / lisp / mh-e / mh-speed.el
CommitLineData
bdcfe844
BW
1;;; mh-speed.el --- Speedbar interface for MH-E.
2
44d55491 3;; Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
bdcfe844 4
c3d9274a 5;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
bdcfe844
BW
6;; Maintainer: Bill Wohler <wohler@newt.com>
7;; Keywords: mail
8;; See: mh-e.el
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs 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)
15;; any later version.
16
17;; GNU Emacs 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.
21
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
3a35cf56
LK
24;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25;; Boston, MA 02110-1301, USA.
bdcfe844
BW
26
27;;; Commentary:
28;; Future versions should only use flists.
29
30;; Speedbar support for MH-E package.
31
32;;; Change Log:
33
bdcfe844
BW
34;;; Code:
35
36;; Requires
f0d73c14 37(eval-when-compile (require 'mh-acros))
a66894d8 38(mh-require-cl)
bdcfe844
BW
39(require 'mh-e)
40(require 'speedbar)
f0d73c14 41(require 'timer)
bdcfe844 42
bdcfe844
BW
43;; Global variables
44(defvar mh-speed-refresh-flag nil)
45(defvar mh-speed-last-selected-folder nil)
46(defvar mh-speed-folder-map (make-hash-table :test #'equal))
bdcfe844
BW
47(defvar mh-speed-flists-cache (make-hash-table :test #'equal))
48(defvar mh-speed-flists-process nil)
49(defvar mh-speed-flists-timer nil)
50(defvar mh-speed-partial-line "")
51
52;; Add our stealth update function
53(unless (member 'mh-speed-stealth-update
54 (cdr (assoc "files" speedbar-stealthy-function-list)))
55 ;; Is changing constant lists in elisp safe?
56 (setq speedbar-stealthy-function-list
57 (copy-tree speedbar-stealthy-function-list))
58 (push 'mh-speed-stealth-update
59 (cdr (assoc "files" speedbar-stealthy-function-list))))
60
61;; Functions called by speedbar to initialize display...
c3d9274a 62;;;###mh-autoload
bdcfe844
BW
63(defun mh-folder-speedbar-buttons (buffer)
64 "Interface function to create MH-E speedbar buffer.
65BUFFER is the MH-E buffer for which the speedbar buffer is to be created."
66 (unless (get-text-property (point-min) 'mh-level)
67 (erase-buffer)
68 (clrhash mh-speed-folder-map)
69 (speedbar-make-tag-line 'bracket ?+ 'mh-speed-toggle nil " " 'ignore nil
44d55491 70 'mh-speedbar-folder 0)
bdcfe844
BW
71 (forward-line -1)
72 (setf (gethash nil mh-speed-folder-map)
924df208
BW
73 (set-marker (or (gethash nil mh-speed-folder-map) (make-marker))
74 (1+ (line-beginning-position))))
bdcfe844
BW
75 (add-text-properties
76 (line-beginning-position) (1+ (line-beginning-position))
77 `(mh-folder nil mh-expanded nil mh-children-p t mh-level 0))
78 (mh-speed-stealth-update t)
6b960c10 79 (when (> mh-speed-update-interval 0)
bdcfe844
BW
80 (mh-speed-flists nil))))
81
c3d9274a 82;;;###mh-autoload
bdcfe844 83(defalias 'mh-show-speedbar-buttons 'mh-folder-speedbar-buttons)
c3d9274a 84;;;###mh-autoload
bdcfe844
BW
85(defalias 'mh-letter-speedbar-buttons 'mh-folder-speedbar-buttons)
86
87;; Keymaps for speedbar...
88(defvar mh-folder-speedbar-key-map (speedbar-make-specialized-keymap)
89 "Specialized speedbar keymap for MH-E buffers.")
90(gnus-define-keys mh-folder-speedbar-key-map
c3d9274a
BW
91 "+" mh-speed-expand-folder
92 "-" mh-speed-contract-folder
93 "\r" mh-speed-view
f0d73c14 94 "r" mh-speed-refresh)
bdcfe844
BW
95
96(defvar mh-show-speedbar-key-map mh-folder-speedbar-key-map)
bdcfe844
BW
97(defvar mh-letter-speedbar-key-map mh-folder-speedbar-key-map)
98
99;; Menus for speedbar...
100(defvar mh-folder-speedbar-menu-items
f0d73c14
BW
101 '("--"
102 ["Visit Folder" mh-speed-view
bdcfe844
BW
103 (save-excursion
104 (set-buffer speedbar-buffer)
105 (get-text-property (line-beginning-position) 'mh-folder))]
f0d73c14 106 ["Expand Nested Folders" mh-speed-expand-folder
bdcfe844
BW
107 (and (get-text-property (line-beginning-position) 'mh-children-p)
108 (not (get-text-property (line-beginning-position) 'mh-expanded)))]
f0d73c14 109 ["Contract Nested Folders" mh-speed-contract-folder
bdcfe844
BW
110 (and (get-text-property (line-beginning-position) 'mh-children-p)
111 (get-text-property (line-beginning-position) 'mh-expanded))]
f0d73c14 112 ["Refresh Speedbar" mh-speed-refresh t])
bdcfe844
BW
113 "Extra menu items for speedbar.")
114
115(defvar mh-show-speedbar-menu-items mh-folder-speedbar-menu-items)
bdcfe844
BW
116(defvar mh-letter-speedbar-menu-items mh-folder-speedbar-menu-items)
117
118(defmacro mh-speed-select-attached-frame ()
119 "Compatibility macro to handle speedbar versions 0.11a and 0.14beta4."
120 (cond ((fboundp 'dframe-select-attached-frame)
121 '(dframe-select-attached-frame speedbar-frame))
122 ((boundp 'speedbar-attached-frame)
123 '(select-frame speedbar-attached-frame))
124 (t (error "Installed speedbar version not supported by MH-E"))))
125
126(defun mh-speed-update-current-folder (force)
127 "Update speedbar highlighting of the current folder.
128The function tries to be smart so that work done is minimized. The currently
129highlighted folder is cached and no highlighting happens unless it changes.
130Also highlighting is suspended while the speedbar frame is selected.
131Otherwise you get the disconcerting behavior of folders popping open on their
132own when you are trying to navigate around in the speedbar buffer.
133
134The update is always carried out if FORCE is non-nil."
135 (let* ((lastf (selected-frame))
c3d9274a 136 (newcf (save-excursion
bdcfe844
BW
137 (mh-speed-select-attached-frame)
138 (prog1 (mh-speed-extract-folder-name (buffer-name))
139 (select-frame lastf))))
c3d9274a
BW
140 (lastb (current-buffer))
141 (case-fold-search t))
bdcfe844
BW
142 (when (or force
143 (and mh-speed-refresh-flag (not (eq lastf speedbar-frame)))
144 (and (stringp newcf)
145 (equal (substring newcf 0 1) "+")
146 (not (equal newcf mh-speed-last-selected-folder))))
147 (setq mh-speed-refresh-flag nil)
148 (select-frame speedbar-frame)
149 (set-buffer speedbar-buffer)
150
151 ;; Remove highlight from previous match...
44d55491 152 (mh-speed-highlight mh-speed-last-selected-folder 'mh-speedbar-folder)
bdcfe844
BW
153
154 ;; If we found a match highlight it...
155 (when (mh-speed-goto-folder newcf)
44d55491 156 (mh-speed-highlight newcf 'mh-speedbar-selected-folder))
bdcfe844
BW
157
158 (setq mh-speed-last-selected-folder newcf)
159 (speedbar-position-cursor-on-line)
160 (set-window-point (frame-first-window speedbar-frame) (point))
161 (set-buffer lastb)
162 (select-frame lastf))
163 (when (eq lastf speedbar-frame)
164 (setq mh-speed-refresh-flag t))))
165
166(defun mh-speed-normal-face (face)
167 "Return normal face for given FACE."
44d55491
MB
168 (cond ((eq face 'mh-speedbar-folder-with-unseen-messages)
169 'mh-speedbar-folder)
170 ((eq face 'mh-speedbar-selected-folder-with-unseen-messages)
171 'mh-speedbar-selected-folder)
bdcfe844
BW
172 (t face)))
173
174(defun mh-speed-bold-face (face)
175 "Return bold face for given FACE."
44d55491
MB
176 (cond ((eq face 'mh-speedbar-folder)
177 'mh-speedbar-folder-with-unseen-messages)
178 ((eq face 'mh-speedbar-selected-folder)
179 'mh-speedbar-selected-folder-with-unseen-messages)
bdcfe844
BW
180 (t face)))
181
182(defun mh-speed-highlight (folder face)
183 "Set FOLDER to FACE."
184 (save-excursion
185 (speedbar-with-writable
186 (goto-char (gethash folder mh-speed-folder-map (point)))
187 (beginning-of-line)
188 (if (re-search-forward "([1-9][0-9]*/[0-9]+)" (line-end-position) t)
189 (setq face (mh-speed-bold-face face))
190 (setq face (mh-speed-normal-face face)))
191 (beginning-of-line)
192 (when (re-search-forward "\\[.\\] " (line-end-position) t)
193 (put-text-property (point) (line-end-position) 'face face)))))
194
195(defun mh-speed-stealth-update (&optional force)
196 "Do stealth update.
197With non-nil FORCE, the update is always carried out."
198 (cond ((save-excursion (set-buffer speedbar-buffer)
199 (get-text-property (point-min) 'mh-level))
200 ;; Execute this hook and *don't* run anything else
201 (mh-speed-update-current-folder force)
202 nil)
203 ;; Otherwise on to your regular programming
204 (t t)))
205
206(defun mh-speed-goto-folder (folder)
207 "Move point to line containing FOLDER.
208The function will expand out parent folders of FOLDER if needed."
209 (let ((prefix folder)
210 (suffix-list ())
211 (last-slash t))
212 (while (and (not (gethash prefix mh-speed-folder-map)) last-slash)
c3d9274a 213 (setq last-slash (mh-search-from-end ?/ prefix))
bdcfe844
BW
214 (when (integerp last-slash)
215 (push (substring prefix (1+ last-slash)) suffix-list)
216 (setq prefix (substring prefix 0 last-slash))))
217 (let ((prefix-position (gethash prefix mh-speed-folder-map)))
218 (if prefix-position
219 (goto-char prefix-position)
220 (goto-char (point-min))
221 (mh-speed-toggle)
222 (unless (get-text-property (point) 'mh-expanded)
223 (mh-speed-toggle))
224 (goto-char (gethash prefix mh-speed-folder-map))))
225 (while suffix-list
226 ;; We always need atleast one toggle. We need two if the directory list
227 ;; is stale since a folder was added.
228 (when (equal prefix (get-text-property (line-beginning-position)
229 'mh-folder))
230 (mh-speed-toggle)
231 (unless (get-text-property (point) 'mh-expanded)
232 (mh-speed-toggle)))
233 (setq prefix (format "%s/%s" prefix (pop suffix-list)))
234 (goto-char (gethash prefix mh-speed-folder-map (point))))
235 (beginning-of-line)
236 (equal folder (get-text-property (point) 'mh-folder))))
237
238(defun mh-speed-extract-folder-name (buffer)
239 "Given an MH-E BUFFER find the folder that should be highlighted.
240Do the right thing for the different kinds of buffers that MH-E uses."
241 (save-excursion
242 (set-buffer buffer)
243 (cond ((eq major-mode 'mh-folder-mode)
244 mh-current-folder)
245 ((eq major-mode 'mh-show-mode)
246 (set-buffer mh-show-folder-buffer)
247 mh-current-folder)
c3d9274a 248 ((eq major-mode 'mh-letter-mode)
bdcfe844
BW
249 (when (string-match mh-user-path buffer-file-name)
250 (let* ((rel-path (substring buffer-file-name (match-end 0)))
c3d9274a 251 (directory-end (mh-search-from-end ?/ rel-path)))
bdcfe844
BW
252 (when directory-end
253 (format "+%s" (substring rel-path 0 directory-end)))))))))
254
255(defun mh-speed-add-buttons (folder level)
256 "Add speedbar button for FOLDER which is at indented by LEVEL amount."
3d7ca223 257 (let ((folder-list (mh-sub-folders folder)))
bdcfe844
BW
258 (mapc
259 (lambda (f)
260 (let* ((folder-name (format "%s%s%s" (or folder "+")
261 (if folder "/" "") (car f)))
262 (counts (gethash folder-name mh-speed-flists-cache)))
263 (speedbar-with-writable
264 (speedbar-make-tag-line
265 'bracket (if (cdr f) ?+ ? )
266 'mh-speed-toggle nil
267 (format "%s%s"
268 (car f)
269 (if counts
270 (format " (%s/%s)" (car counts) (cdr counts))
271 ""))
272 'mh-speed-view nil
273 (if (and counts (> (car counts) 0))
44d55491
MB
274 'mh-speedbar-folder-with-unseen-messages
275 'mh-speedbar-folder)
bdcfe844
BW
276 level)
277 (save-excursion
278 (forward-line -1)
279 (setf (gethash folder-name mh-speed-folder-map)
924df208
BW
280 (set-marker (or (gethash folder-name mh-speed-folder-map)
281 (make-marker))
282 (1+ (line-beginning-position))))
bdcfe844
BW
283 (add-text-properties
284 (line-beginning-position) (1+ (line-beginning-position))
285 `(mh-folder ,folder-name
c3d9274a
BW
286 mh-expanded nil
287 mh-children-p ,(not (not (cdr f)))
288 ,@(if counts `(mh-count
289 (,(car counts) . ,(cdr counts))) ())
290 mh-level ,level))))))
bdcfe844
BW
291 folder-list)))
292
c3d9274a 293;;;###mh-autoload
bdcfe844 294(defun mh-speed-toggle (&rest args)
6b960c10
BW
295 "Toggle the display of child folders in the speedbar.
296The optional ARGS from speedbar are ignored."
bdcfe844
BW
297 (interactive)
298 (declare (ignore args))
299 (beginning-of-line)
300 (let ((parent (get-text-property (point) 'mh-folder))
301 (kids-p (get-text-property (point) 'mh-children-p))
302 (expanded (get-text-property (point) 'mh-expanded))
303 (level (get-text-property (point) 'mh-level))
304 (point (point))
305 start-region)
306 (speedbar-with-writable
307 (cond ((not kids-p) nil)
308 (expanded
309 (forward-line)
310 (setq start-region (point))
311 (while (and (get-text-property (point) 'mh-level)
312 (> (get-text-property (point) 'mh-level) level))
924df208
BW
313 (let ((folder (get-text-property (point) 'mh-folder)))
314 (when (gethash folder mh-speed-folder-map)
315 (set-marker (gethash folder mh-speed-folder-map) nil)
316 (remhash folder mh-speed-folder-map)))
bdcfe844
BW
317 (forward-line))
318 (delete-region start-region (point))
319 (forward-line -1)
320 (speedbar-change-expand-button-char ?+)
321 (add-text-properties
322 (line-beginning-position) (1+ (line-beginning-position))
323 '(mh-expanded nil)))
324 (t
325 (forward-line)
326 (mh-speed-add-buttons parent (1+ level))
327 (goto-char point)
328 (speedbar-change-expand-button-char ?-)
329 (add-text-properties
330 (line-beginning-position) (1+ (line-beginning-position))
331 `(mh-expanded t)))))))
332
333(defalias 'mh-speed-expand-folder 'mh-speed-toggle)
334(defalias 'mh-speed-contract-folder 'mh-speed-toggle)
335
c3d9274a 336;;;###mh-autoload
bdcfe844 337(defun mh-speed-view (&rest args)
6b960c10
BW
338 "Visits the selected folder just as if you had used \\<mh-folder-mode-map>\\[mh-visit-folder].
339The optional ARGS from speedbar are ignored."
bdcfe844
BW
340 (interactive)
341 (declare (ignore args))
342 (let* ((folder (get-text-property (line-beginning-position) 'mh-folder))
a66894d8
BW
343 (range (and (stringp folder)
344 (mh-read-range "Scan" folder t nil nil
345 mh-interpret-number-as-range-flag))))
bdcfe844
BW
346 (when (stringp folder)
347 (speedbar-with-attached-buffer
348 (mh-visit-folder folder range)
349 (delete-other-windows)))))
350
3d7ca223 351(defvar mh-speed-current-folder nil)
924df208 352(defvar mh-speed-flists-folder nil)
bdcfe844 353
f0d73c14
BW
354(defmacro mh-process-kill-without-query (process)
355 "PROCESS can be killed without query on Emacs exit.
356Avoid using `process-kill-without-query' if possible since it is now
357obsolete."
358 (if (fboundp 'set-process-query-on-exit-flag)
359 `(set-process-query-on-exit-flag ,process nil)
360 `(process-kill-without-query ,process)))
361
c3d9274a 362;;;###mh-autoload
a66894d8 363(defun mh-speed-flists (force &rest folders)
bdcfe844 364 "Execute flists -recurse and update message counts.
a66894d8
BW
365If FORCE is non-nil the timer is reset.
366
367Any number of optional FOLDERS can be specified. If specified, flists is run
924df208 368only for that one folder."
bdcfe844
BW
369 (interactive (list t))
370 (when force
924df208
BW
371 (when mh-speed-flists-timer
372 (cancel-timer mh-speed-flists-timer)
373 (setq mh-speed-flists-timer nil))
bdcfe844
BW
374 (when (and (processp mh-speed-flists-process)
375 (not (eq (process-status mh-speed-flists-process) 'exit)))
924df208 376 (set-process-filter mh-speed-flists-process t)
bdcfe844 377 (kill-process mh-speed-flists-process)
924df208 378 (setq mh-speed-partial-line "")
bdcfe844 379 (setq mh-speed-flists-process nil)))
a66894d8 380 (setq mh-speed-flists-folder folders)
bdcfe844
BW
381 (unless mh-speed-flists-timer
382 (setq mh-speed-flists-timer
383 (run-at-time
6b960c10
BW
384 nil (if (> mh-speed-update-interval 0)
385 mh-speed-update-interval
386 nil)
bdcfe844
BW
387 (lambda ()
388 (unless (and (processp mh-speed-flists-process)
389 (not (eq (process-status mh-speed-flists-process)
390 'exit)))
3d7ca223
BW
391 (setq mh-speed-current-folder
392 (concat
a66894d8
BW
393 (if mh-speed-flists-folder
394 (substring (car (reverse mh-speed-flists-folder)) 1)
395 (with-temp-buffer
396 (call-process (expand-file-name "folder" mh-progs)
397 nil '(t nil) nil "-fast")
398 (buffer-substring (point-min) (1- (point-max)))))
3d7ca223 399 "+"))
bdcfe844 400 (setq mh-speed-flists-process
a66894d8
BW
401 (apply #'start-process "*flists*" nil
402 (expand-file-name "flists" mh-progs)
403 (if mh-speed-flists-folder "-noall" "-all")
404 "-sequence" (symbol-name mh-unseen-seq)
405 (or mh-speed-flists-folder '("-recurse"))))
924df208
BW
406 ;; Run flists on all folders the next time around...
407 (setq mh-speed-flists-folder nil)
f0d73c14 408 (mh-process-kill-without-query mh-speed-flists-process)
bdcfe844
BW
409 (set-process-filter mh-speed-flists-process
410 'mh-speed-parse-flists-output)))))))
411
412;; Copied from mh-make-folder-list-filter...
413(defun mh-speed-parse-flists-output (process output)
414 "Parse the incremental results from flists.
415PROCESS is the flists process and OUTPUT is the results that must be handled
416next."
417 (let ((prevailing-match-data (match-data))
418 (position 0)
419 line-end line folder unseen total)
420 (unwind-protect
421 (while (setq line-end (string-match "\n" output position))
422 (setq line (format "%s%s"
423 mh-speed-partial-line
424 (substring output position line-end))
425 mh-speed-partial-line "")
c3d9274a 426 (multiple-value-setq (folder unseen total)
3d7ca223 427 (mh-parse-flist-output-line line mh-speed-current-folder))
924df208
BW
428 (when (and folder unseen total
429 (let ((old-pair (gethash folder mh-speed-flists-cache)))
430 (or (not (equal (car old-pair) unseen))
431 (not (equal (cdr old-pair) total)))))
c3d9274a
BW
432 (setf (gethash folder mh-speed-flists-cache) (cons unseen total))
433 (save-excursion
434 (when (buffer-live-p (get-buffer speedbar-buffer))
435 (set-buffer speedbar-buffer)
436 (speedbar-with-writable
437 (when (get-text-property (point-min) 'mh-level)
438 (let ((pos (gethash folder mh-speed-folder-map))
439 face)
440 (when pos
441 (goto-char pos)
442 (goto-char (line-beginning-position))
443 (cond
444 ((null (get-text-property (point) 'mh-count))
445 (goto-char (line-end-position))
446 (setq face (get-text-property (1- (point)) 'face))
447 (insert (format " (%s/%s)" unseen total))
448 (mh-speed-highlight 'unknown face)
449 (goto-char (line-beginning-position))
450 (add-text-properties (point) (1+ (point))
451 `(mh-count (,unseen . ,total))))
452 ((not (equal (get-text-property (point) 'mh-count)
453 (cons unseen total)))
454 (goto-char (line-end-position))
455 (setq face (get-text-property (1- (point)) 'face))
456 (re-search-backward " " (line-beginning-position) t)
457 (delete-region (point) (line-end-position))
458 (insert (format " (%s/%s)" unseen total))
459 (mh-speed-highlight 'unknown face)
460 (goto-char (line-beginning-position))
461 (add-text-properties
462 (point) (1+ (point))
463 `(mh-count (,unseen . ,total))))))))))))
bdcfe844
BW
464 (setq position (1+ line-end)))
465 (set-match-data prevailing-match-data))
c3d9274a 466 (setq mh-speed-partial-line (substring output position))))
bdcfe844 467
c3d9274a 468;;;###mh-autoload
bdcfe844
BW
469(defun mh-speed-invalidate-map (folder)
470 "Remove FOLDER from various optimization caches."
471 (interactive (list ""))
472 (save-excursion
473 (set-buffer speedbar-buffer)
474 (let* ((speedbar-update-flag nil)
c3d9274a 475 (last-slash (mh-search-from-end ?/ folder))
bdcfe844
BW
476 (parent (if last-slash (substring folder 0 last-slash) nil))
477 (parent-position (gethash parent mh-speed-folder-map))
478 (parent-change nil))
bdcfe844 479 (when parent-position
3d7ca223 480 (let ((parent-kids (mh-sub-folders parent)))
bdcfe844
BW
481 (cond ((null parent-kids)
482 (setq parent-change ?+))
483 ((and (null (cdr parent-kids))
484 (equal (if last-slash
485 (substring folder (1+ last-slash))
486 (substring folder 1))
487 (caar parent-kids)))
488 (setq parent-change ? ))))
489 (goto-char parent-position)
490 (when (equal (get-text-property (line-beginning-position) 'mh-folder)
491 parent)
492 (when (get-text-property (line-beginning-position) 'mh-expanded)
493 (mh-speed-toggle))
494 (when parent-change
495 (speedbar-with-writable
496 (mh-speedbar-change-expand-button-char parent-change)
497 (add-text-properties
498 (line-beginning-position) (1+ (line-beginning-position))
499 `(mh-children-p ,(equal parent-change ?+)))))
44d55491 500 (mh-speed-highlight mh-speed-last-selected-folder 'mh-speedbar-folder)
bdcfe844
BW
501 (setq mh-speed-last-selected-folder nil)
502 (setq mh-speed-refresh-flag t)))
503 (when (equal folder "")
3d7ca223 504 (clrhash mh-sub-folders-cache)))))
bdcfe844 505
f0d73c14 506(defun mh-speed-refresh ()
6b960c10
BW
507 "Regenerates the list of folders in the speedbar.
508
509Run this command if you've added or deleted a folder, or want to update the
510unseen message count before the next automatic update."
f0d73c14
BW
511 (interactive)
512 (mh-speed-flists t)
513 (mh-speed-invalidate-map ""))
514
c3d9274a 515;;;###mh-autoload
bdcfe844
BW
516(defun mh-speed-add-folder (folder)
517 "Add FOLDER since it is being created.
518The function invalidates the latest ancestor that is present."
519 (save-excursion
520 (set-buffer speedbar-buffer)
521 (let ((speedbar-update-flag nil)
c3d9274a 522 (last-slash (mh-search-from-end ?/ folder))
bdcfe844
BW
523 (ancestor folder)
524 (ancestor-pos nil))
525 (block while-loop
526 (while last-slash
527 (setq ancestor (substring ancestor 0 last-slash))
528 (setq ancestor-pos (gethash ancestor mh-speed-folder-map))
529 (when ancestor-pos
530 (return-from while-loop))
c3d9274a 531 (setq last-slash (mh-search-from-end ?/ ancestor))))
bdcfe844
BW
532 (unless ancestor-pos (setq ancestor nil))
533 (goto-char (or ancestor-pos (gethash nil mh-speed-folder-map)))
534 (speedbar-with-writable
535 (mh-speedbar-change-expand-button-char ?+)
536 (add-text-properties
537 (line-beginning-position) (1+ (line-beginning-position))
538 `(mh-children-p t)))
539 (when (get-text-property (line-beginning-position) 'mh-expanded)
540 (mh-speed-toggle))
bdcfe844
BW
541 (setq mh-speed-refresh-flag t))))
542
543;; Make it slightly more general to allow for [ ] buttons to be changed to
544;; [+].
545(defun mh-speedbar-change-expand-button-char (char)
546 "Change the expansion button character to CHAR for the current line."
547 (save-excursion
548 (beginning-of-line)
549 (if (re-search-forward "\\[.\\]" (line-end-position) t)
c3d9274a 550 (speedbar-with-writable
bdcfe844 551 (backward-char 2)
c3d9274a
BW
552 (delete-char 1)
553 (insert-char char 1 t)
554 (put-text-property (point) (1- (point)) 'invisible nil)
555 ;; make sure we fix the image on the text here.
924df208
BW
556 (mh-funcall-if-exists
557 speedbar-insert-image-button-maybe (- (point) 2) 3)))))
bdcfe844
BW
558
559(provide 'mh-speed)
560
cee9f5c6
BW
561;; Local Variables:
562;; indent-tabs-mode: nil
563;; sentence-end-double-space: nil
564;; End:
bdcfe844 565
cee9f5c6 566;; arch-tag: d38ddcd4-3c00-4e37-99bf-8b89dda7b32c
bdcfe844 567;;; mh-speed.el ends here