Anonymous avatar Anonymous committed 533388c

Update to speedbar 0.11.1.

Comments (0)

Files changed (25)

+2000-07-16  Mike Sperber <mike@xemacs.org>
+
+	* speedbar.el (speedbar-easymenu-definition-base): Replaced
+	:visible by :active.
+
+	* sb-w3.el: Conditionalize w3-imenu requirement.
+
+	* speedbar.el (speedbar-convert-emacs21-imagespec-to-xemacs): Use
+	`locate-data-file'.
+
+	* Import speedbar 0.11.1.
+
 1999-08-26  Christoph Wedler  <Christoph.Wedler@sap-ag.de>
 
 	* speedbar.el: Changes to speedbar-v0.8.1.  Should be probably
  	changes to XEmacs' speedbar version (v.0.6.2) are:
 	(speedbar-frame-plist): Keep original FSF 20.4 value.  The glyph
  	settings from XEmacs-20.4 don't work with Windows/NT.
-	(speedbar-supported-extension-expressions): Don't add regexp for
+	(speedbar-supported-extension-expresosions): Don't add regexp for
  	lower-/uppercase -- the regexps are matched case-insensitive.
 	(edebug-setup-hook): Don't quote `speedbar-with-writable'.
 
 # Boston, MA 02111-1307, USA.
 
 VERSION = 1.14
-AUTHOR_VERSION =  0.6.2x
+AUTHOR_VERSION =  0.11.1
 MAINTAINER = XEmacs Development Team <xemacs-beta@xemacs.org>
 PACKAGE = speedbar
 PKG_TYPE = regular
 REQUIRES = xemacs-base
 CATEGORY = oa
 
-ELCS = sb-gud.elc sb-info.elc sb-rmail.elc sb-w3.elc speedbar.elc \
-	speedbspec.elc
+ELCS = sb-gud.elc sb-info.elc sb-rmail.elc sb-w3.elc \
+	speedbar.elc speedbspec.elc \
+	rpm.elc
+
+DATA_FILES = $(wildcard *.xpm)
+
+INFO_FILES = speedbar.info
+TEXI_FILES = speedbar.texi
+MANUAL = speedbar
 
 include ../../XEmacs.rules
 
 GENERATED += custom-load.elc
 
-all:: $(ELCS) auto-autoloads.elc custom-load.elc
+all:: $(ELCS) auto-autoloads.elc custom-load.elc $(INFO_FILES)
 
 srckit: srckit-std
 

Makefile.upstream

