Various docstring and commentary fixes, including
[bpt/emacs.git] / lisp / progmodes / tcl.el
index 5606c0a..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.18 $
+;; Version: $Revision: 1.50 $
 
 ;; This file is part of GNU Emacs.
 
@@ -51,7 +51,7 @@
 ;; LCD Archive Entry:
 ;; tcl|Tom Tromey|tromey@busco.lanl.gov|
 ;; Major mode for editing Tcl|
-;; $Date: 1994/06/03 20:39:14 $|$Revision: 1.18 $|~/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
 
 ;; 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.
 ;
 ;; 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
 ;; * Consider writing code to find help files automatically (for
 ;;   common cases).
 ;; * `#' shouldn't insert `\#' when point is in string.
-;; * '}' doesn't seem to reindent.
 
 \f
 
 ;;; Code:
 
 ;; 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).")
+;; 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
+(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.")
+  "Nil unless using Emacs 19-23 or later.")
 
-(defconst tcl-using-lemacs-19 (string-match "Lucid" emacs-version)
-  "Nil unless using Lucid Emacs).")
+(defconst tcl-using-xemacs-19 (string-match "XEmacs" emacs-version)
+  "Nil unless using XEmacs).")
 
 (require 'comint)
 
 (and (fboundp 'eval-when-compile)
      (eval-when-compile
        (if (and (string-match "19\\." emacs-version)
-               (not (string-match "Lucid" emacs-version)))
+               (not (string-match "XEmacs" emacs-version)))
           (require 'imenu))
        ()))
 
-(defconst tcl-version "$Revision: 1.18 $")
-(defconst tcl-maintainer "Tom Tromey <tromey@busco.lanl.gov>")
+(defconst tcl-version "$Revision: 1.50 $")
+(defconst tcl-maintainer "Tom Tromey <tromey@drip.colorado.edu>")
 
 ;;
 ;; User variables.
@@ -292,7 +410,7 @@ 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
@@ -369,10 +487,9 @@ quoted for Tcl.")
 (defvar inferior-tcl-mode-map nil
   "Keymap used in Inferior Tcl mode.")
 
-;; 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" tcl-mark-defun t]
     ["Indent region" indent-region (tcl-mark)]
@@ -390,7 +507,7 @@ quoted for Tcl.")
     "----"
     ["Tcl help" tcl-help-on-word tcl-help-directory-list]
     ["Send bug report" tcl-submit-bug-report t])
-  "Lucid Emacs menu for Tcl mode.")
+  "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.
@@ -398,7 +515,7 @@ quoted for Tcl.")
   (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" (cdr tcl-lucid-menu))))
+  (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.
@@ -425,34 +542,33 @@ quoted for Tcl.")
   (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-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)
+  (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 tcl-using-emacs-19
-      (if tcl-using-lemacs-19
-         ;; In Lucid, button 3 seems to be the standard for this.
-         (define-key tcl-mode-map 'button3 'tcl-popup-menu)
-       ;; In FSF 19, there is no standard, so I use shift-button2.
-       (tcl-add-fsf-menu tcl-mode-map)
-       (define-key tcl-mode-map [S-down-mouse-2] 'tcl-popup-menu))))
+  (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-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))
+  (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
     ()
@@ -537,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'
@@ -547,7 +663,7 @@ after changing this list.")
   "Regexp to use when matching proc headers.")
 
 (defvar tcl-typeword-list
-  '("global" "upvar")
+  '("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.")
 
@@ -555,7 +671,8 @@ Call `tcl-set-font-lock-keywords' after changing this list.")
 (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.")
@@ -570,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)
@@ -618,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)
@@ -699,7 +820,7 @@ An end of a defun is found by moving forward from the beginning of one."
 
 ;; Ditto end-of-defun.
 (fset 'tcl-end-of-defun
-      (if tcl-using-emacs-19
+      (if (and tcl-using-emacs-19 (not tcl-using-xemacs-19))
          'end-of-defun
        'tcl-internal-end-of-defun))
 
@@ -715,15 +836,15 @@ An end of a defun is found by moving forward from the beginning of one."
   (tcl-beginning-of-defun)
   (backward-paragraph))
 
-;; In GNU Emacs 19.23 and later, mark-defun works as advertised.  I
-;; don't know about Lucid Emacs, so for now it and Emacs 18 just lose.
+;; 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
+      (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 Lucid Emacs, so I'm just assuming it is the same.
+;; 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."
@@ -739,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]+")))
 
@@ -783,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.
@@ -808,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
@@ -825,11 +950,20 @@ Commands:
   (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)
@@ -846,19 +980,35 @@ Commands:
   (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)
@@ -869,14 +1019,22 @@ Commands:
        (setq add-log-current-defun-function 'add-log-tcl-defun))
     (setq parse-sexp-ignore-comments nil))
 
-  ;; Put Tcl menu into menubar for Lucid Emacs.  This happens
+  ;; Put Tcl menu into menubar for XEmacs.  This happens
   ;; automatically for GNU Emacs.
-  (if (and tcl-using-lemacs-19
+  (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-lucid-menu)))
+       (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))
 
@@ -943,7 +1101,7 @@ from the following list to take place:
     ;; 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))
@@ -1042,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))
@@ -1276,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
@@ -1295,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
 
 ;;
@@ -1323,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
@@ -1423,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)
@@ -1436,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.
@@ -1560,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
 
@@ -1623,11 +1834,19 @@ to update the alist.")
   (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.
@@ -1636,11 +1855,12 @@ 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'."
@@ -1700,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)
@@ -1710,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.
@@ -1764,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.
@@ -1889,7 +2123,7 @@ Parts of this were taken from indent-for-comment (simple.el)."
 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)
@@ -1906,18 +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 support for menus in FSF.  We do this by
-;; loading the Lucid menu emulation code.
+;; loading the XEmacs menu emulation code.
 ;;
 
 (defun tcl-popup-menu (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.
@@ -1927,7 +2161,7 @@ The first line is assumed to look like \"#!.../program ...\"."
         ;; using an Emacs before that just suffer.
         (require 'menubar "lmenu")))  ;; This is annoying
   ;; IMHO popup-menu should be autoloaded in FSF Emacs.  Oh well.
-  (popup-menu tcl-lucid-menu))
+  (popup-menu tcl-xemacs-menu))
 
 \f
 
@@ -1977,8 +2211,8 @@ The first line is assumed to look like \"#!.../program ...\"."
       tcl-prompt-regexp
       inferior-tcl-source-command
       tcl-using-emacs-19
-      tcl-using-emacs-19.23
-      tcl-using-lemacs-19
+      tcl-using-emacs-19-23
+      tcl-using-xemacs-19
       tcl-proc-list
       tcl-proc-regexp
       tcl-typeword-list