]> code.delx.au - gnu-emacs/blobdiff - lisp/speedbar.el
(blink-cursor-mode): `emacs-quick-startup' may not be bound yet.
[gnu-emacs] / lisp / speedbar.el
index 82492ff2e49b7c1a3779a3b36e2aa88fcbae6fbc..7a6e01f28599ace734e6be89ef554d180c900fdf 100644 (file)
@@ -1,6 +1,7 @@
 ;;; speedbar.el --- quick access to files and tags in a frame
 
-;;; Copyright (C) 1996, 97, 98, 99, 2000, 01 Free Software Foundation
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2005
+;;           Free Software Foundation
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Version: 0.11a
@@ -92,7 +93,7 @@
 ;; into sub-lists.  A long flat list can be used instead if needed.
 ;; Other filters can be easily added.
 ;;
-;;    AUC-TEX users: The imenu tags for AUC-TEX mode doesn't work very
+;;    AUCTEX users: The imenu tags for AUCTEX mode doesn't work very
 ;; well.  Use the imenu keywords from tex-mode.el for better results.
 ;;
 ;; This file requires the library package assoc (association lists)
 ;; - More functions to create buttons and options
 ;; - Timeout directories we haven't visited in a while.
 
+;;; Code:
+
 (require 'assoc)
 (require 'easymenu)
 
 ;; customization stuff
 (defgroup speedbar nil
   "File and tag browser frame."
-  :group 'tags
+  :group 'etags
   :group 'tools
   :group 'convenience
   :version "20.3")
   :prefix "speedbar-"
   :group 'speedbar)
 
-;;; Code:
 (defvar speedbar-initial-expansion-mode-alist
   '(("buffers" speedbar-buffer-easymenu-definition speedbar-buffers-key-map
      speedbar-buffer-buttons)
@@ -287,7 +289,7 @@ speedbar buffer.")
 (defvar speedbar-special-mode-key-map nil
   "Default keymap used when identifying a specialized display mode.
 This keymap is local to each buffer that wants to define special keybindings
-effective when it's display is shown.")
+effective when its display is shown.")
 
 (defcustom speedbar-visiting-file-hook nil
   "Hooks run when speedbar visits a file in the selected frame."
@@ -354,7 +356,9 @@ Any parameter supported by a frame may be added.  The parameter `height'
 will be initialized to the height of the frame speedbar is
 attached to and added to this list before the new frame is initialized."
   :group 'speedbar
-  :type '(repeat (sexp :tag "Parameter:")))
+  :type '(repeat (cons :format "%v"
+                      (symbol :tag "Parameter")
+                      (sexp :tag "Value"))))
 
 ;; These values by Hrvoje Niksic <hniksic@srce.hr>
 (defcustom speedbar-frame-plist
@@ -371,7 +375,7 @@ is attached to."
                        (symbol :tag "Property")
                        (sexp :tag "Value"))))
 