+# Automatically Generated Makefile by EDE.
+# For use with: make
+#
+# DO NOT MODIFY THIS FILE OR YOUR CHANGES MAY BE LOST.
+# EDE is the Emacs Development Environment.
+# http://www.ultranet.com/~zappo/ede.shtml
+# 
+
+ede_FILES=Project.ede Makefile
+
+opt_LISP=rpm.el sb-gud.el sb-info.el sb-rmail.el sb-w3.el
+EMACS=emacs!
+images_MISC=sb-dir-plus.xpm sb-dir-minus.xpm sb-dir.xpm sb-pg-plus.xpm sb-pg-minus.xpm sb-pg.xpm sb-mail.xpm sb-tag-plus.xpm sb-tag-minus.xpm sb-tag.xpm sb-tag-gt.xpm sb-tag-v.xpm
+info_INFOS=speedbar.texi
+speedbar_LISP=speedbar.el
+EMACS=emacs
+VERSION=0.11.1
+DISTDIR=speedbar-$(VERSION)
+top_builddir = 
+
+DEP_FILES=.deps/.P
+
+all: info speedbar
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+-include $(DEP_FILES)
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+opt:
+	@echo "(add-to-list 'load-path \"$(PWD)\")" > opt-compile-script
+	@echo "(setq debug-on-error t)" >> opt-compile-script
+	$(EMACS) -batch -l opt-compile-script -f batch-byte-compile  $(opt_LISP)
+images: 
+	@
+
+
+info: $(info_INFOS)
+	makeinfo speedbar.texi
+speedbar:
+	@echo "(add-to-list 'load-path \"$(PWD)\")" > speedbar-compile-script
+	@echo "(setq debug-on-error t)" >> speedbar-compile-script
+	$(EMACS) -batch -l speedbar-compile-script -f batch-byte-compile  $(speedbar_LISP)
+
+clean:
+	rm -f *.elc *.info
+
+
+dist:
+	rm -rf $(DISTDIR)
+	mkdir $(DISTDIR)
+	cp $(opt_LISP) $(images_MISC) $(info_INFOS) $(speedbar_LISP) $(ede_FILES) $(DISTDIR)
+	tar -cvzf $(DISTDIR).tar.gz $(DISTDIR)
+	rm -rf $(DISTDIR)
+
+tags: $(opt_LISP) $(images_MISC) $(info_INFOS) $(speedbar_LISP) 
+	etags $^
+
+Makefile: Project.ede
+	@echo Makefile is out of date!  It needs to be regenerated by EDE.
+	@false
+
+
+
+# End of Makefile
+;; Object ede-proj-project
+;; EDE project file.
+(ede-proj-project "ede-proj-project"
+  :name "speedbar"
+  :version "0.11.1"
+  :file "Project.ede"
+  :targets (list   (ede-proj-target-elisp "opt"
+    :name "opt"
+    :path ""
+    :source '("rpm.el" "sb-gud.el" "sb-info.el" "sb-rmail.el" "sb-w3.el")
+    :partofall 'nil
+    )
+   (ede-proj-target-makefile-miscelaneous "images"
+    :name "images"
+    :path ""
+    :source '("sb-dir-plus.xpm" "sb-dir-minus.xpm" "sb-dir.xpm" "sb-pg-plus.xpm" "sb-pg-minus.xpm" "sb-pg.xpm" "sb-mail.xpm" "sb-tag-plus.xpm" "sb-tag-minus.xpm" "sb-tag.xpm" "sb-tag-gt.xpm" "sb-tag-v.xpm")
+    :partofall 'nil
+    )
+   (ede-proj-target-makefile-info "info"
+    :name "info"
+    :path ""
+    :source '("speedbar.texi")
+    )
+   (ede-proj-target-elisp "speedbar"
+    :name "speedbar"
+    :path ""
+    :source '("speedbar.el")
+    )
+   )
+  :configuration-variables 'nil
+  )
+;;; rpm.el --- Manage Red Hat packages in emacs
+
+;;; Copyright (C) 1998, 1999 Eric M. Ludlam
+
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+;; Version: 1.0
+;; Keywords: speedbar, rpm
+;; X-RCS: $Id$
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;;
+;; Manage Red Hat system packages in emacs.  Uses speedbar to display
+;; the package higherarchy, and defines an `rpm-mode' which is useful
+;; for managing and viewing a specific package.
+;;
+;;  This tool depends on speedbar version 0.7 or higher.
+;;
+
+;;; History:
+;;
+;; 1.0  Initial revision
+
+(require 'speedbar)
+;;; Code:
+
+(defvar rpm-system nil
+  "This represents the current system.")
+
+(defvar rpm-speedbar-key-map nil
+  "Keymap used when working with RPMs in speedbar.")
+
+(if rpm-speedbar-key-map
+    nil
+  (setq rpm-speedbar-key-map (speedbar-make-specialized-keymap))
+
+  ;; General viewing pleasure...
+  (define-key speedbar-buffers-key-map "\C-m" 'speedbar-edit-line)
+  (define-key speedbar-buffers-key-map "+" 'speedbar-expand-line)
+  (define-key speedbar-buffers-key-map "-" 'speedbar-contract-line)
+
+  )
+
+(defvar rpm-speedbar-menu
+  ()
+  "Menu part in easymenu format that is used in speedbar while in rpm mode.")
+
+(defvar rpm-font-lock-keywords
+  '(
+    ;; file names
+    ("^\\(/[^ \n]+\\)$" 1 font-lock-reference-face)
+    ;; Tags
+    ("\\(Name\\|Version\\|Release\\|Install date\\|Group\\|Size\\|Packager\\|\
+Summary\\|Description\\|Distribution\\|Vendor\\|Build Date\\|Build Host\\|\
+Source RPM\\|URL\\) *:" 0 font-lock-variable-name-face)
+    ("^Name +: \\([^ \t]+\\)" 1 font-lock-function-name-face)
+    ;; Everything else is from the description.
+    ;; This is a clever font lock hack since it wont double color items
+    ("^\\([^\n]+\\)$" 1 font-lock-comment-face)
+    )
+  "Keywords used to highlight an RPM info buffer.")
+
+(defun rpm-info (package)
+  "View RPM PACKAGE information in the current buffer."
+  (interactive "sPackage: ")
+  (toggle-read-only -1)
+  (call-process "rpm" nil t nil "-qil" package)
+  (goto-char (point-min))
+  (rpm-mode)
+  (set-buffer-modified-p nil)
+  (toggle-read-only 1))
+
+(defun rpm-mode ()
+  "Major mode for viewing package information."
+  (interactive)
+  (kill-all-local-variables)
+  (setq major-mode 'rpm-mode
+	mode-name "RPM")
+  (make-local-variable 'font-lock-defaults)
+  (setq font-lock-defaults '((rpm-font-lock-keywords)
+			     t t
+			     ((?_ . "w") (?/ . "w"))))
+  (run-hooks 'rpm-info-hook))
+
+(defun rpm ()
+  "Red Hat Package Management in Emacs."
+  (interactive)
+  ;; Make sure that speedbar is active
+  (speedbar-frame-mode 1)
+  ;; Make sure our special speedbar major mode is loaded
+  (speedbar-add-expansion-list '("rpm" rpm-speedbar-menu rpm-speedbar-key-map
+				 rpm-speedbar))
+  ;; Now, throw us into RPM mode on speedbar.
+  (speedbar-change-initial-expansion-list "rpm")
+  )
+
+(defun rpm-speedbar (directory zero)
+  "Create buttons in speedbar that represents the current rpm system.
+Takes DIRECTORY and ZERO, which are both ignored."
+  (rpm-fetch-system)
+  (let ((speedbar-tag-hierarchy-method '(sort)))
+    (speedbar-insert-generic-list -1 rpm-system 'rpm-tag-expand 'rpm-tag-find)))
+
+(defun rpm-tag-expand (text token indent)
+  "Expand a tag sublist.  Imenu will return sub-lists of specialized tag types.
+Etags does not support this feature.  TEXT will be the button
+string.  TOKEN will be the list, and INDENT is the current indentation
+level."
+  (cond ((string-match "+" text)	;we have to expand this file
+	 (speedbar-change-expand-button-char ?-)
+	 (speedbar-with-writable
+	   (save-excursion
+	     (end-of-line) (forward-char 1)
+	     (let ((speedbar-tag-hierarchy-method '(sort)))
+	       (speedbar-insert-generic-list indent
+					     token
+					     'rpm-tag-expand
+					     'rpm-tag-find)))))
+	((string-match "-" text)	;we have to contract this node
+	 (speedbar-change-expand-button-char ?+)
+	 (speedbar-delete-subblock indent))
+	(t (error "Ooops... not sure what to do.")))
+  (speedbar-center-buffer-smartly))
+
+(defun rpm-tag-find (text token indent)
+  "When clicking on a found tag, open that RPM file up.
+TEXT is the name of the package.  TOKEN and INDENT are ignored."
+  (let* ((buff (get-buffer-create text))
+	 (bwin (get-buffer-window buff 0)))
+    (if bwin
+	(progn
+	  (select-window bwin)
+	  (raise-frame (window-frame bwin)))
+      (if speedbar-power-click
+	  (let ((pop-up-frames t)) (select-window (display-buffer buff)))
+	(select-frame speedbar-attached-frame)
+	(switch-to-buffer buff)))
+    (erase-buffer)
+    (rpm-info text)))
+
+(defun rpm-fetch-system ()
+  "Fetch the system by executing rpm."
+  (if rpm-system
+      nil
+    (save-excursion
+      (set-buffer (get-buffer-create "*rpm output*"))
+      ;; Get the database information here
+      (if (= (point-min) (point-max))
+	  (progn
+	    (speedbar-message "Running rpm -qa")
+	    (call-process "rpm" nil t nil "-qa" "--queryformat"
+			  "%{name}-%{version}-%{release} %{group}\n")))
+      ;; Convert it into a giant list
+      (speedbar-message "Parsing output ... ")
+      (goto-char (point-min))
+      (while (re-search-forward "^\\([^ ]+\\) \\([^\n]+\\)$" nil t)
+	(let* ((n (match-string 1))
+	       (p (match-string 2))
+	       (sl nil))
+	  ;; Start the directory listing
+	  (string-match "^\\([^/]+\\)\\(/\\|$\\)" p)
+	  (setq sl (assoc (match-string 1 p) rpm-system))
+	  (if (not sl) (setq rpm-system
+			     (cons (setq sl (list (match-string 1 p)))
+				   rpm-system)))
+	  (setq p (substring p (match-end 0)))
+	  ;; Loop to the end of the directory listing
+	  (while (string-match "^\\([^/]+\\)\\(/\\|$\\)" p)
+	    (let ((ssl (assoc (match-string 1 p) sl)))
+	      (if (not ssl)
+		  (setcdr sl (cons (setq ssl (list (match-string 1 p)))
+				   (cdr sl))))
+	      (setq sl ssl))
+	    (setq p (substring p (match-end 0))))
+	  ;; We are at the end.  Append our new element to the end
+	  (while (cdr sl) (setq sl (cdr sl)))
+	  (setcdr sl (cons (cons n 1) nil)))))))
+
+(provide 'rpm)
+;;; rpm.el ends here
Added
New image
+/* XPM */
+static char * sb_dir__xpm[] = {
+"20 15 4 1",
+" 	c None",
+".	c #828282",
+"+	c #000000",
+"@	c #FFF993",
+" .......            ",
+".+++++++.           ",
+".+@@@@@@+.......... ",
+".+@@@@@@@++++++++++.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@++++++@@@@@+.",
+".+@@@@@++++++@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".++++++++++++++++++.",
+" .................. "};
Added
New image
+/* XPM */
+static char * sb_dir+_xpm[] = {
+"20 15 4 1",
+" 	c None",
+".	c #828282",
+"+	c #000000",
+"@	c #FFF993",
+" .......            ",
+".+++++++.           ",
+".+@@@@@@+.......... ",
+".+@@@@@@@++++++++++.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@++@@@@@@@+.",
+".+@@@@@@@++@@@@@@@+.",
+".+@@@@@++++++@@@@@+.",
+".+@@@@@++++++@@@@@+.",
+".+@@@@@@@++@@@@@@@+.",
+".+@@@@@@@++@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".++++++++++++++++++.",
+" .................. "};
Added
New image
+/* XPM */
+static char * sb_dir_xpm[] = {
+"20 15 4 1",
+" 	c None",
+".	c #828282",
+"+	c #000000",
+"@	c #FFF993",
+" .......            ",
+".+++++++.           ",
+".+@@@@@@+.......... ",
+".+@@@@@@@++++++++++.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".++++++++++++++++++.",
+" .................. "};
 ;; files are displayed.  These functions provide gud specific support,
 ;; showing stacks, files, and the like in the side-bar.
 ;;
-;;   To provide special service to all the modes supported by this file,
-;; put the following in your .emacs file.
-;;
-;; (require 'speedbspec)
-;;
-;;   This will load in the known functions, and the mode-enabling code
-;; into 'change-major-mode-hook.
+;;   To enable in emacs 20.2 or earlier, add this to your .emacs file.
+;;   (autoload 'gud-speedbar-buttons "sb-gud"
+;;             "GUD specific speedbar button generator.")
 ;;
 ;;   This file requires speedbar.
 
 ;;; Change log:
-;; 0.1 - Revision
-
-(require 'speedbspec)
+;; 0.1   - First revision
+;; 0.1.1 - Removed dependency on speedbspec.
+;; 0.1.2 - Changed to handle keymap feature.
 
 ;;; Code:
 (defvar gud-last-speedbar-buffer nil
   "Description of the currently displayed GUD stack.
 t means that there is no stack, and we are in display-file mode.")
 
+(defvar gud-speedbar-key-map nil
+  "Keymap used when in the buffers display mode.")
+
+(defun gud-install-speedbar-variables ()
+  "Install those variables used by speedbar to enhance gud/gdb."
+  (if gud-speedbar-key-map
+      nil
+    (setq gud-speedbar-key-map (speedbar-make-specialized-keymap))
+
+    (define-key gud-speedbar-key-map "j" 'speedbar-edit-line)
+    (define-key gud-speedbar-key-map "e" 'speedbar-edit-line)
+    (define-key gud-speedbar-key-map "\C-m" 'speedbar-edit-line)))
+
 (defvar gud-speedbar-menu-items
   ;; Note to self.  Add expand, and turn off items when not available.
   '(["Jump to stack frame" speedbar-edit-line t])
   "Additional menu items to add the the speedbar frame.")
 
+;; Make sure our special speedbar mode is loaded
+(if (featurep 'speedbar)
+    (gud-install-speedbar-variables)
+  (add-hook 'speedbar-load-hook 'gud-install-speedbar-variables))
+
 (defun gud-speedbar-buttons (buffer)
   "Create a speedbar display based on the current state of GUD.
 If the GUD BUFFER is not running a supported debugger, then turn
   (let ((newlst nil)
 	(gud-gdb-fetched-stack-frame-list nil))
     (gud-gdb-run-command-fetch-lines "backtrace" buffer)
-    (if (string-match "No stack" (car gud-gdb-fetched-stack-frame-list))
+    (if (and (car gud-gdb-fetched-stack-frame-list)
+	     (string-match "No stack" (car gud-gdb-fetched-stack-frame-list)))
 	;; Go into some other mode???
 	nil
       (while gud-gdb-fetched-stack-frame-list
 	(let ((e (car gud-gdb-fetched-stack-frame-list))
 	      (name nil) (num nil))
 	  (if (not (or
-		    (string-match "^#\\([0-9]+\\) +[0-9a-fx]+ in \\([0-9a-zA-Z_]+\\) (" e)
-		    (string-match "^#\\([0-9]+\\) +\\([0-9a-zA-Z_]+\\) (" e)))
+		    (string-match "^#\\([0-9]+\\) +[0-9a-fx]+ in \\([:0-9a-zA-Z_]+\\) (" e)
+		    (string-match "^#\\([0-9]+\\) +\\([:0-9a-zA-Z_]+\\) (" e)))
 	      (if (not (string-match
 			"at \\([-0-9a-zA-Z_.]+\\):\\([0-9]+\\)$" e))
 		  nil
 ;;; sb-info --- Speedbar support for Info
 
-;; Copyright (C) 1997, 1998 Free Software Foundation
+;; Copyright (C) 1997, 1998, 2000 Free Software Foundation
 ;;
 ;; Author: Eric M. Ludlam <zappo@gnu.ai.mit.edu>
-;; Version: 0.1
+;; Version: 0.3
 ;; Keywords: file, tags, tools
 ;; X-RCS: $Id$
 ;;
-;; This file is part of GNU Emacs.
+;; This file is patch of GNU Emacs.
 ;;
 ;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;;              675 Mass Ave.
 ;;              Cambridge, MA 02139, USA.
 ;;
-;; Please send bug reports, etc. to zappo@gnu.ai.mit.edu.
+;; Please send bug reports, etc. to zappo@gnu.org
 ;;
 
 ;;; Commentary:
 ;; files are displayed.  These functions provide Info specific support,
 ;; showing links and addresses in the side-bar.
 ;;
-;;   To provide special service to all the modes supported by this file,
-;; put the following in your .emacs file.
+;;   To enable in Emacs 20.2 or earlier, add this to your .emacs file.
+;;   (autoload 'Info-speedbar-buttons "sb-info"
+;;             "Info specific speedbar button generator.")
 ;;
-;; (require 'speedbspec)
-;;
-;;   This will load in the known functions, and the mode-enabling code
-;; into 'change-major-mode-hook.
-;;
-;;   This file requires speedbar.
+;;   This file requires speedbar and Info.
 
 ;;; Change log:
-;; 0.1 - first revision copied from speedbspec.el V 0.1.1
+;; 0.1   - first revision copied from speedbspec.el V 0.1.1
+;; 0.1.1 - No longer require speedbspec
+;; 0.2   - Added a speedbar major mode for displaying Info nodes, and modeled
+;;         the minor mode after it.  Completely replaced the old info display
+;;         with the major mode, and mixed them to move nicely from major to
+;;         minor mode effortlessly.
+;; 0.2.1   Added section adding major display mode at load time.
 
-(require 'speedbspec)
+;(require 'speedbar)
+(require 'info)
 
 ;;; Code:
-(defvar Info-last-speedbar-node nil
-  "Last node viewed with speedbar in the form '(NODE FILE).")
+(defvar Info-speedbar-key-map nil
+  "Keymap used when in the info display mode.")
+
+(defun Info-install-speedbar-variables ()
+  "Install those variables used by speedbar to enhance Info."
+  (if Info-speedbar-key-map
+      nil
+    (setq Info-speedbar-key-map (speedbar-make-specialized-keymap))
+
+    ;; Basic tree features
+    (define-key Info-speedbar-key-map "e" 'speedbar-edit-line)
+    (define-key Info-speedbar-key-map "\C-m" 'speedbar-edit-line)
+    (define-key Info-speedbar-key-map "+" 'speedbar-expand-line)
+    (define-key Info-speedbar-key-map "=" 'speedbar-expand-line)
+    (define-key Info-speedbar-key-map "-" 'speedbar-contract-line)
+    )
+
+  (speedbar-add-expansion-list '("Info" Info-speedbar-menu-items
+				 Info-speedbar-key-map
+				 Info-speedbar-hierarchy-buttons)))
 
 (defvar Info-speedbar-menu-items
-  '(["Browse Item On Line" speedbar-edit-line t])
+  '(["Browse Node" speedbar-edit-line t]
+    ["Expand Node" speedbar-expand-line
+     (save-excursion (beginning-of-line)
+		     (looking-at "[0-9]+: *.\\+. "))]
+    ["Contract Node" speedbar-contract-line
+     (save-excursion (beginning-of-line)
+		     (looking-at "[0-9]+: *.-. "))]
+    )
   "Additional menu-items to add to speedbar frame.")
 
+;; Make sure our special speedbar major mode is loaded
+(if (featurep 'speedbar)
+    (Info-install-speedbar-variables)
+  (add-hook 'speedbar-load-hook 'Info-install-speedbar-variables))
+
+;;; Info hierarchy display method
+;;;###autoload
+(defun Info-speedbar-browser ()
+  "Initialize speedbar to display an info node browser.
+This will add a speedbar major display mode."
+  (interactive)
+  (require 'speedbar)
+  ;; Make sure that speedbar is active
+  (speedbar-frame-mode 1)
+  ;; Now, throw us into Info mode on speedbar.
+  (speedbar-change-initial-expansion-list "Info")
+  )
+
+(defun Info-speedbar-hierarchy-buttons (directory depth &optional node)
+  "Display an Info directory hierarchy in speedbar.
+DIRECTORY is the current directory in the attached frame.
+DEPTH is the current indentation depth.
+NODE is an optional argument that is used to represent the
+specific node to expand."
+  (if (and (not node)
+	   (save-excursion (goto-char (point-min))
+			   (looking-at "Info Nodes:")))
+      ;; Update our "current node" maybe?
+      nil
+    ;; We cannot use the generic list code, that depends on all leaves
+    ;; being known at creation time.
+    (if (not node)
+	(speedbar-with-writable (insert "Info Nodes:\n")))
+    (let ((completions nil)
+	  (cf (selected-frame)))
+      (select-frame speedbar-attached-frame)
+      (save-window-excursion
+	(setq completions
+	      (Info-speedbar-fetch-file-nodes (or node '"(dir)top"))))
+      (select-frame cf)
+      (if completions
+	  (speedbar-with-writable
+	   (while completions
+	     (speedbar-make-tag-line 'bracket ?+ 'Info-speedbar-expand-node
+				     (cdr (car completions))
+				     (car (car completions))
+				     'Info-speedbar-goto-node
+				     (cdr (car completions))
+				     'info-xref depth)
+	     (setq completions (cdr completions)))
+	   t)
+	nil))))
+  
+(defun Info-speedbar-goto-node (text node indent)
+  "When user clicks on TEXT, goto an info NODE.
+The INDENT level is ignored."
+    (select-frame speedbar-attached-frame)
+    (let* ((buff (or (get-buffer "*info*")
+		     (progn (info) (get-buffer "*info*"))))
+	   (bwin (get-buffer-window buff 0)))
+      (if bwin
+	  (progn
+	    (select-window bwin)
+	    (raise-frame (window-frame bwin)))
+	(if speedbar-power-click
+	    (let ((pop-up-frames t)) (select-window (display-buffer buff)))
+	  (select-frame speedbar-attached-frame)
+	  (switch-to-buffer buff)))
+      (if (string-match "^(\\([^)]+\\))\\([^.]+\\)$" node)
+	  (let ((file (match-string 1 node))
+		(node (match-string 2 node)))
+	    (Info-find-node file node)
+	    ;; If we do a find-node, and we were in info mode, restore
+	    ;; the old default method.  Once we are in info mode, it makes
+	    ;; sense to return to whatever method the user was using before.
+	    (if (string= speedbar-initial-expansion-list-name "Info")
+		(speedbar-change-initial-expansion-list
+		 speedbar-previously-used-expansion-list-name))))))
+
+(defun Info-speedbar-expand-node (text token indent)
+  "Expand the node the user clicked on.
+TEXT is the text of the button we clicked on, a + or - item.
+TOKEN is data related to this node (NAME . FILE).
+INDENT is the current indentation depth."
+  (cond ((string-match "+" text)	;we have to expand this file
+	 (speedbar-change-expand-button-char ?-)
+	 (if (speedbar-with-writable
+	       (save-excursion
+		 (end-of-line) (forward-char 1)
+		 (Info-speedbar-hierarchy-buttons nil (1+ indent) token)))
+	     (speedbar-change-expand-button-char ?-)
+	   (speedbar-change-expand-button-char ??)))
+	((string-match "-" text)	;we have to contract this node
+	 (speedbar-change-expand-button-char ?+)
+	 (speedbar-delete-subblock indent))
+	(t (error "Ooops... not sure what to do")))
+  (speedbar-center-buffer-smartly))
+
+(defun Info-speedbar-fetch-file-nodes (nodespec)
+  "Fetch the subnodes from the info NODESPEC.
+NODESPEC is a string of the form: (file)node.
+Optional THISFILE represends the filename of"
+  (save-excursion
+    ;; Set up a buffer we can use to fake-out Info.
+    (set-buffer (get-buffer-create "*info-browse-tmp*"))
+    (if (not (equal major-mode 'Info-mode))
+	(Info-mode))
+    ;; Get the node into this buffer
+    (if (string-match "^(\\([^)]+\\))\\([^.]+\\)$" nodespec)
+	(let ((file (match-string 1 nodespec))
+	      (node (match-string 2 nodespec)))
+	  (Info-find-node file node))
+      (error "Node %s not found!" nodespec))
+    ;; Scan the created buffer
+    (goto-char (point-min))
+    (let ((completions nil)
+	  (thisfile (progn (string-match "^(\\([^)]+\\))" nodespec)
+			   (match-string 1 nodespec))))
+      ;; Always skip the first one...
+      (re-search-forward "\n\\* \\([^:\t\n]*\\):" nil t)
+      (while (re-search-forward "\n\\* \\([^:\t\n]*\\):" nil t)
+	(let ((name (match-string 1)))
+	  (if (looking-at " *\\(([^)]+)[^.\n]+\\)\\.")
+	      (setq name (cons name (match-string 1)))
+	    (if (looking-at "[ \t]*\\(([^)]+)\\)\\.")
+		(setq name (cons name (concat (match-string 1) "Top")))
+	      (if (looking-at " \\([^.]+\\).")
+		  (setq name
+			(cons name (concat "(" thisfile ")" (match-string 1))))
+		(setq name (cons name (concat "(" thisfile ")" name))))))
+	  (setq completions (cons name completions))))
+      (nreverse completions))))
+
+;;; Info mode node listing
 (defun Info-speedbar-buttons (buffer)
   "Create a speedbar display to help navigation in an Info file.
 BUFFER is the buffer speedbar is requesting buttons for."
-  (goto-char (point-min))
-  (if (and (looking-at "<Directory>")
-	   (save-excursion
-	     (set-buffer buffer)
-	     (and (equal (car Info-last-speedbar-node) Info-current-node)
-		  (equal (cdr Info-last-speedbar-node) Info-current-file))))
-      nil
-    (erase-buffer)
-    (speedbar-insert-button "<Directory>" 'info-xref 'highlight
-			    'Info-speedbar-button
-			    'Info-directory)
-    (speedbar-insert-button "<Top>" 'info-xref 'highlight
-			    'Info-speedbar-button
-			    'Info-top-node)
-    (speedbar-insert-button "<Last>" 'info-xref 'highlight
-			    'Info-speedbar-button
-			    'Info-last)
-    (speedbar-insert-button "<Up>" 'info-xref 'highlight
-			    'Info-speedbar-button
-			    'Info-up)
-    (speedbar-insert-button "<Next>" 'info-xref 'highlight
-			    'Info-speedbar-button
-			    'Info-next)
-    (speedbar-insert-button "<Prev>" 'info-xref 'highlight
-			    'Info-speedbar-button
-			    'Info-prev)
-    (let ((completions nil))
-      (save-excursion
-	(set-buffer buffer)
-	(setq Info-last-speedbar-node
-	      (cons Info-current-node Info-current-file))
-	(goto-char (point-min))
-	;; Always skip the first one...
-	(re-search-forward "\n\\* \\([^:\t\n]*\\):" nil t)
-	(while (re-search-forward "\n\\* \\([^:\t\n]*\\):" nil t)
-	  (setq completions (cons (buffer-substring (match-beginning 1)
-						    (match-end 1))
-				  completions))))
-      (setq completions (nreverse completions))
-      (while completions
-	(speedbar-make-tag-line nil nil nil nil
-				(car completions) 'Info-speedbar-menu
-				nil 'info-node 0)
-	(setq completions (cdr completions))))))
-
-(defun Info-speedbar-button (text token indent)
-  "Called when user clicks <Directory> from speedbar.
-TEXT, TOKEN, and INDENT are unused."
-  (speedbar-with-attached-buffer
-   (funcall token)
-   (setq Info-last-speedbar-node nil)
-   (speedbar-update-contents)))
-
-(defun Info-speedbar-menu (text token indent)
-  "Goto the menu node specified in TEXT.
-TOKEN and INDENT are not used."
-  (speedbar-with-attached-buffer
-   (Info-menu text)
-   (setq Info-last-speedbar-node nil)
-   (speedbar-update-contents)))
+  (if (save-excursion (goto-char (point-min))
+		      (not (looking-at "Info Nodes:")))
+      (erase-buffer))
+  (Info-speedbar-hierarchy-buttons nil 0)
+  )
 
 (provide 'sb-info)
 ;;; sb-info.el ends here
Added
New image
+/* XPM */
+static char * sb_mail_xpm[] = {
+"20 15 4 1",
+" 	c None",
+".	c #828282",
+"+	c #000000",
+"@	c #FFFFFF",
+"................... ",
+".++++++++++++++++++.",
+".++@@@@@@@@@@@@@@++.",
+".+@++@@@@@@@@@@++@+.",
+".+@@@++@@@@@@++@@@+.",
+".+@@@@@++@@++@@@@@+.",
+".+@@@@@@@++@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@+@@@@@@+@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@+@@@@@@@@@@+@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".++@@@@@@@@@@@@@@++.",
+".++++++++++++++++++.",
+" .................. "};
Added
New image
+/* XPM */
+static char * sb_file__xpm[] = {
+"20 15 4 1",
+" 	c None",
+".	c #828282",
+"+	c #000000",
+"@	c #FFFFFF",
+"       ............ ",
+"      .++++++++++++.",
+"     .++@@@@@@@@@@+.",
+"    .+@+@@@@@@@@@@+.",
+"   .+@@+@@@@@@@@@@+.",
+"  .+@@@+@@@@@@@@@@+.",
+" .+@@@@+@@@@@@@@@@+.",
+".+++++++@++++++@@@+.",
+".+@@@@@@@++++++@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".++++++++++++++++++.",
+" .................. "};
Added
New image
+/* XPM */
+static char * sb_file+_xpm[] = {
+"20 15 4 1",
+" 	c None",
+".	c #828282",
+"+	c #000000",
+"@	c #FFFFFF",
+"       ............ ",
+"      .++++++++++++.",
+"     .++@@@@@@@@@@+.",
+"    .+@+@@@@@@@@@@+.",
+"   .+@@+@@@@@@@@@@+.",
+"  .+@@@+@@@++@@@@@+.",
+" .+@@@@+@@@++@@@@@+.",
+".+++++++@++++++@@@+.",
+".+@@@@@@@++++++@@@+.",
+".+@@@@@@@@@++@@@@@+.",
+".+@@@@@@@@@++@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".++++++++++++++++++.",
+" .................. "};
Added
New image
+/* XPM */
+static char * sb_file_xpm[] = {
+"20 15 4 1",
+" 	c None",
+".	c #828282",
+"+	c #000000",
+"@	c #FFFFFF",
+"       ............ ",
+"      .++++++++++++.",
+"     .++@@@@@@@@@@+.",
+"    .+@+@@@@@@@@@@+.",
+"   .+@@+@@@@@@@@@@+.",
+"  .+@@@+@@@@@@@@@@+.",
+" .+@@@@+@@@@@@@@@@+.",
+".+++++++@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".++++++++++++++++++.",
+" .................. "};
 ;;; sb-rmail --- Speedbar support for rmail
 
-;; Copyright (C) 1997, 1998 Free Software Foundation
+;; Copyright (C) 1997, 1998, 1999 Free Software Foundation
 ;;
 ;; Author: Eric M. Ludlam <zappo@gnu.ai.mit.edu>
 ;; Version: 0.1
 ;; files are displayed.  These functions provide rmail specific support,
 ;; showing links and addresses in the side-bar.
 ;;
-;;   To provide special service to all the modes supported by this file,
-;; put the following in your .emacs file.
-;;
-;; (require 'speedbspec)
-;;
-;;   This will load in the known functions, and the mode-enabling code
-;; into 'change-major-mode-hook.
+;;   To enable in emacs 20.2 or earlier, add this to your .emacs file.
+;;   (autoload 'rmail-speedbar-buttons "sb-rmail"
+;;             "Rmail specific speedbar button generator.")
 ;;
 ;;   This file requires speedbar.
 
 ;;; Change log:
-;; 0.1 - first revision copied from speedbspec.el V 0.1.1
-
-(require 'speedbspec)
+;; 0.1   - first revision copied from speedbspec.el V 0.1.1
+;; 0.1.1 - removed require speedbspec.
+;; 0.1.2 - Changed to handle new keymap feature.
 
 ;;; Code:
+(defvar rmail-speedbar-match-folder-regexp "^[A-Z0-9]+\\(\\.[A-Z0-9]+\\)?$"
+  "*This regex us used to match folder names to be displayed in speedbar.
+Enabling this will permit speedbar to display your folders for easy
+browsing, and moving of messages.")
+
 (defvar rmail-speedbar-last-user nil
   "The last user to be displayed in the speedbar.")
 
+(defvar rmail-speedbar-key-map nil
+  "Keymap used when in rmail display mode.")
+
+(defun rmail-install-speedbar-variables ()
+  "Install those variables used by speedbar to enhance rmail."
+  (if rmail-speedbar-key-map
+      nil
+    (setq rmail-speedbar-key-map (speedbar-make-specialized-keymap))
+
+    (define-key rmail-speedbar-key-map "e" 'speedbar-edit-line)
+    (define-key rmail-speedbar-key-map "r" 'speedbar-edit-line)
+    (define-key rmail-speedbar-key-map "\C-m" 'speedbar-edit-line)
+    (define-key rmail-speedbar-key-map "M"
+      'rmail-speedbar-move-message-to-folder-on-line)))
+
 (defvar rmail-speedbar-menu-items
-  '(["Browse Item On Line" speedbar-edit-line t]
-    ["Move message to folder" rmail-move-message-to-folder-on-line
+  '(["Read Folder" speedbar-edit-line t]
+    ["Move message to folder" rmail-speedbar-move-message-to-folder-on-line
      (save-excursion (beginning-of-line)
 		     (looking-at "<M> "))])
   "Additional menu-items to add to speedbar frame.")
 
+;; Make sure our special speedbar major mode is loaded
+(if (featurep 'speedbar)
+    (rmail-install-speedbar-variables)
+  (add-hook 'speedbar-load-hook 'rmail-install-speedbar-variables))
+
 (defun rmail-speedbar-buttons (buffer)
   "Create buttons for BUFFER containing rmail messages.
 Click on the address under Reply to: to reply to this person.
       (let* ((case-fold-search nil)
 	     (df (directory-files (save-excursion (set-buffer buffer)
 						  default-directory)
-				  nil "^[A-Z0-9]+\\(\\.[A-Z0-9]+\\)?$")))
+				  nil rmail-speedbar-match-folder-regexp)))
 	(while df
 	  (speedbar-insert-button "<M>" 'speedbar-button-face 'highlight
 				  'rmail-speedbar-move-message (car df))
   "Load in the rmail file TEXT.
 TOKEN and INDENT are not used."
   (speedbar-with-attached-buffer
-   (message "Loading in RMAIL file %s..." text)
+   (speedbar-message "Loading in RMAIL file %s..." text)
    (find-file text)))
 
-(defun rmail-move-message-to-folder-on-line ()
+(defun rmail-speedbar-move-message-to-folder-on-line ()
   "If the current line is a folder, move current message to it."
   (interactive)
   (save-excursion
Added
New image
+/* XPM */
+static char * sb_tag_gt_xpm[] = {
+"20 15 4 1",
+" 	c None",
+".	c #828282",
+"+	c #000000",
+"@	c #FFF993",
+"                    ",
+"                    ",
+"    ............... ",
+"   .+++++++++++++++.",
+"  .+@@@@@++@@@@@@@+.",
+" .+@@@@@@+++@@@@@@+.",
+".+@@@@@@@++++@@@@@+.",
+".+@++@@@@+++++@@@@+.",
+".+@++@@@@+++++.@@@+.",
+".+@@@@@@@++++.@@@@+.",
+" .+@@@@@@+++.@@@@@+.",
+"  .+@@@@@++.@@@@@@+.",
+".  .++++++.++++++++.",
+"    ............... ",
+"                    "};
Added
New image
+/* XPM */
+static char * sb_tag__xpm[] = {
+"20 15 4 1",
+" 	c None",
+".	c #828282",
+"+	c #000000",
+"@	c #FFF993",
+"                    ",
+"                    ",
+"    ............... ",
+"   .+++++++++++++++.",
+"  .+@@@@@@@@@@@@@@+.",
+" .+@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@++@@++++++@@@@@+.",
+".+@++@@++++++@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+" .+@@@@@@@@@@@@@@@+.",
+"  .+@@@@@@@@@@@@@@+.",
+".  .+++++++++++++++.",
+"    ............... ",
+"                    "};
Added
New image
+/* XPM */
+static char * sb_tag+_xpm[] = {
+"20 15 4 1",
+" 	c None",
+".	c #828282",
+"+	c #000000",
+"@	c #FFF993",
+"                    ",
+"                    ",
+"    ............... ",
+"   .+++++++++++++++.",
+"  .+@@@@@@@@@@@@@@+.",
+" .+@@@@@@++@@@@@@@+.",
+".+@@@@@@@++@@@@@@@+.",
+".+@++@@++++++@@@@@+.",
+".+@++@@++++++@@@@@+.",
+".+@@@@@@@++@@@@@@@+.",
+" .+@@@@@@++@@@@@@@+.",
+"  .+@@@@@@@@@@@@@@+.",
+".  .+++++++++++++++.",
+"    ............... ",
+"                    "};
Added
New image
+/* XPM */
+static char * sb_tag_v_xpm[] = {
+"20 15 4 1",
+" 	c None",
+".	c #828282",
+"+	c #000000",
+"@	c #FFF993",
+"                    ",
+"                    ",
+"    ............... ",
+"   .+++++++++++++++.",
+"  .+@@@@@@@@@@@@@@+.",
+" .+@@@++++++++++.@+.",
+".+@@@@@++++++++.@@+.",
+".+@++@@@++++++.@@@+.",
+".+@++@@@@++++.@@@@+.",
+".+@@@@@@@@++.@@@@@+.",
+" .+@@@@@@@@.@@@@@@+.",
+"  .+@@@@@@@@@@@@@@+.",
+".  .+++++++++++++++.",
+"    ............... ",
+"                    "};
Added
New image
+/* XPM */
+static char * sb_tag_xpm[] = {
+"20 15 4 1",
+" 	c None",
+".	c #828282",
+"+	c #000000",
+"@	c #FFF993",
+"                    ",
+"                    ",
+"    ............... ",
+"   .+++++++++++++++.",
+"  .+@@@@@@@@@@@@@@+.",
+" .+@@@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+".+@++@@@@@@@@@@@@@+.",
+".+@++@@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@@@@@+.",
+" .+@@@@@@@@@@@@@@@+.",
+"  .+@@@@@@@@@@@@@@+.",
+".  .+++++++++++++++.",
+"    ............... ",
+"                    "};
 ;;; sb-w3 --- Speedbar support for w3.
 
-;; Copyright (C) 1997 Free Software Foundation
+;; Copyright (C) 1997, 1998 Free Software Foundation
 ;;
-;; Author: Eric M. Ludlam <zappo@gnu.ai.mit.edu>
-;; Version: 0.1
-;; Keywords: file, tags, tools
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+;; Version: 0.2.1
+;; Keywords: tags, tools, w3
 ;; X-RCS: $Id$
 ;;
 ;; This program is free software; you can redistribute it and/or modify
 ;;              675 Mass Ave.
 ;;              Cambridge, MA 02139, USA.
 ;;
-;; Please send bug reports, etc. to zappo@gnu.ai.mit.edu.
+;; Please send bug reports, etc. to zappo@gnu.org
 ;;
 
 ;;; Commentary:
 ;; files are displayed.  These functions provide w3 specific support,
 ;; showing links and addresses in the side-bar.
 ;;
-;;   To provide special service to all the modes supported by this file,
-;; put the following in your .emacs file.
+;;   To enable, add this to your .emacs file.
+;;   (autoload 'w3-speedbar-buttons "sb-w3"
+;;             "W3 specific speedbar button generator.")
 ;;
-;; (require 'speedbspec)
-;;
-;;   This will load in the known functions, and the mode-enabling code
-;; into 'change-major-mode-hook.
+;;   Load w3-toc to get additional tags which represent the major
+;;   headers in a given web page.
 ;;
 ;;   This file requires speedbar.
 
 ;;; Change log:
-;; 0.1 - first revision copied from speedbspec.el V 0.1.1
-
-(require 'speedbspec)
+;; 0.1   - first revision copied from speedbspec.el V 0.1.1
+;; 0.1.1 - Removed dependency on speedbspec
+;; 0.2   - T.V.Raman's addition using newer w3, and w3 imenu.
+;; 0.2.1 - Added new keymap support
 
 ;;; Code:
+(condition-case nil
+    (require 'w3-imenu)
+  (error nil))
+(require 'cl)
+(require 'speedbar)
+
 (defvar w3-speedbar-last-buffer nil
   "The last buffer shown by w3-speedbar.")
 
+(defvar w3-speedbar-key-map nil
+  "Keymap used when in the w3 display mode.")
+
+(if w3-speedbar-key-map
+    nil
+  (setq w3-speedbar-key-map (speedbar-make-specialized-keymap))
+
+  ;; Basic features.
+  (define-key w3-speedbar-key-map "e" 'speedbar-edit-line)
+  (define-key w3-speedbar-key-map "r" 'speedbar-edit-line)
+  (define-key w3-speedbar-key-map "\C-m" 'speedbar-edit-line)
+  )
+
+(defvar w3-speedbar-menu-items
+  '(["Jump to link" speedbar-edit-line t]
+    )
+  "Extra menu items for w3 mode.")
+
 (defun w3-speedbar-buttons (buffer)
   "Create speedbar buttons for the current web BUFFER displayed in w3 mode."
   (save-excursion
 	nil
       (setq w3-speedbar-last-buffer buffer)
       (erase-buffer)
-      (let ((links (save-excursion (set-buffer buffer) (w3-only-links)))
+      (let ((links (save-excursion (set-buffer buffer)
+                                   (w3-only-links)))
+            (toc (save-excursion
+                   (set-buffer buffer) imenu--index-alist))
 	    (part nil))
 	(insert "History:\n")
 	;; This taken out of w3 which was used to create the history list,
 	 url-history-list)
 	(insert "Links:\n")
 	(while links
-	  (setq part (car (cdr (member 'href (car links))))
+	  (setq part (car (cdr (member ':href (car links))))
 		links (cdr links))
-	  (speedbar-insert-button (w3-speedbar-shorten-button part)
-				  'speedbar-file-face 'highlight
-				  'w3-speedbar-link part))))))
+          (when part 
+            (speedbar-insert-button (w3-speedbar-shorten-button part)
+                                    'speedbar-file-face 'highlight
+                                    'w3-speedbar-link
+                                    part)))
+	(if (not (featurep 'w3-imenu))
+	    nil
+	  (insert (format "Contents: %d\n" (length toc)))
+	  (loop for e in toc do
+		(when (car e)
+		  (speedbar-insert-button  (car e)
+					   'bold 'highlight
+					   'w3-speedbar-goto-marker
+					   (cdr e)
+					   'prevline))))))))
+
+(defun w3-speedbar-goto-marker (txt marker indent)
+  "Speedbar callback function for jumping to a marker in a w3 buffer.
+TXT is unused.  MARKER is the location.  INDENT is unused."
+  (pop-to-buffer (marker-buffer marker))
+  (goto-char (marker-position marker)))
     
 (defun w3-speedbar-shorten-button (button)
   "Takes text BUTTON and shortens it as much as possible."
-  ;; I should make this more complex, but I'm not sure how...
-  (let ((fnnd (file-name-nondirectory button)))
-    (if (< 0 (length fnnd))
-	fnnd
-      (if (string-match "\\(ht\\|f\\)tp://" button)
-	  (setq button (substring button (match-end 0))))
-      (if (string-match "/$" button)
-	  (setq button (substring button 0 (match-beginning 0))))
-      button)))
+  ;; I should make this more complex, but I'm not sure
+  ;; how...
+  (when button 
+    (let ((fnnd (file-name-nondirectory button)))
+      (if (< 0 (length fnnd))
+	  fnnd
+	(if (string-match "\\(ht\\|f\\)tp://" button)
+	    (setq button (substring button (match-end 0))))
+	(if (string-match "/$" button)
+	    (setq button (substring button 0 (match-beginning 0))))
+	button))))
 
 (defun w3-speedbar-link (text token indent)
   "Follow link described by TEXT which has the URL TOKEN.
 INDENT is not used."
   (speedbar-with-attached-buffer (w3-fetch token)))
 
-
 (provide 'sb-w3)
 ;;; sb-w3.el ends here

sb-w3.el.upstream

+;;; sb-w3 --- Speedbar support for w3.
+
+;; Copyright (C) 1997, 1998 Free Software Foundation
+;;
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+;; Version: 0.2.1
+;; Keywords: tags, tools, w3
+;; X-RCS: $Id$
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, you can either send email to this
+;; program's author (see below) or write to:
+;;
+;;              The Free Software Foundation, Inc.
+;;              675 Mass Ave.
+;;              Cambridge, MA 02139, USA.
+;;
+;; Please send bug reports, etc. to zappo@gnu.org
+;;
+
+;;; Commentary:
+;;
+;;   Speedbar provides a frame in which files, and locations in
+;; files are displayed.  These functions provide w3 specific support,
+;; showing links and addresses in the side-bar.
+;;
+;;   To enable, add this to your .emacs file.
+;;   (autoload 'w3-speedbar-buttons "sb-w3"
+;;             "W3 specific speedbar button generator.")
+;;
+;;   Load w3-toc to get additional tags which represent the major
+;;   headers in a given web page.
+;;
+;;   This file requires speedbar.
+
+;;; Change log:
+;; 0.1   - first revision copied from speedbspec.el V 0.1.1
+;; 0.1.1 - Removed dependency on speedbspec
+;; 0.2   - T.V.Raman's addition using newer w3, and w3 imenu.
+;; 0.2.1 - Added new keymap support
+
+;;; Code:
+(require 'w3-imenu)
+(require 'cl)
+(require 'speedbar)
+
+(defvar w3-speedbar-last-buffer nil
+  "The last buffer shown by w3-speedbar.")
+
+(defvar w3-speedbar-key-map nil
+  "Keymap used when in the w3 display mode.")
+
+(if w3-speedbar-key-map
+    nil
+  (setq w3-speedbar-key-map (speedbar-make-specialized-keymap))
+
+  ;; Basic features.
+  (define-key w3-speedbar-key-map "e" 'speedbar-edit-line)
+  (define-key w3-speedbar-key-map "r" 'speedbar-edit-line)
+  (define-key w3-speedbar-key-map "\C-m" 'speedbar-edit-line)
+  )
+
+(defvar w3-speedbar-menu-items
+  '(["Jump to link" speedbar-edit-line t]
+    )
+  "Extra menu items for w3 mode.")
+
+(defun w3-speedbar-buttons (buffer)
+  "Create speedbar buttons for the current web BUFFER displayed in w3 mode."
+  (save-excursion
+    (goto-char (point-min))
+    (if (and (looking-at "History:") (equal w3-speedbar-last-buffer buffer))
+	nil
+      (setq w3-speedbar-last-buffer buffer)
+      (erase-buffer)
+      (let ((links (save-excursion (set-buffer buffer)
+                                   (w3-only-links)))
+            (toc (save-excursion
+                   (set-buffer buffer) imenu--index-alist))
+	    (part nil))
+	(insert "History:\n")
+	;; This taken out of w3 which was used to create the history list,
+	;; and is here modified to create the speedbar buttons
+	(cl-maphash
+	 (function
+	  (lambda (url desc)
+	    (speedbar-insert-button (w3-speedbar-shorten-button url)
+				    'speedbar-directory-face 'highlight
+				    'w3-speedbar-link url)))
+	 url-history-list)
+	(insert "Links:\n")
+	(while links
+	  (setq part (car (cdr (member ':href (car links))))
+		links (cdr links))
+          (when part 
+            (speedbar-insert-button (w3-speedbar-shorten-button part)
+                                    'speedbar-file-face 'highlight
+                                    'w3-speedbar-link
+                                    part)))
+	(if (not (featurep 'w3-imenu))
+	    nil
+	  (insert (format "Contents: %d\n" (length toc)))
+	  (loop for e in toc do
+		(when (car e)
+		  (speedbar-insert-button  (car e)
+					   'bold 'highlight
+					   'w3-speedbar-goto-marker
+					   (cdr e)
+					   'prevline))))))))
+
+(defun w3-speedbar-goto-marker (txt marker indent)
+  "Speedbar callback function for jumping to a marker in a w3 buffer.
+TXT is unused.  MARKER is the location.  INDENT is unused."
+  (pop-to-buffer (marker-buffer marker))
+  (goto-char (marker-position marker)))
+    
+(defun w3-speedbar-shorten-button (button)
+  "Takes text BUTTON and shortens it as much as possible."
+  ;; I should make this more complex, but I'm not sure
+  ;; how...
+  (when button 
+    (let ((fnnd (file-name-nondirectory button)))
+      (if (< 0 (length fnnd))
+	  fnnd
+	(if (string-match "\\(ht\\|f\\)tp://" button)
+	    (setq button (substring button (match-end 0))))
+	(if (string-match "/$" button)
+	    (setq button (substring button 0 (match-beginning 0))))
+	button))))
+
+(defun w3-speedbar-link (text token indent)
+  "Follow link described by TEXT which has the URL TOKEN.
+INDENT is not used."
+  (speedbar-with-attached-buffer (w3-fetch token)))
+
+(provide 'sb-w3)
+;;; sb-w3.el ends here
 ;;; speedbar --- quick access to files and tags in a frame
 
-;;; Copyright (C) 1996, 97, 98, 99 Free Software Foundation
+;;; Copyright (C) 1996, 97, 98, 99, 00 Free Software Foundation
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
-;; Version: 0.8.1
+;; Version: 0.11
 ;; Keywords: file, tags, tools
 ;; X-RCS: $Id$
 
 ;; This file is part of GNU Emacs.
-;;
-;; This program is free software; you can redistribute it and/or modify
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;; the Free Software Foundation; either version 2, or (at your option)
 ;; any later version.
-;;
-;; This program is distributed in the hope that it will be useful,
+
+;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;; GNU General Public License for more details.
 ;;
 ;; Adding a speedbar top-level display mode:
 ;;
-;; Unlike the specialized modes, there are no name requirements,
+;;  Unlike the specialized modes, there are no name requirements,
 ;; however the methods for writing a button display, menu, and keymap
 ;; are the same.  Once you create these items, you can call the
 ;; function `speedbar-add-expansion-list'.  It takes one parameter
 ;;; TODO:
 ;; - More functions to create buttons and options
 ;; - Timeout directories we haven't visited in a while.
