Merge from emacs-23; up to 2010-06-12T11:17:12Z!eliz@gnu.org.
[bpt/emacs.git] / lisp / speedbar.el
index 2a9f761..3e707ff 100644 (file)
@@ -1,7 +1,6 @@
 ;;; speedbar --- quick access to files and tags in a frame
 
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2011  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: file, tags, tools
@@ -244,14 +243,14 @@ replaced this way.  Replaceable functions must provide that
 functionality individually.")
 
 (defcustom speedbar-mode-specific-contents-flag t
-  "*Non-nil means speedbar will show special mode contents.
+  "Non-nil means speedbar will show special mode contents.
 This permits some modes to create customized contents for the speedbar
 frame."
   :group 'speedbar
   :type 'boolean)
 
 (defcustom speedbar-query-confirmation-method 'all
-  "*Query control for file operations.
+  "Query control for file operations.
 The 'always flag means to always query before file operations.
 The 'none-but-delete flag means to not query before any file
 operations, except before a file deletion."
@@ -277,24 +276,24 @@ This keymap is local to each buffer that wants to define special keybindings
 effective when its display is shown.")
 
 (defcustom speedbar-before-visiting-file-hook '(push-mark)
-  "*Hooks run before speedbar visits a file in the selected frame.
+  "Hooks run before speedbar visits a file in the selected frame.
 The default buffer is the buffer in the selected window in the attached frame."
   :group 'speedbar
   :type 'hook)
 
 (defcustom speedbar-visiting-file-hook nil
-  "*Hooks run when speedbar visits a file in the selected frame."
+  "Hooks run when speedbar visits a file in the selected frame."
   :group 'speedbar
   :type 'hook)
 
 (defcustom speedbar-before-visiting-tag-hook '(push-mark)
-  "*Hooks run before speedbar visits a tag in the selected frame.
+  "Hooks run before speedbar visits a tag in the selected frame.
 The default buffer is the buffer in the selected window in the attached frame."
   :group 'speedbar
   :type 'hook)
 
 (defcustom speedbar-visiting-tag-hook '(speedbar-highlight-one-tag-line)
-  "*Hooks run when speedbar visits a tag in the selected frame."
+  "Hooks run when speedbar visits a tag in the selected frame."
   :group 'speedbar
   :type 'hook
   :options '(speedbar-highlight-one-tag-line
@@ -303,17 +302,17 @@ The default buffer is the buffer in the selected window in the attached frame."
             ))
 
 (defcustom speedbar-load-hook nil
-  "*Hooks run when speedbar is loaded."
+  "Hooks run when speedbar is loaded."
   :group 'speedbar
   :type 'hook)
 
 (defcustom speedbar-reconfigure-keymaps-hook nil
-  "*Hooks run when the keymaps are regenerated."
+  "Hooks run when the keymaps are regenerated."
   :group 'speedbar
   :type 'hook)
 
 (defcustom speedbar-show-unknown-files nil
-  "*Non-nil show files we can't expand with a ? in the expand button.
+  "Non-nil show files we can't expand with a ? in the expand button.
 A nil value means don't show the file in the list."
   :group 'speedbar
   :type 'boolean)
@@ -326,12 +325,12 @@ A nil value means don't show the file in the list."
 (defvar speedbar-update-speed dframe-update-speed)
 (make-obsolete-variable 'speedbar-update-speed
                        'dframe-update-speed
-                       "speedbar 1.0pre3")
+                       "speedbar 1.0pre3 (Emacs 23.1)")
 
 (defvar speedbar-navigating-speed dframe-update-speed)
 (make-obsolete-variable 'speedbar-navigating-speed
                        'dframe-update-speed
-                       "speedbar 1.0pre3")
+                       "speedbar 1.0pre3 (Emacs 23.1)")
 ;;; END REMOVE THESE
 
 (defcustom speedbar-frame-parameters '((minibuffer . nil)
@@ -342,7 +341,7 @@ A nil value means don't show the file in the list."
                                       (unsplittable . t)
                                       (left-fringe . 0)
                                       )
-  "*Parameters to use when creating the speedbar frame in Emacs.
+  "Parameters to use when creating the speedbar frame in Emacs.
 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."
@@ -359,7 +358,7 @@ attached to and added to this list before the new frame is initialized."
               menubar-visible-p nil
               default-gutter-visible-p nil
               )
-  "*Parameters to use when creating the speedbar frame in XEmacs.
+  "Parameters to use when creating the speedbar frame in XEmacs.
 Parameters not listed here which will be added automatically are
 `height' which will be initialized to the height of the frame speedbar
 is attached to."
@@ -369,7 +368,7 @@ is attached to."
                        (sexp :tag "Value"))))
 
 (defcustom speedbar-use-imenu-flag (fboundp 'imenu)
-  "*Non-nil means use imenu for file parsing, nil to use etags.
+  "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."
   :tag "Use Imenu for tags"
@@ -396,12 +395,12 @@ display is used instead."
   :type 'boolean)
 
 (defcustom speedbar-track-mouse-flag (not speedbar-use-tool-tips-flag)
-  "*Non-nil means to display info about the line under the mouse."
+  "Non-nil means to display info about the line under the mouse."
   :group 'speedbar
   :type 'boolean)
 
 (defcustom speedbar-default-position 'left-right
-  "*Default position of the speedbar frame.
+  "Default position of the speedbar frame.
 Possible values are 'left, 'right or 'left-right.
 If value is 'left-right, the most suitable location is
 determined automatically."
@@ -411,7 +410,7 @@ determined automatically."
                (const :tag "Right" right)))
 
 (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*.
 Use `semantic-tag-hierarchy-method' instead."
   :group 'speedbar
   :type 'boolean)
@@ -419,7 +418,7 @@ Use `semantic-tag-hierarchy-method' instead."
 (defcustom speedbar-tag-hierarchy-method
   '(speedbar-prefix-group-tag-hierarchy
     speedbar-trim-words-tag-hierarchy)
-  "*List of hooks which speedbar will use to organize tags into groups.
+  "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 destructively
@@ -439,7 +438,7 @@ or
   )
 
 (defcustom speedbar-tag-group-name-minimum-length 4
-  "*The minimum length of a prefix group name before expanding.
+  "The minimum length of a prefix group name before expanding.
 Thus, if the `speedbar-tag-hierarchy-method' includes `prefix-group'
 and one such groups common characters is less than this number of
 characters, then the group name will be changed to the form of:
@@ -451,14 +450,14 @@ This way we won't get silly looking listings."
   :type 'integer)
 
 (defcustom speedbar-tag-split-minimum-length 20
-  "*Minimum length before we stop trying to create sub-lists in tags.
+  "Minimum length before we stop trying to create sub-lists in tags.
 This is used by all tag-hierarchy methods that break large lists into
 sub-lists."
   :group 'speedbar
   :type 'integer)
 
 (defcustom speedbar-tag-regroup-maximum-length 10
-  "*Maximum length of submenus that are regrouped.
+  "Maximum length of submenus that are regrouped.
 If the regrouping option is used, then if two or more short subgroups
 are next to each other, then they are combined until this number of
 items is reached."
@@ -466,7 +465,7 @@ items is reached."
   :type 'integer)
 
 (defcustom speedbar-directory-button-trim-method 'span
-  "*Indicates how the directory button will be displayed.
+  "Indicates how the directory button will be displayed.
 Possible values are:
  'span - span large directories over multiple lines.
  'trim - trim large directories to only show the last few.
@@ -479,7 +478,7 @@ Possible values are:
                (const :tag "No trimming." nil)))
 
 (defcustom speedbar-smart-directory-expand-flag t
-  "*Non-nil means speedbar should use smart expansion.
+  "Non-nil means speedbar should use smart expansion.
 Smart expansion only affects when speedbar wants to display a
 directory for a file in the attached frame.  When smart expansion is
 enabled, new directories which are children of a displayed directory
@@ -489,42 +488,42 @@ hierarchy would be replaced with the new directory."
   :type 'boolean)
 
 (defcustom speedbar-indentation-width 1
-  "*When sub-nodes are expanded, the number of spaces used for indentation."
+  "When sub-nodes are expanded, the number of spaces used for indentation."
   :group 'speedbar
   :type 'integer)
 
 (defcustom speedbar-hide-button-brackets-flag nil
-  "*Non-nil means speedbar will hide the brackets around the + or -."
+  "Non-nil means speedbar will hide the brackets around the + or -."
   :group 'speedbar
   :type 'boolean)
 
 (defcustom speedbar-before-popup-hook nil
-  "*Hooks called before popping up the speedbar frame."
+  "Hooks called before popping up the speedbar frame."
   :group 'speedbar
   :type 'hook)
 
 (defcustom speedbar-after-create-hook '(speedbar-frame-reposition-smartly)
-  "*Hooks called after popping up the speedbar frame."
+  "Hooks called after popping up the speedbar frame."
   :group 'speedbar
   :type 'hook)
 
 (defcustom speedbar-before-delete-hook nil
-  "*Hooks called before deleting the speedbar frame."
+  "Hooks called before deleting the speedbar frame."
   :group 'speedbar
   :type 'hook)
 
 (defcustom speedbar-mode-hook nil
-  "*Hooks called after creating a speedbar buffer."
+  "Hook run after creating a speedbar buffer."
   :group 'speedbar
   :type 'hook)
 
 (defcustom speedbar-timer-hook nil
-  "*Hooks called after running the speedbar timer function."
+  "Hooks called after running the speedbar timer function."
   :group 'speedbar
   :type 'hook)
 
 (defcustom speedbar-verbosity-level 1
-  "*Verbosity level of the speedbar.
+  "Verbosity level of the speedbar.
 0 means say nothing.
 1 means medium level verbosity.
 2 and higher are higher levels of verbosity."
@@ -535,7 +534,7 @@ hierarchy would be replaced with the new directory."
   "String separating file text from indicator characters.")
 
 (defcustom speedbar-vc-do-check t
-  "*Non-nil check all files in speedbar to see if they have been checked out.
+  "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'."
   :group 'speedbar-vc
   :type 'boolean)
@@ -546,14 +545,14 @@ Other version control systems can be added by examining the function
 `speedbar-vc-directory-enable-hook' and `speedbar-vc-in-control-hook'.")
 
 (defcustom speedbar-vc-directory-enable-hook nil
-  "*Return non-nil if the current directory should be checked for Version Control.
+  "Return non-nil if the current directory should be checked for Version Control.
 Functions in this hook must accept one parameter which is the directory
 being checked."
   :group 'speedbar-vc
   :type 'hook)
 
 (defcustom speedbar-vc-in-control-hook nil
-  "*Return non-nil if the specified file is under Version Control.
+  "Return non-nil if the specified file is under Version Control.
 Functions in this hook must accept two parameters.  The DIRECTORY of the
 current file, and the FILENAME of the file being checked."
   :group 'speedbar-vc
@@ -563,7 +562,7 @@ current file, and the FILENAME of the file being checked."
   "Local variable maintaining the current version control check position.")
 
 (defcustom speedbar-obj-do-check t
-  "*Non-nil check all files in speedbar to see if they have an object file.
+  "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'"
   :group 'speedbar-vc
@@ -609,14 +608,17 @@ The expression `speedbar-obj-alist' defines who gets tagged.")
 Permits stripping of indicator characters from a line.")
 
 (defcustom speedbar-scanner-reset-hook nil
-  "*Hook called whenever generic scanners are reset.
+  "Hook called whenever generic scanners are reset.
 Set this to implement your own scanning / rescan safe functions with
 state data."
   :group 'speedbar
   :type 'hook)
 
-(defvar speedbar-ignored-modes '(fundamental-mode)
-  "*List of major modes which speedbar will not switch directories for.")
+(defcustom speedbar-ignored-modes '(fundamental-mode)
+  "List of major modes which speedbar will not switch directories for."
+  :group 'speedbar
+  :type '(choice (const nil)
+                (repeat :tag "List of modes" (symbol :tag "Major mode"))))
 
 (defun speedbar-extension-list-to-regex (extlist)
   "Takes EXTLIST, a list of extensions and transforms it into regexp.
@@ -645,11 +647,11 @@ Use the function `speedbar-add-ignored-directory-regexp', or customize the
 variable `speedbar-ignored-directory-expressions' to modify this variable.")
 
 (define-obsolete-variable-alias 'speedbar-ignored-path-expressions
-  'speedbar-ignored-directory-expressions)
+  'speedbar-ignored-directory-expressions "22.1")
 
 (defcustom speedbar-ignored-directory-expressions
   '("[/\\]logs?[/\\]\\'")
-  "*List of regular expressions matching directories speedbar will ignore.
+  "List of regular expressions matching directories speedbar will ignore.
 They should included directories which are notoriously very large
 and take a long time to load in.  Use the function
 `speedbar-add-ignored-directory-regexp' to add new items to this list after
@@ -657,20 +659,20 @@ speedbar is loaded.  You may place anything you like in this list
 before speedbar has been loaded."
   :group 'speedbar
   :type '(repeat (regexp :tag "Directory Regexp"))
-  :set (lambda (sym val)
+  :set (lambda (_sym val)
         (setq speedbar-ignored-directory-expressions val
               speedbar-ignored-directory-regexp
               (speedbar-extension-list-to-regex val))))
 
 (defcustom speedbar-directory-unshown-regexp "^\\(\\..*\\)\\'"
-  "*Regular expression matching directories not to show in speedbar.
+  "Regular expression matching directories not to show in speedbar.
 They should include commonly existing directories which are not
 useful.  It is no longer necessary to include version-control
 directories here; see `vc-directory-exclusion-list'."
   :group 'speedbar
   :type 'string)
 
-(defvar speedbar-file-unshown-regexp
+(defcustom speedbar-file-unshown-regexp
   (let ((nstr "") (noext completion-ignored-extensions))
     (while noext
       (setq nstr (concat nstr (regexp-quote (car noext)) "\\'"
@@ -678,8 +680,10 @@ directories here; see `vc-directory-exclusion-list'."
            noext (cdr noext)))
     ;;               backup      refdir      lockfile
     (concat nstr "\\|#[^#]+#$\\|\\.\\.?\\'\\|\\.#"))
-  "*Regexp matching files we don't want displayed in a speedbar buffer.
-It is generated from the variable `completion-ignored-extensions'.")
+  "Regexp matching files we don't want displayed in a speedbar buffer.
+It is generated from the variable `completion-ignored-extensions'."
+  :group 'speedbar
+  :type 'string)
 
 (defvar speedbar-file-regexp nil
   "Regular expression matching files we know how to expand.
@@ -690,14 +694,14 @@ function `speedbar-extension-list-to-regex'.")
 ;; change in the future.
 (defcustom speedbar-supported-extension-expressions
   (append '(".[ch]\\(\\+\\+\\|pp\\|c\\|h\\|xx\\)?" ".tex\\(i\\(nfo\\)?\\)?"
-           ".el" ".emacs" ".l" ".lsp" ".p" ".java" ".f\\(90\\|77\\|or\\)?")
+           ".el" ".emacs" ".l" ".lsp" ".p" ".java" ".js" ".f\\(90\\|77\\|or\\)?")
          (if speedbar-use-imenu-flag
              '(".ada" ".p[lm]" ".tcl" ".m" ".scm" ".pm" ".py" ".g"
                ;; html is not supported by default, but an imenu tags package
                ;; is available.  Also, html files are nice to be able to see.
                ".s?html"
                ".ma?k" "[Mm]akefile\\(\\.in\\)?")))
-  "*List of regular expressions which will match files supported by tagging.
+  "List of regular expressions which will match files supported by tagging.
 Do not prefix the `.' char with a double \\ to quote it, as the period
 will be stripped by a simplified optimizer when compiled into a
 singular expression.  This variable will be turned into
@@ -709,7 +713,7 @@ need to also modify `completion-ignored-extension' which will also help
 file completion."
   :group 'speedbar
   :type '(repeat (regexp :tag "Extension Regexp"))
-  :set (lambda (sym val)
+  :set (lambda (_sym val)
         (set 'speedbar-supported-extension-expressions val)
         (set 'speedbar-file-regexp (speedbar-extension-list-to-regex val))))
 
@@ -756,111 +760,110 @@ DIRECTORY-EXPRESSION to `speedbar-ignored-directory-expressions'."
          speedbar-ignored-directory-regexp (speedbar-extension-list-to-regex
                                        speedbar-ignored-directory-expressions)))
 
-(defvar speedbar-update-flag dframe-have-timer-flag
-  "*Non-nil means to automatically update the display.
+(defcustom speedbar-update-flag dframe-have-timer-flag
+  "Non-nil means to automatically update the display.
 When this is nil then speedbar will not follow the attached frame's directory.
-When speedbar is active, use:
-
-\\<speedbar-key-map> `\\[speedbar-toggle-updates]'
-
-to toggle this value.")
+If you want to change this while speedbar is active, either use
+\\[customize] or call \\<speedbar-key-map> `\\[speedbar-toggle-updates]'."
+  :group 'speedbar
+  :initialize 'custom-initialize-default
+  :set (lambda (sym val)
+        (set sym val)
+        (speedbar-toggle-updates))
+  :type 'boolean)
 
 (defvar speedbar-update-flag-disable nil
   "Permanently disable changing of the update flag.")
 
-(defvar speedbar-syntax-table nil
+(defvar speedbar-mode-syntax-table
+  (let ((st (make-syntax-table)))
+    ;; Turn off paren matching around here.
+    (modify-syntax-entry ?\' " " st)
+    (modify-syntax-entry ?\" " " st)
+    (modify-syntax-entry ?\( " " st)
+    (modify-syntax-entry ?\) " " st)
+    (modify-syntax-entry ?\{ " " st)
+    (modify-syntax-entry ?\} " " st)
+    (modify-syntax-entry ?\[ " " st)
+    (modify-syntax-entry ?\]  " " st)
+    st)
   "Syntax-table used on the speedbar.")
-
-(if speedbar-syntax-table
-    nil
-  (setq speedbar-syntax-table (make-syntax-table))
-  ;; turn off paren matching around here.
-  (modify-syntax-entry ?\' " " speedbar-syntax-table)
-  (modify-syntax-entry ?\" " " speedbar-syntax-table)
-  (modify-syntax-entry ?( " " speedbar-syntax-table)
-  (modify-syntax-entry ?) " " speedbar-syntax-table)
-  (modify-syntax-entry ?{ " " speedbar-syntax-table)
-  (modify-syntax-entry ?} " " speedbar-syntax-table)
-  (modify-syntax-entry ?[ " " speedbar-syntax-table)
-  (modify-syntax-entry ?] " " speedbar-syntax-table))
-
-(defvar speedbar-key-map nil
+(define-obsolete-variable-alias
+  'speedbar-syntax-table 'speedbar-mode-syntax-table "24.1")
+
+
+(defvar speedbar-mode-map
+  (let ((map (make-keymap)))
+    (suppress-keymap map t)
+
+    ;; Control.
+    (define-key map "t" 'speedbar-toggle-updates)
+    (define-key map "g" 'speedbar-refresh)
+
+    ;; Navigation.
+    (define-key map "n" 'speedbar-next)
+    (define-key map "p" 'speedbar-prev)
+    (define-key map "\M-n" 'speedbar-restricted-next)
+    (define-key map "\M-p" 'speedbar-restricted-prev)
+    (define-key map "\C-\M-n" 'speedbar-forward-list)
+    (define-key map "\C-\M-p" 'speedbar-backward-list)
+    ;; These commands never seemed useful.
+    ;;  (define-key map " " 'speedbar-scroll-up)
+    ;;  (define-key map [delete] 'speedbar-scroll-down)
+
+    ;; Short cuts I happen to find useful.
+    (define-key map "r"
+      (lambda () (interactive)
+        (speedbar-change-initial-expansion-list
+         speedbar-previously-used-expansion-list-name)))
+    (define-key map "b"
+      (lambda () (interactive)
+        (speedbar-change-initial-expansion-list "quick buffers")))
+    (define-key map "f"
+      (lambda () (interactive)
+        (speedbar-change-initial-expansion-list "files")))
+
+    (dframe-update-keymap map)
+    map)
   "Keymap used in speedbar buffer.")
-
-(if speedbar-key-map
-    nil
-  (setq speedbar-key-map (make-keymap))
-  (suppress-keymap speedbar-key-map t)
-
-  ;; control
-  (define-key speedbar-key-map "t" 'speedbar-toggle-updates)
-  (define-key speedbar-key-map "g" 'speedbar-refresh)
-
-  ;; navigation
-  (define-key speedbar-key-map "n" 'speedbar-next)
-  (define-key speedbar-key-map "p" 'speedbar-prev)
-  (define-key speedbar-key-map "\M-n" 'speedbar-restricted-next)
-  (define-key speedbar-key-map "\M-p" 'speedbar-restricted-prev)
-  (define-key speedbar-key-map "\C-\M-n" 'speedbar-forward-list)
-  (define-key speedbar-key-map "\C-\M-p" 'speedbar-backward-list)
-;; These commands never seemed useful.
-;;  (define-key speedbar-key-map " " 'speedbar-scroll-up)
-;;  (define-key speedbar-key-map [delete] 'speedbar-scroll-down)
-
-  ;; Short cuts I happen to find useful
-  (define-key speedbar-key-map "r"
-    (lambda () (interactive)
-      (speedbar-change-initial-expansion-list
-       speedbar-previously-used-expansion-list-name)))
-  (define-key speedbar-key-map "b"
-    (lambda () (interactive)
-      (speedbar-change-initial-expansion-list "quick buffers")))
-  (define-key speedbar-key-map "f"
-    (lambda () (interactive)
-      (speedbar-change-initial-expansion-list "files")))
-
-  (dframe-update-keymap speedbar-key-map)
-)
+(define-obsolete-variable-alias 'speedbar-key-map 'speedbar-mode-map "24.1")
 
 (defun speedbar-make-specialized-keymap ()
   "Create a keymap for use with a speedbar major or minor display mode.
 This basically creates a sparse keymap, and makes its parent be
-`speedbar-key-map'."
+`speedbar-mode-map'."
   (let ((k (make-sparse-keymap)))
-    (set-keymap-parent k speedbar-key-map)
+    (set-keymap-parent k speedbar-mode-map)
     k))
 
-(defvar speedbar-file-key-map nil
+(defvar speedbar-file-key-map
+  (let ((map (speedbar-make-specialized-keymap)))
+
+    ;; Basic tree features.
+    (define-key map "e" 'speedbar-edit-line)
+    (define-key map "\C-m" 'speedbar-edit-line)
+    (define-key map "+" 'speedbar-expand-line)
+    (define-key map "=" 'speedbar-expand-line)
+    (define-key map "-" 'speedbar-contract-line)
+
+    (define-key map "[" 'speedbar-expand-line-descendants)
+    (define-key map "]" 'speedbar-contract-line-descendants)
+
+    (define-key map " " 'speedbar-toggle-line-expansion)
+
+    ;; File based commands.
+    (define-key map "U" 'speedbar-up-directory)
+    (define-key map "I" 'speedbar-item-info)
+    (define-key map "B" 'speedbar-item-byte-compile)
+    (define-key map "L" 'speedbar-item-load)
+    (define-key map "C" 'speedbar-item-copy)
+    (define-key map "D" 'speedbar-item-delete)
+    (define-key map "O" 'speedbar-item-object-delete)
+    (define-key map "R" 'speedbar-item-rename)
+    (define-key map "M" 'speedbar-create-directory)
+    map)
   "Keymap used in speedbar buffer while files are displayed.")
 
-(if speedbar-file-key-map
-    nil
-  (setq speedbar-file-key-map (speedbar-make-specialized-keymap))
-
-  ;; Basic tree features
-  (define-key speedbar-file-key-map "e" 'speedbar-edit-line)
-  (define-key speedbar-file-key-map "\C-m" 'speedbar-edit-line)
-  (define-key speedbar-file-key-map "+" 'speedbar-expand-line)
-  (define-key speedbar-file-key-map "=" 'speedbar-expand-line)
-  (define-key speedbar-file-key-map "-" 'speedbar-contract-line)
-
-  (define-key speedbar-file-key-map "[" 'speedbar-expand-line-descendants)
-  (define-key speedbar-file-key-map "]" 'speedbar-contract-line-descendants)
-
-  (define-key speedbar-file-key-map " " 'speedbar-toggle-line-expansion)
-
-  ;; file based commands
-  (define-key speedbar-file-key-map "U" 'speedbar-up-directory)
-  (define-key speedbar-file-key-map "I" 'speedbar-item-info)
-  (define-key speedbar-file-key-map "B" 'speedbar-item-byte-compile)
-  (define-key speedbar-file-key-map "L" 'speedbar-item-load)
-  (define-key speedbar-file-key-map "C" 'speedbar-item-copy)
-  (define-key speedbar-file-key-map "D" 'speedbar-item-delete)
-  (define-key speedbar-file-key-map "O" 'speedbar-item-object-delete)
-  (define-key speedbar-file-key-map "R" 'speedbar-item-rename)
-  (define-key speedbar-file-key-map "M" 'speedbar-create-directory)
-  )
-
 (defvar speedbar-easymenu-definition-base
   (append
    '("Speedbar"
@@ -1079,7 +1082,7 @@ selected.  If the speedbar frame is active, then select the attached frame."
 Return nil if it doesn't exist."
   (frame-width speedbar-frame))
 
-(defun speedbar-mode ()
+(define-derived-mode speedbar-mode fundamental-mode "Speedbar"
   "Major mode for managing a display of directories and tags.
 \\<speedbar-key-map>
 The first line represents the default directory of the speedbar frame.
@@ -1119,26 +1122,20 @@ tags start with >.  Click the name of the tag to go to that position
 in the selected file.
 
 \\{speedbar-key-map}"
-  ;; NOT interactive
   (save-excursion
-    (kill-all-local-variables)
-    (setq major-mode 'speedbar-mode)
-    (setq mode-name "Speedbar")
-    (set-syntax-table speedbar-syntax-table)
     (setq font-lock-keywords nil) ;; no font-locking please
     (setq truncate-lines t)
     (make-local-variable 'frame-title-format)
-    (setq frame-title-format (concat "Speedbar " speedbar-version))
-    (setq case-fold-search nil)
-    (toggle-read-only 1)
+    (setq frame-title-format (concat "Speedbar " speedbar-version)
+         case-fold-search nil
+         buffer-read-only t)
     (speedbar-set-mode-line-format)
     ;; Add in our dframe hooks.
     (if speedbar-track-mouse-flag
        (setq dframe-track-mouse-function #'speedbar-track-mouse))
     (setq dframe-help-echo-function #'speedbar-item-info
          dframe-mouse-click-function #'speedbar-click
-         dframe-mouse-position-function #'speedbar-position-cursor-on-line)
-    (run-hooks 'speedbar-mode-hook))
+         dframe-mouse-position-function #'speedbar-position-cursor-on-line))
   speedbar-buffer)
 
 (defmacro speedbar-message (fmt &rest args)
@@ -1173,8 +1170,7 @@ frame and window to be the currently active frame and window."
               (with-no-warnings
                 (specifier-instance has-modeline-p)))
           speedbar-buffer)
-      (save-excursion
-       (set-buffer speedbar-buffer)
+      (with-current-buffer speedbar-buffer
        (let* ((w (or (speedbar-frame-width) 20))
               (p1 "<<")
               (p5 ">>")
@@ -1246,8 +1242,7 @@ and the existence of packages."
                               (current-buffer))
                              speedbar-special-mode-key-map)
                        (select-frame cf))))))
-    (save-excursion
-      (set-buffer speedbar-buffer)
+    (with-current-buffer speedbar-buffer
       (use-local-map (or localmap
                         (speedbar-initial-keymap)
                         ;; This creates a small keymap we can glom the
@@ -1291,7 +1286,7 @@ and the existence of packages."
              (if (eq major-mode 'speedbar-mode)
                  ;; XEmacs may let us get in here in other mode buffers.
                  (speedbar-item-info)))
-         (t (speedbar-message nil)))))))
+         (error (speedbar-message nil)))))))
 
 (defun speedbar-show-info-under-mouse ()
   "Call the info function for the line under the mouse."
@@ -1318,7 +1313,7 @@ and the existence of packages."
   "Move to the next ARGth line in a speedbar buffer at the same depth.
 This means that movement is restricted to a subnode, and that siblings
 of intermediate nodes are skipped."
-  (if (not (numberp arg)) (signal 'wrong-type-argument (list arg 'numberp)))
+  (if (not (numberp arg)) (signal 'wrong-type-argument (list 'numberp arg)))
   ;; First find the extent for which we are allowed to move.
   (let ((depth (save-excursion (beginning-of-line)
                               (if (looking-at "[0-9]+:")
@@ -1473,7 +1468,7 @@ File style information is displayed with `speedbar-item-info'."
     (if (looking-at "\\s-*[[<({].[]>)}] ") (goto-char (match-end 0)))
     ;; Get the text
     (speedbar-message "Text: %s" (buffer-substring-no-properties
-                                 (point) (progn (end-of-line) (point))))))
+                                 (point) (line-end-position)))))
 
 (defun speedbar-item-info ()
   "Display info in the minibuffer about the button the mouse is over.
@@ -1499,8 +1494,7 @@ instead of reading it from the speedbar buffer."
 Return nil if not applicable."
   (save-excursion
     (beginning-of-line)
-    (if (re-search-forward " [-+=]?> \\([^\n]+\\)"
-                          (save-excursion(end-of-line)(point)) t)
+    (if (re-search-forward " [-+=]?> \\([^\n]+\\)" (line-end-position) t)
        (let* ((tag (match-string 1))
              (attr (speedbar-line-token))
              (item nil)
@@ -1518,8 +1512,7 @@ Return nil if not applicable."
            (looking-at "\\([0-9]+\\):")
            (setq item (file-name-nondirectory (speedbar-line-directory)))
            (speedbar-message "Tag: %s  in %s" tag item)))
-      (if (re-search-forward "{[+-]} \\([^\n]+\\)$"
-                            (save-excursion(end-of-line)(point)) t)
+      (if (re-search-forward "{[+-]} \\([^\n]+\\)$" (line-end-position) t)
          (speedbar-message "Group of tags \"%s\"" (match-string 1))
        (if (re-search-forward " [+-]?[()|@] \\([^\n]+\\)$" nil t)
            (let* ((detailtext (match-string 1))
@@ -1629,7 +1622,7 @@ Files can be renamed to new names or moved to new directories."
   (let ((f (speedbar-line-file)))
     (if f
        (let* ((basedir (file-name-directory f))
-              (nd (read-file-name "Create directory: "
+              (nd (read-directory-name "Create directory: "
                                   basedir)))
          ;; Make the directory
          (make-directory nd t)
@@ -1646,9 +1639,9 @@ Files can be renamed to new names or moved to new directories."
     (if (speedbar-y-or-n-p (format "Delete %s? " f) t)
        (progn
          (if (file-directory-p f)
-             (delete-directory f)
-           (delete-file f))
-         (speedbar-message "Okie dokie..")
+             (delete-directory f t t)
+           (delete-file f t))
+         (speedbar-message "Okie dokie.")
          (let ((p (point)))
            (speedbar-refresh)
            (goto-char p))
@@ -1695,8 +1688,7 @@ variable `speedbar-obj-alist'."
     (speedbar-enable-update)))
 
 (defun speedbar-toggle-images ()
-  "Toggle use of images in the speedbar frame.
-Images are not available in Emacs 20 or earlier."
+  "Toggle use of images in the speedbar frame."
   (interactive)
   (setq speedbar-use-images (not speedbar-use-images))
   (speedbar-refresh))
@@ -1859,8 +1851,7 @@ of the special mode functions."
   (if (stringp buffer) (setq buffer (get-buffer buffer)))
   (if (not (buffer-live-p buffer))
       nil
-    (save-excursion
-      (set-buffer buffer)
+    (with-current-buffer buffer
       (save-match-data
        (let ((ms (symbol-name major-mode)) v)
          (if (not (string-match "-mode$" ms))
@@ -1893,8 +1884,7 @@ of the special mode functions."
 
 (defun speedbar-remove-localized-speedbar-support (buffer)
   "Remove any traces that BUFFER supports speedbar in a specialized way."
-  (save-excursion
-    (set-buffer buffer)
+  (with-current-buffer buffer
     (kill-local-variable 'speedbar-special-mode-expansion-list)
     (kill-local-variable 'speedbar-special-mode-key-map)
     (kill-local-variable 'speedbar-easymenu-definition-special)))
@@ -1932,7 +1922,7 @@ the file-system."
          nl))
       ))
 
-(defun speedbar-directory-buttons (directory index)
+(defun speedbar-directory-buttons (directory _index)
   "Insert a single button group at point for DIRECTORY.
 Each directory part is a different button.  If part of the directory
 matches the user directory ~, then it is replaced with a ~.
@@ -2065,8 +2055,7 @@ position to insert a new item, and that the new item will end with a CR."
   "Change the expansion button character to CHAR for the current line."
   (save-excursion
     (beginning-of-line)
-    (if (re-search-forward ":\\s-*.\\([-+?]\\)" (save-excursion (end-of-line)
-                                                               (point)) t)
+    (if (re-search-forward ":\\s-*.\\([-+?]\\)" (line-end-position) t)
        (speedbar-with-writable
          (goto-char (match-end 1))
          (insert-char char 1 t)
@@ -2383,8 +2372,8 @@ the list."
              (or (speedbar-line-file)
                  (speedbar-line-directory))))
         (methods (if (get-file-buffer f)
-                     (save-excursion (set-buffer (get-file-buffer f))
-                                     speedbar-tag-hierarchy-method)
+                     (with-current-buffer (get-file-buffer f)
+                        speedbar-tag-hierarchy-method)
                    speedbar-tag-hierarchy-method))
         (lst (if (fboundp 'copy-tree)
                  (copy-tree lst)
@@ -2612,9 +2601,8 @@ name will have the function FIND-FUN and not token."
 This should only be used by modes classified as special."
   (let ((funclst speedbar-special-mode-expansion-list)
        (specialbuff (current-buffer)))
-    (save-excursion
-      (setq speedbar-desired-buffer specialbuff)
-      (set-buffer speedbar-buffer)
+    (setq speedbar-desired-buffer specialbuff)
+    (with-current-buffer speedbar-buffer
       ;; If we are leaving a directory, cache it.
       (if (not speedbar-shown-directories)
          ;; Do nothing
@@ -2856,9 +2844,7 @@ indicator, then do not add a space."
   (speedbar-with-writable
     (save-excursion
       (if (and replace-this
-              (re-search-forward replace-this (save-excursion (end-of-line)
-                                                              (point))
-                                 t))
+              (re-search-forward replace-this (line-end-position) t))
          (delete-region (match-beginning 0) (match-end 0))))
     (end-of-line)
     (if (not (string= " " indicator-string))
@@ -2900,12 +2886,6 @@ indicator, then do not add a space."
            t))
       t)))
 
-;; Load efs/ange-ftp only if compiling to remove byte-compiler warnings.
-;; Steven L Baur <steve@xemacs.org> said this was important:
-(eval-when-compile (or (featurep 'xemacs)
-                      (condition-case () (require 'efs)
-                        (error (require 'ange-ftp)))))
-
 (defun speedbar-check-vc ()
   "Scan all files in a directory, and for each see if it's checked out.
 See `speedbar-this-file-in-vc' and `speedbar-vc-check-dir-p' for how
@@ -2962,9 +2942,7 @@ the file being checked."
         (fn (buffer-substring-no-properties
              ;; Skip-chars: thanks ptype@dra.hmg.gb
              (point) (progn
-                       (skip-chars-forward "^ "
-                                           (save-excursion (end-of-line)
-                                                           (point)))
+                       (skip-chars-forward "^ " (line-end-position))
                        (point))))
         (fulln (concat f fn)))
     (if (<= 2 speedbar-verbosity-level)
@@ -3036,9 +3014,7 @@ the file being checked."
         (fn (buffer-substring-no-properties
              ;; Skip-chars: thanks ptype@dra.hmg.gb
              (point) (progn
-                       (skip-chars-forward "^ "
-                                           (save-excursion (end-of-line)
-                                                           (point)))
+                       (skip-chars-forward "^ " (line-end-position))
                        (point))))
         (fulln (concat f fn)))
     (if (<= 2 speedbar-verbosity-level)
@@ -3259,7 +3235,7 @@ directory with these items."
        ;; If this fails, then it is a non-standard click, and as such,
        ;; perfectly allowed.
        (if (re-search-forward "[]>?}] [^ ]"
-                              (save-excursion (end-of-line) (point))
+                              (line-end-position)
                               t)
            (progn
              (forward-char -1)
@@ -3277,7 +3253,7 @@ With universal argument ARG, flush cached data."
     (condition-case nil
        (progn
          (re-search-forward ":\\s-*.\\+. "
-                            (save-excursion (end-of-line) (point)))
+                            (line-end-position))
          (forward-char -2)
          (speedbar-do-function-pointer))
       (error (speedbar-position-cursor-on-line)))))
@@ -3294,7 +3270,7 @@ With universal argument ARG, flush cached data."
   (condition-case nil
       (progn
        (re-search-forward ":\\s-*.-. "
-                          (save-excursion (end-of-line) (point)))
+                          (line-end-position))
        (forward-char -2)
        (speedbar-do-function-pointer))
     (error (speedbar-position-cursor-on-line))))
@@ -3306,7 +3282,7 @@ With universal argument ARG, flush cached data."
   (condition-case nil
       (progn
        (re-search-forward ":\\s-*.[-+]. "
-                          (save-excursion (end-of-line) (point)))
+                          (line-end-position))
        (forward-char -2)
        (speedbar-do-function-pointer))
     (error (speedbar-position-cursor-on-line))))
@@ -3337,7 +3313,7 @@ Optional argument ARG indicates that any cache should be flushed."
   ;; hidden by default anyway.  Yay!  It's easy.
   )
 
-(defun speedbar-find-file (text token indent)
+(defun speedbar-find-file (text _token indent)
   "Speedbar click handler for filenames.
 TEXT, the file will be displayed in the attached frame.
 TOKEN is unused, but required by the click handler.  INDENT is the
@@ -3357,7 +3333,7 @@ current indentation level."
     (speedbar-set-timer dframe-update-speed))
   (dframe-maybee-jump-to-attached-frame))
 
-(defun speedbar-dir-follow (text token indent)
+(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 subdirectory TEXT.  TOKEN is an unused requirement.  The
@@ -3425,7 +3401,7 @@ expanded.  INDENT is the current indentation level."
   (speedbar-center-buffer-smartly)
   (save-excursion (speedbar-stealthy-updates)))
 
-(defun speedbar-directory-buttons-follow (text token indent)
+(defun speedbar-directory-buttons-follow (_text token _indent)
   "Speedbar click handler for default directory buttons.
 TEXT is the button clicked on.  TOKEN is the directory to follow.
 INDENT is the current indentation level and is unused."
@@ -3446,7 +3422,6 @@ indentation level."
   (cond ((string-match "+" text)       ;we have to expand this file
         (let* ((fn (expand-file-name (concat (speedbar-line-directory indent)
                                              token)))
-               (mode nil)
                (lst (speedbar-fetch-dynamic-tags fn)))
           ;; if no list, then remove expando button
           (if (not lst)
@@ -3462,7 +3437,7 @@ indentation level."
        (t (error "Ooops...  not sure what to do")))
   (speedbar-center-buffer-smartly))
 
-(defun speedbar-tag-find (text token indent)
+(defun speedbar-tag-find (_text token indent)
   "For the tag TEXT in a file TOKEN, go to that position.
 INDENT is the current indentation level."
   (let ((file (speedbar-line-directory indent)))
@@ -3501,7 +3476,7 @@ TOKEN will be the list, and INDENT is the current indentation level."
 ;;; Loading files into the attached frame.
 ;;
 (defcustom speedbar-select-frame-method 'attached
-  "*Specify how to select a frame for displaying a file.
+  "Specify how to select a frame for displaying a file.
 A value of 'attached means to use the attached frame (the frame
 that speedbar was started from.)  A number such as 1 or -1 means to
 pass that number to `other-frame' while selecting a frame from speedbar."
@@ -3675,17 +3650,20 @@ to be at the beginning of a line in the etags buffer.
 
 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.")
+(defcustom speedbar-fetch-etags-command "etags"
+  "Command used to create an etags file.
+This variable is ignored if `speedbar-use-imenu-flag' is t."
+  :group 'speedbar
+  :type 'string)
 
-(defvar speedbar-fetch-etags-arguments '("-D" "-I" "-o" "-")
-  "*List of arguments to use with `speedbar-fetch-etags-command'.
+(defcustom 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."
+  :group 'speedbar
+  :type '(choice (const nil)
+                (repeat :tag "List of arguments" string)))
 
 (defun speedbar-toggle-etags (flag)
   "Toggle FLAG in `speedbar-fetch-etags-arguments'.
@@ -3774,17 +3752,12 @@ The line should contain output from etags.  Parse the output using the
 regular expression EXPR."
   (let* ((sym (if (stringp expr)
                  (if (save-excursion
-                       (re-search-forward expr (save-excursion
-                                                 (end-of-line)
-                                                 (point)) t))
+                       (re-search-forward expr (line-end-position) t))
                      (buffer-substring-no-properties (match-beginning 1)
                                                      (match-end 1)))
                (funcall expr)))
         (pos (let ((j (re-search-forward "[\C-?\C-a]\\([0-9]+\\),\\([0-9]+\\)"
-                                         (save-excursion
-                                           (end-of-line)
-                                           (point))
-                                         t)))
+                                         (line-end-position) t)))
                (if (and j sym)
                    (1+ (string-to-number (buffer-substring-no-properties
                                        (match-beginning 2)
@@ -3797,7 +3770,7 @@ regular expression EXPR."
 (defun speedbar-parse-c-or-c++tag ()
   "Parse a C or C++ tag, which tends to be a little complex."
   (save-excursion
-    (let ((bound (save-excursion (end-of-line) (point))))
+    (let ((bound (line-end-position)))
       (cond ((re-search-forward "\C-?\\([^\C-a]+\\)\C-a" bound t)
             (buffer-substring-no-properties (match-beginning 1)
                                             (match-end 1)))
@@ -3813,7 +3786,7 @@ regular expression EXPR."
 (defun speedbar-parse-tex-string ()
   "Parse a Tex string.  Only find data which is relevant."
   (save-excursion
-    (let ((bound (save-excursion (end-of-line) (point))))
+    (let ((bound (line-end-position)))
       (cond ((re-search-forward "\\(\\(sub\\)*section\\|chapter\\|cite\\)\\s-*{[^\C-?}]*}?" bound t)
             (buffer-substring-no-properties (match-beginning 0)
                                             (match-end 0)))
@@ -3864,12 +3837,12 @@ regular expression EXPR."
     )
   "Menu item elements shown when displaying a buffer list.")
 
-(defun speedbar-buffer-buttons (directory zero)
+(defun speedbar-buffer-buttons (_directory _zero)
   "Create speedbar buttons based on the buffers currently loaded.
 DIRECTORY is the directory of the currently active buffer, and ZERO is 0."
   (speedbar-buffer-buttons-engine nil))
 
-(defun speedbar-buffer-buttons-temp (directory zero)
+(defun speedbar-buffer-buttons-temp (_directory _zero)
   "Create speedbar buttons based on the buffers currently loaded.
 DIRECTORY is the directory of the currently active buffer, and ZERO is 0."
   (speedbar-buffer-buttons-engine t))
@@ -3887,8 +3860,8 @@ If TEMP is non-nil, then clicking on a buffer restores the previous display."
                                    (buffer-name (car bl))))
               (expchar (if known ?+ ??))
               (fn (if known 'speedbar-tag-file nil))
-              (fname (save-excursion (set-buffer (car bl))
-                                     (buffer-file-name))))
+              (fname (with-current-buffer (car bl)
+                        (buffer-file-name))))
          (speedbar-make-tag-line 'bracket expchar fn
                                  (if fname (file-name-nondirectory fname))
                                  (buffer-name (car bl))
@@ -3927,12 +3900,8 @@ If TEMP is non-nil, then clicking on a buffer restores the previous display."
 (defun speedbar-buffers-tail-notes (buffer)
   "Add a note to the end of the last tag line.
 Argument BUFFER is the buffer being tested."
-  (let (mod ro)
-    (save-excursion
-      (set-buffer buffer)
-      (setq mod (buffer-modified-p)
-           ro buffer-read-only))
-    (if ro (speedbar-insert-button "%" nil nil nil nil t))))
+  (when (with-current-buffer buffer buffer-read-only)
+    (speedbar-insert-button "%" nil nil nil nil t)))
 
 (defun speedbar-buffers-item-info ()
   "Display information about the current buffer on the current line."
@@ -3943,12 +3912,11 @@ Argument BUFFER is the buffer being tested."
             (speedbar-message "%s%s %S %d %s"
                               (if (buffer-modified-p buffer) "* " "")
                               item
-                              (save-excursion (set-buffer buffer) major-mode)
-                              (save-excursion (set-buffer buffer)
-                                              (buffer-size))
+                              (with-current-buffer buffer major-mode)
+                              (with-current-buffer buffer (buffer-size))
                               (or (buffer-file-name buffer) "<No file>"))))))
 
-(defun speedbar-buffers-line-directory (&optional depth)
+(defun speedbar-buffers-line-directory (&optional _depth)
   "Fetch the directory of the file (buffer) specified on the current line.
 Optional argument DEPTH specifies the current depth of the back search."
   (save-excursion
@@ -3960,15 +3928,12 @@ Optional argument DEPTH specifies the current depth of the back search."
        (let* ((bn (speedbar-line-text))
               (buffer (if bn (get-buffer bn))))
          (if buffer
-             (if (save-excursion
-                   (end-of-line)
-                   (eq start (point)))
-                 (or (save-excursion (set-buffer buffer)
-                                     default-directory)
+             (if (eq start (line-end-position))
+                 (or (with-current-buffer buffer default-directory)
                      "")
                (buffer-file-name buffer))))))))
 
-(defun speedbar-buffer-click (text token indent)
+(defun speedbar-buffer-click (text token _indent)
   "When the users clicks on a buffer-button in speedbar.
 TEXT is the buffer's name, TOKEN and INDENT are unused."
   (if dframe-power-click
@@ -3995,14 +3960,10 @@ TEXT is the buffer's name, TOKEN and INDENT are unused."
     (beginning-of-line)
     ;; If this fails, then it is a non-standard click, and as such,
     ;; perfectly allowed
-    (if (re-search-forward "[]>?}] [^ ]"
-                          (save-excursion (end-of-line) (point))
-                          t)
+    (if (re-search-forward "[]>?}] [^ ]" (line-end-position) t)
        (let ((text (progn
                      (forward-char -1)
-                     (buffer-substring (point) (save-excursion
-                                                 (end-of-line)
-                                                 (point))))))
+                     (buffer-substring (point) (line-end-position)))))
          (if (get-buffer text)
              (progn
                (set-buffer text)
@@ -4018,14 +3979,11 @@ TEXT is the buffer's name, TOKEN and INDENT are unused."
   "Highlight the current line, unhighlighting a previously jumped to line."
   (speedbar-unhighlight-one-tag-line)
   (setq speedbar-highlight-one-tag-line
-       (speedbar-make-overlay (save-excursion (beginning-of-line) (point))
-                              (save-excursion (end-of-line)
-                                              (forward-char 1)
-                                              (point))))
+       (speedbar-make-overlay (line-beginning-position)
+                              (1+ (line-end-position))))
   (speedbar-overlay-put speedbar-highlight-one-tag-line 'face
                        'speedbar-highlight-face)
-  (add-hook 'pre-command-hook 'speedbar-unhighlight-one-tag-line)
-  )
+  (add-hook 'pre-command-hook 'speedbar-unhighlight-one-tag-line))
 
 (defun speedbar-unhighlight-one-tag-line ()
   "Unhighlight the currently highlighted line."
@@ -4122,37 +4080,38 @@ TEXT is the buffer's name, TOKEN and INDENT are unused."
            (def-edebug-spec speedbar-with-writable def-body)))
 
 ;; Fix a font lock problem for some versions of Emacs
-(if (boundp 'font-lock-global-modes)
-    (if (listp font-lock-global-modes)
-       (add-to-list 'font-lock-global-modes '(not speedbar-mode))
-      )
-  )
-
+(and (boundp 'font-lock-global-modes)
+     font-lock-global-modes
+     (if (eq font-lock-global-modes t)
+        (setq font-lock-global-modes '(not speedbar-mode))
+       (if (eq (car font-lock-global-modes) 'not)
+          (add-to-list 'font-lock-global-modes 'speedbar-mode t)
+        (setq font-lock-global-modes (delq 'speedbar-mode
+                                           font-lock-global-modes)))))
 \f
 ;;; Obsolete variables and functions
 
 (define-obsolete-variable-alias
-  'speedbar-ignored-path-regexp 'speedbar-ignored-directory-regexp)
+  'speedbar-ignored-path-regexp 'speedbar-ignored-directory-regexp "22.1")
 
 (define-obsolete-function-alias 'speedbar-add-ignored-path-regexp
-  'speedbar-add-ignored-directory-regexp)
+  'speedbar-add-ignored-directory-regexp "22.1")
 
 (define-obsolete-function-alias 'speedbar-line-path
-  'speedbar-line-directory)
+  'speedbar-line-directory "22.1")
 
 (define-obsolete-function-alias 'speedbar-buffers-line-path
-  'speedbar-buffers-line-directory)
+  'speedbar-buffers-line-directory "22.1")
 
 (define-obsolete-function-alias 'speedbar-path-line
-  'speedbar-directory-line)
+  'speedbar-directory-line "22.1")
 
 (define-obsolete-function-alias 'speedbar-buffers-line-path
-  'speedbar-buffers-line-directory)
+  'speedbar-buffers-line-directory "22.1")
 
 (provide 'speedbar)
 
 ;; run load-time hooks
 (run-hooks 'speedbar-load-hook)
 
-;; arch-tag: 4477e6d1-f78c-48b9-a503-387d3c9767d5
 ;;; speedbar ends here