-(defcustom speedbar-use-imenu-flag (stringp (locate-library "imenu"))
+(defcustom speedbar-use-imenu-flag (fboundp 'imenu)
   "*Non-nil means use imenu for file parsing.  nil to use etags.
 XEmacs prior to 20.4 doesn't support imenu, therefore the default is to
 use etags instead.  Etags support is not as robust as imenu support."
@@ -382,12 +386,12 @@ use etags instead.  Etags support is not as robust as imenu support."
 (defvar speedbar-dynamic-tags-function-list
   '((speedbar-fetch-dynamic-imenu . speedbar-insert-imenu-list)
     (speedbar-fetch-dynamic-etags . speedbar-insert-etags-list))
-  "Set to a functions which will return and insert a list of tags.
+  "Set to a list of functions which will return and insert a list of tags.
 Each element is of the form ( FETCH .  INSERT ) where FETCH
-is a funciotn which takes one parameter (the file to tag) and returns a
+is a function which takes one parameter (the file to tag) and returns a
 list of tags.  The tag list can be of any form as long as the
 corresponding insert method can handle it.  If it returns t, then an
-error occured, and the next fetch routine is tried.
+error occurred, and the next fetch routine is tried.
 INSERT is a function which takes an INDENTation level, and a LIST of
 tags to insert.  It will then create the speedbar buttons.")
 
@@ -397,7 +401,7 @@ tags to insert.  It will then create the speedbar buttons.")
   :type 'boolean)
 
 (defcustom speedbar-sort-tags nil
-  "*If Non-nil, sort tags in the speedbar display.  *Obsolete*."
+  "*If non-nil, sort tags in the speedbar display.  *Obsolete*."
   :group 'speedbar
   :type 'boolean)
 
@@ -407,14 +411,14 @@ tags to insert.  It will then create the speedbar buttons.")
   "*List of hooks which speedbar will use to organize tags into groups.
 Groups are defined as expandable meta-tags.  Imenu supports
 such things in some languages, such as separating variables from
-functions.  Each hook takes one argument LST, and may destructivly
+functions.  Each hook takes one argument LST, and may destructively
 create a new list of the same form.  LST is a list of elements of the
 form:
   (ELT1 ELT2 ... ELTn)
 where each ELT is of the form
   (TAG-NAME-STRING . NUMBER-OR-MARKER)
 or
-  (GROUP-NAME-STRING ELT1 EL2... ELTn)"
+  (GROUP-NAME-STRING ELT1 ELT2... ELTn)"
   :group 'speedbar
   :type 'hook
   :options '(speedbar-sort-tag-hierarchy
@@ -497,7 +501,7 @@ hierarchy would be replaced with the new directory."
                                    (if (fboundp 'display-graphic-p)
                                        (display-graphic-p)
                                      window-system))
-  "*Non nil if speedbar should display icons."
+  "*Non-nil if speedbar should display icons."
   :group 'speedbar
   :version "21.1"
   :type 'boolean)
@@ -534,7 +538,7 @@ verbosity."
 
 (defcustom speedbar-vc-do-check t
   "*Non-nil check all files in speedbar to see if they have been checked out.
-Any file checked out is marked with `speedbar-vc-indicator'"
+Any file checked out is marked with `speedbar-vc-indicator'."
   :group 'speedbar-vc
   :type 'boolean)
 
@@ -563,7 +567,7 @@ current file, and the FILENAME of the file being checked."
 (defcustom speedbar-obj-do-check t
   "*Non-nil check all files in speedbar to see if they have an object file.
 Any file checked out is marked with `speedbar-obj-indicator', and the
-marking is based on  `speedbar-obj-alist'"
+marking is based on `speedbar-obj-alist'."
   :group 'speedbar-vc
   :type 'boolean)
 
@@ -665,6 +669,9 @@ useful, such as version control."
   "*Regexp matching files we don't want displayed in a speedbar buffer.
 It is generated from the variable `completion-ignored-extensions'")
 
+;; Compiler silencing trick.  The real defvar comes later in this file.
+(defvar speedbar-file-regexp)
+
 ;; this is dangerous to customize, because the defaults will probably
 ;; change in the future.
 (defcustom speedbar-supported-extension-expressions
@@ -689,8 +696,7 @@ file."
   :type '(repeat (regexp :tag "Extension Regexp"))
   :set (lambda (sym val)
         (setq speedbar-supported-extension-expressions val
-              speedbar-file-regexp (speedbar-extension-list-to-regex val)))
-  )
+              speedbar-file-regexp (speedbar-extension-list-to-regex val))))
 
 (defvar speedbar-file-regexp
   (speedbar-extension-list-to-regex speedbar-supported-extension-expressions)
@@ -698,13 +704,22 @@ file."
 Created from `speedbar-supported-extension-expression' with the
 function `speedbar-extension-list-to-regex'")
 
+(defcustom speedbar-scan-subdirs nil
+  "*Non-nil means speedbar will check if subdirs are empty.
+That way you don't have to click on them to find out.  But this
+incurs extra I/O, hence it slows down directory display
+proportionally to the number of subdirs."
+  :group 'speedbar
+  :type 'boolean
+  :version 22.1)
+
 (defun speedbar-add-supported-extension (extension)
   "Add EXTENSION as a new supported extension for speedbar tagging.
 This should start with a `.' if it is not a complete file name, and
 the dot should NOT be quoted in with \\.  Other regular expression
 matchers are allowed however.  EXTENSION may be a single string or a
 list of strings."
-  (interactive "sExtionsion: ")
+  (interactive "sExtension: ")
   (if (not (listp extension)) (setq extension (list extension)))
   (while extension
     (if (member (car extension) speedbar-supported-extension-expressions)
@@ -746,11 +761,9 @@ PATH-EXPRESSION to `speedbar-ignored-path-expressions'."
                                  (display-graphic-p)
                                window-system))
   "*Non-nil means to automatically update the display.
-When this is nil then speedbar will not follow the attached frame's path.
-When speedbar is active, use:
-
-\\<speedbar-key-map> `\\[speedbar-toggle-updates]'
-
+When this is nil then speedbar will not follow the attached
+frame's path.  Type \
+\\<speedbar-key-map>\\[speedbar-toggle-updates] in the speedbar \
 to toggle this value.")
 
 (defvar speedbar-syntax-table nil
@@ -847,7 +860,7 @@ to toggle this value.")
    ))
 
 (defun speedbar-make-specialized-keymap ()
-  "Create a keymap for use w/ a speedbar major or minor display mode.
+  "Create a keymap for use with a speedbar major or minor display mode.
 This basically creates a sparse keymap, and makes it's parent be
 `speedbar-key-map'."
   (let ((k (make-sparse-keymap)))
@@ -932,7 +945,7 @@ This basically creates a sparse keymap, and makes it's parent be
                     (looking-at "[0-9]+: *\\[[+-]\\] [^ \n]+ \\*?[!#]$"))]
     )
   "Additional menu items while in file-mode.")