-;; - Remeber tags when refreshing the display.  (Refresh tags too?)
-;; - More 'special mode support.
 
 (require 'assoc)
 (require 'easymenu)
 
+(condition-case nil
+    (require 'image)
+  (error nil))
+
 (defvar speedbar-xemacsp (string-match "XEmacs" emacs-version)
   "Non-nil if we are running in the XEmacs environment.")
 (defvar speedbar-xemacs20p (and speedbar-xemacsp
-				(= emacs-major-version 20)))
-
-;; From custom web page for compatibility between versions of custom:
+				(>= emacs-major-version 20)))
+
+;; From custom web page for compatibility between versions of custom
+;; with help from ptype@dera.gov.uk (Proto Type)
 (eval-and-compile
   (condition-case ()
       (require 'custom)
 	   (fboundp 'custom-initialize-set))
       nil ;; We've got what we needed
     ;; We have the old custom-library, hack around it!
-    (defmacro defgroup (&rest args)
-      nil)
-    (defmacro defface (var values doc &rest args)
-      (` (progn
-	   (defvar (, var) (quote (, var)))
-	   ;; To make colors for your faces you need to set your .Xdefaults
-	   ;; or set them up ahead of time in your .emacs file.
-	   (make-face (, var))
-	   )))
-    (defmacro defcustom (var value doc &rest args)
-      (` (defvar (, var) (, value) (, doc))))))
+    (if (boundp 'defgroup)
+	nil
+      (defmacro defgroup (&rest args)
+	nil))
+    (if (boundp 'defface)
+	nil
+      (defmacro defface (var values doc &rest args)
+	(` (progn
+	     (defvar (, var) (quote (, var)))
+	     ;; To make colors for your faces you need to set your .Xdefaults
+	     ;; or set them up ahead of time in your .emacs file.
+	     (make-face (, var))
+	     ))))
+    (if (boundp 'defcustom)
+	nil
+      (defmacro defcustom (var value doc &rest args)
+	(` (defvar (, var) (, value) (, doc)))))))
 
 ;; customization stuff
 (defgroup speedbar nil
   "File and tag browser frame."
   :group 'tags
-  :group 'tools)
+;  :group 'tools
+;  :group 'convenience
+;  :version "20.3"
+  )
 
 (defgroup speedbar-faces nil
   "Faces used in speedbar."
   :group 'speedbar
   :type 'hook)
 
-(defcustom speedbar-visiting-tag-hook nil
+(defcustom speedbar-visiting-tag-hook '(speedbar-highlight-one-tag-line)
   "Hooks run when speedbar visits a tag in the selected frame."
   :group 'speedbar
-  :type 'hook)
+  :type 'hook
+  :options '(speedbar-highlight-one-tag-line
+	     speedbar-recenter-to-top
+	     speedbar-recenter
+	     ))
 
 (defcustom speedbar-load-hook nil
   "Hooks run when speedbar is loaded."
   :group 'speedbar
   :type 'hook)
 
+(defcustom speedbar-reconfigure-keymaps-hook nil
+  "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.
 nil means don't show the file in the list."
 				       (menu-bar-lines . 0)
 				       (unsplittable . t))
   "*Parameters to use when creating the speedbar frame in Emacs.
-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."
+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:")))
 
   "*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 "User Imenu"
+  :tag "Use Imenu for tags"
   :group 'speedbar
   :type 'boolean)
 
+(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.
+Each element is of the form ( FETCH .  INSERT ) where FETCH
+is a funciotn 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.
+INSERT is a function which takes an INDENTation level, and a LIST of
+tags to insert.  It will then create the speedbar buttons.")
+
 (defcustom speedbar-track-mouse-flag t
   "*Non-nil means to display info about the line under the mouse."
   :group 'speedbar
   :type 'boolean)
 
 (defcustom speedbar-tag-hierarchy-method
-  '(prefix-group trim-words)
-  "*List of methods 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.
-Available methods are:
-  sort         - Sort tags.  (sometimes unnecessary)
-  trim-words   - Trim all tags by a common prefix, broken @ word sections.
-  prefix-group - Try to guess groups by prefix.
-  simple-group - If imenu already returned some meta groups, stick all
-                 tags that are not in a group into a sub-group."
+  '(speedbar-prefix-group-tag-hierarchy
+    speedbar-trim-words-tag-hierarchy)
+  "*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
+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 'speedbar
-  :type '(repeat
-	  (radio
-	   (const :tag "Sort the tags." sort)
-	   (const :tag "Trim words to common prefix." trim-words)
-	   (const :tag "Create groups from common prefixes." prefix-group)
-	   (const :tag "Group loose tags into their own group." simple-group))
-	  ))
+  :type 'hook
+  :options '(speedbar-trim-words-tag-hierarchy
+	     speedbar-prefix-group-tag-hierarchy
+	     speedbar-simple-group-tag-hierarchy
+	     speedbar-sort-tag-hierarchy)
+  )
 
 (defcustom speedbar-tag-group-name-minimum-length 4
   "*The minimum length of a prefix group name before expanding.
   :group 'speedbar
   :type 'boolean)
 
-(defvar speedbar-hide-button-brackets-flag nil
-  "*Non-nil means speedbar will hide the brackets around the + or -.")
+(defcustom speedbar-indentation-width 1
+  "*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 -."
+  :group 'speedbar
+  :type 'boolean)
+
+(defcustom speedbar-use-images (and (or (fboundp 'defimage)
+					(fboundp 'make-image-specifier))
+				    (if (fboundp 'display-graphic-p)
+					(display-graphic-p)
+				      window-system))
+  "*Non nil if speedbar should display icons."
+  :group 'speedbar
+  :type 'boolean)
 
 (defcustom speedbar-before-popup-hook nil
   "*Hooks called before popping up the speedbar frame."
   :group 'speedbar-vc
   :type 'boolean)
 
-(defvar speedbar-vc-indicator " *"
+(defvar speedbar-vc-indicator "*"
   "Text used to mark files which are currently checked out.
-Currently only RCS is supported.  Other version control systems can be
-added by examining the function `speedbar-this-file-in-vc' and
-`speedbar-vc-check-dir-p'")
+Other version control systems can be added by examining the function
+`speedbar-vc-path-enable-hook' and `speedbar-vc-in-control-hook'.")
 
 (defcustom speedbar-vc-path-enable-hook nil
   "*Return non-nil if the current path should be checked for Version Control.
 variable `speedbar-ignored-path-expressions' to modify this variable.")
 
 (defcustom speedbar-ignored-path-expressions
-  '("/logs?/\\'")
+  '("[/\\]logs?[/\\]\\'")
   "*List of regular expressions matching directories speedbar will ignore.
 They should included paths to directories which are notoriously very
 large and take a long time to load in.  Use the function
 ;; change in the future.
 (defcustom speedbar-supported-extension-expressions
   (append '(".[ch]\\(\\+\\+\\|pp\\|c\\|h\\|xx\\)?" ".tex\\(i\\(nfo\\)?\\)?"
-	    ".el" ".emacs" ".l" ".li?sp" ".p" ".java" ".f\\(90\\|77\\|or\\)?")
+	    ".el" ".emacs" ".l" ".lsp" ".p" ".java" ".f\\(90\\|77\\|or\\)?")
 	  (if speedbar-use-imenu-flag
 	      '(".ada" ".p[lm]" ".tcl" ".m" ".scm" ".pm" ".py"
 		;; 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"
-		;; Instead "Makefile\\(\\.in\\)?", Karl M. Hegbloom
-		;; <karlheg@debian.org> suggested s/th equivalent to:
-		;;"Make.*" "Rules"
-		".ma?k" "makefile\\(\\.in\\)?")))
+		"[Mm]akefile\\(\\.in\\)?")))
   "*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
 			      (or (fboundp 'run-with-idle-timer)
 				  (fboundp 'start-itimer)
 				  (boundp 'post-command-idle-hook))
-			      window-system)
+			      (if (fboundp 'display-graphic-p)
+				  (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:
 
 to toggle this value.")
 
+(defvar speedbar-update-flag-disable nil
+  "Permanently disable chaning of the update flag.")
+
 (defvar speedbar-syntax-table nil
   "Syntax-table used on the speedbar.")
 
   (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
   "Keymap used in speedbar buffer.")
 
   (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) ; unshifted
+  (define-key speedbar-file-key-map "=" 'speedbar-expand-line)
   (define-key speedbar-file-key-map "-" 'speedbar-contract-line)
 
   ;; file based commands
   )
 
 (defvar speedbar-easymenu-definition-base
-  '("Speedbar"
-    ["Update" speedbar-refresh t]
-    ["Auto Update" speedbar-toggle-updates
-     :style toggle :selected speedbar-update-flag]
-    )
+  (append
+   '("Speedbar"
+     ["Update" speedbar-refresh t]
+     ["Auto Update" speedbar-toggle-updates
+      :active (not speedbar-update-flag-disable)
+      :style toggle :selected speedbar-update-flag])
+   (if (and (or (fboundp 'defimage)
+		(fboundp 'make-image-specifier))
+	    (if (fboundp 'display-graphic-p)
+		(display-graphic-p)
+	      window-system))
+       (list
+	["Use Images" speedbar-toggle-images
+	 :style toggle :selected speedbar-use-images]))
+   )
   "Base part of the speedbar menu.")
 
 (defvar speedbar-easymenu-definition-special
     ["Expand File Tags" speedbar-expand-line
      (save-excursion (beginning-of-line)
 		     (looking-at "[0-9]+: *.\\+. "))]
+    ["Flush Cache & Expand" speedbar-flush-expand-line
+     (save-excursion (beginning-of-line)
+		     (looking-at "[0-9]+: *.\\+. "))]
     ["Contract File Tags" speedbar-contract-line
      (save-excursion (beginning-of-line)
 		     (looking-at "[0-9]+: *.-. "))]
  
 (defvar speedbar-easymenu-definition-trailer
   (append
-   '("---")
    (if (and (featurep 'custom) (fboundp 'custom-declare-variable))
        (list ["Customize..." speedbar-customize t]))
    (list
+    ["Detatch" speedbar-detach (and speedbar-frame
+				    (eq (selected-frame) speedbar-frame)) ]
     ["Close" speedbar-close-frame t]
     ["Quit" delete-frame t] ))
   "Menu items appearing at the end of the speedbar menu.")
   (defun speedbar-frame-parameter (frame parameter)
     "Return FRAME's PARAMETER value."
     (cdr (assoc parameter (frame-parameters frame)))))
+
+(if (fboundp 'make-overlay)
+    (progn
+      (defalias 'speedbar-make-overlay 'make-overlay)
+      (defalias 'speedbar-overlay-put 'overlay-put)
+      (defalias 'speedbar-delete-overlay 'delete-overlay)
+      (defalias 'speedbar-overlay-start 'overlay-start)
+      (defalias 'speedbar-overlay-end 'overlay-end)
+      (defalias 'speedbar-mode-line-update 'force-mode-line-update))
+  (defalias 'speedbar-make-overlay 'make-extent)
+  (defalias 'speedbar-overlay-put 'set-extent-property)
+  (defalias 'speedbar-delete-overlay 'delete-extent)
+  (defalias 'speedbar-overlay-start 'extent-start)
+  (defalias 'speedbar-overlay-end 'extent-end)
+  (defalias 'speedbar-mode-line-update 'redraw-modeline))
 
 ;;; Mode definitions/ user commands
 ;;
 	      (set-frame-name "Speedbar")))
 	(speedbar-set-timer speedbar-update-speed)))))
 
+(defun speedbar-detach ()
+  "Detatch the current Speedbar from auto-updating.
+Doing this allows the creation of a second speedbar."
+  (interactive)
+  (save-excursion
+    (set-buffer speedbar-buffer)
+    (rename-buffer (buffer-name) t)
+    (setq speedbar-buffer nil
+	  speedbar-frame nil
+	  speedbar-cached-frame nil)
+    ;; Permanently disable auto-updating in this speedbar buffer.
+    (set (make-local-variable 'speedbar-update-flag) nil)
+    (set (make-local-variable 'speedbar-update-flag-disable) t)
+    ;; Make local copies of all the different variables to prevent
+    ;; funny stuff later...
+    ))
+
 ;;;###autoload
 (defun speedbar-get-focus ()
   "Change frame focus to or from the speedbar frame.
 			       (speedbar-quick-mouse event))
 			      ((or (eq count 2)
 				   (eq count 3))
-			       (mouse-set-point event)
+			       (speedbar-mouse-set-point event)
 			       (speedbar-do-function-pointer)
 			       (speedbar-quick-mouse event)))
 			;; Don't do normal operations.
     (toggle-read-only 1)
     (speedbar-set-mode-line-format)
     (if speedbar-xemacsp
-	(progn
-	  (make-local-variable 'mouse-motion-handler)
-	  (setq mouse-motion-handler 'speedbar-track-mouse-xemacs))
+	(set (make-local-variable 'mouse-motion-handler)
+	     'speedbar-track-mouse-xemacs)
       (if speedbar-track-mouse-flag
-	  (progn
-	    (make-local-variable 'track-mouse)
-	    (setq track-mouse t)))	;this could be messy.
+	  (set (make-local-variable 'track-mouse) t))	;this could be messy.
       (setq auto-show-mode nil))	;no auto-show for Emacs
     (run-hooks 'speedbar-mode-hook))
   (speedbar-update-contents)
 Argument FMT is the format string, and ARGS are the arguments for message."
   (save-selected-window
     (select-frame speedbar-attached-frame)
-    (if (fboundp 'lmessage)
-	;; speedbar should probably support XEmacs message concept better
-	(apply 'lmessage 'no-log fmt args)
-      (apply 'message fmt args))))
+    (apply 'message fmt args)))
 
 (defun speedbar-y-or-n-p (prompt)
   "Like `y-or-n-p', but for use in the speedbar frame.
 	  (if (not (equal mode-line-format tf))
 	      (progn
 		(setq mode-line-format tf)
-		(force-mode-line-update)))))))
+		(speedbar-mode-line-update)))))))
 
 (defun speedbar-temp-buffer-show-function (buffer)
   "Placed in the variable `temp-buffer-show-function' in `speedbar-mode'.
 	  (easy-menu-define speedbar-menu-map (current-local-map)
 			    "Speedbar menu" md)
 	(easy-menu-add md (current-local-map))
-	(set-buffer-menubar (list md))))))
+	(set-buffer-menubar (list md))))
+    (run-hooks 'speedbar-reconfigure-keymaps-hook)))
 
 
 ;;; User Input stuff
 nil if not applicable."
   (save-excursion
     (beginning-of-line)
-    (if (re-search-forward " > \\([^ ]+\\)$"
+    (if (re-search-forward " [-+=]?> \\([^\n]+\\)"
 			   (save-excursion(end-of-line)(point)) t)
 	(let ((tag (match-string 1))
-	      (attr (get-text-property (match-beginning 1)
-				       'speedbar-token))
+	      (attr (speedbar-line-token))
 	      (item nil))
-	  (looking-at "\\([0-9]+\\):")
-	  (setq item (speedbar-line-path (string-to-int (match-string 1))))
-	  (speedbar-message "Tag: %s  in %s @ %s"
-			    tag item (if attr
-					 (if (markerp attr)
-					     (marker-position attr)
-					   attr)
-				       0)))
+	  (if (and (featurep 'semantic) (semantic-token-p attr))
+	      (speedbar-message (semantic-summerize-nonterminal attr))
+	    (looking-at "\\([0-9]+\\):")
+	    (setq item (file-name-nondirectory (speedbar-line-path)))
+	    (speedbar-message "Tag: %s  in %s" tag item)))
       (if (re-search-forward "{[+-]} \\([^\n]+\\)$"
 			     (save-excursion(end-of-line)(point)) t)
 	  (speedbar-message "Group of tags \"%s\"" (match-string 1))
-	nil))))
+	(if (re-search-forward " [+-]?[()|@] \\([^\n]+\\)$" nil t)
+	    (let* ((detailtext (match-string 1))
+		   (detail (or (speedbar-line-token) detailtext))
+		  (parent (save-excursion
+			    (beginning-of-line)
+			    (let ((dep (if (looking-at "[0-9]+:")
+					   (1- (string-to-int (match-string 0)))
+					 0)))
+			      (re-search-backward (concat "^"
+							   (int-to-string dep)
+							   ":")
+						  nil t))
+			    (if (looking-at "[0-9]+: +[-+=>]> \\([^\n]+\\)$")
+				(speedbar-line-token)
+			      nil))))
+	      (if (and (featurep 'semantic) (semantic-token-p detail))
+		  (speedbar-message
+		   (semantic-summerize-nonterminal detail parent))
+		(if parent
+		    (speedbar-message "Detail: %s of tag %s" detail
+				      (if (and (featurep 'semantic)
+					       (semantic-token-p parent))
+					  (semantic-token-name parent)
+					parent))
+		  (speedbar-message "Detail: %s" detail))))
+	  nil)))))
 
 (defun speedbar-files-item-info ()
   "Display info in the mini-buffer about the button the mouse is over."
 	(if (file-directory-p rt)
 	    (setq rt
 		  (concat (expand-file-name rt)
-			  (if (string-match "/$" rt) "" "/")
+			  (if (string-match "[/\\]$" rt) "" "/")
 			  (file-name-nondirectory f))))
 	(if (or (not (file-exists-p rt))
 		(speedbar-y-or-n-p (format "Overwrite %s with %s? " rt f)))
 	  (if (file-directory-p rt)
 	      (setq rt
 		    (concat (expand-file-name rt)
-			    (if (string-match "/\\'" rt) "" "/")
+			    (if (string-match "[/\\]\\'" rt) "" "/")
 			    (file-name-nondirectory f))))
 	  (if (or (not (file-exists-p rt))
 		  (speedbar-y-or-n-p (format "Overwrite %s with %s? " rt f)))
       (speedbar-disable-update)
     (speedbar-enable-update)))
 
+(defun speedbar-toggle-images ()
+  "Toggle automatic update 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."
   (interactive)
 This is a convenience function for special mode that create their own
 specialized speedbar displays."
   (goto-char (point-max))
-  (if (/= (current-column) 0) (insert "\n"))
-  (if prevline (progn (delete-char -1) (insert " "))) ;back up if desired...
+  (let ((start (point)))
+    (if (/= (current-column) 0) (insert "\n"))
+    (put-text-property start (point) 'invisible nil))
+  (if prevline (progn (delete-char -1)
+		      (insert " ") ;back up if desired...
+		      (put-text-property (1- (point)) (point) 'invisible nil)))
   (let ((start (point)))
     (insert text)
     (speedbar-make-button start (point) face mouse function token))
   (let ((start (point)))
     (insert "\n")
     (put-text-property start (point) 'face nil)
+    (put-text-property start (point) 'invisible nil)
     (put-text-property start (point) 'mouse-face nil)))
 
 (defun speedbar-make-button (start end face mouse function &optional token)
   (put-text-property start end 'invisible nil)
   (if function (put-text-property start end 'speedbar-function function))
   (if token (put-text-property start end 'speedbar-token token))
+  ;; So far the only text we have is less that 3 chars.
+  (if (<= (- end start) 3)
+      (speedbar-insert-image-button-maybe start (- end start)))
   )
 
 ;;; Initial Expansion list management
   (setq speedbar-previously-used-expansion-list-name
 	speedbar-initial-expansion-list-name
 	speedbar-initial-expansion-list-name new-default)
-  (speedbar-refresh)
-  (speedbar-reconfigure-keymaps))
+  (if (and speedbar-frame (frame-live-p speedbar-frame))
+      (progn
+	(speedbar-refresh)
+	(speedbar-reconfigure-keymaps))))
 
 (defun speedbar-fetch-replacement-function (function)
   "Return a current mode specific replacement for function, or nil.
 Each directory path part is a different button.  If part of the path
 matches the user directory ~, then it is replaced with a ~.
 INDEX is not used, but is required by the caller."
-  (let* ((tilde (expand-file-name "~"))
+  (let* ((tilde (expand-file-name "~/"))
 	 (dd (expand-file-name directory))
 	 (junk (string-match (regexp-quote tilde) dd))
 	 (displayme (if junk
-			(concat "~" (substring dd (match-end 0)))
+			(concat "~/" (substring dd (match-end 0)))
 		      dd))
 	 (p (point)))
-    (if (string-match "^~/?\\'" displayme) (setq displayme (concat tilde "/")))
+    (if (string-match "^~[/\\]?\\'" displayme) (setq displayme tilde))
     (insert displayme)
     (save-excursion
       (goto-char p)
-      (while (re-search-forward "\\([^/]+\\)/" nil t)
+      (while (re-search-forward "\\([^/\\]+\\)[/\\]" nil t)
 	(speedbar-make-button (match-beginning 1) (match-end 1)
 			      'speedbar-directory-face
 			      'speedbar-highlight-face
 			      'speedbar-directory-buttons-follow
-			      (if (= (match-beginning 1) p)
+			      (if (and (= (match-beginning 1) p)
+				       (not (char-equal (char-after (+ p 1)) ?:)))
 				  (expand-file-name "~/")  ;the tilde
 				(buffer-substring-no-properties
 				 p (match-end 0)))))
 	     (let ((ww (or (speedbar-frame-width) 20)))
 	       (move-to-column ww nil)
 	       (while (>= (current-column) ww)
-		 (re-search-backward "/" nil t)
+		 (re-search-backward "[/\\]" nil t)
 		 (if (<= (current-column) 2)
 		     (progn
-		       (re-search-forward "/" nil t)
+		       (re-search-forward "[/\\]" nil t)
 		       (if (< (current-column) 4)
-			   (re-search-forward "/" nil t))
+			   (re-search-forward "[/\\]" nil t))
 		       (forward-char -1)))
-		 (if (looking-at "/?$")
+		 (if (looking-at "[/\\]?$")
 		     (beginning-of-line)
 		   (insert "/...\n ")
 		   (move-to-column ww nil)))))
 	       (if (< ww tl)
 		   (progn
 		     (move-to-column (- tl ww))
-		     (if (re-search-backward "/" nil t)
+		     (if (re-search-backward "[/\\]" nil t)
 			 (progn
 			   (delete-region (point-min) (point))
 			   (insert "$")
 			   )))))))
       )
-    (if (string-match "\\`/[^/]+/\\'" displayme)
+    (if (string-match "\\`[/\\][^/\\]+[/\\]\\'" displayme)
 	(progn
 	  (insert "  ")
 	  (let ((p (point)))
   (let ((start (point))
 	(end (progn
 	       (insert (int-to-string depth) ":")
-	       (point))))
+	       (point)))
+	(depthspacesize (* depth speedbar-indentation-width)))
     (put-text-property start end 'invisible t)
-    )
-  (insert-char ?  depth nil)
-  (put-text-property (- (point) depth) (point) 'invisible nil)
-  (let* ((exp-button (cond ((eq exp-button-type 'bracket) "[%c]")
-			   ((eq exp-button-type 'angle) "<%c>")
-			   ((eq exp-button-type 'curly) "{%c}")
-			   (t ">")))
-	 (buttxt (format exp-button exp-button-char))
-	 (start (point))
-	 (end (progn (insert buttxt) (point)))
-	 (bf (if exp-button-type 'speedbar-button-face nil))
-	 (mf (if exp-button-function 'speedbar-highlight-face nil))
-	 )
-    (speedbar-make-button start end bf mf exp-button-function exp-button-data)
-    (if speedbar-hide-button-brackets-flag
-	(progn
-	  (put-text-property start (1+ start) 'invisible t)
-	  (put-text-property end (1- end) 'invisible t)))
-    )
-  (insert-char ?  1 nil)
-  (put-text-property (1- (point)) (point) 'invisible nil)
-  (let ((start (point))
-	(end (progn (insert tag-button) (point))))
-    (insert-char ?\n 1 nil)
+    (insert-char ?  depthspacesize nil)
+    (put-text-property (- (point) depthspacesize) (point) 'invisible nil)
+    (let* ((exp-button (cond ((eq exp-button-type 'bracket) "[%c]")
+			     ((eq exp-button-type 'angle) "<%c>")
+			     ((eq exp-button-type 'curly) "{%c}")
+			     (t ">")))
+	   (buttxt (format exp-button exp-button-char))
+	   (start (point))
+	   (end (progn (insert buttxt) (point)))
+	   (bf (if exp-button-type 'speedbar-button-face nil))
+	   (mf (if exp-button-function 'speedbar-highlight-face nil))
+	   )
+      (speedbar-make-button start end bf mf exp-button-function exp-button-data)
+      (if speedbar-hide-button-brackets-flag
+	  (progn
+	    (put-text-property start (1+ start) 'invisible t)
+	    (put-text-property end (1- end) 'invisible t)))
+      )
+    (insert-char ?  1 nil)
     (put-text-property (1- (point)) (point) 'invisible nil)
-    (speedbar-make-button start end tag-button-face
-			  (if tag-button-function 'speedbar-highlight-face nil)
-			  tag-button-function tag-button-data))
-)
-
+    (let ((start (point))
+	  (end (progn (insert tag-button) (point))))
+      (insert-char ?\n 1 nil)
+      (put-text-property (1- (point)) (point) 'invisible nil)
+      (speedbar-make-button start end tag-button-face
+			    (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
 	  (goto-char (match-beginning 1))
 	  (delete-char 1)
 	  (insert-char char 1 t)
-	  (put-text-property (point) (1- (point)) 'invisible nil)))))
+	  (put-text-property (point) (1- (point)) 'invisible nil)
+	  ;; make sure we fix the image on the text here.
+	  (speedbar-insert-image-button-maybe (- (point) 2) 3)))))
 
 
 ;;; Build button lists
   "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
 		(setq sf (cdr sf)))))
 	)))
 
-(defun speedbar-apply-one-tag-hierarchy-method (lst method)
-  "Adjust the tag hierarchy LST by METHOD."
-  (cond
-   ((eq method 'sort)
-    (sort (copy-alist lst)
-	  (lambda (a b) (string< (car a) (car b)))))
-   ((eq method 'prefix-group)
-    (let ((newlst nil)
-	  (sublst nil)
- 	  (work-list nil)
-	  (junk-list nil)
-	  (short-group-list nil)
-	  (short-start-name nil)
-	  (short-end-name nil)
-	  (num-shorts-grouped 0)
-	  (bins (make-vector 256 nil))
-	  (diff-idx 0))
-      ;; Break out sub-lists
-      (while lst
-	(if (listp (cdr-safe (car-safe lst)))
-	    (setq newlst (cons (car lst) newlst))
-	  (setq sublst (cons (car lst) sublst)))
-	(setq lst (cdr lst)))
-      ;; Reverse newlst because it was made backwards.
-      ;; Sublist doesn't need reversing because the act
-      ;; of binning things will reverse it for us.
-      (setq newlst (nreverse newlst))
-      ;; Now, first find out how long our list is.  Never let a
-      ;; list get-shorter than our minimum.
-      (if (<= (length sublst) speedbar-tag-split-minimum-length)
-	  (setq work-list (nreverse sublst))
-	(setq diff-idx (length (try-completion "" sublst)))
-	;; Sort the whole list into bins.
-	(while sublst
-	  (let ((e (car sublst))
-		(s (car (car sublst))))
-	    (cond ((<= (length s) diff-idx)
-		   ;; 0 storage bin for shorty.
-		   (aset bins 0 (cons e (aref bins 0))))
-		  (t
-		   ;; stuff into a bin based on ascii value at diff
-		   (aset bins (aref s diff-idx)
-			 (cons e (aref bins (aref s diff-idx)))))))
-	  (setq sublst (cdr sublst)))
-	;; Go through all our bins  Stick singles into our
-	;; junk-list, everything else as sublsts in work-list.
-	;; If two neighboring lists are both small, make a grouped
-	;; group combinding those two sub-lists.
-	(setq diff-idx 0)
-	(while (> 256 diff-idx)
-	  (let ((l (nreverse ;; Reverse the list since they are stuck in
-		    ;; backwards.
-		    (aref bins diff-idx))))
-	    (if l
-		(let ((tmp (cons (try-completion "" l) l)))
-		  (if (or (> (length l) speedbar-tag-regroup-maximum-length)
-			  (> (+ (length l) (length short-group-list))
-			     speedbar-tag-split-minimum-length))
-		      (progn
-			;; We have reached a longer list, so we
-			;; must finish off a grouped group.
-			(cond
-			 ((and short-group-list
-			       (= (length short-group-list)
-				  num-shorts-grouped))
-			  ;; All singles?  Junk list
-			  (setq junk-list (append short-group-list
-						  junk-list)))
-			 ((= num-shorts-grouped 1)
-			  ;; Only one short group?  Just stick it in
-			  ;; there by itself.  Make a group, and find
<