Various docstring and commentary fixes, including
[bpt/emacs.git] / lisp / progmodes / tcl.el
index 0246648..ef8e27b 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Tom Tromey <tromey@busco.lanl.gov>
 ;;    Chris Lindblad <cjl@lcs.mit.edu>
 ;; Keywords: languages tcl modes
-;; Version: $Revision: 1.4 $
+;; Version: $Revision: 1.50 $
 
 ;; This file is part of GNU Emacs.
 
 ;;   (setq auto-mode-alist (append '(("\\.tcl$" . tcl-mode)) auto-mode-alist))
 ;;
 ;; If you plan to use the interface to the TclX help files, you must
-;; set the variable tcl-help-directory to point to the topmost
-;; directory containing the TclX help files.  Eg:
+;; set the variable tcl-help-directory-list to point to the topmost
+;; directories containing the TclX help files.  Eg:
 ;;
-;;   (setq tcl-help-directory "/usr/local/lib/tclx/help")
+;;   (setq tcl-help-directory-list '("/usr/local/lib/tclx/help"))
 ;;
 ;; Also you will want to add the following to your .emacs:
 ;;
@@ -51,7 +51,7 @@
 ;; LCD Archive Entry:
 ;; tcl|Tom Tromey|tromey@busco.lanl.gov|
 ;; Major mode for editing Tcl|
-;; $Date: 1994/04/07 00:23:36 $|$Revision: 1.4 $|~/modes/tcl.el.Z|
+;; $Date: 1996/03/23 05:14:50 $|$Revision: 1.50 $|~/modes/tcl.el.Z|
 
 ;; CUSTOMIZATION NOTES:
 ;; * tcl-proc-list can be used to customize a list of things that
 ;; according to context.
 
 ;; Change log:
+;; $Log: tcl.el,v $
+;; Revision 1.50  1996/03/23  05:14:50  tromey
+;; (tcl-using-emacs-19): Work with XEmacs 20.0.  From Ben Wing.
+;;
+;; Revision 1.49  1995/12/07  18:27:47  tromey
+;; (add-log-tcl-defun): Don't use tcl-beginning-of-defun; just go to end
+;; of line before searching.
+;;
+;; Revision 1.48  1995/12/07  18:18:21  tromey
+;; (add-log-tcl-defun): Now uses tcl-beginning-of-defun.
+;;
+;; Revision 1.47  1995/08/22  17:49:45  tromey
+;; (tcl-hilit): New function from "Chris Alfeld" <calfeld@math.utah.edu>
+;; (tcl-mode): Call it
+;;
+;; Revision 1.46  1995/08/07  16:02:01  tromey
+;; (tcl-do-auto-fill): Only fill past fill-column; for 19.29.
+;; (tcl-auto-fill-mode): Use force-mode-line-update.
+;;
+;; Revision 1.45  1995/07/23  23:51:25  tromey
+;; (tcl-word-no-props): New function.
+;; (tcl-figure-type): Use it.
+;; (tcl-current-word): Ditto.
+;;
+;; Revision 1.44  1995/07/23  20:26:47  tromey
+;; Doc fixes.
+;;
+;; Revision 1.43  1995/07/17  19:59:49  tromey
+;; (inferior-tcl-mode): Use modeline-process if it exists.
+;;
+;; Revision 1.42  1995/07/17  19:55:25  tromey
+;; XEmacs currently must use tcl-internal-end-of-defun
+;;
+;; Revision 1.41  1995/07/14  21:54:56  tromey
+;; Changes to make menus work in XEmacs.
+;; From Mike Scheidler <c23mts@kocrsv01.delcoelect.com>
+;;
+;; Revision 1.40  1995/07/11  03:13:15  tromey
+;; (tcl-mode): Customize for new dabbrev.
+;;
+;; Revision 1.39  1995/07/09  21:58:03  tromey
+;; (tcl-do-fill-paragraph): New function.
+;; (tcl-mode): Set up for paragraph filling.
+;;
+;; Revision 1.38  1995/07/09  21:30:32  tromey
+;; (tcl-mode): Fixes to 19.29 paragraph variables.
+;;
+;; Revision 1.37  1995/07/09  18:52:16  tromey
+;; (tcl-do-auto-fill): Set fill-prefix.
+;;
+;; Revision 1.36  1995/07/09  01:07:57  tromey
+;; (tcl-imenu-create-index-function): Work with imenu from Emacs 19.29
+;;
+;; Revision 1.35  1995/06/27  20:12:00  tromey
+;; (tcl-type-alist): More itcl changes.
+;;
+;; Revision 1.34  1995/06/27  20:06:05  tromey
+;; More changes for itcl.
+;; Bug fixes for Emacs 19.29.
+;;
+;; Revision 1.33  1995/06/27  20:01:29  tromey
+;; (tcl-set-proc-regexp): Allow leading spaces.
+;; (tcl-proc-list): Changes for itcl.
+;; (tcl-typeword-list): Ditto.
+;; (tcl-keyword-list): Ditto.
+;;
+;; Revision 1.32  1995/05/11  22:12:49  tromey
+;; (tcl-type-alist): Include entry for "proc".
+;;
+;; Revision 1.31  1995/05/10  23:38:12  tromey
+;; (tcl-add-fsf-menu): Use make-lucid-menu-keymap, not
+;; "make-xemacs-menu-keymap".
+;;
+;; Revision 1.30  1995/05/10  18:22:21  tromey
+;; Bug fix in menu code for XEmacs.
+;;
+;; Revision 1.29  1995/05/09  21:36:53  tromey
+;; Changed "Lucid Emacs" to "XEmacs".
+;; Tcl's popup menu now added to existing one, courtesy
+;; dfarmer@evolving.com (Doug Farmer)
+;;
+;; Revision 1.28  1995/04/08  19:52:50  tromey
+;; (tcl-outline-level): New function
+;; (tcl-mode): Added outline-handling stuff.
+;; From Jesper Pedersen <blackie@imada.ou.dk>
+;;
+;; Revision 1.27  1994/10/11  02:01:27  tromey
+;; (tcl-mode): imenu-create-index-function made buffer local.
+;;
+;; Revision 1.26  1994/09/01  18:06:24  tromey
+;; Added filename completion in inferior tcl mode
+;;
+;; Revision 1.25  1994/08/22  15:56:24  tromey
+;; tcl-load-file default to current buffer.
+;;
+;; Revision 1.24  1994/08/21  20:33:05  tromey
+;; Fixed bug in tcl-guess-application.
+;;
+;; Revision 1.23  1994/08/21  03:54:45  tromey
+;; Keybindings don't overshadown comint bindings.
+;;
+;; Revision 1.22  1994/07/26  00:46:07  tromey
+;; Emacs 18 changes from Carl Witty.
+;;
+;; Revision 1.21  1994/07/14  22:49:21  tromey
+;; Added ";;;###autoload" comments where appropriate.
+;;
+; Revision 1.20  1994/06/05  16:57:22  tromey
+; tcl-current-word does the right thing in inferior-tcl-mode.
+;
+; Revision 1.19  1994/06/03  21:09:19  tromey
+; Another menu fix.
+;
+; Revision 1.18  1994/06/03  20:39:14  tromey
+; Fixed menu bug.
+;
+; Revision 1.17  1994/06/03  00:47:15  tromey
+; Fixed bug in bug-reporting code.
+;
+; Revision 1.16  1994/05/26  05:06:14  tromey
+; Menu items now sensitive as appropriate.
+;
+; Revision 1.15  1994/05/22  20:38:11  tromey
+; Added bug-report keybindings and menu entries.
+;
+; Revision 1.14  1994/05/22  20:18:28  tromey
+; Even more compile stuff.
+;
+; Revision 1.13  1994/05/22  20:17:15  tromey
+; Moved emacs version checking code to very beginning.
+;
+; Revision 1.12  1994/05/22  20:14:59  tromey
+; Compile fixes.
+;
+; Revision 1.11  1994/05/22  20:12:44  tromey
+; Fixed mark-defun for 19.23.
+; More menu fixes.
+;
+; Revision 1.10  1994/05/22  20:02:03  tromey
+; Fixed bug with M-;.
+; Wrote bug-reporting code.
+;
+; Revision 1.9  1994/05/22  05:26:51  tromey
+; Fixes for imenu.
+;
+; Revision 1.8  1994/05/22  03:38:07  tromey
+; Fixed menu support.
+;
+; Revision 1.7  1994/05/03  01:23:42  tromey
+; *** empty log message ***
+;
+; Revision 1.6  1994/04/23  16:23:36  tromey
+; Wrote tcl-indent-for-comment
+;
+;;
 ;; 18-Mar-1994         Tom Tromey      Fourth beta release.
 ;;    Added {un,}comment-region to menu.  Idea from
 ;;    Mike Scheidler <c23mts@kocrsv01.delcoelect.com>
 ;; h9118101@hkuxa.hku.hk (Yip Chi Lap [Beta])
 ;; Pertti Tapio Kasanen <ptk@delta.hut.fi>
 ;; schmid@fb3-s7.math.TU-Berlin.DE (Gregor Schmid)
+;; warsaw@nlm.nih.gov (Barry A. Warsaw)
+;; Carl Witty <cwitty@ai.mit.edu>
+;; T. V. Raman <raman@crl.dec.com>
+;; Jesper Pedersen <blackie@imada.ou.dk>
+;; dfarmer@evolving.com (Doug Farmer)
+;; "Chris Alfeld" <calfeld@math.utah.edu>
+;; Ben Wing <wing@666.com>
 
 ;; KNOWN BUGS:
 ;; * indent-region should skip blank lines.  (It does in v19, so I'm
 ;;   line individually.
 ;; * tcl-figure-type should stop at "beginning of line" (only ws
 ;;   before point, and no "\" on previous line).  (see tcl-real-command-p).
-;; * Fix beginning-of-defun.  I believe this will be fully possible in
-;;   FSF Emacs 19.23
 ;; * overrides some comint keybindings; fix.
 ;; * Trailing \ will eat blank lines.  Should deal with this.
 ;;   (this would help catch some potential bugs).
 ;; * Inferior should display in half the screen, not the whole screen.
+;; * Indentation should deal with "switch".
+;; * Consider writing code to find help files automatically (for
+;;   common cases).
+;; * `#' shouldn't insert `\#' when point is in string.
 
 \f
 
 ;;; Code:
 
+;; I sure wish Emacs had a package that made it easy to extract this
+;; sort of information.  Strange definition works with XEmacs 20.0.
+(defconst tcl-using-emacs-19 (not (string-match "18\\." emacs-version))
+  "Nil unless using Emacs 19 (XEmacs or FSF).")
+
+;; FIXME this will break on Emacs 19.100.
+(defconst tcl-using-emacs-19-23
+  (string-match "19\\.\\(2[3-9]\\|[3-9][0-9]\\)" emacs-version)
+  "Nil unless using Emacs 19-23 or later.")
+
+(defconst tcl-using-xemacs-19 (string-match "XEmacs" emacs-version)
+  "Nil unless using XEmacs).")
+
 (require 'comint)
 
+;; When compiling under GNU Emacs, load imenu during compilation.  If
+;; you have 19.22 or earlier, comment this out, or get imenu.
+(and (fboundp 'eval-when-compile)
+     (eval-when-compile
+       (if (and (string-match "19\\." emacs-version)
+               (not (string-match "XEmacs" emacs-version)))
+          (require 'imenu))
+       ()))
+
+(defconst tcl-version "$Revision: 1.50 $")
+(defconst tcl-maintainer "Tom Tromey <tromey@drip.colorado.edu>")
+
 ;;
 ;; User variables.
 ;;
@@ -221,14 +410,14 @@ detecting function is used.  This variable is only used in GNU Emacs
 (defvar tcl-electric-hash-style 'smart
   "*Style of electric hash insertion to use.
 Possible values are 'backslash, meaning that `\\' quoting should be
-done; `quote, meaning that `\"' quoting should be done; 'smart,
+done; 'quote, meaning that `\"' quoting should be done; 'smart,
 meaning that the choice between 'backslash and 'quote should be
 made depending on the number of hashes inserted; or nil, meaning that
 no quoting should be done.  Any other value for this variable is
 taken to mean 'smart.  The default is 'smart.")
 
-(defvar tcl-help-directory nil
-  "*Name of topmost directory containing TclX help files")
+(defvar tcl-help-directory-list nil
+  "*List of topmost directories containing TclX help files")
 
 (defvar tcl-use-smart-word-finder t
   "*If not nil, use a better way of finding the current word when
@@ -264,48 +453,8 @@ quoted for Tcl.")
     ()
   (define-abbrev-table 'tcl-mode-abbrev-table ()))
 
-;; I sure wish Emacs had a package that made it easy to extract this
-;; sort of information.
-(defconst tcl-using-emacs-19 (string-match "19\\." emacs-version)
-  "Nil unless using Emacs 19 (Lucid or FSF).")
-
-;; FIXME this will break on Emacs 19.100.
-(defconst tcl-using-emacs-19.23
-  (string-match "19\\.\\(2[3-9]\\|[3-9][0-9]\\)" emacs-version)
-  "Nil unless using Emacs 19.23 or later.")
-
-(defconst tcl-using-lemacs-19 (string-match "Lucid" emacs-version)
-  "Nil unless using Lucid Emacs).")
-
 (defvar tcl-mode-map ()
   "Keymap used in Tcl mode.")
-(if tcl-mode-map
-    ()
-  (setq tcl-mode-map (make-sparse-keymap))
-  (define-key tcl-mode-map "{" 'tcl-electric-char)
-  (define-key tcl-mode-map "}" 'tcl-electric-brace)
-  (define-key tcl-mode-map "[" 'tcl-electric-char)
-  (define-key tcl-mode-map "]" 'tcl-electric-char)
-  (define-key tcl-mode-map ";" 'tcl-electric-char)
-  (define-key tcl-mode-map "#" 'tcl-electric-hash)
-  ;; FIXME.
-  (define-key tcl-mode-map "\e\C-a" 'tcl-beginning-of-defun)
-  ;; FIXME.
-  (define-key tcl-mode-map "\e\C-e" 'tcl-end-of-defun)
-  ;; FIXME.
-  (define-key tcl-mode-map "\e\C-h" 'mark-tcl-function)
-  (define-key tcl-mode-map "\e\C-q" 'indent-tcl-exp)
-  (define-key tcl-mode-map "\177" 'backward-delete-char-untabify)
-  (define-key tcl-mode-map "\t" 'tcl-indent-command)
-  (define-key tcl-mode-map "\M-\C-x" 'tcl-eval-defun)
-  (and (fboundp 'comment-region)
-       (define-key tcl-mode-map "\C-c\C-c" 'comment-region))
-  (define-key tcl-mode-map "\C-c\C-d" 'tcl-help-on-word)
-  (define-key tcl-mode-map "\C-c\C-e" 'tcl-eval-defun)
-  (define-key tcl-mode-map "\C-c\C-l" 'tcl-load-file)
-  (define-key tcl-mode-map "\C-c\C-p" 'inferior-tcl)
-  (define-key tcl-mode-map "\C-c\C-r" 'tcl-eval-region)
-  (define-key tcl-mode-map "\C-c\C-z" 'switch-to-tcl))
 
 (defvar tcl-mode-syntax-table nil
   "Syntax table in use in Tcl-mode buffers.")
@@ -337,39 +486,102 @@ quoted for Tcl.")
 
 (defvar inferior-tcl-mode-map nil
   "Keymap used in Inferior Tcl mode.")
-(if inferior-tcl-mode-map
-    ()
-  ;; FIXME Use keymap inheritance here?  FIXME we override comint
-  ;; keybindings here.  Maybe someone has a better set?
-  (setq inferior-tcl-mode-map (copy-keymap comint-mode-map))
-  (define-key inferior-tcl-mode-map "\e\C-a" 'tcl-beginning-of-defun)
-  (define-key inferior-tcl-mode-map "\e\C-e" 'tcl-end-of-defun)
-  (define-key inferior-tcl-mode-map "\177" 'backward-delete-char-untabify)
-  (define-key inferior-tcl-mode-map "\M-\C-x" 'tcl-eval-defun)
-  (define-key inferior-tcl-mode-map "\C-c\C-d" 'tcl-help-on-word)
-  (define-key inferior-tcl-mode-map "\C-c\C-e" 'tcl-eval-defun)
-  (define-key inferior-tcl-mode-map "\C-c\C-l" 'tcl-load-file)
-  (define-key inferior-tcl-mode-map "\C-c\C-p" 'inferior-tcl)
-  (define-key inferior-tcl-mode-map "\C-c\C-r" 'tcl-eval-region)
-  (define-key inferior-tcl-mode-map "\C-c\C-z" 'switch-to-tcl))
-
-;; Lucid Emacs menu.
-(defvar tcl-lucid-menu
-  '("Tcl"
-    ["Beginning of function" tcl-beginning-of-defun t]
+
+;; XEmacs menu.
+(defvar tcl-xemacs-menu
+  '(["Beginning of function" tcl-beginning-of-defun t]
     ["End of function" tcl-end-of-defun t]
-    ["Mark function" mark-tcl-function t]
-    ["Indent region" indent-region t]
-    ["Comment region" comment-region t]
-    ["Uncomment region" tcl-uncomment-region t]
+    ["Mark function" tcl-mark-defun t]
+    ["Indent region" indent-region (tcl-mark)]
+    ["Comment region" comment-region (tcl-mark)]
+    ["Uncomment region" tcl-uncomment-region (tcl-mark)]
     "----"
     ["Show Tcl process buffer" inferior-tcl t]
-    ["Send function to Tcl process" tcl-eval-defun t]
-    ["Send region to Tcl process" tcl-eval-region t]
-    ["Send file to Tcl process" tcl-load-file t]
+    ["Send function to Tcl process" tcl-eval-defun
+     (and inferior-tcl-buffer (get-buffer inferior-tcl-buffer))]
+    ["Send region to Tcl process" tcl-eval-region
+     (and inferior-tcl-buffer (get-buffer inferior-tcl-buffer))]
+    ["Send file to Tcl process" tcl-load-file
+     (and inferior-tcl-buffer (get-buffer inferior-tcl-buffer))]
     ["Restart Tcl process with file" tcl-restart-with-file t]
     "----"
-    ["Tcl help" tcl-help-on-word t]))
+    ["Tcl help" tcl-help-on-word tcl-help-directory-list]
+    ["Send bug report" tcl-submit-bug-report t])
+  "XEmacs menu for Tcl mode.")
+
+;; GNU Emacs does menus via keymaps.  Do it in a function in case we
+;; later decide to add it to inferior Tcl mode as well.
+(defun tcl-add-fsf-menu (map)
+  (define-key map [menu-bar] (make-sparse-keymap))
+  ;; This fails in Emacs 19.22 and earlier.
+  (require 'lmenu)
+  (let ((menu (make-lucid-menu-keymap "Tcl" tcl-xemacs-menu)))
+    (define-key map [menu-bar tcl] (cons "Tcl" menu))
+    ;; The following is intended to compute the key sequence
+    ;; information for the menu.  It doesn't work.
+    (x-popup-menu nil menu)))
+
+(defun tcl-fill-mode-map ()
+  (define-key tcl-mode-map "{" 'tcl-electric-char)
+  (define-key tcl-mode-map "}" 'tcl-electric-brace)
+  (define-key tcl-mode-map "[" 'tcl-electric-char)
+  (define-key tcl-mode-map "]" 'tcl-electric-char)
+  (define-key tcl-mode-map ";" 'tcl-electric-char)
+  (define-key tcl-mode-map "#" 'tcl-electric-hash)
+  ;; FIXME.
+  (define-key tcl-mode-map "\e\C-a" 'tcl-beginning-of-defun)
+  ;; FIXME.
+  (define-key tcl-mode-map "\e\C-e" 'tcl-end-of-defun)
+  ;; FIXME.
+  (define-key tcl-mode-map "\e\C-h" 'tcl-mark-defun)
+  (define-key tcl-mode-map "\e\C-q" 'indent-tcl-exp)
+  (define-key tcl-mode-map "\177" 'backward-delete-char-untabify)
+  (define-key tcl-mode-map "\t" 'tcl-indent-command)
+  (define-key tcl-mode-map "\M-;" 'tcl-indent-for-comment)
+  (define-key tcl-mode-map "\M-\C-x" 'tcl-eval-defun)
+  (define-key tcl-mode-map "\C-c\C-b" 'tcl-submit-bug-report)
+  (and (fboundp 'comment-region)
+       (define-key tcl-mode-map "\C-c\C-c" 'comment-region))
+  (define-key tcl-mode-map "\C-c\C-i" 'tcl-help-on-word)
+  (define-key tcl-mode-map "\C-c\C-v" 'tcl-eval-defun)
+  (define-key tcl-mode-map "\C-c\C-f" 'tcl-load-file)
+  (define-key tcl-mode-map "\C-c\C-t" 'inferior-tcl)
+  (define-key tcl-mode-map "\C-c\C-x" 'tcl-eval-region)
+  (define-key tcl-mode-map "\C-c\C-s" 'switch-to-tcl)
+
+  ;; Make menus.
+  (if (and tcl-using-emacs-19 (not tcl-using-xemacs-19))
+      (progn
+       (tcl-add-fsf-menu tcl-mode-map))))
+
+(defun tcl-fill-inferior-map ()
+  (define-key inferior-tcl-mode-map "\t" 'comint-dynamic-complete)
+  (define-key inferior-tcl-mode-map "\M-?"
+    'comint-dynamic-list-filename-completions)
+  (define-key inferior-tcl-mode-map "\e\C-a" 'tcl-beginning-of-defun)
+  (define-key inferior-tcl-mode-map "\e\C-e" 'tcl-end-of-defun)
+  (define-key inferior-tcl-mode-map "\177" 'backward-delete-char-untabify)
+  (define-key inferior-tcl-mode-map "\M-\C-x" 'tcl-eval-defun)
+  (define-key inferior-tcl-mode-map "\C-c\C-b" 'tcl-submit-bug-report)
+  (define-key inferior-tcl-mode-map "\C-c\C-i" 'tcl-help-on-word)
+  (define-key inferior-tcl-mode-map "\C-c\C-v" 'tcl-eval-defun)
+  (define-key inferior-tcl-mode-map "\C-c\C-f" 'tcl-load-file)
+  (define-key inferior-tcl-mode-map "\C-c\C-t" 'inferior-tcl)
+  (define-key inferior-tcl-mode-map "\C-c\C-x" 'tcl-eval-region)
+  (define-key inferior-tcl-mode-map "\C-c\C-s" 'switch-to-tcl))
+
+(if tcl-mode-map
+    ()
+  (setq tcl-mode-map (make-sparse-keymap))
+  (tcl-fill-mode-map))
+
+(if inferior-tcl-mode-map
+    ()
+  ;; FIXME Use keymap inheritance here?  FIXME we override comint
+  ;; keybindings here.  Maybe someone has a better set?
+  (setq inferior-tcl-mode-map (copy-keymap comint-mode-map))
+  (tcl-fill-inferior-map))
+
 
 (defvar inferior-tcl-buffer nil
   "*The current inferior-tcl process buffer.
@@ -418,8 +630,6 @@ Several functions exist which are useful to run from your
 `tcl-mode-hook' (see each function's documentation for more
 information):
 
-  tcl-install-menubar
-    Puts a \"Tcl\" menu on the menubar.  Doesn't work in Emacs 18.
   tcl-guess-application
     Guesses a default setting for `tcl-application' based on any
     \"#!\" line at the top of the file.
@@ -443,7 +653,7 @@ Emacs 18 users must use `setq':
   "Hook for customizing Inferior Tcl mode.")
 
 (defvar tcl-proc-list
-  '("proc")
+  '("proc" "method" "itcl_class")
   "List of commands whose first argument defines something.
 This exists because some people (eg, me) use \"defvar\" et al.
 Call `tcl-set-proc-regexp' and `tcl-set-font-lock-keywords'
@@ -453,15 +663,16 @@ after changing this list.")
   "Regexp to use when matching proc headers.")
 
 (defvar tcl-typeword-list
-  '("global" "upvar")
-  "List of Tcl keywords deonting \"type\".  Used only for highlighting.
+  '("global" "upvar" "inherit" "public" "protected" "common")
+  "List of Tcl keywords denoting \"type\".  Used only for highlighting.
 Call `tcl-set-font-lock-keywords' after changing this list.")
 
 ;; Generally I've picked control operators to be keywords.
 (defvar tcl-keyword-list
   '("if" "then" "else" "elseif" "for" "foreach" "break" "continue" "while"
     "eval" "case" "in" "switch" "default" "exit" "error" "proc" "return"
-    "uplevel" "loop" "for_array_keys" "for_recursive_glob" "for_file")
+    "uplevel" "constructor" "destructor" "itcl_class" "loop" "for_array_keys"
+    "for_recursive_glob" "for_file")
   "List of Tcl keywords.  Used only for highlighting.
 Default list includes some TclX keywords.
 Call `tcl-set-font-lock-keywords' after changing this list.")
@@ -476,6 +687,10 @@ This variable is generally set from `tcl-proc-regexp',
 ;; like 2 sexps.
 (defvar tcl-type-alist
   '(
+    ("proc" nil tcl-expr tcl-commands)
+    ("method" nil tcl-expr tcl-commands)
+    ("destructor" tcl-commands)
+    ("constructor" tcl-commands)
     ("expr" tcl-expr)
     ("catch" tcl-commands)
     ("if" tcl-expr "then" tcl-commands)
@@ -524,7 +739,7 @@ is a Tcl expression, and the last argument is Tcl commands.")
 ;; We use this because Lemacs 19.9 has what we need.
 (defconst tcl-pps-has-arg-6
   (or tcl-using-emacs-19
-      (and tcl-using-lemacs-19
+      (and tcl-using-xemacs-19
           (condition-case nil
               (progn
                 (parse-partial-sexp (point) (point) nil nil nil t)
@@ -603,13 +818,40 @@ An end of a defun is found by moving forward from the beginning of one."
          'beginning-of-defun
        'tcl-internal-beginning-of-defun))
 
-;; Only FSF Emacs 19 works correctly using end-of-defun.  Emacs 18 and
-;; Lucid need our own function.
+;; Ditto end-of-defun.
 (fset 'tcl-end-of-defun
-      (if (and tcl-using-emacs-19 (not tcl-using-lemacs-19))
+      (if (and tcl-using-emacs-19 (not tcl-using-xemacs-19))
          'end-of-defun
        'tcl-internal-end-of-defun))
 
+;; Internal mark-defun that is used for losing Emacsen.
+(defun tcl-internal-mark-defun ()
+  "Put mark at end of Tcl function, point at beginning."
+  (interactive)
+  (push-mark (point))
+  (tcl-end-of-defun)
+  (if tcl-using-emacs-19
+      (push-mark (point) nil t)
+    (push-mark (point)))
+  (tcl-beginning-of-defun)
+  (backward-paragraph))
+
+;; In GNU Emacs 19-23 and later, mark-defun works as advertised.  I
+;; don't know about XEmacs, so for now it and Emacs 18 just lose.
+(fset 'tcl-mark-defun
+      (if tcl-using-emacs-19-23
+         'mark-defun
+       'tcl-internal-mark-defun))
+
+;; In GNU Emacs 19, mark takes an additional "force" argument.  I
+;; don't know about XEmacs, so I'm just assuming it is the same.
+;; Emacs 18 doesn't have this argument.
+(defun tcl-mark ()
+  "Return mark, or nil if none."
+  (if tcl-using-emacs-19
+      (mark t)
+    (mark)))
+
 \f
 
 ;;
@@ -618,7 +860,7 @@ An end of a defun is found by moving forward from the beginning of one."
 
 (defun tcl-set-proc-regexp ()
   "Set `tcl-proc-regexp' from variable `tcl-proc-list'."
-  (setq tcl-proc-regexp (concat "^\\("
+  (setq tcl-proc-regexp (concat "^\\s-*\\("
                                (mapconcat 'identity tcl-proc-list "\\|")
                                "\\)[ \t]+")))
 
@@ -662,6 +904,7 @@ Uses variables `tcl-proc-regexp' and `tcl-keyword-list'."
 ;; The mode itself.
 ;;
 
+;;;###autoload
 (defun tcl-mode ()
   "Major mode for editing Tcl code.
 Expression and list commands understand all Tcl brackets.
@@ -687,6 +930,9 @@ documentation for details):
   tcl-use-hairy-comment-detector
     If t, use more complicated, but slower, comment detector.
     This variable is only used in GNU Emacs 19.
+  tcl-use-smart-word-finder
+    If not nil, use a smarter, Tcl-specific way to find the current
+    word when looking up help on a Tcl command.
 
 Turning on Tcl mode calls the value of the variable `tcl-mode-hook'
 with no args, if that value is non-nil.  Read the documentation for
@@ -702,17 +948,29 @@ Commands:
   (setq mode-name "Tcl")
   (setq local-abbrev-table tcl-mode-abbrev-table)
   (set-syntax-table tcl-mode-syntax-table)
+
   (make-local-variable 'paragraph-start)
-  (setq paragraph-start (concat "^$\\|" page-delimiter))
   (make-local-variable 'paragraph-separate)
-  (setq paragraph-separate paragraph-start)
+  (if (and tcl-using-emacs-19-23
+          (>= emacs-minor-version 29))
+      (progn
+       ;; In Emacs 19.29, you aren't supposed to start these with a
+       ;; ^.
+       (setq paragraph-start "$\\|\f")
+       (setq paragraph-separate paragraph-start))
+    (setq paragraph-start (concat "^$\\|" page-delimiter))
+    (setq paragraph-separate paragraph-start))
   (make-local-variable 'paragraph-ignore-fill-prefix)
   (setq paragraph-ignore-fill-prefix t)
+  (make-local-variable 'fill-paragraph-function)
+  (setq fill-paragraph-function 'tcl-do-fill-paragraph)
+
   (make-local-variable 'indent-line-function)
   (setq indent-line-function 'tcl-indent-line)
   ;; Tcl doesn't require a final newline.
   ;; (make-local-variable 'require-final-newline)
   ;; (setq require-final-newline t)
+
   (make-local-variable 'comment-start)
   (setq comment-start "# ")
   (make-local-variable 'comment-start-skip)
@@ -721,16 +979,36 @@ Commands:
   (setq comment-column 40)
   (make-local-variable 'comment-end)
   (setq comment-end "")
+
+  (make-local-variable 'outline-regexp)
+  (setq outline-regexp "[^\n\^M]")
+  (make-local-variable 'outline-level)
+  (setq outline-level 'tcl-outline-level)
+
   (make-local-variable 'font-lock-keywords)
   (setq font-lock-keywords tcl-font-lock-keywords)
+
+  ;; The following only really makes sense under GNU Emacs 19.
+  (make-local-variable 'imenu-create-index-function)
   (setq imenu-create-index-function 'tcl-imenu-create-index-function)
   (make-local-variable 'parse-sexp-ignore-comments)
+
+  ;; Settings for new dabbrev code.
+  (make-local-variable 'dabbrev-case-fold-search)
+  (setq dabbrev-case-fold-search nil)
+  (make-local-variable 'dabbrev-case-replace)
+  (setq dabbrev-case-replace nil)
+  (make-local-variable 'dabbrev-abbrev-skip-leading-regexp)
+  (setq dabbrev-abbrev-skip-leading-regexp "[$!]")
+  (make-local-variable 'dabbrev-abbrev-char-regexp)
+  (setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_")
+
   (if tcl-using-emacs-19
       (progn
-       ;; This can only be set to t in Emacs 19 and Lucid Emacs.
+       ;; This can only be set to t in Emacs 19 and XEmacs.
        ;; Emacs 18 and Epoch lose.
        (setq parse-sexp-ignore-comments t)
-       ;; Lucid Emacs has defun-prompt-regexp, but I don't believe
+       ;; XEmacs has defun-prompt-regexp, but I don't believe
        ;; that it works for end-of-defun -- only for
        ;; beginning-of-defun.
        (make-local-variable 'defun-prompt-regexp)
@@ -740,6 +1018,24 @@ Commands:
        (make-local-variable 'add-log-current-defun-function)
        (setq add-log-current-defun-function 'add-log-tcl-defun))
     (setq parse-sexp-ignore-comments nil))
+
+  ;; Put Tcl menu into menubar for XEmacs.  This happens
+  ;; automatically for GNU Emacs.
+  (if (and tcl-using-xemacs-19
+          current-menubar
+          (not (assoc "Tcl" current-menubar)))
+      (progn
+       (set-buffer-menubar (copy-sequence current-menubar))
+       (add-menu nil "Tcl" tcl-xemacs-menu)))
+  ;; Append Tcl menu to popup menu for XEmacs.
+  (if (and tcl-using-xemacs-19 (boundp 'mode-popup-menu))
+      (setq mode-popup-menu
+           (cons (concat mode-name " Mode Commands") tcl-xemacs-menu)))
+
+  ;; If hilit19 is loaded, add our stuff.
+  (if (featurep 'hilit19)
+      (tcl-hilit))
+
   (run-hooks 'tcl-mode-hook))
 
 \f
@@ -802,10 +1098,10 @@ from the following list to take place:
   (interactive "p")
   (cond
    ((not tcl-tab-always-indent)
-    ;; Indent if in identation area, otherwise insert TAB.
+    ;; Indent if in indentation area, otherwise insert TAB.
     (if (<= (current-column) (current-indentation))
        (tcl-indent-line)
-      (self-insert-command arg)))
+      (insert-tab arg)))
    ((eq tcl-tab-always-indent t)
     ;; Always indent.
     (tcl-indent-line))
@@ -846,17 +1142,8 @@ from the following list to take place:
        (goto-char eolpoint)
        (tcl-indent-line))
        ((not comment-p)
-       ;; Create an empty comment (since there isn't one on this
-       ;; line).  If line is not blank, make sure we insert a ";"
-       ;; first.
-       (beginning-of-line)
-       (if (/= (point) eolpoint)
-           (progn
-             (goto-char eolpoint)
-             (or (tcl-real-command-p)
-                 (insert ";"))))
        (tcl-indent-line)
-       (indent-for-comment))
+       (tcl-indent-for-comment))
        (t
        ;; Go to start of comment.  We don't leave point where it is
        ;; because we want to skip comment-start-skip.
@@ -913,7 +1200,7 @@ See documentation for variable `tcl-type-alist' for more information."
            (if (looking-at "[a-zA-Z_]+")
                (let ((list tcl-type-alist)
                      entry)
-                 (setq word-stack (cons (current-word) word-stack))
+                 (setq word-stack (cons (tcl-word-no-props) word-stack))
                  (while (and list (not result))
                    (setq entry (car list))
                    (setq list (cdr list))
@@ -1040,19 +1327,6 @@ Returns nil if line starts inside a string, t if in a comment."
 
 \f
 
-(defun mark-tcl-function ()
-  "Put mark at end of Tcl function, point at beginning."
-  (interactive)
-  (push-mark (point))
-  (tcl-end-of-defun)
-  (if tcl-using-emacs-19
-      (push-mark (point) nil t)
-    (push-mark (point)))
-  (tcl-beginning-of-defun)
-  (backward-paragraph))
-
-\f
-
 (defun indent-tcl-exp ()
   "Indent each line of the Tcl grouping following point."
   (interactive)
@@ -1160,17 +1434,18 @@ Returns nil if line starts inside a string, t if in a comment."
 (defun tcl-imenu-create-index-function ()
   "Generate alist of indices for imenu."
   (let ((re (concat tcl-proc-regexp "\\([^ \t\n{]+\\)"))
-       alist)
-    (imenu-progress-message 0)
+       alist prev-pos)
     (goto-char (point-min))
-    (while (re-search-forward re nil t)
-      (imenu-progress-message nil)
-      ;; Position on start of proc name, not beginning of line.
-      (setq alist (cons
-                  (cons (buffer-substring (match-beginning 2) (match-end 2))
-                        (match-beginning 2))
-                  alist)))
-    (imenu-progress-message 100)
+    (imenu-progress-message prev-pos 0)
+    (save-match-data
+      (while (re-search-forward re nil t)
+       (imenu-progress-message prev-pos)
+       ;; Position on start of proc name, not beginning of line.
+       (setq alist (cons
+                    (cons (buffer-substring (match-beginning 2) (match-end 2))
+                          (match-beginning 2))
+                    alist))))
+    (imenu-progress-message prev-pos 100)
     (nreverse alist)))
 
 ;; FIXME Definition of function is very ad-hoc.  Should use
@@ -1179,11 +1454,16 @@ Returns nil if line starts inside a string, t if in a comment."
 (defun add-log-tcl-defun ()
   "Return name of Tcl function point is in, or nil."
   (save-excursion
-    (if (re-search-backward
-        (concat tcl-proc-regexp "\\([^ \t\n{]+\\)") nil t)
+    (end-of-line)
+    (if (re-search-backward (concat tcl-proc-regexp "\\([^ \t\n{]+\\)") nil t)
        (buffer-substring (match-beginning 2)
                          (match-end 2)))))
 
+(defun tcl-outline-level ()
+  (save-excursion
+    (skip-chars-forward " \t")
+    (current-column)))
+
 \f
 
 ;;
@@ -1207,7 +1487,9 @@ Returns nil if line starts inside a string, t if in a comment."
          (progn
            (delete-region (point) inferior-tcl-delete-prompt-marker)
            (set-marker inferior-tcl-delete-prompt-marker nil)))))
-  (comint-output-filter proc string))
+  (if tcl-using-emacs-19
+      (comint-output-filter proc string)
+    (funcall comint-output-filter string)))
 
 (defun tcl-send-string (proc string)
   (save-excursion
@@ -1307,7 +1589,9 @@ The following commands are available:
                                         ">")))
   (setq major-mode 'inferior-tcl-mode)
   (setq mode-name "Inferior Tcl")
-  (setq mode-line-process '(": %s"))
+  (if (boundp 'modeline-process)
+      (setq modeline-process '(": %s"))        ; For XEmacs.
+    (setq mode-line-process '(": %s")))
   (use-local-map inferior-tcl-mode-map)
   (setq local-abbrev-table tcl-mode-abbrev-table)
   (set-syntax-table tcl-mode-syntax-table)
@@ -1320,6 +1604,7 @@ The following commands are available:
   (set-process-filter (get-buffer-process (current-buffer)) 'tcl-filter)
   (run-hooks 'inferior-tcl-mode-hook))
 
+;;;###autoload
 (defun inferior-tcl (cmd)
   "Run inferior Tcl process.
 Prefix arg means enter program name interactively.
@@ -1423,7 +1708,7 @@ of comment."
   (let ((save (point)))
     (tcl-beginning-of-defun)
     (car (tcl-hairy-scan-for-comment nil save nil))))
-       
+
 (defun tcl-simple-in-comment ()
   "Return t if point is in comment, and leave point at beginning
 of comment.  This is faster that `tcl-hairy-in-comment', but is
@@ -1444,23 +1729,65 @@ of comment."
       (tcl-hairy-in-comment)
     (tcl-simple-in-comment)))
 
-(defun tcl-do-auto-fill ()
-  "Auto-fill function for Tcl mode.  Only auto-fills in a comment."
-  (let (in-comment
-       col)
+(defun tcl-do-fill-paragraph (ignore)
+  "fill-paragraph function for Tcl mode.  Only fills in a comment."
+  (let (in-comment col where)
     (save-excursion
+      (end-of-line)
       (setq in-comment (tcl-in-comment))
       (if in-comment
-         (setq col (1- (current-column)))))
-    (if in-comment
-       (progn
-         (do-auto-fill)
-         (save-excursion
-           (back-to-indentation)
-           (delete-region (point) (save-excursion
-                                    (beginning-of-line)
-                                    (point)))
-           (indent-to-column col))))))
+         (progn
+           (setq where (1+ (point)))
+           (setq col (1- (current-column))))))
+    (and in-comment
+        (save-excursion
+          (back-to-indentation)
+          (= col (current-column)))
+        ;; In a comment.  Set the fill prefix, and find the paragraph
+        ;; boundaries by searching for lines that look like
+        ;; comment-only lines.
+        (let ((fill-prefix (buffer-substring (progn
+                                               (beginning-of-line)
+                                               (point))
+                                             where))
+              p-start p-end)
+          ;; Search backwards.
+          (save-excursion
+            (while (looking-at "^[ \t]*#")
+              (forward-line -1))
+            (forward-line)
+            (setq p-start (point)))
+
+          ;; Search forwards.
+          (save-excursion
+            (while (looking-at "^[ \t]*#")
+              (forward-line))
+            (setq p-end (point)))
+
+          ;; Narrow and do the fill.
+          (save-restriction
+            (narrow-to-region p-start p-end)
+            (fill-paragraph ignore)))))
+  t)
+
+(defun tcl-do-auto-fill ()
+  "Auto-fill function for Tcl mode.  Only auto-fills in a comment."
+  (if (> (current-column) fill-column)
+      (let ((fill-prefix "# ")
+           in-comment col)
+       (save-excursion
+         (setq in-comment (tcl-in-comment))
+         (if in-comment
+             (setq col (1- (current-column)))))
+       (if in-comment
+           (progn
+             (do-auto-fill)
+             (save-excursion
+               (back-to-indentation)
+               (delete-region (point) (save-excursion
+                                        (beginning-of-line)
+                                        (point)))
+               (indent-to-column col)))))))
 
 \f
 
@@ -1468,49 +1795,58 @@ of comment."
 ;; Help-related code.
 ;;
 
-(defvar tcl-help-saved-dir nil
-  "Saved help directory.  If `tcl-help-directory' changes, this allows
-tcl-help-on-word to update the alist")
+(defvar tcl-help-saved-dirs nil
+  "Saved help directories.
+If `tcl-help-directory-list' changes, this allows `tcl-help-on-word'
+to update the alist.")
 
 (defvar tcl-help-alist nil
   "Alist with command names as keys and filenames as values.")
 
-(defun tcl-help-snarf-commands (dir)
-  "Build alist of commands and filenames.  There is probably a much
-better implementation of this, but I'm too tired to think of it right
-now."
-  (let ((files (directory-files dir t)))
-    (while files
-      (if (and (file-directory-p (car files))
-              (not
-               (let ((fpart (file-name-nondirectory (car files))))
-                 (or (equal fpart ".")
-                     (equal fpart "..")))))
-         (let ((matches (directory-files (car files) t)))
-           (while matches
-             (or (file-directory-p (car matches))
-                 (setq tcl-help-alist
-                       (cons
-                        (cons (file-name-nondirectory (car matches))
-                              (car matches))
-                        tcl-help-alist)))
-             (setq matches (cdr matches)))))
-      (setq files (cdr files)))))
+(defun tcl-help-snarf-commands (dirlist)
+  "Build alist of commands and filenames."
+  (while dirlist
+    (let ((files (directory-files (car dirlist) t)))
+      (while files
+       (if (and (file-directory-p (car files))
+                (not
+                 (let ((fpart (file-name-nondirectory (car files))))
+                   (or (equal fpart ".")
+                       (equal fpart "..")))))
+           (let ((matches (directory-files (car files) t)))
+             (while matches
+               (or (file-directory-p (car matches))
+                   (setq tcl-help-alist
+                         (cons
+                          (cons (file-name-nondirectory (car matches))
+                                (car matches))
+                          tcl-help-alist)))
+               (setq matches (cdr matches)))))
+       (setq files (cdr files))))
+    (setq dirlist (cdr dirlist))))
 
 (defun tcl-reread-help-files ()
   "Set up to re-read files, and then do it."
   (interactive)
   (message "Building Tcl help file index...")
-  (setq tcl-help-saved-dir tcl-help-directory)
+  (setq tcl-help-saved-dirs tcl-help-directory-list)
   (setq tcl-help-alist nil)
-  (tcl-help-snarf-commands tcl-help-directory)
+  (tcl-help-snarf-commands tcl-help-directory-list)
   (message "Building Tcl help file index...done"))
 
+(defun tcl-word-no-props ()
+  "Like current-word, but strips properties."
+  (let ((word (current-word)))
+    (and (fboundp 'set-text-properties)
+        (set-text-properties 0 (length word) nil word))
+    word))
+
 (defun tcl-current-word (flag)
   "Return current command word, or nil.
 If FLAG is nil, just uses `current-word'.
 Otherwise scans backward for most likely Tcl command word."
-  (if (and flag (eq major-mode 'tcl-mode))
+  (if (and flag
+          (memq major-mode '(tcl-mode inferior-tcl-mode)))
       (condition-case nil
          (save-excursion
            ;; Look backward for first word actually in alist.
@@ -1519,18 +1855,19 @@ Otherwise scans backward for most likely Tcl command word."
              (while (and (not (bobp))
                          (not (tcl-real-command-p)))
                (backward-sexp)))
-           (if (assoc (current-word) tcl-help-alist)
-               (current-word)))
+           (if (assoc (tcl-word-no-props) tcl-help-alist)
+               (tcl-word-no-props)))
        (error nil))
-    (current-word)))
+    (tcl-word-no-props)))
 
+;;;###autoload
 (defun tcl-help-on-word (command &optional arg)
   "Get help on Tcl command.  Default is word at point.
 Prefix argument means invert sense of `tcl-use-smart-word-finder'."
   (interactive
    (list
     (progn
-      (if (not (string= tcl-help-directory tcl-help-saved-dir))
+      (if (not (equal tcl-help-directory-list tcl-help-saved-dirs))
          (tcl-reread-help-files))
       (let ((word (tcl-current-word
                   (if current-prefix-arg
@@ -1542,7 +1879,7 @@ Prefix argument means invert sense of `tcl-use-smart-word-finder'."
           (format "Help on Tcl command (default %s): " word))
         tcl-help-alist nil t)))
     current-prefix-arg))
-  (if (not (string= tcl-help-directory tcl-help-saved-dir))
+  (if (not (equal tcl-help-directory-list tcl-help-saved-dirs))
       (tcl-reread-help-files))
   (if (string= command "")
       (setq command (tcl-current-word
@@ -1583,7 +1920,11 @@ Prefix argument means switch to the Tcl buffer afterwards."
    (list
     ;; car because comint-get-source returns a list holding the
     ;; filename.
-    (car (comint-get-source "Load Tcl file: " tcl-previous-dir/file
+    (car (comint-get-source "Load Tcl file: "
+                           (or (and
+                                (eq major-mode 'tcl-mode)
+                                (buffer-file-name))
+                               tcl-previous-dir/file)
                            '(tcl-mode) t))
     current-prefix-arg))
   (comint-check-source file)
@@ -1593,8 +1934,6 @@ Prefix argument means switch to the Tcl buffer afterwards."
                   (format inferior-tcl-source-command (tcl-quote file)))
   (if and-go (switch-to-tcl t)))
 
-;; Maybe this should work just like tcl-load-file.  But I think what
-;; I've implemented will turn out to be more useful.
 (defun tcl-restart-with-file (file &optional and-go)
   "Restart inferior Tcl with file.
 If an inferior Tcl process exists, it is killed first.
@@ -1647,9 +1986,21 @@ Prefix argument means switch to the Tcl buffer afterwards."
                  (> (prefix-numeric-value arg) 0))
                'tcl-do-auto-fill
              nil))
-    ;; Update mode line.  FIXME I'd use force-mode-line-update, but I
-    ;; don't know if it exists in v18.
-    (set-buffer-modified-p (buffer-modified-p))))
+    (force-mode-line-update)))
+
+;; hilit19 support from "Chris Alfeld" <calfeld@math.utah.edu>
+(defun tcl-hilit ()
+  (hilit-set-mode-patterns
+   '(tcl-mode)
+   '(
+     ("\\(^ *\\|\; *\\)#.*$" nil comment)
+     ("[^\\]\\(\\$[A-Za-z0-9\\-\\_./\\(\\)]+\\)" 1 label)
+     ("[^_]\\<\\(append\\|array\\|auto_execok\\|auto_load\\|auto_mkindex\\|auto_reset\\|break\\|case\\|catch\\|cd\\|close\\|concat\\|continue\\|eof\\|error\\|eval\\|exec\\|exit\\|expr\\|file\\|flush\\|for\\|foreach\\|format\\|gets\\|glob\\|global\\|history\\|if\\|incr\\|info\\|join\\|lappend\\|lindex\\|linsert\\|list\\|llength\\|lrange\\|lreplace\\|lsearch\\|lsort\\|open\\|pid\\|proc\\|puts\\|pwd\\|read\\|regexp\\|regsub\\|rename\\|return\\|scan\\|seek\\|set\\|source\\|split\\|string\\|switch\\|tell\\|time\\|trace\\|unknown\\|unset\\|uplevel\\|upvar\\|while\\)\\>[^_]" 1 keyword) ; tcl keywords
+     ("[^_]\\<\\(after\\|bell\\|bind\\|bindtags\\|clipboard\\|destroy\\|fileevent\\|focus\\|grab\\|image\\|lower\\|option\\|pack\\|place\\|raise\\|scale\\|selection\\|send\\|subst\\|tk\\|tk_popup\\|tkwait\\|update\\|winfo\\|wm\\)\\>[^_]" 1 define) ; tk keywords
+     ("[^_]\\<\\(button\\|canvas\\|checkbutton\\|entry\\|frame\\|label\\|listbox\\|menu\\|menubutton\\|message\\|radiobutton\\|scrollbar\\|text\\|toplevel\\)\\>[^_]" 1 decl) ; tk widgets
+     ("[^_]\\<\\(tix\\((ButtonBox\\|Baloon\\|Control\\|DirList\\|ExFileSelectBox\\|ExFileSelectDialog\\|FileEntry\\|HList\\|LabelEntry\\|LabelFrame\\|NoteBook\\|OptionMenu\\|PanedWindow\\|PopupMenu\\|ScrolledHList\\|ScrolledText\\|ScrolledWindow\\|Select\\|StdButtonBox\\)\\)\\>[^_]" 1 defun) ; tix widgets
+     ("[{}\\\"\\(\\)]" nil include) ; misc punctuation
+     )))
 
 (defun tcl-electric-hash (&optional count)
   "Insert a `#' and quote if it does not start a real comment.
@@ -1716,18 +2067,63 @@ styles."
              (insert "\\"))
          (forward-char))))))
 
+(defun tcl-indent-for-comment ()
+  "Indent this line's comment to comment column, or insert an empty comment.
+Is smart about syntax of Tcl comments.
+Parts of this were taken from indent-for-comment (simple.el)."
+  (interactive "*")
+  (end-of-line)
+  (or (tcl-in-comment)
+      (progn
+       ;; Not in a comment, so we have to insert one.  Create an
+       ;; empty comment (since there isn't one on this line).  If
+       ;; line is not blank, make sure we insert a ";" first.
+       (skip-chars-backward " \t")
+       (let ((eolpoint (point)))
+         (beginning-of-line)
+         (if (/= (point) eolpoint)
+             (progn
+               (goto-char eolpoint)
+               (insert
+                (if (tcl-real-command-p) "" ";")
+                "# ")
+               (backward-char))))))
+  ;; Point is just after the "#" starting a comment.  Move it as
+  ;; appropriate.
+  (let* ((indent (if comment-indent-hook
+                    (funcall comment-indent-hook)
+                  (funcall comment-indent-function)))
+        (begpos (progn
+                  (backward-char)
+                  (point))))
+    (if (/= begpos indent)
+       (progn
+         (skip-chars-backward " \t" (save-excursion
+                                      (beginning-of-line)
+                                      (point)))
+         (delete-region (point) begpos)
+         (indent-to indent)))
+    (looking-at comment-start-skip)    ; Always true.
+    (goto-char (match-end 0))
+    ;; I don't like the effect of the next two.
+    ;;(skip-chars-backward " \t" (match-beginning 0))
+    ;;(skip-chars-backward "^ \t" (match-beginning 0))
+    ))
+
 ;; The following was inspired by the Tcl editing mode written by
 ;; Gregor Schmid <schmid@fb3-s7.math.TU-Berlin.DE>.  His version also
 ;; attempts to snarf the command line options from the command line,
 ;; but I didn't think that would really be that helpful (doesn't seem
 ;; like it owould be right enough.  His version also looks for the
 ;; "#!/bin/csh ... exec" hack, but that seemed even less useful.
+;; FIXME should make sure that the application mentioned actually
+;; exists.
 (defun tcl-guess-application ()
   "Attempt to guess Tcl application by looking at first line.
 The first line is assumed to look like \"#!.../program ...\"."
   (save-excursion
     (goto-char (point-min))
-    (if (looking-at "#![^ \t]*/\\([^ \t/]+\\)\\([ \t]\\|$\\)")
+    (if (looking-at "#![^ \t]*/\\([^ \t\n/]+\\)\\([ \t]\\|$\\)")
        (progn
          (make-local-variable 'tcl-application)
          (setq tcl-application (buffer-substring (match-beginning 1)
@@ -1744,43 +2140,18 @@ The first line is assumed to look like \"#!.../program ...\"."
 \f
 
 ;;
-;; Lucid menu support.
+;; XEmacs menu support.
 ;; Taken from schmid@fb3-s7.math.TU-Berlin.DE (Gregor Schmid),
 ;; who wrote a different Tcl mode.
-;; We also have simple support for menus in FSF.  We do this by
-;; loading the Lucid menu emulation code.
+;; We also have support for menus in FSF.  We do this by
+;; loading the XEmacs menu emulation code.
 ;;
 
-;; Put this into your tcl-mode-hook.
-(defun tcl-install-menubar ()
-  (and tcl-using-emacs-19
-       (not tcl-using-lemacs-19)
-       (if tcl-using-emacs-19.23
-          (require 'lmenu)
-        ;; CAVEATS:
-        ;; * lmenu.el provides 'menubar, which is bogus.
-        ;; * lmenu.el causes menubars to be turned on everywhere.
-        ;;   Doubly bogus!
-        ;; Both of these problems are fixed in Emacs 19.23.  People
-        ;; using an Emacs before that just suffer.
-        (require 'menubar "lmenu")))
-  (if (not (assoc "Tcl" current-menubar))
-      (progn
-       (set-buffer-menubar (copy-sequence current-menubar))
-       (add-menu nil "Tcl" (cdr tcl-lucid-menu))))
-  ;; You might want to do something like the below.  I have it
-  ;; commented out because it overrides existing bindings.
-  ;; For Lucid:
-  ;;   (define-key tcl-mode-map 'button3 'tcl-popup-menu)
-  ;; For FSF:
-  ;;   (define-key tcl-mode-map [down-mouse-3] 'tcl-popup-menu)
-  )
-
 (defun tcl-popup-menu (e)
-  (interactive "e")
+  (interactive "@e")
   (and tcl-using-emacs-19
-       (not tcl-using-lemacs-19)
-       (if tcl-using-emacs-19.23
+       (not tcl-using-xemacs-19)
+       (if tcl-using-emacs-19-23
           (require 'lmenu)
         ;; CAVEATS:
         ;; * lmenu.el provides 'menubar, which is bogus.
@@ -1789,9 +2160,8 @@ The first line is assumed to look like \"#!.../program ...\"."
         ;; Both of these problems are fixed in Emacs 19.23.  People
         ;; using an Emacs before that just suffer.
         (require 'menubar "lmenu")))  ;; This is annoying
-  ;;(mouse-set-point e)
-  ;; IMHO popup-menu should be autoloaded.  Oh well.
-  (popup-menu tcl-lucid-menu))
+  ;; IMHO popup-menu should be autoloaded in FSF Emacs.  Oh well.
+  (popup-menu tcl-xemacs-menu))
 
 \f
 
@@ -1811,6 +2181,47 @@ The first line is assumed to look like \"#!.../program ...\"."
 
 \f
 
+;;
+;; Bug reporting.
+;;
+
+(and (fboundp 'eval-when-compile)
+     (eval-when-compile
+       (require 'reporter)))
+
+(defun tcl-submit-bug-report ()
+  "Submit via mail a bug report on Tcl mode."
+  (interactive)
+  (require 'reporter)
+  (and
+   (y-or-n-p "Do you really want to submit a bug report on Tcl mode? ")
+   (reporter-submit-bug-report
+    tcl-maintainer
+    (concat "Tcl mode " tcl-version)
+    '(tcl-indent-level
+      tcl-continued-indent-level
+      tcl-auto-newline
+      tcl-tab-always-indent
+      tcl-use-hairy-comment-detector
+      tcl-electric-hash-style
+      tcl-help-directory-list
+      tcl-use-smart-word-finder
+      tcl-application
+      tcl-command-switches
+      tcl-prompt-regexp
+      inferior-tcl-source-command
+      tcl-using-emacs-19
+      tcl-using-emacs-19-23
+      tcl-using-xemacs-19
+      tcl-proc-list
+      tcl-proc-regexp
+      tcl-typeword-list
+      tcl-keyword-list
+      tcl-font-lock-keywords
+      tcl-pps-has-arg-6))))
+
+\f
+
 (provide 'tcl)
 
 ;;; tcl.el ends here