+
 (defvar speedbar-easymenu-definition-trailer
   (append
    (if (and (featurep 'custom) (fboundp 'custom-declare-variable))
@@ -943,7 +956,7 @@ This basically creates a sparse keymap, and makes it's parent be
   "Menu items appearing at the end of the speedbar menu.")
 
 (defvar speedbar-desired-buffer nil
-  "Non-nil when speedbar is showing buttons specific a special mode.
+  "Non-nil when speedbar is showing buttons specific to a special mode.
 In this case it is the originating buffer.")
 (defvar speedbar-buffer nil
   "The buffer displaying the speedbar.")
@@ -981,7 +994,7 @@ directories.")
 (if (fboundp 'frame-parameter)
 
     (defalias 'speedbar-frame-parameter 'frame-parameter)
-  
+
   (defun speedbar-frame-parameter (frame parameter)
     "Return FRAME's PARAMETER value."
     (cdr (assoc parameter (frame-parameters frame)))))
@@ -1215,13 +1228,13 @@ Files are completely ignored if they match `speedbar-file-unshown-regexp'
 which is generated from `completion-ignored-extensions'.
 
 Files with a `*' character after their name are files checked out of a
-version control system.  (currently only RCS is supported.)  New
+version control system.  (Currently only RCS is supported.)  New
 version control systems can be added by examining the documentation
-for `speedbar-this-file-in-vc' and `speedbar-vc-check-dir-p'
+for `speedbar-this-file-in-vc' and `speedbar-vc-check-dir-p'.
 
 Files with a `#' or `!' character after them are source files that
 have an object file associated with them.  The `!' indicates that the
-files is out of date.   You can control what source/object associations
+files is out of date.  You can control what source/object associations
 exist through the variable `speedbar-obj-alist'.
 
 Click on the [+] to display a list of tags from that file.  Click on
@@ -1277,7 +1290,6 @@ in the selected file.
                               (speedbar-quick-mouse event)))
                        ;; Don't do normal operations.
                        t)))))
-    (make-local-hook 'kill-buffer-hook)
     (add-hook 'kill-buffer-hook (lambda () (let ((skilling (boundp 'skilling)))
                                             (if skilling
                                                 nil
@@ -1288,8 +1300,9 @@ in the selected file.
     (toggle-read-only 1)
     (speedbar-set-mode-line-format)
     (if speedbar-xemacsp
-       (set (make-local-variable 'mouse-motion-handler)
-            'speedbar-track-mouse-xemacs)
+       (with-no-warnings
+        (set (make-local-variable 'mouse-motion-handler)
+             'speedbar-track-mouse-xemacs))
       (if speedbar-track-mouse-flag
          (set (make-local-variable 'track-mouse) t))   ;this could be messy.
       (setq auto-show-mode nil))       ;no auto-show for Emacs
@@ -1329,7 +1342,7 @@ Optional EVENT is currently not used."
     (if (equal (car pos) speedbar-frame)
        (save-excursion
          (save-window-excursion
-           (apply 'set-mouse-position pos)
+           (apply 'set-mouse-position (list (car pos) (cadr pos) (cddr pos)))
            (speedbar-item-info))))))
 
 (defun speedbar-set-mode-line-format ()
@@ -1338,7 +1351,8 @@ This gives visual indications of what is up.  It EXPECTS the speedbar
 frame and window to be the currently active frame and window."
   (if (and (frame-live-p speedbar-frame)
           (or (not speedbar-xemacsp)
-              (specifier-instance has-modeline-p)))
+              (with-no-warnings
+               (specifier-instance has-modeline-p))))
       (save-excursion
        (set-buffer speedbar-buffer)
        (let* ((w (or (speedbar-frame-width) 20))
@@ -1455,7 +1469,7 @@ and the existence of packages."
 (defun speedbar-mouse-hscroll (e)
   "Read a mouse event E from the mode line, and horizontally scroll.
 If the mouse is being clicked on the far left, or far right of the
-mode-line.  This is only useful for non-XEmacs"
+mode-line.  This is only useful for non-XEmacs."
   (interactive "e")
   (let* ((xp (car (nth 2 (car (cdr e)))))
         (cpw (/ (frame-pixel-width)
@@ -1539,9 +1553,7 @@ Must be bound to event E."
     ;; This gets the cursor where the user can see it.
     (if (not (bolp)) (forward-char -1))
     (sit-for 0)
-    (if (< emacs-major-version 20)
-       (mouse-major-mode-menu e)
-      (mouse-major-mode-menu e nil))))
+    (mouse-major-mode-menu e nil)))
 
 (defun speedbar-hack-buffer-menu (e)
   "Control mouse 1 is buffer menu.
@@ -1666,7 +1678,7 @@ files, or the directory button."
 
 (defun speedbar-up-directory ()
   "Keyboard accelerator for moving the default directory up one.
-Assumes that the current buffer is the speedbar buffer"
+Assumes that the current buffer is the speedbar buffer."
   (interactive)
   (setq default-directory (expand-file-name (concat default-directory "../")))
   (speedbar-update-contents))
@@ -1677,7 +1689,7 @@ Assumes that the current buffer is the speedbar buffer"
   "Refresh the current speedbar display, disposing of any cached data."
   (interactive)
   (let ((dl speedbar-shown-directories)
-       (dm (and (boundp 'deactivate-mark) deactivate-mark)))
+       deactivate-mark)
     (while dl
       (adelete 'speedbar-directory-contents-alist (car dl))
       (setq dl (cdr dl)))
@@ -1688,8 +1700,7 @@ Assumes that the current buffer is the speedbar buffer"
     ;; Reset the timer in case it got really hosed for some reason...
     (speedbar-set-timer speedbar-update-speed)
     (if (<= 1 speedbar-verbosity-level)
-       (speedbar-message "Refreshing speedbar...done"))
-    (if (boundp 'deactivate-mark) (setq deactivate-mark dm))))
+       (speedbar-message "Refreshing speedbar...done"))))
 
 (defun speedbar-item-load ()
   "Load the item under the cursor or mouse if it is a Lisp file."
@@ -1724,7 +1735,7 @@ This should be bound to a mouse EVENT."
   (speedbar-item-info))
 
 (defun speedbar-generic-item-info ()
-  "Attempt to derive, and then display information about thils line item.
+  "Attempt to derive, and then display information about this line item.
 File style information is displayed with `speedbar-item-info'."
   (save-excursion
     (beginning-of-line)
@@ -1739,7 +1750,7 @@ File style information is displayed with `speedbar-item-info'."
 (defun speedbar-item-info ()
   "Display info in the mini-buffer about the button the mouse is over.
 This function can be replaced in `speedbar-mode-functions-list' as
-`speedbar-item-info'"
+`speedbar-item-info'."
   (interactive)
   (let (message-log-max)
     (funcall (or (speedbar-fetch-replacement-function 'speedbar-item-info)
@@ -1925,13 +1936,13 @@ variable `speedbar-obj-alist'."
     (speedbar-enable-update)))
 
 (defun speedbar-toggle-images ()
-  "Toggle automatic update for the speedbar frame."
+  "Toggle images for the speedbar frame."
   (interactive)
   (setq speedbar-use-images (not speedbar-use-images))
   (speedbar-refresh))
 
 (defun speedbar-toggle-sorting ()
-  "Toggle automatic update for the speedbar frame."
+  "Toggle sorting for the speedbar frame."
   (interactive)
   (setq speedbar-sort-tags (not speedbar-sort-tags)))
 
@@ -1944,7 +1955,7 @@ variable `speedbar-obj-alist'."
 ;;; Utility functions
 ;;
 (defun speedbar-set-timer (timeout)
-  "Apply a timer with TIMEOUT, or remove a timer if TIMOUT is nil.
+  "Apply a timer with TIMEOUT, or remove a timer if TIMEOUT is nil.
 TIMEOUT is the number of seconds until the speedbar timer is called
 again.  When TIMEOUT is nil, turn off all timeouts.
 This function will also enable or disable the `vc-checkin-hook' used
@@ -2018,7 +2029,7 @@ When the user clicks on TEXT, FUNCTION is called with the TOKEN parameter.
 This function assumes that the current buffer is the speedbar buffer.
 If PREVLINE, then put this button on the previous line.
 
-This is a convenience function for special mode that create their own
+This is a convenience function for special modes that create their own
 specialized speedbar displays."
   (goto-char (point-max))
   (let ((start (point)))
@@ -2039,7 +2050,7 @@ specialized speedbar displays."
 (defun speedbar-make-button (start end face mouse function &optional token)
   "Create a button from START to END, with FACE as the display face.
 MOUSE is the mouse face.  When this button is clicked on FUNCTION
-will be run with the TOKEN parameter (any Lisp object)"
+will be run with the TOKEN parameter (any Lisp object)."
   (put-text-property start end 'face face)
   (put-text-property start end 'mouse-face mouse)
   (put-text-property start end 'invisible nil)
@@ -2178,7 +2189,7 @@ of the special mode functions."
 The car is the list of directories, the cdr is list of files not
 matching ignored headers.  Cache any directory files found in
 `speedbar-directory-contents-alist' and use that cache before scanning
-the file-system"
+the file-system."
   (setq directory (expand-file-name directory))
   ;; If in powerclick mode, then the directory we are getting
   ;; should be rescanned.
@@ -2187,21 +2198,17 @@ the file-system"
   ;; find the directory, either in the cache, or build it.
   (or (cdr-safe (assoc directory speedbar-directory-contents-alist))
       (let ((default-directory directory)
-           (dir (directory-files directory nil))
-           (dirs nil)
-           (files nil))
-       (while dir
-         (if (not
-              (or (string-match speedbar-file-unshown-regexp (car dir))
-                  (string-match speedbar-directory-unshown-regexp (car dir))))
-             (if (file-directory-p (car dir))
-                 (setq dirs (cons (car dir) dirs))
-               (setq files (cons (car dir) files))))
-         (setq dir (cdr dir)))
-       (let ((nl (cons (nreverse dirs) (list (nreverse files)))))
+           (case-fold-search read-file-name-completion-ignore-case)
+           dirs files)
+       (dolist (file (directory-files directory nil))
+         (or (string-match speedbar-file-unshown-regexp file)
+             (string-match speedbar-directory-unshown-regexp file)
+             (if (file-directory-p file)
+                 (setq dirs (cons file dirs))
+               (setq files (cons file files)))))
+       (let ((nl `(,(nreverse dirs) ,(nreverse files))))
          (aput 'speedbar-directory-contents-alist directory nl)
-         nl))
-      ))
+         nl))))
 
 (defun speedbar-directory-buttons (directory index)
   "Insert a single button group at point for DIRECTORY.
@@ -2292,7 +2299,7 @@ TAG-BUTTON-FACE is a face used for this type of tag.
 Lastly, DEPTH shows the depth of expansion.
 
 This function assumes that the cursor is in the speedbar window at the
-position to insert a new item, and that the new item will end with a CR"
+position to insert a new item, and that the new item will end with a CR."
   (let ((start (point))
        (end (progn
               (insert (int-to-string depth) ":")
@@ -2327,7 +2334,7 @@ position to insert a new item, and that the new item will end with a CR"
                            (if tag-button-function 'speedbar-highlight-face nil)
                            tag-button-function tag-button-data))
     ))
-  
+
 (defun speedbar-change-expand-button-char (char)
   "Change the expansion button character to CHAR for the current line."
   (save-excursion
@@ -2345,34 +2352,40 @@ position to insert a new item, and that the new item will end with a CR"
 \f
 ;;; Build button lists
 ;;
-(defun speedbar-insert-files-at-point (files level)
+(defun speedbar-insert-files-at-point (files level directory)
   "Insert list of FILES starting at point, and indenting all files to LEVEL.
 Tag expandable items with a +, otherwise a ?.  Don't highlight ? as we
 don't know how to manage them.  The input parameter FILES is a cons
-cell of the form ( 'DIRLIST .  'FILELIST )"
+cell of the form ( 'DIRLIST .  'FILELIST )."
   ;; Start inserting all the directories
-  (let ((dirs (car files)))
-    (while dirs
-      (speedbar-make-tag-line 'angle ?+ 'speedbar-dired (car dirs)
-                             (car dirs) 'speedbar-dir-follow nil
-                             'speedbar-directory-face level)
-      (setq dirs (cdr dirs))))
-  (let ((lst (car (cdr files)))
-       (case-fold-search t))
-    (while lst
-      (let* ((known (string-match speedbar-file-regexp (car lst)))
+  (dolist (dir (car files))
+    (if (if speedbar-scan-subdirs
+           (condition-case nil
+               (let ((l (speedbar-file-lists (concat directory dir))))
+                 (or (car l) (cadr l)))
+             (file-error))
+         (file-readable-p (concat directory dir)))
+       (speedbar-make-tag-line 'angle ?+ 'speedbar-dired dir
+                               dir 'speedbar-dir-follow nil
+                               'speedbar-directory-face level)
+      (speedbar-make-tag-line 'angle ?  nil dir
+                             dir 'speedbar-dir-follow nil
+                             'speedbar-directory-face level)))
+  (let ((case-fold-search read-file-name-completion-ignore-case))
+    (dolist (file (cadr files))
+      (let* ((known (and (file-readable-p (concat directory file))
+                        (string-match speedbar-file-regexp file)))
             (expchar (if known ?+ ??))
             (fn (if known 'speedbar-tag-file nil)))
        (if (or speedbar-show-unknown-files (/= expchar ??))
-           (speedbar-make-tag-line 'bracket expchar fn (car lst)
-                                   (car lst) 'speedbar-find-file nil
-                                   'speedbar-file-face level)))
-      (setq lst (cdr lst)))))
+           (speedbar-make-tag-line 'bracket expchar fn file
+                                   file 'speedbar-find-file nil
+                                   'speedbar-file-face level))))))
 
 (defun speedbar-default-directory-list (directory index)
   "Insert files for DIRECTORY with level INDEX at point."
   (speedbar-insert-files-at-point
-   (speedbar-file-lists directory) index)
+   (speedbar-file-lists directory) index directory)
   (speedbar-reset-scanners)
   (if (= index 0)
       ;; If the shown files variable has extra directories, then
@@ -2390,8 +2403,8 @@ cell of the form ( 'DIRLIST .  'FILELIST )"
                (if (looking-at "[0-9]+:[ ]*<")
                    (progn
                      (goto-char (match-end 0))
-                 (speedbar-do-function-pointer)))
-               (setq sf (cdr sf)))))
+                     (speedbar-do-function-pointer)))))
+         (setq sf (cdr sf)))
        )))
 
 (defun speedbar-sort-tag-hierarchy (lst)
@@ -2641,7 +2654,7 @@ name will have the function FIND-FUN and not token."
   (speedbar-insert-generic-list indent lst
                                'speedbar-tag-expand
                                'speedbar-tag-find))
-                               
+
 (defun speedbar-insert-etags-list (indent lst)
   "At level INDENT, insert the etags generated LST."
   (speedbar-insert-generic-list indent lst
@@ -2746,7 +2759,7 @@ name will have the function FIND-FUN and not token."
   (speedbar-reconfigure-keymaps))
 
 (defun speedbar-update-special-contents ()
-  "Used the mode-specific variable to fill in the speedbar buffer.
+  "Use the mode-specific variable to fill in the speedbar buffer.
 This should only be used by modes classified as special."
   (let ((funclst speedbar-special-mode-expansion-list)
        (specialbuff (current-buffer)))
@@ -2870,7 +2883,7 @@ If new functions are added, their state needs to be updated here."
   )
 
 (defun speedbar-find-selected-file (file)
-  "Goto the line where FILE is."
+  "Go to the line where FILE is."
   (goto-char (point-min))
   (let ((m nil))
     (while (and (setq m (re-search-forward
@@ -2920,7 +2933,7 @@ updated."
         (newcf (if newcfd newcfd))
         (lastb (current-buffer))
         (sucf-recursive (boundp 'sucf-recursive))
-        (case-fold-search t))
+        (case-fold-search read-file-name-completion-ignore-case))
     (if (and newcf
             ;; check here, that way we won't refresh to newcf until
             ;; its been written, thus saving ourselves some time
@@ -2972,7 +2985,7 @@ updated."
 (defun speedbar-add-indicator (indicator-string &optional replace-this)
   "Add INDICATOR-STRING to the end of this speedbar line.
 If INDICATOR-STRING is space, and REPLACE-THIS is a character, then
-an the existing indicator is removed.  If there is already an
+the existing indicator is removed.  If there is already an
 indicator, then do not add a space."
   (beginning-of-line)
   ;; The nature of the beast: Assume we are in "the right place"
@@ -3236,7 +3249,7 @@ This should be bound to mouse event E."
 (defun speedbar-do-function-pointer ()
   "Look under the cursor and examine the text properties.
 From this extract the file/tag name, token, indentation level and call
-a function if appropriate"
+a function if appropriate."
   (let* ((fn (get-text-property (point) 'speedbar-function))
         (tok (get-text-property (point) 'speedbar-token))
         ;; The 1-,+ is safe because scaning starts AFTER the point
@@ -3287,7 +3300,7 @@ Optional argument P is where to start the search from."
       nil)))
 
 (defun speedbar-line-file (&optional p)
-  "Retrieve the file or whatever from the line at P point.
+  "Retrieve the file or whatever from the line at point P.
 The return value is a string representing the file.  If it is a
 directory, then it is the directory name."
   (save-match-data
@@ -3301,7 +3314,7 @@ directory, then it is the directory name."
        nil))))
 
 (defun speedbar-goto-this-file (file)
-  "If FILE is displayed, goto this line and return t.
+  "If FILE is displayed, go to this line and return t.
 Otherwise do not move and return nil."
   (let ((path (substring (file-name-directory (expand-file-name file))
                         (length (expand-file-name default-directory))))
@@ -3342,10 +3355,10 @@ Otherwise do not move and return nil."
   "Retrieve the pathname associated with the current line.
 This may require traversing backwards from DEPTH and combining the default
 directory with these items.  This function is replaceable in
-`speedbar-mode-functions-list' as `speedbar-line-path'"
+`speedbar-mode-functions-list' as `speedbar-line-path'."
   (let ((rf (speedbar-fetch-replacement-function 'speedbar-line-path)))
     (if rf (funcall rf depth) default-directory)))
-      
+
 (defun speedbar-files-line-path (&optional depth)
   "Retrieve the pathname associated with the current line.
 This may require traversing backwards from DEPTH and combining the default
@@ -3412,7 +3425,9 @@ directory with these items."
        (if (re-search-forward "[]>?}] [^ ]"
                               (save-excursion (end-of-line) (point))
                               t)
-           (speedbar-do-function-pointer)
+           (progn
+             (forward-char -1)
+             (speedbar-do-function-pointer))
          nil))
       (speedbar-do-function-pointer)))
 
@@ -3429,12 +3444,12 @@ With universal argument ARG, flush cached data."
          (forward-char -2)
          (speedbar-do-function-pointer))
       (error (speedbar-position-cursor-on-line)))))
-  
+
 (defun speedbar-flush-expand-line ()
   "Expand the line under the cursor and flush any cached information."
   (interactive)
   (speedbar-expand-line 1))
-  
+
 (defun speedbar-contract-line ()
   "Contract the line under the cursor."
   (interactive)
@@ -3450,7 +3465,7 @@ With universal argument ARG, flush cached data."
 (if speedbar-xemacsp
     (defalias 'speedbar-mouse-event-p 'button-press-event-p)
   (defun speedbar-mouse-event-p (event)
-    "Return t if the event is a mouse related event"
+    "Return t if the event is a mouse related event."
     ;; And Emacs does it this way
     (if (and (listp event)
             (member (event-basic-type event)
@@ -3483,7 +3498,7 @@ current indentation level."
 
 (defun speedbar-dir-follow (text token indent)
   "Speedbar click handler for directory names.
-Clicking a directory will cause the speedbar to list files in the
+Clicking a directory will cause the speedbar to list files in
 the subdirectory TEXT.  TOKEN is an unused requirement.  The
 subdirectory chosen will be at INDENT level."
   (setq default-directory
@@ -3555,7 +3570,7 @@ expanded.  INDENT is the current indentation level."
 TEXT is the button clicked on.  TOKEN is the directory to follow.
 INDENT is the current indentation level and is unused."
   (if (string-match "^[A-z]:$" token)
-      (setq default-directory (concat token (char-to-string directory-sep-char)))
+      (setq default-directory (concat token "/"))
     (setq default-directory token))
   ;; Because we leave speedbar as the current buffer,
   ;; update contents will change directory without
@@ -3588,7 +3603,7 @@ indentation level."
   (speedbar-center-buffer-smartly))
 
 (defun speedbar-tag-find (text token indent)
-  "For the tag TEXT in a file TOKEN, goto that position.
+  "For the tag TEXT in a file TOKEN, go to that position.
 INDENT is the current indentation level."
   (let ((file (speedbar-line-path indent)))
     (speedbar-find-file-in-frame file)
@@ -3734,7 +3749,7 @@ functions to do caching and flushing if appropriate."
 
     nil
 
-(eval-when-compile (if (locate-library "imenu") (require 'imenu)))
+(eval-when-compile (condition-case nil (require 'imenu) (error nil)))
 
 (defun speedbar-fetch-dynamic-imenu (file)
   "Load FILE into a buffer, and generate tags using Imenu.
@@ -3777,14 +3792,14 @@ This variable is ignored if `speedbar-use-imenu-flag' is non-nil.")
 (defvar speedbar-fetch-etags-command "etags"
   "*Command used to create an etags file.
 
-This variable is ignored if `speedbar-use-imenu-flag' is t")
+This variable is ignored if `speedbar-use-imenu-flag' is t.")
 
 (defvar speedbar-fetch-etags-arguments '("-D" "-I" "-o" "-")
   "*List of arguments to use with `speedbar-fetch-etags-command'.
 This creates an etags output buffer.  Use `speedbar-toggle-etags' to
 modify this list conveniently.
 
-This variable is ignored if `speedbar-use-imenu-flag' is t")
+This variable is ignored if `speedbar-use-imenu-flag' is t.")
 
 (defun speedbar-toggle-etags (flag)
   "Toggle FLAG in `speedbar-fetch-etags-arguments'.
@@ -3794,7 +3809,7 @@ value is \"show\" then toggle the value of
 `speedbar-show-unknown-files'.
 
   This function is a convenience function for XEmacs menu created by
-Farzin Guilak <farzin@protocol.com>"
+Farzin Guilak <farzin@protocol.com>."
   (interactive)
   (cond
    ((equal flag "sort")
@@ -3870,7 +3885,7 @@ Each symbol will be associated with its line position in FILE."
 (defun speedbar-extract-one-symbol (expr)
   "At point, return nil, or one alist in the form: (SYMBOL .  POSITION)
 The line should contain output from etags.  Parse the output using the
-regular expression EXPR"
+regular expression EXPR."
   (let* ((sym (if (stringp expr)
                  (if (save-excursion
                        (re-search-forward expr (save-excursion
@@ -3894,7 +3909,7 @@ regular expression EXPR"
       nil)))
 
 (defun speedbar-parse-c-or-c++tag ()
-  "Parse a c or c++ tag, which tends to be a little complex."
+  "Parse a C or C++ tag, which tends to be a little complex."
   (save-excursion
     (let ((bound (save-excursion (end-of-line) (point))))
       (cond ((re-search-forward "\C-?\\([^\C-a]+\\)\C-a" bound t)
@@ -4118,7 +4133,7 @@ TEXT is the buffer's name, TOKEN and INDENT are unused."
   )
 
 (defun speedbar-unhighlight-one-tag-line ()
-  "Unhighlight the currently highlight line."
+  "Unhighlight the currently highlighted line."
   (if speedbar-highlight-one-tag-line
       (progn
        (speedbar-delete-overlay speedbar-highlight-one-tag-line)
@@ -4147,7 +4162,7 @@ TEXT is the buffer's name, TOKEN and INDENT are unused."
                               (:foreground "cyan4"))
                              (((class color) (background dark))
                               (:foreground "cyan"))
-                             (t (:bold t)))
+                             (t (:weight bold)))
   "Face used for file names."
   :group 'speedbar-faces)
 
@@ -4155,7 +4170,7 @@ TEXT is the buffer's name, TOKEN and INDENT are unused."
                                    (:foreground "blue4"))
                                   (((class color) (background dark))
                                    (:foreground "light blue")))
-  "Faced used for directory names."
+  "Face used for directory names."
   :group 'speedbar-faces)
 (defface speedbar-tag-face '((((class color) (background light))
                              (:foreground "brown"))
@@ -4176,10 +4191,10 @@ TEXT is the buffer's name, TOKEN and INDENT are unused."
                                    (:background "green"))
                                   (((class color) (background dark))
                                    (:background "sea green"))
-                                  (((class grayscale monochrome)
+                                  (((class grayscale mono)
                                     (background light))
                                    (:background "black"))
-                                  (((class grayscale monochrome)
+                                  (((class grayscale mono)
                                     (background dark))
                                    (:background "white")))
   "Face used for highlighting buttons with the mouse."
@@ -4196,10 +4211,10 @@ TEXT is the buffer's name, TOKEN and INDENT are unused."
     (defalias 'defimage-speedbar 'defimage)
 
   (if (not (fboundp 'make-glyph))
-      
+
 (defmacro defimage-speedbar (variable imagespec docstring)
   "Don't bother loading up an image...
-Argument VARIABLE is the varible to define.
+Argument VARIABLE is the variable to define.
 Argument IMAGESPEC is the list defining the image to create.
 Argument DOCSTRING is the documentation for VARIABLE."
   `(defvar ,variable nil ,docstring))
@@ -4216,14 +4231,14 @@ Argument DOCSTRING is the documentation for VARIABLE."
     r))
 
 (defun speedbar-convert-emacs21-imagespec-to-xemacs (spec)
-  "Convert the Emacs21 Image SPEC into an XEmacs image spec."
+  "Convert the Emacs21 image SPEC into an XEmacs image spec."
   (let* ((sl (car spec))
         (itype (nth 1 sl))
         (ifile (nth 3 sl)))
     (vector itype ':file (speedbar-find-image-on-load-path ifile))))
 
 (defmacro defimage-speedbar (variable imagespec docstring)
-  "Devine VARIABLE as an image if `defimage' is not available..
+  "Define VARIABLE as an image if `defimage' is not available.
 IMAGESPEC is the image data, and DOCSTRING is documentation for the image."
   `(defvar ,variable
      ;; The Emacs21 version of defimage looks just like the XEmacs image
@@ -4235,9 +4250,7 @@ IMAGESPEC is the image data, and DOCSTRING is documentation for the image."
           (speedbar-convert-emacs21-imagespec-to-xemacs (quote ,imagespec)))
          'buffer)
        (error nil))
-     ,docstring))
-
-)))
+     ,docstring)))))
 
 (defimage-speedbar speedbar-directory-plus
   ((:type xpm :file "sb-dir-plus.xpm" :ascent center))
@@ -4247,6 +4260,10 @@ IMAGESPEC is the image data, and DOCSTRING is documentation for the image."
   ((:type xpm :file "sb-dir-minus.xpm" :ascent center))
   "Image used for open directories with stuff in them.")
 
+(defimage-speedbar speedbar-directory
+  ((:type xpm :file "sb-dir.xpm" :ascent center))
+  "Image used for empty or unreadable directories.")
+
 (defimage-speedbar speedbar-page-plus
   ((:type xpm :file "sb-pg-plus.xpm" :ascent center))
   "Image used for closed files with stuff in them.")
@@ -4290,6 +4307,7 @@ IMAGESPEC is the image data, and DOCSTRING is documentation for the image."
 (defvar speedbar-expand-image-button-alist
   '(("<+>" . speedbar-directory-plus)
     ("<->" . speedbar-directory-minus)
+    ("< >" . speedbar-directory)
     ("[+]" . speedbar-page-plus)
     ("[-]" . speedbar-page-minus)
     ("[?]" . speedbar-page)
@@ -4341,4 +4359,5 @@ If we have an image associated with it, use that image."
 ;; run load-time hooks
 (run-hooks 'speedbar-load-hook)
 
+;; arch-tag: 4477e6d1-f78c-48b9-a503-387d3c9767d5
 ;;; speedbar.el ends here